diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2009-06-02 04:00:00 +0400 |
---|---|---|
committer | Kornel LesiĆski <kornel@geekhood.net> | 2016-05-28 02:15:59 +0300 |
commit | 829409452d85cd6dd9dfc9151f109d6e13a2bb1c (patch) | |
tree | e0acaea47044d167f35fa197584dee1bde41c329 | |
parent | 8874e4fbc9faabdcff719b9b2ac8ebad4f282bbe (diff) |
9.04 beta
440 files changed, 19683 insertions, 9821 deletions
diff --git a/Asm/x64/7zCrcT8U.asm b/Asm/x64/7zCrcT8U.asm index ee55a90b..41194324 100755 --- a/Asm/x64/7zCrcT8U.asm +++ b/Asm/x64/7zCrcT8U.asm @@ -24,8 +24,8 @@ CrcUpdateT8 PROC push RDI push RBP - mov EAX, ECX - mov RSI, RDX + mov EAX, ECX + mov RSI, RDX mov RDI, R9 @@ -77,8 +77,8 @@ CrcUpdateT8 PROC xor EAX,EDX cmp RSI, R9 - jne main_loop - xor EAX, [RSI] + jne main_loop + xor EAX, [RSI] diff --git a/Asm/x86/7zCrcT8U.asm b/Asm/x86/7zCrcT8U.asm index 49aa2a74..467724b8 100755 --- a/Asm/x86/7zCrcT8U.asm +++ b/Asm/x86/7zCrcT8U.asm @@ -24,9 +24,9 @@ public @CrcUpdateT8@16 push EDI push EBP - mov EAX, ECX - mov ESI, EDX - mov EDI, [ESP + data_size] + mov EAX, ECX + mov ESI, EDX + mov EDI, [ESP + data_size] mov EBP, [ESP + crc_table] test EDI, EDI @@ -77,8 +77,8 @@ public @CrcUpdateT8@16 xor EAX,EDX cmp ESI, EDI - jne main_loop - xor EAX, [ESI] + jne main_loop + xor EAX, [ESI] mov EDI, [ESP + data_size] @@ -1,11 +1,15 @@ /* 7zBuf.h -- Byte Buffer -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ #ifndef __7Z_BUF_H #define __7Z_BUF_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { Byte *data; @@ -28,4 +32,8 @@ void DynBuf_SeekToBeg(CDynBuf *p); int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc); void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc); +#ifdef __cplusplus +} +#endif + #endif @@ -1,7 +1,5 @@ /* 7zCrc.h -- CRC32 calculation -2008-03-13 -Igor Pavlov -Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ #ifndef __7Z_CRC_H #define __7Z_CRC_H @@ -10,6 +8,10 @@ Public domain */ #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + extern UInt32 g_CrcTable[]; 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 CrcCalc(const void *data, size_t size); +#ifdef __cplusplus +} +#endif + #endif @@ -1,5 +1,5 @@ /* 7zFile.h -- File IO -2008-11-22 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ #ifndef __7Z_FILE_H #define __7Z_FILE_H @@ -16,6 +16,10 @@ #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + /* ---------- File ---------- */ @@ -71,4 +75,8 @@ typedef struct void FileOutStream_CreateVTable(CFileOutStream *p); +#ifdef __cplusplus +} +#endif + #endif diff --git a/C/7zVersion.h b/C/7zVersion.h index b7eb2355..2804bc47 100755 --- a/C/7zVersion.h +++ b/C/7zVersion.h @@ -1,7 +1,7 @@ -#define MY_VER_MAJOR 4 -#define MY_VER_MINOR 65 +#define MY_VER_MAJOR 9 +#define MY_VER_MINOR 04 #define MY_VER_BUILD 0 -#define MY_VERSION "4.65" -#define MY_DATE "2009-02-03" +#define MY_VERSION "9.04 beta" +#define MY_DATE "2009-05-30" #define MY_COPYRIGHT ": Igor Pavlov : Public domain" #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE @@ -1,13 +1,15 @@ /* Aes.h -- AES encryption / decryption -2008-08-05 -Igor Pavlov -Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ #ifndef __AES_H #define __AES_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + #define AES_BLOCK_SIZE 16 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_Decode(CAesCbc *p, Byte *data, SizeT size); +#ifdef __cplusplus +} +#endif + #endif @@ -1,13 +1,15 @@ /* Alloc.h -- Memory allocation functions -2008-03-13 -Igor Pavlov -Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ #ifndef __COMMON_ALLOC_H #define __COMMON_ALLOC_H #include <stddef.h> +#ifdef __cplusplus +extern "C" { +#endif + void *MyAlloc(size_t size); void MyFree(void *address); @@ -29,4 +31,8 @@ void BigFree(void *address); #endif +#ifdef __cplusplus +} +#endif + #endif diff --git a/C/Archive/7z/7z.dsp b/C/Archive/7z/7z.dsp index 9626b03e..6d6b8d93 100755 --- a/C/Archive/7z/7z.dsp +++ b/C/Archive/7z/7z.dsp @@ -132,6 +132,14 @@ SOURCE=..\..\Bra86.c # End 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 # End Source File # Begin Source File diff --git a/C/Archive/7z/7zAlloc.h b/C/Archive/7z/7zAlloc.h index e752ef18..a5e88e47 100755 --- a/C/Archive/7z/7zAlloc.h +++ b/C/Archive/7z/7zAlloc.h @@ -1,15 +1,23 @@ /* 7zAlloc.h -- Allocation functions -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ #ifndef __7Z_ALLOC_H #define __7Z_ALLOC_H #include <stddef.h> +#ifdef __cplusplus +extern "C" { +#endif + void *SzAlloc(void *p, size_t size); void SzFree(void *p, void *address); void *SzAllocTemp(void *p, size_t size); void SzFreeTemp(void *p, void *address); +#ifdef __cplusplus +} +#endif + #endif diff --git a/C/Archive/7z/7zDecode.c b/C/Archive/7z/7zDecode.c index 02526f0e..0d310a48 100755 --- a/C/Archive/7z/7zDecode.c +++ b/C/Archive/7z/7zDecode.c @@ -1,14 +1,17 @@ /* 7zDecode.c -- Decoding from 7z folder -2008-11-23 : Igor Pavlov : Public domain */ +2009-05-03 : Igor Pavlov : Public domain */ #include <string.h> #include "../../Bcj2.h" #include "../../Bra.h" #include "../../LzmaDec.h" +#include "../../Lzma2Dec.h" + #include "7zDecode.h" #define k_Copy 0 +#define k_LZMA2 0x21 #define k_LZMA 0x30101 #define k_BCJ 0x03030103 #define k_BCJ2 0x0303011B @@ -61,6 +64,55 @@ static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inSt 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) { while (inSize > 0) @@ -80,7 +132,7 @@ static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer 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_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) @@ -152,7 +204,7 @@ SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder, { 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; UInt64 offset; @@ -196,10 +248,14 @@ SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder, return SZ_ERROR_DATA; RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); } - else + else if (coder->MethodID == k_LZMA) { RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); } + else + { + RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); + } } else if (coder->MethodID == k_BCJ) { diff --git a/C/Archive/7z/7zDecode.h b/C/Archive/7z/7zDecode.h index e19fe387..0d77970d 100755 --- a/C/Archive/7z/7zDecode.h +++ b/C/Archive/7z/7zDecode.h @@ -1,13 +1,21 @@ /* 7zDecode.h -- Decoding from 7z folder -2008-11-23 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ #ifndef __7Z_DECODE_H #define __7Z_DECODE_H #include "7zItem.h" +#ifdef __cplusplus +extern "C" { +#endif + SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder, ILookInStream *stream, UInt64 startPos, Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); +#ifdef __cplusplus +} +#endif + #endif diff --git a/C/Archive/7z/7zExtract.h b/C/Archive/7z/7zExtract.h index 5f78415f..6f46bfa6 100755 --- a/C/Archive/7z/7zExtract.h +++ b/C/Archive/7z/7zExtract.h @@ -1,11 +1,15 @@ /* 7zExtract.h -- Extracting from 7z archive -2008-11-23 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ #ifndef __7Z_EXTRACT_H #define __7Z_EXTRACT_H #include "7zIn.h" +#ifdef __cplusplus +extern "C" { +#endif + /* SzExtract extracts file from archive @@ -38,4 +42,8 @@ SRes SzAr_Extract( ISzAlloc *allocMain, ISzAlloc *allocTemp); +#ifdef __cplusplus +} +#endif + #endif diff --git a/C/Archive/7z/7zHeader.h b/C/Archive/7z/7zHeader.h index 9941b6f7..bc117d2e 100755 --- a/C/Archive/7z/7zHeader.h +++ b/C/Archive/7z/7zHeader.h @@ -1,11 +1,15 @@ /* 7zHeader.h -- 7z Headers -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ #ifndef __7Z_HEADER_H #define __7Z_HEADER_H #include "../../Types.h" +#ifdef __cplusplus +extern "C" { +#endif + #define k7zSignatureSize 6 extern Byte k7zSignature[k7zSignatureSize]; @@ -54,4 +58,8 @@ enum EIdEnum k7zIdDummy }; +#ifdef __cplusplus +} +#endif + #endif diff --git a/C/Archive/7z/7zIn.h b/C/Archive/7z/7zIn.h index c8430a7b..50db4d38 100755 --- a/C/Archive/7z/7zIn.h +++ b/C/Archive/7z/7zIn.h @@ -1,5 +1,5 @@ -/* 7zIn.h -- 7z Input functions -2008-11-23 : Igor Pavlov : Public domain */ +/* 7zIn.h -- 7z Input +2009-02-07 : Igor Pavlov : Public domain */ #ifndef __7Z_IN_H #define __7Z_IN_H @@ -7,6 +7,10 @@ #include "7zHeader.h" #include "7zItem.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { CSzAr db; @@ -38,4 +42,8 @@ SZ_ERROR_FAIL SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp); +#ifdef __cplusplus +} +#endif + #endif diff --git a/C/Archive/7z/7zItem.h b/C/Archive/7z/7zItem.h index 9f1366cd..ce7288c2 100755 --- a/C/Archive/7z/7zItem.h +++ b/C/Archive/7z/7zItem.h @@ -1,11 +1,15 @@ /* 7zItem.h -- 7z Items -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ #ifndef __7Z_ITEM_H #define __7Z_ITEM_H #include "../../7zBuf.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { UInt32 NumInStreams; @@ -81,4 +85,8 @@ typedef struct void SzAr_Init(CSzAr *p); void SzAr_Free(CSzAr *p, ISzAlloc *alloc); +#ifdef __cplusplus +} +#endif + #endif diff --git a/C/Archive/7z/7zMain.c b/C/Archive/7z/7zMain.c index 0c20e8c3..ae65125f 100755 --- a/C/Archive/7z/7zMain.c +++ b/C/Archive/7z/7zMain.c @@ -1,5 +1,5 @@ /* 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 <stdio.h> @@ -13,6 +13,37 @@ #include "7zExtract.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) { char temp[32]; @@ -33,7 +64,7 @@ static void ConvertNumberToString(UInt64 value, char *s) #define PERIOD_100 (PERIOD_4 * 25 - 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; UInt64 v64 = ft->Low | ((UInt64)ft->High << 32); @@ -97,16 +128,19 @@ int MY_CDECL main(int numargs, char *args[]) SRes res; ISzAlloc allocImp; 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) { printf( - "\nUsage: 7zDec <command> <archive_name>\n\n" + "Usage: 7zDec <command> <archive_name>\n\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" - " t: Test integrity of archive\n"); + " t: Test integrity of archive\n" + " x: eXtract files with full paths\n"); return 0; } if (numargs < 3) @@ -141,17 +175,18 @@ int MY_CDECL main(int numargs, char *args[]) if (res == SZ_OK) { 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; else if (strcmp(command, "t") == 0) testCommand = 1; else if (strcmp(command, "e") == 0) extractCommand = 1; + else if (strcmp(command, "x") == 0) { extractCommand = 1; fullPaths = 1; } if (listCommand) { UInt32 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]; ConvertNumberToString(f->Size, s); if (f->MTimeDefined) @@ -159,7 +194,10 @@ int MY_CDECL main(int numargs, char *args[]) else 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) @@ -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. */ 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++) { size_t offset; size_t outSizeProcessed; - CSzFileItem *f = db.db.Files + i; - if (f->IsDir) - printf("Directory "); - else - printf(testCommand ? + const CSzFileItem *f = db.db.Files + i; + if (f->IsDir && !fullPaths) + continue; + printf(testCommand ? "Testing ": "Extracting"); printf(" %s", f->Name); if (f->IsDir) + printf("/"); + else { - printf("\n"); - continue; + res = SzAr_Extract(&db, &lookStream.s, i, + &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) { CSzFile outFile; size_t processedSize; - char *fileName = f->Name; - size_t nameLen = strlen(f->Name); - for (; nameLen > 0; nameLen--) - if (f->Name[nameLen - 1] == '/') + size_t j, nameLen = strlen(f->Name); + const char *destPath; + if (nameLen + 1 > tempSize) + { + SzFree(NULL, temp); + tempSize = nameLen + 1; + temp = (char *)SzAlloc(NULL, tempSize); + if (temp == 0) { - fileName = f->Name + nameLen; + res = SZ_ERROR_MEM; 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"); res = SZ_ERROR_FAIL; @@ -243,6 +304,7 @@ int MY_CDECL main(int numargs, char *args[]) } } SzArEx_Free(&db, &allocImp); + SzFree(NULL, temp); File_Close(&archiveStream.file); if (res == SZ_OK) diff --git a/C/Archive/7z/makefile b/C/Archive/7z/makefile index c7bb05bd..cf06c860 100755 --- a/C/Archive/7z/makefile +++ b/C/Archive/7z/makefile @@ -7,6 +7,7 @@ C_OBJS = \ $O\7zBuf2.obj \ $O\7zCrc.obj \ $O\LzmaDec.obj \ + $O\Lzma2Dec.obj \ $O\Bra86.obj \ $O\Bcj2.obj \ $O\7zFile.obj \ diff --git a/C/Archive/7z/makefile.gcc b/C/Archive/7z/makefile.gcc index 2203dfc1..29d2aa02 100755 --- a/C/Archive/7z/makefile.gcc +++ b/C/Archive/7z/makefile.gcc @@ -4,7 +4,7 @@ LIB = RM = rm -f 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) @@ -44,6 +44,9 @@ $(PROG): $(OBJS) LzmaDec.o: ../../LzmaDec.c $(CXX) $(CFLAGS) ../../LzmaDec.c +Lzma2Dec.o: ../../Lzma2Dec.c + $(CXX) $(CFLAGS) ../../Lzma2Dec.c + Bra86.o: ../../Bra86.c $(CXX) $(CFLAGS) ../../Bra86.c @@ -1,11 +1,15 @@ /* Bcj2.h -- Converter for x86 code (BCJ2) -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ #ifndef __BCJ2_H #define __BCJ2_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + /* Conditions: outSize <= FullOutputSize, @@ -27,4 +31,8 @@ int Bcj2_Decode( const Byte *buf3, SizeT size3, Byte *outBuf, SizeT outSize); +#ifdef __cplusplus +} +#endif + #endif @@ -1,11 +1,15 @@ /* Bra.h -- Branch converters for executables -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ #ifndef __BRA_H #define __BRA_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + /* These functions convert relative addresses to absolute addresses 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 IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +#ifdef __cplusplus +} +#endif + #endif diff --git a/C/BwtSort.h b/C/BwtSort.h index f373213e..ce5598f0 100755 --- a/C/BwtSort.h +++ b/C/BwtSort.h @@ -1,13 +1,15 @@ /* BwtSort.h -- BWT block sorting -2008-03-26 -Igor Pavlov -Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ -#ifndef __BWTSORT_H -#define __BWTSORT_H +#ifndef __BWT_SORT_H +#define __BWT_SORT_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + /* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize can be > 1M */ /* #define BLOCK_SORT_EXTERNAL_FLAGS */ @@ -21,4 +23,8 @@ Public domain */ UInt32 BlockSort(UInt32 *indices, const Byte *data, UInt32 blockSize); +#ifdef __cplusplus +} +#endif + #endif diff --git a/C/CpuArch.h b/C/CpuArch.h index 7384b0c3..10ec02b3 100755 --- a/C/CpuArch.h +++ b/C/CpuArch.h @@ -1,10 +1,12 @@ /* CpuArch.h -2008-08-05 -Igor Pavlov -Public domain */ +2009-03-22 : Igor Pavlov : Public domain */ -#ifndef __CPUARCH_H -#define __CPUARCH_H +#ifndef __CPU_ARCH_H +#define __CPU_ARCH_H + +#ifdef __cplusplus +extern "C" { +#endif /* LITTLE_ENDIAN_UNALIGN means: @@ -23,6 +25,7 @@ about these properties of platform. #define GetUi16(p) (*(const UInt16 *)(p)) #define GetUi32(p) (*(const UInt32 *)(p)) #define GetUi64(p) (*(const UInt64 *)(p)) +#define SetUi16(p, d) *(UInt16 *)(p) = (d); #define SetUi32(p, d) *(UInt32 *)(p) = (d); #else @@ -37,6 +40,10 @@ about these properties of platform. #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); \ ((Byte *)(p))[0] = (Byte)_x_; \ ((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]) +#ifdef __cplusplus +} +#endif + #endif diff --git a/C/Delta.c b/C/Delta.c new file mode 100755 index 00000000..2b327f15 --- /dev/null +++ b/C/Delta.c @@ -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); +} diff --git a/C/Delta.h b/C/Delta.h new file mode 100755 index 00000000..0d4cd627 --- /dev/null +++ b/C/Delta.h @@ -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 diff --git a/C/HuffEnc.h b/C/HuffEnc.h index 00dd9aca..9cf4bfde 100755 --- a/C/HuffEnc.h +++ b/C/HuffEnc.h @@ -1,13 +1,15 @@ -/* HuffEnc.h -- functions for Huffman encoding -2008-03-26 -Igor Pavlov -Public domain */ +/* HuffEnc.h -- Huffman encoding +2009-02-07 : Igor Pavlov : Public domain */ -#ifndef __HUFFENC_H -#define __HUFFENC_H +#ifndef __HUFF_ENC_H +#define __HUFF_ENC_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + /* Conditions: num <= 1024 = 2 ^ NUM_BITS @@ -18,4 +20,8 @@ Conditions: void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen); +#ifdef __cplusplus +} +#endif + #endif @@ -1,5 +1,5 @@ /* LzFind.c -- Match finder for LZ algorithms -2008-10-04 : Igor Pavlov : Public domain */ +2009-04-22 : Igor Pavlov : Public domain */ #include <string.h> @@ -58,6 +58,17 @@ static void MatchFinder_ReadBlock(CMatchFinder *p) { if (p->streamEndWasReached || p->result != SZ_OK) 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 (;;) { Byte *dest = p->buffer + (p->streamPos - p->pos); @@ -88,6 +99,8 @@ void MatchFinder_MoveBlock(CMatchFinder *p) int MatchFinder_NeedMove(CMatchFinder *p) { + if (p->directInput) + return 0; /* if (p->streamEndWasReached) return 0; */ 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->btMode = 1; p->numHashBytes = 4; - /* p->skipModeBits = 0; */ - p->directInput = 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 */ if (LzInWindow_Create(p, sizeReserv, alloc)) { - UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; + UInt32 newCyclicBufferSize = historySize + 1; UInt32 hs; p->matchMaxLen = matchMaxLen; { @@ -192,7 +203,6 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; - /* hs >>= p->skipModeBits; */ hs |= 0xFFFF; /* don't change it! It's required for Deflate */ if (hs > (1 << 24)) { @@ -1,11 +1,15 @@ /* LzFind.h -- Match finder for LZ algorithms -2008-10-04 : Igor Pavlov : Public domain */ +2009-04-22 : Igor Pavlov : Public domain */ -#ifndef __LZFIND_H -#define __LZFIND_H +#ifndef __LZ_FIND_H +#define __LZ_FIND_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef UInt32 CLzRef; typedef struct _CMatchFinder @@ -35,8 +39,8 @@ typedef struct _CMatchFinder UInt32 numHashBytes; int directInput; + size_t directInputRem; int btMode; - /* int skipModeBits; */ int bigHash; UInt32 historySize; UInt32 fixedHashSize; @@ -104,4 +108,8 @@ UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); +#ifdef __cplusplus +} +#endif + #endif diff --git a/C/LzFindMt.c b/C/LzFindMt.c index b49cd76b..5c23f8ea 100755 --- a/C/LzFindMt.c +++ b/C/LzFindMt.c @@ -1,5 +1,5 @@ /* 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" @@ -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(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(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) { diff --git a/C/LzFindMt.h b/C/LzFindMt.h index 2c7e462d..b985af5f 100755 --- a/C/LzFindMt.h +++ b/C/LzFindMt.h @@ -1,11 +1,15 @@ /* 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 -#define __LZFINDMT_H +#ifndef __LZ_FIND_MT_H +#define __LZ_FIND_MT_H -#include "Threads.h" #include "LzFind.h" +#include "Threads.h" + +#ifdef __cplusplus +extern "C" { +#endif #define kMtHashBlockSize (1 << 13) #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_ReleaseStream(CMatchFinderMt *p); +#ifdef __cplusplus +} +#endif + #endif @@ -1,8 +1,8 @@ /* LzHash.h -- HASH functions for LZ algorithms -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ -#ifndef __LZHASH_H -#define __LZHASH_H +#ifndef __LZ_HASH_H +#define __LZ_HASH_H #define kHash2Size (1 << 10) #define kHash3Size (1 << 16) diff --git a/C/Lzma2Dec.c b/C/Lzma2Dec.c new file mode 100755 index 00000000..7ea1cc95 --- /dev/null +++ b/C/Lzma2Dec.c @@ -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; +} diff --git a/C/Lzma2Dec.h b/C/Lzma2Dec.h new file mode 100755 index 00000000..6bc07bbc --- /dev/null +++ b/C/Lzma2Dec.h @@ -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 diff --git a/C/Lzma2Enc.c b/C/Lzma2Enc.c new file mode 100755 index 00000000..afccd4da --- /dev/null +++ b/C/Lzma2Enc.c @@ -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 +} diff --git a/C/Lzma2Enc.h b/C/Lzma2Enc.h new file mode 100755 index 00000000..28352558 --- /dev/null +++ b/C/Lzma2Enc.h @@ -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 diff --git a/C/LzmaDec.h b/C/LzmaDec.h index 98cdbe94..bf7f084b 100755 --- a/C/LzmaDec.h +++ b/C/LzmaDec.h @@ -1,11 +1,15 @@ /* LzmaDec.h -- LZMA Decoder -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ -#ifndef __LZMADEC_H -#define __LZMADEC_H +#ifndef __LZMA_DEC_H +#define __LZMA_DEC_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + /* #define _LZMA_PROB32 */ /* _LZMA_PROB32 can increase the speed on some CPUs, 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, ELzmaStatus *status, ISzAlloc *alloc); +#ifdef __cplusplus +} +#endif + #endif diff --git a/C/LzmaEnc.c b/C/LzmaEnc.c index 9196c43f..20ad727f 100755 --- a/C/LzmaEnc.c +++ b/C/LzmaEnc.c @@ -1,5 +1,5 @@ /* LzmaEnc.c -- LZMA Encoder -2009-02-02 : Igor Pavlov : Public domain */ +2009-04-22 : Igor Pavlov : Public domain */ #include <string.h> @@ -139,7 +139,7 @@ void LzmaEnc_FastPosInit(Byte *g_FastPos) typedef unsigned CState; -typedef struct _COptimal +typedef struct { UInt32 price; @@ -218,7 +218,7 @@ typedef struct UInt32 counters[LZMA_NUM_PB_STATES_MAX]; } CLenPriceEnc; -typedef struct _CRangeEnc +typedef struct { UInt32 range; Byte cache; @@ -232,26 +232,6 @@ typedef struct _CRangeEnc SRes res; } 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 { CLzmaProb *litProbs; @@ -274,7 +254,7 @@ typedef struct UInt32 state; } CSaveState; -typedef struct _CLzmaEnc +typedef struct { IMatchFinder matchFinder; void *matchFinderObj; @@ -351,8 +331,7 @@ typedef struct _CLzmaEnc UInt32 dictSize; UInt32 matchFinderCycles; - ISeqInStream *inStream; - CSeqInStreamBuf seqBufInStream; + int needInit; CSaveState saveState; } 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) { UInt32 nowPos32, startPos32; - if (p->inStream != 0) + if (p->needInit) { - p->matchFinderBase.stream = p->inStream; p->matchFinder.Init(p->matchFinderObj); - p->inStream = 0; + p->needInit = 0; } if (p->finished) @@ -2056,11 +2034,12 @@ static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *a 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) { CLzmaEnc *p = (CLzmaEnc *)pp; - p->inStream = inStream; + p->matchFinderBase.stream = inStream; + p->needInit = 1; p->rc.outStream = outStream; return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); } @@ -2070,15 +2049,16 @@ SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; - p->inStream = inStream; + p->matchFinderBase.stream = inStream; + p->needInit = 1; return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) { - p->seqBufInStream.funcTable.Read = MyRead; - p->seqBufInStream.data = src; - p->seqBufInStream.rem = srcLen; + p->matchFinderBase.directInput = 1; + p->matchFinderBase.bufferBase = (Byte *)src; + p->matchFinderBase.directInputRem = 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; LzmaEnc_SetInputBuf(p, src, srcLen); - p->inStream = &p->seqBufInStream.funcTable; + p->needInit = 1; + return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } @@ -2101,7 +2082,7 @@ void LzmaEnc_Finish(CLzmaEncHandle pp) #endif } -typedef struct _CSeqOutStreamBuf +typedef struct { ISeqOutStream funcTable; Byte *data; @@ -2170,10 +2151,8 @@ SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, return res; } -SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, - ISzAlloc *alloc, ISzAlloc *allocBig) +static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) { - CLzmaEnc *p = (CLzmaEnc *)pp; SRes res = SZ_OK; #ifdef COMPRESS_MF_MT @@ -2183,8 +2162,6 @@ SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *i allocaDummy[i] = (Byte)i; #endif - RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig)); - for (;;) { 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; } +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) { CLzmaEnc *p = (CLzmaEnc *)pp; @@ -2249,8 +2233,11 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte outStream.overflow = False; 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; if (outStream.overflow) diff --git a/C/LzmaEnc.h b/C/LzmaEnc.h index bfbc7d2b..200d60eb 100755 --- a/C/LzmaEnc.h +++ b/C/LzmaEnc.h @@ -1,11 +1,15 @@ /* LzmaEnc.h -- LZMA Encoder -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ -#ifndef __LZMAENC_H -#define __LZMAENC_H +#ifndef __LZMA_ENC_H +#define __LZMA_ENC_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + #define LZMA_PROPS_SIZE 5 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, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); +#ifdef __cplusplus +} +#endif + #endif diff --git a/C/LzmaLib.h b/C/LzmaLib.h index 5c9eeec7..76c99ce7 100755 --- a/C/LzmaLib.h +++ b/C/LzmaLib.h @@ -1,20 +1,16 @@ /* LzmaLib.h -- LZMA library interface -2008-08-05 -Igor Pavlov -Public domain */ +2009-04-07 : Igor Pavlov : Public domain */ -#ifndef __LZMALIB_H -#define __LZMALIB_H +#ifndef __LZMA_LIB_H +#define __LZMA_LIB_H #include "Types.h" #ifdef __cplusplus - #define MY_EXTERN_C extern "C" -#else - #define MY_EXTERN_C extern +extern "C" { #endif -#define MY_STDAPI MY_EXTERN_C int MY_STD_CALL +#define MY_STDAPI int MY_STD_CALL #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, const unsigned char *props, size_t propsSize); +#ifdef __cplusplus +} +#endif + #endif diff --git a/C/LzmaUtil/Lzma86Dec.h b/C/LzmaUtil/Lzma86Dec.h index f7118219..138ce1ff 100755 --- a/C/LzmaUtil/Lzma86Dec.h +++ b/C/LzmaUtil/Lzma86Dec.h @@ -1,13 +1,15 @@ /* Lzma86Dec.h -- LZMA + x86 (BCJ) Filter Decoder -2008-08-05 -Igor Pavlov -Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ -#ifndef __LZMA86DEC_H -#define __LZMA86DEC_H +#ifndef __LZMA86_DEC_H +#define __LZMA86_DEC_H #include "../Types.h" +#ifdef __cplusplus +extern "C" { +#endif + /* Lzma86_GetUnpackSize: In: @@ -42,4 +44,8 @@ Lzma86_Decode: SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen); +#ifdef __cplusplus +} +#endif + #endif diff --git a/C/LzmaUtil/Lzma86Enc.h b/C/LzmaUtil/Lzma86Enc.h index 10be1cd7..355bf343 100755 --- a/C/LzmaUtil/Lzma86Enc.h +++ b/C/LzmaUtil/Lzma86Enc.h @@ -1,13 +1,15 @@ /* Lzma86Enc.h -- LZMA + x86 (BCJ) Filter Encoder -2008-08-05 -Igor Pavlov -Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ -#ifndef __LZMA86ENC_H -#define __LZMA86ENC_H +#ifndef __LZMA86_ENC_H +#define __LZMA86_ENC_H #include "../Types.h" +#ifdef __cplusplus +extern "C" { +#endif + /* It's an example for LZMA + x86 Filter use. 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, int level, UInt32 dictSize, int filterMode); +#ifdef __cplusplus +} +#endif + #endif diff --git a/C/MtCoder.c b/C/MtCoder.c new file mode 100755 index 00000000..57cfe353 --- /dev/null +++ b/C/MtCoder.c @@ -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(<->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; +} diff --git a/C/MtCoder.h b/C/MtCoder.h new file mode 100755 index 00000000..fb813d4d --- /dev/null +++ b/C/MtCoder.h @@ -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 diff --git a/C/RotateDefs.h b/C/RotateDefs.h index 95d9646b..c3a1385c 100755 --- a/C/RotateDefs.h +++ b/C/RotateDefs.h @@ -1,10 +1,8 @@ /* RotateDefs.h -- Rotate functions -2008-08-05 -Igor Pavlov -Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ -#ifndef __ROTATEDEFS_H -#define __ROTATEDEFS_H +#ifndef __ROTATE_DEFS_H +#define __ROTATE_DEFS_H #ifdef _MSC_VER @@ -1,11 +1,15 @@ -/* Crypto/Sha256.h -- SHA-256 Hash function -2008-10-04 : Igor Pavlov : Public domain */ +/* Sha256.h -- SHA-256 Hash +2009-02-07 : Igor Pavlov : Public domain */ #ifndef __CRYPTO_SHA256_H #define __CRYPTO_SHA256_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + #define SHA256_DIGEST_SIZE 32 typedef struct @@ -19,4 +23,8 @@ void Sha256_Init(CSha256 *p); void Sha256_Update(CSha256 *p, const Byte *data, size_t size); void Sha256_Final(CSha256 *p, Byte *digest); +#ifdef __cplusplus +} +#endif + #endif @@ -1,14 +1,20 @@ /* Sort.h -- Sort functions -2008-03-19 -Igor Pavlov -Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ #ifndef __7Z_SORT_H #define __7Z_SORT_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + void HeapSort(UInt32 *p, UInt32 size); /* void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size); */ +#ifdef __cplusplus +} +#endif + #endif diff --git a/C/Threads.c b/C/Threads.c index 4fdd69b0..562b3484 100755 --- a/C/Threads.c +++ b/C/Threads.c @@ -1,11 +1,10 @@ /* Threads.c -- multithreading library -2008-08-05 -Igor Pavlov -Public domain */ +2009-03-27 : Igor Pavlov : Public domain */ -#include "Threads.h" #include <process.h> +#include "Threads.h" + static WRes GetError() { DWORD res = GetLastError(); @@ -15,85 +14,53 @@ static WRes GetError() WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); } WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); } -static WRes MyCloseHandle(HANDLE *h) +WRes HandlePtr_Close(HANDLE *p) { - if (*h != NULL) - if (!CloseHandle(*h)) + if (*p != NULL) + if (!CloseHandle(*p)) return GetError(); - *h = NULL; + *p = NULL; 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 */ - thread->handle = - /* CreateThread(0, 0, startAddress, parameter, 0, &threadId); */ - (HANDLE)_beginthreadex(NULL, 0, startAddress, parameter, 0, &threadId); + *p = + /* CreateThread(0, 0, startAddress, param, 0, &threadId); */ + (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId); /* maybe we must use errno here, but probably GetLastError() is also OK. */ - return HandleToWRes(thread->handle); -} - -WRes WaitObject(HANDLE h) -{ - return (WRes)WaitForSingleObject(h, INFINITE); -} - -WRes Thread_Wait(CThread *thread) -{ - if (thread->handle == NULL) - return 1; - return WaitObject(thread->handle); -} - -WRes Thread_Close(CThread *thread) -{ - return MyCloseHandle(&thread->handle); + return HandleToWRes(*p); } -WRes Event_Create(CEvent *p, BOOL manualReset, int initialSignaled) +WRes Event_Create(CEvent *p, BOOL manualReset, int signaled) { - p->handle = CreateEvent(NULL, manualReset, (initialSignaled ? TRUE : FALSE), NULL); - return HandleToWRes(p->handle); + *p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL); + return HandleToWRes(*p); } -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)); } +WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(*p)); } -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 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 initiallyCount, UInt32 maxCount) +WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount) { - p->handle = CreateSemaphore(NULL, (LONG)initiallyCount, (LONG)maxCount, NULL); - return HandleToWRes(p->handle); + *p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL); + return HandleToWRes(*p); } -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); } +static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) + { return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); } +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 CriticalSection_Init(CCriticalSection *p) { @@ -106,4 +73,3 @@ WRes CriticalSection_Init(CCriticalSection *p) __except (EXCEPTION_EXECUTE_HANDLER) { return 1; } return 0; } - diff --git a/C/Threads.h b/C/Threads.h index a823e578..d0ddd80e 100755 --- a/C/Threads.h +++ b/C/Threads.h @@ -1,68 +1,59 @@ /* Threads.h -- multithreading library -2008-11-22 : Igor Pavlov : Public domain */ +2009-03-27 : Igor Pavlov : Public domain */ -#ifndef __7Z_THRESDS_H -#define __7Z_THRESDS_H +#ifndef __7Z_THREADS_H +#define __7Z_THREADS_H #include "Types.h" -typedef struct _CThread -{ - HANDLE handle; -} CThread; +#ifdef __cplusplus +extern "C" { +#endif + +WRes HandlePtr_Close(HANDLE *h); +WRes Handle_WaitObject(HANDLE h); -#define Thread_Construct(thread) (thread)->handle = NULL -#define Thread_WasCreated(thread) ((thread)->handle != NULL) - +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; #define THREAD_FUNC_CALL_TYPE MY_STD_CALL #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); -WRes Thread_Wait(CThread *thread); -WRes Thread_Close(CThread *thread); - -typedef struct _CEvent -{ - HANDLE handle; -} CEvent; - +typedef HANDLE CEvent; typedef CEvent CAutoResetEvent; typedef CEvent CManualResetEvent; - -#define Event_Construct(event) (event)->handle = NULL -#define Event_IsCreated(event) ((event)->handle != NULL) - -WRes ManualResetEvent_Create(CManualResetEvent *event, int initialSignaled); -WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *event); -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); +#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); + +typedef HANDLE CSemaphore; +#define Semaphore_Construct(p) (*p) = NULL +#define Semaphore_Close(p) HandlePtr_Close(p) +#define Semaphore_Wait(p) Handle_WaitObject(*(p)) +WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount); WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); WRes Semaphore_Release1(CSemaphore *p); -WRes Semaphore_Wait(CSemaphore *p); -WRes Semaphore_Close(CSemaphore *p); - typedef CRITICAL_SECTION CCriticalSection; - WRes CriticalSection_Init(CCriticalSection *p); #define CriticalSection_Delete(p) DeleteCriticalSection(p) #define CriticalSection_Enter(p) EnterCriticalSection(p) #define CriticalSection_Leave(p) LeaveCriticalSection(p) +#ifdef __cplusplus +} #endif +#endif @@ -1,5 +1,5 @@ /* Types.h -- Basic types -2008-11-23 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ #ifndef __7Z_TYPES_H #define __7Z_TYPES_H @@ -10,6 +10,10 @@ #include <windows.h> #endif +#ifdef __cplusplus +extern "C" { +#endif + #define SZ_OK 0 #define SZ_ERROR_DATA 1 @@ -205,4 +209,8 @@ typedef struct #define IAlloc_Alloc(p, size) (p)->Alloc((p), size) #define IAlloc_Free(p, a) (p)->Free((p), a) +#ifdef __cplusplus +} +#endif + #endif @@ -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; +} @@ -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 diff --git a/C/XzCrc64.c b/C/XzCrc64.c new file mode 100755 index 00000000..52952ebe --- /dev/null +++ b/C/XzCrc64.c @@ -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)); +} diff --git a/C/XzCrc64.h b/C/XzCrc64.h new file mode 100755 index 00000000..37a67dc2 --- /dev/null +++ b/C/XzCrc64.h @@ -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 diff --git a/C/XzDec.c b/C/XzDec.c new file mode 100755 index 00000000..8ae234d0 --- /dev/null +++ b/C/XzDec.c @@ -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); +} diff --git a/C/XzEnc.c b/C/XzEnc.c new file mode 100755 index 00000000..3958308b --- /dev/null +++ b/C/XzEnc.c @@ -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; +} diff --git a/C/XzEnc.h b/C/XzEnc.h new file mode 100755 index 00000000..13390df8 --- /dev/null +++ b/C/XzEnc.h @@ -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 diff --git a/C/XzIn.c b/C/XzIn.c new file mode 100755 index 00000000..f8c76bfe --- /dev/null +++ b/C/XzIn.c @@ -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; +} diff --git a/CPP/7zip/Archive/7z/7z.dsp b/CPP/7zip/Archive/7z/7z.dsp index bddb2673..cf7aa975 100755 --- a/CPP/7zip/Archive/7z/7z.dsp +++ b/CPP/7zip/Archive/7z/7z.dsp @@ -598,11 +598,11 @@ SOURCE=..\..\..\Windows\Thread.h # PROP Default_Filter "" # Begin Source File -SOURCE=..\..\Compress\Copy\CopyCoder.cpp +SOURCE=..\..\Compress\CopyCoder.cpp # End Source File # Begin Source File -SOURCE=..\..\Compress\Copy\CopyCoder.h +SOURCE=..\..\Compress\CopyCoder.h # End Source File # End Group # Begin Group "C" diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp index 01803842..c97f893b 100755 --- a/CPP/7zip/Archive/7z/7zEncode.cpp +++ b/CPP/7zip/Archive/7z/7zEncode.cpp @@ -1,21 +1,21 @@ -// Encode.cpp +// 7zEncode.cpp #include "StdAfx.h" -#include "7zEncode.h" -#include "7zSpecStream.h" - -#include "../../IPassword.h" -#include "../../Common/ProgressUtils.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 "../../Common/CreateCoder.h" -#include "../../Common/FilterCoder.h" -static const UInt64 k_AES = 0x06F10701; -static const UInt64 k_BCJ = 0x03030103; +#include "7zEncode.h" +#include "7zSpecStream.h" + +static const UInt64 k_Delta = 0x03; +static const UInt64 k_BCJ = 0x03030103; static const UInt64 k_BCJ2 = 0x0303011B; +static const UInt64 k_AES = 0x06F10701; namespace NArchive { namespace N7z { @@ -240,10 +240,10 @@ HRESULT CEncoder::Encode( UInt32 progressIndex = mainCoderIndex; - for (i = 0; i < _codersInfo.Size(); i++) + for (i = 0; i + 1 < _codersInfo.Size(); i++) { - const CCoderInfo &e = _codersInfo[i]; - if ((e.MethodID == k_BCJ || e.MethodID == k_BCJ2) && i + 1 < _codersInfo.Size()) + UInt64 m = _codersInfo[i].MethodID; + if (m == k_Delta || m == k_BCJ || m == k_BCJ2) progressIndex = i + 1; } diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp index 61b938d0..75505863 100755 --- a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp +++ b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp @@ -9,156 +9,132 @@ namespace N7z { CFolderOutStream::CFolderOutStream() { - _outStreamWithHashSpec = new COutStreamWithCRC; - _outStreamWithHash = _outStreamWithHashSpec; + _crcStreamSpec = new COutStreamWithCRC; + _crcStream = _crcStreamSpec; } HRESULT CFolderOutStream::Init( const CArchiveDatabaseEx *archiveDatabase, - UInt32 ref2Offset, - UInt32 startIndex, + UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, - bool testMode, - bool checkCrc) + bool testMode, bool checkCrc) { - _archiveDatabase = archiveDatabase; + _db = archiveDatabase; _ref2Offset = ref2Offset; _startIndex = startIndex; _extractStatuses = extractStatuses; _extractCallback = extractCallback; _testMode = testMode; - _checkCrc = checkCrc; _currentIndex = 0; _fileIsOpen = false; - return WriteEmptyFiles(); + return ProcessEmptyFiles(); } HRESULT CFolderOutStream::OpenFile() { - Int32 askMode; - if((*_extractStatuses)[_currentIndex]) - askMode = _testMode ? - NArchive::NExtract::NAskMode::kTest : - NArchive::NExtract::NAskMode::kExtract; - else - askMode = NArchive::NExtract::NAskMode::kSkip; + Int32 askMode = ((*_extractStatuses)[_currentIndex]) ? (_testMode ? + NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract): + NArchive::NExtract::NAskMode::kSkip; CMyComPtr<ISequentialOutStream> realOutStream; - UInt32 index = _startIndex + _currentIndex; RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode)); - - _outStreamWithHashSpec->SetStream(realOutStream); - _outStreamWithHashSpec->Init(_checkCrc); - if (askMode == NArchive::NExtract::NAskMode::kExtract && - (!realOutStream)) - { - const CFileItem &fi = _archiveDatabase->Files[index]; - if (!_archiveDatabase->IsItemAnti(index) && !fi.IsDir) - askMode = NArchive::NExtract::NAskMode::kSkip; - } + _crcStreamSpec->SetStream(realOutStream); + _crcStreamSpec->Init(_checkCrc); + _fileIsOpen = true; + const CFileItem &fi = _db->Files[index]; + _rem = fi.Size; + if (askMode == NArchive::NExtract::NAskMode::kExtract && !realOutStream && + !_db->IsItemAnti(index) && !fi.IsDir) + askMode = NArchive::NExtract::NAskMode::kSkip; return _extractCallback->PrepareOperation(askMode); } -HRESULT CFolderOutStream::WriteEmptyFiles() +HRESULT CFolderOutStream::CloseFileAndSetResult(Int32 res) +{ + _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() { - for(;_currentIndex < _extractStatuses->Size(); _currentIndex++) + 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(_extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); - _outStreamWithHashSpec->ReleaseStream(); + RINOK(CloseFileAndSetResult()); } return S_OK; } -STDMETHODIMP CFolderOutStream::Write(const void *data, - UInt32 size, UInt32 *processedSize) +STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { - UInt32 realProcessedSize = 0; - while(_currentIndex < _extractStatuses->Size()) + if (processedSize != NULL) + *processedSize = 0; + while (size != 0) { if (_fileIsOpen) { - UInt32 index = _startIndex + _currentIndex; - const CFileItem &fi = _archiveDatabase->Files[index]; - UInt64 fileSize = fi.Size; - - UInt32 numBytesToWrite = (UInt32)MyMin(fileSize - _filePos, - UInt64(size - realProcessedSize)); - - UInt32 processedSizeLocal; - RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize, - numBytesToWrite, &processedSizeLocal)); - - _filePos += processedSizeLocal; - realProcessedSize += processedSizeLocal; - if (_filePos == fileSize) + UInt32 cur = size < _rem ? size : (UInt32)_rem; + RINOK(_crcStream->Write(data, cur, &cur)); + if (cur == 0) + break; + data = (const Byte *)data + cur; + size -= cur; + _rem -= cur; + if (processedSize != NULL) + *processedSize += cur; + if (_rem == 0) { - bool digestsAreEqual; - if (fi.CrcDefined && _checkCrc) - digestsAreEqual = fi.Crc == _outStreamWithHashSpec->GetCRC(); - 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(); + RINOK(CloseFileAndSetResult()); + RINOK(ProcessEmptyFiles()); + continue; } } else { + RINOK(ProcessEmptyFiles()); + if (_currentIndex == _extractStatuses->Size()) + { + // we support partial extracting + if (processedSize != NULL) + *processedSize += size; + break; + } RINOK(OpenFile()); - _fileIsOpen = true; - _filePos = 0; } } - if (processedSize != NULL) - *processedSize = size; return S_OK; } HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult) { - while(_currentIndex < _extractStatuses->Size()) + while (_currentIndex < _extractStatuses->Size()) { if (_fileIsOpen) { - RINOK(_extractCallback->SetOperationResult(resultEOperationResult)); - _outStreamWithHashSpec->ReleaseStream(); - _fileIsOpen = false; - _currentIndex++; + RINOK(CloseFileAndSetResult(resultEOperationResult)); } else { RINOK(OpenFile()); - _fileIsOpen = true; } } return S_OK; } -HRESULT CFolderOutStream::WasWritingFinished() -{ - if (_currentIndex == _extractStatuses->Size()) - return S_OK; - return E_FAIL; -} - }} diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.h b/CPP/7zip/Archive/7z/7zFolderOutStream.h index f54fba3e..e6e05b85 100755 --- a/CPP/7zip/Archive/7z/7zFolderOutStream.h +++ b/CPP/7zip/Archive/7z/7zFolderOutStream.h @@ -1,7 +1,7 @@ // 7zFolderOutStream.h -#ifndef __7Z_FOLDEROUTSTREAM_H -#define __7Z_FOLDEROUTSTREAM_H +#ifndef __7Z_FOLDER_OUT_STREAM_H +#define __7Z_FOLDER_OUT_STREAM_H #include "7zIn.h" @@ -16,43 +16,39 @@ class CFolderOutStream: public ISequentialOutStream, public CMyUnknownImp { -public: - MY_UNKNOWN_IMP - - CFolderOutStream(); - - STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); -private: - - COutStreamWithCRC *_outStreamWithHashSpec; - CMyComPtr<ISequentialOutStream> _outStreamWithHash; - const CArchiveDatabaseEx *_archiveDatabase; + COutStreamWithCRC *_crcStreamSpec; + CMyComPtr<ISequentialOutStream> _crcStream; + const CArchiveDatabaseEx *_db; const CBoolVector *_extractStatuses; - UInt32 _startIndex; + CMyComPtr<IArchiveExtractCallback> _extractCallback; UInt32 _ref2Offset; + UInt32 _startIndex; int _currentIndex; - // UInt64 _currentDataPos; - CMyComPtr<IArchiveExtractCallback> _extractCallback; bool _testMode; - - bool _fileIsOpen; - bool _checkCrc; - UInt64 _filePos; + bool _fileIsOpen; + UInt64 _rem; HRESULT OpenFile(); - HRESULT WriteEmptyFiles(); + HRESULT CloseFileAndSetResult(Int32 res); + HRESULT CloseFileAndSetResult(); + HRESULT ProcessEmptyFiles(); public: + MY_UNKNOWN_IMP + + CFolderOutStream(); + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + HRESULT Init( const CArchiveDatabaseEx *archiveDatabase, - UInt32 ref2Offset, - UInt32 startIndex, + UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, - bool testMode, - bool checkCrc); + bool testMode, bool checkCrc); HRESULT FlushCorrupted(Int32 resultEOperationResult); - HRESULT WasWritingFinished(); + HRESULT WasWritingFinished() const + { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; } }; }} diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp index 44131fae..6f0cf6b2 100755 --- a/CPP/7zip/Archive/7z/7zHandler.cpp +++ b/CPP/7zip/Archive/7z/7zHandler.cpp @@ -2,10 +2,7 @@ #include "StdAfx.h" -extern "C" -{ - #include "../../../../C/CpuArch.h" -} +#include "../../../../C/CpuArch.h" #include "../../../Common/ComTry.h" #include "../../../Common/IntToString.h" @@ -176,6 +173,8 @@ static UString GetStringForSizeValue(UInt32 value) } static const UInt64 k_Copy = 0x0; +static const UInt64 k_Delta = 3; +static const UInt64 k_LZMA2 = 0x21; static const UInt64 k_LZMA = 0x030101; static const UInt64 k_PPMD = 0x030401; @@ -183,12 +182,10 @@ static wchar_t GetHex(Byte value) { 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; - result += GetHex((Byte)(value >> 4)); - result += GetHex((Byte)(value & 0xF)); - return result; + res += GetHex((Byte)(value >> 4)); + res += GetHex((Byte)(value & 0xF)); } #endif @@ -273,89 +270,82 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va UString methodsString; 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()) methodsString += L' '; + UString methodName, propsString; + bool methodIsKnown = FindMethod( + EXTERNAL_CODECS_VARS + coder.MethodID, methodName); + + if (!methodIsKnown) + methodsString += ConvertMethodIdToString(coder.MethodID); + else { - UString methodName; - bool methodIsKnown = FindMethod( - EXTERNAL_CODECS_VARS - coderInfo.MethodID, methodName); - - if (methodIsKnown) + methodsString += methodName; + if (coder.MethodID == k_Delta && coder.Props.GetCapacity() == 1) + propsString = ConvertUInt32ToString((UInt32)coder.Props[0] + 1); + else if (coder.MethodID == k_LZMA && coder.Props.GetCapacity() == 5) { - methodsString += methodName; - if (coderInfo.MethodID == k_LZMA) - { - if (coderInfo.Props.GetCapacity() >= 5) - { - methodsString += L":"; - UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1); - methodsString += GetStringForSizeValue(dicSize); - } - } - else if (coderInfo.MethodID == k_PPMD) + UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1); + 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) { - 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); + Byte secondByte = *data++; + saltSize += (secondByte >> 4); + ivSize += (secondByte & 0x0F); } } - else if (coderInfo.MethodID == k_AES) + */ + } + } + 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() >= 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); - } - } - */ - } + methodsString += L".."; + break; } else - { - 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); + AddHexToString(methodsString, coder.Props[bi]); } + methodsString += L']'; } } prop = methodsString; diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h index 9adf8464..68fb034f 100755 --- a/CPP/7zip/Archive/7z/7zHandler.h +++ b/CPP/7zip/Archive/7z/7zHandler.h @@ -5,9 +5,6 @@ #include "../../ICoder.h" #include "../IArchive.h" -#include "7zIn.h" - -#include "7zCompressionMode.h" #include "../../Common/CreateCoder.h" @@ -15,6 +12,9 @@ #include "../Common/HandlerOut.h" #endif +#include "7zCompressionMode.h" +#include "7zIn.h" + namespace NArchive { namespace N7z { @@ -90,8 +90,6 @@ private: CRecordVector<CBind> _binds; - HRESULT SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback); - HRESULT SetCompressionMethod(CCompressionMethodMode &method, CObjectVector<COneMethodInfo> &methodsInfo #ifdef COMPRESS_MT diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp index 3e2591d5..e2c250ab 100755 --- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp +++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp @@ -40,31 +40,6 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) 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( CCompressionMethodMode &methodMode, CCompressionMethodMode &headerMethod) @@ -210,7 +185,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt const CArchiveDatabaseEx *db = 0; #ifdef _7Z_VOL - if(_volumes.Size() > 1) + if (_volumes.Size() > 1) return E_FAIL; const CVolume *volume = 0; if (_volumes.Size() == 1) @@ -227,14 +202,13 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt for (UInt32 i = 0; i < numItems; i++) { - Int32 newData; - Int32 newProperties; + Int32 newData, newProps; UInt32 indexInArchive; if (!updateCallback) return E_FAIL; - RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProperties, &indexInArchive)); + RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive)); CUpdateItem ui; - ui.NewProperties = IntToBool(newProperties); + ui.NewProps = IntToBool(newProps); ui.NewData = IntToBool(newData); ui.IndexInArchive = indexInArchive; ui.IndexInClient = i; @@ -243,6 +217,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (ui.IndexInArchive != -1) { + if (db == 0 || ui.IndexInArchive >= db->Files.Size()) + return E_INVALIDARG; const CFileItem &fi = db->Files[ui.IndexInArchive]; ui.Name = fi.Name; ui.IsDir = fi.IsDir; @@ -254,7 +230,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime); } - if (ui.NewProperties) + if (ui.NewProps) { bool nameIsDefined; bool folderStatusIsDefined; @@ -350,7 +326,20 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt headerMethod.NumThreads = 1; #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 @@ -365,8 +354,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt encryptHeaders = _passwordIsDefined; #endif compressMainHeader = true; - if(encryptHeaders) - RINOK(SetPassword(headerMethod, updateCallback)); + if (encryptHeaders) + { + headerMethod.PasswordIsDefined = methodMode.PasswordIsDefined; + headerMethod.Password = methodMode.Password; + } } if (numItems < 2) @@ -391,6 +383,10 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt COutArchive archive; CArchiveDatabase newDatabase; + + CMyComPtr<ICryptoGetTextPassword> getPassword; + updateCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getPassword); + HRESULT res = Update( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL @@ -401,7 +397,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt db, #endif updateItems, - archive, newDatabase, outStream, updateCallback, options); + archive, newDatabase, outStream, updateCallback, options + #ifndef _NO_CRYPTO + , getPassword + #endif + ); RINOK(res); diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp index ab78eeae..f1458e0c 100755 --- a/CPP/7zip/Archive/7z/7zIn.cpp +++ b/CPP/7zip/Archive/7z/7zIn.cpp @@ -2,11 +2,8 @@ #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/StreamUtils.h" @@ -198,16 +195,16 @@ void CInByte2::ReadBytes(Byte *data, size_t size) data[i] = _buffer[_pos++]; } -void CInByte2::SkeepData(UInt64 size) +void CInByte2::SkipData(UInt64 size) { if (size > _size - _pos) ThrowEndOfData(); _pos += (size_t)size; } -void CInByte2::SkeepData() +void CInByte2::SkipData() { - SkeepData(ReadNumber()); + SkipData(ReadNumber()); } UInt64 CInByte2::ReadNumber() @@ -363,7 +360,7 @@ void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) { if (ReadID() == NID::kEnd) break; - SkeepData(); + SkipData(); } } @@ -456,7 +453,7 @@ void CInArchive::WaitAttribute(UInt64 attribute) return; if (type == NID::kEnd) ThrowIncorrect(); - SkeepData(); + SkipData(); } } @@ -502,7 +499,7 @@ void CInArchive::ReadPackInfo( ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs); continue; } - SkeepData(); + SkipData(); } if (packCRCsDefined.IsEmpty()) { @@ -563,7 +560,7 @@ void CInArchive::ReadUnpackInfo( } continue; } - SkeepData(); + SkipData(); } } @@ -590,7 +587,7 @@ void CInArchive::ReadSubStreamsInfo( break; if (type == NID::kEnd) break; - SkeepData(); + SkipData(); } if (numUnpackStreamsInFolders.IsEmpty()) @@ -665,7 +662,7 @@ void CInArchive::ReadSubStreamsInfo( return; } else - SkeepData(); + SkipData(); type = ReadID(); } } @@ -1006,7 +1003,7 @@ HRESULT CInArchive::ReadHeader( db.ArchiveInfo.FileInfoPopIDs.Add(type); } else - SkeepData(size); + SkipData(size); bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 || db.ArchiveInfo.Version.Minor > 2); if (checkRecordsSize && _inByteBack->_pos - ppp != size) diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h index 09c51105..971f27b2 100755 --- a/CPP/7zip/Archive/7z/7zIn.h +++ b/CPP/7zip/Archive/7z/7zIn.h @@ -110,8 +110,8 @@ public: } Byte ReadByte(); void ReadBytes(Byte *data, size_t size); - void SkeepData(UInt64 size); - void SkeepData(); + void SkipData(UInt64 size); + void SkipData(); UInt64 ReadNumber(); CNum ReadNum(); UInt32 ReadUInt32(); @@ -162,8 +162,8 @@ private: UInt64 ReadID() { return _inByteBack->ReadNumber(); } UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); } UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); } - void SkeepData(UInt64 size) { _inByteBack->SkeepData(size); } - void SkeepData() { _inByteBack->SkeepData(); } + void SkipData(UInt64 size) { _inByteBack->SkipData(size); } + void SkipData() { _inByteBack->SkipData(); } void WaitAttribute(UInt64 attribute); void ReadArchiveProperties(CInArchiveInfo &archiveInfo); diff --git a/CPP/7zip/Archive/7z/7zOut.cpp b/CPP/7zip/Archive/7z/7zOut.cpp index 7ac3c18c..e897680e 100755 --- a/CPP/7zip/Archive/7z/7zOut.cpp +++ b/CPP/7zip/Archive/7z/7zOut.cpp @@ -2,16 +2,14 @@ #include "StdAfx.h" +#include "../../../../C/7zCrc.h" + #include "../../../Common/AutoPtr.h" + #include "../../Common/StreamObjects.h" #include "7zOut.h" -extern "C" -{ -#include "../../../../C/7zCrc.h" -} - static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size) { while (size > 0) @@ -141,7 +139,7 @@ void COutArchive::Close() Stream.Release(); } -HRESULT COutArchive::SkeepPrefixArchiveHeader() +HRESULT COutArchive::SkipPrefixArchiveHeader() { #ifdef _7Z_VOL if (_endMarker) diff --git a/CPP/7zip/Archive/7z/7zOut.h b/CPP/7zip/Archive/7z/7zOut.h index bdd84abc..9d8ef308 100755 --- a/CPP/7zip/Archive/7z/7zOut.h +++ b/CPP/7zip/Archive/7z/7zOut.h @@ -1,12 +1,12 @@ -// 7z/Out.h +// 7zOut.h #ifndef __7Z_OUT_H #define __7Z_OUT_H -#include "7zHeader.h" -#include "7zItem.h" #include "7zCompressionMode.h" #include "7zEncode.h" +#include "7zHeader.h" +#include "7zItem.h" #include "../../Common/OutBuffer.h" @@ -137,7 +137,7 @@ public: CMyComPtr<ISequentialOutStream> SeqStream; HRESULT Create(ISequentialOutStream *stream, bool endMarker); void Close(); - HRESULT SkeepPrefixArchiveHeader(); + HRESULT SkipPrefixArchiveHeader(); HRESULT WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS const CArchiveDatabase &db, diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp index 0285b189..9506e8f7 100755 --- a/CPP/7zip/Archive/7z/7zUpdate.cpp +++ b/CPP/7zip/Archive/7z/7zUpdate.cpp @@ -5,10 +5,14 @@ #include "../../Common/LimitedStreams.h" #include "../../Common/ProgressUtils.h" +#include "../../Common/CreateCoder.h" + #include "../../Compress/CopyCoder.h" #include "../Common/ItemNameUtils.h" +#include "../Common/OutStreamWithCRC.h" +#include "7zDecode.h" #include "7zEncode.h" #include "7zFolderInStream.h" #include "7zHandler.h" @@ -18,6 +22,11 @@ namespace NArchive { namespace N7z { +static const UInt64 k_LZMA = 0x030101; +static const UInt64 k_BCJ = 0x03030103; +static const UInt64 k_BCJ2 = 0x0303011B; +static const UInt64 k_AES = 0x06F10701; + static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2"; static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20; static const UInt32 kAlgorithmForBCJ2_LZMA = 1; @@ -64,27 +73,29 @@ UString CUpdateItem::GetExtension() const #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } +#define RINOZ_COMP(a, b) RINOZ(MyCompare(a, b)) + static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2) { size_t c1 = a1.GetCapacity(); size_t c2 = a2.GetCapacity(); - RINOZ(MyCompare(c1, c2)); + RINOZ_COMP(c1, c2); for (size_t i = 0; i < c1; i++) - RINOZ(MyCompare(a1[i], a2[i])); + RINOZ_COMP(a1[i], a2[i]); return 0; } static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2) { - RINOZ(MyCompare(c1.NumInStreams, c2.NumInStreams)); - RINOZ(MyCompare(c1.NumOutStreams, c2.NumOutStreams)); - RINOZ(MyCompare(c1.MethodID, c2.MethodID)); + RINOZ_COMP(c1.NumInStreams, c2.NumInStreams); + RINOZ_COMP(c1.NumOutStreams, c2.NumOutStreams); + RINOZ_COMP(c1.MethodID, c2.MethodID); return CompareBuffers(c1.Props, c2.Props); } static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2) { - RINOZ(MyCompare(b1.InIndex, b2.InIndex)); + RINOZ_COMP(b1.InIndex, b2.InIndex); return MyCompare(b1.OutIndex, b2.OutIndex); } @@ -92,39 +103,52 @@ static int CompareFolders(const CFolder &f1, const CFolder &f2) { int s1 = f1.Coders.Size(); int s2 = f2.Coders.Size(); - RINOZ(MyCompare(s1, s2)); + RINOZ_COMP(s1, s2); int i; for (i = 0; i < s1; i++) RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i])); s1 = f1.BindPairs.Size(); s2 = f2.BindPairs.Size(); - RINOZ(MyCompare(s1, s2)); + RINOZ_COMP(s1, s2); for (i = 0; i < s1; i++) RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i])); return 0; } +/* static int CompareFiles(const CFileItem &f1, const CFileItem &f2) { return MyStringCompareNoCase(f1.Name, f2.Name); } +*/ + +const struct CFolderRepack +{ + int FolderIndex; + int Group; + CNum NumCopyFiles; +}; -static int CompareFolderRefs(const int *p1, const int *p2, void *param) +static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void *param) { - int i1 = *p1; - int i2 = *p2; + RINOZ_COMP(p1->Group, p2->Group); + int i1 = p1->FolderIndex; + int i2 = p2->FolderIndex; const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)param; RINOZ(CompareFolders( db.Folders[i1], db.Folders[i2])); - RINOZ(MyCompare( + return MyCompare(i1, i2); + /* + RINOZ_COMP( db.NumUnpackStreamsVector[i1], - db.NumUnpackStreamsVector[i2])); + db.NumUnpackStreamsVector[i2]); if (db.NumUnpackStreamsVector[i1] == 0) return 0; return CompareFiles( db.Files[db.FolderStartFileIndex[i1]], db.Files[db.FolderStartFileIndex[i2]]); + */ } //////////////////////////////////////////////////////////// @@ -277,20 +301,19 @@ static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *para bool sortByType = *(bool *)param; if (sortByType) { - RINOZ(MyCompare(a1.ExtensionIndex, a2.ExtensionIndex)) + RINOZ_COMP(a1.ExtensionIndex, a2.ExtensionIndex); RINOZ(MyStringCompareNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.ExtensionPos)); RINOZ(MyStringCompareNoCase(u1.Name + a1.NamePos, u2.Name + a2.NamePos)); if (!u1.MTimeDefined && u2.MTimeDefined) return 1; if (u1.MTimeDefined && !u2.MTimeDefined) return -1; - if (u1.MTimeDefined && u2.MTimeDefined) RINOZ(MyCompare(u1.MTime, u2.MTime)); - RINOZ(MyCompare(u1.Size, u2.Size)) + if (u1.MTimeDefined && u2.MTimeDefined) RINOZ_COMP(u1.MTime, u2.MTime); + RINOZ_COMP(u1.Size, u2.Size); } return MyStringCompareNoCase(u1.Name, u2.Name); } struct CSolidGroup { - CCompressionMethodMode Method; CRecordVector<UInt32> Indices; }; @@ -303,7 +326,7 @@ static wchar_t *g_ExeExts[] = L"sys" }; -static bool IsExeFile(const UString &ext) +static bool IsExeExt(const UString &ext) { for (int i = 0; i < sizeof(g_ExeExts) / sizeof(g_ExeExts[0]); i++) if (ext.CompareNoCase(g_ExeExts[i]) == 0) @@ -311,31 +334,23 @@ static bool IsExeFile(const UString &ext) return false; } -static const UInt64 k_LZMA = 0x030101; -static const UInt64 k_BCJ = 0x03030103; -static const UInt64 k_BCJ2 = 0x0303011B; - -static bool GetMethodFull(UInt64 methodID, - UInt32 numInStreams, CMethodFull &methodResult) +static void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult) { methodResult.Id = methodID; methodResult.NumInStreams = numInStreams; methodResult.NumOutStreams = 1; - return true; } -static bool MakeExeMethod(const CCompressionMethodMode &method, +static void MakeExeMethod(const CCompressionMethodMode &method, bool bcj2Filter, CCompressionMethodMode &exeMethod) { exeMethod = method; if (bcj2Filter) { CMethodFull methodFull; - if (!GetMethodFull(k_BCJ2, 4, methodFull)) - return false; + GetMethodFull(k_BCJ2, 4, methodFull); exeMethod.Methods.Insert(0, methodFull); - if (!GetMethodFull(k_LZMA, 1, methodFull)) - return false; + GetMethodFull(k_LZMA, 1, methodFull); { CProp prop; prop.Id = NCoderPropID::kAlgorithm; @@ -383,8 +398,7 @@ static bool MakeExeMethod(const CCompressionMethodMode &method, else { CMethodFull methodFull; - if (!GetMethodFull(k_BCJ, 1, methodFull)) - return false; + GetMethodFull(k_BCJ, 1, methodFull); exeMethod.Methods.Insert(0, methodFull); CBind bind; bind.OutCoder = 0; @@ -393,55 +407,6 @@ static bool MakeExeMethod(const CCompressionMethodMode &method, bind.OutStream = 0; exeMethod.Binds.Add(bind); } - return true; -} - -static void SplitFilesToGroups( - const CCompressionMethodMode &method, - bool useFilters, bool maxFilter, - const CObjectVector<CUpdateItem> &updateItems, - CObjectVector<CSolidGroup> &groups) -{ - if (method.Methods.Size() != 1 || method.Binds.Size() != 0) - useFilters = false; - groups.Clear(); - groups.Add(CSolidGroup()); - groups.Add(CSolidGroup()); - CSolidGroup &generalGroup = groups[0]; - CSolidGroup &exeGroup = groups[1]; - generalGroup.Method = method; - int i; - for (i = 0; i < updateItems.Size(); i++) - { - const CUpdateItem &ui = updateItems[i]; - if (!ui.NewData) - continue; - if (!ui.HasStream()) - continue; - if (useFilters) - { - const UString name = ui.Name; - int dotPos = name.ReverseFind(L'.'); - if (dotPos >= 0) - { - UString ext = name.Mid(dotPos + 1); - if (IsExeFile(ext)) - { - exeGroup.Indices.Add(i); - continue; - } - } - } - generalGroup.Indices.Add(i); - } - if (exeGroup.Indices.Size() > 0) - if (!MakeExeMethod(method, maxFilter, exeGroup.Method)) - exeGroup.Method = method; - for (i = 0; i < groups.Size();) - if (groups[i].Indices.Size() == 0) - groups.Delete(i); - else - i++; } static void FromUpdateItemToFileItem(const CUpdateItem &ui, @@ -462,7 +427,250 @@ static void FromUpdateItemToFileItem(const CUpdateItem &ui, file.HasStream = ui.HasStream(); } -static HRESULT Update2( +class CFolderOutStream2: + public ISequentialOutStream, + public CMyUnknownImp +{ + COutStreamWithCRC *_crcStreamSpec; + CMyComPtr<ISequentialOutStream> _crcStream; + const CArchiveDatabaseEx *_db; + const CBoolVector *_extractStatuses; + CMyComPtr<ISequentialOutStream> _outStream; + UInt32 _startIndex; + int _currentIndex; + bool _fileIsOpen; + UInt64 _rem; + + void OpenFile(); + void CloseFile(); + HRESULT CloseFileAndSetResult(); + HRESULT ProcessEmptyFiles(); +public: + MY_UNKNOWN_IMP + + CFolderOutStream2() + { + _crcStreamSpec = new COutStreamWithCRC; + _crcStream = _crcStreamSpec; + } + + HRESULT Init(const CArchiveDatabaseEx *db, UInt32 startIndex, + const CBoolVector *extractStatuses, ISequentialOutStream *outStream); + void ReleaseOutStream(); + HRESULT CheckFinishedState() const { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; } + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +HRESULT CFolderOutStream2::Init(const CArchiveDatabaseEx *db, UInt32 startIndex, + const CBoolVector *extractStatuses, ISequentialOutStream *outStream) +{ + _db = db; + _startIndex = startIndex; + _extractStatuses = extractStatuses; + _outStream = outStream; + + _currentIndex = 0; + _fileIsOpen = false; + return ProcessEmptyFiles(); +} + +void CFolderOutStream2::ReleaseOutStream() +{ + _outStream.Release(); + _crcStreamSpec->ReleaseStream(); +} + +void CFolderOutStream2::OpenFile() +{ + _crcStreamSpec->SetStream((*_extractStatuses)[_currentIndex] ? _outStream : NULL); + _crcStreamSpec->Init(true); + _fileIsOpen = true; + _rem = _db->Files[_startIndex + _currentIndex].Size; +} + +void CFolderOutStream2::CloseFile() +{ + _crcStreamSpec->ReleaseStream(); + _fileIsOpen = false; + _currentIndex++; +} + +HRESULT CFolderOutStream2::CloseFileAndSetResult() +{ + const CFileItem &file = _db->Files[_startIndex + _currentIndex]; + CloseFile(); + return (file.IsDir || !file.CrcDefined || file.Crc == _crcStreamSpec->GetCRC()) ? S_OK: S_FALSE; +} + +HRESULT CFolderOutStream2::ProcessEmptyFiles() +{ + while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0) + { + OpenFile(); + RINOK(CloseFileAndSetResult()); + } + return S_OK; +} + +STDMETHODIMP CFolderOutStream2::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + while (size != 0) + { + if (_fileIsOpen) + { + UInt32 cur = size < _rem ? size : (UInt32)_rem; + RINOK(_crcStream->Write(data, cur, &cur)); + if (cur == 0) + break; + data = (const Byte *)data + cur; + size -= cur; + _rem -= cur; + if (processedSize != NULL) + *processedSize += cur; + if (_rem == 0) + { + RINOK(CloseFileAndSetResult()); + RINOK(ProcessEmptyFiles()); + continue; + } + } + else + { + RINOK(ProcessEmptyFiles()); + if (_currentIndex == _extractStatuses->Size()) + { + // we don't support partial extracting + return E_FAIL; + } + OpenFile(); + } + } + return S_OK; +} + +class CThreadDecoder: public CVirtThread +{ +public: + HRESULT Result; + CMyComPtr<IInStream> InStream; + + CFolderOutStream2 *FosSpec; + CMyComPtr<ISequentialOutStream> Fos; + + UInt64 StartPos; + const UInt64 *PackSizes; + const CFolder *Folder; + #ifndef _NO_CRYPTO + CMyComPtr<ICryptoGetTextPassword> GetTextPassword; + #endif + + DECL_EXTERNAL_CODECS_VARS + CDecoder Decoder; + + #ifdef COMPRESS_MT + bool MtMode; + UInt32 NumThreads; + #endif + + CThreadDecoder(): + Decoder(true) + { + #ifdef COMPRESS_MT + MtMode = false; + NumThreads = 1; + #endif + FosSpec = new CFolderOutStream2; + Fos = FosSpec; + Result = E_FAIL; + } + virtual void Execute(); +}; + +void CThreadDecoder::Execute() +{ + try + { + #ifndef _NO_CRYPTO + bool passwordIsDefined; + #endif + Result = Decoder.Decode( + EXTERNAL_CODECS_VARS + InStream, + StartPos, + PackSizes, + *Folder, + Fos, + NULL + #ifndef _NO_CRYPTO + , GetTextPassword, passwordIsDefined + #endif + #ifdef COMPRESS_MT + , MtMode, NumThreads + #endif + ); + } + catch(...) + { + Result = E_FAIL; + } + if (Result == S_OK) + Result = FosSpec->CheckFinishedState(); + FosSpec->ReleaseOutStream(); +} + +bool static Is86FilteredFolder(const CFolder &f) +{ + for (int i = 0; i < f.Coders.Size(); i++) + { + CMethodId m = f.Coders[i].MethodID; + if (m == k_BCJ || m == k_BCJ2) + return true; + } + return false; +} + +bool static IsEncryptedFolder(const CFolder &f) +{ + for (int i = 0; i < f.Coders.Size(); i++) + { + CMethodId m = f.Coders[i].MethodID; + if (m == k_AES) + return true; + } + return false; +} + +#ifndef _NO_CRYPTO + +class CCryptoGetTextPassword: + public ICryptoGetTextPassword, + public CMyUnknownImp +{ +public: + UString Password; + + MY_UNKNOWN_IMP + STDMETHOD(CryptoGetTextPassword)(BSTR *password); +}; + +STDMETHODIMP CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password) +{ + return StringToBstr(Password, password); +} + +#endif + +static const int kNumGroupsMax = 4; + +static bool Is86Group(int group) { return (group & 1) != 0; } +static bool IsEncryptedGroup(int group) { return (group & 2) != 0; } +static int GetGroupIndex(bool encrypted, int bcjFiltered) + { return (encrypted ? 2 : 0) + (bcjFiltered ? 1 : 0); } + +HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *db, @@ -471,7 +679,11 @@ static HRESULT Update2( CArchiveDatabase &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, - const CUpdateOptions &options) + const CUpdateOptions &options + #ifndef _NO_CRYPTO + , ICryptoGetTextPassword *getDecoderPassword + #endif + ) { UInt64 numSolidFiles = options.NumSolidFiles; if (numSolidFiles == 0) @@ -490,153 +702,305 @@ static HRESULT Update2( } CRecordVector<int> fileIndexToUpdateIndexMap; + CRecordVector<CFolderRepack> folderRefs; + UInt64 complexity = 0; + UInt64 inSizeForReduce2 = 0; + bool needEncryptedRepack = false; if (db != 0) { fileIndexToUpdateIndexMap.Reserve(db->Files.Size()); - for (int i = 0; i < db->Files.Size(); i++) + int i; + for (i = 0; i < db->Files.Size(); i++) fileIndexToUpdateIndexMap.Add(-1); - } - int i; - for(i = 0; i < updateItems.Size(); i++) - { - int index = updateItems[i].IndexInArchive; - if (index != -1) - fileIndexToUpdateIndexMap[index] = i; - } - CRecordVector<int> folderRefs; - if (db != 0) - { - for(i = 0; i < db->Folders.Size(); i++) + for (i = 0; i < updateItems.Size(); i++) + { + int index = updateItems[i].IndexInArchive; + if (index != -1) + fileIndexToUpdateIndexMap[index] = i; + } + + for (i = 0; i < db->Folders.Size(); i++) { CNum indexInFolder = 0; CNum numCopyItems = 0; CNum numUnpackStreams = db->NumUnpackStreamsVector[i]; - for (CNum fileIndex = db->FolderStartFileIndex[i]; - indexInFolder < numUnpackStreams; fileIndex++) + UInt64 repackSize = 0; + for (CNum fi = db->FolderStartFileIndex[i]; indexInFolder < numUnpackStreams; fi++) { - if (db->Files[fileIndex].HasStream) + const CFileItem &file = db->Files[fi]; + if (file.HasStream) { indexInFolder++; - int updateIndex = fileIndexToUpdateIndexMap[fileIndex]; - if (updateIndex >= 0) - if (!updateItems[updateIndex].NewData) - numCopyItems++; + int updateIndex = fileIndexToUpdateIndexMap[fi]; + if (updateIndex >= 0 && !updateItems[updateIndex].NewData) + { + numCopyItems++; + repackSize += file.Size; + } } } - if (numCopyItems != numUnpackStreams && numCopyItems != 0) - return E_NOTIMPL; // It needs repacking !!! - if (numCopyItems > 0) - folderRefs.Add(i); + + if (numCopyItems == 0) + continue; + + CFolderRepack rep; + rep.FolderIndex = i; + rep.NumCopyFiles = numCopyItems; + const CFolder &f = db->Folders[i]; + bool isEncrypted = IsEncryptedFolder(f); + rep.Group = GetGroupIndex(isEncrypted, Is86FilteredFolder(f)); + folderRefs.Add(rep); + if (numCopyItems == numUnpackStreams) + complexity += db->GetFolderFullPackSize(i); + else + { + complexity += repackSize; + if (repackSize > inSizeForReduce2) + inSizeForReduce2 = repackSize; + if (isEncrypted) + needEncryptedRepack = true; + } } - folderRefs.Sort(CompareFolderRefs, (void *)db); + folderRefs.Sort(CompareFolderRepacks, (void *)db); } - //////////////////////////// - - RINOK(archive.Create(seqOutStream, false)); - RINOK(archive.SkeepPrefixArchiveHeader()); - UInt64 complexity = 0; - for(i = 0; i < folderRefs.Size(); i++) - complexity += db->GetFolderFullPackSize(folderRefs[i]); UInt64 inSizeForReduce = 0; - for(i = 0; i < updateItems.Size(); i++) + int i; + for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (ui.NewData) { complexity += ui.Size; - if (numSolidFiles == 1) - { - if (ui.Size > inSizeForReduce) - inSizeForReduce = ui.Size; - } - else + if (numSolidFiles != 1) inSizeForReduce += ui.Size; + else if (ui.Size > inSizeForReduce) + inSizeForReduce = ui.Size; } } - RINOK(updateCallback->SetTotal(complexity)); - complexity = 0; - RINOK(updateCallback->SetCompleted(&complexity)); + if (inSizeForReduce2 > inSizeForReduce) + inSizeForReduce = inSizeForReduce2; + + const UInt32 kMinReduceSize = (1 << 16); + if (inSizeForReduce < kMinReduceSize) + inSizeForReduce = kMinReduceSize; + + RINOK(updateCallback->SetTotal(complexity)); CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(updateCallback, true); - ///////////////////////////////////////// - // Write Copy Items + CThreadDecoder threadDecoder; + if (!folderRefs.IsEmpty()) + { + #ifdef EXTERNAL_CODECS + threadDecoder._codecsInfo = codecsInfo; + threadDecoder._externalCodecs = *externalCodecs; + #endif + RINOK(threadDecoder.Create()); + } + + CObjectVector<CSolidGroup> groups; + for (i = 0; i < kNumGroupsMax; i++) + groups.Add(CSolidGroup()); - for(i = 0; i < folderRefs.Size(); i++) { - int folderIndex = folderRefs[i]; - - lps->ProgressOffset = complexity; - UInt64 packSize = db->GetFolderFullPackSize(folderIndex); - RINOK(WriteRange(inStream, archive.SeqStream, - db->GetFolderStreamPos(folderIndex, 0), packSize, progress)); - complexity += packSize; - - const CFolder &folder = db->Folders[folderIndex]; - CNum startIndex = db->FolderStartPackStreamIndex[folderIndex]; - for (int j = 0; j < folder.PackStreams.Size(); j++) + // ---------- Split files to 2 groups ---------- + + bool useFilters = options.UseFilters; + const CCompressionMethodMode &method = *options.Method; + if (method.Methods.Size() != 1 || method.Binds.Size() != 0) + useFilters = false; + for (i = 0; i < updateItems.Size(); i++) { - newDatabase.PackSizes.Add(db->PackSizes[startIndex + j]); - // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]); - // newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]); + const CUpdateItem &ui = updateItems[i]; + if (!ui.NewData || !ui.HasStream()) + continue; + bool filteredGroup = false; + if (useFilters) + { + int dotPos = ui.Name.ReverseFind(L'.'); + if (dotPos >= 0) + filteredGroup = IsExeExt(ui.Name.Mid(dotPos + 1)); + } + groups[GetGroupIndex(method.PasswordIsDefined, filteredGroup)].Indices.Add(i); } - newDatabase.Folders.Add(folder); + } - CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; - newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams); + #ifndef _NO_CRYPTO - CNum indexInFolder = 0; - for (CNum fi = db->FolderStartFileIndex[folderIndex]; - indexInFolder < numUnpackStreams; fi++) + CCryptoGetTextPassword *getPasswordSpec = NULL; + if (needEncryptedRepack) + { + getPasswordSpec = new CCryptoGetTextPassword; + threadDecoder.GetTextPassword = getPasswordSpec; + + if (options.Method->PasswordIsDefined) + getPasswordSpec->Password = options.Method->Password; + else { - CFileItem file; - CFileItem2 file2; - db->GetFile(fi, file, file2); - if (file.HasStream) - { - indexInFolder++; - int updateIndex = fileIndexToUpdateIndexMap[fi]; - if (updateIndex >= 0) - { - const CUpdateItem &ui = updateItems[updateIndex]; - if (ui.NewProperties) - { - CFileItem uf; - FromUpdateItemToFileItem(ui, uf, file2); - uf.Size = file.Size; - uf.Crc = file.Crc; - uf.CrcDefined = file.CrcDefined; - uf.HasStream = file.HasStream; - file = uf; - } - } - newDatabase.AddFile(file, file2); - } + if (!getDecoderPassword) + return E_NOTIMPL; + CMyComBSTR password; + RINOK(getDecoderPassword->CryptoGetTextPassword(&password)); + getPasswordSpec->Password = password; } } - folderRefs.ClearAndFree(); - fileIndexToUpdateIndexMap.ClearAndFree(); + #endif - ///////////////////////////////////////// - // Compress New Files + // ---------- Compress ---------- - CObjectVector<CSolidGroup> groups; - SplitFilesToGroups(*options.Method, options.UseFilters, options.MaxFilter, - updateItems, groups); + RINOK(archive.Create(seqOutStream, false)); + RINOK(archive.SkipPrefixArchiveHeader()); - const UInt32 kMinReduceSize = (1 << 16); - if (inSizeForReduce < kMinReduceSize) - inSizeForReduce = kMinReduceSize; + int folderRefIndex = 0; + lps->ProgressOffset = 0; - for (int groupIndex = 0; groupIndex < groups.Size(); groupIndex++) + for (int groupIndex = 0; groupIndex < kNumGroupsMax; groupIndex++) { const CSolidGroup &group = groups[groupIndex]; + + CCompressionMethodMode method; + if (Is86Group(groupIndex)) + MakeExeMethod(*options.Method, options.MaxFilter, method); + else + method = *options.Method; + + if (IsEncryptedGroup(groupIndex)) + { + if (!method.PasswordIsDefined) + { + #ifndef _NO_CRYPTO + if (getPasswordSpec) + method.Password = getPasswordSpec->Password; + #endif + method.PasswordIsDefined = true; + } + } + else + { + method.PasswordIsDefined = false; + method.Password.Empty(); + } + + CEncoder encoder(method); + + for (; folderRefIndex < folderRefs.Size(); folderRefIndex++) + { + const CFolderRepack &rep = folderRefs[folderRefIndex]; + if (rep.Group != groupIndex) + break; + int folderIndex = rep.FolderIndex; + + if (rep.NumCopyFiles == db->NumUnpackStreamsVector[folderIndex]) + { + UInt64 packSize = db->GetFolderFullPackSize(folderIndex); + RINOK(WriteRange(inStream, archive.SeqStream, + db->GetFolderStreamPos(folderIndex, 0), packSize, progress)); + lps->ProgressOffset += packSize; + + const CFolder &folder = db->Folders[folderIndex]; + CNum startIndex = db->FolderStartPackStreamIndex[folderIndex]; + for (int j = 0; j < folder.PackStreams.Size(); j++) + { + newDatabase.PackSizes.Add(db->PackSizes[startIndex + j]); + // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]); + // newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]); + } + newDatabase.Folders.Add(folder); + } + else + { + CStreamBinder sb; + RINOK(sb.CreateEvents()); + CMyComPtr<ISequentialOutStream> sbOutStream; + CMyComPtr<ISequentialInStream> sbInStream; + sb.CreateStreams(&sbInStream, &sbOutStream); + CBoolVector extractStatuses; + + CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; + CNum indexInFolder = 0; + + for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) + { + bool needExtract = false; + if (db->Files[fi].HasStream) + { + indexInFolder++; + int updateIndex = fileIndexToUpdateIndexMap[fi]; + if (updateIndex >= 0 && !updateItems[updateIndex].NewData) + needExtract = true; + } + extractStatuses.Add(needExtract); + } + + RINOK(threadDecoder.FosSpec->Init(db, db->FolderStartFileIndex[folderIndex], &extractStatuses, sbOutStream)); + sbOutStream.Release(); + + threadDecoder.InStream = inStream; + threadDecoder.Folder = &db->Folders[folderIndex]; + threadDecoder.StartPos = db->GetFolderStreamPos(folderIndex, 0); + threadDecoder.PackSizes = &db->PackSizes[db->FolderStartPackStreamIndex[folderIndex]]; + + threadDecoder.Start(); + + int startPackIndex = newDatabase.PackSizes.Size(); + CFolder newFolder; + RINOK(encoder.Encode( + EXTERNAL_CODECS_LOC_VARS + sbInStream, NULL, &inSizeForReduce, newFolder, + archive.SeqStream, newDatabase.PackSizes, progress)); + + threadDecoder.WaitFinish(); + + RINOK(threadDecoder.Result); + + for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) + lps->OutSize += newDatabase.PackSizes[startPackIndex]; + lps->InSize += newFolder.GetUnpackSize(); + + newDatabase.Folders.Add(newFolder); + } + + newDatabase.NumUnpackStreamsVector.Add(rep.NumCopyFiles); + + CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; + + CNum indexInFolder = 0; + for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) + { + CFileItem file; + CFileItem2 file2; + db->GetFile(fi, file, file2); + if (file.HasStream) + { + indexInFolder++; + int updateIndex = fileIndexToUpdateIndexMap[fi]; + if (updateIndex >= 0) + { + const CUpdateItem &ui = updateItems[updateIndex]; + if (ui.NewData) + continue; + if (ui.NewProps) + { + CFileItem uf; + FromUpdateItemToFileItem(ui, uf, file2); + uf.Size = file.Size; + uf.Crc = file.Crc; + uf.CrcDefined = file.CrcDefined; + uf.HasStream = file.HasStream; + file = uf; + } + newDatabase.AddFile(file, file2); + } + } + } + } + int numFiles = group.Indices.Size(); if (numFiles == 0) continue; @@ -657,7 +1021,7 @@ static HRESULT Update2( /* const CUpdateItem &ui = updateItems[index]; CFileItem file; - if (ui.NewProperties) + if (ui.NewProps) FromUpdateItemToFileItem(ui, file); else file = db.Files[ui.IndexInArchive]; @@ -667,8 +1031,6 @@ static HRESULT Update2( */ } - CEncoder encoder(group.Method); - for (i = 0; i < numFiles;) { UInt64 totalSize = 0; @@ -710,7 +1072,7 @@ static HRESULT Update2( lps->OutSize += newDatabase.PackSizes[startPackIndex]; lps->InSize += folderItem.GetUnpackSize(); - // for() + // for () // newDatabase.PackCRCsDefined.Add(false); // newDatabase.PackCRCs.Add(0); @@ -722,7 +1084,7 @@ static HRESULT Update2( const CUpdateItem &ui = updateItems[indices[i + subIndex]]; CFileItem file; CFileItem2 file2; - if (ui.NewProperties) + if (ui.NewProps) FromUpdateItemToFileItem(ui, file, file2); else db->GetFile(ui.IndexInArchive, file, file2); @@ -761,14 +1123,20 @@ static HRESULT Update2( } } + if (folderRefIndex != folderRefs.Size()) + return E_FAIL; + + /* + folderRefs.ClearAndFree(); + fileIndexToUpdateIndexMap.ClearAndFree(); groups.ClearAndFree(); + */ { - ///////////////////////////////////////// - // Write Empty Files & Folders + // ---------- Write Folders & Empty Files ---------- CRecordVector<int> emptyRefs; - for(i = 0; i < updateItems.Size(); i++) + for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (ui.NewData) @@ -776,10 +1144,8 @@ static HRESULT Update2( if (ui.HasStream()) continue; } - else - if (ui.IndexInArchive != -1) - if (db->Files[ui.IndexInArchive].HasStream) - continue; + else if (ui.IndexInArchive != -1 && db->Files[ui.IndexInArchive].HasStream) + continue; emptyRefs.Add(i); } emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems); @@ -788,7 +1154,7 @@ static HRESULT Update2( const CUpdateItem &ui = updateItems[emptyRefs[i]]; CFileItem file; CFileItem2 file2; - if (ui.NewProperties) + if (ui.NewProps) FromUpdateItemToFileItem(ui, file, file2); else db->GetFile(ui.IndexInArchive, file, file2); @@ -800,21 +1166,4 @@ static HRESULT Update2( return S_OK; } -HRESULT Update( - DECL_EXTERNAL_CODECS_LOC_VARS - IInStream *inStream, - const CArchiveDatabaseEx *db, - const CObjectVector<CUpdateItem> &updateItems, - COutArchive &archive, - CArchiveDatabase &newDatabase, - ISequentialOutStream *seqOutStream, - IArchiveUpdateCallback *updateCallback, - const CUpdateOptions &options) -{ - return Update2( - EXTERNAL_CODECS_LOC_VARS - inStream, db, updateItems, - archive, newDatabase, seqOutStream, updateCallback, options); -} - }} diff --git a/CPP/7zip/Archive/7z/7zUpdate.h b/CPP/7zip/Archive/7z/7zUpdate.h index bcc7cef7..31e36224 100755 --- a/CPP/7zip/Archive/7z/7zUpdate.h +++ b/CPP/7zip/Archive/7z/7zUpdate.h @@ -3,9 +3,9 @@ #ifndef __7Z_UPDATE_H #define __7Z_UPDATE_H +#include "7zCompressionMode.h" #include "7zIn.h" #include "7zOut.h" -#include "7zCompressionMode.h" #include "../IArchive.h" @@ -27,7 +27,7 @@ struct CUpdateItem UInt32 Attrib; bool NewData; - bool NewProperties; + bool NewProps; bool IsAnti; bool IsDir; @@ -78,7 +78,11 @@ HRESULT Update( CArchiveDatabase &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, - const CUpdateOptions &options); + const CUpdateOptions &options + #ifndef _NO_CRYPTO + , ICryptoGetTextPassword *getDecoderPassword + #endif + ); }} #endif diff --git a/CPP/7zip/Archive/7z/makefile b/CPP/7zip/Archive/7z/makefile index 1a72da0e..4489f290 100755 --- a/CPP/7zip/Archive/7z/makefile +++ b/CPP/7zip/Archive/7z/makefile @@ -104,7 +104,7 @@ $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../Common/$(*B).cpp $(COMPL) -$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp +$O\CopyCoder.obj: ../../Compress/$(*B).cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) diff --git a/CPP/7zip/Archive/ArchiveExports.cpp b/CPP/7zip/Archive/ArchiveExports.cpp index ae388d67..f7bc9c69 100755 --- a/CPP/7zip/Archive/ArchiveExports.cpp +++ b/CPP/7zip/Archive/ArchiveExports.cpp @@ -3,15 +3,12 @@ #include "StdAfx.h" #include "../../Common/ComTry.h" -#include "../../Common/Types.h" + #include "../../Windows/PropVariant.h" -#include "../Common/RegisterArc.h" -#include "IArchive.h" -#include "../ICoder.h" -#include "../IPassword.h" +#include "../Common/RegisterArc.h" -static const unsigned int kNumArcsMax = 32; +static const unsigned int kNumArcsMax = 48; static unsigned int g_NumArcs = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) diff --git a/CPP/7zip/Archive/ArjHandler.cpp b/CPP/7zip/Archive/ArjHandler.cpp index c40cbbcd..66ad1677 100755 --- a/CPP/7zip/Archive/ArjHandler.cpp +++ b/CPP/7zip/Archive/ArjHandler.cpp @@ -2,14 +2,14 @@ #include "StdAfx.h" +#include "../../../C/CpuArch.h" + #include "Common/ComTry.h" #include "Common/StringConvert.h" #include "Windows/PropVariant.h" #include "Windows/Time.h" -#include "../../../C/CpuArch.h" - #include "../Common/LimitedStreams.h" #include "../Common/ProgressUtils.h" #include "../Common/RegisterArc.h" @@ -180,6 +180,7 @@ struct CItem UInt32 PackSize; UInt32 Size; UInt32 FileCRC; + UInt32 SplitPos; Byte Version; Byte ExtractVersion; @@ -197,6 +198,8 @@ struct CItem bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kGarbled) != 0; } 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 winAtrributes; @@ -240,6 +243,10 @@ HRESULT CItem::Parse(const Byte *p, unsigned size) // FirstChapter = p[28]; // FirstChapter = p[29]; + SplitPos = 0; + if (IsSplitBefore() && firstHeaderSize >= 34) + SplitPos = Get32(p + 30); + unsigned pos = firstHeaderSize; unsigned size1 = size - pos; RINOK(ReadString(p + pos, size1, Name)); @@ -270,7 +277,7 @@ class CInArchive HRESULT ReadBlock(bool &filled); HRESULT ReadSignatureAndBlock(bool &filled); - HRESULT SkeepExtendedHeaders(); + HRESULT SkipExtendedHeaders(); HRESULT SafeReadBytes(void *data, UInt32 size); @@ -389,7 +396,7 @@ HRESULT CInArchive::ReadSignatureAndBlock(bool &filled) return ReadBlock(filled); } -HRESULT CInArchive::SkeepExtendedHeaders() +HRESULT CInArchive::SkipExtendedHeaders() { for (UInt32 i = 0;; i++) { @@ -412,7 +419,7 @@ HRESULT CInArchive::Open(const UInt64 *searchHeaderSizeLimit) if (!filled) return S_FALSE; RINOK(Header.Parse(_block, _blockSize)); - return SkeepExtendedHeaders(); + return SkipExtendedHeaders(); } HRESULT CInArchive::GetNextItem(bool &filled, CItem &item) @@ -428,7 +435,7 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItem &item) extraData = GetUi32(_block + pos); */ - RINOK(SkeepExtendedHeaders()); + RINOK(SkipExtendedHeaders()); filled = true; return S_OK; } @@ -482,8 +489,9 @@ STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidIsDir, VT_BOOL}, - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidSize, VT_UI4}, + { NULL, kpidPosition, VT_UI8}, + { NULL, kpidPackSize, VT_UI4}, { NULL, kpidMTime, VT_FILETIME}, { NULL, kpidAttrib, VT_UI4}, { NULL, kpidEncrypted, VT_BOOL}, @@ -556,6 +564,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidIsDir: prop = item.IsDir(); break; case kpidSize: prop = item.Size; 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 kpidEncrypted: prop = item.IsEncrypted(); break; case kpidCRC: prop = item.FileCRC; break; diff --git a/CPP/7zip/Archive/BZip2/BZip2Handler.cpp b/CPP/7zip/Archive/BZip2/BZip2Handler.cpp deleted file mode 100755 index 05716b62..00000000 --- a/CPP/7zip/Archive/BZip2/BZip2Handler.cpp +++ /dev/null @@ -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(¤tTotalPacked)); - - 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 - -}} diff --git a/CPP/7zip/Archive/BZip2/BZip2Handler.h b/CPP/7zip/Archive/BZip2/BZip2Handler.h deleted file mode 100755 index 5bb3360a..00000000 --- a/CPP/7zip/Archive/BZip2/BZip2Handler.h +++ /dev/null @@ -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 diff --git a/CPP/7zip/Archive/BZip2/BZip2HandlerOut.cpp b/CPP/7zip/Archive/BZip2/BZip2HandlerOut.cpp deleted file mode 100755 index 71311c32..00000000 --- a/CPP/7zip/Archive/BZip2/BZip2HandlerOut.cpp +++ /dev/null @@ -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; -} - -}} diff --git a/CPP/7zip/Archive/BZip2/BZip2Item.h b/CPP/7zip/Archive/BZip2/BZip2Item.h deleted file mode 100755 index d7508ab9..00000000 --- a/CPP/7zip/Archive/BZip2/BZip2Item.h +++ /dev/null @@ -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 - - - diff --git a/CPP/7zip/Archive/BZip2/BZip2Update.cpp b/CPP/7zip/Archive/BZip2/BZip2Update.cpp deleted file mode 100755 index 300d8844..00000000 --- a/CPP/7zip/Archive/BZip2/BZip2Update.cpp +++ /dev/null @@ -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); -} - -}} diff --git a/CPP/7zip/Archive/BZip2/BZip2Update.h b/CPP/7zip/Archive/BZip2/BZip2Update.h deleted file mode 100755 index e54a7e16..00000000 --- a/CPP/7zip/Archive/BZip2/BZip2Update.h +++ /dev/null @@ -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 diff --git a/CPP/7zip/Archive/BZip2/StdAfx.h b/CPP/7zip/Archive/BZip2/StdAfx.h deleted file mode 100755 index e7fb6986..00000000 --- a/CPP/7zip/Archive/BZip2/StdAfx.h +++ /dev/null @@ -1,8 +0,0 @@ -// StdAfx.h - -#ifndef __STDAFX_H -#define __STDAFX_H - -#include "../../../Common/MyWindows.h" - -#endif diff --git a/CPP/7zip/Archive/BZip2/bz2Register.cpp b/CPP/7zip/Archive/BZip2/bz2Register.cpp deleted file mode 100755 index 76d3d25b..00000000 --- a/CPP/7zip/Archive/BZip2/bz2Register.cpp +++ /dev/null @@ -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) diff --git a/CPP/7zip/Archive/Bz2Handler.cpp b/CPP/7zip/Archive/Bz2Handler.cpp new file mode 100755 index 00000000..9b2c4048 --- /dev/null +++ b/CPP/7zip/Archive/Bz2Handler.cpp @@ -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(¤tTotalPacked)); + 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) + +}} diff --git a/CPP/7zip/Archive/Cab/CabBlockInStream.cpp b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp index 308616b8..12c73eb5 100755 --- a/CPP/7zip/Archive/Cab/CabBlockInStream.cpp +++ b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp @@ -2,10 +2,7 @@ #include "StdAfx.h" -extern "C" -{ #include "../../../../C/Alloc.h" -} #include "Common/Defs.h" diff --git a/CPP/7zip/Archive/Cab/CabIn.cpp b/CPP/7zip/Archive/Cab/CabIn.cpp index 2b0a426b..afc0faed 100755 --- a/CPP/7zip/Archive/Cab/CabIn.cpp +++ b/CPP/7zip/Archive/Cab/CabIn.cpp @@ -57,7 +57,7 @@ void CInArchive::ReadOtherArchive(COtherArchive &oa) oa.DiskName = SafeReadName(); } -void CInArchive::Skeep(size_t size) +void CInArchive::Skip(size_t size) { while (size-- != 0) ReadByte(); @@ -104,7 +104,7 @@ HRESULT CInArchive::Open2(IInStream *stream, ai.PerFolderAreaSize = ReadByte(); ai.PerDataBlockAreaSize = ReadByte(); - Skeep(ai.PerCabinetAreaSize); + Skip(ai.PerCabinetAreaSize); } { @@ -124,7 +124,7 @@ HRESULT CInArchive::Open2(IInStream *stream, folder.CompressionTypeMajor = ReadByte(); folder.CompressionTypeMinor = ReadByte(); - Skeep(ai.PerFolderAreaSize); + Skip(ai.PerFolderAreaSize); database.Folders.Add(folder); } diff --git a/CPP/7zip/Archive/Cab/CabIn.h b/CPP/7zip/Archive/Cab/CabIn.h index 197017b9..c9cfcbdd 100755 --- a/CPP/7zip/Archive/Cab/CabIn.h +++ b/CPP/7zip/Archive/Cab/CabIn.h @@ -149,7 +149,7 @@ class CInArchive UInt16 ReadUInt16(); UInt32 ReadUInt32(); AString SafeReadName(); - void Skeep(size_t size); + void Skip(size_t size); void ReadOtherArchive(COtherArchive &oa); HRESULT Open2(IInStream *inStream, diff --git a/CPP/7zip/Archive/Chm/ChmIn.cpp b/CPP/7zip/Archive/Chm/ChmIn.cpp index 1379b1fd..cc571937 100755 --- a/CPP/7zip/Archive/Chm/ChmIn.cpp +++ b/CPP/7zip/Archive/Chm/ChmIn.cpp @@ -2,13 +2,11 @@ #include "StdAfx.h" -#include "Common/StringConvert.h" -#include "Common/MyCom.h" -#include "Common/UTFConvert.h" #include "Common/IntToString.h" -#include "Windows/Defs.h" +#include "Common/UTFConvert.h" #include "../../Common/LimitedStreams.h" + #include "ChmIn.h" namespace NArchive{ @@ -96,9 +94,8 @@ UString CMethodInfo::GetName() const if (IsLzx()) { s = L"LZX:"; - UInt32 numDictBits = LzxInfo.GetNumDictBits(); - wchar_t temp[32]; - ConvertUInt64ToString(numDictBits, temp); + wchar_t temp[16]; + ConvertUInt32ToString(LzxInfo.GetNumDictBits(), temp); s += temp; } else @@ -111,7 +108,7 @@ UString CMethodInfo::GetName() const s2 = GetGuidString(); if (ControlData.GetCapacity() > 0) { - s2 += ":"; + s2 += ':'; for (size_t i = 0; i < ControlData.GetCapacity(); i++) PrintByte(ControlData[i], s2); } @@ -141,7 +138,7 @@ UString CSectionInfo::GetMethodName() const for (int i = 0; i < Methods.Size(); i++) { if (i != 0) - s += L" "; + s += L' '; s += Methods[i].GetName(); } return s; @@ -155,7 +152,7 @@ Byte CInArchive::ReadByte() return b; } -void CInArchive::Skeep(size_t size) +void CInArchive::Skip(size_t size) { while (size-- != 0) ReadByte(); @@ -221,7 +218,7 @@ void CInArchive::ReadString(int size, AString &s) char c = (char)ReadByte(); if (c == 0) { - Skeep(size); + Skip(size); return; } s += c; @@ -236,7 +233,7 @@ void CInArchive::ReadUString(int size, UString &s) wchar_t c = ReadUInt16(); if (c == 0) { - Skeep(2 * size); + Skip(2 * size); return; } s += c; @@ -372,12 +369,12 @@ HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database) RINOK(ReadDirEntry(database)); numItems++; } - Skeep(quickrefLength - 2); + Skip(quickrefLength - 2); if (ReadUInt16() != numItems) return S_FALSE; } else - Skeep(dirChunkSize - 4); + Skip(dirChunkSize - 4); } return S_OK; } @@ -579,7 +576,7 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database) } numItems++; } - Skeep(quickrefLength - 2); + Skip(quickrefLength - 2); if (ReadUInt16() != numItems) return S_FALSE; if (numItems > numDirEntries) @@ -587,7 +584,7 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database) numDirEntries -= numItems; } else - Skeep(dirChunkSize - 4); + Skip(dirChunkSize - 4); } return numDirEntries == 0 ? S_OK : S_FALSE; } diff --git a/CPP/7zip/Archive/Chm/ChmIn.h b/CPP/7zip/Archive/Chm/ChmIn.h index 943336cb..4719a484 100755 --- a/CPP/7zip/Archive/Chm/ChmIn.h +++ b/CPP/7zip/Archive/Chm/ChmIn.h @@ -3,10 +3,12 @@ #ifndef __ARCHIVE_CHM_IN_H #define __ARCHIVE_CHM_IN_H -#include "Common/MyString.h" #include "Common/Buffer.h" +#include "Common/MyString.h" + #include "../../IStream.h" #include "../../Common/InBuffer.h" + #include "ChmHeader.h" namespace NArchive { @@ -215,7 +217,7 @@ class CInArchive Byte ReadByte(); void ReadBytes(Byte *data, UInt32 size); - void Skeep(size_t size); + void Skip(size_t size); UInt16 ReadUInt16(); UInt32 ReadUInt32(); UInt64 ReadUInt64(); diff --git a/CPP/7zip/Archive/Com/ComHandler.cpp b/CPP/7zip/Archive/Com/ComHandler.cpp index 8b46976c..287f6156 100755 --- a/CPP/7zip/Archive/Com/ComHandler.cpp +++ b/CPP/7zip/Archive/Com/ComHandler.cpp @@ -3,8 +3,15 @@ #include "StdAfx.h" #include "Common/ComTry.h" + #include "Windows/PropVariant.h" + +#include "../../Common/LimitedStreams.h" +#include "../../Common/ProgressUtils.h" #include "../../Common/StreamUtils.h" + +#include "../../Compress/CopyCoder.h" + #include "ComHandler.h" namespace NArchive { @@ -15,16 +22,15 @@ STATPROPSTG kProps[] = { NULL, kpidPath, VT_BSTR}, { NULL, kpidIsDir, VT_BOOL}, { NULL, kpidSize, VT_UI8}, - // { NULL, kpidAttributes, VT_UI4}, { NULL, kpidPackSize, VT_UI8}, { NULL, kpidCTime, VT_FILETIME}, { NULL, kpidMTime, VT_FILETIME} }; - STATPROPSTG kArcProps[] = { - { NULL, kpidClusterSize, VT_UI4} + { NULL, kpidClusterSize, VT_UI4}, + { NULL, kpidSectorSize, VT_UI4} }; IMP_IInArchive_Props @@ -37,6 +43,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) switch(propID) { case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break; + case kpidSectorSize: prop = (UInt32)1 << _db.MiniSectorSizeBits; break; } prop.Detach(value); return S_OK; @@ -52,33 +59,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val switch(propID) { - case kpidPath: - { - UString name = _db.GetItemPath(index); - prop = name; - break; - } + case kpidPath: prop = _db.GetItemPath(index); break; case kpidIsDir: prop = item.IsDir(); break; case kpidCTime: prop = item.CTime; break; case kpidMTime: prop = item.MTime; break; - /* - case kpidAttributes: - 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; + case kpidPackSize: if (!item.IsDir()) prop = _db.GetItemPackSize(item.Size); break; + case kpidSize: if (!item.IsDir()) prop = item.Size; break; } prop.Detach(value); return S_OK; @@ -93,7 +79,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, Close(); try { - if (OpenArchive(inStream, _db) != S_OK) + if (_db.Open(inStream) != S_OK) return S_FALSE; _stream = inStream; } @@ -129,25 +115,29 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, } RINOK(extractCallback->SetTotal(totalSize)); - UInt64 currentTotalSize = 0, currentItemSize = 0; + UInt64 totalPackSize; + totalSize = totalPackSize = 0; - CByteBuffer sect; - sect.SetCapacity((UInt32)1 << _db.SectorSizeBits); + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + 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(¤tTotalSize)); + lps->InSize = totalPackSize; + lps->OutSize = totalSize; + RINOK(lps->SetCur()); Int32 index = allFilesMode ? i : indices[i]; 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 ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; - RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + RINOK(extractCallback->GetStream(index, &outStream, askMode)); if (item.IsDir()) { @@ -155,75 +145,31 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); continue; } - if (!testMode && (!realOutStream)) + + totalPackSize += _db.GetItemPackSize(item.Size); + totalSize += item.Size; + + if (!testMode && (!outStream)) continue; RINOK(extractCallback->PrepareOperation(askMode)); 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; - UInt64 prev = 0; - for (UInt64 pos = 0;;) + RINOK(hres); + if (inStream) { - if (sid == NFatID::kEndOfChain) - { - if (pos != item.Size) - break; + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + if (copyCoderSpec->TotalSize == item.Size) 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)); } return S_OK; @@ -236,4 +182,58 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) 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 +} + }} diff --git a/CPP/7zip/Archive/Com/ComHandler.h b/CPP/7zip/Archive/Com/ComHandler.h index 89bc98d0..f2b7de96 100755 --- a/CPP/7zip/Archive/Com/ComHandler.h +++ b/CPP/7zip/Archive/Com/ComHandler.h @@ -12,15 +12,15 @@ namespace NCom { class CHandler: public IInArchive, + public IInArchiveGetStream, public CMyUnknownImp { -public: - MY_UNKNOWN_IMP1(IInArchive) - INTERFACE_IInArchive(;) - -private: CMyComPtr<IInStream> _stream; CDatabase _db; +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; }} diff --git a/CPP/7zip/Archive/Com/ComIn.cpp b/CPP/7zip/Archive/Com/ComIn.cpp index 74e601c1..8f622122 100755 --- a/CPP/7zip/Archive/Com/ComIn.cpp +++ b/CPP/7zip/Archive/Com/ComIn.cpp @@ -2,19 +2,19 @@ #include "StdAfx.h" -extern "C" -{ #include "../../../../C/Alloc.h" -} - #include "../../../../C/CpuArch.h" +#include "Common/IntToString.h" #include "Common/MyCom.h" + #include "../../Common/StreamUtils.h" -#include "Common/IntToString.h" #include "ComIn.h" +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) + namespace NArchive{ namespace NCom{ @@ -50,31 +50,40 @@ static HRESULT ReadIDs(IInStream *inStream, Byte *buf, int sectorSizeBits, UInt3 RINOK(ReadSector(inStream, buf, sectorSizeBits, sid)); UInt32 sectorSize = (UInt32)1 << sectorSizeBits; for (UInt32 t = 0; t < sectorSize; t += 4) - *dest++ = GetUi32(buf + t); + *dest++ = Get32(buf + t); return S_OK; } static void GetFileTimeFromMem(const Byte *p, FILETIME *ft) { - ft->dwLowDateTime = GetUi32(p); - ft->dwHighDateTime = GetUi32(p + 4); + ft->dwLowDateTime = Get32(p); + 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); - // item.NameSize = GetUi16(p + 64); - item.Type = p[66]; - item.LeftDid = GetUi32(p + 68); - item.RightDid = GetUi32(p + 72); - item.SonDid = GetUi32(p + 76); - // item.Flags = GetUi32(p + 96); - GetFileTimeFromMem(p + 100, &item.CTime); - GetFileTimeFromMem(p + 108, &item.MTime); - item.Sid = GetUi32(p + 116); - item.Size = GetUi32(p + 120); + memcpy(Name, p, kNameSizeMax); + // NameSize = Get16(p + 64); + Type = p[66]; + LeftDid = Get32(p + 68); + RightDid = Get32(p + 72); + SonDid = Get32(p + 76); + // Flags = Get32(p + 96); + GetFileTimeFromMem(p + 100, &CTime); + GetFileTimeFromMem(p + 108, &MTime); + Sid = Get32(p + 116); + Size = Get32(p + 120); 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; @@ -106,13 +115,6 @@ HRESULT CDatabase::AddNode(int parent, UInt32 did) static const char kCharOpenBracket = '['; static const char kCharCloseBracket = ']'; -UString DWORDToString(UInt32 val) -{ - wchar_t buf[32]; - ConvertUInt64ToString(val, buf); - return buf; -} - static UString CompoundNameToFileName(const UString &s) { UString res; @@ -122,7 +124,9 @@ static UString CompoundNameToFileName(const UString &s) if (c < 0x20) { res += kCharOpenBracket; - res += DWORDToString(c); + wchar_t buf[32]; + ConvertUInt32ToString(c, buf); + res += buf; res += kCharCloseBracket; } else @@ -201,31 +205,30 @@ UString CDatabase::GetItemPath(UInt32 index) const return s; } -HRESULT OpenArchive(IInStream *inStream, CDatabase &db) +HRESULT CDatabase::Open(IInStream *inStream) { static const UInt32 kHeaderSize = 512; Byte p[kHeaderSize]; RINOK(ReadStream_FALSE(inStream, p, kHeaderSize)); if (memcmp(p, kSignature, kSignatureSize) != 0) return S_FALSE; - UInt16 majorVer = GetUi16(p + 0x1A); - if (majorVer > 4) + if (Get16(p + 0x1A) > 4) // majorVer return S_FALSE; - if (GetUi16(p + 0x1C) != 0xFFFE) + if (Get16(p + 0x1C) != 0xFFFE) return S_FALSE; - UInt16 sectorSizeBits = GetUi16(p + 0x1E); + int sectorSizeBits = Get16(p + 0x1E); bool mode64bit = (sectorSizeBits >= 12); - UInt16 miniSectorSizeBits = GetUi16(p + 0x20); - db.SectorSizeBits = sectorSizeBits; - db.MiniSectorSizeBits = miniSectorSizeBits; + int miniSectorSizeBits = Get16(p + 0x20); + SectorSizeBits = sectorSizeBits; + MiniSectorSizeBits = miniSectorSizeBits; if (sectorSizeBits > 28 || miniSectorSizeBits > 28 || sectorSizeBits < 7 || miniSectorSizeBits < 2 || miniSectorSizeBits > sectorSizeBits) return S_FALSE; - UInt32 numSectorsForFAT = GetUi32(p + 0x2C); - db.LongStreamMinSize = GetUi32(p + 0x38); + UInt32 numSectorsForFAT = Get32(p + 0x2C); + LongStreamMinSize = Get32(p + 0x38); - UInt32 sectSize = (UInt32)1 << (int)(sectorSizeBits); + UInt32 sectSize = (UInt32)1 << (int)sectorSizeBits; CByteBuffer sect; sect.SetCapacity(sectSize); @@ -235,11 +238,11 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db) UInt32 numFatItems = numSectorsForFAT << ssb2; if ((numFatItems >> ssb2) != numSectorsForFAT) return S_FALSE; - db.FatSize = numFatItems; + FatSize = numFatItems; { CUInt32Buf bat; - UInt32 numSectorsForBat = GetUi32(p + 0x48); + UInt32 numSectorsForBat = Get32(p + 0x48); const UInt32 kNumHeaderBatItems = 109; UInt32 numBatItems = kNumHeaderBatItems + (numSectorsForBat << ssb2); if (numBatItems < kNumHeaderBatItems || ((numBatItems - kNumHeaderBatItems) >> ssb2) != numSectorsForBat) @@ -248,8 +251,8 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db) return S_FALSE; UInt32 i; for (i = 0; i < kNumHeaderBatItems; i++) - bat[i] = GetUi32(p + 0x4c + i * 4); - UInt32 sid = GetUi32(p + 0x44); + bat[i] = Get32(p + 0x4c + i * 4); + UInt32 sid = Get32(p + 0x44); for (UInt32 s = 0; s < numSectorsForBat; s++) { RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, bat + i)); @@ -258,7 +261,7 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db) } numBatItems = i; - if (!db.Fat.Allocate(numFatItems)) + if (!Fat.Allocate(numFatItems)) return S_FALSE; UInt32 j = 0; @@ -266,33 +269,33 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db) { if (j >= numBatItems) 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 numSectorsForMat = GetUi32(p + 0x40); + UInt32 numSectorsForMat = Get32(p + 0x40); numMatItems = (UInt32)numSectorsForMat << ssb2; if ((numMatItems >> ssb2) != numSectorsForMat) return S_FALSE; - if (!db.Mat.Allocate(numMatItems)) + if (!Mat.Allocate(numMatItems)) return S_FALSE; UInt32 i; - UInt32 sid = GetUi32(p + 0x3C); + UInt32 sid = Get32(p + 0x3C); 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) return S_FALSE; - sid = db.Fat[sid]; + sid = Fat[sid]; } if (sid != NFatID::kEndOfChain) return S_FALSE; } { - UInt32 sid = GetUi32(p + 0x30); + UInt32 sid = Get32(p + 0x30); for (;;) { if (sid >= numFatItems) @@ -301,16 +304,16 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db) for (UInt32 i = 0; i < sectSize; i += 128) { CItem item; - ReadItem(sect + i, item, mode64bit); - db.Items.Add(item); + item.Parse(sect + i, mode64bit); + Items.Add(item); } - sid = db.Fat[sid]; + sid = Fat[sid]; if (sid == NFatID::kEndOfChain) break; } } - CItem root = db.Items[0]; + CItem root = Items[0]; { UInt32 numSectorsInMiniStream; @@ -320,19 +323,18 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db) return S_FALSE; numSectorsInMiniStream = (UInt32)numSatSects64; } - db.NumSectorsInMiniStream = numSectorsInMiniStream; - if (!db.MiniSids.Allocate(numSectorsInMiniStream)) + NumSectorsInMiniStream = numSectorsInMiniStream; + if (!MiniSids.Allocate(numSectorsInMiniStream)) return S_FALSE; { UInt64 matSize64 = (root.Size + ((UInt64)1 << miniSectorSizeBits) - 1) >> miniSectorSizeBits; if (matSize64 > NFatID::kMaxValue) return S_FALSE; - db.MatSize = (UInt32)matSize64; - if (numMatItems < db.MatSize) + MatSize = (UInt32)matSize64; + if (numMatItems < MatSize) return S_FALSE; } - UInt32 sid = root.Sid; for (UInt32 i = 0; ; i++) { @@ -344,14 +346,14 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db) } if (i >= numSectorsInMiniStream) return S_FALSE; - db.MiniSids[i] = sid; + MiniSids[i] = sid; if (sid >= numFatItems) return S_FALSE; - sid = db.Fat[sid]; + sid = Fat[sid]; } } - return db.AddNode(-1, root.SonDid); + return AddNode(-1, root.SonDid); } }} diff --git a/CPP/7zip/Archive/Com/ComIn.h b/CPP/7zip/Archive/Com/ComIn.h index 081c6aaa..05fc7387 100755 --- a/CPP/7zip/Archive/Com/ComIn.h +++ b/CPP/7zip/Archive/Com/ComIn.h @@ -57,6 +57,8 @@ struct CItem bool IsEmpty() const { return Type == NItemType::kEmpty; } bool IsDir() const { return Type == NItemType::kStorage || Type == NItemType::kRootStorage; } + + void Parse(const Byte *p, bool mode64bit); }; struct CRef @@ -67,15 +69,15 @@ struct CRef class CDatabase { -public: + UInt32 NumSectorsInMiniStream; + CUInt32Buf MiniSids; + HRESULT AddNode(int parent, UInt32 did); +public: CUInt32Buf Fat; UInt32 FatSize; - CUInt32Buf MiniSids; - UInt32 NumSectorsInMiniStream; - CUInt32Buf Mat; UInt32 MatSize; @@ -86,20 +88,29 @@ public: int SectorSizeBits; 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(); - MiniSids.Free(); - Mat.Free(); - Items.Clear(); - Refs.Clear(); + UInt64 mask = ((UInt64)1 << (IsLargeStream(size) ? SectorSizeBits : MiniSectorSizeBits)) - 1; + return (size + mask) & ~mask; } - bool IsLargeStream(UInt64 size) { return size >= LongStreamMinSize; } - UString GetItemPath(UInt32 index) const; + bool GetMiniCluster(UInt32 sid, UInt64 &res) 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); }} diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp index 76739e94..46f835ef 100755 --- a/CPP/7zip/Archive/Common/HandlerOut.cpp +++ b/CPP/7zip/Archive/Common/HandlerOut.cpp @@ -82,11 +82,11 @@ static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5; static bool AreEqual(const UString &methodName, const wchar_t *s) { return (methodName.CompareNoCase(s) == 0); } -static inline bool IsLZMAMethod(const UString &methodName) +bool COneMethodInfo::IsLzma() const { return - AreEqual(methodName, kLZMAMethodName) || - AreEqual(methodName, kLZMA2MethodName); + AreEqual(MethodName, kLZMAMethodName) || + AreEqual(MethodName, kLZMA2MethodName); } static inline bool IsBZip2Method(const UString &methodName) @@ -109,8 +109,12 @@ struct CNameToPropID 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::kPosStateBits, VT_UI4, L"PB" }, { NCoderPropID::kLitContextBits, VT_UI4, L"LC" }, @@ -122,7 +126,8 @@ CNameToPropID g_NameToPropID[] = { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" }, { NCoderPropID::kAlgorithm, VT_UI4, L"a" }, { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" }, - { NCoderPropID::kNumThreads, VT_UI4, L"mt" } + { NCoderPropID::kNumThreads, VT_UI4, L"mt" }, + { NCoderPropID::kDefaultProp, VT_UI4, L"" } }; 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; } -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++) if (name.CompareNoCase(g_NameToPropID[i].Name) == 0) @@ -162,16 +167,26 @@ static int FindPropIdFromStringName(const UString &name) return -1; } -static void SetOneMethodProp(COneMethodInfo &oneMethodInfo, PROPID propID, - const NWindows::NCOM::CPropVariant &value) +static int FindPropIdStart(const UString &name) +{ + for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++) + { + UString t = g_NameToPropID[i].Name; + if (t.CompareNoCase(name.Left(t.Length())) == 0) + return i; + } + return -1; +} + +static void SetMethodProp(COneMethodInfo &m, PROPID propID, const NCOM::CPropVariant &value) { - for (int j = 0; j < oneMethodInfo.Props.Size(); j++) - if (oneMethodInfo.Props[j].Id == propID) + for (int j = 0; j < m.Props.Size(); j++) + if (m.Props[j].Id == propID) return; CProp prop; prop.Id = propID; prop.Value = value; - oneMethodInfo.Props.Add(prop); + m.Props.Add(prop); } void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo @@ -184,7 +199,7 @@ void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo if (oneMethodInfo.MethodName.IsEmpty()) oneMethodInfo.MethodName = kDefaultMethodName; - if (IsLZMAMethod(oneMethodInfo.MethodName)) + if (oneMethodInfo.IsLzma()) { UInt32 dicSize = (level >= 9 ? kLzmaDicSizeX9 : @@ -205,12 +220,12 @@ void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo (level >= 5 ? kLzmaMatchFinderX5 : kLzmaMatchFinderX1); - SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); - SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); - SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); - SetOneMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder); + SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); + SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); + SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); + SetMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder); #ifdef COMPRESS_MT - SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); + SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif } else if (IsDeflateMethod(oneMethodInfo.MethodName)) @@ -229,9 +244,9 @@ void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo (level >= 5 ? kDeflateAlgoX5 : kDeflateAlgoX1); - SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); - SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); - SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); + SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); + SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); + SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); } else if (IsBZip2Method(oneMethodInfo.MethodName)) { @@ -245,10 +260,10 @@ void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo (level >= 3 ? kBZip2DicSizeX3 : kBZip2DicSizeX1)); - SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); - SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); + SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); + SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); #ifdef COMPRESS_MT - SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); + SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif } else if (IsPpmdMethod(oneMethodInfo.MethodName)) @@ -265,8 +280,8 @@ void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo (level >= 5 ? kPpmdOrderX5 : kPpmdOrderX1))); - SetOneMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize); - SetOneMethodProp(oneMethodInfo, NCoderPropID::kOrder, order); + SetMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize); + SetMethodProp(oneMethodInfo, NCoderPropID::kOrder, order); } } @@ -316,25 +331,22 @@ static void SplitParam(const UString ¶m, UString &name, UString &value) HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value) { CProp prop; - if (name.CompareNoCase(L"D") == 0 || - name.CompareNoCase(L"MEM") == 0) + int index = FindPropIdExact(name); + if (index < 0) + return E_INVALIDARG; + const CNameToPropID &nameToPropID = g_NameToPropID[index]; + prop.Id = nameToPropID.PropID; + + if (prop.Id == NCoderPropID::kBlockSize || + prop.Id == NCoderPropID::kDictionarySize || + prop.Id == NCoderPropID::kUsedMemorySize) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(value, dicSize)); - prop.Id = (name.CompareNoCase(L"D") == 0) ? - NCoderPropID::kDictionarySize : - NCoderPropID::kUsedMemorySize; prop.Value = dicSize; } else { - int index = FindPropIdFromStringName(name); - if (index < 0) - return E_INVALIDARG; - - const CNameToPropID &nameToPropID = g_NameToPropID[index]; - prop.Id = nameToPropID.PropID; - NCOM::CPropVariant propValue; if (nameToPropID.VarType == VT_BSTR) @@ -465,7 +477,7 @@ void COutHandler::Init() WriteMTime = true; #ifdef COMPRESS_MT - _numThreads = NWindows::NSystem::GetNumberOfProcessors(); + _numThreads = NSystem::GetNumberOfProcessors(); #endif _level = 5; @@ -576,35 +588,26 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val } else { + int index = FindPropIdStart(realName); + if (index < 0) + return E_INVALIDARG; + const CNameToPropID &nameToPropID = g_NameToPropID[index]; CProp prop; - if (realName.Left(1).CompareNoCase(L"D") == 0) - { - UInt32 dicSize; - RINOK(ParsePropDictionaryValue(realName.Mid(1), 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) + prop.Id = nameToPropID.PropID; + + if (prop.Id == NCoderPropID::kBlockSize || + prop.Id == NCoderPropID::kDictionarySize || + prop.Id == NCoderPropID::kUsedMemorySize) { UInt32 dicSize; - RINOK(ParsePropDictionaryValue(realName.Mid(3), value, dicSize)); - prop.Id = NCoderPropID::kUsedMemorySize; + RINOK(ParsePropDictionaryValue(realName.Mid(MyStringLen(nameToPropID.Name)), value, dicSize)); prop.Value = dicSize; if (number <= mainDicMethodIndex) mainDicSize = dicSize; } else { - int index = FindPropIdFromStringName(realName); + int index = FindPropIdExact(realName); if (index < 0) return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[index]; diff --git a/CPP/7zip/Archive/Common/HandlerOut.h b/CPP/7zip/Archive/Common/HandlerOut.h index 89c81c1f..7ba22b24 100755 --- a/CPP/7zip/Archive/Common/HandlerOut.h +++ b/CPP/7zip/Archive/Common/HandlerOut.h @@ -12,6 +12,8 @@ struct COneMethodInfo { CObjectVector<CProp> Props; UString MethodName; + + bool IsLzma() const; }; class COutHandler diff --git a/CPP/7zip/Archive/Common/InStreamWithCRC.h b/CPP/7zip/Archive/Common/InStreamWithCRC.h index c5ada6fe..0492a5f8 100755 --- a/CPP/7zip/Archive/Common/InStreamWithCRC.h +++ b/CPP/7zip/Archive/Common/InStreamWithCRC.h @@ -1,15 +1,13 @@ // InStreamWithCRC.h -#ifndef __INSTREAMWITHCRC_H -#define __INSTREAMWITHCRC_H +#ifndef __IN_STREAM_WITH_CRC_H +#define __IN_STREAM_WITH_CRC_H + +#include "../../../../C/7zCrc.h" #include "../../../Common/MyCom.h" -#include "../../IStream.h" -extern "C" -{ -#include "../../../../C/7zCrc.h" -} +#include "../../IStream.h" class CSequentialInStreamWithCRC: public ISequentialInStream, diff --git a/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp b/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp index 2ab2da66..f955c225 100755 --- a/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp +++ b/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp @@ -6,19 +6,13 @@ STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize) { - UInt32 realProcessedSize; - HRESULT result; - if(!_stream) - { - realProcessedSize = size; - result = S_OK; - } - else - result = _stream->Write(data, size, &realProcessedSize); + HRESULT result = S_OK; + if (_stream) + result = _stream->Write(data, size, &size); if (_calculate) - _crc = CrcUpdate(_crc, data, realProcessedSize); - _size += realProcessedSize; - if(processedSize != NULL) - *processedSize = realProcessedSize; + _crc = CrcUpdate(_crc, data, size); + _size += size; + if (processedSize != NULL) + *processedSize = size; return result; } diff --git a/CPP/7zip/Archive/Common/OutStreamWithCRC.h b/CPP/7zip/Archive/Common/OutStreamWithCRC.h index a034ee9b..115b442a 100755 --- a/CPP/7zip/Archive/Common/OutStreamWithCRC.h +++ b/CPP/7zip/Archive/Common/OutStreamWithCRC.h @@ -3,13 +3,11 @@ #ifndef __OUT_STREAM_WITH_CRC_H #define __OUT_STREAM_WITH_CRC_H +#include "../../../../C/7zCrc.h" + #include "../../../Common/MyCom.h" -#include "../../IStream.h" -extern "C" -{ -#include "../../../../C/7zCrc.h" -} +#include "../../IStream.h" class COutStreamWithCRC: public ISequentialOutStream, diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp index 51d2568a..0526c1b1 100755 --- a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp +++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp @@ -6,19 +6,13 @@ STDMETHODIMP COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *processedSize) { - UInt32 realProcessedSize; - HRESULT result; - if(!_stream) - { - realProcessedSize = size; - result = S_OK; - } - else - result = _stream->Write(data, size, &realProcessedSize); + HRESULT result = S_OK; + if (_stream) + result = _stream->Write(data, size, &size); if (_calculate) - _sha.Update((const Byte *)data, realProcessedSize); - _size += realProcessedSize; - if(processedSize != NULL) - *processedSize = realProcessedSize; + _sha.Update((const Byte *)data, size); + _size += size; + if (processedSize != NULL) + *processedSize = size; return result; } diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.h b/CPP/7zip/Archive/Common/OutStreamWithSha1.h index 4eab42a7..3bbfbbe1 100755 --- a/CPP/7zip/Archive/Common/OutStreamWithSha1.h +++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.h @@ -3,13 +3,11 @@ #ifndef __OUT_STREAM_WITH_SHA1_H #define __OUT_STREAM_WITH_SHA1_H -#include "../../../Common/MyCom.h" -#include "../../IStream.h" - - - #include "../../Crypto/Sha1.h" +#include "../../../Common/MyCom.h" + +#include "../../IStream.h" class COutStreamWithSha1: public ISequentialOutStream, diff --git a/CPP/7zip/Archive/Cpio/CpioHandler.cpp b/CPP/7zip/Archive/Cpio/CpioHandler.cpp deleted file mode 100755 index d49c854f..00000000 --- a/CPP/7zip/Archive/Cpio/CpioHandler.cpp +++ /dev/null @@ -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 -} - -}} diff --git a/CPP/7zip/Archive/Cpio/CpioHandler.h b/CPP/7zip/Archive/Cpio/CpioHandler.h deleted file mode 100755 index 1993c37f..00000000 --- a/CPP/7zip/Archive/Cpio/CpioHandler.h +++ /dev/null @@ -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 diff --git a/CPP/7zip/Archive/Cpio/CpioHeader.cpp b/CPP/7zip/Archive/Cpio/CpioHeader.cpp deleted file mode 100755 index f7b5a414..00000000 --- a/CPP/7zip/Archive/Cpio/CpioHeader.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// Archive/cpio/Header.h - -#include "StdAfx.h" - -#include "CpioHeader.h" - -namespace NArchive { -namespace NCpio { -namespace NFileHeader { - - namespace NMagic - { - extern const char *kMagic1 = "070701"; - extern const char *kMagic2 = "070702"; - extern const char *kMagic3 = "070707"; - extern const char *kEndName = "TRAILER!!!"; - - const Byte kMagicForRecord2[2] = { 0xC7, 0x71 }; - // unsigned short kMagicForRecord2BE = 0xC771; - } - -}}} - diff --git a/CPP/7zip/Archive/Cpio/CpioHeader.h b/CPP/7zip/Archive/Cpio/CpioHeader.h deleted file mode 100755 index 21afcc17..00000000 --- a/CPP/7zip/Archive/Cpio/CpioHeader.h +++ /dev/null @@ -1,70 +0,0 @@ -// Archive/cpio/Header.h - -#ifndef __ARCHIVE_CPIO_HEADER_H -#define __ARCHIVE_CPIO_HEADER_H - -#include "Common/Types.h" - -namespace NArchive { -namespace NCpio { - -namespace NFileHeader -{ - namespace NMagic - { - extern const char *kMagic1; - extern const char *kMagic2; - extern const char *kMagic3; - extern const char *kEndName; - extern const Byte kMagicForRecord2[2]; - } - - const UInt32 kRecord2Size = 26; - /* - struct CRecord2 - { - unsigned short c_magic; - short c_dev; - unsigned short c_ino; - unsigned short c_mode; - unsigned short c_uid; - unsigned short c_gid; - unsigned short c_nlink; - short c_rdev; - unsigned short c_mtimes[2]; - unsigned short c_namesize; - unsigned short c_filesizes[2]; - }; - */ - - const UInt32 kRecordSize = 110; - /* - struct CRecord - { - char Magic[6]; // "070701" for "new" portable format, "070702" for CRC format - char inode[8]; - char Mode[8]; - char UID[8]; - char GID[8]; - char nlink[8]; - char mtime[8]; - char Size[8]; // must be 0 for FIFOs and directories - char DevMajor[8]; - char DevMinor[8]; - char RDevMajor[8]; //only valid for chr and blk special files - char RDevMinor[8]; //only valid for chr and blk special files - char NameSize[8]; // count includes terminating NUL in pathname - char ChkSum[8]; // 0 for "new" portable format; for CRC format the sum of all the bytes in the file - bool CheckMagic() const - { return memcmp(Magic, NMagic::kMagic1, 6) == 0 || - memcmp(Magic, NMagic::kMagic2, 6) == 0; }; - }; - */ - - const UInt32 kOctRecordSize = 76; - -} - -}} - -#endif diff --git a/CPP/7zip/Archive/Cpio/CpioIn.cpp b/CPP/7zip/Archive/Cpio/CpioIn.cpp deleted file mode 100755 index d4d807e1..00000000 --- a/CPP/7zip/Archive/Cpio/CpioIn.cpp +++ /dev/null @@ -1,272 +0,0 @@ -// Archive/cpioIn.cpp - -#include "StdAfx.h" - -#include "CpioIn.h" - -#include "Common/StringToInt.h" -#include "Windows/Defs.h" - -#include "../../Common/StreamUtils.h" - -#include "CpioHeader.h" - -namespace NArchive { -namespace NCpio { - -HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize) -{ - size_t realProcessedSize = size; - RINOK(ReadStream(m_Stream, data, &realProcessedSize)); - processedSize = (UInt32)realProcessedSize; - m_Position += processedSize; - return S_OK; -} - -Byte CInArchive::ReadByte() -{ - if (_blockPos >= _blockSize) - throw "Incorrect cpio archive"; - return _block[_blockPos++]; -} - -UInt16 CInArchive::ReadUInt16() -{ - UInt16 value = 0; - for (int i = 0; i < 2; i++) - { - Byte b = ReadByte(); - value |= (UInt16(b) << (8 * i)); - } - return value; -} - -UInt32 CInArchive::ReadUInt32() -{ - UInt32 value = 0; - for (int i = 0; i < 4; i++) - { - Byte b = ReadByte(); - value |= (UInt32(b) << (8 * i)); - } - return value; -} - -HRESULT CInArchive::Open(IInStream *inStream) -{ - RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position)); - m_Stream = inStream; - return S_OK; -} - -bool CInArchive::ReadNumber(UInt32 &resultValue) -{ - resultValue = 0; - for (int i = 0; i < 8; i++) - { - char c = char(ReadByte()); - int d; - if (c >= '0' && c <= '9') - d = c - '0'; - else if (c >= 'A' && c <= 'F') - d = 10 + c - 'A'; - else if (c >= 'a' && c <= 'f') - d = 10 + c - 'a'; - else - return false; - resultValue *= 0x10; - resultValue += d; - } - return true; -} - -static bool OctalToNumber(const char *s, UInt64 &res) -{ - const char *end; - res = ConvertOctStringToUInt64(s, &end); - return (*end == ' ' || *end == 0); -} - -static bool OctalToNumber32(const char *s, UInt32 &res) -{ - UInt64 res64; - if (!OctalToNumber(s, res64)) - return false; - res = (UInt32)res64; - return (res64 <= 0xFFFFFFFF); -} - -bool CInArchive::ReadOctNumber(int size, UInt32 &resultValue) -{ - char sz[32 + 4]; - int i; - for (i = 0; i < size && i < 32; i++) - sz[i] = (char)ReadByte(); - sz[i] = 0; - return OctalToNumber32(sz, resultValue); -} - -#define GetFromHex(y) { if (!ReadNumber(y)) return S_FALSE; } -#define GetFromOct6(y) { if (!ReadOctNumber(6, y)) return S_FALSE; } -#define GetFromOct11(y) { if (!ReadOctNumber(11, y)) return S_FALSE; } - -static unsigned short ConvertValue(unsigned short value, bool convert) -{ - if (!convert) - return value; - return (unsigned short)((((unsigned short)(value & 0xFF)) << 8) | (value >> 8)); -} - -static UInt32 GetAlignedSize(UInt32 size, UInt32 align) -{ - while ((size & (align - 1)) != 0) - size++; - return size; -} - - -HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) -{ - filled = false; - - UInt32 processedSize; - item.HeaderPosition = m_Position; - - _blockSize = kMaxBlockSize; - RINOK(ReadBytes(_block, 2, processedSize)); - if (processedSize != 2) - return S_FALSE; - _blockPos = 0; - - UInt32 nameSize; - - bool oldBE = - _block[0] == NFileHeader::NMagic::kMagicForRecord2[1] && - _block[1] == NFileHeader::NMagic::kMagicForRecord2[0]; - - bool binMode = (_block[0] == NFileHeader::NMagic::kMagicForRecord2[0] && - _block[1] == NFileHeader::NMagic::kMagicForRecord2[1]) || - oldBE; - - if (binMode) - { - RINOK(ReadBytes(_block + 2, NFileHeader::kRecord2Size - 2, processedSize)); - if (processedSize != NFileHeader::kRecord2Size - 2) - return S_FALSE; - item.Align = 2; - _blockPos = 2; - item.DevMajor = 0; - item.DevMinor = ConvertValue(ReadUInt16(), oldBE); - item.inode = ConvertValue(ReadUInt16(), oldBE); - item.Mode = ConvertValue(ReadUInt16(), oldBE); - item.UID = ConvertValue(ReadUInt16(), oldBE); - item.GID = ConvertValue(ReadUInt16(), oldBE); - item.NumLinks = ConvertValue(ReadUInt16(), oldBE); - item.RDevMajor =0; - item.RDevMinor = ConvertValue(ReadUInt16(), oldBE); - UInt16 timeHigh = ConvertValue(ReadUInt16(), oldBE); - UInt16 timeLow = ConvertValue(ReadUInt16(), oldBE); - item.ModificationTime = (UInt32(timeHigh) << 16) + timeLow; - nameSize = ConvertValue(ReadUInt16(), oldBE); - UInt16 sizeHigh = ConvertValue(ReadUInt16(), oldBE); - UInt16 sizeLow = ConvertValue(ReadUInt16(), oldBE); - item.Size = (UInt32(sizeHigh) << 16) + sizeLow; - - item.ChkSum = 0; - item.HeaderSize = GetAlignedSize( - nameSize + NFileHeader::kRecord2Size, item.Align); - nameSize = item.HeaderSize - NFileHeader::kRecord2Size; - } - else - { - RINOK(ReadBytes(_block + 2, 4, processedSize)); - if (processedSize != 4) - return S_FALSE; - - bool magicOK = - memcmp(_block, NFileHeader::NMagic::kMagic1, 6) == 0 || - memcmp(_block, NFileHeader::NMagic::kMagic2, 6) == 0; - _blockPos = 6; - if (magicOK) - { - RINOK(ReadBytes(_block + 6, NFileHeader::kRecordSize - 6, processedSize)); - if (processedSize != NFileHeader::kRecordSize - 6) - return S_FALSE; - item.Align = 4; - - GetFromHex(item.inode); - GetFromHex(item.Mode); - GetFromHex(item.UID); - GetFromHex(item.GID); - GetFromHex(item.NumLinks); - UInt32 modificationTime; - GetFromHex(modificationTime); - item.ModificationTime = modificationTime; - GetFromHex(item.Size); - GetFromHex(item.DevMajor); - GetFromHex(item.DevMinor); - GetFromHex(item.RDevMajor); - GetFromHex(item.RDevMinor); - GetFromHex(nameSize); - GetFromHex(item.ChkSum); - item.HeaderSize = GetAlignedSize( - nameSize + NFileHeader::kRecordSize, item.Align); - nameSize = item.HeaderSize - NFileHeader::kRecordSize; - } - else - { - if (!memcmp(_block, NFileHeader::NMagic::kMagic3, 6) == 0) - return S_FALSE; - RINOK(ReadBytes(_block + 6, NFileHeader::kOctRecordSize - 6, processedSize)); - if (processedSize != NFileHeader::kOctRecordSize - 6) - return S_FALSE; - item.Align = 1; - item.DevMajor = 0; - GetFromOct6(item.DevMinor); - GetFromOct6(item.inode); - GetFromOct6(item.Mode); - GetFromOct6(item.UID); - GetFromOct6(item.GID); - GetFromOct6(item.NumLinks); - item.RDevMajor = 0; - GetFromOct6(item.RDevMinor); - UInt32 modificationTime; - GetFromOct11(modificationTime); - item.ModificationTime = modificationTime; - GetFromOct6(nameSize); - GetFromOct11(item.Size); // ????? - item.HeaderSize = GetAlignedSize( - nameSize + NFileHeader::kOctRecordSize, item.Align); - nameSize = item.HeaderSize - NFileHeader::kOctRecordSize; - } - } - if (nameSize == 0 || nameSize >= (1 << 27)) - return E_FAIL; - RINOK(ReadBytes(item.Name.GetBuffer(nameSize), nameSize, processedSize)); - if (processedSize != nameSize) - return E_FAIL; - item.Name.ReleaseBuffer(); - if (strcmp(item.Name, NFileHeader::NMagic::kEndName) == 0) - return S_OK; - filled = true; - return S_OK; -} - -HRESULT CInArchive::Skeep(UInt64 numBytes) -{ - UInt64 newPostion; - RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion)); - m_Position += numBytes; - if (m_Position != newPostion) - return E_FAIL; - return S_OK; -} - -HRESULT CInArchive::SkeepDataRecords(UInt64 dataSize, UInt32 align) -{ - while ((dataSize & (align - 1)) != 0) - dataSize++; - return Skeep(dataSize); -} - -}} diff --git a/CPP/7zip/Archive/Cpio/CpioIn.h b/CPP/7zip/Archive/Cpio/CpioIn.h deleted file mode 100755 index 19e3da10..00000000 --- a/CPP/7zip/Archive/Cpio/CpioIn.h +++ /dev/null @@ -1,41 +0,0 @@ -// CpioIn.h - -#ifndef __ARCHIVE_CPIO_IN_H -#define __ARCHIVE_CPIO_IN_H - -#include "Common/MyCom.h" -#include "Common/Types.h" -#include "../../IStream.h" -#include "CpioItem.h" - -namespace NArchive { -namespace NCpio { - -const UInt32 kMaxBlockSize = NFileHeader::kRecordSize; - -class CInArchive -{ - CMyComPtr<IInStream> m_Stream; - UInt64 m_Position; - - UInt16 _blockSize; - Byte _block[kMaxBlockSize]; - UInt32 _blockPos; - Byte ReadByte(); - UInt16 ReadUInt16(); - UInt32 ReadUInt32(); - - bool ReadNumber(UInt32 &resultValue); - bool ReadOctNumber(int size, UInt32 &resultValue); - - HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize); -public: - HRESULT Open(IInStream *inStream); - HRESULT GetNextItem(bool &filled, CItemEx &itemInfo); - HRESULT Skeep(UInt64 numBytes); - HRESULT SkeepDataRecords(UInt64 dataSize, UInt32 align); -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Cpio/CpioItem.h b/CPP/7zip/Archive/Cpio/CpioItem.h deleted file mode 100755 index 70aa384d..00000000 --- a/CPP/7zip/Archive/Cpio/CpioItem.h +++ /dev/null @@ -1,55 +0,0 @@ -// Archive/cpio/ItemInfo.h - -#ifndef __ARCHIVE_CPIO_ITEMINFO_H -#define __ARCHIVE_CPIO_ITEMINFO_H - -#include <sys/stat.h> - -#include "Common/Types.h" -#include "Common/MyString.h" -#include "CpioHeader.h" - -namespace NArchive { -namespace NCpio { - -struct CItem -{ - AString Name; - UInt32 inode; - UInt32 Mode; - UInt32 UID; - UInt32 GID; - UInt32 Size; - UInt32 ModificationTime; - - // char LinkFlag; - // AString LinkName; ????? - char Magic[8]; - UInt32 NumLinks; - UInt32 DevMajor; - UInt32 DevMinor; - UInt32 RDevMajor; - UInt32 RDevMinor; - UInt32 ChkSum; - - UInt32 Align; - - bool IsDir() const -#ifdef _WIN32 - { return (Mode & _S_IFMT) == _S_IFDIR; } -#else - { return (Mode & S_IFMT) == S_IFDIR; } -#endif -}; - -class CItemEx: public CItem -{ -public: - UInt64 HeaderPosition; - UInt32 HeaderSize; - UInt64 GetDataPosition() const { return HeaderPosition + HeaderSize; }; -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Cpio/CpioRegister.cpp b/CPP/7zip/Archive/Cpio/CpioRegister.cpp deleted file mode 100755 index 62d1265e..00000000 --- a/CPP/7zip/Archive/Cpio/CpioRegister.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// CpioRegister.cpp - -#include "StdAfx.h" - -#include "../../Common/RegisterArc.h" - -#include "CpioHandler.h" -static IInArchive *CreateArc() { return new NArchive::NCpio::CHandler; } - -static CArcInfo g_ArcInfo = - { L"Cpio", L"cpio", 0, 0xED, { 0 }, 0, false, CreateArc, 0 }; - -REGISTER_ARC(Cpio) diff --git a/CPP/7zip/Archive/Cpio/StdAfx.h b/CPP/7zip/Archive/Cpio/StdAfx.h deleted file mode 100755 index e7fb6986..00000000 --- a/CPP/7zip/Archive/Cpio/StdAfx.h +++ /dev/null @@ -1,8 +0,0 @@ -// StdAfx.h - -#ifndef __STDAFX_H -#define __STDAFX_H - -#include "../../../Common/MyWindows.h" - -#endif diff --git a/CPP/7zip/Archive/CpioHandler.cpp b/CPP/7zip/Archive/CpioHandler.cpp new file mode 100755 index 00000000..e5a32936 --- /dev/null +++ b/CPP/7zip/Archive/CpioHandler.cpp @@ -0,0 +1,625 @@ +// CpioHandler.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" +#include "Common/StringToInt.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#include "Common/ItemNameUtils.h" + +namespace NArchive { +namespace NCpio { + +namespace NFileHeader +{ + namespace NMagic + { + extern const char *kMagic1 = "070701"; + extern const char *kMagic2 = "070702"; + extern const char *kMagic3 = "070707"; + extern const char *kEndName = "TRAILER!!!"; + + const Byte kMagicForRecord2[2] = { 0xC7, 0x71 }; + } + + const UInt32 kRecord2Size = 26; + /* + struct CRecord2 + { + unsigned short c_magic; + short c_dev; + unsigned short c_ino; + unsigned short c_mode; + unsigned short c_uid; + unsigned short c_gid; + unsigned short c_nlink; + short c_rdev; + unsigned short c_mtimes[2]; + unsigned short c_namesize; + unsigned short c_filesizes[2]; + }; + */ + + const UInt32 kRecordSize = 110; + /* + struct CRecord + { + char Magic[6]; // "070701" for "new" portable format, "070702" for CRC format + char inode[8]; + char Mode[8]; + char UID[8]; + char GID[8]; + char nlink[8]; + char mtime[8]; + char Size[8]; // must be 0 for FIFOs and directories + char DevMajor[8]; + char DevMinor[8]; + char RDevMajor[8]; //only valid for chr and blk special files + char RDevMinor[8]; //only valid for chr and blk special files + char NameSize[8]; // count includes terminating NUL in pathname + char ChkSum[8]; // 0 for "new" portable format; for CRC format the sum of all the bytes in the file + bool CheckMagic() const + { return memcmp(Magic, NMagic::kMagic1, 6) == 0 || + memcmp(Magic, NMagic::kMagic2, 6) == 0; }; + }; + */ + + const UInt32 kOctRecordSize = 76; + +} + +struct CItem +{ + AString Name; + UInt32 inode; + UInt32 Mode; + UInt32 UID; + UInt32 GID; + UInt32 Size; + UInt32 MTime; + + // char LinkFlag; + // AString LinkName; ????? + char Magic[8]; + UInt32 NumLinks; + UInt32 DevMajor; + UInt32 DevMinor; + UInt32 RDevMajor; + UInt32 RDevMinor; + UInt32 ChkSum; + + UInt32 Align; + + bool IsDir() const { return (Mode & 0170000) == 0040000; } +}; + +class CItemEx: public CItem +{ +public: + UInt64 HeaderPosition; + UInt32 HeaderSize; + UInt64 GetDataPosition() const { return HeaderPosition + HeaderSize; }; +}; + +const UInt32 kMaxBlockSize = NFileHeader::kRecordSize; + +class CInArchive +{ + CMyComPtr<IInStream> m_Stream; + UInt64 m_Position; + + UInt16 _blockSize; + Byte _block[kMaxBlockSize]; + UInt32 _blockPos; + Byte ReadByte(); + UInt16 ReadUInt16(); + UInt32 ReadUInt32(); + + bool ReadNumber(UInt32 &resultValue); + bool ReadOctNumber(int size, UInt32 &resultValue); + + HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize); +public: + HRESULT Open(IInStream *inStream); + HRESULT GetNextItem(bool &filled, CItemEx &itemInfo); + HRESULT Skip(UInt64 numBytes); + HRESULT SkipDataRecords(UInt64 dataSize, UInt32 align); +}; + +HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize) +{ + size_t realProcessedSize = size; + RINOK(ReadStream(m_Stream, data, &realProcessedSize)); + processedSize = (UInt32)realProcessedSize; + m_Position += processedSize; + return S_OK; +} + +Byte CInArchive::ReadByte() +{ + if (_blockPos >= _blockSize) + throw "Incorrect cpio archive"; + return _block[_blockPos++]; +} + +UInt16 CInArchive::ReadUInt16() +{ + UInt16 value = 0; + for (int i = 0; i < 2; i++) + { + Byte b = ReadByte(); + value |= (UInt16(b) << (8 * i)); + } + return value; +} + +UInt32 CInArchive::ReadUInt32() +{ + UInt32 value = 0; + for (int i = 0; i < 4; i++) + { + Byte b = ReadByte(); + value |= (UInt32(b) << (8 * i)); + } + return value; +} + +HRESULT CInArchive::Open(IInStream *inStream) +{ + RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position)); + m_Stream = inStream; + return S_OK; +} + +bool CInArchive::ReadNumber(UInt32 &resultValue) +{ + resultValue = 0; + for (int i = 0; i < 8; i++) + { + char c = char(ReadByte()); + int d; + if (c >= '0' && c <= '9') + d = c - '0'; + else if (c >= 'A' && c <= 'F') + d = 10 + c - 'A'; + else if (c >= 'a' && c <= 'f') + d = 10 + c - 'a'; + else + return false; + resultValue *= 0x10; + resultValue += d; + } + return true; +} + +static bool OctalToNumber(const char *s, UInt64 &res) +{ + const char *end; + res = ConvertOctStringToUInt64(s, &end); + return (*end == ' ' || *end == 0); +} + +static bool OctalToNumber32(const char *s, UInt32 &res) +{ + UInt64 res64; + if (!OctalToNumber(s, res64)) + return false; + res = (UInt32)res64; + return (res64 <= 0xFFFFFFFF); +} + +bool CInArchive::ReadOctNumber(int size, UInt32 &resultValue) +{ + char sz[32 + 4]; + int i; + for (i = 0; i < size && i < 32; i++) + sz[i] = (char)ReadByte(); + sz[i] = 0; + return OctalToNumber32(sz, resultValue); +} + +#define GetFromHex(y) { if (!ReadNumber(y)) return S_FALSE; } +#define GetFromOct6(y) { if (!ReadOctNumber(6, y)) return S_FALSE; } +#define GetFromOct11(y) { if (!ReadOctNumber(11, y)) return S_FALSE; } + +static unsigned short ConvertValue(unsigned short value, bool convert) +{ + if (!convert) + return value; + return (unsigned short)((((unsigned short)(value & 0xFF)) << 8) | (value >> 8)); +} + +static UInt32 GetAlignedSize(UInt32 size, UInt32 align) +{ + while ((size & (align - 1)) != 0) + size++; + return size; +} + + +HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) +{ + filled = false; + + UInt32 processedSize; + item.HeaderPosition = m_Position; + + _blockSize = kMaxBlockSize; + RINOK(ReadBytes(_block, 2, processedSize)); + if (processedSize != 2) + return S_FALSE; + _blockPos = 0; + + UInt32 nameSize; + + bool oldBE = + _block[0] == NFileHeader::NMagic::kMagicForRecord2[1] && + _block[1] == NFileHeader::NMagic::kMagicForRecord2[0]; + + bool binMode = (_block[0] == NFileHeader::NMagic::kMagicForRecord2[0] && + _block[1] == NFileHeader::NMagic::kMagicForRecord2[1]) || + oldBE; + + if (binMode) + { + RINOK(ReadBytes(_block + 2, NFileHeader::kRecord2Size - 2, processedSize)); + if (processedSize != NFileHeader::kRecord2Size - 2) + return S_FALSE; + item.Align = 2; + _blockPos = 2; + item.DevMajor = 0; + item.DevMinor = ConvertValue(ReadUInt16(), oldBE); + item.inode = ConvertValue(ReadUInt16(), oldBE); + item.Mode = ConvertValue(ReadUInt16(), oldBE); + item.UID = ConvertValue(ReadUInt16(), oldBE); + item.GID = ConvertValue(ReadUInt16(), oldBE); + item.NumLinks = ConvertValue(ReadUInt16(), oldBE); + item.RDevMajor =0; + item.RDevMinor = ConvertValue(ReadUInt16(), oldBE); + UInt16 timeHigh = ConvertValue(ReadUInt16(), oldBE); + UInt16 timeLow = ConvertValue(ReadUInt16(), oldBE); + item.MTime = (UInt32(timeHigh) << 16) + timeLow; + nameSize = ConvertValue(ReadUInt16(), oldBE); + UInt16 sizeHigh = ConvertValue(ReadUInt16(), oldBE); + UInt16 sizeLow = ConvertValue(ReadUInt16(), oldBE); + item.Size = (UInt32(sizeHigh) << 16) + sizeLow; + + item.ChkSum = 0; + item.HeaderSize = GetAlignedSize( + nameSize + NFileHeader::kRecord2Size, item.Align); + nameSize = item.HeaderSize - NFileHeader::kRecord2Size; + } + else + { + RINOK(ReadBytes(_block + 2, 4, processedSize)); + if (processedSize != 4) + return S_FALSE; + + bool magicOK = + memcmp(_block, NFileHeader::NMagic::kMagic1, 6) == 0 || + memcmp(_block, NFileHeader::NMagic::kMagic2, 6) == 0; + _blockPos = 6; + if (magicOK) + { + RINOK(ReadBytes(_block + 6, NFileHeader::kRecordSize - 6, processedSize)); + if (processedSize != NFileHeader::kRecordSize - 6) + return S_FALSE; + item.Align = 4; + + GetFromHex(item.inode); + GetFromHex(item.Mode); + GetFromHex(item.UID); + GetFromHex(item.GID); + GetFromHex(item.NumLinks); + UInt32 mTime; + GetFromHex(mTime); + item.MTime = mTime; + GetFromHex(item.Size); + GetFromHex(item.DevMajor); + GetFromHex(item.DevMinor); + GetFromHex(item.RDevMajor); + GetFromHex(item.RDevMinor); + GetFromHex(nameSize); + GetFromHex(item.ChkSum); + item.HeaderSize = GetAlignedSize( + nameSize + NFileHeader::kRecordSize, item.Align); + nameSize = item.HeaderSize - NFileHeader::kRecordSize; + } + else + { + if (!memcmp(_block, NFileHeader::NMagic::kMagic3, 6) == 0) + return S_FALSE; + RINOK(ReadBytes(_block + 6, NFileHeader::kOctRecordSize - 6, processedSize)); + if (processedSize != NFileHeader::kOctRecordSize - 6) + return S_FALSE; + item.Align = 1; + item.DevMajor = 0; + GetFromOct6(item.DevMinor); + GetFromOct6(item.inode); + GetFromOct6(item.Mode); + GetFromOct6(item.UID); + GetFromOct6(item.GID); + GetFromOct6(item.NumLinks); + item.RDevMajor = 0; + GetFromOct6(item.RDevMinor); + UInt32 mTime; + GetFromOct11(mTime); + item.MTime = mTime; + GetFromOct6(nameSize); + GetFromOct11(item.Size); // ????? + item.HeaderSize = GetAlignedSize( + nameSize + NFileHeader::kOctRecordSize, item.Align); + nameSize = item.HeaderSize - NFileHeader::kOctRecordSize; + } + } + if (nameSize == 0 || nameSize >= (1 << 27)) + return E_FAIL; + RINOK(ReadBytes(item.Name.GetBuffer(nameSize), nameSize, processedSize)); + if (processedSize != nameSize) + return E_FAIL; + item.Name.ReleaseBuffer(); + if (strcmp(item.Name, NFileHeader::NMagic::kEndName) == 0) + return S_OK; + filled = true; + return S_OK; +} + +HRESULT CInArchive::Skip(UInt64 numBytes) +{ + UInt64 newPostion; + RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion)); + m_Position += numBytes; + if (m_Position != newPostion) + return E_FAIL; + return S_OK; +} + +HRESULT CInArchive::SkipDataRecords(UInt64 dataSize, UInt32 align) +{ + while ((dataSize & (align - 1)) != 0) + dataSize++; + return Skip(dataSize); +} + + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + CObjectVector<CItemEx> _items; + CMyComPtr<IInStream> _stream; +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +/* +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, kpidPosixAttrib, VT_UI4}, + // { L"inode", kpidinode, VT_UI4} + // { L"CheckSum", kpidiChkSum, VT_UI4} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, 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.SkipDataRecords(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; + + _stream = stream; + } + /* + catch(...) + { + return S_FALSE; + } + */ + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _items.Clear(); + _stream.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: + { + if (item.MTime != 0) + { + FILETIME utc; + NWindows::NTime::UnixTimeToFileTime(item.MTime, utc); + prop = utc; + } + break; + } + case kpidPosixAttrib: prop = item.Mode; 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; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr<ISequentialInStream> inStream(streamSpec); + streamSpec->SetStream(_stream); + + for (i = 0; i < numItems; i++) + { + lps->InSize = lps->OutSize = currentTotalSize; + RINOK(lps->SetCur()); + CMyComPtr<ISequentialOutStream> outStream; + 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, &outStream, askMode)); + currentTotalSize += item.Size; + if (item.IsDir()) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); + continue; + } + if (!testMode && !outStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + if (testMode) + { + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); + continue; + } + RINOK(_stream->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL)); + streamSpec->Init(item.Size); + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + outStream.Release(); + RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ? + NArchive::NExtract::NOperationResult::kOK: + NArchive::NExtract::NOperationResult::kDataError)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + const CItemEx &item = _items[index]; + return CreateLimitedInStream(_stream, item.GetDataPosition(), item.Size, stream); + COM_TRY_END +} + +static IInArchive *CreateArc() { return new NArchive::NCpio::CHandler; } + +static CArcInfo g_ArcInfo = + { L"Cpio", L"cpio", 0, 0xED, { 0 }, 0, false, CreateArc, 0 }; + +REGISTER_ARC(Cpio) + +}} diff --git a/CPP/7zip/Archive/DebHandler.cpp b/CPP/7zip/Archive/DebHandler.cpp index fc962df3..0381e0fd 100755 --- a/CPP/7zip/Archive/DebHandler.cpp +++ b/CPP/7zip/Archive/DebHandler.cpp @@ -30,7 +30,7 @@ namespace NHeader { const int kSignatureLen = 8; - const char *kSignature = "!<arch>\n"; + const char *kSignature = "!<arch>\n"; const int kNameSize = 16; const int kTimeSize = 12; @@ -53,20 +53,15 @@ namespace NHeader const int kHeaderSize = kNameSize + kTimeSize + 6 + 6 + kModeSize + kSizeSize + 1 + 1; } -class CItem +struct CItem { -public: AString Name; UInt64 Size; UInt32 MTime; UInt32 Mode; -}; -class CItemEx: public CItem -{ -public: - UInt64 HeaderPosition; - UInt64 GetDataPosition() const { return HeaderPosition + NHeader::kHeaderSize; }; + UInt64 HeaderPos; + UInt64 GetDataPos() const { return HeaderPos + NHeader::kHeaderSize; }; // UInt64 GetFullSize() const { return NFileHeader::kRecordSize + Size; }; }; @@ -75,12 +70,11 @@ class CInArchive CMyComPtr<IInStream> m_Stream; UInt64 m_Position; - HRESULT GetNextItemReal(bool &filled, CItemEx &itemInfo); - HRESULT Skeep(UInt64 numBytes); + HRESULT GetNextItemReal(bool &filled, CItem &itemInfo); public: HRESULT Open(IInStream *inStream); - HRESULT GetNextItem(bool &filled, CItemEx &itemInfo); - HRESULT SkeepData(UInt64 dataSize); + HRESULT GetNextItem(bool &filled, CItem &itemInfo); + HRESULT SkipData(UInt64 dataSize); }; HRESULT CInArchive::Open(IInStream *inStream) @@ -151,7 +145,7 @@ static bool DecimalToNumber32(const char *s, int size, UInt32 &res) #define RIF(x) { if (!(x)) return S_FALSE; } -HRESULT CInArchive::GetNextItemReal(bool &filled, CItemEx &item) +HRESULT CInArchive::GetNextItemReal(bool &filled, CItem &item) { filled = false; @@ -159,7 +153,7 @@ HRESULT CInArchive::GetNextItemReal(bool &filled, CItemEx &item) const char *cur = header; size_t processedSize = sizeof(header); - item.HeaderPosition = m_Position; + item.HeaderPos = m_Position; RINOK(ReadStream(m_Stream, header, &processedSize)); m_Position += processedSize; if (processedSize != sizeof(header)) @@ -191,7 +185,7 @@ HRESULT CInArchive::GetNextItemReal(bool &filled, CItemEx &item) return S_OK; } -HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) +HRESULT CInArchive::GetNextItem(bool &filled, CItem &item) { for (;;) { @@ -202,38 +196,26 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) return S_OK; if (item.Size != 4) return S_OK; - SkeepData(item.Size); + SkipData(item.Size); } } -HRESULT CInArchive::Skeep(UInt64 numBytes) +HRESULT CInArchive::SkipData(UInt64 dataSize) { - UInt64 newPostion; - RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion)); - m_Position += numBytes; - if (m_Position != newPostion) - return E_FAIL; - return S_OK; + return m_Stream->Seek((dataSize + 1) & (~((UInt64)0x1)), STREAM_SEEK_CUR, &m_Position); } -HRESULT CInArchive::SkeepData(UInt64 dataSize) -{ - return Skeep((dataSize + 1) & (~((UInt64)0x1))); -} - - class CHandler: public IInArchive, + public IInArchiveGetStream, public CMyUnknownImp { + CObjectVector<CItem> _items; + CMyComPtr<IInStream> _stream; public: - MY_UNKNOWN_IMP1(IInArchive) - + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) - -private: - CObjectVector<CItemEx> _items; - CMyComPtr<IInStream> _inStream; + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; @@ -241,7 +223,6 @@ STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, { NULL, kpidMTime, VT_FILETIME} }; @@ -268,7 +249,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, for (;;) { - CItemEx item; + CItem item; bool filled; HRESULT result = archive.GetNextItem(filled, item); if (result == S_FALSE) @@ -278,14 +259,14 @@ STDMETHODIMP CHandler::Open(IInStream *stream, if (!filled) break; _items.Add(item); - archive.SkeepData(item.Size); + archive.SkipData(item.Size); if (openArchiveCallback != NULL) { UInt64 numFiles = _items.Size(); RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); } } - _inStream = stream; + _stream = stream; } return S_OK; COM_TRY_END @@ -293,7 +274,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, STDMETHODIMP CHandler::Close() { - _inStream.Release(); + _stream.Release(); _items.Clear(); return S_OK; } @@ -308,7 +289,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { COM_TRY_BEGIN NWindows::NCOM::CPropVariant prop; - const CItemEx &item = _items[index]; + const CItem &item = _items[index]; switch(propID) { @@ -350,7 +331,6 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, extractCallback->SetTotal(totalSize); UInt64 currentTotalSize = 0; - UInt64 currentItemSize; NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; @@ -361,9 +341,9 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<ISequentialInStream> inStream(streamSpec); - streamSpec->SetStream(_inStream); + streamSpec->SetStream(_stream); - for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) + for (i = 0; i < numItems; i++) { lps->InSize = lps->OutSize = currentTotalSize; RINOK(lps->SetCur()); @@ -372,14 +352,9 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; Int32 index = allFilesMode ? i : indices[i]; - const CItemEx &item = _items[index]; + const CItem &item = _items[index]; RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - currentItemSize = item.Size; - - - - - + currentTotalSize += item.Size; if (!testMode && (!realOutStream)) continue; @@ -389,7 +364,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); continue; } - RINOK(_inStream->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL)); + RINOK(_stream->Seek(item.GetDataPos(), STREAM_SEEK_SET, NULL)); streamSpec->Init(item.Size); RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); realOutStream.Release(); @@ -401,10 +376,18 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, COM_TRY_END } +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + const CItem &item = _items[index]; + return CreateLimitedInStream(_stream, item.GetDataPos(), item.Size, stream); + COM_TRY_END +} + static IInArchive *CreateArc() { return new NArchive::NDeb::CHandler; } static CArcInfo g_ArcInfo = - { L"Deb", L"deb", 0, 0xEC, { '!', '<', 'a', 'r', 'c', 'h', '>', '\n' }, 8, false, CreateArc, 0 }; + { L"Deb", L"deb", 0, 0xEC, { '!', '<', 'a', 'r', 'c', 'h', '>', '\n' }, 8, false, CreateArc, 0 }; REGISTER_ARC(Deb) diff --git a/CPP/7zip/Archive/DllExports2.cpp b/CPP/7zip/Archive/DllExports2.cpp index 545fcbd3..fd8bff28 100755 --- a/CPP/7zip/Archive/DllExports2.cpp +++ b/CPP/7zip/Archive/DllExports2.cpp @@ -7,10 +7,7 @@ #include "../../Common/Types.h" #include "../../Windows/PropVariant.h" #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) -extern "C" -{ #include "../../../C/Alloc.h" -} #endif #include "IArchive.h" diff --git a/CPP/7zip/Archive/ElfHandler.cpp b/CPP/7zip/Archive/ElfHandler.cpp index cac7c3ad..66b18e7a 100755 --- a/CPP/7zip/Archive/ElfHandler.cpp +++ b/CPP/7zip/Archive/ElfHandler.cpp @@ -17,8 +17,6 @@ #include "../Compress/CopyCoder.h" -#include "Common/DummyOutStream.h" - static UInt16 Get16(const Byte *p, int be) { if (be) return GetBe16(p); return GetUi16(p); } static UInt32 Get32(const Byte *p, int be) { if (be) return GetBe32(p); return GetUi32(p); } static UInt64 Get64(const Byte *p, int be) { if (be) return GetBe64(p); return GetUi64(p); } @@ -28,11 +26,11 @@ using namespace NWindows; namespace NArchive { namespace NElf { -#define ELF_CLASS_32 1 -#define ELF_CLASS_64 2 +#define ELF_CLASS_32 1 +#define ELF_CLASS_64 2 -#define ELF_DATA_2LSB 1 -#define ELF_DATA_2MSB 2 +#define ELF_DATA_2LSB 1 +#define ELF_DATA_2MSB 2 #define NUM_SCAN_SECTIONS_MAX (1 << 6) @@ -321,7 +319,7 @@ public: INTERFACE_IInArchive(;) }; -#define ELF_PT_PHDR 6 +#define ELF_PT_PHDR 6 bool CHandler::Parse(const Byte *buf, UInt32 size) { @@ -498,9 +496,6 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, CMyComPtr<ISequentialInStream> inStream(streamSpec); streamSpec->SetStream(_inStream); - CDummyOutStream *outStreamSpec = new CDummyOutStream; - CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); - for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) { lps->InSize = lps->OutSize = currentTotalSize; @@ -511,20 +506,17 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, UInt32 index = allFilesMode ? i : indices[i]; const CSegment &item = _sections[index]; currentItemSize = item.PSize; - { - CMyComPtr<ISequentialOutStream> realOutStream; - RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - if (!testMode && (!realOutStream)) - continue; - outStreamSpec->SetStream(realOutStream); - outStreamSpec->Init(); - } + + CMyComPtr<ISequentialOutStream> outStream; + RINOK(extractCallback->GetStream(index, &outStream, askMode)); + if (!testMode && !outStream) + continue; RINOK(extractCallback->PrepareOperation(askMode)); RINOK(_inStream->Seek(item.Offset, STREAM_SEEK_SET, NULL)); streamSpec->Init(currentItemSize); RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); - outStreamSpec->ReleaseStream(); + outStream.Release(); RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == currentItemSize ? NArchive::NExtract::NOperationResult::kOK: NArchive::NExtract::NOperationResult::kDataError)); diff --git a/CPP/7zip/Archive/FatHandler.cpp b/CPP/7zip/Archive/FatHandler.cpp new file mode 100755 index 00000000..f07d4ccb --- /dev/null +++ b/CPP/7zip/Archive/FatHandler.cpp @@ -0,0 +1,983 @@ +// FatHandler.cpp + +#include "StdAfx.h" + +// #include <stdio.h> + +#include "../../../C/CpuArch.h" + +#include "Common/Buffer.h" +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/MyCom.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#include "Common/DummyOutStream.h" + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) + +#define PRF(x) /* x */ + +namespace NArchive { +namespace NFat { + +static const UInt32 kFatItemUsedByDirMask = (UInt32)1 << 31; + +struct CHeader +{ + UInt32 NumSectors; + UInt16 NumReservedSectors; + Byte NumFats; + UInt32 NumFatSectors; + UInt32 RootDirSector; + UInt32 NumRootDirSectors; + UInt32 DataSector; + + UInt32 FatSize; + UInt32 BadCluster; + + Byte NumFatBits; + Byte SectorSizeLog; + Byte SectorsPerClusterLog; + Byte ClusterSizeLog; + + UInt16 SectorsPerTrack; + UInt16 NumHeads; + UInt32 NumHiddenSectors; + + bool VolFieldsDefined; + + UInt32 VolId; + // Byte VolName[11]; + // Byte FileSys[8]; + + // Byte OemName[5]; + Byte MediaType; + + // 32-bit FAT + UInt16 Flags; + UInt16 FsInfoSector; + UInt32 RootCluster; + + bool IsFat32() const { return NumFatBits == 32; } + UInt64 GetPhySize() const { return (UInt64)NumSectors << SectorSizeLog; } + UInt32 SectorSize() const { return (UInt32)1 << SectorSizeLog; } + UInt32 ClusterSize() const { return (UInt32)1 << ClusterSizeLog; } + UInt32 ClusterToSector(UInt32 c) const { return DataSector + ((c - 2) << SectorsPerClusterLog); } + UInt32 IsEoc(UInt32 c) const { return c > BadCluster; } + UInt32 IsEocAndUnused(UInt32 c) const { return c > BadCluster && (c & kFatItemUsedByDirMask) == 0; } + UInt32 IsValidCluster(UInt32 c) const { return c >= 2 && c < FatSize; } + UInt32 SizeToSectors(UInt32 size) const { return (size + SectorSize() - 1) >> SectorSizeLog; } + UInt32 CalcFatSizeInSectors() const { return SizeToSectors((FatSize * (NumFatBits / 4) + 1) / 2); } + + UInt32 GetFatSector() const + { + UInt32 index = (IsFat32() && (Flags & 0x80) != 0) ? (Flags & 0xF) : 0; + if (index > NumFats) + index = 0; + return NumReservedSectors + index * NumFatSectors; + } + + UInt64 GetFilePackSize(UInt32 unpackSize) const + { + UInt64 mask = ClusterSize() - 1; + return (unpackSize + mask) & ~mask; + } + + UInt32 GetNumClusters(UInt32 size) const + { return (UInt32)(((UInt64)size + ClusterSize() - 1) >> ClusterSizeLog); } + + bool Parse(const Byte *p); +}; + +static int GetLog(UInt32 num) +{ + for (int i = 0; i < 31; i++) + if (((UInt32)1 << i) == num) + return i; + return -1; +} + +bool CHeader::Parse(const Byte *p) +{ + if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA) + return false; + + int codeOffset = 0; + switch (p[0]) + { + case 0xE9: codeOffset = 3 + (Int16)Get16(p + 1); break; + case 0xEB: if (p[2] != 0x90) return false; codeOffset = 2 + (signed char)p[1]; break; + default: return false; + } + { + int s = GetLog(Get16(p + 11)); + if (s < 9 || s > 12) + return false; + SectorSizeLog = (Byte)s; + s = GetLog(p[13]); + if (s < 0) + return false; + SectorsPerClusterLog = (Byte)s; + ClusterSizeLog = SectorSizeLog + SectorsPerClusterLog; + } + + NumReservedSectors = Get16(p + 14); + if (NumReservedSectors == 0) + return false; + + NumFats = p[16]; + if (NumFats < 1 || NumFats > 4) + return false; + + UInt16 numRootDirEntries = Get16(p + 17); + if (numRootDirEntries == 0) + { + if (codeOffset < 90) + return false; + NumFatBits = 32; + NumRootDirSectors = 0; + } + else + { + if (codeOffset < 62) + return false; + NumFatBits = 0; + UInt32 mask = (1 << (SectorSizeLog - 5)) - 1; + if ((numRootDirEntries & mask) != 0) + return false; + NumRootDirSectors = (numRootDirEntries + mask) >> (SectorSizeLog - 5); + } + + NumSectors = Get16(p + 19); + if (NumSectors == 0) + NumSectors = Get32(p + 32); + else if (IsFat32()) + return false; + + MediaType = p[21]; + NumFatSectors = Get16(p + 22); + SectorsPerTrack = Get16(p + 24); + NumHeads = Get16(p + 26); + NumHiddenSectors = Get32(p + 28); + + // memcpy(OemName, p + 3, 5); + + p += 36; + if (IsFat32()) + { + if (NumFatSectors != 0) + return false; + NumFatSectors = Get32(p); + if (NumFatSectors >= (1 << 24)) + return false; + + Flags = Get16(p + 4); + if (Get16(p + 6) != 0) + return false; + RootCluster = Get32(p + 8); + FsInfoSector = Get16(p + 12); + for (int i = 16; i < 28; i++) + if (p[i] != 0) + return false; + p += 28; + } + + // DriveNumber = p[0]; + VolFieldsDefined = (p[2] == 0x29); // ExtendedBootSig + VolId = Get32(p + 3); + // memcpy(VolName, p + 7, 11); + // memcpy(FileSys, p + 18, 8); + + if (NumFatSectors == 0) + return false; + RootDirSector = NumReservedSectors + NumFatSectors * NumFats; + DataSector = RootDirSector + NumRootDirSectors; + if (NumSectors < DataSector) + return false; + UInt32 numDataSectors = NumSectors - DataSector; + UInt32 numClusters = numDataSectors >> SectorsPerClusterLog; + + BadCluster = 0x0FFFFFF7; + if (numClusters < 0xFFF5) + { + if (NumFatBits == 32) + return false; + NumFatBits = (numClusters < 0xFF5) ? 12: 16; + BadCluster &= ((1 << NumFatBits) - 1); + } + else if (NumFatBits != 32) + return false; + + FatSize = numClusters + 2; + if (FatSize > BadCluster || CalcFatSizeInSectors() > NumFatSectors) + return false; + return true; +} + +struct CItem +{ + UString UName; + char DosName[11]; + Byte CTime2; + UInt32 CTime; + UInt32 MTime; + UInt16 ADate; + Byte Attrib; + Byte Flags; + UInt32 Size; + UInt32 Cluster; + Int32 Parent; + + // NT uses Flags to store Low Case status + bool NameIsLow() const { return (Flags & 0x8) != 0; } + bool ExtIsLow() const { return (Flags & 0x10) != 0; } + bool IsDir() const { return (Attrib & 0x10) != 0; } + UString GetShortName() const; + UString GetName() const; + UString GetVolName() const; +}; + +static int CopyAndTrim(char *dest, const char *src, int size, bool toLower) +{ + int i; + memcpy(dest, src, size); + if (toLower) + for (i = 0; i < size; i++) + { + char c = dest[i]; + if (c >= 'A' && c <= 'Z') + dest[i] = c + 0x20; + } + for (i = size - 1; i >= 0 && dest[i] == ' '; i--); + return i + 1; +} + +static UString FatStringToUnicode(const char *s) +{ + return MultiByteToUnicodeString(s, CP_OEMCP); +} + +UString CItem::GetShortName() const +{ + char s[16]; + int i = CopyAndTrim(s, DosName, 8, NameIsLow()); + s[i++] = '.'; + int j = CopyAndTrim(s + i, DosName + 8, 3, ExtIsLow()); + if (j == 0) + j--; + s[i + j] = 0; + return FatStringToUnicode(s); +} + +UString CItem::GetName() const +{ + if (!UName.IsEmpty()) + return UName; + return GetShortName(); +} + +UString CItem::GetVolName() const +{ + if (!UName.IsEmpty()) + return UName; + char s[12]; + int i = CopyAndTrim(s, DosName, 11, false); + s[i] = 0; + return FatStringToUnicode(s); +} + +struct CDatabase +{ + CHeader Header; + CObjectVector<CItem> Items; + UInt32 *Fat; + CMyComPtr<IInStream> InStream; + IArchiveOpenCallback *OpenCallback; + + UInt32 NumFreeClusters; + bool VolItemDefined; + CItem VolItem; + UInt32 NumDirClusters; + CByteBuffer ByteBuf; + UInt64 NumCurUsedBytes; + + CDatabase(): Fat(0) {} + ~CDatabase() { ClearAndClose(); } + + void Clear(); + void ClearAndClose(); + HRESULT OpenProgressFat(bool changeTotal = true); + HRESULT OpenProgress(); + + UString GetItemPath(Int32 index) const; + HRESULT Open(); + HRESULT ReadDir(Int32 parent, UInt32 cluster, int level); + + UInt64 GetHeadersSize() const + { + return (UInt64)(Header.DataSector + (NumDirClusters << Header.SectorsPerClusterLog)) << Header.SectorSizeLog; + } + HRESULT SeekToSector(UInt32 sector); + HRESULT SeekToCluster(UInt32 cluster) { return SeekToSector(Header.ClusterToSector(cluster)); } +}; + +HRESULT CDatabase::SeekToSector(UInt32 sector) +{ + return InStream->Seek((UInt64)sector << Header.SectorSizeLog, STREAM_SEEK_SET, NULL); +} + +void CDatabase::Clear() +{ + VolItemDefined = false; + NumDirClusters = 0; + NumCurUsedBytes = 0; + + Items.Clear(); + delete []Fat; + Fat = 0; +} + +void CDatabase::ClearAndClose() +{ + Clear(); + InStream.Release(); +} + +HRESULT CDatabase::OpenProgressFat(bool changeTotal) +{ + if (!OpenCallback) + return S_OK; + if (changeTotal) + { + UInt64 numTotalBytes = (Header.CalcFatSizeInSectors() << Header.SectorSizeLog) + + ((UInt64)(Header.FatSize - NumFreeClusters) << Header.ClusterSizeLog); + RINOK(OpenCallback->SetTotal(NULL, &numTotalBytes)); + } + return OpenCallback->SetCompleted(NULL, &NumCurUsedBytes); +} + +HRESULT CDatabase::OpenProgress() +{ + if (!OpenCallback) + return S_OK; + UInt64 numItems = Items.Size(); + return OpenCallback->SetCompleted(&numItems, &NumCurUsedBytes); +} + +UString CDatabase::GetItemPath(Int32 index) const +{ + const CItem *item = &Items[index]; + UString name = item->GetName(); + for (;;) + { + index = item->Parent; + if (index < 0) + return name; + item = &Items[index]; + name = item->GetName() + WCHAR_PATH_SEPARATOR + name; + } +} + +static wchar_t *AddSubStringToName(wchar_t *dest, const Byte *p, int numChars) +{ + for (int i = 0; i < numChars; i++) + { + wchar_t c = Get16(p + i * 2); + if (c != 0 && c != 0xFFFF) + *dest++ = c; + } + *dest = 0; + return dest; +} + +HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level) +{ + int startIndex = Items.Size(); + if (startIndex >= (1 << 30) || level > 256) + return S_FALSE; + + UInt32 sectorIndex = 0; + UInt32 blockSize = Header.ClusterSize(); + bool clusterMode = (Header.IsFat32() || parent >= 0); + if (!clusterMode) + { + blockSize = Header.SectorSize(); + RINOK(SeekToSector(Header.RootDirSector)); + } + + ByteBuf.SetCapacity(blockSize); + UString curName; + int checkSum = -1; + int numLongRecords = -1; + for (UInt32 pos = blockSize;; pos += 32) + { + if (pos == blockSize) + { + pos = 0; + + if ((NumDirClusters & 0xFF) == 0) + { + RINOK(OpenProgress()); + } + + if (clusterMode) + { + if (Header.IsEoc(cluster)) + break; + if (!Header.IsValidCluster(cluster)) + return S_FALSE; + PRF(printf("\nCluster = %4X", cluster)); + RINOK(SeekToCluster(cluster)); + UInt32 newCluster = Fat[cluster]; + if ((newCluster & kFatItemUsedByDirMask) != 0) + return S_FALSE; + Fat[cluster] |= kFatItemUsedByDirMask; + cluster = newCluster; + NumDirClusters++; + NumCurUsedBytes += Header.ClusterSize(); + } + else if (sectorIndex++ >= Header.NumRootDirSectors) + break; + + RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize)); + } + const Byte *p = ByteBuf + pos; + if (p[0] == 0) + { + if (clusterMode && !Header.IsEoc(cluster)) + return S_FALSE; + break; + } + if (p[0] == 0xE5) + { + if (numLongRecords > 0) + return S_FALSE; + continue; + } + + Byte attrib = p[11]; + if ((attrib & 0x3F) == 0xF) + { + if (p[0] > 0x7F || Get16(p + 26) != 0) + return S_FALSE; + int longIndex = p[0] & 0x3F; + if (longIndex == 0) + return S_FALSE; + bool isLast = (p[0] & 0x40) != 0; + if (numLongRecords < 0) + { + if (!isLast) + return S_FALSE; + numLongRecords = longIndex; + } + else if (isLast || numLongRecords != longIndex) + return S_FALSE; + + numLongRecords--; + + if (p[12] == 0) + { + wchar_t nameBuf[14]; + wchar_t *dest; + + dest = AddSubStringToName(nameBuf, p + 1, 5); + dest = AddSubStringToName(dest, p + 14, 6); + AddSubStringToName(dest, p + 28, 2); + curName = nameBuf + curName; + if (isLast) + checkSum = p[13]; + if (checkSum != p[13]) + return S_FALSE; + } + } + else + { + if (numLongRecords > 0) + return S_FALSE; + CItem item; + memcpy(item.DosName, p, 11); + + if (checkSum >= 0) + { + Byte sum = 0; + for (int i = 0; i < 11; i++) + sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + (Byte)item.DosName[i]; + if (sum == checkSum) + item.UName = curName; + } + + if (item.DosName[0] == 5) + item.DosName[0] = (char)(Byte)0xE5; + item.Attrib = attrib; + item.Flags = p[12]; + item.Size = Get32(p + 28); + item.Cluster = Get16(p + 26) | ((UInt32)Get16(p + 20) << 16); + item.CTime = Get32(p + 14); + item.CTime2 = p[13]; + item.ADate = Get16(p + 18); + item.MTime = Get32(p + 22); + item.Parent = parent; + + if (attrib == 8) + { + VolItem = item; + VolItemDefined = true; + } + else + if (memcmp(item.DosName, ". ", 11) != 0 && + memcmp(item.DosName, ".. ", 11) != 0) + { + if (!item.IsDir()) + NumCurUsedBytes += Header.GetFilePackSize(item.Size); + Items.Add(item); + PRF(printf("\n%7d: %S", Items.Size(), GetItemPath(Items.Size() - 1))); + } + numLongRecords = -1; + curName.Empty(); + checkSum = -1; + } + } + + int finishIndex = Items.Size(); + for (int i = startIndex; i < finishIndex; i++) + { + const CItem &item = Items[i]; + if (item.IsDir()) + { + PRF(printf("\n%S", GetItemPath(i))); + RINOK(CDatabase::ReadDir(i, item.Cluster, level + 1)); + } + } + return S_OK; +} + +HRESULT CDatabase::Open() +{ + Clear(); + bool numFreeClustersDefined = false; + { + static const UInt32 kHeaderSize = 512; + Byte buf[kHeaderSize]; + RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize)); + if (!Header.Parse(buf)) + return S_FALSE; + UInt64 fileSize; + RINOK(InStream->Seek(0, STREAM_SEEK_END, &fileSize)); + if (fileSize < Header.GetPhySize()) + return S_FALSE; + + if (Header.IsFat32()) + { + SeekToSector(Header.FsInfoSector); + RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize)); + if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA) + return S_FALSE; + if (Get32(buf) == 0x41615252 && Get32(buf + 484) == 0x61417272) + { + NumFreeClusters = Get32(buf + 488); + numFreeClustersDefined = (NumFreeClusters <= Header.FatSize); + } + } + } + + // numFreeClustersDefined = false; // to recalculate NumFreeClusters + if (!numFreeClustersDefined) + NumFreeClusters = 0; + + CByteBuffer byteBuf; + Fat = new UInt32[Header.FatSize]; + + RINOK(OpenProgressFat()); + RINOK(SeekToSector(Header.GetFatSector())); + if (Header.NumFatBits == 32) + { + const UInt32 kBufSize = (1 << 15); + byteBuf.SetCapacity(kBufSize); + for (UInt32 i = 0; i < Header.FatSize;) + { + UInt32 size = Header.FatSize - i; + const UInt32 kBufSize32 = kBufSize / 4; + if (size > kBufSize32) + size = kBufSize32; + UInt32 readSize = Header.SizeToSectors(size * 4) << Header.SectorSizeLog; + RINOK(ReadStream_FALSE(InStream, byteBuf, readSize)); + NumCurUsedBytes += readSize; + + const UInt32 *src = (const UInt32 *)(const Byte *)byteBuf; + UInt32 *dest = Fat + i; + if (numFreeClustersDefined) + for (UInt32 j = 0; j < size; j++) + dest[j] = Get32(src + j) & 0x0FFFFFFF; + else + { + UInt32 numFreeClusters = 0; + for (UInt32 j = 0; j < size; j++) + { + UInt32 v = Get32(src + j) & 0x0FFFFFFF; + numFreeClusters += (UInt32)(v - 1) >> 31; + dest[j] = v; + } + NumFreeClusters += numFreeClusters; + } + i += size; + if ((i & 0xFFFFF) == 0) + { + RINOK(OpenProgressFat(!numFreeClustersDefined)); + } + } + } + else + { + const UInt32 kBufSize = (UInt32)Header.CalcFatSizeInSectors() << Header.SectorSizeLog; + NumCurUsedBytes += kBufSize; + byteBuf.SetCapacity(kBufSize); + Byte *p = byteBuf; + RINOK(ReadStream_FALSE(InStream, p, kBufSize)); + UInt32 fatSize = Header.FatSize; + UInt32 *fat = &Fat[0]; + if (Header.NumFatBits == 16) + for (UInt32 j = 0; j < fatSize; j++) + fat[j] = Get16(p + j * 2); + else + for (UInt32 j = 0; j < fatSize; j++) + fat[j] = (Get16(p + j * 3 / 2) >> ((j & 1) << 2)) & 0xFFF; + + if (!numFreeClustersDefined) + { + UInt32 numFreeClusters = 0; + for (UInt32 i = 0; i < fatSize; i++) + numFreeClusters += (UInt32)(fat[i] - 1) >> 31; + NumFreeClusters = numFreeClusters; + } + } + + RINOK(OpenProgressFat()); + + if ((Fat[0] & 0xFF) != Header.MediaType) + return S_FALSE; + + return ReadDir(-1, Header.RootCluster, 0); +} + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp, + CDatabase +{ +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + *stream = 0; + const CItem &item = Items[index]; + CClusterInStream *streamSpec = new CClusterInStream; + CMyComPtr<ISequentialInStream> streamTemp = streamSpec; + streamSpec->Stream = InStream; + streamSpec->StartOffset = Header.DataSector << Header.SectorSizeLog; + streamSpec->BlockSizeLog = Header.ClusterSizeLog; + streamSpec->Size = item.Size; + + UInt32 numClusters = Header.GetNumClusters(item.Size); + streamSpec->Vector.Reserve(numClusters); + UInt32 cluster = item.Cluster; + UInt32 size = item.Size; + + if (size == 0) + { + if (cluster != 0) + return S_FALSE; + } + else + { + UInt32 clusterSize = Header.ClusterSize(); + for (;; size -= clusterSize) + { + if (!Header.IsValidCluster(cluster)) + return S_FALSE; + streamSpec->Vector.Add(cluster - 2); + cluster = Fat[cluster]; + if (size <= clusterSize) + break; + } + if (!Header.IsEocAndUnused(cluster)) + return S_FALSE; + } + RINOK(streamSpec->InitAndSeek()); + *stream = streamTemp.Detach(); + return S_OK; + COM_TRY_END +} + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidATime, VT_FILETIME}, + { NULL, kpidAttrib, VT_UI8}, + { NULL, kpidShortName, VT_BSTR} +}; + +enum +{ + kpidNumFats = kpidUserDefined + // kpidOemName, + // kpidVolName, + // kpidFileSysType +}; + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidFileSystem, VT_BSTR}, + { NULL, kpidClusterSize, VT_UI4}, + { NULL, kpidPhySize, VT_UI8}, + { NULL, kpidFreeSpace, VT_UI8}, + { NULL, kpidHeadersSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidVolumeName, VT_BSTR}, + + { L"FATs", kpidNumFats, VT_UI4}, + { NULL, kpidSectorSize, VT_UI4}, + { NULL, kpidId, VT_UI4}, + // { L"OEM Name", kpidOemName, VT_BSTR}, + // { L"Volume Name", kpidVolName, VT_BSTR}, + // { L"File System Type", kpidFileSysType, VT_BSTR} + // { NULL, kpidSectorsPerTrack, VT_UI4}, + // { NULL, kpidNumHeads, VT_UI4}, + // { NULL, kpidHiddenSectors, VT_UI4} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_WITH_NAME + +static void FatTimeToProp(UInt32 dosTime, UInt32 ms10, NWindows::NCOM::CPropVariant &prop) +{ + FILETIME localFileTime, utc; + if (NWindows::NTime::DosTimeToFileTime(dosTime, localFileTime)) + if (LocalFileTimeToFileTime(&localFileTime, &utc)) + { + UInt64 t64 = (((UInt64)utc.dwHighDateTime) << 32) + utc.dwLowDateTime; + t64 += ms10 * 100000; + utc.dwLowDateTime = (DWORD)t64; + utc.dwHighDateTime = (DWORD)(t64 >> 32); + prop = utc; + } +} + +/* +static void StringToProp(const Byte *src, int size, NWindows::NCOM::CPropVariant &prop) +{ + char dest[32]; + memcpy(dest, src, size); + dest[size] = 0; + prop = FatStringToUnicode(dest); +} + +#define STRING_TO_PROP(s, p) StringToProp(s, sizeof(s), prop) +*/ + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidFileSystem: + { + wchar_t s[32] = { L'F', L'A', L'T' }; + ConvertUInt32ToString(Header.NumFatBits, s + 3); + prop = s; + break; + } + case kpidClusterSize: prop = Header.ClusterSize(); break; + case kpidPhySize: prop = Header.GetPhySize(); break; + case kpidFreeSpace: prop = (UInt64)NumFreeClusters << Header.ClusterSizeLog; break; + case kpidHeadersSize: prop = GetHeadersSize(); break; + case kpidMTime: if (VolItemDefined) FatTimeToProp(VolItem.MTime, 0, prop); break; + case kpidVolumeName: if (VolItemDefined) prop = VolItem.GetVolName(); break; + case kpidNumFats: if (Header.NumFats != 2) prop = Header.NumFats; break; + case kpidSectorSize: prop = (UInt32)1 << Header.SectorSizeLog; break; + // case kpidSectorsPerTrack: prop = Header.SectorsPerTrack; break; + // case kpidNumHeads: prop = Header.NumHeads; break; + // case kpidOemName: STRING_TO_PROP(Header.OemName, prop); break; + case kpidId: if (Header.VolFieldsDefined) prop = Header.VolId; break; + // case kpidVolName: if (Header.VolFieldsDefined) STRING_TO_PROP(Header.VolName, prop); break; + // case kpidFileSysType: if (Header.VolFieldsDefined) STRING_TO_PROP(Header.FileSys, prop); break; + // case kpidHiddenSectors: prop = Header.NumHiddenSectors; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CItem &item = Items[index]; + switch(propID) + { + case kpidPath: prop = GetItemPath(index); break; + case kpidShortName: prop = item.GetShortName(); break; + case kpidIsDir: prop = item.IsDir(); break; + case kpidMTime: FatTimeToProp(item.MTime, 0, prop); break; + case kpidCTime: FatTimeToProp(item.CTime, item.CTime2, prop); break; + case kpidATime: FatTimeToProp(((UInt32)item.ADate << 16), 0, prop); break; + case kpidAttrib: prop = (UInt32)item.Attrib; break; + case kpidSize: if (!item.IsDir()) prop = item.Size; break; + case kpidPackSize: if (!item.IsDir()) prop = Header.GetFilePackSize(item.Size); break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + { + OpenCallback = callback; + InStream = stream; + HRESULT res; + try + { + res = CDatabase::Open(); + if (res == S_OK) + return S_OK; + } + catch(...) + { + Close(); + throw; + } + Close(); + return res; + } + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + ClearAndClose(); + return S_OK; +} + +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; + UInt32 i; + UInt64 totalSize = 0; + for (i = 0; i < numItems; i++) + { + const CItem &item = Items[allFilesMode ? i : indices[i]]; + if (!item.IsDir()) + totalSize += item.Size; + } + RINOK(extractCallback->SetTotal(totalSize)); + + UInt64 totalPackSize; + totalSize = totalPackSize = 0; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, false); + + CDummyOutStream *outStreamSpec = new CDummyOutStream; + CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); + + for (i = 0; i < numItems; i++) + { + lps->InSize = totalPackSize; + lps->OutSize = totalSize; + RINOK(lps->SetCur()); + CMyComPtr<ISequentialOutStream> realOutStream; + Int32 askMode = testMode ? + NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + const CItem &item = Items[index]; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + if (item.IsDir()) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); + continue; + } + + totalPackSize += Header.GetFilePackSize(item.Size); + totalSize += item.Size; + + if (!testMode && (!realOutStream)) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + + outStreamSpec->SetStream(realOutStream); + realOutStream.Release(); + outStreamSpec->Init(); + + int res = NArchive::NExtract::NOperationResult::kDataError; + CMyComPtr<ISequentialInStream> inStream; + HRESULT hres = GetStream(index, &inStream); + if (hres != S_FALSE) + { + RINOK(hres); + if (inStream) + { + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + if (copyCoderSpec->TotalSize == item.Size) + res = NArchive::NExtract::NOperationResult::kOK; + } + } + outStreamSpec->ReleaseStream(); + RINOK(extractCallback->SetOperationResult(res)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = Items.Size(); + return S_OK; +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"FAT", L"fat img", 0, 0xDA, { 0x55, 0xAA }, 2, false, CreateArc, 0 }; + +REGISTER_ARC(Fat) + +}} diff --git a/CPP/7zip/Archive/GZip/GZipHandler.cpp b/CPP/7zip/Archive/GZip/GZipHandler.cpp deleted file mode 100755 index 96ae85f1..00000000 --- a/CPP/7zip/Archive/GZip/GZipHandler.cpp +++ /dev/null @@ -1,284 +0,0 @@ -// GZipHandler.cpp - -#include "StdAfx.h" - -#include "GZipHandler.h" - -#include "Common/Defs.h" -#include "Common/StringConvert.h" -#include "Common/ComTry.h" -#include "Windows/PropVariant.h" -#include "Windows/Time.h" - -#include "../../ICoder.h" -#include "../../Common/ProgressUtils.h" -#include "../../Common/CreateCoder.h" -#include "../Common/OutStreamWithCRC.h" - -using namespace NWindows; - -namespace NArchive { -namespace NGZip { - -static const CMethodId kMethodId_Deflate = 0x040108; - -const wchar_t *kHostOS[] = -{ - L"FAT", - L"AMIGA", - L"VMS", - L"Unix", - L"VM_CMS", - L"Atari", // what if it's a minix filesystem? [cjh] - L"HPFS", // filesystem used by OS/2 (and NT 3.x) - L"Mac", - L"Z_System", - L"CPM", - L"TOPS20", // pkzip 2.50 NTFS - L"NTFS", // filesystem used by Windows NT - L"QDOS ", // SMS/QDOS - L"Acorn", // Archimedes Acorn RISC OS - L"VFAT", // filesystem used by Windows 95, NT - L"MVS", - L"BeOS", // hybrid POSIX/database filesystem - // BeBOX or PowerMac - L"Tandem", - L"THEOS" -}; - -static const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]); - -static const wchar_t *kUnknownOS = L"Unknown"; - -/* -enum // PropID -{ - kpidExtraIsPresent = kpidUserDefined, - kpidExtraFlags, - kpidIsText -}; -*/ - -STATPROPSTG kProps[] = -{ - { NULL, kpidPath, VT_BSTR}, - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, - { NULL, kpidMTime, VT_FILETIME}, - // { NULL, kpidMethod, VT_UI1}, - { NULL, kpidHostOS, VT_BSTR}, - { NULL, kpidCRC, VT_UI4} - // { L"Extra", kpidExtraIsPresent, VT_BOOL} - // { L"Extra flags", kpidExtraFlags, VT_UI1}, - // { L"Is Text", kpidIsText, VT_BOOL}, -}; - -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) -{ - COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - switch(propID) - { - case kpidPath: - if (m_Item.NameIsPresent()) - prop = MultiByteToUnicodeString(m_Item.Name, CP_ACP); - break; - case kpidMTime: - { - FILETIME utcTime; - if (m_Item.Time != 0) - { - NTime::UnixTimeToFileTime((UInt32)m_Item.Time, utcTime); - prop = utcTime; - } - else - { - // utcTime.dwLowDateTime = utcTime.dwHighDateTime = 0; - // prop = utcTime; - } - break; - } - case kpidSize: prop = UInt64(m_Item.UnPackSize32); break; - case kpidPackSize: prop = m_PackSize; break; - case kpidCommented: prop = m_Item.CommentIsPresent(); break; - case kpidHostOS: - prop = (m_Item.HostOS < kNumHostOSes) ? - kHostOS[m_Item.HostOS] : kUnknownOS; - break; - case kpidMethod: prop = m_Item.CompressionMethod; break; - case kpidCRC: prop = m_Item.FileCRC; break; - /* - case kpidExtraFlags: prop = m_Item.ExtraFlags; break; - case kpidIsText: prop = m_Item.IsText(); break; - case kpidExtraIsPresent: prop = m_Item.ExtraFieldIsPresent(); break; - */ - } - prop.Detach(value); - return S_OK; - COM_TRY_END -} - -STDMETHODIMP CHandler::Open(IInStream *inStream, - const UInt64 * /* maxCheckStartPosition */, - IArchiveOpenCallback * /* openArchiveCallback */) -{ - COM_TRY_BEGIN - try - { - CInArchive archive; - RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition)); - RINOK(archive.ReadHeader(inStream, m_Item)); - m_DataOffset = archive.GetOffset(); - UInt64 newPosition; - RINOK(inStream->Seek(-8, STREAM_SEEK_END, &newPosition)); - m_PackSize = newPosition - (m_StreamStartPosition + m_DataOffset); - if (archive.ReadPostHeader(inStream, m_Item) != S_OK) - return S_FALSE; - m_Stream = inStream; - } - catch(...) - { - return S_FALSE; - } - return S_OK; - COM_TRY_END -} - -STDMETHODIMP CHandler::Close() -{ - m_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) - return E_INVALIDARG; - if (indices[0] != 0) - return E_INVALIDARG; - } - - bool testMode = (_aTestMode != 0); - - extractCallback->SetTotal(m_PackSize); - - UInt64 currentTotalPacked = 0; - - RINOK(extractCallback->SetCompleted(¤tTotalPacked)); - CMyComPtr<ISequentialOutStream> realOutStream; - Int32 askMode; - 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); - - COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; - CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); - outStreamSpec->SetStream(realOutStream); - outStreamSpec->Init(); - realOutStream.Release(); - - CLocalProgress *lps = new CLocalProgress; - CMyComPtr<ICompressProgressInfo> progress = lps; - lps->Init(extractCallback, true); - - CMyComPtr<ICompressCoder> deflateDecoder; - bool firstItem = true; - RINOK(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL)); - Int32 opRes; - for (;;) - { - lps->InSize = currentTotalPacked; - lps->OutSize = outStreamSpec->GetSize(); - - CInArchive archive; - CItem item; - HRESULT result = archive.ReadHeader(m_Stream, item); - if (result != S_OK) - { - if (firstItem) - return E_FAIL; - opRes = NArchive::NExtract::NOperationResult::kOK; - break; - } - firstItem = false; - - UInt64 dataStartPos; - RINOK(m_Stream->Seek(0, STREAM_SEEK_CUR, &dataStartPos)); - - outStreamSpec->InitCRC(); - - if (item.CompressionMethod != NFileHeader::NCompressionMethod::kDeflate) - { - opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; - break; - } - - if (!deflateDecoder) - { - RINOK(CreateCoder( - EXTERNAL_CODECS_VARS - kMethodId_Deflate, deflateDecoder, false)); - if (!deflateDecoder) - { - opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; - break; - } - } - result = deflateDecoder->Code(m_Stream, outStream, NULL, NULL, progress); - if (result != S_OK) - { - if (result != S_FALSE) - return result; - opRes = NArchive::NExtract::NOperationResult::kDataError; - break; - } - - CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize; - RINOK(deflateDecoder.QueryInterface(IID_ICompressGetInStreamProcessedSize, - &getInStreamProcessedSize)); - UInt64 packSize; - RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&packSize)); - UInt64 pos; - RINOK(m_Stream->Seek(dataStartPos + packSize, STREAM_SEEK_SET, &pos)); - - currentTotalPacked = pos - m_StreamStartPosition; - - CItem postItem; - if (archive.ReadPostHeader(m_Stream, postItem) != S_OK) - return E_FAIL; - if((outStreamSpec->GetCRC() != postItem.FileCRC)) - { - opRes = NArchive::NExtract::NOperationResult::kCRCError; - break; - } - } - outStream.Release(); - return extractCallback->SetOperationResult(opRes); - COM_TRY_END -} - -IMPL_ISetCompressCodecsInfo - -}} diff --git a/CPP/7zip/Archive/GZip/GZipHandler.h b/CPP/7zip/Archive/GZip/GZipHandler.h deleted file mode 100755 index 49a01a8d..00000000 --- a/CPP/7zip/Archive/GZip/GZipHandler.h +++ /dev/null @@ -1,63 +0,0 @@ -// GZip/Handler.h - -#ifndef __GZIP_HANDLER_H -#define __GZIP_HANDLER_H - -#include "Common/MyCom.h" - -#include "../IArchive.h" - -#include "../../Common/CreateCoder.h" - -#include "GZipIn.h" -#include "GZipUpdate.h" - -namespace NArchive { -namespace NGZip { - -class CHandler: - public IInArchive, - public IOutArchive, - public ISetProperties, - PUBLIC_ISetCompressCodecsInfo - public CMyUnknownImp -{ -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(); } - -private: - NArchive::NGZip::CItem m_Item; - UInt64 m_StreamStartPosition; - UInt64 m_DataOffset; - UInt64 m_PackSize; - CMyComPtr<IInStream> m_Stream; - CCompressionMethodMode m_Method; - UInt32 m_Level; - - DECL_EXTERNAL_CODECS_VARS - - void InitMethodProperties() - { - m_Method.NumMatchFinderCyclesDefined = false; - m_Level = m_Method.NumPasses = m_Method.NumFastBytes = - m_Method.NumMatchFinderCycles = m_Method.Algo = 0xFFFFFFFF; - } -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/GZip/GZipHandlerOut.cpp b/CPP/7zip/Archive/GZip/GZipHandlerOut.cpp deleted file mode 100755 index bcbfc7e2..00000000 --- a/CPP/7zip/Archive/GZip/GZipHandlerOut.cpp +++ /dev/null @@ -1,202 +0,0 @@ -// GZipHandlerOut.cpp - -#include "StdAfx.h" - -#include "Common/StringConvert.h" -#include "Common/StringToInt.h" - -#include "Windows/PropVariant.h" -#include "Windows/Time.h" - -#include "../../Compress/CopyCoder.h" - -#include "../Common/ParseProperties.h" - -#include "GZipHandler.h" -#include "GZipUpdate.h" - -using namespace NWindows; -using namespace NTime; - -namespace NArchive { -namespace NGZip { - -static const UInt32 kAlgoX1 = 0; -static const UInt32 kAlgoX5 = 1; - -static const UInt32 kNumPassesX1 = 1; -static const UInt32 kNumPassesX7 = 3; -static const UInt32 kNumPassesX9 = 10; - -static const UInt32 kNumFastBytesX1 = 32; -static const UInt32 kNumFastBytesX7 = 64; -static const UInt32 kNumFastBytesX9 = 128; - - -STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) -{ - *timeType = 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; - - UInt64 size; - Int32 newData; - Int32 newProperties; - UInt32 indexInArchive; - UInt32 itemIndex = 0; - if (!updateCallback) - return E_FAIL; - RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProperties, &indexInArchive)); - - CItem newItem = m_Item; - newItem.ExtraFlags = 0; - newItem.Flags = 0; - if (IntToBool(newProperties)) - { - FILETIME utcTime; - UString name; - { - NCOM::CPropVariant prop; - RINOK(updateCallback->GetProperty(itemIndex, kpidMTime, &prop)); - if (prop.vt != VT_FILETIME) - return E_INVALIDARG; - utcTime = prop.filetime; - } - { - NCOM::CPropVariant prop; - RINOK(updateCallback->GetProperty(itemIndex, kpidPath, &prop)); - if (prop.vt == VT_EMPTY) - name.Empty(); - else if (prop.vt != VT_BSTR) - return E_INVALIDARG; - else - name = prop.bstrVal; - } - { - NCOM::CPropVariant prop; - RINOK(updateCallback->GetProperty(itemIndex, 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(!FileTimeToUnixTime(utcTime, newItem.Time)) - return E_INVALIDARG; - newItem.Name = UnicodeStringToMultiByte(name, CP_ACP); - int dirDelimiterPos = newItem.Name.ReverseFind(CHAR_PATH_SEPARATOR); - if (dirDelimiterPos >= 0) - newItem.Name = newItem.Name.Mid(dirDelimiterPos + 1); - - newItem.SetNameIsPresentFlag(!newItem.Name.IsEmpty()); - } - - if (IntToBool(newData)) - { - { - NCOM::CPropVariant prop; - RINOK(updateCallback->GetProperty(itemIndex, kpidSize, &prop)); - if (prop.vt != VT_UI8) - return E_INVALIDARG; - size = prop.uhVal.QuadPart; - } - newItem.UnPackSize32 = (UInt32)size; - - UInt32 level = m_Level; - if (level == 0xFFFFFFFF) - level = 5; - if (m_Method.NumPasses == 0xFFFFFFFF) - m_Method.NumPasses = (level >= 9 ? kNumPassesX9 : - (level >= 7 ? kNumPassesX7 : - kNumPassesX1)); - if (m_Method.NumFastBytes == 0xFFFFFFFF) - m_Method.NumFastBytes = (level >= 9 ? kNumFastBytesX9 : - (level >= 7 ? kNumFastBytesX7 : - kNumFastBytesX1)); - if (m_Method.Algo == 0xFFFFFFFF) - m_Method.Algo = - (level >= 5 ? kAlgoX5 : - kAlgoX1); - - return UpdateArchive( - EXTERNAL_CODECS_VARS - m_Stream, size, outStream, newItem, m_Method, itemIndex, updateCallback); - } - - if (indexInArchive != 0) - return E_INVALIDARG; - - if (IntToBool(newProperties)) - { - COutArchive outArchive; - outArchive.Create(outStream); - outArchive.WriteHeader(newItem); - RINOK(m_Stream->Seek(m_StreamStartPosition + m_DataOffset, STREAM_SEEK_SET, NULL)); - } - else - { - RINOK(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL)); - } - return CopyStreams(m_Stream, outStream); -} - -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) -{ - InitMethodProperties(); - for (int i = 0; i < numProperties; i++) - { - UString name = names[i]; - name.MakeUpper(); - const PROPVARIANT &prop = values[i]; - if (name[0] == L'X') - { - UInt32 level = 9; - RINOK(ParsePropValue(name.Mid(1), prop, level)); - m_Level = level; - } - else if (name.Left(4) == L"PASS") - { - UInt32 num = kNumPassesX9; - RINOK(ParsePropValue(name.Mid(4), prop, num)); - m_Method.NumPasses = num; - } - else if (name.Left(2) == L"FB") - { - UInt32 num = kNumFastBytesX9; - RINOK(ParsePropValue(name.Mid(2), prop, num)); - m_Method.NumFastBytes = num; - } - else if (name.Left(2) == L"MC") - { - UInt32 num = 0xFFFFFFFF; - RINOK(ParsePropValue(name.Mid(2), prop, num)); - m_Method.NumMatchFinderCycles = num; - m_Method.NumMatchFinderCyclesDefined = true; - } - else if (name.Left(1) == L"A") - { - UInt32 num = kAlgoX5; - RINOK(ParsePropValue(name.Mid(1), prop, num)); - m_Method.Algo = num; - } - else - return E_INVALIDARG; - } - return S_OK; -} - -}} diff --git a/CPP/7zip/Archive/GZip/GZipHeader.cpp b/CPP/7zip/Archive/GZip/GZipHeader.cpp deleted file mode 100755 index 88b34e86..00000000 --- a/CPP/7zip/Archive/GZip/GZipHeader.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// Archive/GZip/Header.h - -#include "StdAfx.h" - -#include "GZipHeader.h" - -namespace NArchive { -namespace NGZip { - -extern UInt16 kSignature = 0x8B1F + 1; - -static class CMarkersInitializer -{ -public: - CMarkersInitializer() - { kSignature--; } -} g_MarkerInitializer; - -}} - diff --git a/CPP/7zip/Archive/GZip/GZipHeader.h b/CPP/7zip/Archive/GZip/GZipHeader.h deleted file mode 100755 index 010a60aa..00000000 --- a/CPP/7zip/Archive/GZip/GZipHeader.h +++ /dev/null @@ -1,85 +0,0 @@ -// Archive/GZip/Header.h - -#ifndef __ARCHIVE_GZIP_HEADER_H -#define __ARCHIVE_GZIP_HEADER_H - -#include "Common/Types.h" - -namespace NArchive { -namespace NGZip { - -extern UInt16 kSignature; -static const UInt32 kSignatureSize = 2; - -namespace NFileHeader -{ - /* - struct CBlock - { - UInt16 Id; - Byte CompressionMethod; - Byte Flags; - UInt32 Time; - Byte ExtraFlags; - Byte HostOS; - }; - */ - - namespace NFlags - { - const int kDataIsText = 1 << 0; - const int kHeaderCRCIsPresent = 1 << 1; - const int kExtraIsPresent = 1 << 2; - const int kNameIsPresent = 1 << 3; - const int kComentIsPresent = 1 << 4; - } - - namespace NExtraFlags - { - enum EEnum - { - kMaximum = 2, - kFastest = 4 - }; - } - - namespace NCompressionMethod - { - const Byte kDeflate = 8; - } - - namespace NHostOS - { - enum EEnum - { - kFAT = 0, // filesystem used by MS-DOS, OS/2, Win32 - // pkzip 2.50 (FAT / VFAT / FAT32 file systems) - kAMIGA = 1, - kVMS = 2, // VAX/VMS - kUnix = 3, - kVM_CMS = 4, - kAtari = 5, // what if it's a minix filesystem? [cjh] - kHPFS = 6, // filesystem used by OS/2 (and NT 3.x) - kMac = 7, - kZ_System = 8, - kCPM = 9, - kTOPS20 = 10, // pkzip 2.50 NTFS - kNTFS = 11, // filesystem used by Windows NT - kQDOS = 12, // SMS/QDOS - kAcorn = 13, // Archimedes Acorn RISC OS - kVFAT = 14, // filesystem used by Windows 95, NT - kMVS = 15, - kBeOS = 16, // hybrid POSIX/database filesystem - // BeBOX or PowerMac - kTandem = 17, - kTHEOS = 18, - - kUnknown = 255 - }; - const int kNumHostSystems = 19; - } -} - -}} - -#endif diff --git a/CPP/7zip/Archive/GZip/GZipIn.cpp b/CPP/7zip/Archive/GZip/GZipIn.cpp deleted file mode 100755 index d754c045..00000000 --- a/CPP/7zip/Archive/GZip/GZipIn.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// Archive/GZipIn.cpp - -#include "StdAfx.h" - -#include "GZipIn.h" - -#include "Common/Defs.h" -#include "Common/MyCom.h" -#include "Windows/Defs.h" - -#include "../../Common/StreamUtils.h" - -extern "C" -{ - #include "../../../../C/7zCrc.h" -} - -namespace NArchive { -namespace NGZip { - -HRESULT CInArchive::ReadBytes(ISequentialInStream *inStream, void *data, UInt32 size) -{ - RINOK(ReadStream_FALSE(inStream, data, size)); - m_Position += size; - return S_OK; -} - -HRESULT CInArchive::ReadByte(ISequentialInStream *inStream, Byte &value, UInt32 &crc) -{ - RINOK(ReadBytes(inStream, &value, 1)); - crc = CRC_UPDATE_BYTE(crc, value); - return S_OK; -} - -HRESULT CInArchive::ReadUInt16(ISequentialInStream *inStream, UInt16 &value, UInt32 &crc) -{ - value = 0; - for (int i = 0; i < 2; i++) - { - Byte b; - RINOK(ReadByte(inStream, b, crc)); - value |= (UInt16(b) << (8 * i)); - } - return S_OK; -} - -HRESULT CInArchive::ReadUInt32(ISequentialInStream *inStream, UInt32 &value, UInt32 &crc) -{ - value = 0; - for (int i = 0; i < 4; i++) - { - Byte b; - RINOK(ReadByte(inStream, b, crc)); - value |= (UInt32(b) << (8 * i)); - } - return S_OK; -} - -HRESULT CInArchive::ReadZeroTerminatedString(ISequentialInStream *inStream, AString &resString, UInt32 &crc) -{ - resString.Empty(); - for (;;) - { - Byte c; - RINOK(ReadByte(inStream, c, crc)); - if (c == 0) - return S_OK; - resString += char(c); - } -} - -HRESULT CInArchive::ReadHeader(ISequentialInStream *inStream, CItem &item) -{ - item.Clear(); - m_Position = 0; - - UInt16 signature; - UInt32 crc = CRC_INIT_VAL;; - RINOK(ReadUInt16(inStream, signature, crc)); - if (signature != kSignature) - return S_FALSE; - - RINOK(ReadByte(inStream, item.CompressionMethod, crc)); - RINOK(ReadByte(inStream, item.Flags, crc)); - RINOK(ReadUInt32(inStream, item.Time, crc)); - RINOK(ReadByte(inStream, item.ExtraFlags, crc)); - RINOK(ReadByte(inStream, item.HostOS, crc)); - - if (item.ExtraFieldIsPresent()) - { - UInt16 extraSize; - RINOK(ReadUInt16(inStream, extraSize, crc)); - item.Extra.SetCapacity(extraSize); - RINOK(ReadBytes(inStream, item.Extra, extraSize)); - crc = CrcUpdate(crc, item.Extra, extraSize); - } - if (item.NameIsPresent()) - RINOK(ReadZeroTerminatedString(inStream, item.Name, crc)); - if (item.CommentIsPresent()) - RINOK(ReadZeroTerminatedString(inStream, item.Comment, crc)); - if (item.HeaderCRCIsPresent()) - { - UInt16 headerCRC; - UInt32 dummy = 0; - RINOK(ReadUInt16(inStream, headerCRC, dummy)); - if ((UInt16)CRC_GET_DIGEST(crc) != headerCRC) - return S_FALSE; - } - return S_OK; -} - -HRESULT CInArchive::ReadPostHeader(ISequentialInStream *inStream, CItem &item) -{ - UInt32 dummy = 0; - RINOK(ReadUInt32(inStream, item.FileCRC, dummy)); - return ReadUInt32(inStream, item.UnPackSize32, dummy); -} - -}} diff --git a/CPP/7zip/Archive/GZip/GZipIn.h b/CPP/7zip/Archive/GZip/GZipIn.h deleted file mode 100755 index c2e07490..00000000 --- a/CPP/7zip/Archive/GZip/GZipIn.h +++ /dev/null @@ -1,30 +0,0 @@ -// Archive/GZipIn.h - -#ifndef __ARCHIVE_GZIP_IN_H -#define __ARCHIVE_GZIP_IN_H - -#include "GZipHeader.h" -#include "GZipItem.h" -#include "../../IStream.h" - -namespace NArchive { -namespace NGZip { - -class CInArchive -{ - UInt64 m_Position; - - HRESULT ReadBytes(ISequentialInStream *inStream, void *data, UInt32 size); - HRESULT ReadZeroTerminatedString(ISequentialInStream *inStream, AString &resString, UInt32 &crc); - HRESULT ReadByte(ISequentialInStream *inStream, Byte &value, UInt32 &crc); - HRESULT ReadUInt16(ISequentialInStream *inStream, UInt16 &value, UInt32 &crc); - HRESULT ReadUInt32(ISequentialInStream *inStream, UInt32 &value, UInt32 &crc); -public: - HRESULT ReadHeader(ISequentialInStream *inStream, CItem &item); - HRESULT ReadPostHeader(ISequentialInStream *inStream, CItem &item); - UInt64 GetOffset() const { return m_Position; } -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/GZip/GZipItem.h b/CPP/7zip/Archive/GZip/GZipItem.h deleted file mode 100755 index 678962a9..00000000 --- a/CPP/7zip/Archive/GZip/GZipItem.h +++ /dev/null @@ -1,59 +0,0 @@ -// Archive/GZipItem.h - -#ifndef __ARCHIVE_GZIP_ITEM_H -#define __ARCHIVE_GZIP_ITEM_H - -#include "Common/Types.h" -#include "Common/MyString.h" -#include "Common/Buffer.h" - -namespace NArchive { -namespace NGZip { - -class CItem -{ -private: - bool TestFlag(Byte flag) const { return ((Flags & flag) != 0); } -public: - Byte CompressionMethod; - Byte Flags; - UInt32 Time; - Byte ExtraFlags; - Byte HostOS; - UInt32 FileCRC; - UInt32 UnPackSize32; - - AString Name; - AString Comment; - CByteBuffer Extra; - - bool IsText() const - { return TestFlag(NFileHeader::NFlags::kDataIsText); } - bool HeaderCRCIsPresent() const - { return TestFlag(NFileHeader::NFlags::kHeaderCRCIsPresent); } - bool ExtraFieldIsPresent() const - { return TestFlag(NFileHeader::NFlags::kExtraIsPresent); } - bool NameIsPresent() const - { return TestFlag(NFileHeader::NFlags::kNameIsPresent); } - bool CommentIsPresent() const - { return TestFlag(NFileHeader::NFlags::kComentIsPresent); } - - void SetNameIsPresentFlag(bool nameIsPresent) - { - if (nameIsPresent) - Flags |= NFileHeader::NFlags::kNameIsPresent; - else - Flags &= (~NFileHeader::NFlags::kNameIsPresent); - } - - void Clear() - { - Name.Empty(); - Comment.Empty();; - Extra.SetCapacity(0); - } -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/GZip/GZipOut.cpp b/CPP/7zip/Archive/GZip/GZipOut.cpp deleted file mode 100755 index 3d0d4f7a..00000000 --- a/CPP/7zip/Archive/GZip/GZipOut.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// Archive/GZipOut.cpp - -#include "StdAfx.h" - -#include "GZipOut.h" - -#include "Windows/Defs.h" -#include "../../Common/StreamUtils.h" - -namespace NArchive { -namespace NGZip { - -HRESULT COutArchive::WriteBytes(const void *buffer, UInt32 size) -{ - return WriteStream(m_Stream, buffer, size); -} - -HRESULT COutArchive::WriteByte(Byte value) -{ - return WriteBytes(&value, 1); -} - -HRESULT COutArchive::WriteUInt16(UInt16 value) -{ - for (int i = 0; i < 2; i++) - { - RINOK(WriteByte((Byte)value)); - value >>= 8; - } - return S_OK; -} - -HRESULT COutArchive::WriteUInt32(UInt32 value) -{ - for (int i = 0; i < 4; i++) - { - RINOK(WriteByte((Byte)value)); - value >>= 8; - } - return S_OK; -} - -HRESULT COutArchive::WriteHeader(const CItem &item) -{ - RINOK(WriteUInt16(kSignature)); - RINOK(WriteByte(item.CompressionMethod)); - RINOK(WriteByte((Byte)(item.Flags & NFileHeader::NFlags::kNameIsPresent))); - RINOK(WriteUInt32(item.Time)); - RINOK(WriteByte(item.ExtraFlags)); - RINOK(WriteByte(item.HostOS)); - if (item.NameIsPresent()) - { - RINOK(WriteBytes((const char *)item.Name, item.Name.Length())); - RINOK(WriteByte(0)); - } - return S_OK; -} - -HRESULT COutArchive::WritePostHeader(const CItem &item) -{ - RINOK(WriteUInt32(item.FileCRC)); - return WriteUInt32(item.UnPackSize32); -} - -}} diff --git a/CPP/7zip/Archive/GZip/GZipOut.h b/CPP/7zip/Archive/GZip/GZipOut.h deleted file mode 100755 index a2ba2ebf..00000000 --- a/CPP/7zip/Archive/GZip/GZipOut.h +++ /dev/null @@ -1,29 +0,0 @@ -// Archive/GZipOut.h - -#ifndef __ARCHIVE_GZIP_OUT_H -#define __ARCHIVE_GZIP_OUT_H - -#include "Common/MyCom.h" -#include "GZipHeader.h" -#include "GZipItem.h" -#include "../../IStream.h" - -namespace NArchive { -namespace NGZip { - -class COutArchive -{ - CMyComPtr<ISequentialOutStream> m_Stream; - HRESULT WriteBytes(const void *buffer, UInt32 size); - HRESULT WriteByte(Byte value); - HRESULT WriteUInt16(UInt16 value); - HRESULT WriteUInt32(UInt32 value); -public: - void Create(ISequentialOutStream *outStream) { m_Stream = outStream; } - HRESULT WriteHeader(const CItem &item); - HRESULT WritePostHeader(const CItem &item); -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/GZip/GZipRegister.cpp b/CPP/7zip/Archive/GZip/GZipRegister.cpp deleted file mode 100755 index b4bc6ded..00000000 --- a/CPP/7zip/Archive/GZip/GZipRegister.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// GZipRegister.cpp - -#include "StdAfx.h" - -#include "../../Common/RegisterArc.h" - -#include "GZipHandler.h" -static IInArchive *CreateArc() { return new NArchive::NGZip::CHandler; } -#ifndef EXTRACT_ONLY -static IOutArchive *CreateArcOut() { return new NArchive::NGZip::CHandler; } -#else -#define CreateArcOut 0 -#endif - -static CArcInfo g_ArcInfo = - { L"GZip", L"gz gzip tgz tpz", L"* * .tar .tar", 0xEF, { 0x1F, 0x8B, 8 }, 3, true, CreateArc, CreateArcOut }; - -REGISTER_ARC(GZip) diff --git a/CPP/7zip/Archive/GZip/GZipUpdate.cpp b/CPP/7zip/Archive/GZip/GZipUpdate.cpp deleted file mode 100755 index f3a4d331..00000000 --- a/CPP/7zip/Archive/GZip/GZipUpdate.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// GZipUpdate.cpp - -#include "StdAfx.h" - -#include "Common/Defs.h" -#include "Common/StringConvert.h" - -#include "Windows/Defs.h" -#include "Windows/PropVariant.h" - -#include "../../ICoder.h" - -#include "../../Common/CreateCoder.h" -#include "../../Common/ProgressUtils.h" - -#include "../../Compress/CopyCoder.h" - -#include "../Common/InStreamWithCRC.h" - -#include "GZipUpdate.h" - -namespace NArchive { -namespace NGZip { - -static const CMethodId kMethodId_Deflate = 0x040108; - -static const Byte kHostOS = - #ifdef _WIN32 - NFileHeader::NHostOS::kFAT; - #else - NFileHeader::NHostOS::kUnix; - #endif - -HRESULT UpdateArchive( - DECL_EXTERNAL_CODECS_LOC_VARS - IInStream * /* inStream */, - UInt64 unpackSize, - ISequentialOutStream *outStream, - const CItem &newItem, - const CCompressionMethodMode &compressionMethod, - int indexInClient, - IArchiveUpdateCallback *updateCallback) -{ - UInt64 complexity = unpackSize; - - RINOK(updateCallback->SetTotal(complexity)); - - CMyComPtr<ICompressCoder> deflateEncoder; - - complexity = 0; - RINOK(updateCallback->SetCompleted(&complexity)); - - CMyComPtr<ISequentialInStream> fileInStream; - - RINOK(updateCallback->GetStream(indexInClient, &fileInStream)); - - CSequentialInStreamWithCRC *inStreamSpec = new CSequentialInStreamWithCRC; - CMyComPtr<ISequentialInStream> crcStream(inStreamSpec); - inStreamSpec->SetStream(fileInStream); - inStreamSpec->Init(); - - CLocalProgress *lps = new CLocalProgress; - CMyComPtr<ICompressProgressInfo> progress = lps; - lps->Init(updateCallback, true); - - COutArchive outArchive; - outArchive.Create(outStream); - - CItem item = newItem; - item.CompressionMethod = NFileHeader::NCompressionMethod::kDeflate; - item.ExtraFlags = 0; - item.HostOS = kHostOS; - - RINOK(outArchive.WriteHeader(item)); - - { - RINOK(CreateCoder( - EXTERNAL_CODECS_LOC_VARS - kMethodId_Deflate, deflateEncoder, true)); - if (!deflateEncoder) - return E_NOTIMPL; - - NWindows::NCOM::CPropVariant properties[] = - { - compressionMethod.Algo, - compressionMethod.NumPasses, - compressionMethod.NumFastBytes, - compressionMethod.NumMatchFinderCycles - }; - PROPID propIDs[] = - { - NCoderPropID::kAlgorithm, - NCoderPropID::kNumPasses, - NCoderPropID::kNumFastBytes, - NCoderPropID::kMatchFinderCycles - }; - int numProps = sizeof(propIDs) / sizeof(propIDs[0]); - if (!compressionMethod.NumMatchFinderCyclesDefined) - numProps--; - CMyComPtr<ICompressSetCoderProperties> setCoderProperties; - RINOK(deflateEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties)); - RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, numProps)); - } - RINOK(deflateEncoder->Code(crcStream, outStream, NULL, NULL, progress)); - - item.FileCRC = inStreamSpec->GetCRC(); - item.UnPackSize32 = (UInt32)inStreamSpec->GetSize(); - RINOK(outArchive.WritePostHeader(item)); - return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); -} - -}} diff --git a/CPP/7zip/Archive/GZip/GZipUpdate.h b/CPP/7zip/Archive/GZip/GZipUpdate.h deleted file mode 100755 index 231d7972..00000000 --- a/CPP/7zip/Archive/GZip/GZipUpdate.h +++ /dev/null @@ -1,37 +0,0 @@ -// GZip/Update.h - -#ifndef __GZIP_UPDATE_H -#define __GZIP_UPDATE_H - -#include "../IArchive.h" - -#include "../../Common/CreateCoder.h" - -#include "GZipOut.h" -#include "GZipItem.h" - -namespace NArchive { -namespace NGZip { - -struct CCompressionMethodMode -{ - UInt32 NumPasses; - UInt32 NumFastBytes; - UInt32 Algo; - bool NumMatchFinderCyclesDefined; - UInt32 NumMatchFinderCycles; -}; - -HRESULT UpdateArchive( - DECL_EXTERNAL_CODECS_LOC_VARS - IInStream *inStream, - UInt64 unpackSize, - ISequentialOutStream *outStream, - const CItem &newItem, - const CCompressionMethodMode &compressionMethod, - int indexInClient, - IArchiveUpdateCallback *updateCallback); - -}} - -#endif diff --git a/CPP/7zip/Archive/GZip/StdAfx.h b/CPP/7zip/Archive/GZip/StdAfx.h deleted file mode 100755 index e7fb6986..00000000 --- a/CPP/7zip/Archive/GZip/StdAfx.h +++ /dev/null @@ -1,8 +0,0 @@ -// StdAfx.h - -#ifndef __STDAFX_H -#define __STDAFX_H - -#include "../../../Common/MyWindows.h" - -#endif diff --git a/CPP/7zip/Archive/GzHandler.cpp b/CPP/7zip/Archive/GzHandler.cpp new file mode 100755 index 00000000..8f91003f --- /dev/null +++ b/CPP/7zip/Archive/GzHandler.cpp @@ -0,0 +1,820 @@ +// GzHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/ComTry.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" +#include "../Compress/DeflateDecoder.h" +#include "../Compress/DeflateEncoder.h" + +#include "Common/InStreamWithCRC.h" +#include "Common/OutStreamWithCRC.h" +#include "Common/ParseProperties.h" + +#define Get32(p) GetUi32(p) + +using namespace NWindows; + +namespace NArchive { +namespace NGz { + +static const UInt16 kSignature = 0x8B1F; + +namespace NHeader +{ + namespace NFlags + { + const Byte kIsText = 1 << 0; + const Byte kCrc = 1 << 1; + const Byte kExtra = 1 << 2; + const Byte kName = 1 << 3; + const Byte kComment = 1 << 4; + } + + namespace NExtraFlags + { + const Byte kMaximum = 2; + const Byte kFastest = 4; + } + + namespace NCompressionMethod + { + const Byte kDeflate = 8; + } + + namespace NHostOS + { + enum EEnum + { + kFAT = 0, + kAMIGA, + kVMS, + kUnix, + kVM_CMS, + kAtari, + kHPFS, + kMac, + kZ_System, + kCPM, + kTOPS20, + kNTFS, + kQDOS, + kAcorn, + kVFAT, + kMVS, + kBeOS, + kTandem, + + kUnknown = 255 + }; + } +} + +static const char *kHostOSes[] = +{ + "FAT", + "AMIGA", + "VMS", + "Unix", + "VM/CMS", + "Atari", + "HPFS", + "Macintosh", + "Z-System", + "CP/M", + "TOPS-20", + "NTFS", + "SMS/QDOS", + "Acorn", + "VFAT", + "MVS", + "BeOS", + "Tandem", + "OS/400", + "OS/X" +}; + +static const char *kUnknownOS = "Unknown"; + +class CItem +{ + bool TestFlag(Byte flag) const { return (Flags & flag) != 0; } +public: + Byte Method; + Byte Flags; + Byte ExtraFlags; + Byte HostOS; + UInt32 Time; + UInt32 Crc; + UInt32 Size32; + + AString Name; + AString Comment; + // CByteBuffer Extra; + + // bool IsText() const { return TestFlag(NHeader::NFlags::kIsText); } + bool HeaderCrcIsPresent() const { return TestFlag(NHeader::NFlags::kCrc); } + bool ExtraFieldIsPresent() const { return TestFlag(NHeader::NFlags::kExtra); } + bool NameIsPresent() const { return TestFlag(NHeader::NFlags::kName); } + bool CommentIsPresent() const { return TestFlag(NHeader::NFlags::kComment); } + + void Clear() + { + Name.Empty(); + Comment.Empty(); + // Extra.SetCapacity(0); + } + + HRESULT ReadHeader(NCompress::NDeflate::NDecoder::CCOMCoder *stream); + HRESULT ReadFooter1(NCompress::NDeflate::NDecoder::CCOMCoder *stream); + HRESULT ReadFooter2(ISequentialInStream *stream); + + HRESULT WriteHeader(ISequentialOutStream *stream); + HRESULT WriteFooter(ISequentialOutStream *stream); +}; + +static HRESULT ReadBytes(NCompress::NDeflate::NDecoder::CCOMCoder *stream, Byte *data, UInt32 size) +{ + for (UInt32 i = 0; i < size; i++) + data[i] = stream->ReadByte(); + return stream->InputEofError() ? S_FALSE : S_OK; +} + +static HRESULT SkipBytes(NCompress::NDeflate::NDecoder::CCOMCoder *stream, UInt32 size) +{ + for (UInt32 i = 0; i < size; i++) + stream->ReadByte(); + return stream->InputEofError() ? S_FALSE : S_OK; +} + +static HRESULT ReadUInt16(NCompress::NDeflate::NDecoder::CCOMCoder *stream, UInt16 &value /* , UInt32 &crc */) +{ + value = 0; + for (int i = 0; i < 2; i++) + { + Byte b = stream->ReadByte(); + if (stream->InputEofError()) + return S_FALSE; + // crc = CRC_UPDATE_BYTE(crc, b); + value |= (UInt16(b) << (8 * i)); + } + return S_OK; +} + +static HRESULT ReadString(NCompress::NDeflate::NDecoder::CCOMCoder *stream, AString &s, UInt32 limit /* , UInt32 &crc */) +{ + s.Empty(); + for (UInt32 i = 0; i < limit; i++) + { + Byte b = stream->ReadByte(); + if (stream->InputEofError()) + return S_FALSE; + // crc = CRC_UPDATE_BYTE(crc, b); + if (b == 0) + return S_OK; + s += (char)b; + } + return S_FALSE; +} + +HRESULT CItem::ReadHeader(NCompress::NDeflate::NDecoder::CCOMCoder *stream) +{ + Clear(); + + // Header-CRC field had another meaning in old version of gzip! + // UInt32 crc = CRC_INIT_VAL; + Byte buf[10]; + + RINOK(ReadBytes(stream, buf, 10)); + + if (GetUi16(buf) != kSignature) + return S_FALSE; + + Method = buf[2]; + + if (Method != NHeader::NCompressionMethod::kDeflate) + return S_FALSE; + + Flags = buf[3]; + Time = Get32(buf + 4); + ExtraFlags = buf[8]; + HostOS = buf[9]; + + // crc = CrcUpdate(crc, buf, 10); + + if (ExtraFieldIsPresent()) + { + UInt16 extraSize; + RINOK(ReadUInt16(stream, extraSize /* , crc */)); + RINOK(SkipBytes(stream, extraSize)); + // Extra.SetCapacity(extraSize); + // RINOK(ReadStream_FALSE(stream, Extra, extraSize)); + // crc = CrcUpdate(crc, Extra, extraSize); + } + if (NameIsPresent()) + RINOK(ReadString(stream, Name, (1 << 10) /* , crc */)); + if (CommentIsPresent()) + RINOK(ReadString(stream, Comment, (1 << 16) /* , crc */)); + + if (HeaderCrcIsPresent()) + { + UInt16 headerCRC; + // UInt32 dummy = 0; + RINOK(ReadUInt16(stream, headerCRC /* , dummy */)); + /* + if ((UInt16)CRC_GET_DIGEST(crc) != headerCRC) + return S_FALSE; + */ + } + return stream->InputEofError() ? S_FALSE : S_OK; +} + +HRESULT CItem::ReadFooter1(NCompress::NDeflate::NDecoder::CCOMCoder *stream) +{ + Byte buf[8]; + RINOK(ReadBytes(stream, buf, 8)); + Crc = Get32(buf); + Size32 = Get32(buf + 4); + return stream->InputEofError() ? S_FALSE : S_OK; +} + +HRESULT CItem::ReadFooter2(ISequentialInStream *stream) +{ + Byte buf[8]; + RINOK(ReadStream_FALSE(stream, buf, 8)); + Crc = Get32(buf); + Size32 = Get32(buf + 4); + return S_OK; +} + +HRESULT CItem::WriteHeader(ISequentialOutStream *stream) +{ + Byte buf[10]; + SetUi16(buf, kSignature); + buf[2] = Method; + buf[3] = Flags & NHeader::NFlags::kName; + // buf[3] |= NHeader::NFlags::kCrc; + SetUi32(buf + 4, Time); + buf[8] = ExtraFlags; + buf[9] = HostOS; + RINOK(WriteStream(stream, buf, 10)); + // crc = CrcUpdate(CRC_INIT_VAL, buf, 10); + if (NameIsPresent()) + { + // crc = CrcUpdate(crc, (const char *)Name, Name.Length() + 1); + RINOK(WriteStream(stream, (const char *)Name, Name.Length() + 1)); + } + // SetUi16(buf, (UInt16)CRC_GET_DIGEST(crc)); + // RINOK(WriteStream(stream, buf, 2)); + return S_OK; +} + +HRESULT CItem::WriteFooter(ISequentialOutStream *stream) +{ + Byte buf[8]; + SetUi32(buf, Crc); + SetUi32(buf + 4, Size32); + return WriteStream(stream, buf, 8); +} + +static const UInt32 kAlgoX1 = 0; +static const UInt32 kAlgoX5 = 1; + +static const UInt32 kNumPassesX1 = 1; +static const UInt32 kNumPassesX7 = 3; +static const UInt32 kNumPassesX9 = 10; + +static const UInt32 kNumFastBytesX1 = 32; +static const UInt32 kNumFastBytesX7 = 64; +static const UInt32 kNumFastBytesX9 = 128; + +struct CCompressMode +{ + UInt32 NumPasses; + UInt32 NumFastBytes; + UInt32 Algo; + UInt32 Mc; + bool McDefined; + + bool IsMaximum() const { return Algo > 0; } + + void Init() + { + NumPasses = NumFastBytes = Mc = Algo = 0xFFFFFFFF; + McDefined = false; + } + + void Normalize(UInt32 level) + { + if (level == 0xFFFFFFFF) + level = 5; + if (NumPasses == 0xFFFFFFFF) + NumPasses = + (level >= 9 ? kNumPassesX9 : + (level >= 7 ? kNumPassesX7 : + kNumPassesX1)); + if (NumFastBytes == 0xFFFFFFFF) + NumFastBytes = + (level >= 9 ? kNumFastBytesX9 : + (level >= 7 ? kNumFastBytesX7 : + kNumFastBytesX1)); + if (Algo == 0xFFFFFFFF) + Algo = (level >= 5 ? + kAlgoX5 : + kAlgoX1); + } +}; + +class CHandler: + public IInArchive, + public IArchiveOpenSeq, + public IOutArchive, + public ISetProperties, + public CMyUnknownImp +{ + CItem _item; + UInt64 _startPosition; + UInt64 _headerSize; + UInt64 _packSize; + bool _packSizeDefined; + CMyComPtr<IInStream> _stream; + CMyComPtr<ICompressCoder> _decoder; + NCompress::NDeflate::NDecoder::CCOMCoder *_decoderSpec; + + CCompressMode _method; + UInt32 _level; + + void InitMethodProperties() + { + _level = 0xFFFFFFFF; + _method.Init(); + } + +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(); + _decoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder; + _decoder = _decoderSpec; + } +}; + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidHostOS, VT_BSTR}, + { NULL, kpidCRC, VT_UI4} + // { NULL, kpidComment, VT_BSTR} +} +; + +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) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidPath: + if (_item.NameIsPresent()) + prop = MultiByteToUnicodeString(_item.Name, CP_ACP); + break; + // case kpidComment: if (_item.CommentIsPresent()) prop = MultiByteToUnicodeString(_item.Comment, CP_ACP); break; + case kpidMTime: + { + if (_item.Time != 0) + { + FILETIME utc; + NTime::UnixTimeToFileTime(_item.Time, utc); + prop = utc; + } + break; + } + case kpidSize: if (_stream) prop = (UInt64)_item.Size32; break; + case kpidPackSize: if (_packSizeDefined) prop = _packSize; break; + case kpidHostOS: prop = (_item.HostOS < sizeof(kHostOSes) / sizeof(kHostOSes[0])) ? + kHostOSes[_item.HostOS] : kUnknownOS; break; + case kpidCRC: if (_stream) prop = _item.Crc; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *) +{ + COM_TRY_BEGIN + HRESULT res; + try + { + RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_startPosition)); + res = OpenSeq(stream); + if (res == S_OK) + { + UInt64 endPos; + res = stream->Seek(-8, STREAM_SEEK_END, &endPos); + _packSize = endPos + 8 - _startPosition; + _packSizeDefined = true; + if (res == S_OK) + { + res = _item.ReadFooter2(stream); + _stream = stream; + } + } + } + catch(...) { res = S_FALSE; } + if (res != S_OK) + Close(); + return res; + COM_TRY_END +} + +STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) +{ + COM_TRY_BEGIN + HRESULT res; + try + { + Close(); + _decoderSpec->SetInStream(stream); + _decoderSpec->InitInStream(true); + res = _item.ReadHeader(_decoderSpec); + _headerSize = _decoderSpec->GetInputProcessedSize(); + } + catch(...) { res = S_FALSE; } + if (res != S_OK) + Close(); + return res; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _packSizeDefined = false; + _stream.Release(); + _decoderSpec->ReleaseInStream(); + 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(¤tTotalPacked)); + 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); + + COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; + CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); + outStreamSpec->SetStream(realOutStream); + outStreamSpec->Init(); + realOutStream.Release(); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, true); + + if (_stream) + { + RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); + _decoderSpec->InitInStream(true); + } + bool firstItem = true; + Int32 opRes; + for (;;) + { + lps->InSize = _packSize = _decoderSpec->GetInputProcessedSize(); + _packSizeDefined = true; + lps->OutSize = outStreamSpec->GetSize(); + RINOK(lps->SetCur()); + + CItem item; + if (!firstItem || _stream) + { + HRESULT result = item.ReadHeader(_decoderSpec); + if (result != S_OK) + { + if (result != S_FALSE) + return result; + opRes = firstItem ? + NArchive::NExtract::NOperationResult::kDataError : + NArchive::NExtract::NOperationResult::kOK; + break; + } + } + firstItem = false; + + UInt64 startOffset = outStreamSpec->GetSize(); + outStreamSpec->InitCRC(); + + HRESULT result = _decoderSpec->CodeResume(outStream, NULL, progress); + if (result != S_OK) + { + if (result != S_FALSE) + return result; + opRes = NArchive::NExtract::NOperationResult::kDataError; + break; + } + + _decoderSpec->AlignToByte(); + if (item.ReadFooter1(_decoderSpec) != S_OK) + { + opRes = NArchive::NExtract::NOperationResult::kDataError; + break; + } + if (item.Crc != outStreamSpec->GetCRC() || + item.Size32 != (UInt32)(outStreamSpec->GetSize() - startOffset)) + { + opRes = NArchive::NExtract::NOperationResult::kCRCError; + break; + } + } + outStream.Release(); + return extractCallback->SetOperationResult(opRes); + COM_TRY_END +} + +static const Byte kHostOS = + #ifdef _WIN32 + NHeader::NHostOS::kFAT; + #else + NHeader::NHostOS::kUnix; + #endif + +static HRESULT UpdateArchive( + ISequentialOutStream *outStream, + UInt64 unpackSize, + const CItem &newItem, + const CCompressMode &compressionMode, + IArchiveUpdateCallback *updateCallback) +{ + UInt64 complexity = 0; + RINOK(updateCallback->SetTotal(unpackSize)); + RINOK(updateCallback->SetCompleted(&complexity)); + + CMyComPtr<ISequentialInStream> fileInStream; + + RINOK(updateCallback->GetStream(0, &fileInStream)); + + CSequentialInStreamWithCRC *inStreamSpec = new CSequentialInStreamWithCRC; + CMyComPtr<ISequentialInStream> crcStream(inStreamSpec); + inStreamSpec->SetStream(fileInStream); + inStreamSpec->Init(); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(updateCallback, true); + + CItem item = newItem; + item.Method = NHeader::NCompressionMethod::kDeflate; + item.ExtraFlags = compressionMode.IsMaximum() ? + NHeader::NExtraFlags::kMaximum : + NHeader::NExtraFlags::kFastest; + + item.HostOS = kHostOS; + + RINOK(item.WriteHeader(outStream)); + + NCompress::NDeflate::NEncoder::CCOMCoder *deflateEncoderSpec = new NCompress::NDeflate::NEncoder::CCOMCoder; + CMyComPtr<ICompressCoder> deflateEncoder = deflateEncoderSpec; + { + NWindows::NCOM::CPropVariant props[] = + { + compressionMode.Algo, + compressionMode.NumPasses, + compressionMode.NumFastBytes, + compressionMode.Mc + }; + PROPID propIDs[] = + { + NCoderPropID::kAlgorithm, + NCoderPropID::kNumPasses, + NCoderPropID::kNumFastBytes, + NCoderPropID::kMatchFinderCycles + }; + int numProps = sizeof(propIDs) / sizeof(propIDs[0]); + if (!compressionMode.McDefined) + numProps--; + RINOK(deflateEncoderSpec->SetCoderProperties(propIDs, props, numProps)); + } + RINOK(deflateEncoder->Code(crcStream, outStream, NULL, NULL, progress)); + + item.Crc = inStreamSpec->GetCRC(); + item.Size32 = (UInt32)inStreamSpec->GetSize(); + RINOK(item.WriteFooter(outStream)); + return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); +} + +STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) +{ + *timeType = 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)); + + CItem newItem = _item; + newItem.ExtraFlags = 0; + newItem.Flags = 0; + if (IntToBool(newProps)) + { + { + FILETIME utcTime; + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(0, kpidMTime, &prop)); + if (prop.vt != VT_FILETIME) + return E_INVALIDARG; + utcTime = prop.filetime; + if (!NTime::FileTimeToUnixTime(utcTime, newItem.Time)) + return E_INVALIDARG; + } + { + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(0, kpidPath, &prop)); + if (prop.vt == VT_BSTR) + { + UString name = prop.bstrVal; + int dirDelimiterPos = name.ReverseFind(CHAR_PATH_SEPARATOR); + if (dirDelimiterPos >= 0) + name = name.Mid(dirDelimiterPos + 1); + newItem.Name = UnicodeStringToMultiByte(name, CP_ACP); + if (!newItem.Name.IsEmpty()) + newItem.Flags |= NHeader::NFlags::kName; + } + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + } + { + 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; + } + + _method.Normalize(_level); + return UpdateArchive(outStream, size, newItem, _method, updateCallback); + } + + if (indexInArchive != 0) + return E_INVALIDARG; + + if (!_stream) + return E_NOTIMPL; + + UInt64 offset = _startPosition; + if (IntToBool(newProps)) + { + newItem.WriteHeader(outStream); + offset += _headerSize; + } + RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); + return NCompress::CopyStream(_stream, outStream, NULL); +} + +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) +{ + InitMethodProperties(); + 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.Left(4) == L"PASS") + { + UInt32 num = kNumPassesX9; + RINOK(ParsePropValue(name.Mid(4), prop, num)); + _method.NumPasses = num; + } + else if (name.Left(2) == L"FB") + { + UInt32 num = kNumFastBytesX9; + RINOK(ParsePropValue(name.Mid(2), prop, num)); + _method.NumFastBytes = num; + } + else if (name.Left(2) == L"MC") + { + UInt32 num = 0xFFFFFFFF; + RINOK(ParsePropValue(name.Mid(2), prop, num)); + _method.Mc = num; + _method.McDefined = true; + } + else if (name.Left(1) == L"A") + { + UInt32 num = kAlgoX5; + RINOK(ParsePropValue(name.Mid(1), prop, num)); + _method.Algo = num; + } + 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"GZip", L"gz gzip tgz tpz", L"* * .tar .tar", 0xEF, { 0x1F, 0x8B, 8 }, 3, true, CreateArc, CreateArcOut }; + +REGISTER_ARC(GZip) + +}} diff --git a/CPP/7zip/Archive/IArchive.h b/CPP/7zip/Archive/IArchive.h index 88d6c408..85320276 100755 --- a/CPP/7zip/Archive/IArchive.h +++ b/CPP/7zip/Archive/IArchive.h @@ -3,8 +3,8 @@ #ifndef __IARCHIVE_H #define __IARCHIVE_H -#include "../IStream.h" #include "../IProgress.h" +#include "../IStream.h" #include "../PropID.h" #define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x) @@ -82,7 +82,6 @@ ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10) #define INTERFACE_IArchiveExtractCallback(x) \ INTERFACE_IProgress(x) \ - /* GetStream OUT: S_OK - OK, S_FALSE - skeep this file */ \ STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) x; \ STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \ STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \ @@ -139,6 +138,10 @@ ARCHIVE_INTERFACE(IInArchive, 0x60) INTERFACE_IInArchive(PURE) }; +ARCHIVE_INTERFACE(IArchiveOpenSeq, 0x61) +{ + STDMETHOD(OpenSeq)(ISequentialInStream *stream) PURE; +}; #define INTERFACE_IArchiveUpdateCallback(x) \ INTERFACE_IProgress(x); \ @@ -217,11 +220,14 @@ ARCHIVE_INTERFACE(ISetProperties, 0x03) { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kArcProps) -#define IMP_IInArchive_ArcProps_NO \ +#define IMP_IInArchive_ArcProps_NO_Table \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = 0; return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \ { return E_NOTIMPL; } \ + +#define IMP_IInArchive_ArcProps_NO \ + IMP_IInArchive_ArcProps_NO_Table \ STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \ { value->vt = VT_EMPTY; return S_OK; } diff --git a/CPP/7zip/Archive/Icons/fat.ico b/CPP/7zip/Archive/Icons/fat.ico Binary files differnew file mode 100755 index 00000000..882753ac --- /dev/null +++ b/CPP/7zip/Archive/Icons/fat.ico diff --git a/CPP/7zip/Archive/Icons/ntfs.ico b/CPP/7zip/Archive/Icons/ntfs.ico Binary files differnew file mode 100755 index 00000000..6b2aeb00 --- /dev/null +++ b/CPP/7zip/Archive/Icons/ntfs.ico diff --git a/CPP/7zip/Archive/Icons/vhd.ico b/CPP/7zip/Archive/Icons/vhd.ico Binary files differnew file mode 100755 index 00000000..33bed3c9 --- /dev/null +++ b/CPP/7zip/Archive/Icons/vhd.ico diff --git a/CPP/7zip/Archive/Icons/xar.ico b/CPP/7zip/Archive/Icons/xar.ico Binary files differindex 02707351..281aa7dc 100755 --- a/CPP/7zip/Archive/Icons/xar.ico +++ b/CPP/7zip/Archive/Icons/xar.ico diff --git a/CPP/7zip/Archive/Icons/xz.ico b/CPP/7zip/Archive/Icons/xz.ico Binary files differnew file mode 100755 index 00000000..02707351 --- /dev/null +++ b/CPP/7zip/Archive/Icons/xz.ico diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp index f0c926c4..ed8da189 100755 --- a/CPP/7zip/Archive/Iso/IsoHandler.cpp +++ b/CPP/7zip/Archive/Iso/IsoHandler.cpp @@ -46,9 +46,9 @@ STDMETHODIMP CHandler::Open(IInStream *stream, Close(); // try { - if(_archive.Open(stream) != S_OK) + if (_archive.Open(stream) != S_OK) return S_FALSE; - _inStream = stream; + _stream = stream; } // catch(...) { return S_FALSE; } return S_OK; @@ -58,7 +58,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, STDMETHODIMP CHandler::Close() { _archive.Clear(); - _inStream.Release(); + _stream.Release(); return S_OK; } @@ -160,7 +160,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, bool allFilesMode = (numItems == UInt32(-1)); if (allFilesMode) numItems = _archive.Refs.Size(); - if(numItems == 0) + if (numItems == 0) return S_OK; UInt64 totalSize = 0; UInt32 i; @@ -192,7 +192,10 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<ISequentialInStream> inStream(streamSpec); - streamSpec->SetStream(_inStream); + streamSpec->SetStream(_stream); + + CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream; + CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) { @@ -211,7 +214,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, { const CRef &ref = _archive.Refs[index]; const CDir &item = ref.Dir->_subItems[ref.Index]; - if(item.IsDir()) + if (item.IsDir()) { RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); @@ -231,16 +234,14 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, if (!testMode && (!realOutStream)) continue; RINOK(extractCallback->PrepareOperation(askMode)); - if (testMode) - { - RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); - continue; - } - RINOK(_inStream->Seek(blockIndex * _archive.BlockSize, STREAM_SEEK_SET, NULL)); - streamSpec->Init(currentItemSize); - RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); + outStreamSpec->SetStream(realOutStream); realOutStream.Release(); - RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == currentItemSize) ? + outStreamSpec->Init(currentItemSize); + RINOK(_stream->Seek(blockIndex * _archive.BlockSize, STREAM_SEEK_SET, NULL)); + streamSpec->Init(currentItemSize); + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + outStreamSpec->ReleaseStream(); + RINOK(extractCallback->SetOperationResult(outStreamSpec->IsFinishedOK() ? NArchive::NExtract::NOperationResult::kOK: NArchive::NExtract::NOperationResult::kDataError)); } @@ -248,4 +249,30 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, COM_TRY_END } +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + *stream = 0; + UInt64 blockIndex; + UInt64 currentItemSize; + if (index < (UInt32)_archive.Refs.Size()) + { + const CRef &ref = _archive.Refs[index]; + const CDir &item = ref.Dir->_subItems[ref.Index]; + if (item.IsDir()) + return S_FALSE; + currentItemSize = item.DataLength; + blockIndex = item.ExtentLocation; + } + else + { + int bootIndex = index - _archive.Refs.Size(); + const CBootInitialEntry &be = _archive.BootEntries[bootIndex]; + currentItemSize = _archive.GetBootItemSize(bootIndex); + blockIndex = be.LoadRBA; + } + return CreateLimitedInStream(_stream, blockIndex * _archive.BlockSize, currentItemSize, stream); + COM_TRY_END +} + }} diff --git a/CPP/7zip/Archive/Iso/IsoHandler.h b/CPP/7zip/Archive/Iso/IsoHandler.h index bb905a22..1dcade8f 100755 --- a/CPP/7zip/Archive/Iso/IsoHandler.h +++ b/CPP/7zip/Archive/Iso/IsoHandler.h @@ -1,4 +1,4 @@ -// Iso/Handler.h +// IsoHandler.h #ifndef __ISO_HANDLER_H #define __ISO_HANDLER_H @@ -6,26 +6,23 @@ #include "Common/MyCom.h" #include "../IArchive.h" -#include "IsoItem.h" #include "IsoIn.h" +#include "IsoItem.h" namespace NArchive { namespace NIso { class CHandler: public IInArchive, + public IInArchiveGetStream, public CMyUnknownImp { + CMyComPtr<IInStream> _stream; + CInArchive _archive; public: - MY_UNKNOWN_IMP1( - IInArchive - ) - + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) - -private: - CMyComPtr<IInStream> _inStream; - CInArchive _archive; + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; }} diff --git a/CPP/7zip/Archive/Iso/IsoIn.cpp b/CPP/7zip/Archive/Iso/IsoIn.cpp index dee23395..84143348 100755 --- a/CPP/7zip/Archive/Iso/IsoIn.cpp +++ b/CPP/7zip/Archive/Iso/IsoIn.cpp @@ -3,9 +3,6 @@ #include "StdAfx.h" #include "IsoIn.h" -#include "IsoHeader.h" - -#include "Windows/Defs.h" #include "../../Common/StreamUtils.h" @@ -35,13 +32,13 @@ void CInArchive::ReadBytes(Byte *data, UInt32 size) data[i] = ReadByte(); } -void CInArchive::Skeep(size_t size) +void CInArchive::Skip(size_t size) { while (size-- != 0) ReadByte(); } -void CInArchive::SkeepZeros(size_t size) +void CInArchive::SkipZeros(size_t size) { while (size-- != 0) { @@ -174,8 +171,8 @@ void CInArchive::ReadDirRecord2(CDirRecord &r, Byte len) ReadBytes((Byte *)r.FileId, idLen); int padSize = 1 - (idLen & 1); - // SkeepZeros(1 - (idLen & 1)); - Skeep(1 - (idLen & 1)); // it's bug in some cd's. Must be zeros + // SkipZeros(1 - (idLen & 1)); + Skip(1 - (idLen & 1)); // it's bug in some cd's. Must be zeros int curPos = 33 + idLen + padSize; if (curPos > len) @@ -199,7 +196,7 @@ void CInArchive::ReadVolumeDescriptor(CVolumeDescriptor &d) d.VolFlags = ReadByte(); ReadBytes(d.SystemId, sizeof(d.SystemId)); ReadBytes(d.VolumeId, sizeof(d.VolumeId)); - SkeepZeros(8); + SkipZeros(8); d.VolumeSpaceSize = ReadUInt32(); ReadBytes(d.EscapeSequence, sizeof(d.EscapeSequence)); d.VolumeSetSize = ReadUInt16(); @@ -223,9 +220,9 @@ void CInArchive::ReadVolumeDescriptor(CVolumeDescriptor &d) ReadDateTime(d.ExpirationTime); ReadDateTime(d.EffectiveTime); d.FileStructureVersion = ReadByte(); // = 1 - SkeepZeros(1); + SkipZeros(1); ReadBytes(d.ApplicationUse, sizeof(d.ApplicationUse)); - SkeepZeros(653); + SkipZeros(653); } static const Byte kSig_CD001[5] = { 'C', 'D', '0', '0', '1' }; @@ -371,7 +368,7 @@ HRESULT CInArchive::Open2() } else break; - SkeepZeros(0x800 - 7); + SkipZeros(0x800 - 7); continue; */ } @@ -382,7 +379,7 @@ HRESULT CInArchive::Open2() if (sig[0] == NVolDescType::kTerminator) { break; - // Skeep(0x800 - 7); + // Skip(0x800 - 7); // continue; } switch(sig[0]) diff --git a/CPP/7zip/Archive/Iso/IsoIn.h b/CPP/7zip/Archive/Iso/IsoIn.h index ce53a1e3..49687e27 100755 --- a/CPP/7zip/Archive/Iso/IsoIn.h +++ b/CPP/7zip/Archive/Iso/IsoIn.h @@ -3,13 +3,13 @@ #ifndef __ARCHIVE_ISO_IN_H #define __ARCHIVE_ISO_IN_H -#include "Common/MyCom.h" #include "Common/IntToString.h" +#include "Common/MyCom.h" #include "../../IStream.h" -#include "IsoItem.h" #include "IsoHeader.h" +#include "IsoItem.h" namespace NArchive { namespace NIso { @@ -159,8 +159,8 @@ struct CBootInitialEntry s += L"_"; if (BootMediaType >= kNumBootMediaTypes) { - wchar_t name[32]; - ConvertUInt64ToString(BootMediaType, name); + wchar_t name[16]; + ConvertUInt32ToString(BootMediaType, name); s += name; } else @@ -232,8 +232,8 @@ class CInArchive bool _bootIsDefined; CBootRecordDescriptor _bootDesc; - void Skeep(size_t size); - void SkeepZeros(size_t size); + void Skip(size_t size); + void SkipZeros(size_t size); Byte ReadByte(); void ReadBytes(Byte *data, UInt32 size); UInt16 ReadUInt16Spec(); diff --git a/CPP/7zip/Archive/Lzh/LzhCRC.cpp b/CPP/7zip/Archive/Lzh/LzhCRC.cpp deleted file mode 100755 index e299bf6c..00000000 --- a/CPP/7zip/Archive/Lzh/LzhCRC.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// LzhCRC.cpp - -#include "StdAfx.h" - -#include "LzhCRC.h" - -namespace NArchive { -namespace NLzh { - -static const UInt16 kCRCPoly = 0xA001; - -UInt16 CCRC::Table[256]; - -void CCRC::InitTable() -{ - for (UInt32 i = 0; i < 256; i++) - { - UInt32 r = i; - for (int j = 0; j < 8; j++) - if (r & 1) - r = (r >> 1) ^ kCRCPoly; - else - r >>= 1; - CCRC::Table[i] = (UInt16)r; - } -} - -class CCRCTableInit -{ -public: - CCRCTableInit() { CCRC::InitTable(); } -} g_CRCTableInit; - -void CCRC::Update(const void *data, size_t size) -{ - UInt16 v = _value; - const Byte *p = (const Byte *)data; - for (; size > 0; size--, p++) - v = (UInt16)(Table[((Byte)(v)) ^ *p] ^ (v >> 8)); - _value = v; -} - -}} diff --git a/CPP/7zip/Archive/Lzh/LzhCRC.h b/CPP/7zip/Archive/Lzh/LzhCRC.h deleted file mode 100755 index be2a4569..00000000 --- a/CPP/7zip/Archive/Lzh/LzhCRC.h +++ /dev/null @@ -1,27 +0,0 @@ -// LzhCRC.h - -#ifndef __LZH_CRC_H -#define __LZH_CRC_H - -#include <stddef.h> -#include "Common/Types.h" - -namespace NArchive { -namespace NLzh { - -class CCRC -{ - UInt16 _value; -public: - static UInt16 Table[256]; - static void InitTable(); - - CCRC(): _value(0){}; - void Init() { _value = 0; } - void Update(const void *data, size_t size); - UInt16 GetDigest() const { return _value; } -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Lzh/LzhHandler.cpp b/CPP/7zip/Archive/Lzh/LzhHandler.cpp deleted file mode 100755 index 66153f7a..00000000 --- a/CPP/7zip/Archive/Lzh/LzhHandler.cpp +++ /dev/null @@ -1,387 +0,0 @@ -// LzhHandler.cpp - -#include "StdAfx.h" - -#include "Common/ComTry.h" -#include "Common/Defs.h" -#include "Common/StringConvert.h" - -#include "Windows/PropVariant.h" -#include "Windows/Time.h" - -#include "LzhHandler.h" -#include "LzhOutStreamWithCRC.h" - -#include "../../ICoder.h" - -#include "../../Common/LimitedStreams.h" -#include "../../Common/ProgressUtils.h" - -#include "../../Compress/CopyCoder.h" -#include "../../Compress/LzhDecoder.h" - -#include "../Common/ItemNameUtils.h" - -using namespace NWindows; -using namespace NTime; - -namespace NArchive { -namespace NLzh{ - -struct COsPair -{ - Byte Id; - const wchar_t *Name; -}; - -COsPair g_OsPairs[] = -{ - { 'M', L"MS-DOS" }, - { '2', L"OS/2" }, - { '9', L"OS9" }, - { 'K', L"OS/68K" }, - { '3', L"OS/386" }, - { 'H', L"HUMAN" }, - { 'U', L"UNIX" }, - { 'C', L"CP/M" }, - { 'F', L"FLEX" }, - { 'm', L"Mac" }, - { 'R', L"Runser" }, - { 'T', L"TownsOS" }, - { 'X', L"XOSK" }, - { 'w', L"Windows95" }, - { 'W', L"WindowsNT" }, - { 0, L"MS-DOS" }, - { 'J', L"Java VM" } -}; - -const wchar_t *kUnknownOS = L"Unknown"; - -const int kNumHostOSes = sizeof(g_OsPairs) / sizeof(g_OsPairs[0]); - -static const wchar_t *GetOS(Byte osId) -{ - for (int i = 0; i < kNumHostOSes; i++) - if (g_OsPairs[i].Id == osId) - return g_OsPairs[i].Name; - return kUnknownOS; -}; - -STATPROPSTG kProps[] = -{ - { NULL, kpidPath, VT_BSTR}, - { NULL, kpidIsDir, VT_BOOL}, - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, - { NULL, kpidMTime, VT_FILETIME}, - { NULL, kpidAttrib, VT_UI4}, - - // { NULL, kpidCommented, VT_BOOL}, - - { NULL, kpidCRC, VT_UI4}, - - { NULL, kpidMethod, VT_UI1}, - { NULL, kpidHostOS, VT_BSTR} - -}; - -IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO - -CHandler::CHandler() {} - -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: - { - UString s = NItemName::WinNameToOSName(MultiByteToUnicodeString(item.GetName(), CP_OEMCP)); - if (!s.IsEmpty()) - { - if (s[s.Length() - 1] == WCHAR_PATH_SEPARATOR) - s.Delete(s.Length() - 1); - prop = s; - } - break; - } - case kpidIsDir: prop = item.IsDir(); break; - case kpidSize: prop = item.Size; break; - case kpidPackSize: prop = item.PackSize; break; - case kpidCRC: prop = (UInt32)item.CRC; break; - case kpidHostOS: prop = GetOS(item.OsId); break; - case kpidMTime: - { - FILETIME utcFileTime; - UInt32 unixTime; - if (item.GetUnixTime(unixTime)) - NTime::UnixTimeToFileTime(unixTime, utcFileTime); - else - { - FILETIME localFileTime; - if (DosTimeToFileTime(item.ModifiedTime, localFileTime)) - { - if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime)) - utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0; - } - else - utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0; - } - prop = utcFileTime; - break; - } - /* - case kpidAttrib: prop = (UInt32)item.Attributes; break; - case kpidCommented: prop = item.IsCommented(); break; - */ - case kpidMethod: - { - wchar_t method2[kMethodIdSize + 1]; - method2[kMethodIdSize] = 0; - for (int i = 0; i < kMethodIdSize; i++) - method2[i] = item.Method[i]; - prop = method2; - break; - } - } - prop.Detach(value); - return S_OK; - COM_TRY_END -} - -/* -class CProgressImp: public CProgressVirt -{ -public: - CMyComPtr<IArchiveOpenCallback> Callback; - STDMETHOD(SetCompleted)(const UInt64 *numFiles); -}; - -STDMETHODIMP CProgressImp::SetCompleted(const UInt64 *numFiles) -{ - if (Callback) - return Callback->SetCompleted(numFiles, NULL); - return S_OK; -} -*/ - -STDMETHODIMP CHandler::Open(IInStream *stream, - const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *callback) -{ - COM_TRY_BEGIN - try - { - _items.Clear(); - CInArchive archive; - - UInt64 endPos = 0; - bool needSetTotal = true; - - if (callback != NULL) - { - RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); - RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); - } - - RINOK(archive.Open(stream)); - 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.Skeep(item.PackSize); - if (callback != NULL) - { - if (needSetTotal) - { - RINOK(callback->SetTotal(NULL, &endPos)); - needSetTotal = false; - } - if (_items.Size() % 100 == 0) - { - UInt64 numFiles = _items.Size(); - UInt64 numBytes = item.DataPosition; - RINOK(callback->SetCompleted(&numFiles, &numBytes)); - } - } - } - if (_items.IsEmpty()) - return S_FALSE; - - _stream = stream; - } - catch(...) - { - return S_FALSE; - } - COM_TRY_END - return S_OK; -} - -STDMETHODIMP CHandler::Close() -{ - _items.Clear(); - _stream.Release(); - return S_OK; -} - - - -////////////////////////////////////// -// CHandler::DecompressItems - -STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, - Int32 testModeSpec, IArchiveExtractCallback *extractCallback) -{ - COM_TRY_BEGIN - bool testMode = (testModeSpec != 0); - UInt64 totalUnPacked = 0, totalPacked = 0; - bool allFilesMode = (numItems == UInt32(-1)); - if (allFilesMode) - numItems = _items.Size(); - if(numItems == 0) - return S_OK; - UInt32 i; - for(i = 0; i < numItems; i++) - { - const CItemEx &item = _items[allFilesMode ? i : indices[i]]; - totalUnPacked += item.Size; - totalPacked += item.PackSize; - } - extractCallback->SetTotal(totalUnPacked); - - UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0; - UInt64 currentItemUnPacked, currentItemPacked; - - NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = 0; - CMyComPtr<ICompressCoder> lzhDecoder; - CMyComPtr<ICompressCoder> lzh1Decoder; - CMyComPtr<ICompressCoder> arj2Decoder; - - NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); - CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; - - CLocalProgress *lps = new CLocalProgress; - CMyComPtr<ICompressProgressInfo> progress = lps; - lps->Init(extractCallback, false); - - CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; - CMyComPtr<ISequentialInStream> inStream(streamSpec); - streamSpec->SetStream(_stream); - - for(i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked, - currentTotalPacked += currentItemPacked) - { - currentItemUnPacked = 0; - currentItemPacked = 0; - - lps->InSize = currentTotalPacked; - lps->OutSize = currentTotalUnPacked; - RINOK(lps->SetCur()); - - CMyComPtr<ISequentialOutStream> realOutStream; - Int32 askMode; - askMode = testMode ? NExtract::NAskMode::kTest : - NExtract::NAskMode::kExtract; - Int32 index = allFilesMode ? i : indices[i]; - const CItemEx &item = _items[index]; - RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - - if (item.IsDir()) - { - // if (!testMode) - { - RINOK(extractCallback->PrepareOperation(askMode)); - RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); - } - continue; - } - - if (!testMode && (!realOutStream)) - continue; - - RINOK(extractCallback->PrepareOperation(askMode)); - currentItemUnPacked = item.Size; - currentItemPacked = item.PackSize; - - { - COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; - CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); - outStreamSpec->Init(realOutStream); - realOutStream.Release(); - - UInt64 pos; - _stream->Seek(item.DataPosition, STREAM_SEEK_SET, &pos); - - streamSpec->Init(item.PackSize); - - HRESULT result = S_OK; - Int32 opRes = NExtract::NOperationResult::kOK; - - if (item.IsCopyMethod()) - { - result = copyCoder->Code(inStream, outStream, NULL, NULL, progress); - if (result == S_OK && copyCoderSpec->TotalSize != item.PackSize) - result = S_FALSE; - } - else if (item.IsLh4GroupMethod()) - { - if (!lzhDecoder) - { - lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder; - lzhDecoder = lzhDecoderSpec; - } - lzhDecoderSpec->SetDictionary(item.GetNumDictBits()); - result = lzhDecoder->Code(inStream, outStream, NULL, ¤tItemUnPacked, progress); - } - /* - else if (item.IsLh1GroupMethod()) - { - if (!lzh1Decoder) - { - lzh1DecoderSpec = new NCompress::NLzh1::NDecoder::CCoder; - lzh1Decoder = lzh1DecoderSpec; - } - lzh1DecoderSpec->SetDictionary(item.GetNumDictBits()); - result = lzh1Decoder->Code(inStream, outStream, NULL, ¤tItemUnPacked, progress); - } - */ - else - opRes = NExtract::NOperationResult::kUnSupportedMethod; - - if (opRes == NExtract::NOperationResult::kOK) - { - if (result == S_FALSE) - opRes = NExtract::NOperationResult::kDataError; - else - { - RINOK(result); - if (outStreamSpec->GetCRC() != item.CRC) - opRes = NExtract::NOperationResult::kCRCError; - } - } - outStream.Release(); - RINOK(extractCallback->SetOperationResult(opRes)); - } - } - return S_OK; - COM_TRY_END -} - -}} diff --git a/CPP/7zip/Archive/Lzh/LzhHandler.h b/CPP/7zip/Archive/Lzh/LzhHandler.h deleted file mode 100755 index ed504dd2..00000000 --- a/CPP/7zip/Archive/Lzh/LzhHandler.h +++ /dev/null @@ -1,30 +0,0 @@ -// LzhHandler.h - -#ifndef __LZH_HANDLER_H -#define __LZH_HANDLER_H - -#include "Common/MyCom.h" -#include "../IArchive.h" -#include "LzhIn.h" - -namespace NArchive { -namespace NLzh { - -class CHandler: - public IInArchive, - public CMyUnknownImp -{ -public: - MY_UNKNOWN_IMP1(IInArchive) - - INTERFACE_IInArchive(;) - - CHandler(); -private: - CObjectVector<CItemEx> _items; - CMyComPtr<IInStream> _stream; -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Lzh/LzhHeader.h b/CPP/7zip/Archive/Lzh/LzhHeader.h deleted file mode 100755 index 845b9a21..00000000 --- a/CPP/7zip/Archive/Lzh/LzhHeader.h +++ /dev/null @@ -1,19 +0,0 @@ -// Archive/Lzh/Header.h - -#ifndef __ARCHIVE_LZH_HEADER_H -#define __ARCHIVE_LZH_HEADER_H - -#include "Common/Types.h" - -namespace NArchive { -namespace NLzh { - -const int kMethodIdSize = 5; - -const Byte kExtIdFileName = 0x01; -const Byte kExtIdDirName = 0x02; -const Byte kExtIdUnixTime = 0x54; - -}} - -#endif diff --git a/CPP/7zip/Archive/Lzh/LzhIn.cpp b/CPP/7zip/Archive/Lzh/LzhIn.cpp deleted file mode 100755 index 6783654c..00000000 --- a/CPP/7zip/Archive/Lzh/LzhIn.cpp +++ /dev/null @@ -1,172 +0,0 @@ -// Archive/LzhIn.cpp - -#include "StdAfx.h" - -#include "Common/StringConvert.h" -#include "Common/Buffer.h" - -#include "../../Common/StreamUtils.h" - -#include "LzhIn.h" - -namespace NArchive { -namespace NLzh { - -HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize) -{ - size_t realProcessedSize = size; - RINOK(ReadStream(m_Stream, data, &realProcessedSize)); - processedSize = (UInt32)realProcessedSize; - m_Position += processedSize; - return S_OK; -} - -HRESULT CInArchive::CheckReadBytes(void *data, UInt32 size) -{ - UInt32 processedSize; - RINOK(ReadBytes(data, size, processedSize)); - return (processedSize == size) ? S_OK: S_FALSE; -} - -HRESULT CInArchive::Open(IInStream *inStream) -{ - RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position)); - m_Stream = inStream; - return S_OK; -} - -static const Byte *ReadUInt32(const Byte *p, UInt32 &v) -{ - v = 0; - for (int i = 0; i < 4; i++) - v |= ((UInt32)(*p++) << (i * 8)); - return p; -} - -static const Byte *ReadUInt16(const Byte *p, UInt16 &v) -{ - v = 0; - for (int i = 0; i < 2; i++) - v |= ((UInt16)(*p++) << (i * 8)); - return p; -} - -static const Byte *ReadString(const Byte *p, size_t size, AString &s) -{ - s.Empty(); - for (size_t i = 0; i < size; i++) - { - char c = p[i]; - if (c == 0) - break; - s += c; - } - return p + size; -} - -static Byte CalcSum(const Byte *data, size_t size) -{ - Byte sum = 0; - for (size_t i = 0; i < size; i++) - sum = (Byte)(sum + data[i]); - return sum; -} - -HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) -{ - filled = false; - - UInt32 processedSize; - Byte startHeader[2]; - RINOK(ReadBytes(startHeader, 2, processedSize)) - if (processedSize == 0) - return S_OK; - if (processedSize == 1) - return (startHeader[0] == 0) ? S_OK: S_FALSE; - if (startHeader[0] == 0 && startHeader[1] == 0) - return S_OK; - - Byte header[256]; - const UInt32 kBasicPartSize = 22; - RINOK(ReadBytes(header, kBasicPartSize, processedSize)); - if (processedSize != kBasicPartSize) - return (startHeader[0] == 0) ? S_OK: S_FALSE; - - const Byte *p = header; - memmove(item.Method, p, kMethodIdSize); - if (!item.IsValidMethod()) - return S_OK; - p += kMethodIdSize; - p = ReadUInt32(p, item.PackSize); - p = ReadUInt32(p, item.Size); - p = ReadUInt32(p, item.ModifiedTime); - item.Attributes = *p++; - item.Level = *p++; - if (item.Level > 2) - return S_FALSE; - UInt32 headerSize; - if (item.Level < 2) - { - headerSize = startHeader[0]; - if (headerSize < kBasicPartSize) - return S_FALSE; - UInt32 remain = headerSize - kBasicPartSize; - RINOK(CheckReadBytes(header + kBasicPartSize, remain)); - if (startHeader[1] != CalcSum(header, headerSize)) - return S_FALSE; - size_t nameLength = *p++; - if ((p - header) + nameLength + 2 > headerSize) - return S_FALSE; - p = ReadString(p, nameLength, item.Name); - } - else - headerSize = startHeader[0] | ((UInt32)startHeader[1] << 8); - p = ReadUInt16(p, item.CRC); - if (item.Level != 0) - { - if (item.Level == 2) - { - RINOK(CheckReadBytes(header + kBasicPartSize, 2)); - } - if ((size_t)(p - header) + 3 > headerSize) - return S_FALSE; - item.OsId = *p++; - UInt16 nextSize; - p = ReadUInt16(p, nextSize); - while (nextSize != 0) - { - if (nextSize < 3) - return S_FALSE; - if (item.Level == 1) - { - if (item.PackSize < nextSize) - return S_FALSE; - item.PackSize -= nextSize; - } - CExtension ext; - RINOK(CheckReadBytes(&ext.Type, 1)) - nextSize -= 3; - ext.Data.SetCapacity(nextSize); - RINOK(CheckReadBytes((Byte *)ext.Data, nextSize)) - item.Extensions.Add(ext); - Byte hdr2[2]; - RINOK(CheckReadBytes(hdr2, 2)); - ReadUInt16(hdr2, nextSize); - } - } - item.DataPosition = m_Position; - filled = true; - return S_OK; -} - -HRESULT CInArchive::Skeep(UInt64 numBytes) -{ - UInt64 newPostion; - RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion)); - m_Position += numBytes; - if (m_Position != newPostion) - return E_FAIL; - return S_OK; -} - -}} diff --git a/CPP/7zip/Archive/Lzh/LzhIn.h b/CPP/7zip/Archive/Lzh/LzhIn.h deleted file mode 100755 index 344a133f..00000000 --- a/CPP/7zip/Archive/Lzh/LzhIn.h +++ /dev/null @@ -1,29 +0,0 @@ -// Archive/LzhIn.h - -#ifndef __ARCHIVE_LZHIN_H -#define __ARCHIVE_LZHIN_H - -#include "Common/MyCom.h" -#include "../../IStream.h" - -#include "LzhItem.h" - -namespace NArchive { -namespace NLzh { - -class CInArchive -{ - CMyComPtr<IInStream> m_Stream; - UInt64 m_Position; - - HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize); - HRESULT CheckReadBytes(void *data, UInt32 size); -public: - HRESULT Open(IInStream *inStream); - HRESULT GetNextItem(bool &filled, CItemEx &itemInfo); - HRESULT Skeep(UInt64 numBytes); -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Lzh/LzhItem.h b/CPP/7zip/Archive/Lzh/LzhItem.h deleted file mode 100755 index 494a65bf..00000000 --- a/CPP/7zip/Archive/Lzh/LzhItem.h +++ /dev/null @@ -1,172 +0,0 @@ -// Archive/LzhItem.h - -#ifndef __ARCHIVE_LZH_ITEM_H -#define __ARCHIVE_LZH_ITEM_H - -#include "Common/Types.h" -#include "Common/MyString.h" -#include "Common/Buffer.h" -#include "LzhHeader.h" - -namespace NArchive { -namespace NLzh { - -struct CExtension -{ - Byte Type; - CByteBuffer Data; - AString GetString() const - { - AString s; - for (size_t i = 0; i < Data.GetCapacity(); i++) - { - char c = (char)Data[i]; - if (c == 0) - break; - s += c; - } - return s; - } -}; - -struct CItem -{ -public: - AString Name; - Byte Method[kMethodIdSize]; - UInt32 PackSize; - UInt32 Size; - UInt32 ModifiedTime; - Byte Attributes; - Byte Level; - UInt16 CRC; - Byte OsId; - CObjectVector<CExtension> Extensions; - - bool IsValidMethod() const { return (Method[0] == '-' && Method[1] == 'l' && Method[4] == '-'); } - bool IsLhMethod() const {return (IsValidMethod() && Method[2] == 'h'); } - bool IsDir() const {return (IsLhMethod() && Method[3] == 'd'); } - - bool IsCopyMethod() const - { - return (IsLhMethod() && Method[3] == '0') || - (IsValidMethod() && Method[2] == 'z' && Method[3] == '4'); - } - - bool IsLh1GroupMethod() const - { - if (!IsLhMethod()) - return false; - switch(Method[3]) - { - case '1': - return true; - } - return false; - } - - bool IsLh4GroupMethod() const - { - if (!IsLhMethod()) - return false; - switch(Method[3]) - { - case '4': - case '5': - case '6': - case '7': - return true; - } - return false; - } - - int GetNumDictBits() const - { - if (!IsLhMethod()) - return 0; - switch(Method[3]) - { - case '1': - return 12; - case '2': - return 13; - case '3': - return 13; - case '4': - return 12; - case '5': - return 13; - case '6': - return 15; - case '7': - return 16; - } - return 0; - } - - int FindExt(Byte type) const - { - for (int i = 0; i < Extensions.Size(); i++) - if (Extensions[i].Type == type) - return i; - return -1; - } - bool GetUnixTime(UInt32 &value) const - { - int index = FindExt(kExtIdUnixTime); - if (index < 0) - { - if (Level == 2) - { - value = ModifiedTime; - return true; - } - return false; - } - const Byte *data = (const Byte *)(Extensions[index].Data); - value = data[0] | - ((UInt32)data[1] << 8) | - ((UInt32)data[2] << 16) | - ((UInt32)data[3] << 24); - return true; - } - - AString GetDirName() const - { - int index = FindExt(kExtIdDirName); - if (index < 0) - return AString(); - return Extensions[index].GetString(); - } - - AString GetFileName() const - { - int index = FindExt(kExtIdFileName); - if (index < 0) - return Name; - return Extensions[index].GetString(); - } - - AString GetName() const - { - AString dirName = GetDirName(); - dirName.Replace((char)(unsigned char)0xFF, '\\'); - if (!dirName.IsEmpty()) - { - char c = dirName[dirName.Length() - 1]; - if (c != '\\') - dirName += '\\'; - } - return dirName + GetFileName(); - } -}; - -class CItemEx: public CItem -{ -public: - UInt64 DataPosition; -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Lzh/LzhOutStreamWithCRC.cpp b/CPP/7zip/Archive/Lzh/LzhOutStreamWithCRC.cpp deleted file mode 100755 index 2281a884..00000000 --- a/CPP/7zip/Archive/Lzh/LzhOutStreamWithCRC.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// LzhOutStreamWithCRC.cpp - -#include "StdAfx.h" - -#include "LzhOutStreamWithCRC.h" - -namespace NArchive { -namespace NLzh { - -STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize) -{ - UInt32 realProcessedSize; - HRESULT result; - if(!_stream) - { - realProcessedSize = size; - result = S_OK; - } - else - result = _stream->Write(data, size, &realProcessedSize); - _crc.Update(data, realProcessedSize); - if(processedSize != NULL) - *processedSize = realProcessedSize; - return result; -} - -}} diff --git a/CPP/7zip/Archive/Lzh/LzhOutStreamWithCRC.h b/CPP/7zip/Archive/Lzh/LzhOutStreamWithCRC.h deleted file mode 100755 index fd73f4ae..00000000 --- a/CPP/7zip/Archive/Lzh/LzhOutStreamWithCRC.h +++ /dev/null @@ -1,38 +0,0 @@ -// LzhOutStreamWithCRC.h - -#ifndef __LZHOUTSTREAMWITHCRC_H -#define __LZHOUTSTREAMWITHCRC_H - -#include "LzhCRC.h" -#include "../../../Common/MyCom.h" -#include "../../IStream.h" - -namespace NArchive { -namespace NLzh { - -class COutStreamWithCRC: - public ISequentialOutStream, - public CMyUnknownImp -{ -public: - MY_UNKNOWN_IMP - - STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); -private: - CCRC _crc; - CMyComPtr<ISequentialOutStream> _stream; -public: - void Init(ISequentialOutStream *stream) - { - _stream = stream; - _crc.Init(); - } - void ReleaseStream() { _stream.Release(); } - UInt32 GetCRC() const { return _crc.GetDigest(); } - void InitCRC() { _crc.Init(); } - -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Lzh/LzhRegister.cpp b/CPP/7zip/Archive/Lzh/LzhRegister.cpp deleted file mode 100755 index b9b1d473..00000000 --- a/CPP/7zip/Archive/Lzh/LzhRegister.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// LzhRegister.cpp - -#include "StdAfx.h" - -#include "../../Common/RegisterArc.h" - -#include "LzhHandler.h" -static IInArchive *CreateArc() { return new NArchive::NLzh::CHandler; } - -static CArcInfo g_ArcInfo = - { L"Lzh", L"lzh lha", 0, 6, { '-', 'l' }, 2, false, CreateArc, 0 }; - -REGISTER_ARC(Lzh) diff --git a/CPP/7zip/Archive/Lzh/StdAfx.h b/CPP/7zip/Archive/Lzh/StdAfx.h deleted file mode 100755 index e7fb6986..00000000 --- a/CPP/7zip/Archive/Lzh/StdAfx.h +++ /dev/null @@ -1,8 +0,0 @@ -// StdAfx.h - -#ifndef __STDAFX_H -#define __STDAFX_H - -#include "../../../Common/MyWindows.h" - -#endif diff --git a/CPP/7zip/Archive/LzhHandler.cpp b/CPP/7zip/Archive/LzhHandler.cpp new file mode 100755 index 00000000..19a9516a --- /dev/null +++ b/CPP/7zip/Archive/LzhHandler.cpp @@ -0,0 +1,783 @@ +// LzhHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/Buffer.h" +#include "Common/ComTry.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../ICoder.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" +#include "../Compress/LzhDecoder.h" + +#include "IArchive.h" + +#include "Common/ItemNameUtils.h" + +using namespace NWindows; +using namespace NTime; + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) + +namespace NArchive { +namespace NLzh{ + +const int kMethodIdSize = 5; + +const Byte kExtIdFileName = 0x01; +const Byte kExtIdDirName = 0x02; +const Byte kExtIdUnixTime = 0x54; + +struct CExtension +{ + Byte Type; + CByteBuffer Data; + AString GetString() const + { + AString s; + for (size_t i = 0; i < Data.GetCapacity(); i++) + { + char c = (char)Data[i]; + if (c == 0) + break; + s += c; + } + return s; + } +}; + +struct CItem +{ + AString Name; + Byte Method[kMethodIdSize]; + Byte Attributes; + Byte Level; + Byte OsId; + UInt32 PackSize; + UInt32 Size; + UInt32 ModifiedTime; + UInt16 CRC; + CObjectVector<CExtension> Extensions; + + bool IsValidMethod() const { return (Method[0] == '-' && Method[1] == 'l' && Method[4] == '-'); } + bool IsLhMethod() const {return (IsValidMethod() && Method[2] == 'h'); } + bool IsDir() const {return (IsLhMethod() && Method[3] == 'd'); } + + bool IsCopyMethod() const + { + return (IsLhMethod() && Method[3] == '0') || + (IsValidMethod() && Method[2] == 'z' && Method[3] == '4'); + } + + bool IsLh1GroupMethod() const + { + if (!IsLhMethod()) + return false; + switch(Method[3]) + { + case '1': + return true; + } + return false; + } + + bool IsLh4GroupMethod() const + { + if (!IsLhMethod()) + return false; + switch(Method[3]) + { + case '4': + case '5': + case '6': + case '7': + return true; + } + return false; + } + + int GetNumDictBits() const + { + if (!IsLhMethod()) + return 0; + switch(Method[3]) + { + case '1': return 12; + case '2': return 13; + case '3': return 13; + case '4': return 12; + case '5': return 13; + case '6': return 15; + case '7': return 16; + } + return 0; + } + + int FindExt(Byte type) const + { + for (int i = 0; i < Extensions.Size(); i++) + if (Extensions[i].Type == type) + return i; + return -1; + } + bool GetUnixTime(UInt32 &value) const + { + int index = FindExt(kExtIdUnixTime); + if (index < 0) + { + if (Level == 2) + { + value = ModifiedTime; + return true; + } + return false; + } + const Byte *data = (const Byte *)(Extensions[index].Data); + value = GetUi32(data); + return true; + } + + AString GetDirName() const + { + int index = FindExt(kExtIdDirName); + if (index < 0) + return AString(); + return Extensions[index].GetString(); + } + + AString GetFileName() const + { + int index = FindExt(kExtIdFileName); + if (index < 0) + return Name; + return Extensions[index].GetString(); + } + + AString GetName() const + { + AString dirName = GetDirName(); + dirName.Replace((char)(unsigned char)0xFF, '\\'); + if (!dirName.IsEmpty()) + { + char c = dirName[dirName.Length() - 1]; + if (c != '\\') + dirName += '\\'; + } + return dirName + GetFileName(); + } +}; + +struct CItemEx: public CItem +{ + UInt64 DataPosition; +}; + +class CInArchive +{ + CMyComPtr<IInStream> m_Stream; + UInt64 m_Position; + + HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize); + HRESULT CheckReadBytes(void *data, UInt32 size); +public: + HRESULT Open(IInStream *inStream); + HRESULT GetNextItem(bool &filled, CItemEx &itemInfo); + HRESULT Skip(UInt64 numBytes); +}; + +HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize) +{ + size_t realProcessedSize = size; + RINOK(ReadStream(m_Stream, data, &realProcessedSize)); + processedSize = (UInt32)realProcessedSize; + m_Position += processedSize; + return S_OK; +} + +HRESULT CInArchive::CheckReadBytes(void *data, UInt32 size) +{ + UInt32 processedSize; + RINOK(ReadBytes(data, size, processedSize)); + return (processedSize == size) ? S_OK: S_FALSE; +} + +HRESULT CInArchive::Open(IInStream *inStream) +{ + RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position)); + m_Stream = inStream; + return S_OK; +} + +static const Byte *ReadUInt16(const Byte *p, UInt16 &v) +{ + v = Get16(p); + return p + 2; +} + +static const Byte *ReadString(const Byte *p, size_t size, AString &s) +{ + s.Empty(); + for (size_t i = 0; i < size; i++) + { + char c = p[i]; + if (c == 0) + break; + s += c; + } + return p + size; +} + +static Byte CalcSum(const Byte *data, size_t size) +{ + Byte sum = 0; + for (size_t i = 0; i < size; i++) + sum = (Byte)(sum + data[i]); + return sum; +} + +HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) +{ + filled = false; + + UInt32 processedSize; + Byte startHeader[2]; + RINOK(ReadBytes(startHeader, 2, processedSize)) + if (processedSize == 0) + return S_OK; + if (processedSize == 1) + return (startHeader[0] == 0) ? S_OK: S_FALSE; + if (startHeader[0] == 0 && startHeader[1] == 0) + return S_OK; + + Byte header[256]; + const UInt32 kBasicPartSize = 22; + RINOK(ReadBytes(header, kBasicPartSize, processedSize)); + if (processedSize != kBasicPartSize) + return (startHeader[0] == 0) ? S_OK: S_FALSE; + + const Byte *p = header; + memmove(item.Method, p, kMethodIdSize); + if (!item.IsValidMethod()) + return S_OK; + p += kMethodIdSize; + item.PackSize = Get32(p); + item.Size = Get32(p + 4); + item.ModifiedTime = Get32(p + 8); + item.Attributes = p[12]; + item.Level = p[13]; + p += 14; + if (item.Level > 2) + return S_FALSE; + UInt32 headerSize; + if (item.Level < 2) + { + headerSize = startHeader[0]; + if (headerSize < kBasicPartSize) + return S_FALSE; + UInt32 remain = headerSize - kBasicPartSize; + RINOK(CheckReadBytes(header + kBasicPartSize, remain)); + if (startHeader[1] != CalcSum(header, headerSize)) + return S_FALSE; + size_t nameLength = *p++; + if ((p - header) + nameLength + 2 > headerSize) + return S_FALSE; + p = ReadString(p, nameLength, item.Name); + } + else + headerSize = startHeader[0] | ((UInt32)startHeader[1] << 8); + p = ReadUInt16(p, item.CRC); + if (item.Level != 0) + { + if (item.Level == 2) + { + RINOK(CheckReadBytes(header + kBasicPartSize, 2)); + } + if ((size_t)(p - header) + 3 > headerSize) + return S_FALSE; + item.OsId = *p++; + UInt16 nextSize; + p = ReadUInt16(p, nextSize); + while (nextSize != 0) + { + if (nextSize < 3) + return S_FALSE; + if (item.Level == 1) + { + if (item.PackSize < nextSize) + return S_FALSE; + item.PackSize -= nextSize; + } + CExtension ext; + RINOK(CheckReadBytes(&ext.Type, 1)) + nextSize -= 3; + ext.Data.SetCapacity(nextSize); + RINOK(CheckReadBytes((Byte *)ext.Data, nextSize)) + item.Extensions.Add(ext); + Byte hdr2[2]; + RINOK(CheckReadBytes(hdr2, 2)); + ReadUInt16(hdr2, nextSize); + } + } + item.DataPosition = m_Position; + filled = true; + return S_OK; +} + +HRESULT CInArchive::Skip(UInt64 numBytes) +{ + UInt64 newPostion; + RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion)); + m_Position += numBytes; + if (m_Position != newPostion) + return E_FAIL; + return S_OK; +} + +struct COsPair +{ + Byte Id; + const char *Name; +}; + +static COsPair g_OsPairs[] = +{ + { 0, "MS-DOS" }, + { 'M', "MS-DOS" }, + { '2', "OS/2" }, + { '9', "OS9" }, + { 'K', "OS/68K" }, + { '3', "OS/386" }, + { 'H', "HUMAN" }, + { 'U', "UNIX" }, + { 'C', "CP/M" }, + { 'F', "FLEX" }, + { 'm', "Mac" }, + { 'R', "Runser" }, + { 'T', "TownsOS" }, + { 'X', "XOSK" }, + { 'w', "Windows 95" }, + { 'W', "Windows NT" }, + { 'J', "Java VM" } +}; + +static const char *kUnknownOS = "Unknown"; + +static const char *GetOS(Byte osId) +{ + for (int i = 0; i < sizeof(g_OsPairs) / sizeof(g_OsPairs[0]); i++) + if (g_OsPairs[i].Id == osId) + return g_OsPairs[i].Name; + return kUnknownOS; +}; + +static STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + // { NULL, kpidAttrib, VT_UI4}, + { NULL, kpidCRC, VT_UI4}, + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidHostOS, VT_BSTR} +}; + +class CCRC +{ + UInt16 _value; +public: + static UInt16 Table[256]; + static void InitTable(); + + CCRC(): _value(0){}; + void Init() { _value = 0; } + void Update(const void *data, size_t size); + UInt16 GetDigest() const { return _value; } +}; + +static const UInt16 kCRCPoly = 0xA001; + +UInt16 CCRC::Table[256]; + +void CCRC::InitTable() +{ + for (UInt32 i = 0; i < 256; i++) + { + UInt32 r = i; + for (int j = 0; j < 8; j++) + if (r & 1) + r = (r >> 1) ^ kCRCPoly; + else + r >>= 1; + CCRC::Table[i] = (UInt16)r; + } +} + +class CCRCTableInit +{ +public: + CCRCTableInit() { CCRC::InitTable(); } +} g_CRCTableInit; + +void CCRC::Update(const void *data, size_t size) +{ + UInt16 v = _value; + const Byte *p = (const Byte *)data; + for (; size > 0; size--, p++) + v = (UInt16)(Table[((Byte)(v)) ^ *p] ^ (v >> 8)); + _value = v; +} + + +class COutStreamWithCRC: + public ISequentialOutStream, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +private: + CCRC _crc; + CMyComPtr<ISequentialOutStream> _stream; +public: + void Init(ISequentialOutStream *stream) + { + _stream = stream; + _crc.Init(); + } + void ReleaseStream() { _stream.Release(); } + UInt32 GetCRC() const { return _crc.GetDigest(); } + void InitCRC() { _crc.Init(); } + +}; + +STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessedSize; + HRESULT result; + if(!_stream) + { + realProcessedSize = size; + result = S_OK; + } + else + result = _stream->Write(data, size, &realProcessedSize); + _crc.Update(data, realProcessedSize); + if(processedSize != NULL) + *processedSize = realProcessedSize; + return result; +} + +class CHandler: + public IInArchive, + public CMyUnknownImp +{ + CObjectVector<CItemEx> _items; + CMyComPtr<IInStream> _stream; +public: + MY_UNKNOWN_IMP1(IInArchive) + INTERFACE_IInArchive(;) + CHandler(); +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO + +CHandler::CHandler() {} + +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: + { + UString s = NItemName::WinNameToOSName(MultiByteToUnicodeString(item.GetName(), CP_OEMCP)); + if (!s.IsEmpty()) + { + if (s[s.Length() - 1] == WCHAR_PATH_SEPARATOR) + s.Delete(s.Length() - 1); + prop = s; + } + break; + } + case kpidIsDir: prop = item.IsDir(); break; + case kpidSize: prop = item.Size; break; + case kpidPackSize: prop = item.PackSize; break; + case kpidCRC: prop = (UInt32)item.CRC; break; + case kpidHostOS: prop = GetOS(item.OsId); break; + case kpidMTime: + { + FILETIME utc; + UInt32 unixTime; + if (item.GetUnixTime(unixTime)) + NTime::UnixTimeToFileTime(unixTime, utc); + else + { + FILETIME localFileTime; + if (DosTimeToFileTime(item.ModifiedTime, localFileTime)) + { + if (!LocalFileTimeToFileTime(&localFileTime, &utc)) + utc.dwHighDateTime = utc.dwLowDateTime = 0; + } + else + utc.dwHighDateTime = utc.dwLowDateTime = 0; + } + prop = utc; + break; + } + // case kpidAttrib: prop = (UInt32)item.Attributes; break; + case kpidMethod: + { + char method2[kMethodIdSize + 1]; + method2[kMethodIdSize] = 0; + memcpy(method2, item.Method, kMethodIdSize); + prop = method2; + break; + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + try + { + _items.Clear(); + CInArchive archive; + + UInt64 endPos = 0; + bool needSetTotal = true; + + if (callback != NULL) + { + RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + } + + RINOK(archive.Open(stream)); + 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.Skip(item.PackSize); + if (callback != NULL) + { + if (needSetTotal) + { + RINOK(callback->SetTotal(NULL, &endPos)); + needSetTotal = false; + } + if (_items.Size() % 100 == 0) + { + UInt64 numFiles = _items.Size(); + UInt64 numBytes = item.DataPosition; + RINOK(callback->SetCompleted(&numFiles, &numBytes)); + } + } + } + if (_items.IsEmpty()) + return S_FALSE; + + _stream = stream; + } + catch(...) + { + return S_FALSE; + } + COM_TRY_END + return S_OK; +} + +STDMETHODIMP CHandler::Close() +{ + _items.Clear(); + _stream.Release(); + return S_OK; +} + + + +////////////////////////////////////// +// CHandler::DecompressItems + +STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, + Int32 testModeSpec, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool testMode = (testModeSpec != 0); + UInt64 totalUnPacked = 0, totalPacked = 0; + bool allFilesMode = (numItems == UInt32(-1)); + if (allFilesMode) + numItems = _items.Size(); + if(numItems == 0) + return S_OK; + UInt32 i; + for(i = 0; i < numItems; i++) + { + const CItemEx &item = _items[allFilesMode ? i : indices[i]]; + totalUnPacked += item.Size; + totalPacked += item.PackSize; + } + extractCallback->SetTotal(totalUnPacked); + + UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0; + UInt64 currentItemUnPacked, currentItemPacked; + + NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = 0; + CMyComPtr<ICompressCoder> lzhDecoder; + CMyComPtr<ICompressCoder> lzh1Decoder; + CMyComPtr<ICompressCoder> arj2Decoder; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr<ISequentialInStream> inStream(streamSpec); + streamSpec->SetStream(_stream); + + for(i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked, + currentTotalPacked += currentItemPacked) + { + currentItemUnPacked = 0; + currentItemPacked = 0; + + lps->InSize = currentTotalPacked; + lps->OutSize = currentTotalUnPacked; + RINOK(lps->SetCur()); + + CMyComPtr<ISequentialOutStream> realOutStream; + Int32 askMode; + askMode = testMode ? NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + const CItemEx &item = _items[index]; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + if (item.IsDir()) + { + // if (!testMode) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + } + continue; + } + + if (!testMode && (!realOutStream)) + continue; + + RINOK(extractCallback->PrepareOperation(askMode)); + currentItemUnPacked = item.Size; + currentItemPacked = item.PackSize; + + { + COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; + CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); + outStreamSpec->Init(realOutStream); + realOutStream.Release(); + + UInt64 pos; + _stream->Seek(item.DataPosition, STREAM_SEEK_SET, &pos); + + streamSpec->Init(item.PackSize); + + HRESULT result = S_OK; + Int32 opRes = NExtract::NOperationResult::kOK; + + if (item.IsCopyMethod()) + { + result = copyCoder->Code(inStream, outStream, NULL, NULL, progress); + if (result == S_OK && copyCoderSpec->TotalSize != item.PackSize) + result = S_FALSE; + } + else if (item.IsLh4GroupMethod()) + { + if (!lzhDecoder) + { + lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder; + lzhDecoder = lzhDecoderSpec; + } + lzhDecoderSpec->SetDictionary(item.GetNumDictBits()); + result = lzhDecoder->Code(inStream, outStream, NULL, ¤tItemUnPacked, progress); + } + /* + else if (item.IsLh1GroupMethod()) + { + if (!lzh1Decoder) + { + lzh1DecoderSpec = new NCompress::NLzh1::NDecoder::CCoder; + lzh1Decoder = lzh1DecoderSpec; + } + lzh1DecoderSpec->SetDictionary(item.GetNumDictBits()); + result = lzh1Decoder->Code(inStream, outStream, NULL, ¤tItemUnPacked, progress); + } + */ + else + opRes = NExtract::NOperationResult::kUnSupportedMethod; + + if (opRes == NExtract::NOperationResult::kOK) + { + if (result == S_FALSE) + opRes = NExtract::NOperationResult::kDataError; + else + { + RINOK(result); + if (outStreamSpec->GetCRC() != item.CRC) + opRes = NExtract::NOperationResult::kCRCError; + } + } + outStream.Release(); + RINOK(extractCallback->SetOperationResult(opRes)); + } + } + return S_OK; + COM_TRY_END +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"Lzh", L"lzh lha", 0, 6, { '-', 'l' }, 2, false, CreateArc, 0 }; + +REGISTER_ARC(Lzh) + +}} diff --git a/CPP/7zip/Archive/Lzma/LzmaArcRegister.cpp b/CPP/7zip/Archive/Lzma/LzmaArcRegister.cpp deleted file mode 100755 index bbeb177b..00000000 --- a/CPP/7zip/Archive/Lzma/LzmaArcRegister.cpp +++ /dev/null @@ -1,14 +0,0 @@ -// LzmaArcRegister.cpp - -#include "StdAfx.h" - -#include "../../Common/RegisterArc.h" - -#include "LzmaHandler.h" - -static IInArchive *CreateArc() { return new NArchive::NLzma::CHandler; } - -static CArcInfo g_ArcInfo = - { L"Lzma", L"lzma lzma86", 0, 0xA, {0 }, 0, true, CreateArc, NULL }; - -REGISTER_ARC(Lzma) diff --git a/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.cpp b/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.cpp deleted file mode 100755 index 26c1092f..00000000 --- a/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.cpp +++ /dev/null @@ -1,86 +0,0 @@ -// LzmaFiltersDecode.cpp - -#include "StdAfx.h" - -#include "LzmaFiltersDecode.h" - -namespace NArchive { -namespace NLzma { - -static const UInt64 k_LZMA = 0x030101; -static const UInt64 k_BCJ = 0x03030103; - -HRESULT CDecoder::Code( - DECL_EXTERNAL_CODECS_LOC_VARS - const CHeader &block, - ISequentialInStream *inStream, ISequentialOutStream *outStream, - UInt64 *inProcessedSize, ICompressProgressInfo *progress) -{ - *inProcessedSize = (UInt64)(Int64)-1; - - if (block.FilterMethod > 1) - return E_NOTIMPL; - - if (!_lzmaDecoder) - { - RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_LZMA, _lzmaDecoder, false)); - if (_lzmaDecoder == 0) - return E_NOTIMPL; - } - - { - CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; - _lzmaDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); - if (!setDecoderProperties) - return E_NOTIMPL; - RINOK(setDecoderProperties->SetDecoderProperties2(block.LzmaProps, 5)); - } - - bool filteredMode = (block.FilterMethod == 1); - - CMyComPtr<ICompressSetOutStream> setOutStream; - - if (filteredMode) - { - if (!_bcjStream) - { - CMyComPtr<ICompressCoder> coder; - RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_BCJ, coder, false)); - if (!coder) - return E_NOTIMPL; - coder.QueryInterface(IID_ISequentialOutStream, &_bcjStream); - if (!_bcjStream) - return E_NOTIMPL; - } - - _bcjStream.QueryInterface(IID_ICompressSetOutStream, &setOutStream); - if (!setOutStream) - return E_NOTIMPL; - RINOK(setOutStream->SetOutStream(outStream)); - outStream = _bcjStream; - } - - const UInt64 *unpackSize = block.HasUnpackSize() ? &block.UnpackSize : NULL; - RINOK(_lzmaDecoder->Code(inStream, outStream, NULL, unpackSize, progress)); - - if (filteredMode) - { - CMyComPtr<IOutStreamFlush> flush; - _bcjStream.QueryInterface(IID_IOutStreamFlush, &flush); - if (flush) - { - RINOK(flush->Flush()); - } - RINOK(setOutStream->ReleaseOutStream()); - } - - CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize; - _lzmaDecoder.QueryInterface(IID_ICompressGetInStreamProcessedSize, &getInStreamProcessedSize); - if (getInStreamProcessedSize) - { - RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(inProcessedSize)); - } - return S_OK; -} - -}} diff --git a/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.h b/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.h deleted file mode 100755 index 36de4966..00000000 --- a/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.h +++ /dev/null @@ -1,26 +0,0 @@ -// LzmaFiltersDecode.h - -#ifndef __LZMA_FILTERS_DECODE_H -#define __LZMA_FILTERS_DECODE_H - -#include "../../Common/CreateCoder.h" - -#include "LzmaItem.h" - -namespace NArchive { -namespace NLzma { - -class CDecoder -{ - CMyComPtr<ICompressCoder> _lzmaDecoder; - CMyComPtr<ISequentialOutStream> _bcjStream; -public: - HRESULT Code(DECL_EXTERNAL_CODECS_LOC_VARS - const CHeader &block, - ISequentialInStream *inStream, ISequentialOutStream *outStream, - UInt64 *inProcessedSize, ICompressProgressInfo *progress); -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Lzma/LzmaHandler.cpp b/CPP/7zip/Archive/Lzma/LzmaHandler.cpp deleted file mode 100755 index c434595d..00000000 --- a/CPP/7zip/Archive/Lzma/LzmaHandler.cpp +++ /dev/null @@ -1,243 +0,0 @@ -// LzmaHandler.cpp - -#include "StdAfx.h" - -#include "LzmaHandler.h" - -#include "Common/Defs.h" -#include "Common/StringConvert.h" -#include "Common/ComTry.h" -#include "Common/IntToString.h" - -#include "Windows/PropVariant.h" - -#include "../../Common/ProgressUtils.h" -#include "../../Common/StreamUtils.h" -#include "../Common/DummyOutStream.h" - -#include "LzmaFiltersDecode.h" - -namespace NArchive { -namespace NLzma { - -STATPROPSTG kProps[] = -{ - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, - { NULL, kpidMethod, VT_UI1} -}; - -IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO - -STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) -{ - *numItems = 1; - return S_OK; -} - -static void ConvertUInt32ToString(UInt32 value, wchar_t *s) -{ - ConvertUInt64ToString(value, s + MyStringLen(s)); -} - -static void DictSizeToString(UInt32 value, wchar_t *s) -{ - for (int i = 0; i <= 31; i++) - if ((UInt32(1) << i) == value) - { - ConvertUInt32ToString(i, s); - return; - } - wchar_t c = L'b'; - if ((value & ((1 << 20) - 1)) == 0) - { - value >>= 20; - c = L'm'; - } - else if ((value & ((1 << 10) - 1)) == 0) - { - value >>= 10; - c = L'k'; - } - ConvertUInt32ToString(value, s); - int p = MyStringLen(s); - s[p++] = c; - s[p++] = L'\0'; -} - -static void MyStrCat(wchar_t *d, const wchar_t *s) -{ - MyStringCopy(d + MyStringLen(d), s); -} - -STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) -{ - if (index != 0) - return E_INVALIDARG; - NWindows::NCOM::CPropVariant propVariant; - switch(propID) - { - case kpidSize: - if (m_StreamInfo.HasUnpackSize()) - propVariant = (UInt64)m_StreamInfo.UnpackSize; - break; - case kpidPackSize: - propVariant = (UInt64)m_PackSize; - break; - case kpidMethod: - { - wchar_t s[64]; - s[0] = '\0'; - if (m_StreamInfo.IsThereFilter) - { - const wchar_t *f; - if (m_StreamInfo.FilterMethod == 0) - f = L"Copy"; - else if (m_StreamInfo.FilterMethod == 1) - f = L"BCJ"; - else - f = L"Unknown"; - MyStrCat(s, f); - MyStrCat(s, L" "); - } - MyStrCat(s, L"LZMA:"); - DictSizeToString(m_StreamInfo.GetDicSize(), s); - propVariant = s; - break; - } - } - propVariant.Detach(value); - return S_OK; -} - -STDMETHODIMP CHandler::Open(IInStream *inStream, - const UInt64 * /* maxCheckStartPosition */, - IArchiveOpenCallback * /* openArchiveCallback */) -{ - { - RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition)); - - HRESULT res = ReadStreamHeader(inStream, m_StreamInfo); - if (res != S_OK) - return S_FALSE; - - Byte b; - RINOK(ReadStream_FALSE(inStream, &b, 1)); - if (b != 0) - return S_FALSE; - - UInt64 endPos; - RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); - m_PackSize = endPos - m_StreamStartPosition - m_StreamInfo.GetHeaderSize(); - - m_Stream = inStream; - } - return S_OK; -} - -STDMETHODIMP CHandler::Close() -{ - m_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) - return E_INVALIDARG; - if (indices[0] != 0) - return E_INVALIDARG; - } - - bool testMode = (_aTestMode != 0); - - RINOK(extractCallback->SetTotal(m_PackSize)); - - UInt64 currentTotalPacked = 0; - - CDummyOutStream *outStreamSpec = new CDummyOutStream; - CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); - - { - CMyComPtr<ISequentialOutStream> realOutStream; - Int32 askMode = testMode ? - NArchive::NExtract::NAskMode::kTest : - NArchive::NExtract::NAskMode::kExtract; - - RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); - - outStreamSpec->SetStream(realOutStream); - outStreamSpec->Init(); - if(!testMode && !realOutStream) - return S_OK; - extractCallback->PrepareOperation(askMode); - } - - CLocalProgress *lps = new CLocalProgress; - CMyComPtr<ICompressProgressInfo> progress = lps; - lps->Init(extractCallback, true); - - CDecoder decoder; - RINOK(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL)); - UInt64 streamPos = m_StreamStartPosition; - Int32 opRes = NArchive::NExtract::NOperationResult::kOK; - bool firstItem = true; - for (;;) - { - CHeader st; - HRESULT result = ReadStreamHeader(m_Stream, st); - if (result != S_OK) - { - if (firstItem) - return E_FAIL; - break; - } - firstItem = false; - - lps->OutSize = outStreamSpec->GetSize(); - lps->InSize = currentTotalPacked; - RINOK(lps->SetCur()); - - streamPos += st.GetHeaderSize(); - UInt64 packProcessed; - - { - result = decoder.Code( - EXTERNAL_CODECS_VARS - st, m_Stream, outStream, &packProcessed, progress); - if (result == E_NOTIMPL) - { - opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; - break; - } - if (result == S_FALSE) - { - opRes = NArchive::NExtract::NOperationResult::kDataError; - break; - } - RINOK(result); - } - - if (packProcessed == (UInt64)(Int64)-1) - break; - RINOK(m_Stream->Seek(streamPos + packProcessed, STREAM_SEEK_SET, NULL)); - currentTotalPacked += packProcessed; - streamPos += packProcessed; - } - outStream.Release(); - return extractCallback->SetOperationResult(opRes); - COM_TRY_END -} - -IMPL_ISetCompressCodecsInfo - -}} diff --git a/CPP/7zip/Archive/Lzma/LzmaHandler.h b/CPP/7zip/Archive/Lzma/LzmaHandler.h deleted file mode 100755 index e8fdcedc..00000000 --- a/CPP/7zip/Archive/Lzma/LzmaHandler.h +++ /dev/null @@ -1,69 +0,0 @@ -// Lzma/Handler.h - -#ifndef __GZIP_HANDLER_H -#define __GZIP_HANDLER_H - -#include "Common/MyCom.h" - -#include "../IArchive.h" -#include "../../Common/CreateCoder.h" - -#include "LzmaIn.h" - -namespace NArchive { -namespace NLzma { - -// const UInt64 k_LZMA = 0x030101; - -class CHandler: - public IInArchive, - PUBLIC_ISetCompressCodecsInfo - public CMyUnknownImp -{ -public: - MY_QUERYINTERFACE_BEGIN - MY_QUERYINTERFACE_ENTRY(IInArchive) - QUERY_ENTRY_ISetCompressCodecsInfo - MY_QUERYINTERFACE_END - MY_ADDREF_RELEASE - - STDMETHOD(Open)(IInStream *inStream, - const UInt64 *maxCheckStartPosition, - IArchiveOpenCallback *openArchiveCallback); - STDMETHOD(Close)(); - - STDMETHOD(GetNumberOfItems)(UInt32 *numItems); - STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); - STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, - Int32 testMode, IArchiveExtractCallback *extractCallback); - - STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value); - - STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties); - STDMETHOD(GetPropertyInfo)(UInt32 index, - BSTR *name, PROPID *propID, VARTYPE *varType); - - STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties); - STDMETHOD(GetArchivePropertyInfo)(UInt32 index, - BSTR *name, PROPID *propID, VARTYPE *varType); - - UString GetMethodString(); -public: - CHandler() { } - -private: - CHeader m_StreamInfo; - UInt64 m_StreamStartPosition; - UInt64 m_PackSize; - - CMyComPtr<IInStream> m_Stream; - - DECL_EXTERNAL_CODECS_VARS - - DECL_ISetCompressCodecsInfo - -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Lzma/LzmaIn.cpp b/CPP/7zip/Archive/Lzma/LzmaIn.cpp deleted file mode 100755 index 342b01e1..00000000 --- a/CPP/7zip/Archive/Lzma/LzmaIn.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// Archive/LzmaIn.cpp - -#include "StdAfx.h" - -#include "LzmaIn.h" - -#include "../../Common/StreamUtils.h" - -namespace NArchive { -namespace NLzma { - -static bool CheckDictSize(const Byte *p) -{ - UInt32 dicSize = GetUi32(p); - int i; - for (i = 1; i <= 30; i++) - if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i)) - return true; - return false; -} - -HRESULT ReadStreamHeader(ISequentialInStream *inStream, CHeader &block) -{ - Byte sig[5 + 9]; - RINOK(ReadStream_FALSE(inStream, sig, 5 + 8)); - - const Byte kMaxProp0Val = 5 * 5 * 9 - 1; - if (sig[0] > kMaxProp0Val) - return S_FALSE; - - for (int i = 0; i < 5; i++) - block.LzmaProps[i] = sig[i]; - - block.IsThereFilter = false; - block.FilterMethod = 0; - - if (!CheckDictSize(sig + 1)) - { - if (sig[0] > 1 || sig[1] > kMaxProp0Val) - return S_FALSE; - block.IsThereFilter = true; - block.FilterMethod = sig[0]; - for (int i = 0; i < 5; i++) - block.LzmaProps[i] = sig[i + 1]; - if (!CheckDictSize(block.LzmaProps + 1)) - return S_FALSE; - RINOK(ReadStream_FALSE(inStream, sig + 5 + 8, 1)); - } - UInt32 unpOffset = 5 + (block.IsThereFilter ? 1 : 0); - block.UnpackSize = GetUi64(sig + unpOffset); - if (block.HasUnpackSize() && block.UnpackSize >= ((UInt64)1 << 56)) - return S_FALSE; - return S_OK; -} - -}} diff --git a/CPP/7zip/Archive/Lzma/LzmaIn.h b/CPP/7zip/Archive/Lzma/LzmaIn.h deleted file mode 100755 index 6f237f2d..00000000 --- a/CPP/7zip/Archive/Lzma/LzmaIn.h +++ /dev/null @@ -1,16 +0,0 @@ -// Archive/LzmaIn.h - -#ifndef __ARCHIVE_LZMA_IN_H -#define __ARCHIVE_LZMA_IN_H - -#include "LzmaItem.h" -#include "../../IStream.h" - -namespace NArchive { -namespace NLzma { - -HRESULT ReadStreamHeader(ISequentialInStream *inStream, CHeader &st); - -}} - -#endif diff --git a/CPP/7zip/Archive/Lzma/LzmaItem.h b/CPP/7zip/Archive/Lzma/LzmaItem.h deleted file mode 100755 index 8fcae210..00000000 --- a/CPP/7zip/Archive/Lzma/LzmaItem.h +++ /dev/null @@ -1,27 +0,0 @@ -// Archive/LzmaItem.h - -#ifndef __ARCHIVE_LZMA_ITEM_H -#define __ARCHIVE_LZMA_ITEM_H - -#include "Common/Types.h" - -#include "../../../../C/CpuArch.h" - -namespace NArchive { -namespace NLzma { - -struct CHeader -{ - UInt64 UnpackSize; - bool IsThereFilter; - Byte FilterMethod; - Byte LzmaProps[5]; - - UInt32 GetDicSize() const { return GetUi32(LzmaProps + 1); } - bool HasUnpackSize() const { return (UnpackSize != (UInt64)(Int64)-1); } - unsigned GetHeaderSize() const { return 5 + 8 + (IsThereFilter ? 1 : 0); } -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Lzma/StdAfx.h b/CPP/7zip/Archive/Lzma/StdAfx.h deleted file mode 100755 index e7fb6986..00000000 --- a/CPP/7zip/Archive/Lzma/StdAfx.h +++ /dev/null @@ -1,8 +0,0 @@ -// StdAfx.h - -#ifndef __STDAFX_H -#define __STDAFX_H - -#include "../../../Common/MyWindows.h" - -#endif diff --git a/CPP/7zip/Archive/LzmaHandler.cpp b/CPP/7zip/Archive/LzmaHandler.cpp new file mode 100755 index 00000000..5dd0aac7 --- /dev/null +++ b/CPP/7zip/Archive/LzmaHandler.cpp @@ -0,0 +1,436 @@ +// LzmaHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/ComTry.h" +#include "Common/IntToString.h" + +#include "Windows/PropVariant.h" + +#include "../Common/CreateCoder.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/LzmaDecoder.h" + +#include "Common/DummyOutStream.h" + +using namespace NWindows; + +namespace NArchive { +namespace NLzma { + +static bool CheckDicSize(const Byte *p) +{ + UInt32 dicSize = GetUi32(p); + for (int i = 1; i <= 30; i++) + if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i)) + return true; + return (dicSize == 0xFFFFFFFF); +} + +STATPROPSTG kProps[] = +{ + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMethod, VT_BSTR} +}; + +struct CHeader +{ + UInt64 Size; + Byte FilterID; + Byte LzmaProps[5]; + + UInt32 GetDicSize() const { return GetUi32(LzmaProps + 1); } + bool HasSize() const { return (Size != (UInt64)(Int64)-1); } + bool Parse(const Byte *buf, bool isThereFilter); +}; + +bool CHeader::Parse(const Byte *buf, bool isThereFilter) +{ + FilterID = 0; + if (isThereFilter) + FilterID = buf[0]; + const Byte *sig = buf + (isThereFilter ? 1 : 0); + for (int i = 0; i < 5; i++) + LzmaProps[i] = sig[i]; + Size = GetUi64(sig + 5); + return + LzmaProps[0] < 5 * 5 * 9 && + FilterID < 2 && + (!HasSize() || Size < ((UInt64)1 << 56)) && + CheckDicSize(LzmaProps + 1); +} + +class CDecoder +{ + NCompress::NLzma::CDecoder *_lzmaDecoderSpec; + CMyComPtr<ICompressCoder> _lzmaDecoder; + CMyComPtr<ISequentialOutStream> _bcjStream; +public: + ~CDecoder(); + HRESULT Create(DECL_EXTERNAL_CODECS_LOC_VARS + bool filtered, ISequentialInStream *inStream); + + HRESULT Code(const CHeader &header, ISequentialOutStream *outStream, ICompressProgressInfo *progress); + + UInt64 GetInputProcessedSize() const { return _lzmaDecoderSpec->GetInputProcessedSize(); } + + void ReleaseInStream() { if (_lzmaDecoder) _lzmaDecoderSpec->ReleaseInStream(); } + + HRESULT ReadInput(Byte *data, UInt32 size, UInt32 *processedSize) + { return _lzmaDecoderSpec->ReadFromInputStream(data, size, processedSize); } +}; + +static const UInt64 k_BCJ = 0x03030103; + +HRESULT CDecoder::Create( + DECL_EXTERNAL_CODECS_LOC_VARS + bool filteredMode, ISequentialInStream *inStream) +{ + if (!_lzmaDecoder) + { + _lzmaDecoderSpec = new NCompress::NLzma::CDecoder; + _lzmaDecoder = _lzmaDecoderSpec; + } + + if (filteredMode) + { + if (!_bcjStream) + { + CMyComPtr<ICompressCoder> coder; + RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_BCJ, coder, false)); + if (!coder) + return E_NOTIMPL; + coder.QueryInterface(IID_ISequentialOutStream, &_bcjStream); + if (!_bcjStream) + return E_NOTIMPL; + } + } + + return _lzmaDecoderSpec->SetInStream(inStream); +} + +CDecoder::~CDecoder() +{ + ReleaseInStream(); +} + +HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream, + ICompressProgressInfo *progress) +{ + if (header.FilterID > 1) + return E_NOTIMPL; + + { + CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; + _lzmaDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); + if (!setDecoderProperties) + return E_NOTIMPL; + RINOK(setDecoderProperties->SetDecoderProperties2(header.LzmaProps, 5)); + } + + CMyComPtr<ICompressSetOutStream> setOutStream; + + bool filteredMode = (header.FilterID == 1); + + if (filteredMode) + { + _bcjStream.QueryInterface(IID_ICompressSetOutStream, &setOutStream); + if (!setOutStream) + return E_NOTIMPL; + RINOK(setOutStream->SetOutStream(outStream)); + outStream = _bcjStream; + } + + const UInt64 *Size = header.HasSize() ? &header.Size : NULL; + HRESULT res = _lzmaDecoderSpec->CodeResume(outStream, Size, progress); + + if (filteredMode) + { + CMyComPtr<IOutStreamFlush> flush; + _bcjStream.QueryInterface(IID_IOutStreamFlush, &flush); + if (flush) + { + HRESULT res2 = flush->Flush(); + if (res == S_OK) + res = res2; + } + HRESULT res2 = setOutStream->ReleaseOutStream(); + if (res == S_OK) + res = res2; + } + RINOK(res); + + return S_OK; +} + + +class CHandler: + public IInArchive, + public IArchiveOpenSeq, + PUBLIC_ISetCompressCodecsInfo + public CMyUnknownImp +{ + CHeader _header; + bool _lzma86; + UInt64 _startPosition; + UInt64 _packSize; + bool _packSizeDefined; + CMyComPtr<IInStream> _stream; + CMyComPtr<ISequentialInStream> _seqStream; + + DECL_EXTERNAL_CODECS_VARS + DECL_ISetCompressCodecsInfo + +public: + MY_QUERYINTERFACE_BEGIN + MY_QUERYINTERFACE_ENTRY(IInArchive) + MY_QUERYINTERFACE_ENTRY(IArchiveOpenSeq) + QUERY_ENTRY_ISetCompressCodecsInfo + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + INTERFACE_IInArchive(;) + STDMETHOD(OpenSeq)(ISequentialInStream *stream); + + CHandler(bool lzma86) { _lzma86 = lzma86; } + + unsigned GetHeaderSize() const { return 5 + 8 + (_lzma86 ? 1 : 0); } + +}; + +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; +} + +static void DictSizeToString(UInt32 value, char *s) +{ + for (int i = 0; i <= 31; i++) + if ((UInt32(1) << i) == value) + { + ::ConvertUInt32ToString(i, s); + return; + } + char c = 'b'; + if ((value & ((1 << 20) - 1)) == 0) + { + value >>= 20; + c = 'm'; + } + else if ((value & ((1 << 10) - 1)) == 0) + { + value >>= 10; + c = 'k'; + } + ::ConvertUInt32ToString(value, s); + int p = MyStringLen(s); + s[p++] = c; + s[p++] = '\0'; +} + +static void MyStrCat(char *d, const char *s) +{ + MyStringCopy(d + MyStringLen(d), s); +} + +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidSize: if (_stream && _header.HasSize()) prop = _header.Size; break; + case kpidPackSize: if (_packSizeDefined) prop = _packSize; break; + case kpidMethod: + if (_stream) + { + char s[64]; + s[0] = '\0'; + if (_header.FilterID != 0) + MyStrCat(s, "BCJ "); + MyStrCat(s, "LZMA:"); + DictSizeToString(_header.GetDicSize(), s + MyStringLen(s)); + prop = s; + } + break; + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *) +{ + RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &_startPosition)); + + const UInt32 kBufSize = 1 + 5 + 8 + 1; + Byte buf[kBufSize]; + + RINOK(ReadStream_FALSE(inStream, buf, kBufSize)); + + if (!_header.Parse(buf, _lzma86)) + return S_FALSE; + const Byte *start = buf + GetHeaderSize(); + if (start[0] != 0) + return S_FALSE; + + UInt64 endPos; + RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); + _packSize = endPos - _startPosition; + _packSizeDefined = true; + + _stream = inStream; + _seqStream = inStream; + return S_OK; +} + +STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) +{ + Close(); + _seqStream = stream; + return S_OK; +} + +STDMETHODIMP CHandler::Close() +{ + _packSizeDefined = false; + _stream.Release(); + _seqStream.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); + + + 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); + + 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); + + if (_stream) + { + RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); + } + + CDecoder decoder; + HRESULT result = decoder.Create( + EXTERNAL_CODECS_VARS + _lzma86, _seqStream); + RINOK(result); + + Int32 opRes = NArchive::NExtract::NOperationResult::kOK; + bool firstItem = true; + + for (;;) + { + lps->OutSize = outStreamSpec->GetSize(); + lps->InSize = _packSize = decoder.GetInputProcessedSize(); + _packSizeDefined = true; + RINOK(lps->SetCur()); + + CHeader st; + + const UInt32 kBufSize = 1 + 5 + 8; + Byte buf[kBufSize]; + const UInt32 headerSize = GetHeaderSize(); + UInt32 processed; + RINOK(decoder.ReadInput(buf, headerSize, &processed)); + if (processed != headerSize) + break; + + if (!st.Parse(buf, _lzma86)) + break; + firstItem = false; + + result = decoder.Code(st, outStream, progress); + if (result == E_NOTIMPL) + { + opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; + break; + } + if (result == S_FALSE) + { + opRes = NArchive::NExtract::NOperationResult::kDataError; + break; + } + RINOK(result); + } + if (firstItem) + return E_FAIL; + outStream.Release(); + return extractCallback->SetOperationResult(opRes); + COM_TRY_END +} + +IMPL_ISetCompressCodecsInfo + +static IInArchive *CreateArc() { return new CHandler(false); } +static IInArchive *CreateArc86() { return new CHandler(true); } + +namespace NLzmaAr { + +static CArcInfo g_ArcInfo = + { L"lzma", L"lzma", 0, 0xA, { 0 }, 0, true, CreateArc, NULL }; +REGISTER_ARC(Lzma) + +} + +namespace NLzma86Ar { + +static CArcInfo g_ArcInfo = + { L"lzma86", L"lzma86", 0, 0xB, { 0 }, 0, true, CreateArc86, NULL }; +REGISTER_ARC(Lzma86) + +} + +}} diff --git a/CPP/7zip/Archive/MachoHandler.cpp b/CPP/7zip/Archive/MachoHandler.cpp index 76f63a21..342a8e76 100755 --- a/CPP/7zip/Archive/MachoHandler.cpp +++ b/CPP/7zip/Archive/MachoHandler.cpp @@ -16,8 +16,6 @@ #include "../Compress/CopyCoder.h" -#include "Common/DummyOutStream.h" - static UInt32 Get32(const Byte *p, int be) { if (be) return GetBe32(p); return GetUi32(p); } static UInt64 Get64(const Byte *p, int be) { if (be) return GetBe64(p); return GetUi64(p); } @@ -35,8 +33,8 @@ namespace NMacho { #define MACH_MACHINE_PPC64 (MACH_ARCH_ABI64 | MACH_MACHINE_PPC) #define MACH_MACHINE_AMD64 (MACH_ARCH_ABI64 | MACH_MACHINE_386) -#define MACH_CMD_SEGMENT_32 1 -#define MACH_CMD_SEGMENT_64 0x19 +#define MACH_CMD_SEGMENT_32 1 +#define MACH_CMD_SEGMENT_64 0x19 #define MACH_SECT_TYPE_MASK 0x000000FF #define MACH_SECT_ATTR_MASK 0xFFFFFF00 @@ -427,22 +425,10 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); - - - - - - - - - CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<ISequentialInStream> inStream(streamSpec); streamSpec->SetStream(_inStream); - CDummyOutStream *outStreamSpec = new CDummyOutStream; - CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); - for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) { lps->InSize = lps->OutSize = currentTotalSize; @@ -453,24 +439,19 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, UInt32 index = allFilesMode ? i : indices[i]; const CSection &item = _sections[index]; currentItemSize = item.GetPackSize(); - { - CMyComPtr<ISequentialOutStream> realOutStream; - RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - if (!testMode && (!realOutStream)) - continue; - outStreamSpec->SetStream(realOutStream); - outStreamSpec->Init(); - } + + CMyComPtr<ISequentialOutStream> outStream; + RINOK(extractCallback->GetStream(index, &outStream, askMode)); + if (!testMode && !outStream) + continue; RINOK(extractCallback->PrepareOperation(askMode)); RINOK(_inStream->Seek(item.Pa, STREAM_SEEK_SET, NULL)); streamSpec->Init(currentItemSize); RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); - outStreamSpec->ReleaseStream(); - RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == currentItemSize) ? - + outStream.Release(); + RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == currentItemSize ? NArchive::NExtract::NOperationResult::kOK: - NArchive::NExtract::NOperationResult::kDataError)); } return S_OK; @@ -485,4 +466,3 @@ static CArcInfo g_ArcInfo = REGISTER_ARC(Macho) }} -
\ No newline at end of file diff --git a/CPP/7zip/Archive/MbrHandler.cpp b/CPP/7zip/Archive/MbrHandler.cpp new file mode 100755 index 00000000..47b18f15 --- /dev/null +++ b/CPP/7zip/Archive/MbrHandler.cpp @@ -0,0 +1,508 @@ +// MbrHandler.cpp + +#include "StdAfx.h" + +// #define SHOW_DEBUG_INFO + +#ifdef SHOW_DEBUG_INFO +#include <stdio.h> +#endif + +#include "../../../C/CpuArch.h" + +#include "Common/Buffer.h" +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/MyString.h" + +#include "Windows/PropVariant.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + +using namespace NWindows; + +namespace NArchive { +namespace NMbr { + +struct CChs +{ + Byte Head; + Byte SectCyl; + Byte Cyl8; + + UInt32 GetSector() const { return SectCyl & 0x3F; } + UInt32 GetCyl() const { return ((UInt32)SectCyl >> 6 << 8) | Cyl8; } + void ToString(NCOM::CPropVariant &prop) const; + + void Parse(const Byte *p) + { + Head = p[0]; + SectCyl = p[1]; + Cyl8 = p[2]; + } + bool Check() const { return GetSector() > 0; } +}; + +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } + +static int CompareChs(const CChs &c1, const CChs &c2) +{ + RINOZ(MyCompare(c1.GetCyl(), c2.GetCyl())); + RINOZ(MyCompare(c1.Head, c2.Head)); + return MyCompare(c1.GetSector(), c2.GetSector()); +} + +static void AddUIntToString(UInt32 val, AString &res) +{ + char s[16]; + ConvertUInt32ToString(val, s); + res += s; +} + +void CChs::ToString(NCOM::CPropVariant &prop) const +{ + AString s; + AddUIntToString(GetCyl(), s); + s += '-'; + AddUIntToString(Head, s); + s += '-'; + AddUIntToString(GetSector(), s); + prop = s; +} + +struct CPartition +{ + Byte Status; + CChs BeginChs; + Byte Type; + CChs EndChs; + UInt32 Lba; + UInt32 NumBlocks; + + CPartition() { memset (this, 0, sizeof(*this)); } + + bool IsEmpty() const { return Type == 0; } + bool IsExtended() const { return Type == 5 || Type == 0xF; } + UInt32 GetLimit() const { return Lba + NumBlocks; } + // bool IsActive() const { return Status == 0x80; } + UInt64 GetPos() const { return (UInt64)Lba * 512; } + UInt64 GetSize() const { return (UInt64)NumBlocks * 512; } + + bool CheckLbaLimits() const { return (UInt32)0xFFFFFFFF - Lba >= NumBlocks; } + bool Parse(const Byte *p) + { + Status = p[0]; + BeginChs.Parse(p + 1); + Type = p[4]; + EndChs.Parse(p + 5); + Lba = GetUi32(p + 8); + NumBlocks = GetUi32(p + 12); + if (Type == 0) + return true; + if (Status != 0 && Status != 0x80) + return false; + return + BeginChs.Check() && + EndChs.Check() && + CompareChs(BeginChs, EndChs) <= 0 && + NumBlocks > 0 && + CheckLbaLimits(); + } + + #ifdef SHOW_DEBUG_INFO + void Print() const + { + NCOM::CPropVariant prop, prop2; + BeginChs.ToString(prop); + EndChs.ToString(prop2); + printf(" %2x %2x %8X %8X %12S %12S", (int)Status, (int)Type, Lba, NumBlocks, prop.bstrVal, prop2.bstrVal); + } + #endif +}; + +struct CPartType +{ + UInt32 Id; + const char *Ext; + const char *Name; +}; + +static const char *kFat = "fat"; + +static const CPartType kPartTypes[] = +{ + { 0x01, kFat, "FAT12" }, + { 0x04, kFat, "FAT16 DOS 3.0+" }, + { 0x05, 0, "Extended" }, + { 0x06, kFat, "FAT16 DOS 3.31+" }, + { 0x07, "ntfs", "NTFS" }, + { 0x0B, kFat, "FAT32" }, + { 0x0C, kFat, "FAT32-LBA" }, + { 0x0E, kFat, "FAT16-LBA" }, + { 0x0F, 0, "Extended-LBA" }, + { 0x11, kFat, "FAT12-Hidden" }, + { 0x14, kFat, "FAT16-Hidden < 32 MB" }, + { 0x16, kFat, "FAT16-Hidden >= 32 MB" }, + { 0x1B, kFat, "FAT32-Hidden" }, + { 0x1C, kFat, "FAT32-LBA-Hidden" }, + { 0x1E, kFat, "FAT16-LBA-WIN95-Hidden" }, + { 0x82, 0, "Solaris x86 / Linux swap" }, + { 0x83, 0, "Linux" }, + { 0xBE, 0, "Solaris 8 boot" }, + { 0xBF, 0, "New Solaris x86" }, + { 0xC2, 0, "Linux-Hidden" }, + { 0xC3, 0, "Linux swap-Hidden" }, + { 0xEE, 0, "EFI-MBR" }, + { 0xEE, 0, "EFI" } +}; + +static int FindPartType(UInt32 type) +{ + for (int i = 0; i < sizeof(kPartTypes) / sizeof(kPartTypes[0]); i++) + if (kPartTypes[i].Id == type) + return i; + return -1; +} + +struct CItem +{ + bool IsReal; + bool IsPrim; + UInt64 Size; + CPartition Part; +}; + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + CMyComPtr<IInStream> _stream; + CObjectVector<CItem> _items; + UInt64 _totalSize; + CByteBuffer _buffer; + + HRESULT ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int level); +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int level) +{ + if (level >= 128 || _items.Size() >= 128) + return S_FALSE; + + const int kNumHeaderParts = 4; + CPartition parts[kNumHeaderParts]; + + { + const UInt32 kSectorSize = 512; + _buffer.SetCapacity(kSectorSize); + Byte *buf = _buffer; + UInt64 newPos = (UInt64)lba << 9; + if (newPos + 512 > _totalSize) + return S_FALSE; + RINOK(stream->Seek(newPos, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream_FALSE(stream, buf, kSectorSize)); + + if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA) + return S_FALSE; + + for (int i = 0; i < kNumHeaderParts; i++) + if (!parts[i].Parse(buf + 0x1BE + 16 * i)) + return S_FALSE; + } + + PRF(printf("\n# %8X", lba)); + + UInt32 limLba = lba + 1; + if (limLba == 0) + return S_FALSE; + + for (int i = 0; i < kNumHeaderParts; i++) + { + CPartition &part = parts[i]; + + if (part.IsEmpty()) + continue; + PRF(printf("\n %2d ", (int)level)); + #ifdef SHOW_DEBUG_INFO + part.Print(); + #endif + + int numItems = _items.Size(); + UInt32 newLba = lba + part.Lba; + + if (part.IsExtended()) + { + // if (part.Type == 5) // Check it! + newLba = baseLba + part.Lba; + if (newLba < limLba) + return S_FALSE; + HRESULT res = ReadTables(stream, level < 1 ? newLba : baseLba, newLba, level + 1); + if (res != S_FALSE && res != S_OK) + return res; + } + if (newLba < limLba) + return S_FALSE; + part.Lba = newLba; + if (!part.CheckLbaLimits()) + return S_FALSE; + + CItem n; + n.Part = part; + bool addItem = false; + if (numItems == _items.Size()) + { + n.IsPrim = (level == 0); + n.IsReal = true; + addItem = true; + } + else + { + const CItem &back = _items.Back(); + UInt32 backLimit = back.Part.GetLimit(); + UInt32 partLimit = part.GetLimit(); + if (backLimit < partLimit) + { + n.IsReal = false; + n.Part.Lba = backLimit; + n.Part.NumBlocks = partLimit - backLimit; + addItem = true; + } + } + if (addItem) + { + if (n.Part.GetLimit() < limLba) + return S_FALSE; + limLba = n.Part.GetLimit(); + n.Size = n.Part.GetSize(); + _items.Add(n); + } + } + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback * /* openArchiveCallback */) +{ + COM_TRY_BEGIN + Close(); + RINOK(stream->Seek(0, STREAM_SEEK_END, &_totalSize)); + RINOK(ReadTables(stream, 0, 0, 0)); + if (_items.IsEmpty()) + return S_FALSE; + UInt32 lbaLimit = _items.Back().Part.GetLimit(); + UInt64 lim = (UInt64)lbaLimit << 9; + if (lim < _totalSize) + { + CItem n; + n.Part.Lba = lbaLimit; + n.Size = _totalSize - lim; + n.IsReal = false; + _items.Add(n); + } + _stream = stream; + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _items.Clear(); + _stream.Release(); + return S_OK; +} + +enum +{ + kpidPrimary = kpidUserDefined, + kpidBegChs, + kpidEndChs, +}; + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidFileSystem, VT_BSTR}, + { NULL, kpidOffset, VT_UI8}, + { L"Primary", kpidPrimary, VT_BOOL}, + { L"Begin CHS", kpidBegChs, VT_BSTR}, + { L"End CHS", kpidEndChs, VT_BSTR} +}; + +IMP_IInArchive_Props_WITH_NAME +IMP_IInArchive_ArcProps_NO_Table + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidMainSubfile: + { + int mainIndex = -1; + for (int i = 0; i < _items.Size(); i++) + if (_items[i].IsReal) + { + if (mainIndex >= 0) + { + mainIndex = -1; + break; + } + mainIndex = i; + } + if (mainIndex >= 0) + prop = (UInt32)mainIndex; + break; + } + } + prop.Detach(value); + 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 + NCOM::CPropVariant prop; + + const CItem &item = _items[index]; + const CPartition &part = item.Part; + switch(propID) + { + case kpidPath: + { + AString s; + AddUIntToString(index, s); + if (item.IsReal) + { + int typeIndex = FindPartType(part.Type); + s += '.'; + const char *ext = "img"; + if (typeIndex >= 0 && kPartTypes[typeIndex].Ext != 0) + ext = kPartTypes[typeIndex].Ext; + s += ext; + } + prop = s; + break; + } + case kpidFileSystem: + if (item.IsReal) + { + char s[32]; + ConvertUInt32ToString(part.Type, s); + const char *res = s; + int typeIndex = FindPartType(part.Type); + if (typeIndex >= 0 && kPartTypes[typeIndex].Name) + res = kPartTypes[typeIndex].Name; + prop = res; + } + break; + case kpidSize: prop = item.Size; break;; + case kpidPackSize: prop = item.Size; break; + case kpidOffset: prop = part.GetPos(); break; + case kpidPrimary: if (item.IsReal) prop = item.IsPrim; break; + case kpidBegChs: if (item.IsReal) part.BeginChs.ToString(prop); break; + case kpidEndChs: if (item.IsReal) part.EndChs.ToString(prop); 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); + + totalSize = 0; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr<ISequentialInStream> inStream(streamSpec); + streamSpec->SetStream(_stream); + + for (i = 0; i < numItems; i++) + { + lps->InSize = totalSize; + lps->OutSize = totalSize; + RINOK(lps->SetCur()); + CMyComPtr<ISequentialOutStream> outStream; + Int32 askMode = testMode ? + NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + const CItem &item = _items[index]; + const CPartition &part = item.Part; + RINOK(extractCallback->GetStream(index, &outStream, askMode)); + totalSize += item.Size; + if (!testMode && (!outStream)) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + + RINOK(_stream->Seek(part.GetPos(), STREAM_SEEK_SET, NULL)); + streamSpec->Init(item.Size); + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + outStream.Release(); + RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == item.Size ? + NArchive::NExtract::NOperationResult::kOK: + NArchive::NExtract::NOperationResult::kDataError)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + const CItem &item = _items[index]; + return CreateLimitedInStream(_stream, item.Part.GetPos(), item.Size, stream); + COM_TRY_END +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"MBR", L"mbr", 0, 0xDB, { 1, 1, 0 }, 3, false, CreateArc, 0 }; + +REGISTER_ARC(Mbr) + +}} diff --git a/CPP/7zip/Archive/MubHandler.cpp b/CPP/7zip/Archive/MubHandler.cpp index 25c3815e..f099aad2 100755 --- a/CPP/7zip/Archive/MubHandler.cpp +++ b/CPP/7zip/Archive/MubHandler.cpp @@ -34,22 +34,23 @@ const UInt32 kNumFilesMax = 10; class CHandler: public IInArchive, + public IInArchiveGetStream, public CMyUnknownImp { UInt64 _startPos; - CMyComPtr<IInStream> _inStream; + CMyComPtr<IInStream> _stream; UInt32 _numItems; CItem _items[kNumFilesMax + 1]; HRESULT Open2(IInStream *stream); public: - MY_UNKNOWN_IMP1(IInArchive) + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; STATPROPSTG kProps[] = { - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8} + { NULL, kpidSize, VT_UI8} }; IMP_IInArchive_Props @@ -166,7 +167,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, { if (Open2(inStream) != S_OK) return S_FALSE; - _inStream = inStream; + _stream = inStream; } catch(...) { return S_FALSE; } return S_OK; @@ -175,7 +176,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, STDMETHODIMP CHandler::Close() { - _inStream.Release(); + _stream.Release(); _numItems = 0; return S_OK; } @@ -203,7 +204,6 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, extractCallback->SetTotal(totalSize); UInt64 currentTotalSize = 0; - UInt64 currentItemSize; NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; @@ -214,9 +214,9 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<ISequentialInStream> inStream(streamSpec); - streamSpec->SetStream(_inStream); + streamSpec->SetStream(_stream); - for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) + for (i = 0; i < numItems; i++) { lps->InSize = lps->OutSize = currentTotalSize; RINOK(lps->SetCur()); @@ -227,12 +227,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, UInt32 index = allFilesMode ? i : indices[i]; const CItem &item = _items[index]; RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - currentItemSize = item.Size; - - - - - + currentTotalSize += item.Size; if (!testMode && (!realOutStream)) continue; @@ -242,7 +237,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); continue; } - RINOK(_inStream->Seek(_startPos + item.Offset, STREAM_SEEK_SET, NULL)); + RINOK(_stream->Seek(_startPos + item.Offset, STREAM_SEEK_SET, NULL)); streamSpec->Init(item.Size); RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); realOutStream.Release(); @@ -254,6 +249,14 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, COM_TRY_END } +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + const CItem &item = _items[index]; + return CreateLimitedInStream(_stream, _startPos + item.Offset, item.Size, stream); + COM_TRY_END +} + static IInArchive *CreateArc() { return new CHandler; } static CArcInfo g_ArcInfo = diff --git a/CPP/7zip/Archive/NtfsHandler.cpp b/CPP/7zip/Archive/NtfsHandler.cpp new file mode 100755 index 00000000..37847a24 --- /dev/null +++ b/CPP/7zip/Archive/NtfsHandler.cpp @@ -0,0 +1,1725 @@ +// NtfsHandler.cpp + +#include "StdAfx.h" + +// #define SHOW_DEBUG_INFO +// #define SHOW_DEBUG_INFO2 + +#if defined(SHOW_DEBUG_INFO) || defined(SHOW_DEBUG_INFO2) +#include <stdio.h> +#endif + +#include "../../../C/CpuArch.h" + +#include "Common/Buffer.h" +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/MyCom.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#include "Common/DummyOutStream.h" + +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + +#ifdef SHOW_DEBUG_INFO2 +#define PRF2(x) x +#else +#define PRF2(x) +#endif + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) +#define Get64(p) GetUi64(p) + +#define G16(p, dest) dest = Get16(p); +#define G32(p, dest) dest = Get32(p); +#define G64(p, dest) dest = Get64(p); + +namespace NArchive { +namespace Ntfs { + +static const UInt32 kNumSysRecs = 16; +static const UInt32 kRecIndex_Volume = 3; +static const UInt32 kRecIndex_BadClus = 8; + +struct CHeader +{ + Byte SectorSizeLog; + Byte ClusterSizeLog; + // Byte MediaType; + UInt32 NumHiddenSectors; + UInt64 NumClusters; + UInt64 MftCluster; + UInt64 SerialNumber; + UInt16 SectorsPerTrack; + UInt16 NumHeads; + + UInt64 GetPhySize() const { return NumClusters << ClusterSizeLog; } + UInt32 ClusterSize() const { return (UInt32)1 << ClusterSizeLog; } + bool Parse(const Byte *p); +}; + +static int GetLog(UInt32 num) +{ + for (int i = 0; i < 31; i++) + if (((UInt32)1 << i) == num) + return i; + return -1; +} + +bool CHeader::Parse(const Byte *p) +{ + if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA) + return false; + + int codeOffset = 0; + switch (p[0]) + { + case 0xE9: codeOffset = 3 + (Int16)Get16(p + 1); break; + case 0xEB: if (p[2] != 0x90) return false; codeOffset = 2 + (signed char)p[1]; break; + default: return false; + } + Byte sectorsPerClusterLog; + + if (memcmp(p + 3, "NTFS ", 8) != 0) + return false; + { + int s = GetLog(Get16(p + 11)); + if (s < 9 || s > 12) + return false; + SectorSizeLog = (Byte)s; + s = GetLog(p[13]); + if (s < 0) + return false; + sectorsPerClusterLog = (Byte)s; + ClusterSizeLog = SectorSizeLog + sectorsPerClusterLog; + } + + for (int i = 14; i < 21; i++) + if (p[i] != 0) + return false; + + // MediaType = p[21]; + if (Get16(p + 22) != 0) // NumFatSectors + return false; + G16(p + 24, SectorsPerTrack); + G16(p + 26, NumHeads); + G32(p + 28, NumHiddenSectors); + if (Get32(p + 32) != 0) // NumSectors32 + return false; + + // DriveNumber = p[0x24]; + if (p[0x25] != 0) // CurrentHead + return false; + if (p[0x26] != 0x80) // ExtendedBootSig + return false; + if (p[0x27] != 0) // reserved + return false; + UInt64 numSectors = Get64(p + 0x28); + NumClusters = numSectors >> sectorsPerClusterLog; + + G64(p + 0x30, MftCluster); + // G64(p + 0x38, Mft2Cluster); + G64(p + 0x48, SerialNumber); + UInt32 numClustersInMftRec; + UInt32 numClustersInIndexBlock; + G32(p + 0x40, numClustersInMftRec); + G32(p + 0x44, numClustersInIndexBlock); + return (numClustersInMftRec < 256 && numClustersInIndexBlock < 256); +} + +struct CMftRef +{ + UInt64 Val; + UInt64 GetIndex() const { return Val & (((UInt64)1 << 48) - 1); } + UInt16 GetNumber() const { return (UInt16)(Val >> 48); } + bool IsBaseItself() const { return Val == 0; } +}; + +#define ATNAME(n) ATTR_TYPE_ ## n +#define DEF_ATTR_TYPE(v, n) ATNAME(n) = v + +typedef enum +{ + DEF_ATTR_TYPE(0x00, UNUSED), + DEF_ATTR_TYPE(0x10, STANDARD_INFO), + DEF_ATTR_TYPE(0x20, ATTRIBUTE_LIST), + DEF_ATTR_TYPE(0x30, FILE_NAME), + DEF_ATTR_TYPE(0x40, OBJECT_ID), + DEF_ATTR_TYPE(0x50, SECURITY_DESCRIPTOR), + DEF_ATTR_TYPE(0x60, VOLUME_NAME), + DEF_ATTR_TYPE(0x70, VOLUME_INFO), + DEF_ATTR_TYPE(0x80, DATA), + DEF_ATTR_TYPE(0x90, INDEX_ROOT), + DEF_ATTR_TYPE(0xA0, INDEX_ALLOCATION), + DEF_ATTR_TYPE(0xB0, BITMAP), + DEF_ATTR_TYPE(0xC0, REPARSE_POINT), + DEF_ATTR_TYPE(0xD0, EA_INFO), + DEF_ATTR_TYPE(0xE0, EA), + DEF_ATTR_TYPE(0xF0, PROPERTY_SET), + DEF_ATTR_TYPE(0x100, LOGGED_UTILITY_STREAM), + DEF_ATTR_TYPE(0x1000, FIRST_USER_DEFINED_ATTRIBUTE) +}; + +static const Byte kFileNameType_Posix = 0; +static const Byte kFileNameType_Win32 = 1; +static const Byte kFileNameType_Dos = 2; +static const Byte kFileNameType_Win32Dos = 3; + +struct CFileNameAttr +{ + CMftRef ParentDirRef; + // UInt64 CTime; + // UInt64 MTime; + // UInt64 ThisRecMTime; + // UInt64 ATime; + // UInt64 AllocatedSize; + // UInt64 DataSize; + // UInt16 PackedEaSize; + UString Name; + UInt32 Attrib; + Byte NameType; + + bool IsDos() const { return NameType == kFileNameType_Dos; } + bool Parse(const Byte *p, unsigned size); +}; + +static void GetString(const Byte *p, unsigned length, UString &res) +{ + wchar_t *s = res.GetBuffer(length); + for (unsigned i = 0; i < length; i++) + s[i] = Get16(p + i * 2); + s[length] = 0; + res.ReleaseBuffer(); +} + +bool CFileNameAttr::Parse(const Byte *p, unsigned size) +{ + if (size < 0x42) + return false; + G64(p + 0x00, ParentDirRef.Val); + // G64(p + 0x08, CTime); + // G64(p + 0x10, MTime); + // G64(p + 0x18, ThisRecMTime); + // G64(p + 0x20, ATime); + // G64(p + 0x28, AllocatedSize); + // G64(p + 0x30, DataSize); + G32(p + 0x38, Attrib); + // G16(p + 0x3C, PackedEaSize); + NameType = p[0x41]; + unsigned length = p[0x40]; + if (0x42 + length > size) + return false; + GetString(p + 0x42, length, Name); + return true; +} + +struct CSiAttr +{ + UInt64 CTime; + UInt64 MTime; + // UInt64 ThisRecMTime; + UInt64 ATime; + UInt32 Attrib; + + /* + UInt32 MaxVersions; + UInt32 Version; + UInt32 ClassId; + UInt32 OwnerId; + UInt32 SecurityId; + UInt64 QuotaCharged; + */ + + bool Parse(const Byte *p, unsigned size); +}; + +bool CSiAttr::Parse(const Byte *p, unsigned size) +{ + if (size < 0x24) + return false; + G64(p + 0x00, CTime); + G64(p + 0x08, MTime); + // G64(p + 0x10, ThisRecMTime); + G64(p + 0x18, ATime); + G32(p + 0x20, Attrib); + return true; +} + +static const UInt64 kEmptyExtent = (UInt64)(Int64)-1; + +struct CExtent +{ + UInt64 Virt; + UInt64 Phy; + + bool IsEmpty() const { return Phy == kEmptyExtent; } +}; + +struct CVolInfo +{ + Byte MajorVer; + Byte MinorVer; + // UInt16 Flags; + + bool Parse(const Byte *p, unsigned size); +}; + +bool CVolInfo::Parse(const Byte *p, unsigned size) +{ + if (size < 12) + return false; + MajorVer = p[8]; + MinorVer = p[9]; + // Flags = Get16(p + 10); + return true; +} + +struct CAttr +{ + UInt32 Type; + // UInt32 Length; + UString Name; + // UInt16 Flags; + // UInt16 Instance; + CByteBuffer Data; + Byte NonResident; + + // Non-Resident + Byte CompressionUnit; + UInt64 LowVcn; + UInt64 HighVcn; + UInt64 AllocatedSize; + UInt64 Size; + UInt64 PackSize; + UInt64 InitializedSize; + + // Resident + // UInt16 ResidentFlags; + + bool IsCompressionUnitSupported() const { return CompressionUnit == 0 || CompressionUnit == 4; } + + UInt32 Parse(const Byte *p, unsigned size); + bool ParseFileName(CFileNameAttr &a) const { return a.Parse(Data, (unsigned)Data.GetCapacity()); } + bool ParseSi(CSiAttr &a) const { return a.Parse(Data, (unsigned)Data.GetCapacity()); } + bool ParseVolInfo(CVolInfo &a) const { return a.Parse(Data, (unsigned)Data.GetCapacity()); } + bool ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax, int compressionUnit) const; + UInt64 GetSize() const { return NonResident ? Size : Data.GetCapacity(); } + UInt64 GetPackSize() const + { + if (!NonResident) + return Data.GetCapacity(); + if (CompressionUnit != 0) + return PackSize; + return AllocatedSize; + } +}; + +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } + +static int CompareAttr(void *const *elem1, void *const *elem2, void *) +{ + const CAttr &a1 = *(*((const CAttr **)elem1)); + const CAttr &a2 = *(*((const CAttr **)elem2)); + RINOZ(MyCompare(a1.Type, a2.Type)); + RINOZ(MyCompare(a1.Name, a2.Name)); + return MyCompare(a1.LowVcn, a2.LowVcn); +} + +UInt32 CAttr::Parse(const Byte *p, unsigned size) +{ + if (size < 4) + return 0; + G32(p, Type); + if (Type == 0xFFFFFFFF) + return 4; + if (size < 0x18) + return 0; + PRF(printf(" T=%2X", Type)); + + UInt32 length = Get32(p + 0x04); + PRF(printf(" L=%3d", length)); + if (length > size) + return 0; + NonResident = p[0x08]; + { + int nameLength = p[9]; + UInt32 nameOffset = Get16(p + 0x0A); + if (nameLength != 0) + { + if (nameOffset + nameLength * 2 > length) + return 0; + GetString(p + nameOffset, nameLength, Name); + PRF(printf(" N=%S", Name)); + } + } + + // G16(p + 0x0C, Flags); + // G16(p + 0x0E, Instance); + // PRF(printf(" F=%4X", Flags)); + // PRF(printf(" Inst=%d", Instance)); + + UInt32 dataSize; + UInt32 offs; + if (NonResident) + { + if (length < 0x40) + return 0; + PRF(printf(" NR")); + G64(p + 0x10, LowVcn); + G64(p + 0x18, HighVcn); + G64(p + 0x28, AllocatedSize); + G64(p + 0x30, Size); + G64(p + 0x38, InitializedSize); + G16(p + 0x20, offs); + CompressionUnit = p[0x22]; + + PackSize = Size; + if (CompressionUnit != 0) + { + if (length < 0x48) + return 0; + G64(p + 0x40, PackSize); + PRF(printf(" PS=%I64x", PackSize)); + } + + // PRF(printf("\n")); + PRF(printf(" ASize=%4I64d", AllocatedSize)); + PRF(printf(" Size=%I64d", Size)); + PRF(printf(" IS=%I64d", InitializedSize)); + PRF(printf(" Low=%I64d", LowVcn)); + PRF(printf(" High=%I64d", HighVcn)); + PRF(printf(" CU=%d", (int)CompressionUnit)); + dataSize = length - offs; + } + else + { + if (length < 0x18) + return 0; + PRF(printf(" RES")); + dataSize = Get32(p + 0x10); + PRF(printf(" dataSize=%3d", dataSize)); + offs = Get16(p + 0x14); + // G16(p + 0x16, ResidentFlags); + // PRF(printf(" ResFlags=%4X", ResidentFlags)); + } + if (offs > length || dataSize > length || length - dataSize < offs) + return 0; + Data.SetCapacity(dataSize); + memcpy(Data, p + offs, dataSize); + #ifdef SHOW_DEBUG_INFO + PRF(printf(" : ")); + for (unsigned i = 0; i < Data.GetCapacity(); i++) + { + PRF(printf(" %02X", (int)Data[i])); + } + #endif + return length; +} + +bool CAttr::ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax, int compressionUnit) const +{ + const Byte *p = Data; + unsigned size = (unsigned)Data.GetCapacity(); + UInt64 vcn = LowVcn; + UInt64 lcn = 0; + UInt64 highVcn1 = HighVcn + 1; + if (LowVcn != extents.Back().Virt || highVcn1 > (UInt64)1 << 63) + return false; + + extents.DeleteBack(); + + PRF2(printf("\n# ParseExtents # LowVcn = %4I64X # HighVcn = %4I64X", LowVcn, HighVcn)); + + while (size > 0) + { + Byte b = *p++; + size--; + if (b == 0) + break; + UInt32 num = b & 0xF; + if (num == 0 || num > 8 || num > size) + return false; + + int i; + UInt64 vSize = p[num - 1]; + for (i = (int)num - 2; i >= 0; i--) + vSize = (vSize << 8) | p[i]; + if (vSize == 0) + return false; + p += num; + size -= num; + if ((highVcn1 - vcn) < vSize) + return false; + + num = (b >> 4) & 0xF; + if (num > 8 || num > size) + return false; + CExtent e; + e.Virt = vcn; + if (num == 0) + { + if (compressionUnit == 0) + return false; + e.Phy = kEmptyExtent; + } + else + { + Int64 v = (signed char)p[num - 1]; + for (i = (int)num - 2; i >= 0; i--) + v = (v << 8) | p[i]; + p += num; + size -= num; + lcn += v; + if (lcn > numClustersMax) + return false; + e.Phy = lcn; + } + extents.Add(e); + vcn += vSize; + } + CExtent e; + e.Phy = kEmptyExtent; + e.Virt = vcn; + extents.Add(e); + return (highVcn1 == vcn); +} + +static const UInt64 kEmptyTag = (UInt64)(Int64)-1; + +static const int kNumCacheChunksLog = 1; +static const UInt32 kNumCacheChunks = (1 << kNumCacheChunksLog); + +class CInStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _virtPos; + UInt64 _physPos; + UInt64 _curRem; + bool _sparseMode; + size_t _compressedPos; + + UInt64 _tags[kNumCacheChunks]; + int _chunkSizeLog; + CByteBuffer _inBuf; + CByteBuffer _outBuf; +public: + CMyComPtr<IInStream> Stream; + UInt64 Size; + UInt64 InitializedSize; + int BlockSizeLog; + int CompressionUnit; + bool InUse; + CRecordVector<CExtent> Extents; + + HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); } + + UInt32 GetCuSize() const { return (UInt32)1 << (BlockSizeLog + CompressionUnit); } + HRESULT InitAndSeek(int compressionUnit) + { + CompressionUnit = compressionUnit; + if (compressionUnit != 0) + { + UInt32 cuSize = GetCuSize(); + _inBuf.SetCapacity(cuSize); + _chunkSizeLog = BlockSizeLog + CompressionUnit; + _outBuf.SetCapacity(kNumCacheChunks << _chunkSizeLog); + } + for (int i = 0; i < kNumCacheChunks; i++) + _tags[i] = kEmptyTag; + + _sparseMode = false; + _curRem = 0; + _virtPos = 0; + _physPos = 0; + const CExtent &e = Extents[0]; + if (!e.IsEmpty()) + _physPos = e.Phy << BlockSizeLog; + return SeekToPhys(); + } + + MY_UNKNOWN_IMP1(IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + +static size_t Lznt1Dec(Byte *dest, size_t outBufLim, size_t destLen, const Byte *src, size_t srcLen) +{ + size_t destSize = 0; + while (destSize < destLen) + { + if (srcLen < 2 || (destSize & 0xFFF) != 0) + break; + UInt32 v = Get16(src); + if (v == 0) + break; + src += 2; + srcLen -= 2; + UInt32 comprSize = (v & 0xFFF) + 1; + if (comprSize > srcLen) + break; + srcLen -= comprSize; + if ((v & 0x8000) == 0) + { + if (comprSize != (1 << 12)) + break; + memcpy(dest + destSize, src, comprSize); + src += comprSize; + destSize += comprSize; + } + else + { + if (destSize + (1 << 12) > outBufLim || (src[0] & 1) != 0) + return 0; + int numDistBits = 4; + UInt32 sbOffset = 0; + UInt32 pos = 0; + + do + { + comprSize--; + for (UInt32 mask = src[pos++] | 0x100; mask > 1 && comprSize > 0; mask >>= 1) + { + if ((mask & 1) == 0) + { + if (sbOffset >= (1 << 12)) + return 0; + dest[destSize++] = src[pos++]; + sbOffset++; + comprSize--; + } + else + { + if (comprSize < 2) + return 0; + UInt32 v = Get16(src + pos); + pos += 2; + comprSize -= 2; + + while (((sbOffset - 1) >> numDistBits) != 0) + numDistBits++; + + UInt32 len = (v & (0xFFFF >> numDistBits)) + 3; + if (sbOffset + len > (1 << 12)) + return 0; + UInt32 dist = (v >> (16 - numDistBits)); + if (dist >= sbOffset) + return 0; + Int32 offs = -1 - dist; + Byte *p = dest + destSize; + for (UInt32 t = 0; t < len; t++) + p[t] = p[t + offs]; + destSize += len; + sbOffset += len; + } + } + } + while (comprSize > 0); + src += pos; + } + } + return destSize; +} + +STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + if (_virtPos >= Size) + return (Size == _virtPos) ? S_OK: E_FAIL; + if (size == 0) + return S_OK; + UInt64 rem = Size - _virtPos; + if (size > rem) + size = (UInt32)rem; + if (_virtPos >= InitializedSize) + { + memset((Byte *)data, 0, size); + _virtPos += size; + *processedSize = size; + return S_OK; + } + rem = InitializedSize - _virtPos; + if (size > rem) + size = (UInt32)rem; + + while (_curRem == 0) + { + UInt64 cacheTag = _virtPos >> _chunkSizeLog; + UInt32 cacheIndex = (UInt32)cacheTag & (kNumCacheChunks - 1); + if (_tags[cacheIndex] == cacheTag) + { + UInt32 chunkSize = (UInt32)1 << _chunkSizeLog; + UInt32 offset = (UInt32)_virtPos & (chunkSize - 1); + UInt32 cur = MyMin(chunkSize - offset, size); + memcpy(data, _outBuf + (cacheIndex << _chunkSizeLog) + offset, cur); + *processedSize = cur; + _virtPos += cur; + return S_OK; + } + + PRF2(printf("\nVirtPos = %6d", _virtPos)); + + UInt32 comprUnitSize = (UInt32)1 << CompressionUnit; + UInt64 virtBlock = _virtPos >> BlockSizeLog; + UInt64 virtBlock2 = virtBlock & ~((UInt64)comprUnitSize - 1); + + int left = 0, right = Extents.Size(); + for (;;) + { + int mid = (left + right) / 2; + if (mid == left) + break; + if (virtBlock2 < Extents[mid].Virt) + right = mid; + else + left = mid; + } + + bool isCompressed = false; + UInt64 virtBlock2End = virtBlock2 + comprUnitSize; + if (CompressionUnit != 0) + for (int i = left; i < Extents.Size(); i++) + { + const CExtent &e = Extents[i]; + if (e.Virt >= virtBlock2End) + break; + if (e.IsEmpty()) + { + isCompressed = true; + break; + } + } + + int i; + for (i = left; Extents[i + 1].Virt <= virtBlock; i++); + + _sparseMode = false; + if (!isCompressed) + { + const CExtent &e = Extents[i]; + UInt64 newPos = (e.Phy << BlockSizeLog) + _virtPos - (e.Virt << BlockSizeLog); + if (newPos != _physPos) + { + _physPos = newPos; + RINOK(SeekToPhys()); + } + UInt64 next = Extents[i + 1].Virt; + if (next > virtBlock2End) + next &= ~((UInt64)comprUnitSize - 1); + next <<= BlockSizeLog; + if (next > Size) + next = Size; + _curRem = next - _virtPos; + break; + } + bool thereArePhy = false; + for (int i2 = left; i2 < Extents.Size(); i2++) + { + const CExtent &e = Extents[i2]; + if (e.Virt >= virtBlock2End) + break; + if (!e.IsEmpty()) + { + thereArePhy = true; + break; + } + } + if (!thereArePhy) + { + _curRem = (Extents[i + 1].Virt << BlockSizeLog) - _virtPos; + _sparseMode = true; + break; + } + + size_t offs = 0; + UInt64 curVirt = virtBlock2; + for (i = left; i < Extents.Size(); i++) + { + const CExtent &e = Extents[i]; + if (e.IsEmpty()) + break; + if (e.Virt >= virtBlock2End) + return S_FALSE; + UInt64 newPos = (e.Phy + (curVirt - e.Virt)) << BlockSizeLog; + if (newPos != _physPos) + { + _physPos = newPos; + RINOK(SeekToPhys()); + } + UInt64 numChunks = Extents[i + 1].Virt - curVirt; + if (curVirt + numChunks > virtBlock2End) + numChunks = virtBlock2End - curVirt; + size_t compressed = (size_t)numChunks << BlockSizeLog; + RINOK(ReadStream_FALSE(Stream, _inBuf + offs, compressed)); + curVirt += numChunks; + _physPos += compressed; + offs += compressed; + } + size_t destLenMax = GetCuSize(); + size_t destLen = destLenMax; + UInt64 rem = Size - (virtBlock2 << BlockSizeLog); + if (destLen > rem) + destLen = (size_t)rem; + + Byte *dest = _outBuf + (cacheIndex << _chunkSizeLog); + size_t destSizeRes = Lznt1Dec(dest, destLenMax, destLen, _inBuf, offs); + _tags[cacheIndex] = cacheTag; + + // some files in Vista have destSize > destLen + if (destSizeRes < destLen) + { + memset(dest, 0, destLenMax); + if (InUse) + return S_FALSE; + } + } + if (size > _curRem) + size = (UInt32)_curRem; + HRESULT res = S_OK; + if (_sparseMode) + memset(data, 0, size); + else + { + res = Stream->Read(data, size, &size); + _physPos += size; + } + if (processedSize != NULL) + *processedSize = size; + _virtPos += size; + _curRem -= size; + return res; +} + +STDMETHODIMP CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + UInt64 newVirtPos = offset; + switch(seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: newVirtPos += _virtPos; break; + case STREAM_SEEK_END: newVirtPos += Size; break; + default: return STG_E_INVALIDFUNCTION; + } + if (_virtPos != newVirtPos) + _curRem = 0; + _virtPos = newVirtPos; + if (newPosition) + *newPosition = newVirtPos; + return S_OK; +} + +class CByteBufStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _virtPos; +public: + CByteBuffer Buf; + void Init() { _virtPos = 0; } + + MY_UNKNOWN_IMP1(IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + +STDMETHODIMP CByteBufStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + if (_virtPos >= Buf.GetCapacity()) + return (_virtPos == Buf.GetCapacity()) ? S_OK: E_FAIL; + UInt64 rem = Buf.GetCapacity() - _virtPos; + if (rem < size) + size = (UInt32)rem; + memcpy(data, Buf + (size_t)_virtPos, size); + if (processedSize != NULL) + *processedSize = size; + _virtPos += size; + return S_OK; +} + +STDMETHODIMP CByteBufStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch(seekOrigin) + { + case STREAM_SEEK_SET: _virtPos = offset; break; + case STREAM_SEEK_CUR: _virtPos += offset; break; + case STREAM_SEEK_END: _virtPos = Buf.GetCapacity() + offset; break; + default: return STG_E_INVALIDFUNCTION; + } + if (newPosition) + *newPosition = _virtPos; + return S_OK; +} + +HRESULT DataParseExtents(int clusterSizeLog, const CObjectVector<CAttr> attrs, + int attrIndex, int attrIndexLim, UInt64 numPhysClusters, CRecordVector<CExtent> &Extents) +{ + CExtent e; + e.Virt = 0; + e.Phy = kEmptyExtent; + Extents.Add(e); + const CAttr &attr0 = attrs[attrIndex]; + + if (attr0.AllocatedSize < attr0.Size || + (attrs[attrIndexLim - 1].HighVcn + 1) != (attr0.AllocatedSize >> clusterSizeLog) || + (attr0.AllocatedSize & ((1 << clusterSizeLog) - 1)) != 0) + return S_FALSE; + + for (int i = attrIndex; i < attrIndexLim; i++) + if (!attrs[i].ParseExtents(Extents, numPhysClusters, attr0.CompressionUnit)) + return S_FALSE; + + UInt64 packSizeCalc = 0; + for (int k = 0; k < Extents.Size(); k++) + { + CExtent &e = Extents[k]; + if (!e.IsEmpty()) + packSizeCalc += (Extents[k + 1].Virt - e.Virt) << clusterSizeLog; + PRF2(printf("\nSize = %4I64X", Extents[k + 1].Virt - e.Virt)); + PRF2(printf(" Pos = %4I64X", e.Phy)); + } + + if (attr0.CompressionUnit != 0) + { + if (packSizeCalc != attr0.PackSize) + return S_FALSE; + } + else + { + if (packSizeCalc != attr0.AllocatedSize) + return S_FALSE; + } + return S_OK; +} + +struct CDataRef +{ + int Start; + int Num; +}; + +struct CMftRec +{ + UInt32 Magic; + // UInt64 Lsn; + UInt16 SeqNumber; + UInt16 Flags; + // UInt16 LinkCount; + // UInt16 NextAttrInstance; + CMftRef BaseMftRef; + // UInt32 ThisRecNumber; + UInt32 MyNumNameLinks; + + CObjectVector<CAttr> DataAttrs; + CObjectVector<CFileNameAttr> FileNames; + CRecordVector<CDataRef> DataRefs; + + CSiAttr SiAttr; + + + void MoveAttrsFrom(CMftRec &src) + { + DataAttrs += src.DataAttrs; + FileNames += src.FileNames; + src.DataAttrs.ClearAndFree(); + src.FileNames.ClearAndFree(); + } + + UInt64 GetPackSize() const + { + UInt64 res = 0; + for (int i = 0; i < DataRefs.Size(); i++) + res += DataAttrs[DataRefs[i].Start].GetPackSize(); + return res; + } + + bool Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNumber, CObjectVector<CAttr> *attrs); + + bool IsEmpty() const { return (Magic <= 2); } + + bool InUse() const { return (Flags & 1) != 0; } + bool IsDir() const { return (Flags & 2) != 0; } + + void ParseDataNames(); + HRESULT GetStream(IInStream *mainStream, int dataIndex, + int clusterSizeLog, UInt64 numPhysClusters, IInStream **stream) const; + + UInt64 GetSize(int dataIndex) const { return DataAttrs[DataRefs[dataIndex].Start].GetSize(); } + + CMftRec(): MyNumNameLinks(0) {} +}; + +void CMftRec::ParseDataNames() +{ + DataRefs.Clear(); + DataAttrs.Sort(CompareAttr, 0); + + for (int i = 0; i < DataAttrs.Size();) + { + CDataRef ref; + ref.Start = i; + for (i++; i < DataAttrs.Size(); i++) + if (DataAttrs[ref.Start].Name != DataAttrs[i].Name) + break; + ref.Num = i - ref.Start; + DataRefs.Add(ref); + } +} + +HRESULT CMftRec::GetStream(IInStream *mainStream, int dataIndex, + int clusterSizeLog, UInt64 numPhysClusters, IInStream **destStream) const +{ + *destStream = 0; + CByteBufStream *streamSpec = new CByteBufStream; + CMyComPtr<IInStream> streamTemp = streamSpec; + + if (dataIndex < 0) + return E_FAIL; + + if (dataIndex < DataRefs.Size()) + { + const CDataRef &ref = DataRefs[dataIndex]; + int numNonResident = 0; + int i; + for (i = ref.Start; i < ref.Start + ref.Num; i++) + if (DataAttrs[i].NonResident) + numNonResident++; + + const CAttr &attr0 = DataAttrs[ref.Start]; + + if (numNonResident != 0 || ref.Num != 1) + { + if (numNonResident != ref.Num || !attr0.IsCompressionUnitSupported()) + return S_FALSE; + CInStream *streamSpec = new CInStream; + CMyComPtr<IInStream> streamTemp = streamSpec; + RINOK(DataParseExtents(clusterSizeLog, DataAttrs, ref.Start, ref.Start + ref.Num, numPhysClusters, streamSpec->Extents)); + streamSpec->Size = attr0.Size; + streamSpec->InitializedSize = attr0.InitializedSize; + streamSpec->Stream = mainStream; + streamSpec->BlockSizeLog = clusterSizeLog; + streamSpec->InUse = InUse(); + RINOK(streamSpec->InitAndSeek(attr0.CompressionUnit)); + *destStream = streamTemp.Detach(); + return S_OK; + } + streamSpec->Buf = attr0.Data; + } + streamSpec->Init(); + *destStream = streamTemp.Detach(); + return S_OK; +} + +bool CMftRec::Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNumber, + CObjectVector<CAttr> *attrs) +{ + G32(p, Magic); + if (IsEmpty()) + return true; + if (Magic != 0x454c4946) + return false; + + UInt32 usaOffset; + UInt32 numUsaItems; + G16(p + 0x04, usaOffset); + G16(p + 0x06, numUsaItems); + + if ((usaOffset & 1) != 0 || usaOffset + numUsaItems * 2 > ((UInt32)1 << sectorSizeLog) - 2 || + numUsaItems == 0 || numUsaItems - 1 != numSectors) + return false; + + UInt16 usn = Get16(p + usaOffset); + // PRF(printf("\nusn = %d", usn)); + for (UInt32 i = 1; i < numUsaItems; i++) + { + void *pp = p + (i << sectorSizeLog) - 2; + if (Get16(pp) != usn) + return false; + SetUi16(pp, Get16(p + usaOffset + i * 2)); + } + + // G64(p + 0x08, Lsn); + G16(p + 0x10, SeqNumber); + // G16(p + 0x12, LinkCount); + // PRF(printf(" L=%d", LinkCount)); + UInt32 attrOffs = Get16(p + 0x14); + G16(p + 0x16, Flags); + PRF(printf(" F=%4X", Flags)); + + UInt32 bytesInUse = Get32(p + 0x18); + UInt32 bytesAlloc = Get32(p + 0x1C); + G64(p + 0x20, BaseMftRef.Val); + if (BaseMftRef.Val != 0) + { + PRF(printf(" BaseRef=%d", (int)BaseMftRef.Val)); + // return false; // Check it; + } + // G16(p + 0x28, NextAttrInstance); + if (usaOffset >= 0x30) + if (Get32(p + 0x2C) != recNumber) // NTFS 3.1+ + return false; + + UInt32 limit = numSectors << sectorSizeLog; + if (attrOffs >= limit || (attrOffs & 7) != 0 || bytesInUse > limit + || bytesAlloc != limit) + return false; + + + for (UInt32 t = attrOffs; t < limit;) + { + CAttr attr; + // PRF(printf("\n %2d:", Attrs.Size())); + PRF(printf("\n")); + UInt32 length = attr.Parse(p + t, limit - t); + if (length == 0 || limit - t < length) + return false; + t += length; + if (attr.Type == 0xFFFFFFFF) + break; + switch(attr.Type) + { + case ATTR_TYPE_FILE_NAME: + { + CFileNameAttr fna; + if (!attr.ParseFileName(fna)) + return false; + FileNames.Add(fna); + PRF(printf(" flags = %4x", (int)fna.NameType)); + PRF(printf("\n %S", fna.Name)); + break; + } + case ATTR_TYPE_STANDARD_INFO: + if (!attr.ParseSi(SiAttr)) + return false; + break; + case ATTR_TYPE_DATA: + DataAttrs.Add(attr); + break; + default: + if (attrs) + attrs->Add(attr); + break; + } + } + + return true; +} + +struct CItem +{ + int RecIndex; + int DataIndex; + CMftRef ParentRef; + UString Name; + UInt32 Attrib; + + bool IsDir() const { return (DataIndex < 0); } +}; + +struct CDatabase +{ + CHeader Header; + CObjectVector<CItem> Items; + CObjectVector<CMftRec> Recs; + CMyComPtr<IInStream> InStream; + IArchiveOpenCallback *OpenCallback; + + CByteBuffer ByteBuf; + + CObjectVector<CAttr> VolAttrs; + + ~CDatabase() { ClearAndClose(); } + + void Clear(); + void ClearAndClose(); + + UString GetItemPath(Int32 index) const; + HRESULT Open(); + HRESULT ReadDir(Int32 parent, UInt32 cluster, int level); + + HRESULT SeekToCluster(UInt64 cluster); + + int FindMtfRec(const CMftRef &ref) const + { + UInt64 val = ref.GetIndex(); + int left = 0, right = Items.Size(); + while (left != right) + { + int mid = (left + right) / 2; + UInt64 midValue = Items[mid].RecIndex; + if (val == midValue) + return mid; + if (val < midValue) + right = mid; + else + left = mid + 1; + } + return -1; + } + +}; + +HRESULT CDatabase::SeekToCluster(UInt64 cluster) +{ + return InStream->Seek(cluster << Header.ClusterSizeLog, STREAM_SEEK_SET, NULL); +} + +void CDatabase::Clear() +{ + Items.Clear(); + Recs.Clear(); +} + +void CDatabase::ClearAndClose() +{ + Clear(); + InStream.Release(); +} + +#define MY_DIR_PREFIX(x) L"[" x L"]" WSTRING_PATH_SEPARATOR + +UString CDatabase::GetItemPath(Int32 index) const +{ + const CItem *item = &Items[index]; + UString name = item->Name; + for (int j = 0; j < 256; j++) + { + CMftRef ref = item->ParentRef; + index = FindMtfRec(ref); + if (ref.GetIndex() == 5) + return name; + if (index < 0 || Recs[Items[index].RecIndex].SeqNumber != ref.GetNumber()) + return MY_DIR_PREFIX(L"UNKNOWN") + name; + item = &Items[index]; + name = item->Name + WCHAR_PATH_SEPARATOR + name; + } + return MY_DIR_PREFIX(L"BAD") + name; +} + +HRESULT CDatabase::Open() +{ + Clear(); + + static const UInt32 kHeaderSize = 512; + Byte buf[kHeaderSize]; + RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize)); + if (!Header.Parse(buf)) + return S_FALSE; + UInt64 fileSize; + RINOK(InStream->Seek(0, STREAM_SEEK_END, &fileSize)); + if (fileSize < Header.GetPhySize()) + return S_FALSE; + + SeekToCluster(Header.MftCluster); + + CMftRec mftRec; + UInt32 numSectorsInRec; + int recSizeLog; + CMyComPtr<IInStream> mftStream; + { + UInt32 blockSize = 1 << 12; + ByteBuf.SetCapacity(blockSize); + RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize)); + + UInt32 allocSize = Get32(ByteBuf + 0x1C); + recSizeLog = GetLog(allocSize); + if (recSizeLog < Header.SectorSizeLog) + return false; + numSectorsInRec = 1 << (recSizeLog - Header.SectorSizeLog); + if (!mftRec.Parse(ByteBuf, Header.SectorSizeLog, numSectorsInRec, NULL, 0)) + return S_FALSE; + if (mftRec.IsEmpty()) + return S_FALSE; + mftRec.ParseDataNames(); + if (mftRec.DataRefs.IsEmpty()) + return S_FALSE; + RINOK(mftRec.GetStream(InStream, 0, Header.ClusterSizeLog, Header.NumClusters, &mftStream)); + if (!mftStream) + return S_FALSE; + } + + UInt64 mftSize = mftRec.DataAttrs[0].Size; + if ((mftSize >> 4) > Header.GetPhySize()) + return S_FALSE; + + UInt64 numFiles = mftSize >> recSizeLog; + if (numFiles > (1 << 30)) + return S_FALSE; + if (OpenCallback) + { + RINOK(OpenCallback->SetTotal(&numFiles, &mftSize)); + } + const UInt32 kBufSize = (1 << 15); + if (kBufSize < (1 << recSizeLog)) + return S_FALSE; + + ByteBuf.SetCapacity((size_t)kBufSize); + Recs.Reserve((int)numFiles); + for (UInt64 pos64 = 0;;) + { + if (OpenCallback) + { + // Sleep(0); + UInt64 numFiles = Recs.Size(); + RINOK(OpenCallback->SetCompleted(&numFiles, &pos64)); + } + UInt32 readSize = kBufSize; + UInt64 rem = mftSize - pos64; + if (readSize > rem) + readSize = (UInt32)rem; + if (readSize < ((UInt32)1 << recSizeLog)) + break; + RINOK(ReadStream_FALSE(mftStream, ByteBuf, (size_t)readSize)); + pos64 += readSize; + for (int i = 0; ((UInt32)(i + 1) << recSizeLog) <= readSize; i++) + { + PRF(printf("\n---------------------")); + PRF(printf("\n%5d:", Recs.Size())); + Byte *p = ByteBuf + ((UInt32)i << recSizeLog); + CMftRec rec; + if (!rec.Parse(p, Header.SectorSizeLog, numSectorsInRec, (UInt32)Recs.Size(), + (Recs.Size() == kRecIndex_Volume) ? &VolAttrs: NULL)) + return S_FALSE; + Recs.Add(rec); + } + } + + int i; + for (i = 0; i < Recs.Size(); i++) + { + CMftRec &rec = Recs[i]; + if (!rec.BaseMftRef.IsBaseItself()) + { + UInt64 refIndex = rec.BaseMftRef.GetIndex(); + if (refIndex > (UInt32)Recs.Size()) + return S_FALSE; + CMftRec &refRec = Recs[(int)refIndex]; + bool moveAttrs = (refRec.SeqNumber == rec.BaseMftRef.GetNumber() && refRec.BaseMftRef.IsBaseItself()); + if (rec.InUse() && refRec.InUse()) + { + if (!moveAttrs) + return S_FALSE; + } + else if (rec.InUse() || refRec.InUse()) + moveAttrs = false; + if (moveAttrs) + refRec.MoveAttrsFrom(rec); + } + } + + for (i = 0; i < Recs.Size(); i++) + Recs[i].ParseDataNames(); + + for (i = 0; i < Recs.Size(); i++) + { + CMftRec &rec = Recs[i]; + if (rec.IsEmpty() || !rec.BaseMftRef.IsBaseItself()) + continue; + int numNames = 0; + // printf("\n%4d: ", i); + for (int t = 0; t < rec.FileNames.Size(); t++) + { + const CFileNameAttr &fna = rec.FileNames[t]; + // printf("%4d %S | ", (int)fna.NameType, fna.Name); + if (fna.IsDos()) + continue; + int numDatas = rec.DataRefs.Size(); + + // For hard linked files we show substreams only for first Name. + if (numDatas > 1 && numNames > 0) + numDatas = 1; + numNames++; + + if (rec.IsDir()) + { + CItem item; + item.Name = fna.Name; + item.RecIndex = i; + item.DataIndex = -1; + item.ParentRef = fna.ParentDirRef; + item.Attrib = rec.SiAttr.Attrib | 0x10; + // item.Attrib = fna.Attrib; + Items.Add(item); + } + for (int di = 0; di < numDatas; di++) + { + CItem item; + item.Name = fna.Name; + item.Attrib = rec.SiAttr.Attrib; + const UString &subName = rec.DataAttrs[rec.DataRefs[di].Start].Name; + if (!subName.IsEmpty()) + { + // $BadClus:$Bad is sparse file for all clusters. So we skip it. + if (i == kRecIndex_BadClus && subName == L"$Bad") + continue; + item.Name += L":"; + item.Name += subName; + item.Attrib = fna.Attrib; + } + + PRF(printf("\n%3d", i)); + PRF(printf(" attrib=%2x", rec.SiAttr.Attrib)); + PRF(printf(" %S", item.Name)); + + item.RecIndex = i; + item.DataIndex = di; + item.ParentRef = fna.ParentDirRef; + + Items.Add(item); + rec.MyNumNameLinks++; + } + } + rec.FileNames.ClearAndFree(); + } + + return S_OK; +} + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp, + CDatabase +{ +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + IInStream *stream2; + const CItem &item = Items[index]; + const CMftRec &rec = Recs[item.RecIndex]; + HRESULT res = rec.GetStream(InStream, item.DataIndex, Header.ClusterSizeLog, Header.NumClusters, &stream2); + *stream = (ISequentialInStream *)stream2; + return res; + COM_TRY_END +} + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidATime, VT_FILETIME}, + { NULL, kpidAttrib, VT_UI4}, + { NULL, kpidLinks, VT_UI4} +}; + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidVolumeName, VT_BSTR}, + { NULL, kpidFileSystem, VT_BSTR}, + { NULL, kpidClusterSize, VT_UI4}, + { NULL, kpidPhySize, VT_UI8}, + { NULL, kpidHeadersSize, VT_UI8}, + { NULL, kpidCTime, VT_FILETIME}, + + { NULL, kpidSectorSize, VT_UI4}, + { NULL, kpidId, VT_UI8} + // { NULL, kpidSectorsPerTrack, VT_UI4}, + // { NULL, kpidNumHeads, VT_UI4}, + // { NULL, kpidHiddenSectors, VT_UI4} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +static void NtfsTimeToProp(UInt64 t, NWindows::NCOM::CPropVariant &prop) +{ + FILETIME ft; + ft.dwLowDateTime = (DWORD)t; + ft.dwHighDateTime = (DWORD)(t >> 32); + prop = ft; +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + + const CMftRec *volRec = (Recs.Size() > kRecIndex_Volume ? &Recs[kRecIndex_Volume] : NULL); + + switch(propID) + { + case kpidClusterSize: prop = Header.ClusterSize(); break; + case kpidPhySize: prop = Header.GetPhySize(); break; + /* + case kpidHeadersSize: + { + UInt64 val = 0; + for (int i = 0; i < kNumSysRecs; i++) + { + printf("\n%2d: %8I64d ", i, Recs[i].GetPackSize()); + if (i == 8) + i = i + val += Recs[i].GetPackSize(); + } + prop = val; + break; + } + */ + case kpidCTime: if (volRec) NtfsTimeToProp(volRec->SiAttr.CTime, prop); break;break; + case kpidVolumeName: + { + for (int i = 0; i < VolAttrs.Size(); i++) + { + const CAttr &attr = VolAttrs[i]; + if (attr.Type == ATTR_TYPE_VOLUME_NAME) + { + UString name; + GetString(attr.Data, (int)attr.Data.GetCapacity() / 2, name); + prop = name; + break; + } + } + break; + } + case kpidFileSystem: + { + AString s = "NTFS"; + for (int i = 0; i < VolAttrs.Size(); i++) + { + const CAttr &attr = VolAttrs[i]; + if (attr.Type == ATTR_TYPE_VOLUME_INFO) + { + CVolInfo vi; + if (attr.ParseVolInfo(vi)) + { + s += ' '; + char temp[16]; + ConvertUInt32ToString(vi.MajorVer, temp); + s += temp; + s += '.'; + ConvertUInt32ToString(vi.MinorVer, temp); + s += temp; + } + break; + } + } + prop = s; + break; + } + case kpidSectorSize: prop = (UInt32)1 << Header.SectorSizeLog; break; + case kpidId: prop = Header.SerialNumber; break; + // case kpidMediaType: prop = Header.MediaType; break; + // case kpidSectorsPerTrack: prop = Header.SectorsPerTrack; break; + // case kpidNumHeads: prop = Header.NumHeads; break; + // case kpidHiddenSectors: prop = Header.NumHiddenSectors; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CItem &item = Items[index]; + const CMftRec &rec = Recs[item.RecIndex]; + + const CAttr *data= NULL; + if (item.DataIndex >= 0) + data = &rec.DataAttrs[rec.DataRefs[item.DataIndex].Start]; + + switch(propID) + { + case kpidPath: + { + UString name = GetItemPath(index); + const wchar_t *prefix = NULL; + if (!rec.InUse()) + prefix = MY_DIR_PREFIX(L"DELETED"); + else if (item.RecIndex < kNumSysRecs) + prefix = MY_DIR_PREFIX(L"SYSTEM"); + if (prefix) + name = prefix + name; + prop = name; + break; + } + + case kpidIsDir: prop = item.IsDir(); break; + case kpidMTime: NtfsTimeToProp(rec.SiAttr.MTime, prop); break; + + case kpidCTime: NtfsTimeToProp(rec.SiAttr.CTime, prop); break; + case kpidATime: NtfsTimeToProp(rec.SiAttr.ATime, prop); break; + case kpidAttrib: + prop = item.Attrib; + break; + case kpidLinks: prop = rec.MyNumNameLinks; break; + case kpidSize: if (data) prop = data->GetSize(); break; + case kpidPackSize: if (data) prop = data->GetPackSize(); break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + { + OpenCallback = callback; + InStream = stream; + HRESULT res; + try + { + res = CDatabase::Open(); + if (res == S_OK) + return S_OK; + } + catch(...) + { + Close(); + throw; + } + Close(); + return res; + } + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + ClearAndClose(); + return S_OK; +} + +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; + UInt32 i; + UInt64 totalSize = 0; + for (i = 0; i < numItems; i++) + { + const CItem &item = Items[allFilesMode ? i : indices[i]]; + const CMftRec &rec = Recs[item.RecIndex]; + if (!rec.IsDir()) + totalSize += rec.GetSize(item.DataIndex); + } + RINOK(extractCallback->SetTotal(totalSize)); + + UInt64 totalPackSize; + totalSize = totalPackSize = 0; + + CByteBuffer buf; + UInt32 clusterSize = Header.ClusterSize(); + buf.SetCapacity(clusterSize); + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, false); + + CDummyOutStream *outStreamSpec = new CDummyOutStream; + CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); + + for (i = 0; i < numItems; i++) + { + lps->InSize = totalPackSize; + lps->OutSize = totalSize; + RINOK(lps->SetCur()); + CMyComPtr<ISequentialOutStream> realOutStream; + Int32 askMode = testMode ? + NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + const CItem &item = Items[index]; + if (item.IsDir()) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); + continue; + } + + if (!testMode && (!realOutStream)) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + + outStreamSpec->SetStream(realOutStream); + realOutStream.Release(); + outStreamSpec->Init(); + + const CMftRec &rec = Recs[item.RecIndex]; + const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start]; + + int res = NArchive::NExtract::NOperationResult::kDataError; + { + CMyComPtr<IInStream> inStream; + HRESULT hres = rec.GetStream(InStream, item.DataIndex, Header.ClusterSizeLog, Header.NumClusters, &inStream); + if (hres == S_FALSE) + res = NArchive::NExtract::NOperationResult::kUnSupportedMethod; + else + { + RINOK(hres); + if (inStream) + { + HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress); + if (hres != S_OK && hres != S_FALSE) + { + RINOK(hres); + } + if (/* copyCoderSpec->TotalSize == item.GetSize() && */ hres == S_OK) + res = NArchive::NExtract::NOperationResult::kOK; + } + } + } + totalPackSize += data.GetPackSize(); + totalSize += data.GetSize(); + outStreamSpec->ReleaseStream(); + RINOK(extractCallback->SetOperationResult(res)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = Items.Size(); + return S_OK; +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"NTFS", L"ntfs img", 0, 0xD9, { 'N', 'T', 'F', 'S', ' ', ' ', ' ', ' ', 0 }, 9, false, CreateArc, 0 }; + +REGISTER_ARC(Fat) + +}} diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp index 70af37c7..a1304ae4 100755 --- a/CPP/7zip/Archive/PeHandler.cpp +++ b/CPP/7zip/Archive/PeHandler.cpp @@ -18,8 +18,6 @@ #include "../Compress/CopyCoder.h" -#include "Common/DummyOutStream.h" - #define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) #define Get64(p) GetUi64(p) @@ -549,11 +547,6 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidStackCommit: prop = _optHeader.StackCommit; break; case kpidHeapReserve: prop = _optHeader.HeapReserve; break; case kpidHeapCommit: prop = _optHeader.HeapCommit; break; - - /* - if (_optHeader.Is64Bit()) - s += " 64-bit"; - */ } prop.Detach(value); return S_OK; @@ -785,8 +778,6 @@ HRESULT CalcCheckSum(ISequentialInStream *stream, UInt32 size, UInt32 excludePos RINOK(ReadStream(stream, buf, &processed)); /* - */ - /* for (; processed < rem; processed++) buf[processed] = 0; */ @@ -880,9 +871,6 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, CMyComPtr<ISequentialInStream> inStream(streamSpec); streamSpec->SetStream(_inStream); - CDummyOutStream *outStreamSpec = new CDummyOutStream; - CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); - for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) { lps->InSize = lps->OutSize = currentTotalSize; @@ -893,20 +881,17 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, UInt32 index = allFilesMode ? i : indices[i]; const CSection &item = _sections[index]; currentItemSize = item.GetPackSize(); - { - CMyComPtr<ISequentialOutStream> realOutStream; - RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - if (!testMode && (!realOutStream)) - continue; - outStreamSpec->SetStream(realOutStream); - outStreamSpec->Init(); - } + + CMyComPtr<ISequentialOutStream> outStream; + RINOK(extractCallback->GetStream(index, &outStream, askMode)); + if (!testMode && !outStream) + continue; RINOK(extractCallback->PrepareOperation(askMode)); RINOK(_inStream->Seek(item.Pa, STREAM_SEEK_SET, NULL)); streamSpec->Init(currentItemSize); RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); - outStreamSpec->ReleaseStream(); + outStream.Release(); RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == currentItemSize) ? checkSumOK ? NArchive::NExtract::NOperationResult::kOK: diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp index 2431e449..93c19265 100755 --- a/CPP/7zip/Archive/Rar/RarHandler.cpp +++ b/CPP/7zip/Archive/Rar/RarHandler.cpp @@ -251,7 +251,10 @@ public: } else if (!_newStyle) { - if (ext.CompareNoCase(L"000") == 0 || ext.CompareNoCase(L"001") == 0) + if (ext.CompareNoCase(L"000") == 0 || + ext.CompareNoCase(L"001") == 0 || + ext.CompareNoCase(L"r00") == 0 || + ext.CompareNoCase(L"r01") == 0) { _afterPart.Empty(); _first = false; diff --git a/CPP/7zip/Archive/Rar/RarIn.cpp b/CPP/7zip/Archive/Rar/RarIn.cpp index 18669405..4810649b 100755 --- a/CPP/7zip/Archive/Rar/RarIn.cpp +++ b/CPP/7zip/Archive/Rar/RarIn.cpp @@ -2,19 +2,17 @@ #include "StdAfx.h" +#include "../../../../C/7zCrc.h" + #include "Common/StringConvert.h" #include "Common/UTFConvert.h" -#include "RarIn.h" #include "../../Common/LimitedStreams.h" #include "../../Common/StreamUtils.h" #include "../Common/FindSignature.h" -extern "C" -{ - #include "../../../../C/7zCrc.h" -} +#include "RarIn.h" namespace NArchive { namespace NRar { diff --git a/CPP/7zip/Archive/Rar/RarVolumeInStream.cpp b/CPP/7zip/Archive/Rar/RarVolumeInStream.cpp index 1845e20a..25194f91 100755 --- a/CPP/7zip/Archive/Rar/RarVolumeInStream.cpp +++ b/CPP/7zip/Archive/Rar/RarVolumeInStream.cpp @@ -2,15 +2,9 @@ #include "StdAfx.h" -#include "RarVolumeInStream.h" - -#include "Windows/Defs.h" -#include "Common/Defs.h" +#include "../../../../C/7zCrc.h" -extern "C" -{ - #include "../../../../C/7zCrc.h" -} +#include "RarVolumeInStream.h" namespace NArchive { namespace NRar { diff --git a/CPP/7zip/Archive/RpmHandler.cpp b/CPP/7zip/Archive/RpmHandler.cpp index c6951799..13b67390 100755 --- a/CPP/7zip/Archive/RpmHandler.cpp +++ b/CPP/7zip/Archive/RpmHandler.cpp @@ -9,6 +9,7 @@ #include "Windows/PropVariant.h" +#include "../Common/LimitedStreams.h" #include "../Common/ProgressUtils.h" #include "../Common/RegisterArc.h" #include "../Common/StreamUtils.h" @@ -113,23 +114,23 @@ HRESULT OpenArchive(IInStream *inStream) return S_FALSE; CSigHeaderSig sigHeader, header; - if(lead.SignatureType == RPMSIG_NONE) + if (lead.SignatureType == RPMSIG_NONE) { ; } - else if(lead.SignatureType == RPMSIG_PGP262_1024) + else if (lead.SignatureType == RPMSIG_PGP262_1024) { UInt64 pos; RINOK(inStream->Seek(256, STREAM_SEEK_CUR, &pos)); } - else if(lead.SignatureType == RPMSIG_HEADERSIG) + else if (lead.SignatureType == RPMSIG_HEADERSIG) { RINOK(RedSigHeaderSig(inStream, sigHeader)); - if(!sigHeader.MagicCheck()) + if (!sigHeader.MagicCheck()) return S_FALSE; UInt32 len = sigHeader.GetLostHeaderLen(); RINOK(inStream->Seek(len, STREAM_SEEK_CUR, &pos)); - if((pos % 8) != 0) + if ((pos % 8) != 0) { RINOK(inStream->Seek((pos / 8 + 1) * 8 - pos, STREAM_SEEK_CUR, &pos)); @@ -139,10 +140,10 @@ HRESULT OpenArchive(IInStream *inStream) return S_FALSE; RINOK(RedSigHeaderSig(inStream, header)); - if(!header.MagicCheck()) + if (!header.MagicCheck()) return S_FALSE; int headerLen = header.GetLostHeaderLen(); - if(headerLen == -1) + if (headerLen == -1) return S_FALSE; RINOK(inStream->Seek(headerLen, STREAM_SEEK_CUR, &pos)); return S_OK; @@ -150,28 +151,34 @@ HRESULT OpenArchive(IInStream *inStream) class CHandler: public IInArchive, + public IInArchiveGetStream, public CMyUnknownImp { + CMyComPtr<IInStream> _stream; + UInt64 _pos; + UInt64 _size; + Byte _sig[4]; public: - MY_UNKNOWN_IMP1(IInArchive) - + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) - -private: - CMyComPtr<IInStream> m_InStream; - UInt64 m_Pos; - UInt64 m_Size; - Byte _sig[4]; + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; STATPROPSTG kProps[] = { - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8} + { NULL, kpidSize, VT_UI8} }; IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO +IMP_IInArchive_ArcProps_NO_Table + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) { case kpidMainSubfile: prop = (UInt32)0; break; } + prop.Detach(value); + return S_OK; +} STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 * /* maxCheckStartPosition */, @@ -180,29 +187,24 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, COM_TRY_BEGIN try { - if(OpenArchive(inStream) != S_OK) + Close(); + if (OpenArchive(inStream) != S_OK) return S_FALSE; - RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Pos)); + RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &_pos)); + RINOK(ReadStream_FALSE(inStream, _sig, sizeof(_sig) / sizeof(_sig[0]))); UInt64 endPosition; RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPosition)); - m_Size = endPosition - m_Pos; - - RINOK(inStream->Seek(m_Pos, STREAM_SEEK_SET, NULL)); - RINOK(ReadStream_FALSE(inStream, _sig, sizeof(_sig) / sizeof(_sig[0]))); - - m_InStream = inStream; + _size = endPosition - _pos; + _stream = inStream; return S_OK; } - catch(...) - { - return S_FALSE; - } + catch(...) { return S_FALSE; } COM_TRY_END } STDMETHODIMP CHandler::Close() { - m_InStream.Release(); + _stream.Release(); return S_OK; } @@ -219,19 +221,19 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN { case kpidSize: case kpidPackSize: - prop = m_Size; + prop = _size; break; case kpidExtension: { - wchar_t s[32]; - MyStringCopy(s, L"cpio."); - const wchar_t *ext; + char s[32]; + MyStringCopy(s, "cpio."); + const char *ext; if (_sig[0] == 0x1F && _sig[1] == 0x8B) - ext = L"gz"; + ext = "gz"; else if (_sig[0] == 'B' && _sig[1] == 'Z' && _sig[2] == 'h') - ext = L"bz2"; + ext = "bz2"; else - ext = L"lzma"; + ext = "lzma"; MyStringCopy(s + MyStringLen(s), ext); prop = s; break; @@ -245,58 +247,50 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 _aTestMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == UInt32(-1)); - if (allFilesMode) + if (numItems == UInt32(-1)) numItems = 1; - if(numItems == 0) + if (numItems == 0) return S_OK; - if(numItems != 1) - return E_FAIL; - if (indices[0] != 0) - return E_FAIL; + if (numItems != 1 || indices[0] != 0) + return E_INVALIDARG; bool testMode = (_aTestMode != 0); - - UInt64 currentTotalSize = 0; - RINOK(extractCallback->SetTotal(m_Size)); - RINOK(extractCallback->SetCompleted(¤tTotalSize)); - CMyComPtr<ISequentialOutStream> realOutStream; + + RINOK(extractCallback->SetTotal(_size)); + CMyComPtr<ISequentialOutStream> outStream; Int32 askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; - Int32 index = 0; - - RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - - if(!testMode && (!realOutStream)) + RINOK(extractCallback->GetStream(0, &outStream, askMode)); + if (!testMode && !outStream) return S_OK; - RINOK(extractCallback->PrepareOperation(askMode)); - if (testMode) - { - RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); - return S_OK; - } - - RINOK(m_InStream->Seek(m_Pos, STREAM_SEEK_SET, NULL)); - + CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder; CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); - RINOK(copyCoder->Code(m_InStream, realOutStream, NULL, NULL, progress)); - realOutStream.Release(); + RINOK(_stream->Seek(_pos, STREAM_SEEK_SET, NULL)); + RINOK(copyCoder->Code(_stream, outStream, NULL, NULL, progress)); + outStream.Release(); return extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK); COM_TRY_END } +STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + return CreateLimitedInStream(_stream, _pos, _size, stream); + COM_TRY_END +} + static IInArchive *CreateArc() { return new NArchive::NRpm::CHandler; } static CArcInfo g_ArcInfo = - { L"Rpm", L"rpm", 0, 0xEB, { 0}, 0, false, CreateArc, 0 }; + { L"Rpm", L"rpm", 0, 0xEB, { 0xED, 0xAB, 0xEE, 0xDB}, 4, false, CreateArc, 0 }; REGISTER_ARC(Rpm) diff --git a/CPP/7zip/Archive/Split/SplitHandler.h b/CPP/7zip/Archive/Split/SplitHandler.h deleted file mode 100755 index 9e020763..00000000 --- a/CPP/7zip/Archive/Split/SplitHandler.h +++ /dev/null @@ -1,37 +0,0 @@ -// Split/Handler.h - -#ifndef __SPLIT_HANDLER_H -#define __SPLIT_HANDLER_H - -#include "Common/MyCom.h" -#include "Common/MyString.h" -#include "../IArchive.h" - -namespace NArchive { -namespace NSplit { - -class CHandler: - public IInArchive, - public IInArchiveGetStream, - // public IOutArchive, - public CMyUnknownImp -{ -public: - MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) - - INTERFACE_IInArchive(;) - - STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); - -private: - UString _subName; - UString _name; - CObjectVector<CMyComPtr<IInStream> > _streams; - CRecordVector<UInt64> _sizes; - - UInt64 _totalSize; -}; - -}} - -#endif diff --git a/CPP/7zip/Archive/Split/SplitHandlerOut.cpp b/CPP/7zip/Archive/Split/SplitHandlerOut.cpp deleted file mode 100755 index 6edf86f4..00000000 --- a/CPP/7zip/Archive/Split/SplitHandlerOut.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// Split/OutHandler.cpp - -#include "StdAfx.h" - -#include "SplitHandler.h" -#include "../../../Windows/PropVariant.h" -#include "../../../Common/ComTry.h" -#include "../../../Common/StringToInt.h" - -using namespace NWindows; - -namespace NArchive { -namespace NSplit { - -/* -STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) -{ - *type = NFileTimeType::kWindows; - return S_OK; -} - -STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, - IArchiveUpdateCallback *updateCallback) -{ - COM_TRY_BEGIN - - if (numItems != 1) - return E_INVALIDARG; - - UInt64 volumeSize = 0; - - CMyComPtr<IArchiveUpdateCallback2> callback2; - updateCallback->QueryInterface(IID_IArchiveUpdateCallback2, - (void **)&callback2); - - RINOK(callback2->GetVolumeSize(0, &volumeSize)); - - Int32 newData; - Int32 newProperties; - UInt32 indexInArchive; - if (!updateCallback) - return E_FAIL; - - UInt32 fileIndex = 0; - RINOK(updateCallback->GetUpdateItemInfo(fileIndex, - &newData, &newProperties, &indexInArchive)); - - if (newProperties != 0) - { - { - NCOM::CPropVariant prop; - RINOK(updateCallback->GetProperty(fileIndex, kpidIsFolder, &prop)); - if (prop.vt == VT_EMPTY) - { - } - else if (prop.vt != VT_BOOL) - return E_INVALIDARG; - else - { - if (prop.boolVal != VARIANT_FALSE) - return E_INVALIDARG; - } - } - { - NCOM::CPropVariant prop; - RINOK(updateCallback->GetProperty(fileIndex, kpidIsAnti, &prop)); - if (prop.vt == VT_EMPTY) - { - } - else if (prop.vt != VT_BOOL) - return E_INVALIDARG; - else - { - if (prop.boolVal != VARIANT_FALSE) - return E_INVALIDARG; - } - } - } - UInt64 newSize; - bool thereIsCopyData = false; - if (newData != 0) - { - NCOM::CPropVariant prop; - RINOK(updateCallback->GetProperty(fileIndex, kpidSize, &prop)); - if (prop.vt != VT_UI8) - return E_INVALIDARG; - newSize = prop.uhVal.QuadPart; - } - else - thereIsCopyData = true; - - UInt64 pos = 0; - while(pos < newSize) - { - - } - return S_OK; - COM_TRY_END -} -*/ - -}} diff --git a/CPP/7zip/Archive/Split/SplitRegister.cpp b/CPP/7zip/Archive/Split/SplitRegister.cpp deleted file mode 100755 index 56ddba29..00000000 --- a/CPP/7zip/Archive/Split/SplitRegister.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// SplitRegister.cpp - -#include "StdAfx.h" - -#include "../../Common/RegisterArc.h" - -#include "SplitHandler.h" -static IInArchive *CreateArc() { return new NArchive::NSplit::CHandler; } -/* -#ifndef EXTRACT_ONLY -static IOutArchive *CreateArcOut() { return new NArchive::NSplit::CHandler; } -#else -#define CreateArcOut 0 -#endif -*/ - -static CArcInfo g_ArcInfo = -{ L"Split", L"001", 0, 0xEA, { 0 }, 0, false, CreateArc, 0 }; - -REGISTER_ARC(Split) diff --git a/CPP/7zip/Archive/Split/StdAfx.h b/CPP/7zip/Archive/Split/StdAfx.h deleted file mode 100755 index e7fb6986..00000000 --- a/CPP/7zip/Archive/Split/StdAfx.h +++ /dev/null @@ -1,8 +0,0 @@ -// StdAfx.h - -#ifndef __STDAFX_H -#define __STDAFX_H - -#include "../../../Common/MyWindows.h" - -#endif diff --git a/CPP/7zip/Archive/Split/SplitHandler.cpp b/CPP/7zip/Archive/SplitHandler.cpp index 61b7f4a7..892e12af 100755 --- a/CPP/7zip/Archive/Split/SplitHandler.cpp +++ b/CPP/7zip/Archive/SplitHandler.cpp @@ -3,24 +3,18 @@ #include "StdAfx.h" #include "Common/ComTry.h" -#include "Common/Defs.h" -#include "Common/NewHandler.h" -#include "Common/StringConvert.h" +#include "Common/MyString.h" #include "Windows/PropVariant.h" -#include "Windows/Time.h" -#include "../../Common/ProgressUtils.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" -#include "../../Compress/CopyCoder.h" +#include "../Compress/CopyCoder.h" -#include "../Common/ItemNameUtils.h" -#include "../Common/MultiStream.h" - -#include "SplitHandler.h" +#include "Common/MultiStream.h" using namespace NWindows; -using namespace NTime; namespace NArchive { namespace NSplit { @@ -28,19 +22,50 @@ namespace NSplit { STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidSize, VT_UI8} }; -IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO +STATPROPSTG kArcProps[] = +{ + { NULL, kpidNumVolumes, VT_UI4} +}; -class CSeqName +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp { + UString _subName; + CObjectVector<CMyComPtr<IInStream> > _streams; + CRecordVector<UInt64> _sizes; + UInt64 _totalSize; public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidMainSubfile: prop = (UInt32)0; break; + case kpidNumVolumes: prop = (UInt32)_streams.Size(); break; + } + prop.Detach(value); + return S_OK; +} + +struct CSeqName +{ UString _unchangedPart; UString _changedPart; bool _splitStyle; + UString GetNextName() { UString newName; @@ -125,23 +150,24 @@ STDMETHODIMP CHandler::Open(IInStream *stream, &openVolumeCallback) != S_OK) return S_FALSE; + UString name; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); if (prop.vt != VT_BSTR) return S_FALSE; - _name = prop.bstrVal; + name = prop.bstrVal; } - int dotPos = _name.ReverseFind('.'); + int dotPos = name.ReverseFind('.'); UString prefix, ext; if (dotPos >= 0) { - prefix = _name.Left(dotPos + 1); - ext = _name.Mid(dotPos + 1); + prefix = name.Left(dotPos + 1); + ext = name.Mid(dotPos + 1); } else - ext = _name; + ext = name; UString extBig = ext; extBig.MakeUpper(); @@ -258,9 +284,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN NWindows::NCOM::CPropVariant prop; switch(propID) { - case kpidPath: - prop = _subName; - break; + case kpidPath: prop = _subName; break; case kpidSize: case kpidPackSize: prop = _totalSize; @@ -271,48 +295,28 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN } STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, - Int32 _aTestMode, IArchiveExtractCallback *_anExtractCallback) + Int32 _aTestMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN + if (numItems == UInt32(-1)) + numItems = 1; + if (numItems == 0) + return S_OK; + if (numItems != 1 || indices[0] != 0) + return E_INVALIDARG; - if (numItems != UInt32(-1)) - { - if (numItems != 1) - return E_INVALIDARG; - if (indices[0] != 0) - return E_INVALIDARG; - } bool testMode = (_aTestMode != 0); - CMyComPtr<IArchiveExtractCallback> extractCallback = _anExtractCallback; - extractCallback->SetTotal(_totalSize); - - /* - CMyComPtr<IArchiveVolumeExtractCallback> volumeExtractCallback; - if (extractCallback.QueryInterface(&volumeExtractCallback) != S_OK) - return E_FAIL; - */ - UInt64 currentTotalSize = 0; - UInt64 currentItemSize; - - RINOK(extractCallback->SetCompleted(¤tTotalSize)); - CMyComPtr<ISequentialOutStream> realOutStream; - Int32 askMode; - askMode = testMode ? NArchive::NExtract::NAskMode::kTest : - NArchive::NExtract::NAskMode::kExtract; - Int32 index = 0; - RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - - RINOK(extractCallback->PrepareOperation(askMode)); - if (testMode) - { - RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); + RINOK(extractCallback->SetTotal(_totalSize)); + CMyComPtr<ISequentialOutStream> outStream; + Int32 askMode = testMode ? + NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract; + RINOK(extractCallback->GetStream(0, &outStream, askMode)); + if (!testMode && !outStream) return S_OK; - } + RINOK(extractCallback->PrepareOperation(askMode)); - if (!testMode && (!realOutStream)) - return S_OK; - NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; @@ -320,22 +324,23 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); - for (int i = 0; i < _streams.Size(); i++, currentTotalSize += currentItemSize) + for (int i = 0; i < _streams.Size(); i++) { lps->InSize = lps->OutSize = currentTotalSize; RINOK(lps->SetCur()); IInStream *inStream = _streams[i]; RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); - RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); - currentItemSize = copyCoderSpec->TotalSize; + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + currentTotalSize += copyCoderSpec->TotalSize; } - realOutStream.Release(); + outStream.Release(); return extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK); COM_TRY_END } STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) { + COM_TRY_BEGIN if (index != 0) return E_INVALIDARG; *stream = 0; @@ -352,6 +357,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) streamSpec->Init(); *stream = streamTemp.Detach(); return S_OK; + COM_TRY_END } +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = +{ L"Split", L"001", 0, 0xEA, { 0 }, 0, false, CreateArc, 0 }; + +REGISTER_ARC(Split) + }} diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp index f8000c85..aa4b2aec 100755 --- a/CPP/7zip/Archive/Tar/TarHandler.cpp +++ b/CPP/7zip/Archive/Tar/TarHandler.cpp @@ -13,9 +13,6 @@ #include "../../Common/LimitedStreams.h" #include "../../Common/ProgressUtils.h" -#include "../../Compress/CopyCoder.h" - -#include "../Common/DummyOutStream.h" #include "../Common/ItemNameUtils.h" #include "TarHandler.h" @@ -33,22 +30,35 @@ STATPROPSTG kProps[] = { NULL, kpidSize, VT_UI8}, { NULL, kpidPackSize, VT_UI8}, { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidPosixAttrib, VT_UI4}, { NULL, kpidUser, VT_BSTR}, - { NULL, kpidGroup, VT_BSTR} + { NULL, kpidGroup, VT_BSTR}, + { NULL, kpidLink, VT_BSTR} }; IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO +IMP_IInArchive_ArcProps_NO_Table + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidPhySize: if (_phySizeDefined) prop = _phySize; break; + } + prop.Detach(value); + return S_OK; +} HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) { UInt64 endPos = 0; - if (callback != NULL) { RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); } + _isGood = true; UInt64 pos = 0; for (;;) { @@ -61,8 +71,13 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) _items.Add(item); RINOK(stream->Seek(item.GetPackSize(), STREAM_SEEK_CUR, &pos)); - if (pos >= endPos) + if (pos > endPos) return S_FALSE; + if (pos == endPos) + { + _isGood = false; + break; + } if (callback != NULL) { if (_items.Size() == 1) @@ -98,70 +113,134 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) return S_OK; } -STDMETHODIMP CHandler::Open(IInStream *stream, - const UInt64 * /* maxCheckStartPosition */, - IArchiveOpenCallback *openArchiveCallback) +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN { Close(); RINOK(Open2(stream, openArchiveCallback)); - _inStream = stream; + _stream = stream; } return S_OK; COM_TRY_END } +STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) +{ + Close(); + _seqStream = stream; + return S_OK; +} + STDMETHODIMP CHandler::Close() { + _phySizeDefined = false; + _curIndex = 0; + _latestIsRead = false; _items.Clear(); - _inStream.Release(); + _seqStream.Release(); + _stream.Release(); return S_OK; } STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { - *numItems = _items.Size(); + *numItems = (_stream ? _items.Size() : (UInt32)(Int32)-1); + return S_OK; +} + +CHandler::CHandler() +{ + copyCoderSpec = new NCompress::CCopyCoder(); + copyCoder = copyCoderSpec; +} + +HRESULT CHandler::SkipTo(UInt32 index) +{ + while (_curIndex < index || !_latestIsRead) + { + if (_latestIsRead) + { + UInt64 packSize = _latestItem.GetPackSize(); + RINOK(copyCoderSpec->Code(_seqStream, NULL, &packSize, &packSize, NULL)); + _latestIsRead = false; + _curIndex++; + } + else + { + bool filled; + // item.HeaderPosition = pos; + RINOK(ReadItem(_seqStream, filled, _latestItem)); + if (!filled) + return E_INVALIDARG; + _latestIsRead = true; + } + } return S_OK; } +static UString TarStringToUnicode(const AString &s) +{ + return MultiByteToUnicodeString(s, CP_OEMCP); +} + STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NWindows::NCOM::CPropVariant prop; - const CItemEx &item = _items[index]; + + const CItemEx *item; + if (_stream) + item = &_items[index]; + else + { + if (index < _curIndex) + return E_INVALIDARG; + else + { + RINOK(SkipTo(index)); + item = &_latestItem; + } + } switch(propID) { - case kpidPath: prop = NItemName::GetOSName2(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break; - case kpidIsDir: prop = item.IsDir(); break; - case kpidSize: prop = item.Size; break; - case kpidPackSize: prop = item.GetPackSize(); break; + case kpidPath: prop = NItemName::GetOSName2(TarStringToUnicode(item->Name)); break; + case kpidIsDir: prop = item->IsDir(); break; + case kpidSize: prop = item->Size; break; + case kpidPackSize: prop = item->GetPackSize(); break; case kpidMTime: - if (item.MTime != 0) + if (item->MTime != 0) { FILETIME ft; - NTime::UnixTimeToFileTime(item.MTime, ft); + NTime::UnixTimeToFileTime(item->MTime, ft); prop = ft; } break; - case kpidUser: prop = MultiByteToUnicodeString(item.UserName, CP_OEMCP); break; - case kpidGroup: prop = MultiByteToUnicodeString(item.GroupName, CP_OEMCP); break; + case kpidPosixAttrib: prop = item->Mode; break; + case kpidUser: prop = TarStringToUnicode(item->User); break; + case kpidGroup: prop = TarStringToUnicode(item->Group); break; + case kpidLink: prop = TarStringToUnicode(item->LinkName); break; } prop.Detach(value); return S_OK; COM_TRY_END } -STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, +HRESULT CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 _aTestMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN + ISequentialInStream *stream = _seqStream; + bool seqMode = (_stream == NULL); + if (!seqMode) + stream = _stream; + bool testMode = (_aTestMode != 0); - bool allFilesMode = (numItems == UInt32(-1)); + bool allFilesMode = (numItems == (UInt32)-1); if (allFilesMode) numItems = _items.Size(); - if (numItems == 0) + if (_stream && numItems == 0) return S_OK; UInt64 totalSize = 0; UInt32 i; @@ -169,24 +248,21 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, totalSize += _items[allFilesMode ? i : indices[i]].Size; extractCallback->SetTotal(totalSize); - UInt64 totalPackSize, curPackSize, curSize; + UInt64 totalPackSize; totalSize = totalPackSize = 0; - NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); - CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; - CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<ISequentialInStream> inStream(streamSpec); - streamSpec->SetStream(_inStream); + streamSpec->SetStream(stream); - CDummyOutStream *outStreamSpec = new CDummyOutStream; + CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); - for (i = 0; i < numItems; i++, totalSize += curSize, totalPackSize += curPackSize) + for (i = 0; i < numItems || seqMode; i++) { lps->InSize = totalPackSize; lps->OutSize = totalSize; @@ -196,29 +272,54 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; Int32 index = allFilesMode ? i : indices[i]; - const CItemEx &item = _items[index]; + const CItemEx *item; + if (seqMode) + { + HRESULT res = SkipTo(index); + if (res == E_INVALIDARG) + break; + RINOK(res); + item = &_latestItem; + } + else + item = &_items[index]; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - curSize = item.Size; - curPackSize = item.GetPackSize(); - if (item.IsDir()) + totalSize += item->Size; + totalPackSize += item->GetPackSize(); + if (item->IsDir()) { RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); continue; } - if (!testMode && (!realOutStream)) - continue; + bool skipMode = false; + if (!testMode && !realOutStream) + { + if (!seqMode) + continue; + skipMode = true; + askMode = NArchive::NExtract::NAskMode::kSkip; + } RINOK(extractCallback->PrepareOperation(askMode)); outStreamSpec->SetStream(realOutStream); realOutStream.Release(); - outStreamSpec->Init(); + outStreamSpec->Init(skipMode ? 0 : item->Size, true); - RINOK(_inStream->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL)); - streamSpec->Init(item.Size); + if (!seqMode) + { + RINOK(_stream->Seek(item->GetDataPosition(), STREAM_SEEK_SET, NULL)); + } + streamSpec->Init(item->GetPackSize()); RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + if (seqMode) + { + _latestIsRead = false; + _curIndex++; + } outStreamSpec->ReleaseStream(); - RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == item.Size ? + RINOK(extractCallback->SetOperationResult(outStreamSpec->GetRem() == 0 ? NArchive::NExtract::NOperationResult::kOK: NArchive::NExtract::NOperationResult::kDataError)); } @@ -226,4 +327,12 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, COM_TRY_END } +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + const CItemEx &item = _items[index]; + return CreateLimitedInStream(_stream, item.GetDataPosition(), item.Size, stream); + COM_TRY_END +} + }} diff --git a/CPP/7zip/Archive/Tar/TarHandler.h b/CPP/7zip/Archive/Tar/TarHandler.h index a98b5404..d2def9a1 100755 --- a/CPP/7zip/Archive/Tar/TarHandler.h +++ b/CPP/7zip/Archive/Tar/TarHandler.h @@ -1,4 +1,4 @@ -// Tar/Handler.h +// TarHandler.h #ifndef __TAR_HANDLER_H #define __TAR_HANDLER_H @@ -6,6 +6,8 @@ #include "Common/MyCom.h" #include "../IArchive.h" +#include "../../Compress/CopyCoder.h" + #include "TarItem.h" namespace NArchive { @@ -13,23 +15,43 @@ namespace NTar { class CHandler: public IInArchive, + public IArchiveOpenSeq, + public IInArchiveGetStream, public IOutArchive, public CMyUnknownImp { + CObjectVector<CItemEx> _items; + CMyComPtr<IInStream> _stream; + CMyComPtr<ISequentialInStream> _seqStream; + bool _isGood; + + UInt32 _curIndex; + bool _latestIsRead; + CItemEx _latestItem; + + UInt64 _phySize; + bool _phySizeDefined; + + NCompress::CCopyCoder *copyCoderSpec; + CMyComPtr<ICompressCoder> copyCoder; + + HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); + HRESULT SkipTo(UInt32 index); + public: - MY_UNKNOWN_IMP2( + MY_UNKNOWN_IMP4( IInArchive, + IArchiveOpenSeq, + IInArchiveGetStream, IOutArchive ) INTERFACE_IInArchive(;) INTERFACE_IOutArchive(;) + STDMETHOD(OpenSeq)(ISequentialInStream *stream); + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); - HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); - -private: - CObjectVector<CItemEx> _items; - CMyComPtr<IInStream> _inStream; + CHandler(); }; }} diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp index 3454868e..4c0cb5f8 100755 --- a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp +++ b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp @@ -1,20 +1,17 @@ -// Tar/HandlerOut.cpp +// TarHandlerOut.cpp #include "StdAfx.h" -#include "Common/StringConvert.h" #include "Common/ComTry.h" +#include "Common/StringConvert.h" #include "Windows/PropVariant.h" #include "Windows/Time.h" -#include "../Common/ItemNameUtils.h" - #include "TarHandler.h" #include "TarUpdate.h" using namespace NWindows; -using namespace NCOM; namespace NArchive { namespace NTar { @@ -25,94 +22,95 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) return S_OK; } +static HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, AString &res) +{ + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(index, propId, &prop)); + if (prop.vt == VT_BSTR) + res = UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP); + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + return S_OK; +} + STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *callback) { COM_TRY_BEGIN + if ((_stream && !_isGood) || _seqStream) + return E_NOTIMPL; CObjectVector<CUpdateItem> updateItems; for (UInt32 i = 0; i < numItems; i++) { CUpdateItem ui; Int32 newData; - Int32 newProperties; + Int32 newProps; UInt32 indexInArchive; if (!callback) return E_FAIL; - RINOK(callback->GetUpdateItemInfo(i, &newData, &newProperties, &indexInArchive)); - ui.NewProperties = IntToBool(newProperties); + RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive)); + ui.NewProps = IntToBool(newProps); ui.NewData = IntToBool(newData); ui.IndexInArchive = indexInArchive; ui.IndexInClient = i; - if (IntToBool(newProperties)) + if (IntToBool(newProps)) { - FILETIME utcTime; - UString name; - /* - UInt32 attributes; { NCOM::CPropVariant prop; - RINOK(callback->GetProperty(i, kpidAttrib, &prop)); + RINOK(callback->GetProperty(i, kpidIsDir, &prop)); if (prop.vt == VT_EMPTY) - attributes = 0; - else if (prop.vt != VT_UI4) + ui.IsDir = false; + else if (prop.vt != VT_BOOL) return E_INVALIDARG; else - attributes = prop.ulVal; - } - */ - { - NCOM::CPropVariant prop; - RINOK(callback->GetProperty(i, kpidMTime, &prop)); - if (prop.vt != VT_FILETIME) - return E_INVALIDARG; - utcTime = prop.filetime; + ui.IsDir = (prop.boolVal != VARIANT_FALSE); } + { NCOM::CPropVariant prop; - RINOK(callback->GetProperty(i, kpidPath, &prop)); + RINOK(callback->GetProperty(i, kpidPosixAttrib, &prop)); if (prop.vt == VT_EMPTY) - name.Empty(); - else if (prop.vt != VT_BSTR) + ui.Mode = 0777 | (ui.IsDir ? 0040000 : 0100000); + else if (prop.vt != VT_UI4) return E_INVALIDARG; else - name = prop.bstrVal; + ui.Mode = prop.ulVal; } { NCOM::CPropVariant prop; - RINOK(callback->GetProperty(i, kpidIsDir, &prop)); + RINOK(callback->GetProperty(i, kpidMTime, &prop)); if (prop.vt == VT_EMPTY) - ui.IsDir = false; - else if (prop.vt != VT_BOOL) + ui.Time = 0; + else if (prop.vt != VT_FILETIME) return E_INVALIDARG; - else - ui.IsDir = (prop.boolVal != VARIANT_FALSE); + else if (!NTime::FileTimeToUnixTime(prop.filetime, ui.Time)) + ui.Time = 0; } - ui.Name = UnicodeStringToMultiByte(NItemName::MakeLegalName(name), CP_OEMCP); - if (ui.IsDir) - ui.Name += '/'; - - if (!NTime::FileTimeToUnixTime(utcTime, ui.Time)) { - ui.Time = 0; - // return E_INVALIDARG; + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(i, kpidPath, &prop)); + if (prop.vt == VT_BSTR) + ui.Name = UnicodeStringToMultiByte(NItemName::MakeLegalName(prop.bstrVal), CP_OEMCP); + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + if (ui.IsDir) + ui.Name += '/'; } + RINOK(GetPropString(callback, i, kpidUser, ui.User)); + RINOK(GetPropString(callback, i, kpidGroup, ui.Group)); } if (IntToBool(newData)) { - UInt64 size; - { - NCOM::CPropVariant prop; - RINOK(callback->GetProperty(i, kpidSize, &prop)); - if (prop.vt != VT_UI8) - return E_INVALIDARG; - size = prop.uhVal.QuadPart; - } - ui.Size = size; + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(i, kpidSize, &prop)); + if (prop.vt != VT_UI8) + return E_INVALIDARG; + ui.Size = prop.uhVal.QuadPart; } updateItems.Add(ui); } - return UpdateArchive(_inStream, outStream, _items, updateItems, callback); + return UpdateArchive(_stream, outStream, _items, updateItems, callback); COM_TRY_END } diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp index 55215ac7..b8409195 100755 --- a/CPP/7zip/Archive/Tar/TarIn.cpp +++ b/CPP/7zip/Archive/Tar/TarIn.cpp @@ -1,15 +1,13 @@ -// Archive/TarIn.cpp +// TarIn.cpp #include "StdAfx.h" -#include "TarIn.h" -#include "TarHeader.h" - #include "Common/StringToInt.h" -#include "Windows/Defs.h" #include "../../Common/StreamUtils.h" +#include "TarIn.h" + namespace NArchive { namespace NTar { @@ -98,8 +96,8 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE memcpy(item.Magic, p, 8); p += 8; - ReadString(p, NFileHeader::kUserNameSize, item.UserName); p += NFileHeader::kUserNameSize; - ReadString(p, NFileHeader::kUserNameSize, item.GroupName); p += NFileHeader::kUserNameSize; + ReadString(p, NFileHeader::kUserNameSize, item.User); p += NFileHeader::kUserNameSize; + ReadString(p, NFileHeader::kGroupNameSize, item.Group); p += NFileHeader::kGroupNameSize; item.DeviceMajorDefined = (p[0] != 0); RIF(OctalToNumber32(p, 8, item.DeviceMajor)); p += 8; item.DeviceMinorDefined = (p[0] != 0); RIF(OctalToNumber32(p, 8, item.DeviceMinor)); p += 8; @@ -132,7 +130,8 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item) if (!filled) return S_OK; // GNUtar extension - if (item.LinkFlag == 'L') + if (item.LinkFlag == 'L' || // NEXT file has a long name + item.LinkFlag == 'K') // NEXT file has a long linkname { if (item.Name.Compare(NFileHeader::kLongLink) != 0) if (item.Name.Compare(NFileHeader::kLongLink2) != 0) @@ -150,11 +149,17 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item) fullName.ReleaseBuffer(); UInt64 headerPosition = item.HeaderPosition; + if (item.LinkFlag == 'L') { size_t processedSize2; RINOK(GetNextItemReal(stream, filled, item, processedSize2)); + item.LongLinkSize = (unsigned)processedSize; + } + else + { + item.LongLinkSize = (unsigned)processedSize - NFileHeader::kRecordSize; + item.Size = 0; } - item.LongLinkSize = (unsigned)processedSize; item.Name = fullName; item.HeaderPosition = headerPosition; } diff --git a/CPP/7zip/Archive/Tar/TarItem.h b/CPP/7zip/Archive/Tar/TarItem.h index 7d95844d..afe8997d 100755 --- a/CPP/7zip/Archive/Tar/TarItem.h +++ b/CPP/7zip/Archive/Tar/TarItem.h @@ -1,12 +1,10 @@ -// Archive/Tar/Item.h +// TarItem.h #ifndef __ARCHIVE_TAR_ITEM_H #define __ARCHIVE_TAR_ITEM_H -#include "Common/Types.h" -#include "Common/MyString.h" - #include "../Common/ItemNameUtils.h" + #include "TarHeader.h" namespace NArchive { @@ -25,8 +23,8 @@ struct CItem UInt32 DeviceMinor; AString LinkName; - AString UserName; - AString GroupName; + AString User; + AString Group; char Magic[8]; char LinkFlag; diff --git a/CPP/7zip/Archive/Tar/TarOut.cpp b/CPP/7zip/Archive/Tar/TarOut.cpp index 0892748f..1ec314c7 100755 --- a/CPP/7zip/Archive/Tar/TarOut.cpp +++ b/CPP/7zip/Archive/Tar/TarOut.cpp @@ -1,14 +1,13 @@ -// Archive/TarOut.cpp +// TarOut.cpp #include "StdAfx.h" -#include "TarOut.h" -#include "TarHeader.h" - #include "Common/IntToString.h" -#include "Windows/Defs.h" + #include "../../Common/StreamUtils.h" +#include "TarOut.h" + namespace NArchive { namespace NTar { @@ -114,10 +113,10 @@ HRESULT COutArchive::WriteHeaderReal(const CItem &item) memmove(cur, item.Magic, 8); cur += 8; - RETURN_IF_NOT_TRUE(CopyString(cur, item.UserName, NFileHeader::kUserNameSize)); - cur += NFileHeader::kUserNameSize; - RETURN_IF_NOT_TRUE(CopyString(cur, item.GroupName, NFileHeader::kGroupNameSize)); + RETURN_IF_NOT_TRUE(CopyString(cur, item.User, NFileHeader::kUserNameSize)); cur += NFileHeader::kUserNameSize; + RETURN_IF_NOT_TRUE(CopyString(cur, item.Group, NFileHeader::kGroupNameSize)); + cur += NFileHeader::kGroupNameSize; if (item.DeviceMajorDefined) diff --git a/CPP/7zip/Archive/Tar/TarUpdate.cpp b/CPP/7zip/Archive/Tar/TarUpdate.cpp index 1c048915..0577848f 100755 --- a/CPP/7zip/Archive/Tar/TarUpdate.cpp +++ b/CPP/7zip/Archive/Tar/TarUpdate.cpp @@ -55,10 +55,12 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, const CUpdateItem &ui = updateItems[i]; CItem item; - if (ui.NewProperties) + if (ui.NewProps) { - item.Mode = 0777; - item.Name = (ui.Name); + item.Mode = ui.Mode; + item.Name = ui.Name; + item.User = ui.User; + item.Group = ui.Group; if (ui.IsDir) { item.LinkFlag = NFileHeader::NLinkFlag::kDirectory; @@ -77,21 +79,16 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, memmove(item.Magic, NFileHeader::NMagic::kEmpty, 8); } else - { - const CItemEx &existItemInfo = inputItems[ui.IndexInArchive]; - item = existItemInfo; - } + item = inputItems[ui.IndexInArchive]; + if (ui.NewData) { item.Size = ui.Size; - if (item.Size == UInt64(Int64(-1))) + if (item.Size == (UInt64)(Int64)-1) return E_INVALIDARG; } else - { - const CItemEx &existItemInfo = inputItems[ui.IndexInArchive]; - item.Size = existItemInfo.Size; - } + item.Size = inputItems[ui.IndexInArchive].Size; if (ui.NewData) { @@ -116,7 +113,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, { const CItemEx &existItemInfo = inputItems[ui.IndexInArchive]; UInt64 size; - if (ui.NewProperties) + if (ui.NewProps) { RINOK(outArchive.WriteHeader(item)); RINOK(inStream->Seek(existItemInfo.GetDataPosition(), STREAM_SEEK_SET, NULL)); diff --git a/CPP/7zip/Archive/Tar/TarUpdate.h b/CPP/7zip/Archive/Tar/TarUpdate.h index 7d196d1c..fb217d19 100755 --- a/CPP/7zip/Archive/Tar/TarUpdate.h +++ b/CPP/7zip/Archive/Tar/TarUpdate.h @@ -1,4 +1,4 @@ -// Tar/Update.h +// TarUpdate.h #ifndef __TAR_UPDATE_H #define __TAR_UPDATE_H @@ -11,14 +11,16 @@ namespace NTar { struct CUpdateItem { - bool NewData; - bool NewProperties; int IndexInArchive; int IndexInClient; - UInt32 Time; + UInt32 Mode; UInt64 Size; AString Name; + AString User; + AString Group; + bool NewData; + bool NewProps; bool IsDir; }; diff --git a/CPP/7zip/Archive/Udf/UdfHandler.cpp b/CPP/7zip/Archive/Udf/UdfHandler.cpp index 12329147..07b61c51 100755 --- a/CPP/7zip/Archive/Udf/UdfHandler.cpp +++ b/CPP/7zip/Archive/Udf/UdfHandler.cpp @@ -8,12 +8,11 @@ #include "Windows/PropVariant.h" #include "Windows/Time.h" +#include "../../Common/LimitedStreams.h" #include "../../Common/ProgressUtils.h" #include "../../Compress/CopyCoder.h" -#include "../Common/DummyOutStream.h" - #include "UdfHandler.h" namespace NArchive { @@ -201,79 +200,129 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val COM_TRY_END } -class CUdfInStream: - public ISequentialInStream, +class CBufInStream: + public IInStream, public CMyUnknownImp { + CByteBuffer _data; + UInt64 _pos; + +public: + void Init(const CByteBuffer &data) + { + _data = data; + _pos = 0; + } + MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - UInt64 _rem; + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + + +STDMETHODIMP CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + if (_pos > _data.GetCapacity()) + return E_FAIL; + size_t rem = _data.GetCapacity() - (size_t)_pos; + if (size < rem) + rem = (size_t)size; + memcpy(data, (const Byte *)_data + _pos, rem); + _pos += rem; + if (processedSize != NULL) + *processedSize = (UInt32)rem; + return S_OK; +} + +STDMETHODIMP CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch(seekOrigin) + { + case STREAM_SEEK_SET: _pos = offset; break; + case STREAM_SEEK_CUR: _pos += offset; break; + case STREAM_SEEK_END: _pos = _data.GetCapacity() + offset; break; + default: return STG_E_INVALIDFUNCTION; + } + if (newPosition) + *newPosition = _pos; + return S_OK; +} + +struct CSeekExtent +{ + UInt64 Phy; + UInt64 Virt; +}; + +class CExtentsStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _phyPos; + UInt64 _virtPos; + bool _needStartSeek; + + HRESULT SeekToPhys() { return Stream->Seek(_phyPos, STREAM_SEEK_SET, NULL); } + public: - CInArchive *_archive; - CMyComPtr<IInStream> _stream; - CRef2 _ref2; - int _extentIndex; - UInt32 _offsetInExtent; + CMyComPtr<IInStream> Stream; + CRecordVector<CSeekExtent> Extents; - void Init(UInt64 size) + MY_UNKNOWN_IMP1(IInStream) + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + void ReleaseStream() { Stream.Release(); } + + void Init() { - _extentIndex = 0; - _offsetInExtent = 0; - _rem = size; + _virtPos = 0; + _phyPos = 0; + _needStartSeek = true; } - void ReleaseStream() { _stream.Release(); } + }; -STDMETHODIMP CUdfInStream::Read(void *data, UInt32 size, UInt32 *processedSize) + +STDMETHODIMP CExtentsStream::Read(void *data, UInt32 size, UInt32 *processedSize) { if (processedSize) *processedSize = 0; - if (size > _rem) - size = (UInt32)_rem; - while (size > 0) + if (size > 0) { - const CLogVol &vol = _archive->LogVols[_ref2.Vol]; - const CRef &ref = vol.FileSets[_ref2.Fs].Refs[_ref2.Ref]; - const CFile &file = _archive->Files[ref.FileIndex]; - const CItem &item = _archive->Items[file.ItemIndex]; - - HRESULT res = S_OK; - if (item.IsInline) + UInt64 totalSize = Extents.Back().Virt; + if (_virtPos >= totalSize) + return (_virtPos == totalSize) ? S_OK : E_FAIL; + int left = 0, right = Extents.Size() - 1; + for (;;) { - size_t rem = item.InlineData.GetCapacity() - _offsetInExtent; - if (rem == 0) - return S_OK; - if (rem > _rem) - rem = (size_t)_rem; - memcpy(data, (const Byte *)item.InlineData + _offsetInExtent, rem); + int mid = (left + right) / 2; + if (mid == left) + break; + if (_virtPos < Extents[mid].Virt) + right = mid; + else + left = mid; } - else + + const CSeekExtent &extent = Extents[left]; + UInt64 phyPos = extent.Phy + (_virtPos - extent.Virt); + if (_needStartSeek || _phyPos != phyPos) { - if (_extentIndex >= item.Extents.Size()) - return S_OK; - const CMyExtent &extent = item.Extents[_extentIndex]; - UInt32 rem = extent.GetLen() - _offsetInExtent; - if (rem == 0) - { - _extentIndex++; - _offsetInExtent = 0; - continue; - } - if (size > rem) - size = rem; - - int partitionIndex = vol.PartitionMaps[extent.PartitionRef].PartitionIndex; - UInt32 logBlockNumber = extent.Pos; - const CPartition &partition = _archive->Partitions[partitionIndex]; - UInt64 offset = ((UInt64)partition.Pos << _archive->SecLogSize) + - (UInt64)logBlockNumber * vol.BlockSize + _offsetInExtent; - - RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); - res = _stream->Read(data, size, &size); + _needStartSeek = false; + _phyPos = phyPos; + RINOK(SeekToPhys()); } - _offsetInExtent += size; - _rem -= size; + + UInt64 rem = Extents[left + 1].Virt - _virtPos; + if (size > rem) + size = (UInt32)rem; + + HRESULT res = Stream->Read(data, size, &size); + _phyPos += size; + _virtPos += size; if (processedSize) *processedSize = size; return res; @@ -281,6 +330,83 @@ STDMETHODIMP CUdfInStream::Read(void *data, UInt32 size, UInt32 *processedSize) return S_OK; } +STDMETHODIMP CExtentsStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch(seekOrigin) + { + case STREAM_SEEK_SET: _virtPos = offset; break; + case STREAM_SEEK_CUR: _virtPos += offset; break; + case STREAM_SEEK_END: _virtPos = Extents.Back().Virt + offset; break; + default: return STG_E_INVALIDFUNCTION; + } + if (newPosition) + *newPosition = _virtPos; + return S_OK; +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + *stream = 0; + + const CRef2 &ref2 = _refs2[index]; + const CLogVol &vol = _archive.LogVols[ref2.Vol]; + const CRef &ref = vol.FileSets[ref2.Fs].Refs[ref2.Ref]; + const CFile &file = _archive.Files[ref.FileIndex]; + const CItem &item = _archive.Items[file.ItemIndex]; + UInt64 size = item.Size; + + if (!item.IsRecAndAlloc() || !item.CheckChunkSizes() || ! _archive.CheckItemExtents(ref2.Vol, item)) + return E_NOTIMPL; + + if (item.IsInline) + { + CBufInStream *inStreamSpec = new CBufInStream; + CMyComPtr<ISequentialInStream> inStream = inStreamSpec; + inStreamSpec->Init(item.InlineData); + *stream = inStream .Detach(); + return S_OK; + } + + CExtentsStream *extentStreamSpec = new CExtentsStream(); + CMyComPtr<ISequentialInStream> extentStream = extentStreamSpec; + + extentStreamSpec->Stream = _inStream; + + UInt64 virtOffset = 0; + for (int extentIndex = 0; extentIndex < item.Extents.Size(); extentIndex++) + { + const CMyExtent &extent = item.Extents[extentIndex]; + UInt32 len = extent.GetLen(); + if (len == 0) + continue; + if (size < len) + return S_FALSE; + + int partitionIndex = vol.PartitionMaps[extent.PartitionRef].PartitionIndex; + UInt32 logBlockNumber = extent.Pos; + const CPartition &partition = _archive.Partitions[partitionIndex]; + UInt64 offset = ((UInt64)partition.Pos << _archive.SecLogSize) + + (UInt64)logBlockNumber * vol.BlockSize; + + CSeekExtent se; + se.Phy = offset; + se.Virt = virtOffset; + virtOffset += len; + extentStreamSpec->Extents.Add(se); + + size -= len; + } + if (size != 0) + return S_FALSE; + CSeekExtent se; + se.Phy = 0; + se.Virt = virtOffset; + extentStreamSpec->Extents.Add(se); + extentStreamSpec->Init(); + *stream = extentStream.Detach(); + return S_OK; +} + STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 _aTestMode, IArchiveExtractCallback *extractCallback) { @@ -307,7 +433,6 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, extractCallback->SetTotal(totalSize); UInt64 currentTotalSize = 0; - UInt64 currentItemSize; NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; @@ -316,20 +441,13 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); - CUdfInStream *udfInStreamSpec = new CUdfInStream(); - CMyComPtr<ISequentialInStream> udfInStream = udfInStreamSpec; - - udfInStreamSpec->_archive = &_archive; - udfInStreamSpec->_stream = _inStream; - - CDummyOutStream *outStreamSpec = new CDummyOutStream; + CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); - for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) + for (i = 0; i < numItems; i++) { lps->InSize = lps->OutSize = currentTotalSize; RINOK(lps->SetCur()); - currentItemSize = 0; CMyComPtr<ISequentialOutStream> realOutStream; Int32 askMode = testMode ? NArchive::NExtract::NAskMode::kTest : @@ -349,24 +467,28 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); continue; } - currentItemSize = item.Size; + currentTotalSize += item.Size; - if (!testMode && (!realOutStream)) + if (!testMode && !realOutStream) continue; - RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->PrepareOperation(askMode)); outStreamSpec->SetStream(realOutStream); realOutStream.Release(); - outStreamSpec->Init(); - Int32 opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; - if (item.IsRecAndAlloc() && item.CheckChunkSizes() && _archive.CheckItemExtents(ref2.Vol, item)) + outStreamSpec->Init(item.Size); + Int32 opRes; + CMyComPtr<ISequentialInStream> udfInStream; + HRESULT res = GetStream(index, &udfInStream); + if (res == E_NOTIMPL) + opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; + else if (res != S_OK) + opRes = NArchive::NExtract::NOperationResult::kDataError; + else { - udfInStreamSpec->_ref2 = ref2; - udfInStreamSpec->Init(item.Size); RINOK(copyCoder->Code(udfInStream, outStream, NULL, NULL, progress)); - opRes = (outStreamSpec->GetSize() == currentItemSize) ? - NArchive::NExtract::NOperationResult::kOK: - NArchive::NExtract::NOperationResult::kDataError; + opRes = outStreamSpec->IsFinishedOK() ? + NArchive::NExtract::NOperationResult::kOK: + NArchive::NExtract::NOperationResult::kDataError; } outStreamSpec->ReleaseStream(); RINOK(extractCallback->SetOperationResult(opRes)); diff --git a/CPP/7zip/Archive/Udf/UdfHandler.h b/CPP/7zip/Archive/Udf/UdfHandler.h index ceab85ae..63f859af 100755 --- a/CPP/7zip/Archive/Udf/UdfHandler.h +++ b/CPP/7zip/Archive/Udf/UdfHandler.h @@ -20,14 +20,16 @@ struct CRef2 class CHandler: public IInArchive, + public IInArchiveGetStream, public CMyUnknownImp { CMyComPtr<IInStream> _inStream; CInArchive _archive; CRecordVector<CRef2> _refs2; public: - MY_UNKNOWN_IMP1(IInArchive) + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; }} diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp index 75a0c333..d2f9e731 100755 --- a/CPP/7zip/Archive/Udf/UdfIn.cpp +++ b/CPP/7zip/Archive/Udf/UdfIn.cpp @@ -2,14 +2,11 @@ #include "StdAfx.h" -#include "UdfIn.h" +#include "../../../../C/CpuArch.h" #include "../../Common/StreamUtils.h" -extern "C" -{ - #include "../../../../C/CpuArch.h" -} +#include "UdfIn.h" #define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) @@ -580,11 +577,16 @@ HRESULT CInArchive::Open2() UInt64 fileSize; RINOK(_stream->Seek(0, STREAM_SEEK_END, &fileSize)); - const int kSecLogSizeMax = 11; - const int kSecLogSizeMin = 8; + // Some UDFs contain additional 2 KB of zeros, so we also check 12, corrected to 11. + const int kSecLogSizeMax = 12; Byte buf[1 << kSecLogSizeMax]; - for (SecLogSize = kSecLogSizeMax; SecLogSize >= kSecLogSizeMin; SecLogSize -= 3) + Byte kSizesLog[] = { 11, 8, 12 }; + + for (int i = 0;; i++) { + if (i == sizeof(kSizesLog) / sizeof(kSizesLog[0])) + return S_FALSE; + SecLogSize = kSizesLog[i]; Int32 bufSize = 1 << SecLogSize; if (bufSize > fileSize) return S_FALSE; @@ -595,8 +597,8 @@ HRESULT CInArchive::Open2() if (tag.Id == DESC_TYPE_AnchorVolPtr) break; } - if (SecLogSize < kSecLogSizeMin) - return S_FALSE; + if (SecLogSize == 12) + SecLogSize = 11; CExtent extentVDS; extentVDS.Parse(buf + 16); diff --git a/CPP/7zip/Archive/VhdHandler.cpp b/CPP/7zip/Archive/VhdHandler.cpp new file mode 100755 index 00000000..5fc2c918 --- /dev/null +++ b/CPP/7zip/Archive/VhdHandler.cpp @@ -0,0 +1,731 @@ +// VhdHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/Buffer.h" +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/MyString.h" + +#include "Windows/PropVariant.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#define Get16(p) GetBe16(p) +#define Get32(p) GetBe32(p) +#define Get64(p) GetBe64(p) + +#define G32(p, dest) dest = Get32(p); +#define G64(p, dest) dest = Get64(p); + +using namespace NWindows; + +namespace NArchive { +namespace NVhd { + +static const UInt32 kUnusedBlock = 0xFFFFFFFF; + +static const UInt32 kDiskType_Fixed = 2; +static const UInt32 kDiskType_Dynamic = 3; +static const UInt32 kDiskType_Diff = 4; + +static const char *kDiskTypes[] = +{ + "0", + "1", + "Fixed", + "Dynamic", + "Differencing" +}; + +struct CFooter +{ + // UInt32 Features; + // UInt32 FormatVersion; + UInt64 DataOffset; + UInt32 CTime; + UInt32 CreatorApp; + UInt32 CreatorVersion; + UInt32 CreatorHostOS; + // UInt64 OriginalSize; + UInt64 CurrentSize; + UInt32 DiskGeometry; + UInt32 Type; + Byte Id[16]; + Byte SavedState; + + bool IsFixed() const { return Type == kDiskType_Fixed; } + bool ThereIsDynamic() const { return Type == kDiskType_Dynamic || Type == kDiskType_Diff; } + // bool IsSupported() const { return Type == kDiskType_Fixed || Type == kDiskType_Dynamic || Type == kDiskType_Diff; } + UInt32 NumCyls() const { return DiskGeometry >> 16; } + UInt32 NumHeads() const { return (DiskGeometry >> 8) & 0xFF; } + UInt32 NumSectorsPerTrack() const { return DiskGeometry & 0xFF; } + AString GetTypeString() const; + bool Parse(const Byte *p); +}; + +AString CFooter::GetTypeString() const +{ + if (Type < sizeof(kDiskTypes) / sizeof(kDiskTypes[0])) + return kDiskTypes[Type]; + char s[16]; + ConvertUInt32ToString(Type, s); + return s; +} + +static bool CheckBlock(const Byte *p, unsigned size, unsigned checkSumOffset, unsigned zeroOffset) +{ + UInt32 sum = 0; + unsigned i; + for (i = 0; i < checkSumOffset; i++) + sum += p[i]; + for (i = checkSumOffset + 4; i < size; i++) + sum += p[i]; + if (~sum != Get32(p + checkSumOffset)) + return false; + for (i = zeroOffset; i < size; i++) + if (p[i] != 0) + return false; + return true; +} + +bool CFooter::Parse(const Byte *p) +{ + if (memcmp(p, "conectix", 8) != 0) + return false; + // G32(p + 0x08, Features); + // G32(p + 0x0C, FormatVersion); + G64(p + 0x10, DataOffset); + G32(p + 0x18, CTime); + G32(p + 0x1C, CreatorApp); + G32(p + 0x20, CreatorVersion); + G32(p + 0x24, CreatorHostOS); + // G64(p + 0x28, OriginalSize); + G64(p + 0x30, CurrentSize); + G32(p + 0x38, DiskGeometry); + G32(p + 0x3C, Type); + memcpy(Id, p + 0x44, 16); + SavedState = p[0x54]; + return CheckBlock(p, 512, 0x40, 0x55); +} + +/* +struct CParentLocatorEntry +{ + UInt32 Code; + UInt32 DataSpace; + UInt32 DataLen; + UInt64 DataOffset; + + bool Parse(const Byte *p); +}; +bool CParentLocatorEntry::Parse(const Byte *p) +{ + G32(p + 0x00, Code); + G32(p + 0x04, DataSpace); + G32(p + 0x08, DataLen); + G32(p + 0x10, DataOffset); + return (Get32(p + 0x0C) == 0); // Resrved +} +*/ + +struct CDynHeader +{ + // UInt64 DataOffset; + UInt64 TableOffset; + // UInt32 HeaderVersion; + UInt32 NumBlocks; + int BlockSizeLog; + UInt32 ParentTime; + Byte ParentId[16]; + UString ParentName; + // CParentLocatorEntry ParentLocators[8]; + + bool Parse(const Byte *p); + UInt32 NumBitMapSectors() const + { + UInt32 numSectorsInBlock = (1 << (BlockSizeLog - 9)); + return (numSectorsInBlock + 512 * 8 - 1) / (512 * 8); + } +}; + +static int GetLog(UInt32 num) +{ + for (int i = 0; i < 31; i++) + if (((UInt32)1 << i) == num) + return i; + return -1; +} + +bool CDynHeader::Parse(const Byte *p) +{ + if (memcmp(p, "cxsparse", 8) != 0) + return false; + // G64(p + 0x08, DataOffset); + G64(p + 0x10, TableOffset); + // G32(p + 0x18, HeaderVersion); + G32(p + 0x1C, NumBlocks); + BlockSizeLog = GetLog(Get32(p + 0x20)); + if (BlockSizeLog < 9 || BlockSizeLog > 30) + return false; + G32(p + 0x38, ParentTime); + if (Get32(p + 0x3C) != 0) // reserved + return false; + memcpy(ParentId, p + 0x28, 16); + { + const int kNameLength = 256; + wchar_t *s = ParentName.GetBuffer(kNameLength); + for (unsigned i = 0; i < kNameLength; i++) + s[i] = Get16(p + 0x40 + i * 2); + s[kNameLength] = 0; + ParentName.ReleaseBuffer(); + } + /* + for (int i = 0; i < 8; i++) + if (!ParentLocators[i].Parse(p + 0x240 + i * 24)) + return false; + */ + return CheckBlock(p, 1024, 0x24, 0x240 + 8 * 24); +} + +class CHandler: + public IInStream, + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + UInt64 _virtPos; + UInt64 _phyPos; + UInt64 _phyLimit; + + CFooter Footer; + CDynHeader Dyn; + CRecordVector<UInt32> Bat; + CByteBuffer BitMap; + UInt32 BitMapTag; + UInt32 NumUsedBlocks; + CMyComPtr<IInStream> Stream; + CMyComPtr<IInStream> ParentStream; + CHandler *Parent; + + HRESULT Seek(UInt64 offset); + HRESULT InitAndSeek(); + HRESULT ReadPhy(UInt64 offset, void *data, UInt32 size); + + bool NeedParent() const { return Footer.Type == kDiskType_Diff; } + UInt64 GetSize() const { return Footer.CurrentSize; } + UInt64 GetPackSize() const + { return Footer.ThereIsDynamic() ? ((UInt64)NumUsedBlocks << Dyn.BlockSizeLog) : Footer.CurrentSize; } + + UString GetParentName() const + { + const CHandler *p = this; + UString res; + while (p && p->NeedParent()) + { + if (!res.IsEmpty()) + res += L" -> "; + res += p->Dyn.ParentName; + p = p->Parent; + } + return res; + } + + bool IsOK() const + { + const CHandler *p = this; + while (p->NeedParent()) + { + p = p->Parent; + if (p == 0) + return false; + } + return true; + } + + HRESULT Open3(); + HRESULT Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback *openArchiveCallback, int level); + +public: + MY_UNKNOWN_IMP3(IInArchive, IInArchiveGetStream, IInStream) + + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + +HRESULT CHandler::Seek(UInt64 offset) { return Stream->Seek(offset, STREAM_SEEK_SET, NULL); } + +HRESULT CHandler::InitAndSeek() +{ + if (ParentStream) + { + RINOK(Parent->InitAndSeek()); + } + _virtPos = _phyPos = 0; + BitMapTag = kUnusedBlock; + BitMap.SetCapacity(Dyn.NumBitMapSectors() << 9); + return Seek(0); +} + +HRESULT CHandler::ReadPhy(UInt64 offset, void *data, UInt32 size) +{ + if (offset + size > _phyLimit) + return S_FALSE; + if (offset != _phyPos) + { + _phyPos = offset; + RINOK(Seek(offset)); + } + HRESULT res = ReadStream_FALSE(Stream, data, size); + _phyPos += size; + return res; +} + +HRESULT CHandler::Open3() +{ + RINOK(Stream->Seek(0, STREAM_SEEK_END, &_phyPos)); + if (_phyPos < 512) + return S_FALSE; + const UInt32 kDynSize = 1024; + Byte buf[kDynSize]; + + _phyLimit = _phyPos; + RINOK(ReadPhy(_phyLimit - 512, buf, 512)); + if (!Footer.Parse(buf)) + return S_FALSE; + _phyLimit -= 512; + + if (!Footer.ThereIsDynamic()) + return S_OK; + + RINOK(ReadPhy(0, buf + 512, 512)); + if (memcmp(buf, buf + 512, 512) != 0) + return S_FALSE; + + RINOK(ReadPhy(Footer.DataOffset, buf, kDynSize)); + if (!Dyn.Parse(buf)) + return S_FALSE; + + if (Dyn.NumBlocks >= (UInt32)1 << 31) + return S_FALSE; + if (GetSize() != ((UInt64)Dyn.NumBlocks << Dyn.BlockSizeLog)) + return S_FALSE; + + Bat.Reserve(Dyn.NumBlocks); + while ((UInt32)Bat.Size() < Dyn.NumBlocks) + { + RINOK(ReadPhy(Dyn.TableOffset + (UInt64)Bat.Size() * 4, buf, 512)); + for (UInt32 j = 0; j < 512; j += 4) + { + UInt32 v = Get32(buf + j); + if (v != kUnusedBlock) + NumUsedBlocks++; + Bat.Add(v); + if ((UInt32)Bat.Size() >= Dyn.NumBlocks) + break; + } + } + return S_OK; +} + +STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + if (_virtPos >= GetSize()) + return (GetSize() == _virtPos) ? S_OK: E_FAIL; + if (size == 0) + return S_OK; + UInt32 blockIndex = (UInt32)(_virtPos >> Dyn.BlockSizeLog); + UInt32 blockSectIndex = Bat[blockIndex]; + UInt32 blockSize = (UInt32)1 << Dyn.BlockSizeLog; + UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1); + size = MyMin(blockSize - offsetInBlock, size); + + HRESULT res = S_OK; + if (blockSectIndex == kUnusedBlock) + { + if (ParentStream) + { + RINOK(ParentStream->Seek(_virtPos, STREAM_SEEK_SET, NULL)); + res = ParentStream->Read(data, size, &size); + } + else + memset(data, 0, size); + } + else + { + UInt64 newPos = (UInt64)blockSectIndex << 9; + if (BitMapTag != blockIndex) + { + RINOK(ReadPhy(newPos, BitMap, (UInt32)BitMap.GetCapacity())); + BitMapTag = blockIndex; + } + RINOK(ReadPhy(newPos + BitMap.GetCapacity() + offsetInBlock, data, size)); + for (UInt32 cur = 0; cur < size;) + { + UInt32 rem = MyMin(0x200 - (offsetInBlock & 0x1FF), size - cur); + UInt32 bmi = offsetInBlock >> 9; + if (((BitMap[bmi >> 3] >> (7 - (bmi & 7))) & 1) == 0) + { + if (ParentStream) + { + RINOK(ParentStream->Seek(_virtPos + cur, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream_FALSE(ParentStream, (Byte *)data + cur, rem)); + } + else + { + const Byte *p = (const Byte *)data + cur; + for (UInt32 i = 0; i < rem; i++) + if (p[i] != 0) + return S_FALSE; + } + } + offsetInBlock += rem; + cur += rem; + } + } + if (processedSize != NULL) + *processedSize = size; + _virtPos += size; + return res; +} + +STDMETHODIMP CHandler::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch(seekOrigin) + { + case STREAM_SEEK_SET: _virtPos = offset; break; + case STREAM_SEEK_CUR: _virtPos += offset; break; + case STREAM_SEEK_END: _virtPos = GetSize() + offset; break; + default: return STG_E_INVALIDFUNCTION; + } + if (newPosition) + *newPosition = _virtPos; + return S_OK; +} + +enum +{ + kpidParent = kpidUserDefined, + kpidSavedState +}; + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidSize, VT_UI8}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidClusterSize, VT_UI8}, + { NULL, kpidMethod, VT_BSTR}, + { L"Parent", kpidParent, VT_BSTR}, + { NULL, kpidCreatorApp, VT_BSTR}, + { NULL, kpidHostOS, VT_BSTR}, + { L"Saved State", kpidSavedState, VT_BOOL}, + { NULL, kpidId, VT_BSTR} + }; + +STATPROPSTG kProps[] = +{ + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidCTime, VT_FILETIME} + + /* + { NULL, kpidNumCyls, VT_UI4}, + { NULL, kpidNumHeads, VT_UI4}, + { NULL, kpidSectorsPerTrack, VT_UI4} + */ +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_WITH_NAME + +// VHD start time: 2000-01-01 +static const UInt64 kVhdTimeStartValue = (UInt64)3600 * 24 * (399 * 365 + 24 * 4); + +static void VhdTimeToFileTime(UInt32 vhdTime, NCOM::CPropVariant &prop) +{ + FILETIME ft, utc; + UInt64 v = (kVhdTimeStartValue + vhdTime) * 10000000; + ft.dwLowDateTime = (DWORD)v; + ft.dwHighDateTime = (DWORD)(v >> 32); + // specification says that it's UTC time, but Virtual PC 6 writes local time. Why? + LocalFileTimeToFileTime(&ft, &utc); + prop = utc; +} + +static void StringToAString(char *dest, UInt32 s) +{ + for (int i = 24; i >= 0; i -= 8) + { + Byte b = (Byte)((s >> i) & 0xFF); + if (b < 0x20 || b > 0x7F) + break; + *dest++ = b; + } + *dest = 0; +} + +static void ConvertByteToHex(unsigned value, char *s) +{ + for (int i = 0; i < 2; i++) + { + unsigned t = value & 0xF; + value >>= 4; + s[1 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NCOM::CPropVariant prop; + switch(propID) + { + case kpidMainSubfile: prop = (UInt32)0; break; + case kpidCTime: VhdTimeToFileTime(Footer.CTime, prop); break; + case kpidClusterSize: if (Footer.ThereIsDynamic()) prop = (UInt32)1 << Dyn.BlockSizeLog; break; + case kpidMethod: + { + AString s = Footer.GetTypeString(); + if (NeedParent()) + { + s += " -> "; + const CHandler *p = this; + while (p != 0 && p->NeedParent()) + p = p->Parent; + if (p == 0) + s += '?'; + else + s += p->Footer.GetTypeString(); + } + prop = s; + break; + } + case kpidCreatorApp: + { + char s[16]; + StringToAString(s, Footer.CreatorApp); + AString res = s; + res.Trim(); + ConvertUInt32ToString(Footer.CreatorVersion >> 16, s); + res += ' '; + res += s; + res += '.'; + ConvertUInt32ToString(Footer.CreatorVersion & 0xFFFF, s); + res += s; + prop = res; + break; + } + case kpidHostOS: + { + if (Footer.CreatorHostOS == 0x5769326b) + prop = "Windows"; + else + { + char s[16]; + StringToAString(s, Footer.CreatorHostOS); + prop = s; + } + break; + } + case kpidId: + { + char s[32 + 4]; + for (int i = 0; i < 16; i++) + ConvertByteToHex(Footer.Id[i], s + i * 2); + s[32] = 0; + prop = s; + break; + } + case kpidSavedState: prop = Footer.SavedState ? true : false; break; + case kpidParent: if (NeedParent()) prop = GetParentName(); break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +HRESULT CHandler::Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback *openArchiveCallback, int level) +{ + Close(); + Stream = stream; + if (level > 32) + return S_FALSE; + RINOK(Open3()); + if (child && memcmp(child->Dyn.ParentId, Footer.Id, 16) != 0) + return S_FALSE; + if (Footer.Type != kDiskType_Diff) + return S_OK; + CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; + if (openArchiveCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback) != S_OK) + return S_FALSE; + CMyComPtr<IInStream> nextStream; + HRESULT res = openVolumeCallback->GetStream(Dyn.ParentName, &nextStream); + if (res == S_FALSE) + return S_OK; + RINOK(res); + + Parent = new CHandler; + ParentStream = Parent; + return Parent->Open2(nextStream, this, openArchiveCallback, level + 1); +} + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback * openArchiveCallback) +{ + COM_TRY_BEGIN + { + HRESULT res; + try + { + res = Open2(stream, NULL, openArchiveCallback, 0); + if (res == S_OK) + return S_OK; + } + catch(...) + { + Close(); + throw; + } + Close(); + return res; + } + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + Bat.Clear(); + NumUsedBlocks = 0; + Parent = 0; + Stream.Release(); + ParentStream.Release(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + + switch(propID) + { + case kpidSize: prop = GetSize(); break; + case kpidPackSize: prop = GetPackSize(); break; + case kpidCTime: VhdTimeToFileTime(Footer.CTime, prop); break; + /* + case kpidNumCyls: prop = Footer.NumCyls(); break; + case kpidNumHeads: prop = Footer.NumHeads(); break; + case kpidSectorsPerTrack: prop = Footer.NumSectorsPerTrack(); 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 + if (numItems == UInt32(-1)) + numItems = 1; + if (numItems == 0) + return S_OK; + if (numItems != 1 || indices[0] != 0) + return E_INVALIDARG; + + bool testMode = (_aTestMode != 0); + + RINOK(extractCallback->SetTotal(GetSize())); + CMyComPtr<ISequentialOutStream> outStream; + Int32 askMode = testMode ? + NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract; + RINOK(extractCallback->GetStream(0, &outStream, askMode)); + if (!testMode && !outStream) + return S_OK; + RINOK(extractCallback->PrepareOperation(askMode)); + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, false); + + int res = NArchive::NExtract::NOperationResult::kDataError; + CMyComPtr<ISequentialInStream> inStream; + HRESULT hres = GetStream(0, &inStream); + if (hres == S_FALSE) + res = NArchive::NExtract::NOperationResult::kUnSupportedMethod; + else + { + RINOK(hres); + HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress); + if (hres == S_OK) + { + if (copyCoderSpec->TotalSize == GetSize()) + res = NArchive::NExtract::NOperationResult::kOK; + } + else + { + if (hres != S_FALSE) + { + RINOK(hres); + } + } + } + outStream.Release(); + return extractCallback->SetOperationResult(res); + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + *stream = 0; + if (Footer.IsFixed()) + { + CLimitedInStream *streamSpec = new CLimitedInStream; + CMyComPtr<ISequentialInStream> streamTemp = streamSpec; + streamSpec->SetStream(Stream); + streamSpec->InitAndSeek(0, GetSize()); + RINOK(streamSpec->SeekToStart()); + *stream = streamTemp.Detach(); + return S_OK; + } + if (!Footer.ThereIsDynamic() || !IsOK()) + return S_FALSE; + CMyComPtr<ISequentialInStream> streamTemp = this; + RINOK(InitAndSeek()); + *stream = streamTemp.Detach(); + return S_OK; + COM_TRY_END +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"VHD", L"vhd", L".mbr", 0xDC, { 'c', 'o', 'n', 'e', 'c', 't', 'i', 'x', 0, 0 }, 10, false, CreateArc, 0 }; + +REGISTER_ARC(Vhd) + +}} diff --git a/CPP/7zip/Archive/Wim/WimIn.cpp b/CPP/7zip/Archive/Wim/WimIn.cpp index 121e33ab..90c3c2c2 100755 --- a/CPP/7zip/Archive/Wim/WimIn.cpp +++ b/CPP/7zip/Archive/Wim/WimIn.cpp @@ -2,7 +2,8 @@ #include "StdAfx.h" -#include "Common/MyCom.h" +#include "../../../../C/CpuArch.h" + #include "Common/IntToString.h" #include "../../Common/StreamUtils.h" @@ -11,8 +12,6 @@ #include "../Common/OutStreamWithSha1.h" -#include "../../../../C/CpuArch.h" - #include "WimIn.h" #define Get16(p) GetUi16(p) @@ -354,7 +353,7 @@ static HRESULT ParseDir(const Byte *base, size_t size, sum += len; pos += 8; } - pos += sum; // skeep security descriptors + pos += sum; // skip security descriptors while ((pos & 7) != 0) pos++; if (pos != totalLength) @@ -498,8 +497,8 @@ HRESULT OpenArchive(IInStream *inStream, const CHeader &h, CByteBuffer &xml, CDa RINOK(UnpackData(inStream, si.Resource, h.IsLzxMode(), metadata, hash)); if (memcmp(hash, si.Hash, kHashSize) != 0) return S_FALSE; - wchar_t sz[32]; - ConvertUInt64ToString(imageIndex++, sz); + wchar_t sz[16]; + ConvertUInt32ToString(imageIndex++, sz); UString s = sz; s += WCHAR_PATH_SEPARATOR; RINOK(ParseDir(metadata, metadata.GetCapacity(), s, db.Items)); diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp new file mode 100755 index 00000000..116e96b6 --- /dev/null +++ b/CPP/7zip/Archive/XzHandler.cpp @@ -0,0 +1,714 @@ +// XzHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" +#include "../../../C/XzCrc64.h" +#include "../../../C/XzEnc.h" + +#include "../../Common/ComTry.h" +#include "../../Common/IntToString.h" + +#include "../ICoder.h" + +#include "../Common/CWrappers.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#include "IArchive.h" + +#include "Common/HandlerOut.h" + +using namespace NWindows; + +namespace NCompress { +namespace NLzma2 { + +HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props); + +}} + +static void *SzAlloc(void *, size_t size) { return MyAlloc(size); } +static void SzFree(void *, void *address) { MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +namespace NArchive { +namespace NXz { + +struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit; + +class CHandler: + public IInArchive, + public IArchiveOpenSeq, + #ifndef EXTRACT_ONLY + public IOutArchive, + public ISetProperties, + public COutHandler, + #endif + public CMyUnknownImp +{ + Int64 _startPosition; + UInt64 _packSize; + UInt64 _unpackSize; + UInt64 _numBlocks; + AString _methodsString; + bool _useSeq; + UInt64 _unpackSizeDefined; + UInt64 _packSizeDefined; + + CMyComPtr<IInStream> _stream; + CMyComPtr<ISequentialInStream> _seqStream; + + UInt32 _crcSize; + + void Init() + { + _crcSize = 4; + COutHandler::Init(); + } + + HRESULT Open2(IInStream *inStream, IArchiveOpenCallback *callback); + +public: + MY_QUERYINTERFACE_BEGIN + MY_QUERYINTERFACE_ENTRY(IInArchive) + MY_QUERYINTERFACE_ENTRY(IArchiveOpenSeq) + #ifndef EXTRACT_ONLY + MY_QUERYINTERFACE_ENTRY(IOutArchive) + MY_QUERYINTERFACE_ENTRY(ISetProperties) + #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + INTERFACE_IInArchive(;) + STDMETHOD(OpenSeq)(ISequentialInStream *stream); + + #ifndef EXTRACT_ONLY + INTERFACE_IOutArchive(;) + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps); + #endif + + CHandler(); +}; + +CHandler::CHandler() +{ + Init(); +} + +STATPROPSTG kProps[] = +{ + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMethod, VT_BSTR} +}; + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidNumBlocks, VT_UI4} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +static char GetHex(Byte value) +{ + return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} + +static inline void AddHexToString(AString &res, Byte value) +{ + res += GetHex((Byte)(value >> 4)); + res += GetHex((Byte)(value & 0xF)); +} + +static AString ConvertUInt32ToString(UInt32 value) +{ + char temp[32]; + ::ConvertUInt32ToString(value, temp); + return temp; +} + +static AString Lzma2PropToString(int prop) +{ + if ((prop & 1) == 0) + return ConvertUInt32ToString(prop / 2 + 12); + AString res; + char c; + + UInt32 size = (2 | ((prop) & 1)) << ((prop) / 2 + 1); + + if (prop > 17) + { + res = ConvertUInt32ToString(size >> 10); + c = 'm'; + } + else + { + res = ConvertUInt32ToString(size); + c = 'k'; + } + return res + c; +} + +struct CMethodNamePair +{ + UInt32 Id; + const char *Name; +}; + +static CMethodNamePair g_NamePairs[] = +{ + { XZ_ID_Subblock, "SB" }, + { XZ_ID_Delta, "Delta" }, + { XZ_ID_X86, "x86" }, + { XZ_ID_PPC, "PPC" }, + { XZ_ID_IA64, "IA64" }, + { XZ_ID_ARM, "ARM" }, + { XZ_ID_ARMT, "ARMT" }, + { XZ_ID_SPARC, "SPARC" }, + { XZ_ID_LZMA2, "LZMA2" } +}; + +static AString GetMethodString(const CXzFilter &f) +{ + AString s; + + for (int i = 0; i < sizeof(g_NamePairs) / sizeof(g_NamePairs[i]); i++) + if (g_NamePairs[i].Id == f.id) + s = g_NamePairs[i].Name; + if (s.IsEmpty()) + { + char temp[32]; + ::ConvertUInt64ToString(f.id, temp); + s = temp; + } + + if (f.propsSize > 0) + { + s += ':'; + if (f.id == XZ_ID_LZMA2 && f.propsSize == 1) + s += Lzma2PropToString(f.props[0]); + else if (f.id == XZ_ID_Delta && f.propsSize == 1) + s += ConvertUInt32ToString((UInt32)f.props[0] + 1); + else + { + s += '['; + for (UInt32 bi = 0; bi < f.propsSize; bi++) + AddHexToString(s, f.props[bi]); + s += ']'; + } + } + return s; +} + +static void AddString(AString &dest, const AString &src) +{ + if (!dest.IsEmpty()) + dest += ' '; + dest += src; +} + +static const char *kChecks[] = +{ + "NoCheck", + "CRC32", + NULL, + NULL, + "CRC64", + NULL, + NULL, + NULL, + NULL, + NULL, + "SHA256", + NULL, + NULL, + NULL, + NULL, + NULL +}; + +static AString GetCheckString(const CXzs &xzs) +{ + size_t i; + UInt32 mask = 0; + for (i = 0; i < xzs.num; i++) + mask |= ((UInt32)1 << XzFlags_GetCheckType(xzs.streams[i].flags)); + AString s; + for (i = 0; i <= XZ_CHECK_MASK; i++) + if (((mask >> i) & 1) != 0) + { + AString s2; + if (kChecks[i]) + s2 = kChecks[i]; + else + s2 = "Check-" + ConvertUInt32ToString((UInt32)i); + AddString(s, s2); + } + return s; +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidNumBlocks: if (!_useSeq) prop = _numBlocks; break; + case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; + case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidSize: if (_unpackSizeDefined) prop = _unpackSize; break; + case kpidPackSize: if (_packSizeDefined) prop = _packSize; break; + case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + + +struct COpenCallbackWrap +{ + ICompressProgress p; + IArchiveOpenCallback *OpenCallback; + HRESULT Res; + COpenCallbackWrap(IArchiveOpenCallback *progress); +}; + +static SRes OpenCallbackProgress(void *pp, UInt64 inSize, UInt64 /* outSize */) +{ + COpenCallbackWrap *p = (COpenCallbackWrap *)pp; + p->Res = p->OpenCallback->SetCompleted(NULL, &inSize); + return (SRes)p->Res; +} + +COpenCallbackWrap::COpenCallbackWrap(IArchiveOpenCallback *callback) +{ + p.Progress = OpenCallbackProgress; + OpenCallback = callback; + Res = SZ_OK; +} + +struct CXzsCPP +{ + CXzs p; + CXzsCPP() { Xzs_Construct(&p); } + ~CXzsCPP() { Xzs_Free(&p, &g_Alloc); } +}; + +HRESULT CHandler::Open2(IInStream *inStream, IArchiveOpenCallback *callback) +{ + CSeekInStreamWrap inStreamImp(inStream); + + CLookToRead lookStream; + LookToRead_CreateVTable(&lookStream, True); + lookStream.realStream = &inStreamImp.p; + LookToRead_Init(&lookStream); + + COpenCallbackWrap openWrap(callback); + RINOK(inStream->Seek(0, STREAM_SEEK_END, &_packSize)); + RINOK(callback->SetTotal(NULL, &_packSize)); + + CXzsCPP xzs; + SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.s, &_startPosition, &openWrap.p, &g_Alloc); + if (res == SZ_ERROR_NO_ARCHIVE && xzs.p.num > 0) + res = SZ_OK; + if (res == SZ_OK) + { + _packSize -= _startPosition; + _unpackSize = Xzs_GetUnpackSize(&xzs.p); + _unpackSizeDefined = _packSizeDefined = true; + _numBlocks = (UInt64)Xzs_GetNumBlocks(&xzs.p); + + RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); + CXzStreamFlags st; + CSeqInStreamWrap inStreamWrap(inStream); + SRes res2 = Xz_ReadHeader(&st, &inStreamWrap.p); + + if (res2 == SZ_OK) + { + CXzBlock block; + Bool isIndex; + UInt32 headerSizeRes; + res2 = XzBlock_ReadHeader(&block, &inStreamWrap.p, &isIndex, &headerSizeRes); + if (res2 == SZ_OK && !isIndex) + { + int numFilters = XzBlock_GetNumFilters(&block); + for (int i = 0; i < numFilters; i++) + AddString(_methodsString, GetMethodString(block.filters[i])); + } + } + AddString(_methodsString, GetCheckString(xzs.p)); + } + + if (res != SZ_OK || _startPosition != 0) + { + RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); + CXzStreamFlags st; + CSeqInStreamWrap inStreamWrap(inStream); + SRes res2 = Xz_ReadHeader(&st, &inStreamWrap.p); + if (res2 == SZ_OK) + { + res = res2; + _startPosition = 0; + _useSeq = True; + _unpackSizeDefined = _packSizeDefined = false; + } + } + if (res == SZ_ERROR_NO_ARCHIVE) + return S_FALSE; + RINOK(SResToHRESULT(res)); + _stream = inStream; + _seqStream = inStream; + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + try + { + Close(); + return Open2(inStream, callback); + } + catch(...) { return S_FALSE; } + COM_TRY_END +} + +STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) +{ + Close(); + _seqStream = stream; + return S_OK; +} + +STDMETHODIMP CHandler::Close() +{ + _numBlocks = 0; + _useSeq = true; + _unpackSizeDefined = _packSizeDefined = false; + _methodsString.Empty(); + _stream.Release(); + _seqStream.Release(); + return S_OK; +} + +class CSeekToSeqStream: + public IInStream, + public CMyUnknownImp +{ +public: + CMyComPtr<ISequentialInStream> Stream; + MY_UNKNOWN_IMP1(IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + +STDMETHODIMP CSeekToSeqStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + return Stream->Read(data, size, processedSize); +} + +STDMETHODIMP CSeekToSeqStream::Seek(Int64, UInt32, UInt64 *) { return E_NOTIMPL; } + +struct CXzUnpackerCPP +{ + Byte *InBuf; + Byte *OutBuf; + CXzUnpacker p; + CXzUnpackerCPP(): InBuf(0), OutBuf(0) {} + ~CXzUnpackerCPP() + { + XzUnpacker_Free(&p); + MyFree(InBuf); + MyFree(OutBuf); + } +}; + +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); + + extractCallback->SetTotal(_packSize); + UInt64 currentTotalPacked = 0; + RINOK(extractCallback->SetCompleted(¤tTotalPacked)); + 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); + + if (_stream) + { + RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); + } + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, true); + + CCompressProgressWrap progressWrap(progress); + + SRes res; + + const UInt32 kInBufSize = 1 << 15; + const UInt32 kOutBufSize = 1 << 21; + + UInt32 inPos = 0; + UInt32 inSize = 0; + UInt32 outPos = 0; + CXzUnpackerCPP xzu; + res = XzUnpacker_Create(&xzu.p, &g_Alloc); + if (res == SZ_OK) + { + xzu.InBuf = (Byte *)MyAlloc(kInBufSize); + xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize); + if (xzu.InBuf == 0 || xzu.OutBuf == 0) + res = SZ_ERROR_MEM; + } + if (res == SZ_OK) + for (;;) + { + if (inPos == inSize) + { + inPos = inSize = 0; + RINOK(_seqStream->Read(xzu.InBuf, kInBufSize, &inSize)); + } + + SizeT inLen = inSize - inPos; + SizeT outLen = kOutBufSize - outPos; + ECoderStatus status; + res = XzUnpacker_Code(&xzu.p, + xzu.OutBuf + outPos, &outLen, + xzu.InBuf + inPos, &inLen, + (inSize == 0 ? CODER_FINISH_END : CODER_FINISH_ANY), &status); + + // printf("\n_inPos = %6d inLen = %5d, outLen = %5d", inPos, inLen, outLen); + + inPos += (UInt32)inLen; + outPos += (UInt32)outLen; + lps->InSize += inLen; + lps->OutSize += outLen; + + bool finished = (((inLen == 0) && (outLen == 0)) || res != SZ_OK); + + if (outPos == kOutBufSize || finished) + { + if (realOutStream && outPos > 0) + { + RINOK(WriteStream(realOutStream, xzu.OutBuf, outPos)); + } + outPos = 0; + } + if (finished) + { + _packSize = lps->InSize; + _unpackSize = lps->OutSize; + _packSizeDefined = _unpackSizeDefined = true; + if (res == SZ_OK) + { + if (status == CODER_STATUS_NEEDS_MORE_INPUT) + { + if (XzUnpacker_IsStreamWasFinished(&xzu.p)) + _packSize -= xzu.p.padSize; + else + res = SZ_ERROR_DATA; + } + else + res = SZ_ERROR_DATA; + } + break; + } + RINOK(lps->SetCur()); + } + + Int32 opRes; + switch(res) + { + case SZ_OK: + opRes = NArchive::NExtract::NOperationResult::kOK; break; + case SZ_ERROR_UNSUPPORTED: + opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; break; + case SZ_ERROR_CRC: + opRes = NArchive::NExtract::NOperationResult::kCRCError; break; + case SZ_ERROR_DATA: + case SZ_ERROR_ARCHIVE: + case SZ_ERROR_NO_ARCHIVE: + opRes = NArchive::NExtract::NOperationResult::kDataError; break; + default: + return SResToHRESULT(res); + } + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(opRes)); + return S_OK; + COM_TRY_END +} + +#ifndef EXTRACT_ONLY + +STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) +{ + *timeType = NFileTimeType::kUnix; + return S_OK; +} + +STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, + IArchiveUpdateCallback *updateCallback) +{ + CSeqOutStreamWrap seqOutStream(outStream); + + if (numItems == 0) + { + SRes res = Xz_EncodeEmpty(&seqOutStream.p); + return SResToHRESULT(res); + } + + 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_EMPTY) + if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE) + 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; + RINOK(updateCallback->SetTotal(size)); + } + + CLzma2EncProps lzma2Props; + Lzma2EncProps_Init(&lzma2Props); + + lzma2Props.lzmaProps.level = _level; + + CMyComPtr<ISequentialInStream> fileInStream; + RINOK(updateCallback->GetStream(0, &fileInStream)); + + CSeqInStreamWrap seqInStream(fileInStream); + + for (int i = 0; i < _methods.Size(); i++) + { + COneMethodInfo &m = _methods[i]; + SetCompressionMethod2(m + #ifdef COMPRESS_MT + , _numThreads + #endif + ); + if (m.IsLzma()) + { + for (int j = 0; j < m.Props.Size(); j++) + { + const CProp &prop = m.Props[j]; + RINOK(NCompress::NLzma2::SetLzma2Prop(prop.Id, prop.Value, lzma2Props)); + } + } + } + + #ifdef COMPRESS_MT + lzma2Props.numTotalThreads = _numThreads; + #endif + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(updateCallback, true); + + CCompressProgressWrap progressWrap(progress); + SRes res = Xz_Encode(&seqOutStream.p, &seqInStream.p, &lzma2Props, False, &progressWrap.p); + if (res == SZ_OK) + return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); + return SResToHRESULT(res); + } + if (indexInArchive != 0) + return E_INVALIDARG; + if (_stream) + RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); + return NCompress::CopyStream(_stream, outStream, 0); +} + +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) +{ + COM_TRY_BEGIN + BeforeSetProperty(); + for (int i = 0; i < numProps; i++) + { + RINOK(SetProperty(names[i], values[i])); + } + return S_OK; + COM_TRY_END +} + +#endif + +static IInArchive *CreateArc() { return new NArchive::NXz::CHandler; } +#ifndef EXTRACT_ONLY +static IOutArchive *CreateArcOut() { return new NArchive::NXz::CHandler; } +#else +#define CreateArcOut 0 +#endif + +static CArcInfo g_ArcInfo = + { L"xz", L"xz txz", L"* .tar", 0xC, {0xFD, '7' , 'z', 'X', 'Z', '\0'}, 6, true, CreateArc, CreateArcOut }; + +REGISTER_ARC(xz) + +}} diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp index 212a8b4b..9157deeb 100755 --- a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp @@ -2,10 +2,7 @@ #include "StdAfx.h" -extern "C" -{ #include "../../../../C/7zCrc.h" -} #include "Windows/PropVariant.h" diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp index 25cbd886..547ecf92 100755 --- a/CPP/7zip/Archive/Zip/ZipHandler.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp @@ -3,16 +3,13 @@ #include "StdAfx.h" #include "Common/ComTry.h" -#include "Common/Defs.h" #include "Common/IntToString.h" -#include "Common/StringConvert.h" #include "Windows/PropVariant.h" #include "Windows/Time.h" #include "../../IPassword.h" -#include "../../Common/CreateCoder.h" #include "../../Common/FilterCoder.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamObjects.h" @@ -37,38 +34,34 @@ using namespace NWindows; namespace NArchive { namespace NZip { -// static const CMethodId kMethodId_Store = 0; static const CMethodId kMethodId_ZipBase = 0x040100; static const CMethodId kMethodId_BZip2 = 0x040202; -const wchar_t *kHostOS[] = +static const char *kHostOS[] = { - L"FAT", - L"AMIGA", - L"VMS", - L"Unix", - L"VM/CMS", - L"Atari", - L"HPFS", - L"Macintosh", - L"Z-System", - L"CP/M", - L"TOPS-20", - L"NTFS", - L"SMS/QDOS", - L"Acorn", - L"VFAT", - L"MVS", - L"BeOS", - L"Tandem", - L"OS/400", - L"OS/X" + "FAT", + "AMIGA", + "VMS", + "Unix", + "VM/CMS", + "Atari", + "HPFS", + "Macintosh", + "Z-System", + "CP/M", + "TOPS-20", + "NTFS", + "SMS/QDOS", + "Acorn", + "VFAT", + "MVS", + "BeOS", + "Tandem", + "OS/400", + "OS/X" }; - -static const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]); - -static const wchar_t *kUnknownOS = L"Unknown"; +static const char *kUnknownOS = "Unknown"; STATPROPSTG kProps[] = { @@ -93,50 +86,50 @@ STATPROPSTG kProps[] = // { NULL, kpidUnpackVer, VT_UI1}, }; -const wchar_t *kMethods[] = +const char *kMethods[] = { - L"Store", - L"Shrink", - L"Reduced1", - L"Reduced2", - L"Reduced2", - L"Reduced3", - L"Implode", - L"Tokenizing", - L"Deflate", - L"Deflate64", - L"PKImploding" + "Store", + "Shrink", + "Reduced1", + "Reduced2", + "Reduced2", + "Reduced3", + "Implode", + "Tokenizing", + "Deflate", + "Deflate64", + "PKImploding" }; const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]); -const wchar_t *kBZip2Method = L"BZip2"; -const wchar_t *kLZMAMethod = L"LZMA"; -const wchar_t *kJpegMethod = L"Jpeg"; -const wchar_t *kWavPackMethod = L"WavPack"; -const wchar_t *kPPMdMethod = L"PPMd"; -const wchar_t *kAESMethod = L"AES"; -const wchar_t *kZipCryptoMethod = L"ZipCrypto"; -const wchar_t *kStrongCryptoMethod = L"StrongCrypto"; +const char *kBZip2Method = "BZip2"; +const char *kLZMAMethod = "LZMA"; +const char *kJpegMethod = "Jpeg"; +const char *kWavPackMethod = "WavPack"; +const char *kPPMdMethod = "PPMd"; +const char *kAESMethod = "AES"; +const char *kZipCryptoMethod = "ZipCrypto"; +const char *kStrongCryptoMethod = "StrongCrypto"; struct CStrongCryptoPair { UInt16 Id; - const wchar_t *Name; + const char *Name; }; CStrongCryptoPair g_StrongCryptoPairs[] = { - { NStrongCryptoFlags::kDES, L"DES" }, - { NStrongCryptoFlags::kRC2old, L"RC2a" }, - { NStrongCryptoFlags::k3DES168, L"3DES-168" }, - { NStrongCryptoFlags::k3DES112, L"3DES-112" }, - { NStrongCryptoFlags::kAES128, L"pkAES-128" }, - { NStrongCryptoFlags::kAES192, L"pkAES-192" }, - { NStrongCryptoFlags::kAES256, L"pkAES-256" }, - { NStrongCryptoFlags::kRC2, L"RC2" }, - { NStrongCryptoFlags::kBlowfish, L"Blowfish" }, - { NStrongCryptoFlags::kTwofish, L"Twofish" }, - { NStrongCryptoFlags::kRC4, L"RC4" } + { NStrongCryptoFlags::kDES, "DES" }, + { NStrongCryptoFlags::kRC2old, "RC2a" }, + { NStrongCryptoFlags::k3DES168, "3DES-168" }, + { NStrongCryptoFlags::k3DES112, "3DES-112" }, + { NStrongCryptoFlags::kAES128, "pkAES-128" }, + { NStrongCryptoFlags::kAES192, "pkAES-192" }, + { NStrongCryptoFlags::kAES256, "pkAES-256" }, + { NStrongCryptoFlags::kRC2, "RC2" }, + { NStrongCryptoFlags::kBlowfish, "Blowfish" }, + { NStrongCryptoFlags::kTwofish, "Twofish" }, + { NStrongCryptoFlags::kRC4, "RC4" } }; STATPROPSTG kArcProps[] = @@ -202,9 +195,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidPackSize: prop = item.PackSize; break; case kpidTimeType: { - FILETIME utcFileTime; - if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kTagTime, utcFileTime)) + FILETIME ft; + UInt32 unixTime; + if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, ft)) prop = (UInt32)NFileTimeType::kWindows; + else if (item.CentralExtra.GetUnixTime(NFileHeader::NUnixTime::kMTime, unixTime)) + prop = (UInt32)NFileTimeType::kUnix; + else + prop = (UInt32)NFileTimeType::kDOS; break; } case kpidCTime: @@ -223,19 +221,21 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } case kpidMTime: { - FILETIME utcFileTime; - if (!item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, utcFileTime)) + FILETIME utc; + if (!item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, utc)) { - FILETIME localFileTime; - if (NTime::DosTimeToFileTime(item.Time, localFileTime)) + UInt32 unixTime; + if (item.CentralExtra.GetUnixTime(NFileHeader::NUnixTime::kMTime, unixTime)) + NTime::UnixTimeToFileTime(unixTime, utc); + else { - if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime)) - utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0; + FILETIME localFileTime; + if (!NTime::DosTimeToFileTime(item.Time, localFileTime) || + !LocalFileTimeToFileTime(&localFileTime, &utc)) + utc.dwHighDateTime = utc.dwLowDateTime = 0; } - else - utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0; } - prop = utcFileTime; + prop = utc; break; } case kpidAttrib: prop = item.GetWinAttributes(); break; @@ -245,7 +245,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidMethod: { UInt16 methodId = item.CompressionMethod; - UString method; + AString method; if (item.IsEncrypted()) { if (methodId == NFileHeader::NCompressionMethod::kWzAES) @@ -254,11 +254,11 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val CWzAesExtraField aesField; if (item.CentralExtra.GetWzAesField(aesField)) { - method += L"-"; - wchar_t s[32]; + method += '-'; + char s[32]; ConvertUInt64ToString((aesField.Strength + 1) * 64 , s); method += s; - method += L" "; + method += ' '; methodId = aesField.Method; } } @@ -286,7 +286,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } else method += kZipCryptoMethod; - method += L" "; + method += ' '; } } if (methodId < kNumMethods) @@ -296,7 +296,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case NFileHeader::NCompressionMethod::kLZMA: method += kLZMAMethod; if (item.IsLzmaEOS()) - method += L":EOS"; + method += ":EOS"; break; case NFileHeader::NCompressionMethod::kBZip2: method += kBZip2Method; break; case NFileHeader::NCompressionMethod::kJpeg: method += kJpegMethod; break; @@ -304,7 +304,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case NFileHeader::NCompressionMethod::kPPMd: method += kPPMdMethod; break; default: { - wchar_t s[32]; + char s[32]; ConvertUInt64ToString(methodId, s); method += s; } @@ -313,7 +313,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val break; } case kpidHostOS: - prop = (item.MadeByVersion.HostOS < kNumHostOSes) ? + prop = (item.MadeByVersion.HostOS < sizeof(kHostOS) / sizeof(kHostOS[0])) ? (kHostOS[item.MadeByVersion.HostOS]) : kUnknownOS; break; } diff --git a/CPP/7zip/Archive/Zip/ZipHeader.h b/CPP/7zip/Archive/Zip/ZipHeader.h index e974079d..4839f554 100755 --- a/CPP/7zip/Archive/Zip/ZipHeader.h +++ b/CPP/7zip/Archive/Zip/ZipHeader.h @@ -93,6 +93,7 @@ namespace NFileHeader kZip64 = 0x01, kNTFS = 0x0A, kStrongEncrypt = 0x17, + kUnixTime = 0x5455, kWzAES = 0x9901 }; } @@ -103,8 +104,18 @@ namespace NFileHeader enum { kMTime = 0, - kATime = 1, - kCTime = 2 + kATime, + kCTime + }; + } + + namespace NUnixTime + { + enum + { + kMTime = 0, + kATime, + kCTime }; } diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp index 5fb53ef2..e396fe5b 100755 --- a/CPP/7zip/Archive/Zip/ZipIn.cpp +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp @@ -2,17 +2,14 @@ #include "StdAfx.h" -#include "ZipIn.h" -#include "Windows/Defs.h" -#include "Common/StringConvert.h" +#include "../../../../C/CpuArch.h" + #include "Common/DynamicBuffer.h" + #include "../../Common/LimitedStreams.h" #include "../../Common/StreamUtils.h" -extern "C" -{ - #include "../../../../C/CpuArch.h" -} +#include "ZipIn.h" #define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) @@ -21,10 +18,9 @@ extern "C" namespace NArchive { namespace NZip { -// static const char kEndOfString = '\0'; - HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { + _inBufMode = false; Close(); RINOK(stream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition)); m_Position = m_StreamStartPosition; @@ -36,6 +32,7 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) void CInArchive::Close() { + _inBuffer.ReleaseStream(); m_Stream.Release(); } @@ -117,13 +114,26 @@ HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchHea HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize) { size_t realProcessedSize = size; - HRESULT result = ReadStream(m_Stream, data, &realProcessedSize); + HRESULT result = S_OK; + if (_inBufMode) + { + try { realProcessedSize = _inBuffer.ReadBytes((Byte *)data, size); } + catch (const CInBufferException &e) { return e.ErrorCode; } + } + else + result = ReadStream(m_Stream, data, &realProcessedSize); if (processedSize != NULL) *processedSize = (UInt32)realProcessedSize; m_Position += realProcessedSize; return result; } +void CInArchive::Skip(UInt64 num) +{ + for (UInt64 i = 0; i < num; i++) + ReadByte(); +} + void CInArchive::IncreaseRealPosition(UInt64 addValue) { if (m_Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position) != S_OK) @@ -160,51 +170,42 @@ Byte CInArchive::ReadByte() UInt16 CInArchive::ReadUInt16() { - UInt16 value = 0; - for (int i = 0; i < 2; i++) - value |= (((UInt16)ReadByte()) << (8 * i)); - return value; + Byte buf[2]; + SafeReadBytes(buf, 2); + return Get16(buf); } UInt32 CInArchive::ReadUInt32() { - UInt32 value = 0; - for (int i = 0; i < 4; i++) - value |= (((UInt32)ReadByte()) << (8 * i)); - return value; + Byte buf[4]; + SafeReadBytes(buf, 4); + return Get32(buf); } UInt64 CInArchive::ReadUInt64() { - UInt64 value = 0; - for (int i = 0; i < 8; i++) - value |= (((UInt64)ReadByte()) << (8 * i)); - return value; + Byte buf[8]; + SafeReadBytes(buf, 8); + return Get64(buf); } bool CInArchive::ReadUInt32(UInt32 &value) { - value = 0; - for (int i = 0; i < 4; i++) - { - Byte b; - if (!ReadBytesAndTestSize(&b, 1)) - return false; - value |= (UInt32(b) << (8 * i)); - } + Byte buf[4]; + if (!ReadBytesAndTestSize(buf, 4)) + return false; + value = Get32(buf); return true; } - -AString CInArchive::ReadFileName(UInt32 nameSize) +void CInArchive::ReadFileName(UInt32 nameSize, AString &dest) { if (nameSize == 0) - return AString(); - char *p = m_NameBuffer.GetBuffer(nameSize); + dest.Empty(); + char *p = dest.GetBuffer((int)nameSize); SafeReadBytes(p, nameSize); p[nameSize] = 0; - m_NameBuffer.ReleaseBuffer(); - return m_NameBuffer; + dest.ReleaseBuffer(); } void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const @@ -212,38 +213,6 @@ void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const archiveInfo = m_ArchiveInfo; } -/* -void CInArchive::ThrowIncorrectArchiveException() -{ - throw CInArchiveException(CInArchiveException::kIncorrectArchive); -} -*/ - -static UInt32 GetUInt32(const Byte *data) -{ - return - ((UInt32)(Byte)data[0]) | - (((UInt32)(Byte)data[1]) << 8) | - (((UInt32)(Byte)data[2]) << 16) | - (((UInt32)(Byte)data[3]) << 24); -} - -/* -static UInt16 GetUInt16(const Byte *data) -{ - return - ((UInt16)(Byte)data[0]) | - (((UInt16)(Byte)data[1]) << 8); -} -*/ - -static UInt64 GetUInt64(const Byte *data) -{ - return GetUInt32(data) | ((UInt64)GetUInt32(data + 4) << 32); -} - - - void CInArchive::ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock, UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber) { @@ -301,22 +270,26 @@ void CInArchive::ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock, } remain -= dataSize; } - IncreaseRealPosition(remain); + Skip(remain); } HRESULT CInArchive::ReadLocalItem(CItemEx &item) { - item.ExtractVersion.Version = ReadByte(); - item.ExtractVersion.HostOS = ReadByte(); - item.Flags = ReadUInt16(); - item.CompressionMethod = ReadUInt16(); - item.Time = ReadUInt32(); - item.FileCRC = ReadUInt32(); - item.PackSize = ReadUInt32(); - item.UnPackSize = ReadUInt32(); - UInt32 fileNameSize = ReadUInt16(); - item.LocalExtraSize = ReadUInt16(); - item.Name = ReadFileName(fileNameSize); + const int kBufSize = 26; + Byte p[kBufSize]; + SafeReadBytes(p, kBufSize); + + item.ExtractVersion.Version = p[0]; + item.ExtractVersion.HostOS = p[1]; + item.Flags = Get16(p + 2); + item.CompressionMethod = Get16(p + 4); + item.Time = Get32(p + 6); + item.FileCRC = Get32(p + 10); + item.PackSize = Get32(p + 14); + item.UnPackSize = Get32(p + 18); + UInt32 fileNameSize = Get16(p + 22); + item.LocalExtraSize = Get16(p + 24); + ReadFileName(fileNameSize, item.Name); item.FileHeaderWithNameSize = 4 + NFileHeader::kLocalBlockSize + fileNameSize; if (item.LocalExtraSize > 0) { @@ -400,16 +373,16 @@ HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item) { // descriptorSignature field is Info-ZIP's extension // to Zip specification. - UInt32 descriptorSignature = GetUInt32(buffer + i); + UInt32 descriptorSignature = Get32(buffer + i); // !!!! It must be fixed for Zip64 archives - UInt32 descriptorPackSize = GetUInt32(buffer + i + 8); + UInt32 descriptorPackSize = Get32(buffer + i + 8); if (descriptorSignature== NSignature::kDataDescriptor && descriptorPackSize == packedSize + i) { descriptorWasFound = true; - item.FileCRC = GetUInt32(buffer + i + 4); + item.FileCRC = Get32(buffer + i + 4); item.PackSize = descriptorPackSize; - item.UnPackSize = GetUInt32(buffer + i + 12); + item.UnPackSize = Get32(buffer + i + 12); IncreaseRealPosition(Int64(Int32(0 - (numBytesInBuffer - i - NFileHeader::kDataDescriptorSize)))); break; } @@ -487,7 +460,7 @@ HRESULT CInArchive::ReadCdItem(CItemEx &item) item.InternalAttributes = Get16(p + 32); item.ExternalAttributes = Get32(p + 34); item.LocalHeaderPosition = Get32(p + 38); - item.Name = ReadFileName(headerNameSize); + ReadFileName(headerNameSize, item.Name); if (headerExtraSize > 0) { @@ -515,11 +488,11 @@ HRESULT CInArchive::TryEcd64(UInt64 offset, CCdInfo &cdInfo) Byte buf[kEcd64Size]; if (!ReadBytesAndTestSize(buf, kEcd64Size)) return S_FALSE; - if (GetUInt32(buf) != NSignature::kZip64EndOfCentralDir) + if (Get32(buf) != NSignature::kZip64EndOfCentralDir) return S_FALSE; - // cdInfo.NumEntries = GetUInt64(buf + 24); - cdInfo.Size = GetUInt64(buf + 40); - cdInfo.Offset = GetUInt64(buf + 48); + // cdInfo.NumEntries = Get64(buf + 24); + cdInfo.Size = Get64(buf + 40); + cdInfo.Offset = Get64(buf + 48); return S_OK; } @@ -540,14 +513,14 @@ HRESULT CInArchive::FindCd(CCdInfo &cdInfo) return S_FALSE; for (int i = (int)(bufSize - kEcdSize); i >= 0; i--) { - if (GetUInt32(buf + i) == NSignature::kEndOfCentralDir) + if (Get32(buf + i) == NSignature::kEndOfCentralDir) { if (i >= kZip64EcdLocatorSize) { const Byte *locator = buf + i - kZip64EcdLocatorSize; - if (GetUInt32(locator) == NSignature::kZip64EndOfCentralDirLocator) + if (Get32(locator) == NSignature::kZip64EndOfCentralDirLocator) { - UInt64 ecd64Offset = GetUInt64(locator + 8); + UInt64 ecd64Offset = Get64(locator + 8); if (TryEcd64(ecd64Offset, cdInfo) == S_OK) return S_OK; if (TryEcd64(m_ArchiveInfo.StartPosition + ecd64Offset, cdInfo) == S_OK) @@ -557,11 +530,11 @@ HRESULT CInArchive::FindCd(CCdInfo &cdInfo) } } } - if (GetUInt32(buf + i + 4) == 0) + if (Get32(buf + i + 4) == 0) { // cdInfo.NumEntries = GetUInt16(buf + i + 10); - cdInfo.Size = GetUInt32(buf + i + 12); - cdInfo.Offset = GetUInt32(buf + i + 16); + cdInfo.Size = Get32(buf + i + 12); + cdInfo.Offset = Get32(buf + i + 16); UInt64 curPos = endPosition - bufSize + i; UInt64 cdEnd = cdInfo.Size + cdInfo.Offset; if (curPos > cdEnd) @@ -579,6 +552,13 @@ HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, UInt64 cdOffset, UI RINOK(m_Stream->Seek(cdOffset, STREAM_SEEK_SET, &m_Position)); if (m_Position != cdOffset) return S_FALSE; + + if (!_inBuffer.Create(1 << 15)) + return E_OUTOFMEMORY; + _inBuffer.SetStream(m_Stream); + _inBuffer.Init(); + _inBufMode = true; + while(m_Position - cdOffset < cdSize) { if (ReadUInt32() != NSignature::kCentralFileHeader) @@ -765,6 +745,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr if (res == S_FALSE) { + _inBufMode = false; m_ArchiveInfo.Base = 0; RINOK(m_Stream->Seek(m_ArchiveInfo.StartPosition, STREAM_SEEK_SET, &m_Position)); if (m_Position != m_ArchiveInfo.StartPosition) @@ -789,7 +770,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr SafeReadBytes(buf, kBufSize); ecd64.Parse(buf); - IncreaseRealPosition(recordSize - kZip64EcdSize); + Skip(recordSize - kZip64EcdSize); if (!ReadUInt32(m_Signature)) return S_FALSE; if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0) @@ -838,6 +819,8 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr (!items.IsEmpty()))) return S_FALSE; + _inBufMode = false; + _inBuffer.Free(); return S_OK; } diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h index 750095d6..5f4fe143 100755 --- a/CPP/7zip/Archive/Zip/ZipIn.h +++ b/CPP/7zip/Archive/Zip/ZipIn.h @@ -4,8 +4,11 @@ #define __ZIP_IN_H #include "Common/MyCom.h" + #include "../../IStream.h" +#include "../../Common/InBuffer.h" + #include "ZipHeader.h" #include "ZipItemEx.h" @@ -65,13 +68,14 @@ class CInArchive UInt32 m_Signature; UInt64 m_StreamStartPosition; UInt64 m_Position; - AString m_NameBuffer; + + bool _inBufMode; + CInBuffer _inBuffer; HRESULT Seek(UInt64 offset); HRESULT FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit); - bool ReadUInt32(UInt32 &signature); - AString ReadFileName(UInt32 nameSize); + void ReadFileName(UInt32 nameSize, AString &dest); HRESULT ReadBytes(void *data, UInt32 size, UInt32 *processedSize); bool ReadBytesAndTestSize(void *data, UInt32 size); @@ -81,7 +85,9 @@ class CInArchive UInt16 ReadUInt16(); UInt32 ReadUInt32(); UInt64 ReadUInt64(); + bool ReadUInt32(UInt32 &signature); + void Skip(UInt64 num); void IncreaseRealPosition(UInt64 addValue); void ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock, diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp index 03472d85..139b0129 100755 --- a/CPP/7zip/Archive/Zip/ZipItem.cpp +++ b/CPP/7zip/Archive/Zip/ZipItem.cpp @@ -51,6 +51,31 @@ bool CExtraSubBlock::ExtractNtfsTime(int index, FILETIME &ft) const return false; } +bool CExtraSubBlock::ExtractUnixTime(int index, UInt32 &res) const +{ + res = 0; + UInt32 size = (UInt32)Data.GetCapacity(); + if (ID != NFileHeader::NExtraID::kUnixTime || size < 5) + return false; + const Byte *p = (const Byte *)Data; + Byte flags = *p++; + size--; + for (int i = 0; i < 3; i++) + if ((flags & (1 << i)) != 0) + { + if (size < 4) + return false; + if (index == i) + { + res = GetUi32(p); + return true; + } + p += 4; + size -= 4; + } + return false; +} + bool CLocalItem::IsDir() const { return NItemName::HasTailSlash(Name, GetCodePage()); diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h index c0f780f8..31f2de73 100755 --- a/CPP/7zip/Archive/Zip/ZipItem.h +++ b/CPP/7zip/Archive/Zip/ZipItem.h @@ -28,6 +28,7 @@ struct CExtraSubBlock UInt16 ID; CByteBuffer Data; bool ExtractNtfsTime(int index, FILETIME &ft) const; + bool ExtractUnixTime(int index, UInt32 &res) const; }; struct CWzAesExtraField @@ -151,6 +152,17 @@ struct CExtraBlock return false; } + bool GetUnixTime(int index, UInt32 &res) const + { + for (int i = 0; i < SubBlocks.Size(); i++) + { + const CExtraSubBlock &sb = SubBlocks[i]; + if (sb.ID == NFileHeader::NExtraID::kUnixTime) + return sb.ExtractUnixTime(index, res); + } + return false; + } + /* bool HasStrongCryptoField() const { diff --git a/CPP/7zip/Archive/Zip/ZipRegister.cpp b/CPP/7zip/Archive/Zip/ZipRegister.cpp index 12db3e44..2fd36950 100755 --- a/CPP/7zip/Archive/Zip/ZipRegister.cpp +++ b/CPP/7zip/Archive/Zip/ZipRegister.cpp @@ -13,6 +13,6 @@ static IOutArchive *CreateArcOut() { return new NArchive::NZip::CHandler; } #endif static CArcInfo g_ArcInfo = - { L"Zip", L"zip jar xpi", 0, 1, { 0x50, 0x4B, 0x03, 0x04 }, 4, false, CreateArc, CreateArcOut }; + { L"Zip", L"zip jar xpi odt ods docx xlsx", 0, 1, { 0x50, 0x4B, 0x03, 0x04 }, 4, false, CreateArc, CreateArcOut }; REGISTER_ARC(Zip) diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp index 5c7e64db..c76ee488 100755 --- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp +++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp @@ -47,8 +47,7 @@ static HRESULT CopyBlockToArchive(ISequentialInStream *inStream, { CMyComPtr<ISequentialOutStream> outStream; outArchive.CreateStreamForCopying(&outStream); - CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder; - return copyCoder->Code(inStream, outStream, NULL, NULL, progress); + return NCompress::CopyStream(inStream, outStream, progress); } static HRESULT WriteRange(IInStream *inStream, COutArchive &outArchive, diff --git a/CPP/7zip/Bundles/Alone/Alone.dsp b/CPP/7zip/Bundles/Alone/Alone.dsp index fc4e97f0..7c557105 100755 --- a/CPP/7zip/Bundles/Alone/Alone.dsp +++ b/CPP/7zip/Bundles/Alone/Alone.dsp @@ -44,7 +44,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "COMPRESS_BZIP2_MT" /D "BREAK_HANDLER" /D "_7ZIP_LARGE_PAGES" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "COMPRESS_BZIP2_MT" /D "BREAK_HANDLER" /D "_7ZIP_LARGE_PAGES" /D "BENCH_MT" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe @@ -69,7 +69,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "COMPRESS_BZIP2_MT" /D "BREAK_HANDLER" /D "_7ZIP_LARGE_PAGES" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "COMPRESS_BZIP2_MT" /D "BREAK_HANDLER" /D "_7ZIP_LARGE_PAGES" /D "BENCH_MT" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe @@ -94,7 +94,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c -# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "COMPRESS_BZIP2_MT" /D "BREAK_HANDLER" /D "_7ZIP_LARGE_PAGES" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "COMPRESS_BZIP2_MT" /D "BREAK_HANDLER" /D "_7ZIP_LARGE_PAGES" /D "BENCH_MT" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe @@ -121,7 +121,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c -# ADD CPP /nologo /Gz /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "COMPRESS_BZIP2_MT" /D "BREAK_HANDLER" /D "_7ZIP_LARGE_PAGES" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "COMPRESS_BZIP2_MT" /D "BREAK_HANDLER" /D "_7ZIP_LARGE_PAGES" /D "BENCH_MT" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe @@ -321,14 +321,6 @@ SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File -SOURCE=..\..\..\Common\MyWindows.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\..\Common\MyWindows.h -# End Source File -# Begin Source File - SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File @@ -337,14 +329,6 @@ SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File -SOURCE=..\..\..\Common\Random.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\..\Common\Random.h -# End Source File -# Begin Source File - SOURCE=..\..\..\Common\StdInStream.cpp # End Source File # Begin Source File @@ -533,6 +517,14 @@ SOURCE=..\..\Archive\Common\CrossThreadProgress.h # End Source File # Begin Source File +SOURCE=..\..\Common\CWrappers.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CWrappers.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\FilePathAutoRename.cpp # End Source File # Begin Source File @@ -868,7 +860,23 @@ SOURCE=..\..\Compress\ImplodeHuffmanDecoder.h # PROP Default_Filter "" # Begin Source File -SOURCE=..\..\Compress\Lzma.h +SOURCE=..\..\Compress\Lzma2Decoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Decoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Encoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Encoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Register.cpp # End Source File # Begin Source File @@ -1185,7 +1193,7 @@ SOURCE=..\..\Compress\ByteSwap.h # End Source File # Begin Source File -SOURCE=..\..\Compress\ByteSwapRegister.cpp +SOURCE=..\..\Compress\DeltaFilter.cpp # End Source File # Begin Source File @@ -1315,94 +1323,6 @@ SOURCE=..\..\Archive\7z\7zUpdate.cpp SOURCE=..\..\Archive\7z\7zUpdate.h # End Source File # End Group -# Begin Group "bz2" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\..\Archive\BZip2\bz2Register.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\BZip2\BZip2Handler.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\BZip2\BZip2Handler.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\BZip2\BZip2HandlerOut.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\BZip2\BZip2Item.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\BZip2\BZip2Update.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\BZip2\BZip2Update.h -# End Source File -# End Group -# Begin Group "gz" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipHandler.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipHandler.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipHandlerOut.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipHeader.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipHeader.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipIn.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipIn.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipItem.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipOut.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipOut.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipRegister.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipUpdate.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipUpdate.h -# End Source File -# End Group # Begin Group "tar" # PROP Default_Filter "" @@ -1623,22 +1543,6 @@ SOURCE=..\..\Archive\Common\ParseProperties.cpp SOURCE=..\..\Archive\Common\ParseProperties.h # End Source File # End Group -# Begin Group "split" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\..\Archive\Split\SplitHandler.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Split\SplitHandler.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Split\SplitRegister.cpp -# End Source File -# End Group # Begin Group "cab" # PROP Default_Filter "" @@ -1683,44 +1587,28 @@ SOURCE=..\..\Archive\Cab\CabItem.h SOURCE=..\..\Archive\Cab\CabRegister.cpp # End Source File # End Group -# Begin Group "Lzma - Ar" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\..\Archive\Lzma\LzmaArcRegister.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Lzma\LzmaFiltersDecode.cpp -# End Source File # Begin Source File -SOURCE=..\..\Archive\Lzma\LzmaFiltersDecode.h +SOURCE=..\..\Archive\Bz2Handler.cpp # End Source File # Begin Source File -SOURCE=..\..\Archive\Lzma\LzmaHandler.cpp +SOURCE=..\..\Archive\GzHandler.cpp # End Source File # Begin Source File -SOURCE=..\..\Archive\Lzma\LzmaHandler.h +SOURCE=..\..\Archive\LzmaHandler.cpp # End Source File # Begin Source File -SOURCE=..\..\Archive\Lzma\LzmaIn.cpp +SOURCE=..\..\Archive\SplitHandler.cpp # End Source File # Begin Source File -SOURCE=..\..\Archive\Lzma\LzmaIn.h +SOURCE=..\..\Archive\XzHandler.cpp # End Source File # Begin Source File -SOURCE=..\..\Archive\Lzma\LzmaItem.h -# End Source File -# End Group -# Begin Source File - SOURCE=..\..\Archive\ZHandler.cpp # End Source File # End Group @@ -2082,6 +1970,142 @@ SOURCE=..\..\PropID.h # Begin Group "C" # PROP Default_Filter "" +# Begin Group "Xz" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\..\C\Xz.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Xz.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzCrc64.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzCrc64.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzDec.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzEnc.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzEnc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzIn.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# End Group # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c @@ -2112,6 +2136,30 @@ SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\7zStream.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Aes.c !IF "$(CFG)" == "Alone - Win32 Release" @@ -2285,6 +2333,34 @@ SOURCE=..\..\..\..\C\CpuArch.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Delta.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Delta.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\HuffEnc.c !IF "$(CFG)" == "Alone - Win32 Release" @@ -2377,6 +2453,62 @@ SOURCE=..\..\..\..\C\LzHash.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Lzma2Dec.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Dec.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Enc.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Enc.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\LzmaDec.c !IF "$(CFG)" == "Alone - Win32 Release" @@ -2433,6 +2565,34 @@ SOURCE=..\..\..\..\C\LzmaEnc.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\MtCoder.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\MtCoder.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\RotateDefs.h # End Source File # Begin Source File diff --git a/CPP/7zip/Bundles/Alone/makefile b/CPP/7zip/Bundles/Alone/makefile index 2b948601..5a8a359b 100755 --- a/CPP/7zip/Bundles/Alone/makefile +++ b/CPP/7zip/Bundles/Alone/makefile @@ -8,6 +8,7 @@ CFLAGS = $(CFLAGS) -I ../../../ \ -D_7ZIP_LARGE_PAGES \ -DBREAK_HANDLER \ -DBENCH_MT \ + -DSUPPORT_DEVICE_FILE \ CONSOLE_OBJS = \ $O\ConsoleClose.obj \ @@ -51,6 +52,7 @@ WIN_OBJS = \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ + $O\CWrappers.obj \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\FilterCoder.obj \ @@ -93,6 +95,11 @@ UI_COMMON_OBJS = \ $O\WorkDir.obj \ AR_OBJS = \ + $O\Bz2Handler.obj \ + $O\GzHandler.obj \ + $O\LzmaHandler.obj \ + $O\SplitHandler.obj \ + $O\XzHandler.obj \ $O\ZHandler.obj \ AR_COMMON_OBJS = \ @@ -126,12 +133,6 @@ AR_COMMON_OBJS = \ $O\7zUpdate.obj \ $O\7zRegister.obj \ -BZ2_OBJS = \ - $O\BZip2Handler.obj \ - $O\BZip2HandlerOut.obj \ - $O\BZip2Update.obj \ - $O\bz2Register.obj \ - CAB_OBJS = \ $O\CabBlockInStream.obj \ $O\CabHandler.obj \ @@ -139,26 +140,6 @@ CAB_OBJS = \ $O\CabIn.obj \ $O\CabRegister.obj \ -GZ_OBJS = \ - $O\GZipHandler.obj \ - $O\GZipHandlerOut.obj \ - $O\GZipHeader.obj \ - $O\GZipIn.obj \ - $O\GZipOut.obj \ - $O\GZipUpdate.obj \ - $O\GZipRegister.obj \ - -LZM_OBJS = \ - $O\LzmaArcRegister.obj \ - $O\LzmaFiltersDecode.obj \ - $O\LzmaHandler.obj \ - $O\LzmaIn.obj \ - -SPLIT_OBJS = \ - $O\SplitHandler.obj \ - $O\SplitHandlerOut.obj \ - $O\SplitRegister.obj \ - TAR_OBJS = \ $O\TarHandler.obj \ $O\TarHandlerOut.obj \ @@ -190,7 +171,6 @@ COMPRESS_OBJS = \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ - $O\ByteSwapRegister.obj \ $O\BZip2CRC.obj \ $O\BZip2Decoder.obj \ $O\BZip2Encoder.obj \ @@ -201,8 +181,12 @@ COMPRESS_OBJS = \ $O\DeflateDecoder.obj \ $O\DeflateEncoder.obj \ $O\DeflateRegister.obj \ + $O\DeltaFilter.obj \ $O\ImplodeDecoder.obj \ $O\ImplodeHuffmanDecoder.obj \ + $O\Lzma2Decoder.obj \ + $O\Lzma2Encoder.obj \ + $O\Lzma2Register.obj \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ $O\LzmaRegister.obj \ @@ -233,20 +217,30 @@ CRYPTO_OBJS = \ $O\ZipStrong.obj \ C_OBJS = \ + $O\7zStream.obj \ + $O\Aes.obj \ $O\Alloc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\BwtSort.obj \ + $O\Delta.obj \ $O\HuffEnc.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ + $O\Lzma2Dec.obj \ + $O\Lzma2Enc.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ + $O\MtCoder.obj \ + $O\Sha256.obj \ $O\Sort.obj \ $O\Threads.obj \ - $O\Aes.obj \ - $O\Sha256.obj \ + $O\Xz.obj \ + $O\XzCrc64.obj \ + $O\XzDec.obj \ + $O\XzEnc.obj \ + $O\XzIn.obj \ !include "../../Crc2.mak" @@ -261,11 +255,7 @@ OBJS = \ $(AR_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ - $(BZ2_OBJS) \ $(CAB_OBJS) \ - $(GZ_OBJS) \ - $(LZM_OBJS) \ - $(SPLIT_OBJS) \ $(TAR_OBJS) \ $(ZIP_OBJS) \ $(COMPRESS_OBJS) \ @@ -296,16 +286,8 @@ $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) -$(BZ2_OBJS): ../../Archive/BZip2/$(*B).cpp - $(COMPL) $(CAB_OBJS): ../../Archive/Cab/$(*B).cpp $(COMPL) -$(GZ_OBJS): ../../Archive/GZip/$(*B).cpp - $(COMPL) -$(LZM_OBJS): ../../Archive/Lzma/$(*B).cpp - $(COMPL) -$(SPLIT_OBJS): ../../Archive/Split/$(*B).cpp - $(COMPL) $(TAR_OBJS): ../../Archive/Tar/$(*B).cpp $(COMPL) $(ZIP_OBJS): ../../Archive/Zip/$(*B).cpp diff --git a/CPP/7zip/Bundles/Alone7z/makefile b/CPP/7zip/Bundles/Alone7z/makefile index d255af78..c2bf482c 100755 --- a/CPP/7zip/Bundles/Alone7z/makefile +++ b/CPP/7zip/Bundles/Alone7z/makefile @@ -1,4 +1,4 @@ -PROG = 7za.exe +PROG = 7zr.exe LIBS = $(LIBS) user32.lib oleaut32.lib Advapi32.lib CFLAGS = $(CFLAGS) -I ../../../ \ @@ -53,6 +53,7 @@ WIN_OBJS = \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ + $O\CWrappers.obj \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\InBuffer.obj \ @@ -91,6 +92,11 @@ UI_COMMON_OBJS = \ $O\UpdateProduce.obj \ $O\WorkDir.obj \ +AR_OBJS = \ + $O\LzmaHandler.obj \ + $O\SplitHandler.obj \ + $O\XzHandler.obj \ + AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ @@ -121,17 +127,6 @@ AR_COMMON_OBJS = \ $O\7zSpecStream.obj \ $O\7zUpdate.obj \ -LZM_OBJS = \ - $O\LzmaArcRegister.obj \ - $O\LzmaFiltersDecode.obj \ - $O\LzmaHandler.obj \ - $O\LzmaIn.obj \ - -SPLIT_OBJS = \ - $O\SplitHandler.obj \ - $O\SplitHandlerOut.obj \ - $O\SplitRegister.obj \ - COMPRESS_OBJS = \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ @@ -141,9 +136,12 @@ COMPRESS_OBJS = \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ - $O\ByteSwapRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ + $O\DeltaFilter.obj \ + $O\Lzma2Decoder.obj \ + $O\Lzma2Encoder.obj \ + $O\Lzma2Register.obj \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ $O\LzmaRegister.obj \ @@ -153,16 +151,28 @@ LZMA_BENCH_OBJS = \ $O\LzmaBenchCon.obj \ C_OBJS = \ - $O\7zCrc.obj \ + $O\7zStream.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\Alloc.obj \ - $O\LzmaDec.obj \ - $O\LzmaEnc.obj \ + $O\Delta.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ + $O\Lzma2Dec.obj \ + $O\Lzma2Enc.obj \ + $O\LzmaDec.obj \ + $O\LzmaEnc.obj \ + $O\MtCoder.obj \ + $O\Sha256.obj \ $O\Threads.obj \ + $O\Xz.obj \ + $O\XzCrc64.obj \ + $O\XzDec.obj \ + $O\XzEnc.obj \ + $O\XzIn.obj \ + +!include "../../Crc2.mak" OBJS = \ $O\StdAfx.obj \ @@ -171,10 +181,9 @@ OBJS = \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(UI_COMMON_OBJS) \ + $(AR_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ - $(LZM_OBJS) \ - $(SPLIT_OBJS) \ $(COMPRESS_OBJS) \ $(LZMA_BENCH_OBJS) \ $(C_OBJS) \ @@ -195,18 +204,17 @@ $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp $(COMPL) +$(AR_OBJS): ../../Archive/$(*B).cpp + $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) -$(LZM_OBJS): ../../Archive/Lzma/$(*B).cpp - $(COMPL) -$(SPLIT_OBJS): ../../Archive/Split/$(*B).cpp - $(COMPL) $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL_O2) $(LZMA_BENCH_OBJS): ../../Compress/LZMA_Alone/$(*B).cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) +!include "../../Crc.mak" diff --git a/CPP/7zip/Bundles/Format7z/makefile b/CPP/7zip/Bundles/Format7z/makefile index 65be7a0c..e26aeadd 100755 --- a/CPP/7zip/Bundles/Format7z/makefile +++ b/CPP/7zip/Bundles/Format7z/makefile @@ -28,6 +28,7 @@ WIN_OBJS = \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ + $O\CWrappers.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ @@ -86,7 +87,6 @@ COMPRESS_OBJS = \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ - $O\ByteSwapRegister.obj \ $O\BZip2Crc.obj \ $O\BZip2Decoder.obj \ $O\BZip2Encoder.obj \ @@ -96,6 +96,10 @@ COMPRESS_OBJS = \ $O\DeflateDecoder.obj \ $O\DeflateEncoder.obj \ $O\DeflateRegister.obj \ + $O\DeltaFilter.obj \ + $O\Lzma2Decoder.obj \ + $O\Lzma2Encoder.obj \ + $O\Lzma2Register.obj \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ $O\LzmaRegister.obj \ @@ -112,20 +116,24 @@ CRYPTO_OBJS = \ $O\Sha1.obj \ C_OBJS = \ + $O\Aes.obj \ $O\Alloc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\BwtSort.obj \ + $O\Delta.obj \ $O\HuffEnc.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ + $O\Lzma2Dec.obj \ + $O\Lzma2Enc.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ + $O\MtCoder.obj \ + $O\Sha256.obj \ $O\Sort.obj \ $O\Threads.obj \ - $O\Aes.obj \ - $O\Sha256.obj \ !include "../../Crc2.mak" diff --git a/CPP/7zip/Bundles/Format7zExtract/makefile b/CPP/7zip/Bundles/Format7zExtract/makefile index c8ef3df8..c2dd4f7f 100755 --- a/CPP/7zip/Bundles/Format7zExtract/makefile +++ b/CPP/7zip/Bundles/Format7zExtract/makefile @@ -26,6 +26,7 @@ WIN_OBJS = \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ + $O\CWrappers.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ @@ -74,7 +75,6 @@ COMPRESS_OBJS = \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ - $O\ByteSwapRegister.obj \ $O\BZip2Crc.obj \ $O\BZip2Decoder.obj \ $O\BZip2Register.obj \ @@ -82,6 +82,9 @@ COMPRESS_OBJS = \ $O\CopyRegister.obj \ $O\DeflateDecoder.obj \ $O\DeflateRegister.obj \ + $O\DeltaFilter.obj \ + $O\Lzma2Decoder.obj \ + $O\Lzma2Register.obj \ $O\LzmaDecoder.obj \ $O\LzmaRegister.obj \ $O\LzOutWindow.obj \ @@ -94,14 +97,16 @@ CRYPTO_OBJS = \ $O\MyAes.obj \ C_OBJS = \ + $O\Aes.obj \ $O\Alloc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ + $O\Delta.obj \ + $O\Lzma2Dec.obj \ $O\LzmaDec.obj \ - $O\Threads.obj \ - $O\Aes.obj \ $O\Sha256.obj \ + $O\Threads.obj \ !include "../../Crc2.mak" diff --git a/CPP/7zip/Bundles/Format7zExtractR/makefile b/CPP/7zip/Bundles/Format7zExtractR/makefile index f544083b..9f06ca5a 100755 --- a/CPP/7zip/Bundles/Format7zExtractR/makefile +++ b/CPP/7zip/Bundles/Format7zExtractR/makefile @@ -26,6 +26,7 @@ WIN_OBJS = \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ + $O\CWrappers.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ @@ -76,9 +77,11 @@ COMPRESS_OBJS = \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ - $O\ByteSwapRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ + $O\DeltaFilter.obj \ + $O\Lzma2Decoder.obj \ + $O\Lzma2Register.obj \ $O\LzmaDecoder.obj \ $O\LzmaRegister.obj \ @@ -88,6 +91,8 @@ C_OBJS = \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ + $O\Delta.obj \ + $O\Lzma2Dec.obj \ $O\LzmaDec.obj \ $O\Threads.obj \ diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsp b/CPP/7zip/Bundles/Format7zF/Format7z.dsp index c80e4f64..33caaf95 100755 --- a/CPP/7zip/Bundles/Format7zF/Format7z.dsp +++ b/CPP/7zip/Bundles/Format7zF/Format7z.dsp @@ -124,6 +124,10 @@ SOURCE=..\..\Archive\Icons\dmg.ico # End Source File # Begin Source File +SOURCE=..\..\Archive\Icons\fat.ico +# End Source File +# Begin Source File + SOURCE=..\..\Archive\Icons\gz.ico # End Source File # Begin Source File @@ -144,6 +148,10 @@ SOURCE=..\..\Archive\Icons\lzma.ico # End Source File # Begin Source File +SOURCE=..\..\Archive\Icons\ntfs.ico +# End Source File +# Begin Source File + SOURCE=..\..\Archive\Icons\rar.ico # End Source File # Begin Source File @@ -160,6 +168,10 @@ SOURCE=..\..\Archive\Icons\tar.ico # End Source File # Begin Source File +SOURCE=..\..\Archive\Icons\vhd.ico +# End Source File +# Begin Source File + SOURCE=..\..\Archive\Icons\wim.ico # End Source File # Begin Source File @@ -168,6 +180,10 @@ SOURCE=..\..\Archive\Icons\xar.ico # End Source File # Begin Source File +SOURCE=..\..\Archive\Icons\xz.ico +# End Source File +# Begin Source File + SOURCE=..\..\Archive\Icons\z.ico # End Source File # Begin Source File @@ -593,23 +609,35 @@ SOURCE=..\..\Compress\ByteSwap.cpp # End Source File # Begin Source File -SOURCE=..\..\Compress\ByteSwap.h +SOURCE=..\..\Compress\CopyCoder.cpp # End Source File # Begin Source File -SOURCE=..\..\Compress\ByteSwapRegister.cpp +SOURCE=..\..\Compress\CopyCoder.h # End Source File # Begin Source File -SOURCE=..\..\Compress\CopyCoder.cpp +SOURCE=..\..\Compress\CopyRegister.cpp # End Source File # Begin Source File -SOURCE=..\..\Compress\CopyCoder.h +SOURCE=..\..\Compress\Lzma2Decoder.cpp # End Source File # Begin Source File -SOURCE=..\..\Compress\CopyRegister.cpp +SOURCE=..\..\Compress\Lzma2Decoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Encoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Encoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Register.cpp # End Source File # Begin Source File @@ -690,6 +718,10 @@ SOURCE=..\..\Compress\ArjDecoder2.h # End Source File # Begin Source File +SOURCE=..\..\Compress\DeltaFilter.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Compress\HuffmanDecoder.h # End Source File # Begin Source File @@ -896,6 +928,14 @@ SOURCE=..\..\Common\CreateCoder.h # End Source File # Begin Source File +SOURCE=..\..\Common\CWrappers.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CWrappers.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\FilterCoder.cpp # End Source File # Begin Source File @@ -1042,6 +1082,100 @@ SOURCE=..\..\Common\VirtThread.h # Begin Group "C" # PROP Default_Filter "" +# Begin Group "xz" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\..\C\Xz.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /W4 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# ADD CPP /W4 /WX +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Xz.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzCrc64.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /W4 /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# ADD CPP /W4 /WX +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzCrc64.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzDec.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /W4 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# ADD CPP /W4 /WX +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzEnc.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzEnc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzIn.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /W4 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# ADD CPP /W4 /WX +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\..\..\C\7zBuf2.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c @@ -1064,6 +1198,11 @@ SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\7zStream.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Aes.c !IF "$(CFG)" == "7z - Win32 Release" @@ -1169,6 +1308,15 @@ SOURCE=..\..\..\..\C\CpuArch.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Delta.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Delta.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\HuffEnc.c !IF "$(CFG)" == "7z - Win32 Release" @@ -1233,6 +1381,46 @@ SOURCE=..\..\..\..\C\LzHash.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Lzma2Dec.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Dec.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Enc.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Enc.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\LzmaDec.c !IF "$(CFG)" == "7z - Win32 Release" @@ -1273,6 +1461,15 @@ SOURCE=..\..\..\..\C\LzmaEnc.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\MtCoder.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\MtCoder.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\RotateDefs.h # End Source File # Begin Source File @@ -1500,38 +1697,6 @@ SOURCE=..\..\Archive\Rar\RarVolumeInStream.cpp SOURCE=..\..\Archive\Rar\RarVolumeInStream.h # End Source File # End Group -# Begin Group "bz2" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\..\Archive\BZip2\bz2Register.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\BZip2\BZip2Handler.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\BZip2\BZip2Handler.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\BZip2\BZip2HandlerOut.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\BZip2\BZip2Item.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\BZip2\BZip2Update.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\BZip2\BZip2Update.h -# End Source File -# End Group # Begin Group "Cab" # PROP Default_Filter "" @@ -1700,98 +1865,6 @@ SOURCE=..\..\Archive\Common\ParseProperties.cpp SOURCE=..\..\Archive\Common\ParseProperties.h # End Source File # End Group -# Begin Group "Cpio" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\..\Archive\Cpio\CpioHandler.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Cpio\CpioHandler.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Cpio\CpioHeader.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Cpio\CpioHeader.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Cpio\CpioIn.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Cpio\CpioIn.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Cpio\CpioItem.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Cpio\CpioRegister.cpp -# End Source File -# End Group -# Begin Group "GZip" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipHandler.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipHandler.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipHandlerOut.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipHeader.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipHeader.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipIn.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipIn.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipItem.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipOut.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipOut.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipRegister.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipUpdate.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\GZip\GZipUpdate.h -# End Source File -# End Group # Begin Group "Iso" # PROP Default_Filter "" @@ -1828,54 +1901,6 @@ SOURCE=..\..\Archive\Iso\IsoItem.h SOURCE=..\..\Archive\Iso\IsoRegister.cpp # End Source File # End Group -# Begin Group "Lzh" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\..\Archive\Lzh\LzhCRC.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Lzh\LzhCRC.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Lzh\LzhHandler.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Lzh\LzhHandler.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Lzh\LzhHeader.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Lzh\LzhIn.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Lzh\LzhIn.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Lzh\LzhItem.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Lzh\LzhOutStreamWithCRC.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Lzh\LzhOutStreamWithCRC.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Lzh\LzhRegister.cpp -# End Source File -# End Group # Begin Group "Nsis" # PROP Default_Filter "" @@ -1908,30 +1933,6 @@ SOURCE=..\..\Archive\Nsis\NsisIn.h SOURCE=..\..\Archive\Nsis\NsisRegister.cpp # End Source File # End Group -# Begin Group "RPM" - -# PROP Default_Filter "" -# End Group -# Begin Group "Split" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\..\Archive\Split\SplitHandler.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Split\SplitHandler.h -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Split\SplitHandlerOut.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Split\SplitRegister.cpp -# End Source File -# End Group # Begin Group "Tar" # PROP Default_Filter "" @@ -2112,117 +2113,113 @@ SOURCE=..\..\Archive\Com\ComIn.h SOURCE=..\..\Archive\Com\ComRegister.cpp # End Source File # End Group -# Begin Group "Lzma Ar" +# Begin Group "Hfs" # PROP Default_Filter "" # Begin Source File -SOURCE=..\..\Archive\Lzma\LzmaArcRegister.cpp +SOURCE=..\..\Archive\Hfs\HfsHandler.cpp # End Source File # Begin Source File -SOURCE=..\..\Archive\Lzma\LzmaFiltersDecode.cpp +SOURCE=..\..\Archive\Hfs\HfsHandler.h # End Source File # Begin Source File -SOURCE=..\..\Archive\Lzma\LzmaFiltersDecode.h +SOURCE=..\..\Archive\Hfs\HfsIn.cpp # End Source File # Begin Source File -SOURCE=..\..\Archive\Lzma\LzmaHandler.cpp +SOURCE=..\..\Archive\Hfs\HfsIn.h # End Source File # Begin Source File -SOURCE=..\..\Archive\Lzma\LzmaHandler.h +SOURCE=..\..\Archive\Hfs\HfsRegister.cpp # End Source File +# End Group +# Begin Group "Udf" + +# PROP Default_Filter "" # Begin Source File -SOURCE=..\..\Archive\Lzma\LzmaIn.cpp +SOURCE=..\..\Archive\Udf\UdfHandler.cpp # End Source File # Begin Source File -SOURCE=..\..\Archive\Lzma\LzmaIn.h +SOURCE=..\..\Archive\Udf\UdfHandler.h # End Source File # Begin Source File -SOURCE=..\..\Archive\Lzma\LzmaItem.h +SOURCE=..\..\Archive\Udf\UdfIn.cpp # End Source File -# End Group -# Begin Group "Hfs" - -# PROP Default_Filter "" # Begin Source File -SOURCE=..\..\Archive\Hfs\HfsHandler.cpp +SOURCE=..\..\Archive\Udf\UdfIn.h # End Source File # Begin Source File -SOURCE=..\..\Archive\Hfs\HfsHandler.h +SOURCE=..\..\Archive\Udf\UdfRegister.cpp # End Source File +# End Group # Begin Source File -SOURCE=..\..\Archive\Hfs\HfsIn.cpp +SOURCE=..\..\Archive\ArjHandler.cpp # End Source File # Begin Source File -SOURCE=..\..\Archive\Hfs\HfsIn.h +SOURCE=..\..\Archive\Bz2Handler.cpp # End Source File # Begin Source File -SOURCE=..\..\Archive\Hfs\HfsRegister.cpp +SOURCE=..\..\Archive\CpioHandler.cpp # End Source File -# End Group -# Begin Group "Udf" - -# PROP Default_Filter "" # Begin Source File -SOURCE=..\..\Archive\Udf\UdfHandler.cpp +SOURCE=..\..\Archive\DebHandler.cpp # End Source File # Begin Source File -SOURCE=..\..\Archive\Udf\UdfHandler.h +SOURCE=..\..\Archive\DmgHandler.cpp # End Source File # Begin Source File -SOURCE=..\..\Archive\Udf\UdfIn.cpp +SOURCE=..\..\Archive\ElfHandler.cpp # End Source File # Begin Source File -SOURCE=..\..\Archive\Udf\UdfIn.h +SOURCE=..\..\Archive\FatHandler.cpp # End Source File # Begin Source File -SOURCE=..\..\Archive\Udf\UdfRegister.cpp +SOURCE=..\..\Archive\GzHandler.cpp # End Source File -# End Group # Begin Source File -SOURCE=..\..\Archive\ArjHandler.cpp +SOURCE=..\..\Archive\IArchive.h # End Source File # Begin Source File -SOURCE=..\..\Archive\DebHandler.cpp +SOURCE=..\..\Archive\LzhHandler.cpp # End Source File # Begin Source File -SOURCE=..\..\Archive\DmgHandler.cpp +SOURCE=..\..\Archive\LzmaHandler.cpp # End Source File # Begin Source File -SOURCE=..\..\Archive\ElfHandler.cpp +SOURCE=..\..\Archive\MachoHandler.cpp # End Source File # Begin Source File -SOURCE=..\..\Archive\IArchive.h +SOURCE=..\..\Archive\MbrHandler.cpp # End Source File # Begin Source File -SOURCE=..\..\Archive\MachoHandler.cpp +SOURCE=..\..\Archive\MubHandler.cpp # End Source File # Begin Source File -SOURCE=..\..\Archive\MubHandler.cpp +SOURCE=..\..\Archive\NtfsHandler.cpp # End Source File # Begin Source File @@ -2234,10 +2231,22 @@ SOURCE=..\..\Archive\RpmHandler.cpp # End Source File # Begin Source File +SOURCE=..\..\Archive\SplitHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\VhdHandler.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Archive\XarHandler.cpp # End Source File # Begin Source File +SOURCE=..\..\Archive\XzHandler.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Archive\ZHandler.cpp # End Source File # End Group diff --git a/CPP/7zip/Bundles/Format7zF/makefile b/CPP/7zip/Bundles/Format7zF/makefile index 18a2d731..a1f09365 100755 --- a/CPP/7zip/Bundles/Format7zF/makefile +++ b/CPP/7zip/Bundles/Format7zF/makefile @@ -35,6 +35,7 @@ WIN_OBJS = \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\CreateCoder.obj \ + $O\CWrappers.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ @@ -55,14 +56,25 @@ AR_OBJS = \ $O\ArchiveExports.obj \ $O\DllExports2.obj \ $O\ArjHandler.obj \ + $O\Bz2Handler.obj \ + $O\CpioHandler.obj \ $O\DebHandler.obj \ $O\DmgHandler.obj \ $O\ElfHandler.obj \ + $O\FatHandler.obj \ + $O\GzHandler.obj \ + $O\LzhHandler.obj \ + $O\LzmaHandler.obj \ $O\MachoHandler.obj \ + $O\MbrHandler.obj \ $O\MubHandler.obj \ + $O\NtfsHandler.obj \ $O\PeHandler.obj \ $O\RpmHandler.obj \ + $O\SplitHandler.obj \ + $O\VhdHandler.obj \ $O\XarHandler.obj \ + $O\XzHandler.obj \ $O\ZHandler.obj \ AR_COMMON_OBJS = \ @@ -97,12 +109,6 @@ AR_COMMON_OBJS = \ $O\7zUpdate.obj \ $O\7zRegister.obj \ -BZ2_OBJS = \ - $O\BZip2Handler.obj \ - $O\BZip2HandlerOut.obj \ - $O\BZip2Update.obj \ - $O\bz2Register.obj \ - CAB_OBJS = \ $O\CabBlockInStream.obj \ $O\CabHandler.obj \ @@ -121,21 +127,6 @@ COM_OBJS = \ $O\ComIn.obj \ $O\ComRegister.obj \ -CPIO_OBJS = \ - $O\CpioHandler.obj \ - $O\CpioHeader.obj \ - $O\CpioIn.obj \ - $O\CpioRegister.obj \ - -GZ_OBJS = \ - $O\GZipHandler.obj \ - $O\GZipHandlerOut.obj \ - $O\GZipHeader.obj \ - $O\GZipIn.obj \ - $O\GZipOut.obj \ - $O\GZipUpdate.obj \ - $O\GZipRegister.obj \ - HFS_OBJS = \ $O\HfsHandler.obj \ $O\HfsIn.obj \ @@ -147,19 +138,6 @@ ISO_OBJS = \ $O\IsoIn.obj \ $O\IsoRegister.obj \ -LZH_OBJS = \ - $O\LzhCRC.obj \ - $O\LzhHandler.obj \ - $O\LzhIn.obj \ - $O\LzhOutStreamWithCRC.obj \ - $O\LzhRegister.obj \ - -LZM_OBJS = \ - $O\LzmaArcRegister.obj \ - $O\LzmaFiltersDecode.obj \ - $O\LzmaHandler.obj \ - $O\LzmaIn.obj \ - NSIS_OBJS = \ $O\NsisDecode.obj \ $O\NsisHandler.obj \ @@ -174,11 +152,6 @@ RAR_OBJS = \ $O\RarVolumeInStream.obj \ $O\RarRegister.obj \ -SPLIT_OBJS = \ - $O\SplitHandler.obj \ - $O\SplitHandlerOut.obj \ - $O\SplitRegister.obj \ - TAR_OBJS = \ $O\TarHandler.obj \ $O\TarHandlerOut.obj \ @@ -222,7 +195,6 @@ COMPRESS_OBJS = \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ - $O\ByteSwapRegister.obj \ $O\BZip2Crc.obj \ $O\BZip2Decoder.obj \ $O\BZip2Encoder.obj \ @@ -234,9 +206,13 @@ COMPRESS_OBJS = \ $O\DeflateEncoder.obj \ $O\DeflateNsisRegister.obj \ $O\DeflateRegister.obj \ + $O\DeltaFilter.obj \ $O\ImplodeDecoder.obj \ $O\ImplodeHuffmanDecoder.obj \ $O\LzhDecoder.obj \ + $O\Lzma2Decoder.obj \ + $O\Lzma2Encoder.obj \ + $O\Lzma2Register.obj \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ $O\LzmaRegister.obj \ @@ -272,20 +248,31 @@ CRYPTO_OBJS = \ C_OBJS = \ + $O\7zBuf2.obj \ + $O\7zStream.obj \ + $O\Aes.obj \ $O\Alloc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\BwtSort.obj \ + $O\Delta.obj \ $O\HuffEnc.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ + $O\Lzma2Dec.obj \ + $O\Lzma2Enc.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ + $O\MtCoder.obj \ + $O\Sha256.obj \ $O\Sort.obj \ $O\Threads.obj \ - $O\Aes.obj \ - $O\Sha256.obj \ + $O\Xz.obj \ + $O\XzCrc64.obj \ + $O\XzDec.obj \ + $O\XzEnc.obj \ + $O\XzIn.obj \ !include "../../Crc2.mak" @@ -298,19 +285,13 @@ OBJS = \ $(AR_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ - $(BZ2_OBJS) \ $(CAB_OBJS) \ $(CHM_OBJS) \ $(COM_OBJS) \ - $(CPIO_OBJS) \ - $(GZ_OBJS) \ $(HFS_OBJS) \ $(ISO_OBJS) \ - $(LZH_OBJS) \ - $(LZM_OBJS) \ $(NSIS_OBJS) \ $(RAR_OBJS) \ - $(SPLIT_OBJS) \ $(TAR_OBJS) \ $(UDF_OBJS) \ $(WIM_OBJS) \ @@ -337,32 +318,20 @@ $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) -$(BZ2_OBJS): ../../Archive/BZip2/$(*B).cpp - $(COMPL) $(CAB_OBJS): ../../Archive/Cab/$(*B).cpp $(COMPL) $(CHM_OBJS): ../../Archive/Chm/$(*B).cpp $(COMPL) $(COM_OBJS): ../../Archive/Com/$(*B).cpp $(COMPL) -$(CPIO_OBJS): ../../Archive/Cpio/$(*B).cpp - $(COMPL) -$(GZ_OBJS): ../../Archive/GZip/$(*B).cpp - $(COMPL) $(HFS_OBJS): ../../Archive/Hfs/$(*B).cpp $(COMPL) $(ISO_OBJS): ../../Archive/Iso/$(*B).cpp $(COMPL) -$(LZH_OBJS): ../../Archive/Lzh/$(*B).cpp - $(COMPL) -$(LZM_OBJS): ../../Archive/Lzma/$(*B).cpp - $(COMPL) $(NSIS_OBJS): ../../Archive/Nsis/$(*B).cpp $(COMPL) $(RAR_OBJS): ../../Archive/Rar/$(*B).cpp $(COMPL) -$(SPLIT_OBJS): ../../Archive/Split/$(*B).cpp - $(COMPL) $(TAR_OBJS): ../../Archive/Tar/$(*B).cpp $(COMPL) $(UDF_OBJS): ../../Archive/Udf/$(*B).cpp diff --git a/CPP/7zip/Bundles/Format7zF/resource.rc b/CPP/7zip/Bundles/Format7zF/resource.rc index 79ef2950..babd1149 100755 --- a/CPP/7zip/Bundles/Format7zF/resource.rc +++ b/CPP/7zip/Bundles/Format7zF/resource.rc @@ -23,10 +23,14 @@ MY_VERSION_INFO_DLL("7z Standalone Plugin", "7za") 17 ICON "../../Archive/Icons/dmg.ico" 18 ICON "../../Archive/Icons/hfs.ico" 19 ICON "../../Archive/Icons/xar.ico" +20 ICON "../../Archive/Icons/vhd.ico" +21 ICON "../../Archive/Icons/fat.ico" +22 ICON "../../Archive/Icons/ntfs.ico" +23 ICON "../../Archive/Icons/xz.ico" STRINGTABLE BEGIN - 100 "7z:0 zip:1 bz2:2 bzip2:2 tbz2:2 tbz:2 rar:3 arj:4 z:5 taz:5 lzh:6 lha:6 cab:7 iso:8 split:9 rpm:10 deb:11 cpio:12 tar:13 gz:14 gzip:14 tgz:14 tpz:14 wim:15 swm:15 lzma:16 dmg:17 hfs:18 xar:19" + 100 "7z:0 zip:1 bz2:2 bzip2:2 tbz2:2 tbz:2 rar:3 arj:4 z:5 taz:5 lzh:6 lha:6 cab:7 iso:8 split:9 rpm:10 deb:11 cpio:12 tar:13 gz:14 gzip:14 tgz:14 tpz:14 wim:15 swm:15 lzma:16 dmg:17 hfs:18 xar:19 vhd:20 fat:21 ntfs:22 xz:23" END diff --git a/CPP/7zip/Bundles/Format7zR/makefile b/CPP/7zip/Bundles/Format7zR/makefile index b103f2a6..77544ce2 100755 --- a/CPP/7zip/Bundles/Format7zR/makefile +++ b/CPP/7zip/Bundles/Format7zR/makefile @@ -26,6 +26,7 @@ WIN_OBJS = \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ + $O\CWrappers.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ @@ -83,9 +84,12 @@ COMPRESS_OBJS = \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ - $O\ByteSwapRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ + $O\DeltaFilter.obj \ + $O\Lzma2Decoder.obj \ + $O\Lzma2Encoder.obj \ + $O\Lzma2Register.obj \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ $O\LzmaRegister.obj \ @@ -96,10 +100,14 @@ C_OBJS = \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ + $O\Delta.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ + $O\Lzma2Dec.obj \ + $O\Lzma2Enc.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ + $O\MtCoder.obj \ $O\Threads.obj \ OBJS = \ diff --git a/CPP/7zip/Bundles/SFXCon/Main.cpp b/CPP/7zip/Bundles/SFXCon/Main.cpp index ac8c1cdf..140f8364 100755 --- a/CPP/7zip/Bundles/SFXCon/Main.cpp +++ b/CPP/7zip/Bundles/SFXCon/Main.cpp @@ -5,26 +5,15 @@ #include "Common/MyInitGuid.h" #include "Common/CommandLineParser.h" -#include "Common/MyCom.h" #include "Common/MyException.h" -#include "Common/StdOutStream.h" -#include "Common/StringConvert.h" -#include "Common/Wildcard.h" -#include "Windows/Defs.h" -#include "Windows/FileName.h" #ifdef _WIN32 #include "Windows/DLL.h" #include "Windows/FileDir.h" #endif -#include "../../IPassword.h" -#include "../../ICoder.h" - -#include "../../UI/Common/DefaultName.h" #include "../../UI/Common/ExitCode.h" #include "../../UI/Common/Extract.h" -#include "../../UI/Common/OpenArchive.h" #include "../../UI/Console/ExtractCallbackConsole.h" #include "../../UI/Console/List.h" @@ -36,6 +25,7 @@ using namespace NWindows; using namespace NFile; using namespace NCommandLineParser; +int g_CodePage = -1; extern CStdOutStream *g_StdStream; static const char *kCopyrightString = @@ -343,10 +333,7 @@ int Main2( if(passwordEnabled) password = parser[NKey::kPassword].PostStrings[0]; - NFind::CFileInfoW archiveFileInfo; - if (!NFind::FindFile(arcPath, archiveFileInfo)) - throw kCantFindSFX; - if (archiveFileInfo.IsDir()) + if (!NFind::DoesFileExist(arcPath)) throw kCantFindSFX; UString outputDir; @@ -380,14 +367,21 @@ int Main2( CExtractCallbackConsole *ecs = new CExtractCallbackConsole; CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; ecs->OutStream = g_StdStream; + + #ifndef _NO_CRYPTO ecs->PasswordIsDefined = passwordEnabled; ecs->Password = password; + #endif + ecs->Init(); COpenCallbackConsole openCallback; openCallback.OutStream = g_StdStream; + + #ifndef _NO_CRYPTO openCallback.PasswordIsDefined = passwordEnabled; openCallback.Password = password; + #endif CExtractOptions eo; eo.StdOutMode = false; @@ -429,11 +423,14 @@ int Main2( UInt64 numErrors = 0; HRESULT result = ListArchives( codecs, CIntVector(), + false, v1, v2, wildcardCensorHead, true, false, - passwordEnabled, - password, numErrors); + #ifndef _NO_CRYPTO + passwordEnabled, password, + #endif + numErrors); if (numErrors > 0) { g_StdOut << endl << "Errors: " << numErrors; diff --git a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp index 8dc222a5..c4e367f6 100755 --- a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp +++ b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp @@ -285,6 +285,14 @@ SOURCE=..\..\Compress\CopyRegister.cpp # End Source File # Begin Source File +SOURCE=..\..\Compress\Lzma2Decoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Register.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Compress\LzmaDecoder.cpp # End Source File # Begin Source File @@ -477,6 +485,14 @@ SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\UTFConvert.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\UTFConvert.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File @@ -721,6 +737,15 @@ SOURCE=..\..\..\..\C\Bra86.c # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Lzma2Dec.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Dec.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\LzmaDec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File diff --git a/CPP/7zip/Bundles/SFXCon/makefile b/CPP/7zip/Bundles/SFXCon/makefile index a18aa7ac..cac6d6ef 100755 --- a/CPP/7zip/Bundles/SFXCon/makefile +++ b/CPP/7zip/Bundles/SFXCon/makefile @@ -27,6 +27,7 @@ COMMON_OBJS = \ $O\StringConvert.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ + $O\UTFConvert.obj \ WIN_OBJS = \ $O\DLL.obj \ @@ -89,6 +90,8 @@ COMPRESS_OBJS = \ $O\BcjRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ + $O\Lzma2Decoder.obj \ + $O\Lzma2Register.obj \ $O\LzmaDecoder.obj \ $O\LzmaRegister.obj \ $O\PpmdDecoder.obj \ @@ -100,12 +103,13 @@ CRYPTO_OBJS = \ $O\MyAes.obj \ C_OBJS = \ + $O\Aes.obj \ $O\Alloc.obj \ $O\Bra86.obj \ + $O\Lzma2Dec.obj \ $O\LzmaDec.obj \ - $O\Threads.obj \ - $O\Aes.obj \ $O\Sha256.obj \ + $O\Threads.obj \ !include "../../Crc2.mak" diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp index 5ec72dc4..8ebe2504 100755 --- a/CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp +++ b/CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp @@ -2,14 +2,14 @@ #include "StdAfx.h" -#include "ExtractCallback.h" - #include "Common/Wildcard.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/PropVariant.h" +#include "ExtractCallback.h" + using namespace NWindows; using namespace NFile; @@ -167,7 +167,7 @@ STDMETHODIMP CExtractCallbackImp::GetStream(UInt32 index, } NFind::CFileInfoW fileInfo; - if (NFind::FindFile(fullProcessedPath, fileInfo)) + if (fileInfo.Find(fullProcessedPath)) { if (!NDirectory::DeleteFileAlways(fullProcessedPath)) { diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp index d867b74a..e5353c21 100755 --- a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp +++ b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp @@ -2,12 +2,7 @@ #include "StdAfx.h" -#include "ExtractEngine.h" - -#include "Common/StringConvert.h" - #include "Windows/FileDir.h" -#include "Windows/FileFind.h" #include "Windows/Thread.h" #include "../../UI/Common/OpenArchive.h" @@ -15,6 +10,7 @@ #include "../../UI/FileManager/FormatUtils.h" #include "ExtractCallback.h" +#include "ExtractEngine.h" using namespace NWindows; @@ -40,18 +36,18 @@ struct CThreadExtracting void Process() { NFile::NFind::CFileInfoW fi; - if (!NFile::NFind::FindFile(FileName, fi)) + if (!fi.Find(FileName)) { ErrorMessage = kCantFindArchive; Result = E_FAIL; return; } - Result = MyOpenArchive(Codecs, CIntVector(), FileName, ArchiveLink, ExtractCallbackSpec); + Result = ArchiveLink.Open2(Codecs, CIntVector(), false, NULL, FileName, ExtractCallbackSpec); if (Result != S_OK) { if (Result != S_OK) - ErrorMessage = kCantOpenArchive; + ErrorMessage = kCantOpenArchive; return; } diff --git a/CPP/7zip/Bundles/SFXSetup/Main.cpp b/CPP/7zip/Bundles/SFXSetup/Main.cpp index 3f048710..ece6e3de 100755 --- a/CPP/7zip/Bundles/SFXSetup/Main.cpp +++ b/CPP/7zip/Bundles/SFXSetup/Main.cpp @@ -4,25 +4,18 @@ #include <initguid.h> +#include "Common/CommandLineParser.h" #include "Common/StringConvert.h" -#include "Common/Random.h" #include "Common/TextConfig.h" -#include "Common/CommandLineParser.h" +#include "Windows/DLL.h" #include "Windows/FileDir.h" -#include "Windows/FileIO.h" #include "Windows/FileFind.h" -#include "Windows/FileName.h" -#include "Windows/DLL.h" +#include "Windows/FileIO.h" #include "Windows/ResourceString.h" -#include "../../IPassword.h" -#include "../../ICoder.h" -#include "../../Archive/IArchive.h" #include "../../UI/Explorer/MyMessages.h" -// #include "../../UI/GUI/ExtractGUI.h" - #include "ExtractEngine.h" #include "resource.h" diff --git a/CPP/7zip/Bundles/SFXWin/Main.cpp b/CPP/7zip/Bundles/SFXWin/Main.cpp index 7cc70882..a538960b 100755 --- a/CPP/7zip/Bundles/SFXWin/Main.cpp +++ b/CPP/7zip/Bundles/SFXWin/Main.cpp @@ -100,9 +100,12 @@ int APIENTRY WinMain2() CExtractCallbackImp *ecs = new CExtractCallbackImp; CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; ecs->Init(); + + #ifndef _NO_CRYPTO ecs->PasswordIsDefined = !password.IsEmpty(); ecs->Password = password; - + #endif + CExtractOptions eo; eo.OutputDir = outputFolderDefined ? outputFolder : fullPath.Left(fileNamePartStartIndex); diff --git a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp index fdb33a85..ddd7c5fa 100755 --- a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp +++ b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp @@ -261,6 +261,14 @@ SOURCE=..\..\Compress\CopyRegister.cpp # End Source File # Begin Source File +SOURCE=..\..\Compress\Lzma2Decoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Register.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Compress\LzmaDecoder.cpp # End Source File # Begin Source File @@ -789,6 +797,15 @@ SOURCE=..\..\..\..\C\Bra86.c # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Lzma2Dec.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Dec.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\LzmaDec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File diff --git a/CPP/7zip/Bundles/SFXWin/makefile b/CPP/7zip/Bundles/SFXWin/makefile index 8302b7d0..ec0b8590 100755 --- a/CPP/7zip/Bundles/SFXWin/makefile +++ b/CPP/7zip/Bundles/SFXWin/makefile @@ -97,6 +97,8 @@ COMPRESS_OBJS = \ $O\BcjRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ + $O\Lzma2Decoder.obj \ + $O\Lzma2Register.obj \ $O\LzmaDecoder.obj \ $O\LzmaRegister.obj \ $O\PpmdDecoder.obj \ @@ -108,12 +110,13 @@ CRYPTO_OBJS = \ $O\MyAes.obj \ C_OBJS = \ + $O\Aes.obj \ $O\Alloc.obj \ $O\Bra86.obj \ + $O\Lzma2Dec.obj \ $O\LzmaDec.obj \ - $O\Threads.obj \ - $O\Aes.obj \ $O\Sha256.obj \ + $O\Threads.obj \ !include "../../Crc2.mak" diff --git a/CPP/7zip/Common/CWrappers.cpp b/CPP/7zip/Common/CWrappers.cpp new file mode 100755 index 00000000..d440027d --- /dev/null +++ b/CPP/7zip/Common/CWrappers.cpp @@ -0,0 +1,127 @@ +// CWrappers.h + +#include "StdAfx.h" + +#include "CWrappers.h" + +#include "StreamUtils.h" + +#define PROGRESS_UNKNOWN_VALUE ((UInt64)(Int64)-1) + +#define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x) + +static SRes CompressProgress(void *pp, UInt64 inSize, UInt64 outSize) +{ + CCompressProgressWrap *p = (CCompressProgressWrap *)pp; + p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize)); + return (SRes)p->Res; +} + +CCompressProgressWrap::CCompressProgressWrap(ICompressProgressInfo *progress) +{ + p.Progress = CompressProgress; + Progress = progress; + Res = SZ_OK; +} + +static const UInt32 kStreamStepSize = (UInt32)1 << 31; + +SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) +{ + switch(res) + { + case S_OK: return SZ_OK; + case E_OUTOFMEMORY: return SZ_ERROR_MEM; + case E_INVALIDARG: return SZ_ERROR_PARAM; + case E_ABORT: return SZ_ERROR_PROGRESS; + case S_FALSE: return SZ_ERROR_DATA; + } + return defaultRes; +} + +static SRes MyRead(void *object, void *data, size_t *size) +{ + CSeqInStreamWrap *p = (CSeqInStreamWrap *)object; + UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize); + p->Res = (p->Stream->Read(data, curSize, &curSize)); + *size = curSize; + if (p->Res == S_OK) + return SZ_OK; + return HRESULT_To_SRes(p->Res, SZ_ERROR_READ); +} + +static size_t MyWrite(void *object, const void *data, size_t size) +{ + CSeqOutStreamWrap *p = (CSeqOutStreamWrap *)object; + if (p->Stream) + { + p->Res = WriteStream(p->Stream, data, size); + if (p->Res != 0) + return 0; + } + else + p->Res = S_OK; + p->Processed += size; + return size; +} + +CSeqInStreamWrap::CSeqInStreamWrap(ISequentialInStream *stream) +{ + p.Read = MyRead; + Stream = stream; +} + +CSeqOutStreamWrap::CSeqOutStreamWrap(ISequentialOutStream *stream) +{ + p.Write = MyWrite; + Stream = stream; + Res = SZ_OK; + Processed = 0; +} + +HRESULT SResToHRESULT(SRes res) +{ + switch(res) + { + case SZ_OK: return S_OK; + case SZ_ERROR_MEM: return E_OUTOFMEMORY; + case SZ_ERROR_PARAM: return E_INVALIDARG; + case SZ_ERROR_PROGRESS: return E_ABORT; + case SZ_ERROR_DATA: return S_FALSE; + } + return E_FAIL; +} + +static SRes InStreamWrap_Read(void *pp, void *data, size_t *size) +{ + CSeekInStreamWrap *p = (CSeekInStreamWrap *)pp; + UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize); + p->Res = p->Stream->Read(data, curSize, &curSize); + *size = curSize; + return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ; +} + +static SRes InStreamWrap_Seek(void *pp, Int64 *offset, ESzSeek origin) +{ + CSeekInStreamWrap *p = (CSeekInStreamWrap *)pp; + UInt32 moveMethod; + switch(origin) + { + case SZ_SEEK_SET: moveMethod = STREAM_SEEK_SET; break; + case SZ_SEEK_CUR: moveMethod = STREAM_SEEK_CUR; break; + case SZ_SEEK_END: moveMethod = STREAM_SEEK_END; break; + default: return SZ_ERROR_PARAM; + } + UInt64 newPosition; + p->Res = p->Stream->Seek(*offset, moveMethod, &newPosition); + *offset = (Int64)newPosition; + return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ; +} + +CSeekInStreamWrap::CSeekInStreamWrap(IInStream *stream) +{ + Stream = stream; + p.Read = InStreamWrap_Read; + p.Seek = InStreamWrap_Seek; + Res = S_OK; +} diff --git a/CPP/7zip/Common/CWrappers.h b/CPP/7zip/Common/CWrappers.h new file mode 100755 index 00000000..f7ac96cb --- /dev/null +++ b/CPP/7zip/Common/CWrappers.h @@ -0,0 +1,46 @@ +// CWrappers.h + +#ifndef __C_WRAPPERS_H +#define __C_WRAPPERS_H + +#include "../../../C/Types.h" + +#include "../ICoder.h" +#include "../../Common/MyCom.h" + +struct CCompressProgressWrap +{ + ICompressProgress p; + ICompressProgressInfo *Progress; + HRESULT Res; + CCompressProgressWrap(ICompressProgressInfo *progress); +}; + +struct CSeqInStreamWrap +{ + ISeqInStream p; + ISequentialInStream *Stream; + HRESULT Res; + CSeqInStreamWrap(ISequentialInStream *stream); +}; + +struct CSeekInStreamWrap +{ + ISeekInStream p; + IInStream *Stream; + HRESULT Res; + CSeekInStreamWrap(IInStream *stream); +}; + +struct CSeqOutStreamWrap +{ + ISeqOutStream p; + ISequentialOutStream *Stream; + HRESULT Res; + UInt64 Processed; + CSeqOutStreamWrap(ISequentialOutStream *stream); +}; + +HRESULT SResToHRESULT(SRes res); + +#endif diff --git a/CPP/7zip/Common/FilePathAutoRename.cpp b/CPP/7zip/Common/FilePathAutoRename.cpp index bf69fc79..7d6e36f1 100755 --- a/CPP/7zip/Common/FilePathAutoRename.cpp +++ b/CPP/7zip/Common/FilePathAutoRename.cpp @@ -1,25 +1,25 @@ // FilePathAutoRename.cpp #include "StdAfx.h" -#include "FilePathAutoRename.h" #include "Common/Defs.h" #include "Common/IntToString.h" -#include "Windows/FileName.h" #include "Windows/FileFind.h" +#include "FilePathAutoRename.h" + using namespace NWindows; static bool MakeAutoName(const UString &name, - const UString &extension, int value, UString &path) + const UString &extension, unsigned value, UString &path) { - wchar_t number[32]; - ConvertUInt64ToString(value, number); + wchar_t number[16]; + ConvertUInt32ToString(value, number); path = name; path += number; path += extension; - return NFile::NFind::DoesFileExist(path); + return NFile::NFind::DoesFileOrDirExist(path); } bool AutoRenamePath(UString &fullProcessedPath) @@ -34,7 +34,7 @@ bool AutoRenamePath(UString &fullProcessedPath) #endif UString name, extension; - if (dotPos > slashPos && dotPos > 0) + if (dotPos > slashPos && dotPos > 0) { name = fullProcessedPath.Left(dotPos); extension = fullProcessedPath.Mid(dotPos); @@ -42,16 +42,14 @@ bool AutoRenamePath(UString &fullProcessedPath) else name = fullProcessedPath; name += L'_'; - int indexLeft = 1, indexRight = (1 << 30); - while (indexLeft != indexRight) + unsigned left = 1, right = (1 << 30); + while (left != right) { - int indexMid = (indexLeft + indexRight) / 2; - if (MakeAutoName(name, extension, indexMid, path)) - indexLeft = indexMid + 1; + unsigned mid = (left + right) / 2; + if (MakeAutoName(name, extension, mid, path)) + left = mid + 1; else - indexRight = indexMid; + right = mid; } - if (MakeAutoName(name, extension, indexRight, fullProcessedPath)) - return false; - return true; + return !MakeAutoName(name, extension, right, fullProcessedPath); } diff --git a/CPP/7zip/Common/FileStreams.cpp b/CPP/7zip/Common/FileStreams.cpp index eb7ad3a2..f7c01d2c 100755 --- a/CPP/7zip/Common/FileStreams.cpp +++ b/CPP/7zip/Common/FileStreams.cpp @@ -8,6 +8,11 @@ #include <errno.h> #endif +#ifdef SUPPORT_DEVICE_FILE +#include "../../../C/Alloc.h" +#include "../../Common/Defs.h" +#endif + #include "FileStreams.h" static inline HRESULT ConvertBoolToHRESULT(bool result) @@ -52,24 +57,138 @@ bool CInFileStream::OpenShared(LPCWSTR fileName, bool shareForWrite) #endif #endif +#ifdef SUPPORT_DEVICE_FILE + +static const UInt32 kClusterSize = 1 << 18; +CInFileStream::CInFileStream(): + VirtPos(0), + PhyPos(0), + Buffer(0), + BufferSize(0) +{ +} + +#endif + +CInFileStream::~CInFileStream() +{ + #ifdef SUPPORT_DEVICE_FILE + MidFree(Buffer); + #endif +} + STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef USE_WIN_FILE + #ifdef SUPPORT_DEVICE_FILE + if (processedSize != NULL) + *processedSize = 0; + if (size == 0) + return S_OK; + if (File.IsDeviceFile) + { + if (File.LengthDefined) + { + if (VirtPos >= File.Length) + return VirtPos == File.Length ? S_OK : E_FAIL; + UInt64 rem = File.Length - VirtPos; + if (size > rem) + size = (UInt32)rem; + } + for (;;) + { + const UInt32 mask = kClusterSize - 1; + UInt64 mask2 = ~(UInt64)mask; + UInt64 alignedPos = VirtPos & mask2; + if (BufferSize > 0 && BufferStartPos == alignedPos) + { + UInt32 pos = (UInt32)VirtPos & mask; + if (pos >= BufferSize) + return S_OK; + UInt32 rem = MyMin(BufferSize - pos, size); + memcpy(data, Buffer + pos, rem); + VirtPos += rem; + if (processedSize != NULL) + *processedSize += rem; + return S_OK; + } + + bool useBuffer = false; + if ((VirtPos & mask) != 0 || ((ptrdiff_t)data & mask) != 0 ) + useBuffer = true; + else + { + UInt64 end = VirtPos + size; + if ((end & mask) != 0) + { + end &= mask2; + if (end <= VirtPos) + useBuffer = true; + else + size = (UInt32)(end - VirtPos); + } + } + if (!useBuffer) + break; + if (alignedPos != PhyPos) + { + UInt64 realNewPosition; + bool result = File.Seek(alignedPos, FILE_BEGIN, realNewPosition); + if (!result) + return ConvertBoolToHRESULT(result); + PhyPos = realNewPosition; + } + + BufferStartPos = alignedPos; + UInt32 readSize = kClusterSize; + if (File.LengthDefined) + readSize = (UInt32)MyMin(File.Length - PhyPos, (UInt64)kClusterSize); + + if (Buffer == 0) + { + Buffer = (Byte *)MidAlloc(kClusterSize); + if (Buffer == 0) + return E_OUTOFMEMORY; + } + bool result = File.Read1(Buffer, readSize, BufferSize); + if (!result) + return ConvertBoolToHRESULT(result); + + if (BufferSize == 0) + return S_OK; + PhyPos += BufferSize; + } + + if (VirtPos != PhyPos) + { + UInt64 realNewPosition; + bool result = File.Seek(VirtPos, FILE_BEGIN, realNewPosition); + if (!result) + return ConvertBoolToHRESULT(result); + PhyPos = VirtPos = realNewPosition; + } + } + #endif + UInt32 realProcessedSize; bool result = File.ReadPart(data, size, realProcessedSize); - if(processedSize != NULL) + if (processedSize != NULL) *processedSize = realProcessedSize; + #ifdef SUPPORT_DEVICE_FILE + VirtPos += realProcessedSize; + PhyPos += realProcessedSize; + #endif return ConvertBoolToHRESULT(result); #else - if(processedSize != NULL) + if (processedSize != NULL) *processedSize = 0; ssize_t res = File.Read(data, (size_t)size); if (res == -1) return E_FAIL; - if(processedSize != NULL) + if (processedSize != NULL) *processedSize = (UInt32)res; return S_OK; @@ -80,10 +199,13 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 - UInt32 realProcessedSize; - BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), - data, size, (DWORD *)&realProcessedSize, NULL); - if(processedSize != NULL) + + DWORD realProcessedSize; + UInt32 sizeTemp = (1 << 20); + if (sizeTemp > size) + sizeTemp = size; + BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, sizeTemp, &realProcessedSize, NULL); + if (processedSize != NULL) *processedSize = realProcessedSize; if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE) return S_OK; @@ -91,7 +213,7 @@ STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSi #else - if(processedSize != NULL) + if (processedSize != NULL) *processedSize = 0; ssize_t res; do @@ -101,7 +223,7 @@ STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSi while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; - if(processedSize != NULL) + if (processedSize != NULL) *processedSize = (UInt32)res; return S_OK; @@ -113,14 +235,37 @@ STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSi STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - if(seekOrigin >= 3) + if (seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef USE_WIN_FILE + #ifdef SUPPORT_DEVICE_FILE + if (File.IsDeviceFile) + { + UInt64 newVirtPos = offset; + switch(seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: newVirtPos += VirtPos; break; + case STREAM_SEEK_END: newVirtPos += File.Length; break; + default: return STG_E_INVALIDFUNCTION; + } + VirtPos = newVirtPos; + if (newPosition) + *newPosition = newVirtPos; + return S_OK; + } + #endif + UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); - if(newPosition != NULL) + + #ifdef SUPPORT_DEVICE_FILE + PhyPos = VirtPos = realNewPosition; + #endif + + if (newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); @@ -129,7 +274,7 @@ STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; - if(newPosition != NULL) + if (newPosition != NULL) *newPosition = (UInt64)res; return S_OK; @@ -157,18 +302,18 @@ STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *proces UInt32 realProcessedSize; bool result = File.WritePart(data, size, realProcessedSize); ProcessedSize += realProcessedSize; - if(processedSize != NULL) + if (processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else - if(processedSize != NULL) + if (processedSize != NULL) *processedSize = 0; ssize_t res = File.Write(data, (size_t)size); if (res == -1) return E_FAIL; - if(processedSize != NULL) + if (processedSize != NULL) *processedSize = (UInt32)res; ProcessedSize += res; return S_OK; @@ -178,13 +323,13 @@ STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *proces STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - if(seekOrigin >= 3) + if (seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef USE_WIN_FILE UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); - if(newPosition != NULL) + if (newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); @@ -193,7 +338,7 @@ STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; - if(newPosition != NULL) + if (newPosition != NULL) *newPosition = (UInt64)res; return S_OK; @@ -204,7 +349,7 @@ STDMETHODIMP COutFileStream::SetSize(Int64 newSize) { #ifdef USE_WIN_FILE UInt64 currentPos; - if(!File.Seek(0, FILE_CURRENT, currentPos)) + if (!File.Seek(0, FILE_CURRENT, currentPos)) return E_FAIL; bool result = File.SetLength(newSize); UInt64 currentPos2; @@ -218,7 +363,7 @@ STDMETHODIMP COutFileStream::SetSize(Int64 newSize) #ifndef _WIN32_WCE STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { - if(processedSize != NULL) + if (processedSize != NULL) *processedSize = 0; #ifdef _WIN32 @@ -235,7 +380,7 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro data, sizeTemp, (DWORD *)&realProcessedSize, NULL); size -= realProcessedSize; data = (const void *)((const Byte *)data + realProcessedSize); - if(processedSize != NULL) + if (processedSize != NULL) *processedSize += realProcessedSize; } return ConvertBoolToHRESULT(res != FALSE); @@ -250,7 +395,7 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; - if(processedSize != NULL) + if (processedSize != NULL) *processedSize = (UInt32)res; return S_OK; diff --git a/CPP/7zip/Common/FileStreams.h b/CPP/7zip/Common/FileStreams.h index 361c2199..32869192 100755 --- a/CPP/7zip/Common/FileStreams.h +++ b/CPP/7zip/Common/FileStreams.h @@ -13,9 +13,10 @@ #include "../../Common/C_FileIO.h" #endif -#include "../IStream.h" #include "../../Common/MyCom.h" +#include "../IStream.h" + class CInFileStream: public IInStream, public IStreamGetSize, @@ -24,12 +25,22 @@ class CInFileStream: public: #ifdef USE_WIN_FILE NWindows::NFile::NIO::CInFile File; + #ifdef SUPPORT_DEVICE_FILE + UInt64 VirtPos; + UInt64 PhyPos; + UInt64 BufferStartPos; + Byte *Buffer; + UInt32 BufferSize; + #endif #else NC::NFile::NIO::CInFile File; #endif - CInFileStream() {} - virtual ~CInFileStream() {} + virtual ~CInFileStream(); + #ifdef SUPPORT_DEVICE_FILE + CInFileStream(); + #endif + bool Open(LPCTSTR fileName); #ifdef USE_WIN_FILE #ifndef _UNICODE @@ -58,9 +69,6 @@ class CStdInFileStream: public CMyUnknownImp { public: - // HANDLE File; - // CStdInFileStream() File(INVALID_HANDLE_VALUE): {} - // void Open() { File = GetStdHandle(STD_INPUT_HANDLE); }; MY_UNKNOWN_IMP virtual ~CStdInFileStream() {} diff --git a/CPP/7zip/Common/FilterCoder.cpp b/CPP/7zip/Common/FilterCoder.cpp index 6b34260c..d9911085 100755 --- a/CPP/7zip/Common/FilterCoder.cpp +++ b/CPP/7zip/Common/FilterCoder.cpp @@ -2,12 +2,11 @@ #include "StdAfx.h" -#include "FilterCoder.h" -extern "C" -{ #include "../../../C/Alloc.h" -} + #include "../../Common/Defs.h" + +#include "FilterCoder.h" #include "StreamUtils.h" static const UInt32 kBufferSize = 1 << 17; diff --git a/CPP/7zip/Common/InBuffer.cpp b/CPP/7zip/Common/InBuffer.cpp index 29e3ea16..03924d2a 100755 --- a/CPP/7zip/Common/InBuffer.cpp +++ b/CPP/7zip/Common/InBuffer.cpp @@ -2,12 +2,9 @@ #include "StdAfx.h" -#include "InBuffer.h" +#include "../../../C/Alloc.h" -extern "C" -{ - #include "../../../C/Alloc.h" -} +#include "InBuffer.h" CInBuffer::CInBuffer(): _buffer(0), diff --git a/CPP/7zip/Common/InMemStream.h b/CPP/7zip/Common/InMemStream.h index adc5aadd..ec493977 100755 --- a/CPP/7zip/Common/InMemStream.h +++ b/CPP/7zip/Common/InMemStream.h @@ -1,11 +1,14 @@ // InMemStream.h -#ifndef __INMEMSTREAM_H -#define __INMEMSTREAM_H +#ifndef __IN_MEM_STREAM_H +#define __IN_MEM_STREAM_H #include <stdio.h> +#include "../../../C/Alloc.h" + #include "../../Common/MyCom.h" + #include "MemBlocks.h" class CIntListCheck diff --git a/CPP/7zip/Common/LimitedStreams.cpp b/CPP/7zip/Common/LimitedStreams.cpp index 490aa37b..1837e320 100755 --- a/CPP/7zip/Common/LimitedStreams.cpp +++ b/CPP/7zip/Common/LimitedStreams.cpp @@ -17,11 +17,116 @@ STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *p if (realProcessedSize == 0) _wasFinished = true; } - if(processedSize != NULL) + if (processedSize != NULL) *processedSize = realProcessedSize; return result; } +STDMETHODIMP CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + if (_virtPos >= _size) + return (_virtPos == _size) ? S_OK: E_FAIL; + UInt64 rem = _size - _virtPos; + if (rem < size) + size = (UInt32)rem; + UInt64 newPos = _startOffset + _virtPos; + if (newPos != _physPos) + { + _physPos = newPos; + RINOK(SeekToPhys()); + } + HRESULT res = _stream->Read(data, size, &size); + if (processedSize != NULL) + *processedSize = size; + _physPos += size; + _virtPos += size; + return res; +} + +STDMETHODIMP CLimitedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch(seekOrigin) + { + case STREAM_SEEK_SET: _virtPos = offset; break; + case STREAM_SEEK_CUR: _virtPos += offset; break; + case STREAM_SEEK_END: _virtPos = _size + offset; break; + default: return STG_E_INVALIDFUNCTION; + } + if (newPosition) + *newPosition = _virtPos; + return S_OK; +} + +STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + if (_virtPos >= Size) + return (_virtPos == Size) ? S_OK: E_FAIL; + + if (_curRem == 0) + { + UInt32 blockSize = (UInt32)1 << BlockSizeLog; + UInt32 virtBlock = (UInt32)(_virtPos >> BlockSizeLog); + UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1); + UInt32 phyBlock = Vector[virtBlock]; + UInt64 newPos = StartOffset + ((UInt64)phyBlock << BlockSizeLog) + offsetInBlock; + if (newPos != _physPos) + { + _physPos = newPos; + RINOK(SeekToPhys()); + } + _curRem = blockSize - offsetInBlock; + for (int i = 1; i < 64 && (virtBlock + i) < (UInt32)Vector.Size() && phyBlock + i == Vector[virtBlock + i]; i++) + _curRem += (UInt32)1 << BlockSizeLog; + UInt64 rem = Size - _virtPos; + if (_curRem > rem) + _curRem = (UInt32)rem; + } + if (size > _curRem) + size = _curRem; + HRESULT res = Stream->Read(data, size, &size); + if (processedSize != NULL) + *processedSize = size; + _physPos += size; + _virtPos += size; + _curRem -= size; + return res; +} + +STDMETHODIMP CClusterInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + UInt64 newVirtPos = offset; + switch(seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: newVirtPos += _virtPos; break; + case STREAM_SEEK_END: newVirtPos += Size; break; + default: return STG_E_INVALIDFUNCTION; + } + if (_virtPos != newVirtPos) + _curRem = 0; + _virtPos = newVirtPos; + if (newPosition) + *newPosition = newVirtPos; + return S_OK; +} + + +HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream) +{ + *resStream = 0; + CLimitedInStream *streamSpec = new CLimitedInStream; + CMyComPtr<ISequentialInStream> streamTemp = streamSpec; + streamSpec->SetStream(inStream); + RINOK(streamSpec->InitAndSeek(pos, size)); + streamSpec->SeekToStart(); + *resStream = streamTemp.Detach(); + return S_OK; +} + STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { HRESULT result = S_OK; @@ -29,12 +134,16 @@ STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, U *processedSize = 0; if (size > _size) { - size = (UInt32)_size; - if (size == 0) + if (_size == 0) { _overflow = true; - return E_FAIL; + if (!_overflowIsAllowed) + return E_FAIL; + if (processedSize != NULL) + *processedSize = size; + return S_OK; } + size = (UInt32)_size; } if (_stream) result = _stream->Write(data, size, &size); diff --git a/CPP/7zip/Common/LimitedStreams.h b/CPP/7zip/Common/LimitedStreams.h index 9bfdc8eb..f6900d51 100755 --- a/CPP/7zip/Common/LimitedStreams.h +++ b/CPP/7zip/Common/LimitedStreams.h @@ -1,9 +1,10 @@ // LimitedStreams.h -#ifndef __LIMITEDSTREAMS_H -#define __LIMITEDSTREAMS_H +#ifndef __LIMITED_STREAMS_H +#define __LIMITED_STREAMS_H #include "../../Common/MyCom.h" +#include "../../Common/MyVector.h" #include "../IStream.h" class CLimitedSequentialInStream: @@ -30,6 +31,73 @@ public: bool WasFinished() const { return _wasFinished; } }; +class CLimitedInStream: + public IInStream, + public CMyUnknownImp +{ + CMyComPtr<IInStream> _stream; + UInt64 _virtPos; + UInt64 _physPos; + UInt64 _size; + UInt64 _startOffset; + + HRESULT SeekToPhys() { return _stream->Seek(_physPos, STREAM_SEEK_SET, NULL); } +public: + void SetStream(IInStream *stream) { _stream = stream; } + HRESULT InitAndSeek(UInt64 startOffset, UInt64 size) + { + _startOffset = startOffset; + _physPos = startOffset; + _virtPos = 0; + _size = size; + return SeekToPhys(); + } + + MY_UNKNOWN_IMP1(IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + + HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); } +}; + +class CClusterInStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _virtPos; + UInt64 _physPos; + UInt32 _curRem; +public: + CMyComPtr<IInStream> Stream; + UInt64 StartOffset; + UInt64 Size; + int BlockSizeLog; + CRecordVector<UInt32> Vector; + + HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); } + + HRESULT InitAndSeek() + { + _curRem = 0; + _virtPos = 0; + _physPos = StartOffset; + if (Vector.Size() > 0) + { + _physPos = StartOffset + (Vector[0] << BlockSizeLog); + return SeekToPhys(); + } + return S_OK; + } + + MY_UNKNOWN_IMP1(IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + +HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream); + class CLimitedSequentialOutStream: public ISequentialOutStream, public CMyUnknownImp @@ -37,15 +105,17 @@ class CLimitedSequentialOutStream: CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; bool _overflow; + bool _overflowIsAllowed; public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } - void Init(UInt64 size) + void Init(UInt64 size, bool overflowIsAllowed = false) { _size = size; _overflow = false; + _overflowIsAllowed = overflowIsAllowed; } bool IsFinishedOK() const { return (_size == 0 && !_overflow); } UInt64 GetRem() const { return _size; } diff --git a/CPP/7zip/Common/MemBlocks.cpp b/CPP/7zip/Common/MemBlocks.cpp index baceb163..a5b93b5e 100755 --- a/CPP/7zip/Common/MemBlocks.cpp +++ b/CPP/7zip/Common/MemBlocks.cpp @@ -2,10 +2,10 @@ #include "StdAfx.h" -#include "Common/MyCom.h" +#include "../../../C/Alloc.h" -#include "StreamUtils.h" #include "MemBlocks.h" +#include "StreamUtils.h" bool CMemBlockManager::AllocateSpace(size_t numBlocks) { diff --git a/CPP/7zip/Common/MemBlocks.h b/CPP/7zip/Common/MemBlocks.h index dcdc0d82..e1058ae3 100755 --- a/CPP/7zip/Common/MemBlocks.h +++ b/CPP/7zip/Common/MemBlocks.h @@ -1,14 +1,8 @@ // MemBlocks.h -#ifndef __MEMBLOCKS_H -#define __MEMBLOCKS_H +#ifndef __MEM_BLOCKS_H +#define __MEM_BLOCKS_H -extern "C" -{ -#include "../../../C/Alloc.h" -} - -#include "Common/Types.h" #include "Common/MyVector.h" #include "Windows/Synchronization.h" diff --git a/CPP/7zip/Common/MethodProps.cpp b/CPP/7zip/Common/MethodProps.cpp index 86adc6b8..5836d0f8 100755 --- a/CPP/7zip/Common/MethodProps.cpp +++ b/CPP/7zip/Common/MethodProps.cpp @@ -8,14 +8,14 @@ #include "MethodProps.h" -static UInt64 k_LZMA = 0x030101; -// static UInt64 k_LZMA2 = 0x030102; +static const UInt64 k_LZMA = 0x030101; +static const UInt64 k_LZMA2 = 0x21; HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder) { bool tryReduce = false; UInt32 reducedDictionarySize = 1 << 10; - if (inSizeForReduce != 0 && (method.Id == k_LZMA /* || methodFull.MethodID == k_LZMA2 */)) + if (inSizeForReduce != 0 && (method.Id == k_LZMA || method.Id == k_LZMA2)) { for (;;) { diff --git a/CPP/7zip/Common/OutBuffer.cpp b/CPP/7zip/Common/OutBuffer.cpp index 998525c3..2e5debd8 100755 --- a/CPP/7zip/Common/OutBuffer.cpp +++ b/CPP/7zip/Common/OutBuffer.cpp @@ -1,13 +1,10 @@ -// OutByte.cpp +// OutBuffer.cpp #include "StdAfx.h" -#include "OutBuffer.h" +#include "../../../C/Alloc.h" -extern "C" -{ - #include "../../../C/Alloc.h" -} +#include "OutBuffer.h" bool COutBuffer::Create(UInt32 bufferSize) { diff --git a/CPP/7zip/Common/VirtThread.cpp b/CPP/7zip/Common/VirtThread.cpp index f12581ad..cf39bd02 100755 --- a/CPP/7zip/Common/VirtThread.cpp +++ b/CPP/7zip/Common/VirtThread.cpp @@ -40,6 +40,7 @@ CVirtThread::~CVirtThread() ExitEvent = true; if (StartEvent.IsCreated()) StartEvent.Set(); - Thread.Wait(); + if (Thread.IsCreated()) + Thread.Wait(); } diff --git a/CPP/7zip/Compress/BZip2Decoder.cpp b/CPP/7zip/Compress/BZip2Decoder.cpp index c44debf0..ef896f6a 100755 --- a/CPP/7zip/Compress/BZip2Decoder.cpp +++ b/CPP/7zip/Compress/BZip2Decoder.cpp @@ -2,10 +2,7 @@ #include "StdAfx.h" -extern "C" -{ #include "../../../C/Alloc.h" -} #include "../../Common/Defs.h" @@ -420,15 +417,19 @@ static UInt32 NO_INLINE DecodeBlock2Rand(const UInt32 *tt, UInt32 blockSize, UIn return crc.GetDigest(); } -#ifdef COMPRESS_BZIP2_MT -CDecoder::CDecoder(): - m_States(0) +CDecoder::CDecoder() { + #ifdef COMPRESS_BZIP2_MT + m_States = 0; m_NumThreadsPrev = 0; NumThreads = 1; + #endif; + _needInStreamInit = true; } +#ifdef COMPRESS_BZIP2_MT + CDecoder::~CDecoder() { Free(); @@ -611,43 +612,61 @@ HRESULT CDecoder::DecodeFile(bool &isBZ, ICompressProgressInfo *progress) } HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) + bool &isBZ, ICompressProgressInfo *progress) { + isBZ = false; + try + { + if (!m_InStream.Create(kBufferSize)) return E_OUTOFMEMORY; if (!m_OutStream.Create(kBufferSize)) return E_OUTOFMEMORY; - m_InStream.SetStream(inStream); - m_InStream.Init(); + if (inStream) + m_InStream.SetStream(inStream); + + CDecoderFlusher flusher(this, inStream != NULL); + + if (_needInStreamInit) + { + m_InStream.Init(); + _needInStreamInit = false; + } + _inStart = m_InStream.GetProcessedSize(); + + m_InStream.AlignToByte(); m_OutStream.SetStream(outStream); m_OutStream.Init(); - CDecoderFlusher flusher(this); - - bool isBZ; RINOK(DecodeFile(isBZ, progress)); - return isBZ ? S_OK: S_FALSE; -} + flusher.NeedFlush = false; + return Flush(); -STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) -{ - try { return CodeReal(inStream, outStream, inSize, outSize, progress); } + } catch(const CInBufferException &e) { return e.ErrorCode; } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return E_FAIL; } } -STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) { - if (value == NULL) - return E_INVALIDARG; - *value = m_InStream.GetProcessedSize(); - return S_OK; + _needInStreamInit = true; + bool isBZ; + RINOK(CodeReal(inStream, outStream, isBZ, progress)); + return isBZ ? S_OK : S_FALSE; } +HRESULT CDecoder::CodeResume(ISequentialOutStream *outStream, bool &isBZ, ICompressProgressInfo *progress) +{ + return CodeReal(NULL, outStream, isBZ, progress); +} + +STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { m_InStream.SetStream(inStream); return S_OK; } +STDMETHODIMP CDecoder::ReleaseInStream() { m_InStream.ReleaseStream(); return S_OK; } + #ifdef COMPRESS_BZIP2_MT static THREAD_FUNC_DECL MFThread(void *p) { ((CState *)p)->ThreadFunc(); return 0; } @@ -694,7 +713,7 @@ void CState::ThreadFunc() nextBlockIndex = 0; Decoder->NextBlockIndex = nextBlockIndex; UInt32 crc; - UInt64 packSize; + UInt64 packSize = 0; UInt32 blockSize = 0, origPtr = 0; bool randMode = false; @@ -752,8 +771,9 @@ void CState::ThreadFunc() { if (Decoder->Progress) { + UInt64 inSize = packSize - Decoder->_inStart; UInt64 unpackSize = Decoder->m_OutStream.GetProcessedSize(); - res = Decoder->Progress->SetRatioInfo(&packSize, &unpackSize); + res = Decoder->Progress->SetRatioInfo(&inSize, &unpackSize); } } else diff --git a/CPP/7zip/Compress/BZip2Decoder.h b/CPP/7zip/Compress/BZip2Decoder.h index 195b6b38..ea06449e 100755 --- a/CPP/7zip/Compress/BZip2Decoder.h +++ b/CPP/7zip/Compress/BZip2Decoder.h @@ -62,7 +62,6 @@ class CDecoder : #ifdef COMPRESS_BZIP2_MT public ICompressSetCoderMt, #endif - public ICompressGetInStreamProcessedSize, public CMyUnknownImp { public: @@ -71,9 +70,11 @@ public: NBitm::CDecoder<CInBuffer> m_InStream; Byte m_Selectors[kNumSelectorsMax]; CHuffmanDecoder m_HuffmanDecoders[kNumTablesMax]; + UInt64 _inStart; + private: - UInt32 m_NumThreadsPrev; + bool _needInStreamInit; UInt32 ReadBits(int numBits); Byte ReadByte(); @@ -82,18 +83,22 @@ private: HRESULT PrepareBlock(CState &state); HRESULT DecodeFile(bool &isBZ, ICompressProgressInfo *progress); HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + bool &isBZ, ICompressProgressInfo *progress); class CDecoderFlusher { CDecoder *_decoder; public: bool NeedFlush; - CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {} + bool ReleaseInStream; + CDecoderFlusher(CDecoder *decoder, bool releaseInStream): + _decoder(decoder), + ReleaseInStream(releaseInStream), + NeedFlush(true) {} ~CDecoderFlusher() { if (NeedFlush) _decoder->Flush(); - _decoder->ReleaseStreams(); + _decoder->ReleaseStreams(ReleaseInStream); } }; @@ -103,6 +108,7 @@ public: #ifdef COMPRESS_BZIP2_MT ICompressProgressInfo *Progress; CState *m_States; + UInt32 m_NumThreadsPrev; NWindows::NSynchronization::CManualResetEvent CanProcessEvent; NWindows::NSynchronization::CCriticalSection CS; @@ -118,7 +124,6 @@ public: HRESULT Result2; UInt32 BlockSizeMax; - CDecoder(); ~CDecoder(); HRESULT Create(); void Free(); @@ -127,28 +132,37 @@ public: CState m_States[1]; #endif + CDecoder(); + HRESULT ReadSignatures(bool &wasFinished, UInt32 &crc); HRESULT Flush() { return m_OutStream.Flush(); } - void ReleaseStreams() + void ReleaseStreams(bool releaseInStream) { - m_InStream.ReleaseStream(); + if (releaseInStream) + m_InStream.ReleaseStream(); m_OutStream.ReleaseStream(); } + MY_QUERYINTERFACE_BEGIN #ifdef COMPRESS_BZIP2_MT - MY_UNKNOWN_IMP2(ICompressSetCoderMt, ICompressGetInStreamProcessedSize) - #else - MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize) + MY_QUERYINTERFACE_ENTRY(ICompressSetCoderMt) #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); - STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream)(); + HRESULT CodeResume(ISequentialOutStream *outStream, bool &isBZ, ICompressProgressInfo *progress); + UInt64 GetInputProcessedSize() const { return m_InStream.GetProcessedSize(); } + #ifdef COMPRESS_BZIP2_MT STDMETHOD(SetNumberOfThreads)(UInt32 numThreads); #endif diff --git a/CPP/7zip/Compress/BZip2Encoder.cpp b/CPP/7zip/Compress/BZip2Encoder.cpp index ef284a33..0546c15c 100755 --- a/CPP/7zip/Compress/BZip2Encoder.cpp +++ b/CPP/7zip/Compress/BZip2Encoder.cpp @@ -2,12 +2,9 @@ #include "StdAfx.h" -extern "C" -{ #include "../../../C/Alloc.h" #include "../../../C/BwtSort.h" #include "../../../C/HuffEnc.h" -} #include "BZip2Crc.h" #include "BZip2Encoder.h" @@ -823,7 +820,7 @@ HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * WriteByte(kFinSig5); WriteCrc(CombinedCrc.GetDigest()); - return S_OK; + return Flush(); } STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, diff --git a/CPP/7zip/Compress/BZip2Encoder.h b/CPP/7zip/Compress/BZip2Encoder.h index 1dda0aa8..a79813f3 100755 --- a/CPP/7zip/Compress/BZip2Encoder.h +++ b/CPP/7zip/Compress/BZip2Encoder.h @@ -1,4 +1,4 @@ -// Compress/BZip2Encoder.h +// BZip2Encoder.h #ifndef __COMPRESS_BZIP2_ENCODER_H #define __COMPRESS_BZIP2_ENCODER_H @@ -215,12 +215,9 @@ public: { CEncoder *_coder; public: - bool NeedFlush; - CFlusher(CEncoder *coder): _coder(coder), NeedFlush(true) {} + CFlusher(CEncoder *coder): _coder(coder) {} ~CFlusher() { - if (NeedFlush) - _coder->Flush(); _coder->ReleaseStreams(); } }; diff --git a/CPP/7zip/Compress/Bcj2Coder.cpp b/CPP/7zip/Compress/Bcj2Coder.cpp index e1356abb..13ce5160 100755 --- a/CPP/7zip/Compress/Bcj2Coder.cpp +++ b/CPP/7zip/Compress/Bcj2Coder.cpp @@ -2,10 +2,7 @@ #include "StdAfx.h" -extern "C" -{ #include "../../../C/Alloc.h" -} #include "Bcj2Coder.h" diff --git a/CPP/7zip/Compress/BcjCoder.h b/CPP/7zip/Compress/BcjCoder.h index 612bb547..0754bcd2 100755 --- a/CPP/7zip/Compress/BcjCoder.h +++ b/CPP/7zip/Compress/BcjCoder.h @@ -3,10 +3,7 @@ #ifndef __COMPRESS_BCJ_CODER_H #define __COMPRESS_BCJ_CODER_H -extern "C" -{ #include "../../../C/Bra.h" -} #include "BranchCoder.h" diff --git a/CPP/7zip/Compress/BitlDecoder.h b/CPP/7zip/Compress/BitlDecoder.h index 0ccd7154..3bee413a 100755 --- a/CPP/7zip/Compress/BitlDecoder.h +++ b/CPP/7zip/Compress/BitlDecoder.h @@ -35,15 +35,11 @@ public: m_Value = 0; NumExtraBytes = 0; } - UInt64 GetProcessedSize() const - { return m_Stream.GetProcessedSize() - (kNumBigValueBits - m_BitPos) / 8; } - UInt64 GetProcessedBitsSize() const - { return (m_Stream.GetProcessedSize() << 3) - (kNumBigValueBits - m_BitPos); } - int GetBitPosition() const { return (m_BitPos & 7); } + UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() + NumExtraBytes - (kNumBigValueBits - m_BitPos) / 8; } void Normalize() { - for (;m_BitPos >= 8; m_BitPos -= 8) + for (; m_BitPos >= 8; m_BitPos -= 8) { Byte b = 0; if (!m_Stream.ReadByte(b)) @@ -114,10 +110,31 @@ public: UInt32 ReadBits(int numBits) { Normalize(); - UInt32 res = m_NormalValue & ( (1 << numBits) - 1); + UInt32 res = m_NormalValue & ((1 << numBits) - 1); MovePos(numBits); return res; } + + void AlignToByte() { MovePos((32 - this->m_BitPos) & 7); } + + Byte ReadByte() + { + if (this->m_BitPos == kNumBigValueBits) + { + Byte b = 0; + if (!this->m_Stream.ReadByte(b)) + { + b = 0xFF; + this->NumExtraBytes++; + } + return b; + } + { + Byte b = (Byte)(m_NormalValue & 0xFF); + MovePos(8); + return b; + } + } }; } diff --git a/CPP/7zip/Compress/BitmDecoder.h b/CPP/7zip/Compress/BitmDecoder.h index fbe4c949..2885ed78 100755 --- a/CPP/7zip/Compress/BitmDecoder.h +++ b/CPP/7zip/Compress/BitmDecoder.h @@ -31,9 +31,7 @@ public: Normalize(); } - UInt64 GetProcessedSize() const - { return m_Stream.GetProcessedSize() - (kNumBigValueBits - m_BitPos) / 8; } - UInt32 GetBitPosition() const { return (m_BitPos & 7); } + UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() - (kNumBigValueBits - m_BitPos) / 8; } void Normalize() { @@ -59,6 +57,8 @@ public: MovePos(numBits); return res; } + + void AlignToByte() { MovePos((32 - m_BitPos) & 7); } }; } diff --git a/CPP/7zip/Compress/BranchMisc.cpp b/CPP/7zip/Compress/BranchMisc.cpp index 5a19c44a..423b723a 100755 --- a/CPP/7zip/Compress/BranchMisc.cpp +++ b/CPP/7zip/Compress/BranchMisc.cpp @@ -2,10 +2,7 @@ #include "StdAfx.h" -extern "C" -{ #include "../../../C/Bra.h" -} #include "BranchMisc.h" diff --git a/CPP/7zip/Compress/ByteSwap.cpp b/CPP/7zip/Compress/ByteSwap.cpp index 3f252f2c..645b6ffc 100755 --- a/CPP/7zip/Compress/ByteSwap.cpp +++ b/CPP/7zip/Compress/ByteSwap.cpp @@ -2,7 +2,31 @@ #include "StdAfx.h" -#include "ByteSwap.h" +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +#include "../Common/RegisterCodec.h" + +class CByteSwap2: + public ICompressFilter, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + STDMETHOD(Init)(); + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); +}; + +class CByteSwap4: + public ICompressFilter, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + STDMETHOD(Init)(); + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); +}; STDMETHODIMP CByteSwap2::Init() { return S_OK; } @@ -36,3 +60,14 @@ STDMETHODIMP_(UInt32) CByteSwap4::Filter(Byte *data, UInt32 size) } return i; } + +static void *CreateCodec2() { return (void *)(ICompressFilter *)(new CByteSwap2); } +static void *CreateCodec4() { return (void *)(ICompressFilter *)(new CByteSwap4); } + +static CCodecInfo g_CodecsInfo[] = +{ + { CreateCodec2, CreateCodec2, 0x020302, L"Swap2", 1, true }, + { CreateCodec4, CreateCodec4, 0x020304, L"Swap4", 1, true } +}; + +REGISTER_CODECS(ByteSwap) diff --git a/CPP/7zip/Compress/ByteSwap.h b/CPP/7zip/Compress/ByteSwap.h deleted file mode 100755 index f13bec80..00000000 --- a/CPP/7zip/Compress/ByteSwap.h +++ /dev/null @@ -1,30 +0,0 @@ -// ByteSwap.h - -#ifndef __COMPRESS_BYTE_SWAP_H -#define __COMPRESS_BYTE_SWAP_H - -#include "../../Common/MyCom.h" - -#include "../ICoder.h" - -class CByteSwap2: - public ICompressFilter, - public CMyUnknownImp -{ -public: - MY_UNKNOWN_IMP - STDMETHOD(Init)(); - STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); -}; - -class CByteSwap4: - public ICompressFilter, - public CMyUnknownImp -{ -public: - MY_UNKNOWN_IMP - STDMETHOD(Init)(); - STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); -}; - -#endif diff --git a/CPP/7zip/Compress/ByteSwapRegister.cpp b/CPP/7zip/Compress/ByteSwapRegister.cpp deleted file mode 100755 index e3405ca0..00000000 --- a/CPP/7zip/Compress/ByteSwapRegister.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// ByteSwapRegister.cpp - -#include "StdAfx.h" - -#include "../Common/RegisterCodec.h" - -#include "ByteSwap.h" - -static void *CreateCodec2() { return (void *)(ICompressFilter *)(new CByteSwap2); } -static void *CreateCodec4() { return (void *)(ICompressFilter *)(new CByteSwap4); } - -static CCodecInfo g_CodecsInfo[] = -{ - { CreateCodec2, CreateCodec4, 0x020302, L"Swap2", 1, true }, - { CreateCodec4, CreateCodec4, 0x020304, L"Swap4", 1, true } -}; - -REGISTER_CODECS(ByteSwap) diff --git a/CPP/7zip/Compress/CodecExports.cpp b/CPP/7zip/Compress/CodecExports.cpp index cd7a209c..4ff1c0fc 100755 --- a/CPP/7zip/Compress/CodecExports.cpp +++ b/CPP/7zip/Compress/CodecExports.cpp @@ -3,10 +3,13 @@ #include "StdAfx.h" #include "../../Common/ComTry.h" + #include "../../Windows/PropVariant.h" -#include "../Common/RegisterCodec.h" + #include "../ICoder.h" +#include "../Common/RegisterCodec.h" + extern unsigned int g_NumCodecs; extern const CCodecInfo *g_Codecs[]; diff --git a/CPP/7zip/Compress/CopyCoder.cpp b/CPP/7zip/Compress/CopyCoder.cpp index 899ffa3a..f71692a7 100755 --- a/CPP/7zip/Compress/CopyCoder.cpp +++ b/CPP/7zip/Compress/CopyCoder.cpp @@ -2,10 +2,7 @@ #include "StdAfx.h" -extern "C" -{ #include "../../../C/Alloc.h" -} #include "../Common/StreamUtils.h" @@ -35,16 +32,18 @@ STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, TotalSize = 0; for (;;) { - UInt32 realProcessedSize; UInt32 size = kBufferSize; if (outSize != 0) if (size > *outSize - TotalSize) size = (UInt32)(*outSize - TotalSize); - RINOK(inStream->Read(_buffer, size, &realProcessedSize)); - if (realProcessedSize == 0) + RINOK(inStream->Read(_buffer, size, &size)); + if (size == 0) break; - RINOK(WriteStream(outStream, _buffer, realProcessedSize)); - TotalSize += realProcessedSize; + if (outStream) + { + RINOK(WriteStream(outStream, _buffer, size)); + } + TotalSize += size; if (progress != NULL) { RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize)); @@ -59,4 +58,10 @@ STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value) return S_OK; } +HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress) +{ + CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder; + return copyCoder->Code(inStream, outStream, NULL, NULL, progress); +} + } diff --git a/CPP/7zip/Compress/CopyCoder.h b/CPP/7zip/Compress/CopyCoder.h index c5736781..c5445ccf 100755 --- a/CPP/7zip/Compress/CopyCoder.h +++ b/CPP/7zip/Compress/CopyCoder.h @@ -17,7 +17,7 @@ class CCopyCoder: Byte *_buffer; public: UInt64 TotalSize; - CCopyCoder(): TotalSize(0) , _buffer(0) {}; + CCopyCoder(): TotalSize(0), _buffer(0) {}; ~CCopyCoder(); MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize) @@ -27,6 +27,8 @@ public: STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); }; +HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress); + } #endif diff --git a/CPP/7zip/Compress/DeflateDecoder.cpp b/CPP/7zip/Compress/DeflateDecoder.cpp index dae60c07..cf4a5105 100755 --- a/CPP/7zip/Compress/DeflateDecoder.cpp +++ b/CPP/7zip/Compress/DeflateDecoder.cpp @@ -15,6 +15,7 @@ CCoder::CCoder(bool deflate64Mode, bool deflateNSIS): _deflate64Mode(deflate64Mode), _deflateNSIS(deflateNSIS), _keepHistory(false), + _needInitInStream(true), ZlibMode(false) {} UInt32 CCoder::ReadBits(int numBits) @@ -70,9 +71,7 @@ bool CCoder::ReadTables(void) if (blockType == NBlockType::kStored) { m_StoredMode = true; - UInt32 currentBitPosition = m_InBitStream.GetBitPosition(); - int numBitsForAlign = (int)(currentBitPosition > 0 ? (8 - currentBitPosition): 0); - ReadBits(numBitsForAlign); + m_InBitStream.AlignToByte(); m_StoredBlockSize = ReadBits(kStoredBlockLengthFieldSize); if (_deflateNSIS) return true; @@ -130,10 +129,8 @@ HRESULT CCoder::CodeSpec(UInt32 curSize) if (!_keepHistory) if (!m_OutWindowStream.Create(_deflate64Mode ? kHistorySize64: kHistorySize32)) return E_OUTOFMEMORY; - if (!m_InBitStream.Create(1 << 17)) - return E_OUTOFMEMORY; + RINOK(InitInStream(_needInitInStream)); m_OutWindowStream.Init(_keepHistory); - m_InBitStream.Init(); m_FinalBlock = false; _remainLen = 0; _needReadTable = true; @@ -167,7 +164,7 @@ HRESULT CCoder::CodeSpec(UInt32 curSize) if(m_StoredMode) { for (; m_StoredBlockSize > 0 && curSize > 0; m_StoredBlockSize--, curSize--) - m_OutWindowStream.PutByte((Byte)m_InBitStream.ReadBits(8)); + m_OutWindowStream.PutByte(m_InBitStream.ReadByte()); _needReadTable = (m_StoredBlockSize == 0); continue; } @@ -231,14 +228,29 @@ HRESULT CCoder::CodeSpec(UInt32 curSize) return S_OK; } -HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 *, const UInt64 *outSize, ICompressProgressInfo *progress) +#ifdef _NO_EXCEPTIONS + +#define DEFLATE_TRY_BEGIN +#define DEFLATE_TRY_END + +#else + +#define DEFLATE_TRY_BEGIN try { +#define DEFLATE_TRY_END } \ + catch(const CInBufferException &e) { return e.ErrorCode; } \ + catch(const CLzOutWindowException &e) { return e.ErrorCode; } \ + catch(...) { return S_FALSE; } + +#endif + +HRESULT CCoder::CodeReal(ISequentialOutStream *outStream, + const UInt64 *outSize, ICompressProgressInfo *progress) { - SetInStream(inStream); + DEFLATE_TRY_BEGIN m_OutWindowStream.SetStream(outStream); - SetOutStreamSize(outSize); CCoderReleaser flusher(this); + const UInt64 inStart = m_InBitStream.GetProcessedSize(); const UInt64 start = m_OutWindowStream.GetProcessedSize(); for (;;) { @@ -256,45 +268,33 @@ HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *ou break; if (progress != NULL) { - const UInt64 inSize = m_InBitStream.GetProcessedSize(); + const UInt64 inSize = m_InBitStream.GetProcessedSize() - inStart; const UInt64 nowPos64 = m_OutWindowStream.GetProcessedSize() - start; RINOK(progress->SetRatioInfo(&inSize, &nowPos64)); } } if (_remainLen == kLenIdFinished && ZlibMode) { - UInt32 currentBitPosition = m_InBitStream.GetBitPosition(); - int numBitsForAlign = (int)(currentBitPosition > 0 ? (8 - currentBitPosition): 0); - ReadBits(numBitsForAlign); + m_InBitStream.AlignToByte(); for (int i = 0; i < 4; i++) - ZlibFooter[i] = (Byte)m_InBitStream.ReadBits(8); + ZlibFooter[i] = m_InBitStream.ReadByte(); } flusher.NeedFlush = false; - return Flush(); + HRESULT res = Flush(); + if (res == S_OK && InputEofError()) + return S_FALSE; + return res; + DEFLATE_TRY_END } - -#ifdef _NO_EXCEPTIONS - -#define DEFLATE_TRY_BEGIN -#define DEFLATE_TRY_END - -#else - -#define DEFLATE_TRY_BEGIN try { -#define DEFLATE_TRY_END } \ - catch(const CInBufferException &e) { return e.ErrorCode; } \ - catch(const CLzOutWindowException &e) { return e.ErrorCode; } \ - catch(...) { return S_FALSE; } - -#endif - HRESULT CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) + const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { - DEFLATE_TRY_BEGIN - return CodeReal(inStream, outStream, inSize, outSize, progress); - DEFLATE_TRY_END + SetInStream(inStream); + SetOutStreamSize(outSize); + HRESULT res = CodeReal(outStream, outSize, progress); + ReleaseInStream(); + return res; } STDMETHODIMP CCoder::GetInStreamProcessedSize(UInt64 *value) @@ -320,6 +320,7 @@ STDMETHODIMP CCoder::ReleaseInStream() STDMETHODIMP CCoder::SetOutStreamSize(const UInt64 * /* outSize */) { _remainLen = kLenIdNeedInit; + _needInitInStream = true; m_OutWindowStream.Init(_keepHistory); return S_OK; } @@ -342,4 +343,11 @@ STDMETHODIMP CCoder::Read(void *data, UInt32 size, UInt32 *processedSize) #endif +STDMETHODIMP CCoder::CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + _remainLen = kLenIdNeedInit; + m_OutWindowStream.Init(_keepHistory); + return CodeReal(outStream, outSize, progress); +} + }}} diff --git a/CPP/7zip/Compress/DeflateDecoder.h b/CPP/7zip/Compress/DeflateDecoder.h index 796d90a4..56ab2bea 100755 --- a/CPP/7zip/Compress/DeflateDecoder.h +++ b/CPP/7zip/Compress/DeflateDecoder.h @@ -44,6 +44,7 @@ class CCoder: bool _deflateNSIS; bool _deflate64Mode; bool _keepHistory; + bool _needInitInStream; Int32 _remainLen; UInt32 _rep0; bool _needReadTable; @@ -53,24 +54,18 @@ class CCoder: bool DeCodeLevelTable(Byte *values, int numSymbols); bool ReadTables(); - void ReleaseStreams() - { - m_OutWindowStream.ReleaseStream(); - ReleaseInStream(); - } - HRESULT Flush() { return m_OutWindowStream.Flush(); } class CCoderReleaser { - CCoder *m_Coder; + CCoder *_coder; public: bool NeedFlush; - CCoderReleaser(CCoder *coder): m_Coder(coder), NeedFlush(true) {} + CCoderReleaser(CCoder *coder): _coder(coder), NeedFlush(true) {} ~CCoderReleaser() { if (NeedFlush) - m_Coder->Flush(); - m_Coder->ReleaseStreams(); + _coder->Flush(); + _coder->ReleaseOutStream(); } }; friend class CCoderReleaser; @@ -81,10 +76,17 @@ public: Byte ZlibFooter[4]; CCoder(bool deflate64Mode, bool deflateNSIS = false); + virtual ~CCoder() {}; + void SetKeepHistory(bool keepHistory) { _keepHistory = keepHistory; } - HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + void ReleaseOutStream() + { + m_OutWindowStream.ReleaseStream(); + } + + HRESULT CodeReal(ISequentialOutStream *outStream, + const UInt64 *outSize, ICompressProgressInfo *progress); #ifndef NO_READ_FROM_CODER MY_UNKNOWN_IMP4( @@ -109,6 +111,25 @@ public: STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); #endif + STDMETHOD(CodeResume)(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress); + + HRESULT InitInStream(bool needInit) + { + if (!m_InBitStream.Create(1 << 17)) + return E_OUTOFMEMORY; + if (needInit) + { + m_InBitStream.Init(); + _needInitInStream = false; + } + return S_OK; + } + + void AlignToByte() { m_InBitStream.AlignToByte(); } + Byte ReadByte() { return (Byte)m_InBitStream.ReadBits(8); } + bool InputEofError() const { return m_InBitStream.ExtraBitsWereRead(); } + UInt64 GetInputProcessedSize() const { return m_InBitStream.GetProcessedSize(); } + // IGetInStreamProcessedSize STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); }; diff --git a/CPP/7zip/Compress/DeflateEncoder.cpp b/CPP/7zip/Compress/DeflateEncoder.cpp index b5c70969..28906e8c 100755 --- a/CPP/7zip/Compress/DeflateEncoder.cpp +++ b/CPP/7zip/Compress/DeflateEncoder.cpp @@ -2,11 +2,8 @@ #include "StdAfx.h" -extern "C" -{ #include "../../../C/Alloc.h" #include "../../../C/HuffEnc.h" -} #include "Common/ComTry.h" diff --git a/CPP/7zip/Compress/DeflateEncoder.h b/CPP/7zip/Compress/DeflateEncoder.h index 2790bcc7..71c39e4e 100755 --- a/CPP/7zip/Compress/DeflateEncoder.h +++ b/CPP/7zip/Compress/DeflateEncoder.h @@ -3,10 +3,7 @@ #ifndef __DEFLATE_ENCODER_H #define __DEFLATE_ENCODER_H -extern "C" -{ - #include "../../../C/LzFind.h" -} +#include "../../../C/LzFind.h" #include "Common/MyCom.h" diff --git a/CPP/7zip/Compress/DeltaFilter.cpp b/CPP/7zip/Compress/DeltaFilter.cpp new file mode 100755 index 00000000..2e421acf --- /dev/null +++ b/CPP/7zip/Compress/DeltaFilter.cpp @@ -0,0 +1,112 @@ +// DeltaFilter.cpp + +#include "StdAfx.h" + +#include "../../../C/Delta.h" + +#include "../Common/RegisterCodec.h" + +#include "BranchCoder.h" + +struct CDelta +{ + unsigned _delta; + Byte _state[DELTA_STATE_SIZE]; + CDelta(): _delta(1) {} + void DeltaInit() { Delta_Init(_state); } +}; + +class CDeltaEncoder: + public ICompressFilter, + public ICompressSetCoderProperties, + public ICompressWriteCoderProperties, + CDelta, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties) + STDMETHOD(Init)(); + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); + STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); +}; + +class CDeltaDecoder: + public ICompressFilter, + public ICompressSetDecoderProperties2, + CDelta, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2) + STDMETHOD(Init)(); + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); +}; + +STDMETHODIMP CDeltaEncoder::Init() +{ + DeltaInit(); + return S_OK; +} + +STDMETHODIMP_(UInt32) CDeltaEncoder::Filter(Byte *data, UInt32 size) +{ + Delta_Encode(_state, _delta, data, size); + return size; +} + +STDMETHODIMP CDeltaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) +{ + UInt32 delta = _delta; + for (UInt32 i = 0; i < numProps; i++) + { + const PROPVARIANT &prop = props[i]; + if (propIDs[i] != NCoderPropID::kDefaultProp || prop.vt != VT_UI4 || prop.ulVal < 1 || prop.ulVal > 256) + return E_INVALIDARG; + delta = prop.ulVal; + } + _delta = delta; + return S_OK; +} + +STDMETHODIMP CDeltaEncoder::WriteCoderProperties(ISequentialOutStream *outStream) +{ + Byte prop = (Byte)(_delta - 1); + return outStream->Write(&prop, 1, NULL); +} + +STDMETHODIMP CDeltaDecoder::Init() +{ + DeltaInit(); + return S_OK; +} + +STDMETHODIMP_(UInt32) CDeltaDecoder::Filter(Byte *data, UInt32 size) +{ + Delta_Decode(_state, _delta, data, size); + return size; +} + +STDMETHODIMP CDeltaDecoder::SetDecoderProperties2(const Byte *props, UInt32 size) +{ + if (size != 1) + return E_INVALIDARG; + _delta = (unsigned)props[0] + 1; + return S_OK; +} + +#define CREATE_CODEC(x) \ + static void *CreateCodec ## x() { return (void *)(ICompressFilter *)(new C ## x ## Decoder); } \ + static void *CreateCodec ## x ## Out() { return (void *)(ICompressFilter *)(new C ## x ## Encoder); } + +CREATE_CODEC(Delta) + +#define METHOD_ITEM(x, id, name) { CreateCodec ## x, CreateCodec ## x ## Out, id, name, 1, true } + +static CCodecInfo g_CodecsInfo[] = +{ + METHOD_ITEM(Delta, 3, L"Delta") +}; + +REGISTER_CODECS(Delta) diff --git a/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsp b/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsp index 76fa7b84..9b005efb 100755 --- a/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsp +++ b/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsp @@ -297,6 +297,14 @@ SOURCE=..\..\..\Common\Types.h # PROP Default_Filter "" # Begin Source File +SOURCE=..\..\Common\CWrappers.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CWrappers.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/Compress/LZMA_Alone/LzmaAlone.cpp b/CPP/7zip/Compress/LZMA_Alone/LzmaAlone.cpp index 4044c86d..3d8e475f 100755 --- a/CPP/7zip/Compress/LZMA_Alone/LzmaAlone.cpp +++ b/CPP/7zip/Compress/LZMA_Alone/LzmaAlone.cpp @@ -31,13 +31,10 @@ #include "../../../Windows/System.h" #endif -extern "C" -{ - #include "../../../../C/7zVersion.h" - #include "../../../../C/Alloc.h" - #include "../../../../C/LzmaUtil/Lzma86Dec.h" - #include "../../../../C/LzmaUtil/Lzma86Enc.h" -} +#include "../../../../C/7zVersion.h" +#include "../../../../C/Alloc.h" +#include "../../../../C/LzmaUtil/Lzma86Dec.h" +#include "../../../../C/LzmaUtil/Lzma86Enc.h" using namespace NCommandLineParser; diff --git a/CPP/7zip/Compress/LZMA_Alone/LzmaBench.cpp b/CPP/7zip/Compress/LZMA_Alone/LzmaBench.cpp index 2ad9a577..6a325fe0 100755 --- a/CPP/7zip/Compress/LZMA_Alone/LzmaBench.cpp +++ b/CPP/7zip/Compress/LZMA_Alone/LzmaBench.cpp @@ -28,11 +28,8 @@ #endif #endif -extern "C" -{ #include "../../../../C/7zCrc.h" #include "../../../../C/Alloc.h" -} #include "../../../Common/MyCom.h" @@ -575,22 +572,22 @@ HRESULT CEncoderInfo::Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandom PROPID propIDs[] = { NCoderPropID::kDictionarySize, - NCoderPropID::kMultiThread + NCoderPropID::kNumThreads }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); - PROPVARIANT properties[kNumProps]; - properties[0].vt = VT_UI4; - properties[0].ulVal = (UInt32)dictionarySize; + PROPVARIANT props[kNumProps]; + props[0].vt = VT_UI4; + props[0].ulVal = dictionarySize; - properties[1].vt = VT_BOOL; - properties[1].boolVal = (numThreads > 1) ? VARIANT_TRUE : VARIANT_FALSE; + props[1].vt = VT_UI4; + props[1].ulVal = numThreads; { CMyComPtr<ICompressSetCoderProperties> setCoderProperties; RINOK(encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties)); if (!setCoderProperties) return E_FAIL; - RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, kNumProps)); + RINOK(setCoderProperties->SetCoderProperties(propIDs, props, kNumProps)); CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; encoder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProperties); diff --git a/CPP/7zip/Compress/LZMA_Alone/makefile b/CPP/7zip/Compress/LZMA_Alone/makefile index 1c4baa0b..f6d94081 100755 --- a/CPP/7zip/Compress/LZMA_Alone/makefile +++ b/CPP/7zip/Compress/LZMA_Alone/makefile @@ -26,6 +26,7 @@ WIN_OBJS = \ $O\System.obj 7ZIP_COMMON_OBJS = \ + $O\CWrappers.obj \ $O\InBuffer.obj \ $O\OutBuffer.obj \ $O\StreamUtils.obj \ diff --git a/CPP/7zip/Compress/Lzma2Decoder.cpp b/CPP/7zip/Compress/Lzma2Decoder.cpp new file mode 100755 index 00000000..322015e2 --- /dev/null +++ b/CPP/7zip/Compress/Lzma2Decoder.cpp @@ -0,0 +1,189 @@ +// Lzma2Decoder.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "../Common/StreamUtils.h" + +#include "Lzma2Decoder.h" + +static HRESULT SResToHRESULT(SRes res) +{ + switch(res) + { + case SZ_OK: return S_OK; + case SZ_ERROR_MEM: return E_OUTOFMEMORY; + case SZ_ERROR_PARAM: return E_INVALIDARG; + // case SZ_ERROR_PROGRESS: return E_ABORT; + case SZ_ERROR_DATA: return S_FALSE; + } + return E_FAIL; +} + +namespace NCompress { +namespace NLzma2 { + +static const UInt32 kInBufSize = 1 << 20; + +CDecoder::CDecoder(): _inBuf(0), _outSizeDefined(false) +{ + Lzma2Dec_Construct(&_state); +} + +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 }; + +CDecoder::~CDecoder() +{ + Lzma2Dec_Free(&_state, &g_Alloc); + MyFree(_inBuf); +} + +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size) +{ + if (size != 1) return SZ_ERROR_UNSUPPORTED; + RINOK(SResToHRESULT(Lzma2Dec_Allocate(&_state, prop[0], &g_Alloc))); + if (_inBuf == 0) + { + _inBuf = (Byte *)MyAlloc(kInBufSize); + if (_inBuf == 0) + return E_OUTOFMEMORY; + } + + return S_OK; +} + +STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { *value = _inSizeProcessed; return S_OK; } +STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; } +STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; } + +STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) +{ + _outSizeDefined = (outSize != NULL); + if (_outSizeDefined) + _outSize = *outSize; + + Lzma2Dec_Init(&_state); + + _inPos = _inSize = 0; + _inSizeProcessed = _outSizeProcessed = 0; + return S_OK; +} + +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 * /* inSize */, + const UInt64 *outSize, ICompressProgressInfo *progress) +{ + if (_inBuf == 0) + return S_FALSE; + SetOutStreamSize(outSize); + + for (;;) + { + if (_inPos == _inSize) + { + _inPos = _inSize = 0; + RINOK(inStream->Read(_inBuf, kInBufSize, &_inSize)); + } + + SizeT dicPos = _state.decoder.dicPos; + SizeT curSize = _state.decoder.dicBufSize - dicPos; + const UInt32 kStepSize = ((UInt32)1 << 22); + if (curSize > kStepSize) + curSize = (SizeT)kStepSize; + + ELzmaFinishMode finishMode = LZMA_FINISH_ANY; + if (_outSizeDefined) + { + const UInt64 rem = _outSize - _outSizeProcessed; + if (rem < curSize) + { + curSize = (SizeT)rem; + /* + // finishMode = LZMA_FINISH_END; + we can't use LZMA_FINISH_END here to allow partial decoding + */ + } + } + + SizeT inSizeProcessed = _inSize - _inPos; + ELzmaStatus status; + SRes res = Lzma2Dec_DecodeToDic(&_state, dicPos + curSize, _inBuf + _inPos, &inSizeProcessed, finishMode, &status); + + _inPos += (UInt32)inSizeProcessed; + _inSizeProcessed += inSizeProcessed; + SizeT outSizeProcessed = _state.decoder.dicPos - dicPos; + _outSizeProcessed += outSizeProcessed; + + bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0); + bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize); + + if (res != 0 || _state.decoder.dicPos == _state.decoder.dicBufSize || finished || stopDecoding) + { + HRESULT res2 = WriteStream(outStream, _state.decoder.dic, _state.decoder.dicPos); + if (res != 0) + return S_FALSE; + RINOK(res2); + if (stopDecoding) + return S_OK; + if (finished) + return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE); + } + if (_state.decoder.dicPos == _state.decoder.dicBufSize) + _state.decoder.dicPos = 0; + + if (progress != NULL) + { + RINOK(progress->SetRatioInfo(&_inSizeProcessed, &_outSizeProcessed)); + } + } +} + +#ifndef NO_READ_FROM_CODER + +STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + do + { + if (_inPos == _inSize) + { + _inPos = _inSize = 0; + RINOK(_inStream->Read(_inBuf, kInBufSize, &_inSize)); + } + { + SizeT inProcessed = _inSize - _inPos; + + if (_outSizeDefined) + { + const UInt64 rem = _outSize - _outSizeProcessed; + if (rem < size) + size = (UInt32)rem; + } + + SizeT outProcessed = size; + ELzmaStatus status; + SRes res = Lzma2Dec_DecodeToBuf(&_state, (Byte *)data, &outProcessed, + _inBuf + _inPos, &inProcessed, LZMA_FINISH_ANY, &status); + _inPos += (UInt32)inProcessed; + _inSizeProcessed += inProcessed; + _outSizeProcessed += outProcessed; + size -= (UInt32)outProcessed; + data = (Byte *)data + outProcessed; + if (processedSize) + *processedSize += (UInt32)outProcessed; + RINOK(SResToHRESULT(res)); + if (inProcessed == 0 && outProcessed == 0) + return S_OK; + } + } + while (size != 0); + return S_OK; +} + +#endif + +}} diff --git a/CPP/7zip/Compress/Lzma2Decoder.h b/CPP/7zip/Compress/Lzma2Decoder.h new file mode 100755 index 00000000..fd7ca2f3 --- /dev/null +++ b/CPP/7zip/Compress/Lzma2Decoder.h @@ -0,0 +1,73 @@ +// Lzma2Decoder.h + +#ifndef __LZMA2_DECODER_H +#define __LZMA2_DECODER_H + +#include "../../../C/Lzma2Dec.h" + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +namespace NCompress { +namespace NLzma2 { + +class CDecoder: + public ICompressCoder, + public ICompressSetDecoderProperties2, + public ICompressGetInStreamProcessedSize, + #ifndef NO_READ_FROM_CODER + public ICompressSetInStream, + public ICompressSetOutStreamSize, + public ISequentialInStream, + #endif + public CMyUnknownImp +{ + CMyComPtr<ISequentialInStream> _inStream; + Byte *_inBuf; + UInt32 _inPos; + UInt32 _inSize; + CLzma2Dec _state; + bool _outSizeDefined; + UInt64 _outSize; + UInt64 _inSizeProcessed; + UInt64 _outSizeProcessed; +public: + + #ifndef NO_READ_FROM_CODER + MY_UNKNOWN_IMP5( + ICompressSetDecoderProperties2, + ICompressGetInStreamProcessedSize, + ICompressSetInStream, + ICompressSetOutStreamSize, + ISequentialInStream) + #else + MY_UNKNOWN_IMP2( + ICompressSetDecoderProperties2, + ICompressGetInStreamProcessedSize) + #endif + + STDMETHOD(Code)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *_inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); + + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream)(); + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); + + #ifndef NO_READ_FROM_CODER + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + #endif + + CDecoder(); + virtual ~CDecoder(); + +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/Lzma2Encoder.cpp b/CPP/7zip/Compress/Lzma2Encoder.cpp new file mode 100755 index 00000000..5e4c71be --- /dev/null +++ b/CPP/7zip/Compress/Lzma2Encoder.cpp @@ -0,0 +1,94 @@ +// Lzma2Encoder.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "../Common/CWrappers.h" +#include "../Common/StreamUtils.h" + +#include "Lzma2Encoder.h" + +namespace NCompress { + +namespace NLzma { + +HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep); + +} + +namespace NLzma2 { + +static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } +static void SzBigFree(void *, void *address) { BigFree(address); } +static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; + +static void *SzAlloc(void *, size_t size) { return MyAlloc(size); } +static void SzFree(void *, void *address) { MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +CEncoder::CEncoder() +{ + _encoder = 0; + _encoder = Lzma2Enc_Create(&g_Alloc, &g_BigAlloc); + if (_encoder == 0) + throw 1; +} + +CEncoder::~CEncoder() +{ + if (_encoder != 0) + Lzma2Enc_Destroy(_encoder); +} + +HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props) +{ + switch (propID) + { + case NCoderPropID::kBlockSize: + if (prop.vt != VT_UI4) return E_INVALIDARG; lzma2Props.blockSize = prop.ulVal; break; + case NCoderPropID::kNumThreads: + if (prop.vt != VT_UI4) return E_INVALIDARG; lzma2Props.numTotalThreads = (int)(prop.ulVal); break; + default: + RINOK(NLzma::SetLzmaProp(propID, prop, lzma2Props.lzmaProps)); + } + return S_OK; +} + +STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, + const PROPVARIANT *coderProps, UInt32 numProps) +{ + CLzma2EncProps lzma2Props; + Lzma2EncProps_Init(&lzma2Props); + + for (UInt32 i = 0; i < numProps; i++) + { + RINOK(SetLzma2Prop(propIDs[i], coderProps[i], lzma2Props)); + } + return SResToHRESULT(Lzma2Enc_SetProps(_encoder, &lzma2Props)); +} + +STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) +{ + Byte prop = Lzma2Enc_WriteProperties(_encoder); + return WriteStream(outStream, &prop, 1); +} + +STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) +{ + CSeqInStreamWrap inWrap(inStream); + CSeqOutStreamWrap outWrap(outStream); + CCompressProgressWrap progressWrap(progress); + + SRes res = Lzma2Enc_Encode(_encoder, &outWrap.p, &inWrap.p, progress ? &progressWrap.p : NULL); + if (res == SZ_ERROR_READ && inWrap.Res != S_OK) + return inWrap.Res; + if (res == SZ_ERROR_WRITE && outWrap.Res != S_OK) + return outWrap.Res; + if (res == SZ_ERROR_PROGRESS && progressWrap.Res != S_OK) + return progressWrap.Res; + return SResToHRESULT(res); +} + +}} diff --git a/CPP/7zip/Compress/Lzma2Encoder.h b/CPP/7zip/Compress/Lzma2Encoder.h new file mode 100755 index 00000000..f0fb74d3 --- /dev/null +++ b/CPP/7zip/Compress/Lzma2Encoder.h @@ -0,0 +1,36 @@ +// Lzma2Encoder.h + +#ifndef __LZMA2_ENCODER_H +#define __LZMA2_ENCODER_H + +#include "../../../C/Lzma2Enc.h" + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +namespace NCompress { +namespace NLzma2 { + +class CEncoder: + public ICompressCoder, + public ICompressSetCoderProperties, + public ICompressWriteCoderProperties, + public CMyUnknownImp +{ + CLzma2EncHandle _encoder; +public: + MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties) + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); + STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); + + CEncoder(); + virtual ~CEncoder(); +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/Lzma2Register.cpp b/CPP/7zip/Compress/Lzma2Register.cpp new file mode 100755 index 00000000..cace871e --- /dev/null +++ b/CPP/7zip/Compress/Lzma2Register.cpp @@ -0,0 +1,20 @@ +// Lzma2Register.cpp + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "Lzma2Decoder.h" + +static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NLzma2::CDecoder); } +#ifndef EXTRACT_ONLY +#include "Lzma2Encoder.h" +static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NLzma2::CEncoder); } +#else +#define CreateCodecOut 0 +#endif + +static CCodecInfo g_CodecInfo = + { CreateCodec, CreateCodecOut, 0x21, L"LZMA2", 1, false }; + +REGISTER_CODEC(LZMA2) diff --git a/CPP/7zip/Compress/LzmaDecoder.cpp b/CPP/7zip/Compress/LzmaDecoder.cpp index 5bfffe90..c74d5ade 100755 --- a/CPP/7zip/Compress/LzmaDecoder.cpp +++ b/CPP/7zip/Compress/LzmaDecoder.cpp @@ -2,10 +2,7 @@ #include "StdAfx.h" -extern "C" -{ #include "../../../C/Alloc.h" -} #include "../Common/StreamUtils.h" @@ -19,7 +16,6 @@ static HRESULT SResToHRESULT(SRes res) case SZ_ERROR_MEM: return E_OUTOFMEMORY; case SZ_ERROR_PARAM: return E_INVALIDARG; case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; - // case SZ_ERROR_PROGRESS: return E_ABORT; case SZ_ERROR_DATA: return S_FALSE; } return E_FAIL; @@ -30,8 +26,10 @@ namespace NLzma { static const UInt32 kInBufSize = 1 << 20; -CDecoder::CDecoder(): _inBuf(0), _outSizeDefined(false), FinishStream(false) +CDecoder::CDecoder(): _inBuf(0), _propsWereSet(false), _outSizeDefined(false), FinishStream(false) { + _inSizeProcessed = 0; + _inPos = _inSize = 0; LzmaDec_Construct(&_state); } @@ -45,43 +43,47 @@ CDecoder::~CDecoder() MyFree(_inBuf); } -STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size) +HRESULT CDecoder::CreateInputBuffer() { - RINOK(SResToHRESULT(LzmaDec_Allocate(&_state, prop, size, &g_Alloc))); - if (_inBuf == 0) { _inBuf = (Byte *)MyAlloc(kInBufSize); if (_inBuf == 0) return E_OUTOFMEMORY; } - return S_OK; } -STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { *value = _inSizeProcessed; return S_OK; } -STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; } -STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; } +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size) +{ + RINOK(SResToHRESULT(LzmaDec_Allocate(&_state, prop, size, &g_Alloc))); + _propsWereSet = true; + return CreateInputBuffer(); +} -STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) +void CDecoder::SetOutStreamSizeResume(const UInt64 *outSize) { _outSizeDefined = (outSize != NULL); if (_outSizeDefined) _outSize = *outSize; - + _outSizeProcessed = 0; LzmaDec_Init(&_state); - +} + +STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) +{ + _inSizeProcessed = 0; _inPos = _inSize = 0; - _inSizeProcessed = _outSizeProcessed = 0; + SetOutStreamSizeResume(outSize); return S_OK; } -STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) +HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress) { - if (_inBuf == 0) + if (_inBuf == 0 || !_propsWereSet) return S_FALSE; - SetOutStreamSize(outSize); + + UInt64 startInProgress = _inSizeProcessed; for (;;) { @@ -135,15 +137,26 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream if (_state.dicPos == _state.dicBufSize) _state.dicPos = 0; - if (progress != NULL) + if (progress) { - RINOK(progress->SetRatioInfo(&_inSizeProcessed, &_outSizeProcessed)); + UInt64 inSize = _inSizeProcessed - startInProgress; + RINOK(progress->SetRatioInfo(&inSize, &_outSizeProcessed)); } } } +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + SetOutStreamSize(outSize); + return CodeSpec(inStream, outStream, progress); +} + #ifndef NO_READ_FROM_CODER +STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; } +STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; } + STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) { if (processedSize) @@ -185,6 +198,42 @@ STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) return S_OK; } +HRESULT CDecoder::CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + SetOutStreamSizeResume(outSize); + return CodeSpec(_inStream, outStream, progress); +} + +HRESULT CDecoder::ReadFromInputStream(void *data, UInt32 size, UInt32 *processedSize) +{ + RINOK(CreateInputBuffer()); + if (processedSize) + *processedSize = 0; + while (size > 0) + { + if (_inPos == _inSize) + { + _inPos = _inSize = 0; + RINOK(_inStream->Read(_inBuf, kInBufSize, &_inSize)); + if (_inSize == 0) + break; + } + { + UInt32 curSize = _inSize - _inPos; + if (curSize > size) + curSize = size; + memcpy(data, _inBuf + _inPos, curSize); + _inPos += curSize; + _inSizeProcessed += curSize; + size -= curSize; + data = (Byte *)data + curSize; + if (processedSize) + *processedSize += curSize; + } + } + return S_OK; +} + #endif }} diff --git a/CPP/7zip/Compress/LzmaDecoder.h b/CPP/7zip/Compress/LzmaDecoder.h index e132d5cb..d4bc9d3b 100755 --- a/CPP/7zip/Compress/LzmaDecoder.h +++ b/CPP/7zip/Compress/LzmaDecoder.h @@ -3,10 +3,7 @@ #ifndef __LZMA_DECODER_H #define __LZMA_DECODER_H -extern "C" -{ #include "../../../C/LzmaDec.h" -} #include "../../Common/MyCom.h" #include "../ICoder.h" @@ -17,7 +14,6 @@ namespace NLzma { class CDecoder: public ICompressCoder, public ICompressSetDecoderProperties2, - public ICompressGetInStreamProcessedSize, #ifndef NO_READ_FROM_CODER public ICompressSetInStream, public ICompressSetOutStreamSize, @@ -30,35 +26,42 @@ class CDecoder: UInt32 _inPos; UInt32 _inSize; CLzmaDec _state; + bool _propsWereSet; bool _outSizeDefined; UInt64 _outSize; UInt64 _inSizeProcessed; UInt64 _outSizeProcessed; -public: + + HRESULT CreateInputBuffer(); + HRESULT CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress); + void SetOutStreamSizeResume(const UInt64 *outSize); +public: + MY_QUERYINTERFACE_BEGIN + MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2) #ifndef NO_READ_FROM_CODER - MY_UNKNOWN_IMP5( - ICompressSetDecoderProperties2, - ICompressGetInStreamProcessedSize, - ICompressSetInStream, - ICompressSetOutStreamSize, - ISequentialInStream) - #else - MY_UNKNOWN_IMP2( - ICompressSetDecoderProperties2, - ICompressGetInStreamProcessedSize) + MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) + MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize) + MY_QUERYINTERFACE_ENTRY(ISequentialInStream) #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); - STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); - STDMETHOD(SetInStream)(ISequentialInStream *inStream); - STDMETHOD(ReleaseInStream)(); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); #ifndef NO_READ_FROM_CODER + + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream)(); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + + HRESULT CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress); + HRESULT ReadFromInputStream(void *data, UInt32 size, UInt32 *processedSize); + UInt64 GetInputProcessedSize() const { return _inSizeProcessed; } + #endif bool FinishStream; diff --git a/CPP/7zip/Compress/LzmaEncoder.cpp b/CPP/7zip/Compress/LzmaEncoder.cpp index 986e1edb..9bdedaeb 100755 --- a/CPP/7zip/Compress/LzmaEncoder.cpp +++ b/CPP/7zip/Compress/LzmaEncoder.cpp @@ -2,49 +2,16 @@ #include "StdAfx.h" -extern "C" -{ #include "../../../C/Alloc.h" -} +#include "../Common/CWrappers.h" #include "../Common/StreamUtils.h" #include "LzmaEncoder.h" -static HRESULT SResToHRESULT(SRes res) -{ - switch(res) - { - case SZ_OK: return S_OK; - case SZ_ERROR_MEM: return E_OUTOFMEMORY; - case SZ_ERROR_PARAM: return E_INVALIDARG; - // case SZ_ERROR_THREAD: return E_FAIL; - } - return E_FAIL; -} - namespace NCompress { namespace NLzma { -static const UInt32 kStreamStepSize = (UInt32)1 << 31; - -static SRes MyRead(void *object, void *data, size_t *size) -{ - UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize); - HRESULT res = ((CSeqInStream *)object)->RealStream->Read(data, curSize, &curSize); - *size = curSize; - return (SRes)res; -} - -static size_t MyWrite(void *object, const void *data, size_t size) -{ - CSeqOutStream *p = (CSeqOutStream *)object; - p->Res = WriteStream(p->RealStream, data, size); - if (p->Res != 0) - return 0; - return size; -} - static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } static void SzBigFree(void *, void *address) { BigFree(address); } static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; @@ -55,8 +22,6 @@ static ISzAlloc g_Alloc = { SzAlloc, SzFree }; CEncoder::CEncoder() { - _seqInStream.SeqInStream.Read = MyRead; - _seqOutStream.SeqOutStream.Write = MyWrite; _encoder = 0; _encoder = LzmaEnc_Create(&g_Alloc); if (_encoder == 0) @@ -108,6 +73,31 @@ static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes) return 1; } +HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep) +{ + if (propID == NCoderPropID::kMatchFinder) + { + if (prop.vt != VT_BSTR) + return E_INVALIDARG; + return ParseMatchFinder(prop.bstrVal, &ep.btMode, &ep.numHashBytes) ? S_OK : E_INVALIDARG; + } + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 v = prop.ulVal; + switch (propID) + { + case NCoderPropID::kNumFastBytes: ep.fb = v; break; + case NCoderPropID::kMatchFinderCycles: ep.mc = v; break; + case NCoderPropID::kAlgorithm: ep.algo = v; break; + case NCoderPropID::kDictionarySize: ep.dictSize = v; break; + case NCoderPropID::kPosStateBits: ep.pb = v; break; + case NCoderPropID::kLitPosBits: ep.lp = v; break; + case NCoderPropID::kLitContextBits: ep.lc = v; break; + default: return E_INVALIDARG; + } + return S_OK; +} + STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps) { @@ -117,34 +107,15 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, for (UInt32 i = 0; i < numProps; i++) { const PROPVARIANT &prop = coderProps[i]; - switch (propIDs[i]) + PROPID propID = propIDs[i]; + switch (propID) { - case NCoderPropID::kNumFastBytes: - if (prop.vt != VT_UI4) return E_INVALIDARG; props.fb = prop.ulVal; break; - case NCoderPropID::kMatchFinderCycles: - if (prop.vt != VT_UI4) return E_INVALIDARG; props.mc = prop.ulVal; break; - case NCoderPropID::kAlgorithm: - if (prop.vt != VT_UI4) return E_INVALIDARG; props.algo = prop.ulVal; break; - case NCoderPropID::kDictionarySize: - if (prop.vt != VT_UI4) return E_INVALIDARG; props.dictSize = prop.ulVal; break; - case NCoderPropID::kPosStateBits: - if (prop.vt != VT_UI4) return E_INVALIDARG; props.pb = prop.ulVal; break; - case NCoderPropID::kLitPosBits: - if (prop.vt != VT_UI4) return E_INVALIDARG; props.lp = prop.ulVal; break; - case NCoderPropID::kLitContextBits: - if (prop.vt != VT_UI4) return E_INVALIDARG; props.lc = prop.ulVal; break; - case NCoderPropID::kNumThreads: - if (prop.vt != VT_UI4) return E_INVALIDARG; props.numThreads = prop.ulVal; break; - case NCoderPropID::kMultiThread: - if (prop.vt != VT_BOOL) return E_INVALIDARG; props.numThreads = ((prop.boolVal == VARIANT_TRUE) ? 2 : 1); break; case NCoderPropID::kEndMarker: if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal == VARIANT_TRUE); break; - case NCoderPropID::kMatchFinder: - if (prop.vt != VT_BSTR) return E_INVALIDARG; - if (!ParseMatchFinder(prop.bstrVal, &props.btMode, &props.numHashBytes /* , &_matchFinderBase.skipModeBits */)) - return E_INVALIDARG; break; + case NCoderPropID::kNumThreads: + if (prop.vt != VT_UI4) return E_INVALIDARG; props.numThreads = prop.ulVal; break; default: - return E_INVALIDARG; + RINOK(SetLzmaProp(propID, prop, props)); } } return SResToHRESULT(LzmaEnc_SetProps(_encoder, &props)); @@ -158,53 +129,20 @@ STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) return WriteStream(outStream, props, size); } -STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream) -{ - _seqOutStream.RealStream = outStream; - _seqOutStream.Res = S_OK; - return S_OK; -} - -STDMETHODIMP CEncoder::ReleaseOutStream() -{ - _seqOutStream.RealStream.Release(); - return S_OK; -} - -typedef struct _CCompressProgressImp -{ - ICompressProgress p; - ICompressProgressInfo *Progress; - HRESULT Res; -} CCompressProgressImp; - -#define PROGRESS_UNKNOWN_VALUE ((UInt64)(Int64)-1) - -#define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x) - -SRes CompressProgress(void *pp, UInt64 inSize, UInt64 outSize) -{ - CCompressProgressImp *p = (CCompressProgressImp *)pp; - p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize)); - return (SRes)p->Res; -} - STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) { - CCompressProgressImp progressImp; - progressImp.p.Progress = CompressProgress; - progressImp.Progress = progress; - progressImp.Res = SZ_OK; - - _seqInStream.RealStream = inStream; - SetOutStream(outStream); - SRes res = LzmaEnc_Encode(_encoder, &_seqOutStream.SeqOutStream, &_seqInStream.SeqInStream, progress ? &progressImp.p : NULL, &g_Alloc, &g_BigAlloc); - ReleaseOutStream(); - if (res == SZ_ERROR_WRITE && _seqOutStream.Res != S_OK) - return _seqOutStream.Res; - if (res == SZ_ERROR_PROGRESS && progressImp.Res != S_OK) - return progressImp.Res; + CSeqInStreamWrap inWrap(inStream); + CSeqOutStreamWrap outWrap(outStream); + CCompressProgressWrap progressWrap(progress); + + SRes res = LzmaEnc_Encode(_encoder, &outWrap.p, &inWrap.p, progress ? &progressWrap.p : NULL, &g_Alloc, &g_BigAlloc); + if (res == SZ_ERROR_READ && inWrap.Res != S_OK) + return inWrap.Res; + if (res == SZ_ERROR_WRITE && outWrap.Res != S_OK) + return outWrap.Res; + if (res == SZ_ERROR_PROGRESS && progressWrap.Res != S_OK) + return progressWrap.Res; return SResToHRESULT(res); } diff --git a/CPP/7zip/Compress/LzmaEncoder.h b/CPP/7zip/Compress/LzmaEncoder.h index 4205d2b1..904c0002 100755 --- a/CPP/7zip/Compress/LzmaEncoder.h +++ b/CPP/7zip/Compress/LzmaEncoder.h @@ -3,10 +3,7 @@ #ifndef __LZMA_ENCODER_H #define __LZMA_ENCODER_H -extern "C" -{ #include "../../../C/LzmaEnc.h" -} #include "../../Common/MyCom.h" @@ -15,47 +12,22 @@ extern "C" namespace NCompress { namespace NLzma { -struct CSeqInStream -{ - ISeqInStream SeqInStream; - ISequentialInStream *RealStream; -}; - -struct CSeqOutStream -{ - ISeqOutStream SeqOutStream; - CMyComPtr<ISequentialOutStream> RealStream; - HRESULT Res; -}; - -class CEncoder : +class CEncoder: public ICompressCoder, - public ICompressSetOutStream, public ICompressSetCoderProperties, public ICompressWriteCoderProperties, public CMyUnknownImp { CLzmaEncHandle _encoder; - - CSeqInStream _seqInStream; - CSeqOutStream _seqOutStream; - public: - CEncoder(); - - MY_UNKNOWN_IMP3( - ICompressSetOutStream, - ICompressSetCoderProperties, - ICompressWriteCoderProperties - ) + MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties) STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); - STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); - STDMETHOD(ReleaseOutStream)(); + CEncoder(); virtual ~CEncoder(); }; diff --git a/CPP/7zip/Compress/PpmdContext.h b/CPP/7zip/Compress/PpmdContext.h index f4fa78e4..cfff53ed 100755 --- a/CPP/7zip/Compress/PpmdContext.h +++ b/CPP/7zip/Compress/PpmdContext.h @@ -1,5 +1,6 @@ // PpmdContext.h -// This code is based on Dmitry Shkarin's PPMdH code +// 2009-05-30 : Igor Pavlov : Public domain +// This code is based on Dmitry Shkarin's PPMdH code (public domain) #ifndef __COMPRESS_PPMD_CONTEXT_H #define __COMPRESS_PPMD_CONTEXT_H diff --git a/CPP/7zip/Compress/PpmdDecode.h b/CPP/7zip/Compress/PpmdDecode.h index 860c65b4..d5ca25fe 100755 --- a/CPP/7zip/Compress/PpmdDecode.h +++ b/CPP/7zip/Compress/PpmdDecode.h @@ -1,5 +1,6 @@ // PpmdDecode.h -// This code is based on Dmitry Shkarin's PPMdH code +// 2009-05-30 : Igor Pavlov : Public domain +// This code is based on Dmitry Shkarin's PPMdH code (public domain) #ifndef __COMPRESS_PPMD_DECODE_H #define __COMPRESS_PPMD_DECODE_H diff --git a/CPP/7zip/Compress/PpmdDecoder.cpp b/CPP/7zip/Compress/PpmdDecoder.cpp index dea36d9a..0ac98c8b 100755 --- a/CPP/7zip/Compress/PpmdDecoder.cpp +++ b/CPP/7zip/Compress/PpmdDecoder.cpp @@ -1,4 +1,5 @@ // PpmdDecoder.cpp +// 2009-05-30 : Igor Pavlov : Public domain #include "StdAfx.h" diff --git a/CPP/7zip/Compress/PpmdDecoder.h b/CPP/7zip/Compress/PpmdDecoder.h index 0d8817d4..31ab8f82 100755 --- a/CPP/7zip/Compress/PpmdDecoder.h +++ b/CPP/7zip/Compress/PpmdDecoder.h @@ -1,4 +1,5 @@ // PpmdDecoder.h +// 2009-05-30 : Igor Pavlov : Public domain #ifndef __COMPRESS_PPMD_DECODER_H #define __COMPRESS_PPMD_DECODER_H diff --git a/CPP/7zip/Compress/PpmdEncode.h b/CPP/7zip/Compress/PpmdEncode.h index 0db92361..012f859c 100755 --- a/CPP/7zip/Compress/PpmdEncode.h +++ b/CPP/7zip/Compress/PpmdEncode.h @@ -1,5 +1,6 @@ // PpmdEncode.h -// This code is based on Dmitry Shkarin's PPMdH code +// 2009-05-30 : Igor Pavlov : Public domain +// This code is based on Dmitry Shkarin's PPMdH code (public domain) #ifndef __COMPRESS_PPMD_ENCODE_H #define __COMPRESS_PPMD_ENCODE_H diff --git a/CPP/7zip/Compress/PpmdEncoder.cpp b/CPP/7zip/Compress/PpmdEncoder.cpp index 1e98c091..0af2ae7d 100755 --- a/CPP/7zip/Compress/PpmdEncoder.cpp +++ b/CPP/7zip/Compress/PpmdEncoder.cpp @@ -1,4 +1,5 @@ // PpmdEncoder.cpp +// 2009-05-30 : Igor Pavlov : Public domain #include "StdAfx.h" diff --git a/CPP/7zip/Compress/PpmdEncoder.h b/CPP/7zip/Compress/PpmdEncoder.h index 72b10651..07b368a7 100755 --- a/CPP/7zip/Compress/PpmdEncoder.h +++ b/CPP/7zip/Compress/PpmdEncoder.h @@ -1,4 +1,5 @@ // PpmdEncoder.h +// 2009-05-30 : Igor Pavlov : Public domain #ifndef __COMPRESS_PPMD_ENCODER_H #define __COMPRESS_PPMD_ENCODER_H diff --git a/CPP/7zip/Compress/PpmdRegister.cpp b/CPP/7zip/Compress/PpmdRegister.cpp index cac1fb85..9f59fcdd 100755 --- a/CPP/7zip/Compress/PpmdRegister.cpp +++ b/CPP/7zip/Compress/PpmdRegister.cpp @@ -1,4 +1,5 @@ // PpmdRegister.cpp +// 2009-05-30 : Igor Pavlov : Public domain #include "StdAfx.h" diff --git a/CPP/7zip/Compress/PpmdSubAlloc.h b/CPP/7zip/Compress/PpmdSubAlloc.h index a7dd122c..143f4632 100755 --- a/CPP/7zip/Compress/PpmdSubAlloc.h +++ b/CPP/7zip/Compress/PpmdSubAlloc.h @@ -1,13 +1,11 @@ // PpmdSubAlloc.h -// This code is based on Dmitry Shkarin's PPMdH code +// 2009-05-30 : Igor Pavlov : Public domain +// This code is based on Dmitry Shkarin's PPMdH code (public domain) #ifndef __COMPRESS_PPMD_SUB_ALLOC_H #define __COMPRESS_PPMD_SUB_ALLOC_H -extern "C" -{ #include "../../../C/Alloc.h" -} #include "PpmdType.h" diff --git a/CPP/7zip/Compress/PpmdType.h b/CPP/7zip/Compress/PpmdType.h index 4f0e65e8..e4b0203c 100755 --- a/CPP/7zip/Compress/PpmdType.h +++ b/CPP/7zip/Compress/PpmdType.h @@ -1,12 +1,6 @@ -/**************************************************************************** - * This file is part of PPMd project * - * Written and distributed to public domain by Dmitry Shkarin 1997, * - * 1999-2001 * - * Contents: compilation parameters and miscelaneous definitions * - * Comments: system & compiler dependent file - - * modified by Igor Pavlov (2004-08-29). - ****************************************************************************/ +// PpmdType.h +// 2009-05-30 : Igor Pavlov : Public domain +// This code is based on Dmitry Shkarin's PPMdH code (public domain) #ifndef __COMPRESS_PPMD_TYPE_H #define __COMPRESS_PPMD_TYPE_H diff --git a/CPP/7zip/Compress/RangeCoder.h b/CPP/7zip/Compress/RangeCoder.h index 1e14ac1f..1eb2a6d4 100755 --- a/CPP/7zip/Compress/RangeCoder.h +++ b/CPP/7zip/Compress/RangeCoder.h @@ -1,4 +1,5 @@ // Compress/RangeCoder.h +// 2009-05-30 : Igor Pavlov : Public domain #ifndef __COMPRESS_RANGE_CODER_H #define __COMPRESS_RANGE_CODER_H diff --git a/CPP/7zip/Compress/RangeCoderBit.h b/CPP/7zip/Compress/RangeCoderBit.h index 566cdd41..b5a1830d 100755 --- a/CPP/7zip/Compress/RangeCoderBit.h +++ b/CPP/7zip/Compress/RangeCoderBit.h @@ -1,4 +1,5 @@ // Compress/RangeCoderBit.h +// 2009-05-30 : Igor Pavlov : Public domain #ifndef __COMPRESS_RANGE_CODER_BIT_H #define __COMPRESS_RANGE_CODER_BIT_H diff --git a/CPP/7zip/Compress/Rar3Vm.cpp b/CPP/7zip/Compress/Rar3Vm.cpp index ffca79d0..759dfbdb 100755 --- a/CPP/7zip/Compress/Rar3Vm.cpp +++ b/CPP/7zip/Compress/Rar3Vm.cpp @@ -12,11 +12,8 @@ Note: #include "StdAfx.h" -extern "C" -{ #include "../../../C/7zCrc.h" #include "../../../C/Alloc.h" -} #include "Rar3Vm.h" diff --git a/CPP/7zip/Compress/ShrinkDecoder.cpp b/CPP/7zip/Compress/ShrinkDecoder.cpp index 6eaacd4b..a89d323c 100755 --- a/CPP/7zip/Compress/ShrinkDecoder.cpp +++ b/CPP/7zip/Compress/ShrinkDecoder.cpp @@ -2,10 +2,7 @@ #include "StdAfx.h" -extern "C" -{ #include "../../../C/Alloc.h" -} #include "../Common/InBuffer.h" #include "../Common/OutBuffer.h" diff --git a/CPP/7zip/Compress/ZDecoder.cpp b/CPP/7zip/Compress/ZDecoder.cpp index 6982a7e0..e28c6451 100755 --- a/CPP/7zip/Compress/ZDecoder.cpp +++ b/CPP/7zip/Compress/ZDecoder.cpp @@ -2,10 +2,7 @@ #include "StdAfx.h" -extern "C" -{ #include "../../../C/Alloc.h" -} #include "../Common/InBuffer.h" #include "../Common/OutBuffer.h" diff --git a/CPP/7zip/Crypto/7zAes.cpp b/CPP/7zip/Crypto/7zAes.cpp index 3a1cbd68..41ccb1d2 100755 --- a/CPP/7zip/Crypto/7zAes.cpp +++ b/CPP/7zip/Crypto/7zAes.cpp @@ -2,14 +2,13 @@ #include "StdAfx.h" -extern "C" -{ #include "../../../C/Sha256.h" -} #include "Windows/Synchronization.h" + #include "../Common/StreamObjects.h" #include "../Common/StreamUtils.h" + #include "7zAes.h" #include "MyAes.h" diff --git a/CPP/7zip/Crypto/MyAes.h b/CPP/7zip/Crypto/MyAes.h index ffc6fea5..24e90d6f 100755 --- a/CPP/7zip/Crypto/MyAes.h +++ b/CPP/7zip/Crypto/MyAes.h @@ -3,10 +3,7 @@ #ifndef __CRYPTO_MY_AES_H #define __CRYPTO_MY_AES_H -extern "C" -{ #include "../../../C/Aes.h" -} #include "../../Common/MyCom.h" #include "../../Common/Types.h" diff --git a/CPP/7zip/Crypto/Rar20Crypto.cpp b/CPP/7zip/Crypto/Rar20Crypto.cpp index 8fd2ab23..c2df0e52 100755 --- a/CPP/7zip/Crypto/Rar20Crypto.cpp +++ b/CPP/7zip/Crypto/Rar20Crypto.cpp @@ -2,12 +2,9 @@ #include "StdAfx.h" -extern "C" -{ - #include "../../../C/7zCrc.h" - #include "../../../C/CpuArch.h" - #include "../../../C/RotateDefs.h" -} +#include "../../../C/7zCrc.h" +#include "../../../C/CpuArch.h" +#include "../../../C/RotateDefs.h" #include "Rar20Crypto.h" diff --git a/CPP/7zip/Crypto/RarAes.h b/CPP/7zip/Crypto/RarAes.h index aa8e06ba..374017b8 100755 --- a/CPP/7zip/Crypto/RarAes.h +++ b/CPP/7zip/Crypto/RarAes.h @@ -3,10 +3,7 @@ #ifndef __CRYPTO_RAR_AES_H #define __CRYPTO_RAR_AES_H -extern "C" -{ #include "../../../C/Aes.h" -} #include "Common/Buffer.h" #include "Common/MyCom.h" diff --git a/CPP/7zip/Crypto/Sha1.cpp b/CPP/7zip/Crypto/Sha1.cpp index af211f6c..84e589b2 100755 --- a/CPP/7zip/Crypto/Sha1.cpp +++ b/CPP/7zip/Crypto/Sha1.cpp @@ -4,11 +4,9 @@ #include "StdAfx.h" -#include "Sha1.h" -extern "C" -{ #include "../../../C/RotateDefs.h" -} + +#include "Sha1.h" namespace NCrypto { namespace NSha1 { diff --git a/CPP/7zip/Crypto/WzAes.h b/CPP/7zip/Crypto/WzAes.h index 2c7a4b43..22f4d4dd 100755 --- a/CPP/7zip/Crypto/WzAes.h +++ b/CPP/7zip/Crypto/WzAes.h @@ -12,10 +12,7 @@ specified in password Based File Encryption Utility: #ifndef __CRYPTO_WZ_AES_H #define __CRYPTO_WZ_AES_H -extern "C" -{ #include "../../../C/Aes.h" -} #include "Common/Buffer.h" #include "Common/MyCom.h" diff --git a/CPP/7zip/Crypto/ZipCrypto.cpp b/CPP/7zip/Crypto/ZipCrypto.cpp index fc9f8ac2..f5972c57 100755 --- a/CPP/7zip/Crypto/ZipCrypto.cpp +++ b/CPP/7zip/Crypto/ZipCrypto.cpp @@ -2,10 +2,7 @@ #include "StdAfx.h" -extern "C" -{ #include "../../../C/7zCrc.h" -} #include "../Common/StreamUtils.h" diff --git a/CPP/7zip/Crypto/ZipStrong.cpp b/CPP/7zip/Crypto/ZipStrong.cpp index e693febd..b29a3ad4 100755 --- a/CPP/7zip/Crypto/ZipStrong.cpp +++ b/CPP/7zip/Crypto/ZipStrong.cpp @@ -2,11 +2,8 @@ #include "StdAfx.h" -extern "C" -{ #include "../../../C/7zCrc.h" #include "../../../C/CpuArch.h" -} #include "../Common/StreamUtils.h" diff --git a/CPP/7zip/Guid.txt b/CPP/7zip/Guid.txt index 387a74d7..25939aaa 100755 --- a/CPP/7zip/Guid.txt +++ b/CPP/7zip/Guid.txt @@ -7,11 +7,12 @@ 01 IFolderArchive.h 05 IArchiveFolder - 06 IInFolderArchive + // 06 IInFolderArchive // old 07 IFileExtractCallback.h::IFolderArchiveExtractCallback 0A IOutFolderArchive 0B IFolderArchiveUpdateCallback 0Ń Agent.h::IArchiveFolderInternal + 0D IInFolderArchive 03 IStream.h @@ -65,6 +66,7 @@ 40 IInArchiveGetStream 50 IArchiveOpenSetSubArchiveName 60 IInArchive + 61 IArchiveOpenSeq 80 IArchiveUpdateCallback 82 IArchiveUpdateCallback2 @@ -86,12 +88,15 @@ 09 IFolderClone 0A IFolderSetFlatMode 0B IFolderOperationsExtractCallback + 0C IFolderArchiveProperties + 0D IGetFolderArchiveProperties + 0E IFolderProperties -09 FolderInterface.h +09 IFolder.h :: FOLDER_MANAGER_INTERFACE - 00 // old IFolderManager - 01 IFolderManager + 00 - 03 // old IFolderManager + 04 IFolderManager @@ -116,8 +121,14 @@ Handler GUIDs: 07 7z 08 Cab 09 Nsis - 0A Lzma - + 0A lzma + 0B lzma86 + 0C xz + + D9 Ntfs + DA Fat + DB Mbr + DC Vhd DD Pe DE Elf DF Mach-O diff --git a/CPP/7zip/ICoder.h b/CPP/7zip/ICoder.h index 262dfdba..b5d4d556 100755 --- a/CPP/7zip/ICoder.h +++ b/CPP/7zip/ICoder.h @@ -14,21 +14,15 @@ CODER_INTERFACE(ICompressProgressInfo, 0x04) CODER_INTERFACE(ICompressCoder, 0x05) { - STDMETHOD(Code)(ISequentialInStream *inStream, - ISequentialOutStream *outStream, - const UInt64 *inSize, - const UInt64 *outSize, + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) PURE; }; CODER_INTERFACE(ICompressCoder2, 0x18) { - STDMETHOD(Code)(ISequentialInStream **inStreams, - const UInt64 **inSizes, - UInt32 numInStreams, - ISequentialOutStream **outStreams, - const UInt64 **outSizes, - UInt32 numOutStreams, + STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, + ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) PURE; }; @@ -36,28 +30,27 @@ namespace NCoderPropID { enum EEnum { - kDictionarySize = 0x400, + kDefaultProp = 0, + kDictionarySize, kUsedMemorySize, kOrder, kBlockSize, - kPosStateBits = 0x440, + kPosStateBits, kLitContextBits, kLitPosBits, - kNumFastBytes = 0x450, + kNumFastBytes, kMatchFinder, kMatchFinderCycles, - kNumPasses = 0x460, - kAlgorithm = 0x470, - kMultiThread = 0x480, + kNumPasses, + kAlgorithm, kNumThreads, - kEndMarker = 0x490 + kEndMarker }; } CODER_INTERFACE(ICompressSetCoderProperties, 0x20) { - STDMETHOD(SetCoderProperties)(const PROPID *propIDs, - const PROPVARIANT *properties, UInt32 numProperties) PURE; + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) PURE; }; /* @@ -74,7 +67,7 @@ CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22) CODER_INTERFACE(ICompressWriteCoderProperties, 0x23) { - STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStreams) PURE; + STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream) PURE; }; CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24) diff --git a/CPP/7zip/MyVersion.h b/CPP/7zip/MyVersion.h index 68058ec3..ad2f0242 100755 --- a/CPP/7zip/MyVersion.h +++ b/CPP/7zip/MyVersion.h @@ -1,8 +1,8 @@ -#define MY_VER_MAJOR 4 -#define MY_VER_MINOR 65 +#define MY_VER_MAJOR 9 +#define MY_VER_MINOR 04 #define MY_VER_BUILD 0 -#define MY_VERSION "4.65" -#define MY_7ZIP_VERSION "7-Zip 4.65" -#define MY_DATE "2009-02-03" +#define MY_VERSION "9.04 beta" +#define MY_7ZIP_VERSION "7-Zip 9.04 beta" +#define MY_DATE "2009-05-30" #define MY_COPYRIGHT "Copyright (c) 1999-2009 Igor Pavlov" #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE diff --git a/CPP/7zip/PropID.h b/CPP/7zip/PropID.h index 9de487e8..d6f3a7c1 100755 --- a/CPP/7zip/PropID.h +++ b/CPP/7zip/PropID.h @@ -6,7 +6,7 @@ enum { kpidNoProperty = 0, - + kpidMainSubfile = 1, kpidHandlerItemIndex = 2, kpidPath, kpidName, @@ -54,6 +54,12 @@ enum kpidChecksum, kpidCharacts, kpidVa, + kpidId, + kpidShortName, + kpidCreatorApp, + kpidSectorSize, + kpidPosixAttrib, + kpidLink, kpidTotalSize = 0x1100, kpidFreeSpace, diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp index 0b57049c..0b8f7c37 100755 --- a/CPP/7zip/UI/Agent/Agent.cpp +++ b/CPP/7zip/UI/Agent/Agent.cpp @@ -2,23 +2,14 @@ #include "StdAfx.h" -#include "Common/StringConvert.h" +#include "../../../../C/Sort.h" + #include "Common/ComTry.h" -#include "Windows/Defs.h" -#include "Windows/PropVariant.h" -#include "Windows/FileFind.h" -#include "../Common/DefaultName.h" #include "../Common/ArchiveExtractCallback.h" #include "Agent.h" -extern "C" -{ - #include "../../../../C/Sort.h" -} - - using namespace NWindows; STDMETHODIMP CAgentFolder::GetAgentFolder(CAgentFolder **agentFolder) @@ -46,7 +37,6 @@ void CAgentFolder::LoadFolder(CProxyFolder *folder) } } - STDMETHODIMP CAgentFolder::LoadItems() { if (!_agentSpec->_archiveLink.IsOpen) @@ -238,6 +228,40 @@ STDMETHODIMP CAgentFolder::BindToParentFolder(IFolderFolder **resultFolder) COM_TRY_END } +STDMETHODIMP CAgentFolder::GetStream(UInt32 index, ISequentialInStream **stream) +{ + CMyComPtr<IInArchiveGetStream> getStream; + _agentSpec->GetArchive()->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream); + if (!getStream) + return S_OK; + + const CProxyFolder *folder; + UInt32 realIndex; + if (_flatMode) + { + const CProxyItem &item = _items[index]; + folder = item.Folder; + realIndex = item.Index; + } + else + { + folder = _proxyFolderItem; + realIndex = index; + } + + UInt32 indexInArchive; + if (realIndex < (UInt32)folder->Folders.Size()) + { + const CProxyFolder &item = folder->Folders[realIndex]; + if (!item.IsLeaf) + return S_OK; + indexInArchive = item.Index; + } + else + indexInArchive = folder->Files[realIndex - folder->Folders.Size()].Index; + return getStream->GetStream(indexInArchive, stream); +} + STATPROPSTG kProperties[] = { { NULL, kpidNumSubDirs, VT_UI4}, @@ -261,6 +285,8 @@ STDMETHODIMP CAgentFolder::GetNumberOfProperties(UInt32 *numProperties) *numProperties += kNumProperties; if (!_flatMode) (*numProperties)--; + if (!_agentSpec->_proxyArchive->ThereIsPathProp) + (*numProperties)++; return S_OK; COM_TRY_END } @@ -270,6 +296,18 @@ STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *pro COM_TRY_BEGIN UInt32 numProperties; _agentSpec->GetArchive()->GetNumberOfProperties(&numProperties); + if (!_agentSpec->_proxyArchive->ThereIsPathProp) + { + if (index == 0) + { + *propID = kpidName; + *varType = VT_BSTR; + *name = 0; + return S_OK; + } + index--; + } + if (index < numProperties) { RINOK(_agentSpec->GetArchive()->GetPropertyInfo(index, name, propID, varType)); @@ -378,7 +416,7 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices, NExtract::NPathMode::EEnum pathMode, NExtract::NOverwriteMode::EEnum overwriteMode, const wchar_t *path, - INT32 testMode, + Int32 testMode, IFolderArchiveExtractCallback *extractCallback2) { COM_TRY_BEGIN @@ -399,17 +437,12 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices, extractCallbackSpec->InitForMulti(false, pathMode, overwriteMode); - extractCallbackSpec->Init(_agentSpec->GetArchive(), + extractCallbackSpec->Init(NULL, &_agentSpec->GetArc(), extractCallback2, - false, + false, testMode ? true : false, false, (path ? path : L""), pathParts, - _agentSpec->DefaultName, - _agentSpec->DefaultTime, - _agentSpec->DefaultAttrib, - (UInt64)(Int64)-1 - // ,_agentSpec->_srcDirectoryPrefix - ); + (UInt64)(Int64)-1); CUIntVector realIndices; GetRealIndices(indices, numItems, realIndices); return _agentSpec->GetArchive()->Extract(&realIndices.Front(), @@ -433,18 +466,21 @@ CAgent::~CAgent() } STDMETHODIMP CAgent::Open( + IInStream *inStream, const wchar_t *filePath, BSTR *archiveType, - // CLSID *clsIDResult, IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN _archiveFilePath = filePath; - NFile::NFind::CFileInfoW fileInfo; - if (!NFile::NFind::FindFile(_archiveFilePath, fileInfo)) - return ::GetLastError(); - if (fileInfo.IsDir()) - return E_FAIL; + NFile::NFind::CFileInfoW fi; + if (!inStream) + { + if (!fi.Find(_archiveFilePath)) + return ::GetLastError(); + if (fi.IsDir()) + return E_FAIL; + } CArcInfoEx archiverInfo0, archiverInfo1; _compressCodecsInfo.Release(); @@ -452,14 +488,16 @@ STDMETHODIMP CAgent::Open( _compressCodecsInfo = _codecs; RINOK(_codecs->Load()); - RINOK(OpenArchive(_codecs, CIntVector(), _archiveFilePath, _archiveLink, openArchiveCallback)); - // _archive = _archiveLink.GetArchive(); - DefaultName = _archiveLink.GetDefaultItemName(); - const CArcInfoEx &ai = _codecs->Formats[_archiveLink.GetArchiverIndex()]; + RINOK(_archiveLink.Open(_codecs, CIntVector(), false, inStream, _archiveFilePath, openArchiveCallback)); - DefaultTime = fileInfo.MTime; - DefaultAttrib = fileInfo.Attrib; - ArchiveType = ai.Name; + CArc &arc = _archiveLink.Arcs.Back(); + if (!inStream) + { + arc.MTimeDefined = !fi.IsDevice; + arc.MTime = fi.MTime; + } + + ArchiveType = _codecs->Formats[arc.FormatIndex].Name; if (archiveType == 0) return S_OK; return StringToBstr(ArchiveType, archiveType); @@ -474,7 +512,7 @@ STDMETHODIMP CAgent::ReOpen(IArchiveOpenCallback *openArchiveCallback) delete _proxyArchive; _proxyArchive = NULL; } - RINOK(ReOpenArchive(_codecs, _archiveLink, _archiveFilePath, openArchiveCallback)); + RINOK(_archiveLink.ReOpen(_codecs, _archiveFilePath, openArchiveCallback)); return ReadItems(); COM_TRY_END } @@ -482,13 +520,7 @@ STDMETHODIMP CAgent::ReOpen(IArchiveOpenCallback *openArchiveCallback) STDMETHODIMP CAgent::Close() { COM_TRY_BEGIN - RINOK(_archiveLink.Close()); - if (_archiveLink.GetNumLevels() > 1) - { - // return S_OK; - } - // _archive->Close(); - return S_OK; + return _archiveLink.Close(); COM_TRY_END } @@ -504,11 +536,7 @@ HRESULT CAgent::ReadItems() if (_proxyArchive != NULL) return S_OK; _proxyArchive = new CProxyArchive(); - return _proxyArchive->Load(GetArchive(), - DefaultName, - // _defaultTime, - // _defaultAttrib, - NULL); + return _proxyArchive->Load(GetArc(), NULL); } STDMETHODIMP CAgent::BindToRootFolder(IFolderFolder **resultFolder) @@ -528,24 +556,19 @@ STDMETHODIMP CAgent::Extract( NExtract::NPathMode::EEnum pathMode, NExtract::NOverwriteMode::EEnum overwriteMode, const wchar_t *path, - INT32 testMode, + Int32 testMode, IFolderArchiveExtractCallback *extractCallback2) { COM_TRY_BEGIN CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; extractCallbackSpec->InitForMulti(false, pathMode, overwriteMode); - extractCallbackSpec->Init(GetArchive(), + extractCallbackSpec->Init(NULL, &GetArc(), extractCallback2, - false, + false, testMode ? true : false, false, path, UStringVector(), - DefaultName, - DefaultTime, - DefaultAttrib, - (UInt64)(Int64)-1 - // ,_srcDirectoryPrefix - ); + (UInt64)(Int64)-1); return GetArchive()->Extract(0, (UInt32)(Int32)-1, testMode, extractCallback); COM_TRY_END } @@ -590,4 +613,3 @@ STDMETHODIMP CAgent::GetArchivePropertyInfo(UInt32 index, name, propID, varType); COM_TRY_END } - diff --git a/CPP/7zip/UI/Agent/Agent.h b/CPP/7zip/UI/Agent/Agent.h index 64fb31f6..b95725e4 100755 --- a/CPP/7zip/UI/Agent/Agent.h +++ b/CPP/7zip/UI/Agent/Agent.h @@ -4,19 +4,20 @@ #define __AGENT_AGENT_H #include "Common/MyCom.h" + #include "Windows/PropVariant.h" -#include "../Common/UpdateAction.h" #include "../Common/OpenArchive.h" - -#include "IFolderArchive.h" -#include "AgentProxy.h" +#include "../Common/UpdateAction.h" #ifdef NEW_FOLDER_INTERFACE #include "../FileManager/IFolder.h" #include "../Common/LoadCodecs.h" #endif +#include "AgentProxy.h" +#include "IFolderArchive.h" + class CAgentFolder; DECL_INTERFACE(IArchiveFolderInternal, 0x01, 0xC) @@ -38,6 +39,7 @@ class CAgentFolder: public IGetFolderArchiveProperties, public IArchiveFolder, public IArchiveFolderInternal, + public IInArchiveGetStream, #ifdef NEW_FOLDER_INTERFACE public IFolderOperations, public IFolderSetFlatMode, @@ -52,6 +54,7 @@ public: MY_QUERYINTERFACE_ENTRY(IGetFolderArchiveProperties) MY_QUERYINTERFACE_ENTRY(IArchiveFolder) MY_QUERYINTERFACE_ENTRY(IArchiveFolderInternal) + MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream) #ifdef NEW_FOLDER_INTERFACE MY_QUERYINTERFACE_ENTRY(IFolderOperations) MY_QUERYINTERFACE_ENTRY(IFolderSetFlatMode) @@ -73,11 +76,13 @@ public: NExtract::NPathMode::EEnum pathMode, NExtract::NOverwriteMode::EEnum overwriteMode, const wchar_t *path, - INT32 testMode, + Int32 testMode, IFolderArchiveExtractCallback *extractCallback); STDMETHOD(GetAgentFolder)(CAgentFolder **agentFolder); + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); + #ifdef NEW_FOLDER_INTERFACE INTERFACE_FolderOperations(;) @@ -170,7 +175,7 @@ public: IFolderArchiveUpdateCallback *updateCallback100); // ISetProperties - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, INT32 numProperties); + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties); #endif CCodecs *_codecs; @@ -182,14 +187,8 @@ private: HRESULT ReadItems(); public: CProxyArchive *_proxyArchive; - CArchiveLink _archiveLink; - // IInArchive *_archive2; - - UString DefaultName; - FILETIME DefaultTime; - DWORD DefaultAttrib; UString ArchiveType; @@ -206,8 +205,9 @@ public: CObjectVector<NWindows::NCOM::CPropVariant> m_PropValues; #endif - IInArchive *GetArchive() { return _archiveLink.GetArchive(); } - bool CanUpdate() const { return _archiveLink.GetNumLevels() <= 1; } + const CArc &GetArc() { return _archiveLink.Arcs.Back(); } + IInArchive *GetArchive() { return GetArc().Archive; } + bool CanUpdate() const { return _archiveLink.Arcs.Size() == 1; } }; #ifdef NEW_FOLDER_INTERFACE diff --git a/CPP/7zip/UI/Agent/AgentOut.cpp b/CPP/7zip/UI/Agent/AgentOut.cpp index ffeac1c6..51a5affa 100755 --- a/CPP/7zip/UI/Agent/AgentOut.cpp +++ b/CPP/7zip/UI/Agent/AgentOut.cpp @@ -27,12 +27,6 @@ using namespace NWindows; using namespace NCOM; -static HRESULT CopyBlock(ISequentialInStream *inStream, ISequentialOutStream *outStream) -{ - CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder; - return copyCoder->Code(inStream, outStream, NULL, NULL, NULL); -} - STDMETHODIMP CAgent::SetFolder(IFolderFolder *folder) { _archiveNamePrefix.Empty(); @@ -86,20 +80,6 @@ STDMETHODIMP CAgent::SetFiles(const wchar_t *folderPrefix, return S_OK; } - -static HRESULT GetFileTime(CAgent *agent, UInt32 itemIndex, FILETIME &fileTime) -{ - CPropVariant property; - RINOK(agent->GetArchive()->GetProperty(itemIndex, kpidMTime, &property)); - if (property.vt == VT_FILETIME) - fileTime = property.filetime; - else if (property.vt == VT_EMPTY) - fileTime = agent->DefaultTime; - else - throw 4190407; - return S_OK; -} - static HRESULT EnumerateArchiveItems(CAgent *agent, const CProxyFolder &item, const UString &prefix, @@ -110,8 +90,7 @@ static HRESULT EnumerateArchiveItems(CAgent *agent, { const CProxyFile &fileItem = item.Files[i]; CArcItem ai; - - RINOK(::GetFileTime(agent, fileItem.Index, ai.MTime)); + RINOK(agent->GetArc().GetItemMTime(fileItem.Index, ai.MTime, ai.MTimeDefined)); CPropVariant property; agent->GetArchive()->GetProperty(fileItem.Index, kpidSize, &property); @@ -128,10 +107,10 @@ static HRESULT EnumerateArchiveItems(CAgent *agent, { const CProxyFolder &dirItem = item.Folders[i]; UString fullName = prefix + dirItem.Name; - if(dirItem.IsLeaf) + if (dirItem.IsLeaf) { CArcItem ai; - RINOK(::GetFileTime(agent, dirItem.Index, ai.MTime)); + RINOK(agent->GetArc().GetItemMTime(dirItem.Index, ai.MTime, ai.MTimeDefined)); ai.IsDir = true; ai.SizeDefined = false; ai.Name = fullName; @@ -149,7 +128,7 @@ struct CAgUpCallbackImp: public IUpdateProduceCallback const CObjectVector<CArcItem> *_arcItems; IFolderArchiveUpdateCallback *_callback; - CAgUpCallbackImp(const CObjectVector<CArcItem> *a, + CAgUpCallbackImp(const CObjectVector<CArcItem> *a, IFolderArchiveUpdateCallback *callback): _arcItems(a), _callback(callback) {} HRESULT ShowDeleteFile(int arcIndex); }; @@ -268,7 +247,7 @@ STDMETHODIMP CAgent::DoOperation( { UString resultPath; int pos; - if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos)) + if (!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos)) return E_FAIL; NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos)); } @@ -316,7 +295,7 @@ STDMETHODIMP CAgent::DoOperation( if (!sfxStreamSpec->Open(sfxModule)) return E_FAIL; // throw "Can't open sfx module"; - RINOK(CopyBlock(sfxStream, outStream)); + RINOK(NCompress::CopyStream(sfxStream, outStream, NULL)); } RINOK(outArchive->UpdateItems(outStream, updatePairs2.Size(),updateCallback)); @@ -350,7 +329,7 @@ HRESULT CAgent::CommonUpdate( { UString resultPath; int pos; - if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos)) + if (!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos)) throw 141716; NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos)); } @@ -362,8 +341,8 @@ HRESULT CAgent::CommonUpdate( resultName = newArchiveName; if (i > 0) { - wchar_t s[32]; - ConvertUInt64ToString(i, s); + wchar_t s[16]; + ConvertUInt32ToString(i, s); resultName += s; } if (outStreamSpec->Open(realPath)) @@ -515,11 +494,11 @@ HRESULT CAgent::RenameItem( CUpdatePair2 up2; up2.NewData = false; up2.NewProps = true; - RINOK(IsArchiveItemAnti(GetArchive(), i, up2.IsAnti)); + RINOK(GetArc().IsItemAnti(i, up2.IsAnti)); up2.ArcIndex = i; UString oldFullPath; - RINOK(GetArchiveItemPath(GetArchive(), i, DefaultName, oldFullPath)); + RINOK(GetArc().GetItemPath(i, oldFullPath)); if (oldItemPath.CompareNoCase(oldFullPath.Left(oldItemPath.Length())) != 0) return E_INVALIDARG; @@ -543,7 +522,7 @@ HRESULT CAgent::RenameItem( } STDMETHODIMP CAgent::SetProperties(const wchar_t **names, - const PROPVARIANT *values, INT32 numProperties) + const PROPVARIANT *values, Int32 numProperties) { m_PropNames.Clear(); m_PropValues.Clear(); diff --git a/CPP/7zip/UI/Agent/AgentProxy.cpp b/CPP/7zip/UI/Agent/AgentProxy.cpp index 0a2de592..9686cf34 100755 --- a/CPP/7zip/UI/Agent/AgentProxy.cpp +++ b/CPP/7zip/UI/Agent/AgentProxy.cpp @@ -2,18 +2,14 @@ #include "StdAfx.h" -#include "AgentProxy.h" +#include "../../../../C/Sort.h" -#include "Common/MyCom.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" -#include "Windows/Defs.h" + #include "../Common/OpenArchive.h" -extern "C" -{ - #include "../../../../C/Sort.h" -} +#include "AgentProxy.h" using namespace NWindows; @@ -58,7 +54,7 @@ CProxyFolder* CProxyFolder::AddDirSubItem(UInt32 index, bool leaf, const UString if (folderIndex >= 0) { CProxyFolder *item = &Folders[folderIndex]; - if(leaf) + if (leaf) { item->Index = index; item->IsLeaf = true; @@ -116,16 +112,16 @@ void CProxyFolder::AddRealIndices(CUIntVector &realIndices) const if (IsLeaf) realIndices.Add(Index); int i; - for(i = 0; i < Folders.Size(); i++) + for (i = 0; i < Folders.Size(); i++) Folders[i].AddRealIndices(realIndices); - for(i = 0; i < Files.Size(); i++) + for (i = 0; i < Files.Size(); i++) realIndices.Add(Files[i].Index); } void CProxyFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const { realIndices.Clear(); - for(UInt32 i = 0; i < numItems; i++) + for (UInt32 i = 0; i < numItems; i++) { int index = indices[i]; int numDirItems = Folders.Size(); @@ -140,24 +136,6 @@ void CProxyFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntV /////////////////////////////////////////////// // CProxyArchive -HRESULT CProxyArchive::Reload(IInArchive *archive, IProgress *progress) -{ - RootFolder.Clear(); - return ReadObjects(archive, progress); -} - -HRESULT CProxyArchive::Load(IInArchive *archive, - const UString &defaultName, - // const FILETIME &defaultTime, - // UInt32 defaultAttributes, - IProgress *progress) -{ - DefaultName = defaultName; - // DefaultTime = defaultTime; - // DefaultAttributes = defaultAttributes; - return Reload(archive, progress); -} - static UInt64 GetSize(IInArchive *archive, UInt32 index, PROPID propID) { NCOM::CPropVariant prop; @@ -182,13 +160,8 @@ void CProxyFolder::CalculateSizes(IInArchive *archive) PackSize += GetSize(archive, index, kpidPackSize); { NCOM::CPropVariant prop; - if (archive->GetProperty(index, kpidCRC, &prop) == S_OK) - { - if (prop.vt == VT_UI4) - Crc += prop.ulVal; - else - CrcIsDefined = false; - } + if (archive->GetProperty(index, kpidCRC, &prop) == S_OK && prop.vt == VT_UI4) + Crc += prop.ulVal; else CrcIsDefined = false; } @@ -207,70 +180,67 @@ void CProxyFolder::CalculateSizes(IInArchive *archive) } } -HRESULT CProxyArchive::ReadObjects(IInArchive *archive, IProgress *progress) +HRESULT CProxyArchive::Load(const CArc &arc, IProgress *progress) { + RootFolder.Clear(); + IInArchive *archive = arc.Archive; + { + ThereIsPathProp = false; + UInt32 numProps; + archive->GetNumberOfProperties(&numProps); + for (UInt32 i = 0; i < numProps; i++) + { + CMyComBSTR name; + PROPID propID; + VARTYPE varType; + RINOK(archive->GetPropertyInfo(i, &name, &propID, &varType)); + if (propID == kpidPath) + { + ThereIsPathProp = true; + break; + } + } + } + UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); if (progress != NULL) { - UINT64 totalItems = numItems; + UInt64 totalItems = numItems; RINOK(progress->SetTotal(totalItems)); } - for(UInt32 i = 0; i < numItems; i++) + UString fileName; + for (UInt32 i = 0; i < numItems; i++) { - if (progress != NULL) + if (progress != NULL && (i & 0xFFFFF) == 0) { - UINT64 currentItemIndex = i; + UInt64 currentItemIndex = i; RINOK(progress->SetCompleted(¤tItemIndex)); } - NCOM::CPropVariant propVariantPath; - RINOK(archive->GetProperty(i, kpidPath, &propVariantPath)); - CProxyFolder *currentItem = &RootFolder; - UString fileName; - if(propVariantPath.vt == VT_EMPTY) + UString filePath; + RINOK(arc.GetItemPath(i, filePath)); + CProxyFolder *curItem = &RootFolder; + int len = filePath.Length(); + fileName.Empty(); + for (int j = 0; j < len; j++) { - fileName = DefaultName; - - NCOM::CPropVariant prop; - RINOK(archive->GetProperty(i, kpidExtension, &prop)); - if (prop.vt == VT_BSTR) + wchar_t c = filePath[j]; + if (c == WCHAR_PATH_SEPARATOR || c == L'/') { - fileName += L'.'; - fileName += prop.bstrVal; - } - else if (prop.vt != VT_EMPTY) - return E_FAIL; - - } - else - { - if(propVariantPath.vt != VT_BSTR) - return E_FAIL; - UString filePath = propVariantPath.bstrVal; - - int len = filePath.Length(); - for (int i = 0; i < len; i++) - { - wchar_t c = filePath[i]; - if (c == WCHAR_PATH_SEPARATOR || c == L'/') - { - currentItem = currentItem->AddDirSubItem((UInt32)(Int32)-1, false, fileName); - fileName.Empty(); - } - else - fileName += c; + curItem = curItem->AddDirSubItem((UInt32)(Int32)-1, false, fileName); + fileName.Empty(); } + else + fileName += c; } - NCOM::CPropVariant propVariantIsFolder; bool isFolder; RINOK(IsArchiveItemFolder(archive, i, isFolder)); - if(isFolder) - currentItem->AddDirSubItem(i, true, fileName); + if (isFolder) + curItem->AddDirSubItem(i, true, fileName); else - currentItem->AddFileSubItem(i, fileName); + curItem->AddFileSubItem(i, fileName); } RootFolder.CalculateSizes(archive); return S_OK; } - diff --git a/CPP/7zip/UI/Agent/AgentProxy.h b/CPP/7zip/UI/Agent/AgentProxy.h index a0111088..d4caca16 100755 --- a/CPP/7zip/UI/Agent/AgentProxy.h +++ b/CPP/7zip/UI/Agent/AgentProxy.h @@ -5,18 +5,16 @@ #include "Common/MyString.h" -#include "../../Archive/IArchive.h" +#include "../Common/OpenArchive.h" -class CProxyFile +struct CProxyFile { -public: UInt32 Index; UString Name; }; -class CProxyFolder: public CProxyFile +struct CProxyFolder: public CProxyFile { -public: CProxyFolder *Parent; CObjectVector<CProxyFolder> Folders; CObjectVector<CProxyFile> Files; @@ -44,20 +42,12 @@ public: void CalculateSizes(IInArchive *archive); }; -class CProxyArchive +struct CProxyArchive { - HRESULT ReadObjects(IInArchive *archive, IProgress *progress); -public: - UString DefaultName; - // FILETIME DefaultTime; - // UInt32 DefaultAttributes; CProxyFolder RootFolder; - HRESULT Reload(IInArchive *archive, IProgress *progress); - HRESULT Load(IInArchive *archive, - const UString &defaultName, - // const FILETIME &defaultTime, - // UInt32 defaultAttributes, - IProgress *progress); + bool ThereIsPathProp; + + HRESULT Load(const CArc &arc, IProgress *progress); }; -#endif
\ No newline at end of file +#endif diff --git a/CPP/7zip/UI/Agent/ArchiveFolder.cpp b/CPP/7zip/UI/Agent/ArchiveFolder.cpp index 780d26b8..57975e7d 100755 --- a/CPP/7zip/UI/Agent/ArchiveFolder.cpp +++ b/CPP/7zip/UI/Agent/ArchiveFolder.cpp @@ -1,17 +1,9 @@ -// Zip/ArchiveFolder.cpp +// Agent/ArchiveFolder.cpp #include "StdAfx.h" #include "Common/ComTry.h" -#include "Common/StringConvert.h" -#include "Windows/Defs.h" -#include "Windows/PropVariant.h" -#include "Windows/PropVariantConversions.h" -#include "Windows/FileDir.h" -#include "../../Common/FileStreams.h" - -#include "../Common/UpdatePair.h" #include "../Common/ArchiveExtractCallback.h" #include "Agent.h" @@ -19,7 +11,7 @@ using namespace NWindows; using namespace NCOM; -STDMETHODIMP CAgentFolder::CopyTo(const UINT32 *indices, UINT32 numItems, +STDMETHODIMP CAgentFolder::CopyTo(const UInt32 *indices, UInt32 numItems, const wchar_t *path, IFolderOperationsExtractCallback *callback) { COM_TRY_BEGIN @@ -46,18 +38,12 @@ STDMETHODIMP CAgentFolder::CopyTo(const UINT32 *indices, UINT32 numItems, NExtract::NPathMode::kCurrentPathnames; extractCallbackSpec->InitForMulti(false, pathMode, NExtract::NOverwriteMode::kAskBefore); - extractCallbackSpec->Init(_agentSpec->GetArchive(), + extractCallbackSpec->Init(NULL, &_agentSpec->GetArc(), extractCallback2, - false, + false, false, false, path, pathParts, - _agentSpec->DefaultName, - _agentSpec->DefaultTime, - _agentSpec->DefaultAttrib, - (UInt64)(Int64)-1 - - // ,_agentSpec->_srcDirectoryPrefix - ); + (UInt64)(Int64)-1); CUIntVector realIndices; GetRealIndices(indices, numItems, realIndices); return _agentSpec->GetArchive()->Extract(&realIndices.Front(), @@ -65,7 +51,7 @@ STDMETHODIMP CAgentFolder::CopyTo(const UINT32 *indices, UINT32 numItems, COM_TRY_END } -STDMETHODIMP CAgentFolder::MoveTo(const UINT32 * /* indices */, UINT32 /* numItems */, +STDMETHODIMP CAgentFolder::MoveTo(const UInt32 * /* indices */, UInt32 /* numItems */, const wchar_t * /* path */, IFolderOperationsExtractCallback * /* callback */) { return E_NOTIMPL; diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp index f339a287..98c75f4d 100755 --- a/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp +++ b/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp @@ -6,8 +6,6 @@ #include "Common/StringConvert.h" -#include "../Common/OpenArchive.h" - static inline UINT GetCurrentFileCodePage() { return AreFileApisANSI() ? CP_ACP : CP_OEMCP; } @@ -28,7 +26,7 @@ int CArchiveFolderManager::FindFormat(const UString &type) return -1; } -STDMETHODIMP CArchiveFolderManager::OpenFolderFile(const wchar_t *filePath, +STDMETHODIMP CArchiveFolderManager::OpenFolderFile(IInStream *inStream, const wchar_t *filePath, IFolderFolder **resultFolder, IProgress *progress) { CMyComPtr<IArchiveOpenCallback> openArchiveCallback; @@ -39,7 +37,7 @@ STDMETHODIMP CArchiveFolderManager::OpenFolderFile(const wchar_t *filePath, } CAgent *agent = new CAgent(); CMyComPtr<IInFolderArchive> archive = agent; - RINOK(agent->Open(filePath, NULL, openArchiveCallback)); + RINOK(agent->Open(inStream, filePath, NULL, openArchiveCallback)); return agent->BindToRootFolder(resultFolder); } diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp index 304dce83..8f03f44d 100755 --- a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp +++ b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp @@ -1,17 +1,15 @@ // FolderOut.cpp #include "StdAfx.h" -#include "Agent.h" -#include "Common/StringConvert.h" #include "Common/ComTry.h" + #include "Windows/FileDir.h" -// #include "../Common/CompressEngineCommon.h" -#include "../Common/ZipRegistry.h" -#include "../Common/UpdateAction.h" #include "../Common/WorkDir.h" +#include "Agent.h" + using namespace NWindows; using namespace NFile; using namespace NDirectory; @@ -35,7 +33,7 @@ HRESULT CAgentFolder::CommonUpdateOperation( NWorkDir::CInfo workDirInfo; ReadWorkDirInfo(workDirInfo); UString archiveFilePath = _agentSpec->_archiveFilePath; - UString workDir = GetWorkDir(workDirInfo, archiveFilePath ); + UString workDir = GetWorkDir(workDirInfo, archiveFilePath); CreateComplexDirectory(workDir); CTempFileW tempFile; @@ -86,11 +84,12 @@ HRESULT CAgentFolder::CommonUpdateOperation( // m_FolderItem = NULL; - if (!DeleteFileAlways(archiveFilePath )) - return GetLastError(); + if (NFind::DoesFileExist(archiveFilePath)) + if (!DeleteFileAlways(archiveFilePath)) + return GetLastError(); tempFile.DisableDeleting(); - if (!MyMoveFile(tempFileName, archiveFilePath )) + if (!MyMoveFile(tempFileName, archiveFilePath)) return GetLastError(); { @@ -134,17 +133,23 @@ STDMETHODIMP CAgentFolder::CopyFrom( IProgress *progress) { COM_TRY_BEGIN - RINOK(_agentSpec->SetFiles(fromFolderPath, itemsPaths, numItems)); - RINOK(_agentSpec->SetFolder(this)); CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100; if (progress != 0) { - CMyComPtr<IProgress> progressWrapper = progress; - RINOK(progressWrapper.QueryInterface( - IID_IFolderArchiveUpdateCallback, &updateCallback100)); + RINOK(progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&updateCallback100)); + } + try + { + RINOK(_agentSpec->SetFiles(fromFolderPath, itemsPaths, numItems)); + RINOK(_agentSpec->SetFolder(this)); + return CommonUpdateOperation(false, false, false, NULL, + &NUpdateArchive::kAddActionSet, 0, 0, updateCallback100); + } + catch(const UString &s) + { + RINOK(updateCallback100->UpdateErrorMessage(UString(L"Error: ") + s)); + return E_FAIL; } - return CommonUpdateOperation(false, false, false, NULL, - &NUpdateArchive::kAddActionSet, 0, 0, updateCallback100); COM_TRY_END } diff --git a/CPP/7zip/UI/Agent/IFolderArchive.h b/CPP/7zip/UI/Agent/IFolderArchive.h index 7bb12482..91da1150 100755 --- a/CPP/7zip/UI/Agent/IFolderArchive.h +++ b/CPP/7zip/UI/Agent/IFolderArchive.h @@ -3,14 +3,13 @@ #ifndef __IFOLDER_ARCHIVE_H #define __IFOLDER_ARCHIVE_H +#include "../../IDecl.h" #include "../../Archive/IArchive.h" -// #include "../Format/Common/ArchiveInterface.h" -#include "../../UI/FileManager/IFolder.h" -#include "../Common/IFileExtractCallback.h" -#include "../Common/ExtractMode.h" #include "../../UI/Common/LoadCodecs.h" +#include "../../UI/FileManager/IFolder.h" -#include "../../IDecl.h" +#include "../Common/ExtractMode.h" +#include "../Common/IFileExtractCallback.h" #define FOLDER_ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 0x01, x) #define FOLDER_ARCHIVE_INTERFACE(i, x) FOLDER_ARCHIVE_INTERFACE_SUB(i, IUnknown, x) @@ -28,7 +27,7 @@ FOLDER_ARCHIVE_INTERFACE(IArchiveFolder, 0x05) }; #define INTERFACE_IInFolderArchive(x) \ - STDMETHOD(Open)(const wchar_t *filePath, BSTR *archiveType, IArchiveOpenCallback *openArchiveCallback) x; \ + STDMETHOD(Open)(IInStream *inStream, const wchar_t *filePath, BSTR *archiveType, IArchiveOpenCallback *openArchiveCallback) x; \ STDMETHOD(ReOpen)(IArchiveOpenCallback *openArchiveCallback) x; \ STDMETHOD(Close)() x; \ STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \ @@ -38,7 +37,7 @@ FOLDER_ARCHIVE_INTERFACE(IArchiveFolder, 0x05) NExtract::NOverwriteMode::EEnum overwriteMode, const wchar_t *path, \ Int32 testMode, IFolderArchiveExtractCallback *extractCallback2) x; \ -FOLDER_ARCHIVE_INTERFACE(IInFolderArchive, 0x06) +FOLDER_ARCHIVE_INTERFACE(IInFolderArchive, 0x0D) { INTERFACE_IInFolderArchive(PURE) }; diff --git a/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp index e14197d2..21549c90 100755 --- a/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp +++ b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp @@ -90,19 +90,29 @@ HRESULT CUpdateCallbackAgent::SetOperationResult(Int32 operationResult) HRESULT CUpdateCallbackAgent::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { + *password = NULL; *passwordIsDefined = BoolToInt(false); if (!_cryptoGetTextPassword) { if (!Callback) return S_OK; - HRESULT result = Callback.QueryInterface( - IID_ICryptoGetTextPassword2, &_cryptoGetTextPassword); - if (result != S_OK) + Callback.QueryInterface(IID_ICryptoGetTextPassword2, &_cryptoGetTextPassword); + if (!_cryptoGetTextPassword) return S_OK; } return _cryptoGetTextPassword->CryptoGetTextPassword2(passwordIsDefined, password); } +HRESULT CUpdateCallbackAgent::CryptoGetTextPassword(BSTR *password) +{ + *password = NULL; + CMyComPtr<ICryptoGetTextPassword> getTextPassword; + Callback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); + if (!getTextPassword) + return E_NOTIMPL; + return getTextPassword->CryptoGetTextPassword(password); +} + /* HRESULT CUpdateCallbackAgent::ShowDeleteFile(const wchar_t *name) { diff --git a/CPP/7zip/UI/Client7z/Client7z.cpp b/CPP/7zip/UI/Client7z/Client7z.cpp index a63144a7..7c052171 100755 --- a/CPP/7zip/UI/Client7z/Client7z.cpp +++ b/CPP/7zip/UI/Client7z/Client7z.cpp @@ -330,7 +330,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, else { NFile::NFind::CFileInfoW fi; - if (NFile::NFind::FindFile(fullProcessedPath, fi)) + if (fi.Find(fullProcessedPath)) { if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) { @@ -621,8 +621,8 @@ STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) { - wchar_t temp[32]; - ConvertUInt64ToString(index + 1, temp); + wchar_t temp[16]; + ConvertUInt32ToString(index + 1, temp); UString res = temp; while (res.Length() < 2) res = UString(L'0') + res; @@ -707,7 +707,7 @@ int MY_CDECL main(int argc, char* argv[]) UString name = GetUnicodeString(argv[i], CP_OEMCP); NFile::NFind::CFileInfoW fi; - if (!NFile::NFind::FindFile(name, fi)) + if (!fi.Find(name)) { PrintString(UString(L"Can't find file") + name); return 1; diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp index 46e8a2a1..96d47c08 100755 --- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp @@ -11,18 +11,18 @@ #include "Common/StringConvert.h" #include "Common/StringToInt.h" -#include "Windows/FileName.h" #include "Windows/FileDir.h" +#include "Windows/FileName.h" #ifdef _WIN32 #include "Windows/FileMapping.h" #include "Windows/Synchronization.h" #endif #include "ArchiveCommandLine.h" -#include "UpdateAction.h" -#include "Update.h" -#include "SortUtils.h" #include "EnumDirItems.h" +#include "SortUtils.h" +#include "Update.h" +#include "UpdateAction.h" extern bool g_CaseSensitive; @@ -38,6 +38,8 @@ using namespace NCommandLineParser; using namespace NWindows; using namespace NFile; +int g_CodePage = -1; + namespace NKey { enum Enum { @@ -69,10 +71,12 @@ enum Enum kEmail, kShowDialog, kLargePages, - kCharSet, + kListfileCharSet, + kConsoleCharSet, kTechMode, kShareForWrite, - kCaseSensitive + kCaseSensitive, + kCalcCrc, }; } @@ -137,9 +141,11 @@ static const CSwitchForm kSwitchForms[] = { L"AD", NSwitchType::kSimple, false }, { L"SLP", NSwitchType::kUnLimitedPostString, false, 0}, { L"SCS", NSwitchType::kUnLimitedPostString, false, 0}, + { L"SCC", NSwitchType::kUnLimitedPostString, false, 0}, { L"SLT", NSwitchType::kSimple, false }, { L"SSW", NSwitchType::kSimple, false }, - { L"SSC", NSwitchType::kPostChar, false, 0, 0, L"-" } + { L"SSC", NSwitchType::kPostChar, false, 0, 0, L"-" }, + { L"SCRC", NSwitchType::kSimple, false } }; static const CCommandForm g_CommandForms[] = @@ -412,9 +418,9 @@ static void ConvertToLongName(const UString &prefix, UString &name) { if (name.IsEmpty() || DoesNameContainWildCard(name)) return; - NFind::CFileInfoW fileInfo; - if (NFind::FindFile(prefix + name, fileInfo)) - name = fileInfo.Name; + NFind::CFileInfoW fi; + if (fi.Find(prefix + name)) + name = fi.Name; } static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items) @@ -698,6 +704,7 @@ void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings, options.IsInTerminal = MY_IS_TERMINAL(stdin); options.IsStdOutTerminal = MY_IS_TERMINAL(stdout); options.IsStdErrTerminal = MY_IS_TERMINAL(stderr); + options.StdInMode = parser[NKey::kStdIn].ThereIs; options.StdOutMode = parser[NKey::kStdOut].ThereIs; options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs; options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs; @@ -722,11 +729,28 @@ struct CCodePagePair static CCodePagePair g_CodePagePairs[] = { { L"UTF-8", CP_UTF8 }, - { L"WIN", CP_ACP }, - { L"DOS", CP_OEMCP } + { L"WIN", CP_ACP }, + { L"DOS", CP_OEMCP } }; -static const int kNumCodePages = sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0]); +static int FindCharset(const NCommandLineParser::CParser &parser, int keyIndex, int defaultVal) +{ + if (!parser[keyIndex].ThereIs) + return defaultVal; + + UString name = parser[keyIndex].PostStrings.Back(); + name.MakeUpper(); + int i; + for (i = 0; i < sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0]); i++) + { + const CCodePagePair &pair = g_CodePagePairs[i]; + if (name.Compare(pair.Name) == 0) + return pair.CodePage; + } + if (i == sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0])) + ThrowUserErrorException(); + return -1; +} static bool ConvertStringToUInt32(const wchar_t *s, UInt32 &v) { @@ -751,6 +775,7 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) ThrowUserErrorException(); options.TechMode = parser[NKey::kTechMode].ThereIs; + options.CalcCrc = parser[NKey::kCalcCrc].ThereIs; if (parser[NKey::kCaseSensitive].ThereIs) g_CaseSensitive = (parser[NKey::kCaseSensitive].PostCharIndex < 0); @@ -761,24 +786,8 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) else recursedType = NRecursedType::kNonRecursed; - UINT codePage = CP_UTF8; - if (parser[NKey::kCharSet].ThereIs) - { - UString name = parser[NKey::kCharSet].PostStrings.Front(); - name.MakeUpper(); - int i; - for (i = 0; i < kNumCodePages; i++) - { - const CCodePagePair &pair = g_CodePagePairs[i]; - if (name.Compare(pair.Name) == 0) - { - codePage = pair.CodePage; - break; - } - } - if (i >= kNumCodePages) - ThrowUserErrorException(); - } + g_CodePage = FindCharset(parser, NKey::kConsoleCharSet, -1); + UINT codePage = FindCharset(parser, NKey::kListfileCharSet, CP_UTF8); bool thereAreSwitchIncludes = false; if (parser[NKey::kInclude].ThereIs) @@ -795,6 +804,13 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs && options.Command.CommandType != NCommandType::kBenchmark && options.Command.CommandType != NCommandType::kInfo; + + bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); + bool isExtractOrList = isExtractGroupCommand || options.Command.CommandType == NCommandType::kList; + + if (isExtractOrList && options.StdInMode) + thereIsArchiveName = false; + if (thereIsArchiveName) { if (curCommandIndex >= numNonSwitchStrings) @@ -808,7 +824,6 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) options.YesToAll = parser[NKey::kYes].ThereIs; - bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); #ifndef _NO_CRYPTO options.PasswordEnabled = parser[NKey::kPassword].ThereIs; @@ -816,16 +831,13 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) options.Password = parser[NKey::kPassword].PostStrings[0]; #endif - options.StdInMode = parser[NKey::kStdIn].ThereIs; options.ShowDialog = parser[NKey::kShowDialog].ThereIs; if (parser[NKey::kArchiveType].ThereIs) options.ArcType = parser[NKey::kArchiveType].PostStrings[0]; - if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) + if (isExtractOrList) { - if (options.StdInMode) - ThrowException("Reading archives from stdin is not implemented"); if (!options.WildcardCensor.AllAreRelative()) ThrowException("Cannot use absolute pathnames for this command"); @@ -849,6 +861,15 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) archiveWildcardCensor.ExtendExclude(); + if (options.StdInMode) + { + UString arcName = parser[NKey::kStdIn].PostStrings.Front(); + options.ArchivePathsSorted.Add(arcName); + options.ArchivePathsFullSorted.Add(arcName); + } + else + { + UStringVector archivePaths; { @@ -889,6 +910,8 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) options.ArchivePathsSorted.Add(archivePaths[indices[i]]); options.ArchivePathsFullSorted.Add(archivePathsFull[indices[i]]); } + + } if (isExtractGroupCommand) { diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.h b/CPP/7zip/UI/Common/ArchiveCommandLine.h index 9c37f336..6f79b7ee 100755 --- a/CPP/7zip/UI/Common/ArchiveCommandLine.h +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.h @@ -73,6 +73,7 @@ struct CArchiveCommandLineOptions bool TechMode; // Extract + bool CalcCrc; bool AppendName; UString OutputDir; NExtract::NOverwriteMode::EEnum OverwriteMode; diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp index 5af5286b..4c0cc90b 100755 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp @@ -2,24 +2,19 @@ #include "StdAfx.h" -#include "ArchiveExtractCallback.h" - -#include "Common/Wildcard.h" -#include "Common/StringConvert.h" #include "Common/ComTry.h" +#include "Common/Wildcard.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" -#include "Windows/Time.h" -#include "Windows/Defs.h" #include "Windows/PropVariant.h" - #include "Windows/PropVariantConversions.h" #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" -#include "OpenArchive.h" + +#include "ArchiveExtractCallback.h" using namespace NWindows; @@ -27,20 +22,20 @@ static const wchar_t *kCantAutoRename = L"ERROR: Can not create file with auto n static const wchar_t *kCantRenameFile = L"ERROR: Can not rename existing file "; static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; - void CArchiveExtractCallback::Init( - IInArchive *archiveHandler, + const NWildcard::CCensorNode *wildcardCensor, + const CArc *arc, IFolderArchiveExtractCallback *extractCallback2, - bool stdOutMode, + bool stdOutMode, bool testMode, bool crcMode, const UString &directoryPath, const UStringVector &removePathParts, - const UString &itemDefaultName, - const FILETIME &utcMTimeDefault, - UInt32 attributesDefault, UInt64 packSize) { + _wildcardCensor = wildcardCensor; + _stdOutMode = stdOutMode; - _numErrors = 0; + _testMode = testMode; + _crcMode = crcMode; _unpTotal = 1; _packTotal = packSize; @@ -51,11 +46,9 @@ void CArchiveExtractCallback::Init( LocalProgressSpec->Init(extractCallback2, true); LocalProgressSpec->SendProgress = false; - _itemDefaultName = itemDefaultName; - _utcMTimeDefault = utcMTimeDefault; - _attributesDefault = attributesDefault; + _removePathParts = removePathParts; - _archiveHandler = archiveHandler; + _arc = arc; _directoryPath = directoryPath; NFile::NName::NormalizeDirPathPrefix(_directoryPath); } @@ -117,7 +110,7 @@ STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const U void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath) { fullPath = _directoryPath; - for(int i = 0; i < dirPathParts.Size(); i++) + for (int i = 0; i < dirPathParts.Size(); i++) { if (i > 0) fullPath += wchar_t(NFile::NName::kDirDelimiter); @@ -126,24 +119,11 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat } } -static UString MakePathNameFromParts(const UStringVector &parts) -{ - UString result; - for(int i = 0; i < parts.Size(); i++) - { - if(i != 0) - result += wchar_t(NFile::NName::kDirDelimiter); - result += parts[i]; - } - return result; -} - - HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined) { filetimeIsDefined = false; NCOM::CPropVariant prop; - RINOK(_archiveHandler->GetProperty(index, propID, &prop)); + RINOK(_arc->Archive->GetProperty(index, propID, &prop)); if (prop.vt == VT_FILETIME) { filetime = prop.filetime; @@ -154,26 +134,40 @@ HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &fil return S_OK; } +HRESULT CArchiveExtractCallback::GetUnpackSize() +{ + NCOM::CPropVariant prop; + RINOK(_arc->Archive->GetProperty(_index, kpidSize, &prop)); + _curSizeDefined = (prop.vt != VT_EMPTY); + if (_curSizeDefined) + _curSize = ConvertPropVariantToUInt64(prop); + return S_OK; +} + STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { COM_TRY_BEGIN + _crcStream.Release(); *outStream = 0; _outFileStream.Release(); _encrypted = false; _isSplit = false; _curSize = 0; + _curSizeDefined = false; + _index = index; UString fullPath; - RINOK(GetArchiveItemPath(_archiveHandler, index, _itemDefaultName, fullPath)); - RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.IsDir)); + IInArchive *archive = _arc->Archive; + RINOK(_arc->GetItemPath(index, fullPath)); + RINOK(IsArchiveItemFolder(archive, index, _fi.IsDir)); _filePath = fullPath; { NCOM::CPropVariant prop; - RINOK(_archiveHandler->GetProperty(index, kpidPosition, &prop)); + RINOK(archive->GetProperty(index, kpidPosition, &prop)); if (prop.vt != VT_EMPTY) { if (prop.vt != VT_UI8) @@ -183,22 +177,17 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre } } - RINOK(IsArchiveItemProp(_archiveHandler, index, kpidEncrypted, _encrypted)); + RINOK(GetArchiveItemBoolProp(archive, index, kpidEncrypted, _encrypted)); + + RINOK(GetUnpackSize()); - bool newFileSizeDefined; - UInt64 newFileSize; + if (_wildcardCensor) { - NCOM::CPropVariant prop; - RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop)); - newFileSizeDefined = (prop.vt != VT_EMPTY); - if (newFileSizeDefined) - { - newFileSize = ConvertPropVariantToUInt64(prop); - _curSize = newFileSize; - } + if (!_wildcardCensor->CheckPath(fullPath, !_fi.IsDir)) + return S_OK; } - if(askExtractMode == NArchive::NExtract::NAskMode::kExtract) + if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) { if (_stdOutMode) { @@ -209,32 +198,29 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre { NCOM::CPropVariant prop; - RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop)); - if (prop.vt == VT_EMPTY) + RINOK(archive->GetProperty(index, kpidAttrib, &prop)); + if (prop.vt == VT_UI4) { - _processedFileInfo.Attributes = _attributesDefault; - _processedFileInfo.AttributesAreDefined = false; + _fi.Attrib = prop.ulVal; + _fi.AttribDefined = true; } + else if (prop.vt == VT_EMPTY) + _fi.AttribDefined = false; else - { - if (prop.vt != VT_UI4) - return E_FAIL; - _processedFileInfo.Attributes = prop.ulVal; - _processedFileInfo.AttributesAreDefined = true; - } + return E_FAIL; } - RINOK(GetTime(index, kpidCTime, _processedFileInfo.CTime, _processedFileInfo.CTimeDefined)); - RINOK(GetTime(index, kpidATime, _processedFileInfo.ATime, _processedFileInfo.ATimeDefined)); - RINOK(GetTime(index, kpidMTime, _processedFileInfo.MTime, _processedFileInfo.MTimeDefined)); + RINOK(GetTime(index, kpidCTime, _fi.CTime, _fi.CTimeDefined)); + RINOK(GetTime(index, kpidATime, _fi.ATime, _fi.ATimeDefined)); + RINOK(GetTime(index, kpidMTime, _fi.MTime, _fi.MTimeDefined)); bool isAnti = false; - RINOK(IsArchiveItemProp(_archiveHandler, index, kpidIsAnti, isAnti)); + RINOK(_arc->IsItemAnti(index, isAnti)); UStringVector pathParts; SplitPathToParts(fullPath, pathParts); - if(pathParts.IsEmpty()) + if (pathParts.IsEmpty()) return E_FAIL; int numRemovePathParts = 0; switch(_pathMode) @@ -262,7 +248,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre UString processedPath = MakePathNameFromParts(pathParts); if (!isAnti) { - if (!_processedFileInfo.IsDir) + if (!_fi.IsDir) { if (!pathParts.IsEmpty()) pathParts.DeleteBack(); @@ -272,18 +258,18 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre { UString fullPathNew; CreateComplexDirectory(pathParts, fullPathNew); - if (_processedFileInfo.IsDir) + if (_fi.IsDir) NFile::NDirectory::SetDirTime(fullPathNew, - (WriteCTime && _processedFileInfo.CTimeDefined) ? &_processedFileInfo.CTime : NULL, - (WriteATime && _processedFileInfo.ATimeDefined) ? &_processedFileInfo.ATime : NULL, - (WriteMTime && _processedFileInfo.MTimeDefined) ? &_processedFileInfo.MTime : &_utcMTimeDefault); + (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL, + (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL, + (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL)); } } UString fullProcessedPath = _directoryPath + processedPath; - if(_processedFileInfo.IsDir) + if (_fi.IsDir) { _diskFilePath = fullProcessedPath; if (isAnti) @@ -294,7 +280,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre if (!_isSplit) { NFile::NFind::CFileInfoW fileInfo; - if(NFile::NFind::FindFile(fullProcessedPath, fileInfo)) + if (fileInfo.Find(fullProcessedPath)) { switch(_overwriteMode) { @@ -305,8 +291,8 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre Int32 overwiteResult; RINOK(_extractCallback2->AskOverwrite( fullProcessedPath, &fileInfo.MTime, &fileInfo.Size, fullPath, - _processedFileInfo.MTimeDefined ? &_processedFileInfo.MTime : NULL, - newFileSizeDefined ? &newFileSize : NULL, + _fi.MTimeDefined ? &_fi.MTime : NULL, + _curSizeDefined ? &_curSize : NULL, &overwiteResult)) switch(overwiteResult) @@ -349,7 +335,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } - if(!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath)) + if (!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath)) { UString message = UString(kCantRenameFile) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); @@ -392,6 +378,17 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre { *outStream = NULL; } + if (_crcMode) + { + _crcStreamSpec = new COutStreamWithCRC; + _crcStream = _crcStreamSpec; + CMyComPtr<ISequentialOutStream> crcStream = _crcStreamSpec; + _crcStreamSpec->SetStream(*outStream); + if (*outStream) + (*outStream)->Release(); + *outStream = crcStream.Detach(); + _crcStreamSpec->Init(true); + } return S_OK; COM_TRY_END } @@ -403,9 +400,13 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: - _extractMode = true; + if (_testMode) + askExtractMode = NArchive::NExtract::NAskMode::kTest; + else + _extractMode = true; + break; }; - return _extractCallback2->PrepareOperation(_filePath, _processedFileInfo.IsDir, + return _extractCallback2->PrepareOperation(_filePath, _fi.IsDir, askExtractMode, _isSplit ? &_position: 0); COM_TRY_END } @@ -424,24 +425,35 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) _outFileStream.Release(); return E_FAIL; } - if (_outFileStream != NULL) + if (_crcStream) + { + CrcSum += _crcStreamSpec->GetCRC(); + _curSize = _crcStreamSpec->GetSize(); + _curSizeDefined = true; + _crcStream.Release(); + } + if (_outFileStream) { _outFileStreamSpec->SetTime( - (WriteCTime && _processedFileInfo.CTimeDefined) ? &_processedFileInfo.CTime : NULL, - (WriteATime && _processedFileInfo.ATimeDefined) ? &_processedFileInfo.ATime : NULL, - (WriteMTime && _processedFileInfo.MTimeDefined) ? &_processedFileInfo.MTime : &_utcMTimeDefault); + (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL, + (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL, + (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL)); _curSize = _outFileStreamSpec->ProcessedSize; + _curSizeDefined = true; RINOK(_outFileStreamSpec->Close()); _outFileStream.Release(); } - UnpackSize += _curSize; - if (_processedFileInfo.IsDir) + if (!_curSizeDefined) + GetUnpackSize(); + if (_curSizeDefined) + UnpackSize += _curSize; + if (_fi.IsDir) NumFolders++; else NumFiles++; - if (_extractMode && _processedFileInfo.AttributesAreDefined) - NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attributes); + if (_extractMode && _fi.AttribDefined) + NFile::NDirectory::MySetFileAttributes(_diskFilePath, _fi.Attrib); RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted)); return S_OK; COM_TRY_END diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h index e895c54b..367e4b07 100755 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h @@ -1,19 +1,23 @@ // ArchiveExtractCallback.h -#ifndef __ARCHIVEEXTRACTCALLBACK_H -#define __ARCHIVEEXTRACTCALLBACK_H +#ifndef __ARCHIVE_EXTRACT_CALLBACK_H +#define __ARCHIVE_EXTRACT_CALLBACK_H -#include "../../Archive/IArchive.h" -#include "IFileExtractCallback.h" - -#include "Common/MyString.h" #include "Common/MyCom.h" +#include "Common/Wildcard.h" + +#include "../../IPassword.h" #include "../../Common/FileStreams.h" #include "../../Common/ProgressUtils.h" -#include "../../IPassword.h" + +#include "../../Archive/IArchive.h" + +#include "../../Archive/Common/OutStreamWithCRC.h" #include "ExtractMode.h" +#include "IFileExtractCallback.h" +#include "OpenArchive.h" class CArchiveExtractCallback: public IArchiveExtractCallback, @@ -22,22 +26,8 @@ class CArchiveExtractCallback: public ICompressProgressInfo, public CMyUnknownImp { -public: - MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo) - // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback) - - INTERFACE_IArchiveExtractCallback(;) - - STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); - - // IArchiveVolumeExtractCallback - // STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream); - - // ICryptoGetTextPassword - STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword); - -private: - CMyComPtr<IInArchive> _archiveHandler; + const CArc *_arc; + const NWildcard::CCensorNode *_wildcardCensor; CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2; CMyComPtr<ICompressProgressInfo> _compressProgress; CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword; @@ -45,12 +35,11 @@ private: NExtract::NPathMode::EEnum _pathMode; NExtract::NOverwriteMode::EEnum _overwriteMode; + UString _diskFilePath; UString _filePath; UInt64 _position; bool _isSplit; - UString _diskFilePath; - bool _extractMode; bool WriteCTime; @@ -64,29 +53,61 @@ private: FILETIME CTime; FILETIME ATime; FILETIME MTime; - UInt32 Attributes; + UInt32 Attrib; bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; + bool AttribDefined; bool IsDir; - bool AttributesAreDefined; - } _processedFileInfo; + } _fi; + UInt32 _index; UInt64 _curSize; + bool _curSizeDefined; COutFileStream *_outFileStreamSpec; CMyComPtr<ISequentialOutStream> _outFileStream; + + COutStreamWithCRC *_crcStreamSpec; + CMyComPtr<ISequentialOutStream> _crcStream; + UStringVector _removePathParts; - UString _itemDefaultName; - FILETIME _utcMTimeDefault; - UInt32 _attributesDefault; bool _stdOutMode; + bool _testMode; + bool _crcMode; + bool _multiArchives; + + CMyComPtr<ICompressProgressInfo> _localProgress; + UInt64 _packTotal; + UInt64 _unpTotal; void CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath); HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined); + HRESULT GetUnpackSize(); + public: + + CLocalProgress *LocalProgressSpec; + + UInt64 NumFolders; + UInt64 NumFiles; + UInt64 UnpackSize; + UInt32 CrcSum; + + MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo) + // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback) + + INTERFACE_IArchiveExtractCallback(;) + + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); + + // IArchiveVolumeExtractCallback + // STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream); + + STDMETHOD(CryptoGetTextPassword)(BSTR *password); + CArchiveExtractCallback(): WriteCTime(true), WriteATime(true), @@ -97,37 +118,26 @@ public: _localProgress = LocalProgressSpec; } - CLocalProgress *LocalProgressSpec; - CMyComPtr<ICompressProgressInfo> _localProgress; - UInt64 _packTotal; - UInt64 _unpTotal; - - bool _multiArchives; - UInt64 NumFolders; - UInt64 NumFiles; - UInt64 UnpackSize; - void InitForMulti(bool multiArchives, NExtract::NPathMode::EEnum pathMode, NExtract::NOverwriteMode::EEnum overwriteMode) { - _multiArchives = multiArchives; NumFolders = NumFiles = UnpackSize = 0; + _multiArchives = multiArchives; _pathMode = pathMode; _overwriteMode = overwriteMode; + NumFolders = NumFiles = UnpackSize = 0; + CrcSum = 0; } void Init( - IInArchive *archiveHandler, + const NWildcard::CCensorNode *wildcardCensor, + const CArc *arc, IFolderArchiveExtractCallback *extractCallback2, - bool stdOutMode, + bool stdOutMode, bool testMode, bool crcMode, const UString &directoryPath, const UStringVector &removePathParts, - const UString &itemDefaultName, - const FILETIME &utcMTimeDefault, - UInt32 attributesDefault, UInt64 packSize); - UInt64 _numErrors; }; #endif diff --git a/CPP/7zip/UI/Common/ArchiveName.cpp b/CPP/7zip/UI/Common/ArchiveName.cpp index 9b9a4fe6..c3684def 100755 --- a/CPP/7zip/UI/Common/ArchiveName.cpp +++ b/CPP/7zip/UI/Common/ArchiveName.cpp @@ -2,12 +2,14 @@ #include "StdAfx.h" -#include "Windows/FileFind.h" #include "Windows/FileDir.h" +#include "Windows/FileFind.h" + +#include "ExtractingFilePath.h" using namespace NWindows; -UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) +static UString CreateArchiveName2(const UString &srcName, bool fromPrev, bool keepName) { UString resultName = L"Archive"; if (fromPrev) @@ -20,7 +22,7 @@ UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) { dirPrefix.Delete(dirPrefix.Length() - 1); NFile::NFind::CFileInfoW fileInfo; - if (NFile::NFind::FindFile(dirPrefix, fileInfo)) + if (fileInfo.Find(dirPrefix)) resultName = fileInfo.Name; } } @@ -28,8 +30,9 @@ UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) else { NFile::NFind::CFileInfoW fileInfo; - if (!NFile::NFind::FindFile(srcName, fileInfo)) - return resultName; + if (!fileInfo.Find(srcName)) + // return resultName; + return srcName; resultName = fileInfo.Name; if (!fileInfo.IsDir() && !keepName) { @@ -44,3 +47,8 @@ UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) } return resultName; } + +UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) +{ + return GetCorrectFsPath(CreateArchiveName2(srcName, fromPrev, keepName)); +} diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp index 8f289d1b..7188bcb6 100755 --- a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp @@ -2,14 +2,15 @@ #include "StdAfx.h" -#include "ArchiveOpenCallback.h" - #include "Common/StringConvert.h" #include "Common/ComTry.h" + #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" +#include "ArchiveOpenCallback.h" + using namespace NWindows; STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes) @@ -91,7 +92,7 @@ STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStre } *inStream = NULL; UString fullPath = _folderPrefix + name; - if (!NFile::NFind::FindFile(fullPath, _fileInfo)) + if (!_fileInfo.Find(fullPath)) return S_FALSE; if (_fileInfo.IsDir()) return S_FALSE; diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/CPP/7zip/UI/Common/ArchiveOpenCallback.h index ca445974..c6651e8f 100755 --- a/CPP/7zip/UI/Common/ArchiveOpenCallback.h +++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.h @@ -3,8 +3,9 @@ #ifndef __ARCHIVE_OPEN_CALLBACK_H #define __ARCHIVE_OPEN_CALLBACK_H -#include "Common/MyString.h" #include "Common/MyCom.h" +#include "Common/MyString.h" + #include "Windows/FileFind.h" #ifndef _NO_CRYPTO @@ -71,6 +72,7 @@ public: { _subArchiveMode = true; _subArchiveName = name; + TotalSize = 0; return S_OK; } @@ -86,10 +88,10 @@ public: UInt64 TotalSize; COpenCallbackImp(): Callback(NULL) {} - void Init(const UString &folderPrefix, const UString &fileName) + void Init(const UString &folderPrefix, const UString &fileName) { _folderPrefix = folderPrefix; - if (!NWindows::NFile::NFind::FindFile(_folderPrefix + fileName, _fileInfo)) + if (!_fileInfo.Find(_folderPrefix + fileName)) throw 1; FileNames.Clear(); _subArchiveMode = false; diff --git a/CPP/7zip/UI/Common/CompressCall.cpp b/CPP/7zip/UI/Common/CompressCall.cpp index 3564c950..47f89ed6 100755 --- a/CPP/7zip/UI/Common/CompressCall.cpp +++ b/CPP/7zip/UI/Common/CompressCall.cpp @@ -2,20 +2,20 @@ #include "StdAfx.h" -#include "CompressCall.h" - -#include "Common/Random.h" #include "Common/IntToString.h" #include "Common/MyCom.h" +#include "Common/Random.h" #include "Common/StringConvert.h" -#include "Windows/Synchronization.h" -#include "Windows/FileMapping.h" #include "Windows/FileDir.h" +#include "Windows/FileMapping.h" +#include "Windows/Synchronization.h" #include "../FileManager/ProgramLocation.h" #include "../FileManager/RegistryUtils.h" +#include "CompressCall.h" + #ifndef _UNICODE extern bool g_IsNT; #endif _UNICODE @@ -122,8 +122,8 @@ static HRESULT CreateTempEvent(const wchar_t *name, for (;;) { int number = random.Generate(); - wchar_t temp[32]; - ConvertUInt64ToString((UInt32)number, temp); + wchar_t temp[16]; + ConvertUInt32ToString((UInt32)number, temp); eventName = name; eventName += temp; RINOK(event.CreateWithName(false, GetSystemString(eventName))); @@ -151,8 +151,8 @@ static HRESULT CreateMap(const UStringVector &names, for (;;) { int number = random.Generate(); - wchar_t temp[32]; - ConvertUInt64ToString(UInt32(number), temp); + wchar_t temp[16]; + ConvertUInt32ToString(UInt32(number), temp); mappingName = id; mappingName += L"Mapping"; mappingName += temp; @@ -169,8 +169,8 @@ static HRESULT CreateMap(const UStringVector &names, params += mappingName; params += L":"; - wchar_t string[10]; - ConvertUInt64ToString(totalSize, string); + wchar_t string[16]; + ConvertUInt32ToString(totalSize, string); params += string; params += L":"; @@ -231,8 +231,8 @@ HRESULT CompressFiles( for (;;) { int number = random.Generate(); - wchar_t temp[32]; - ConvertUInt64ToString(UInt32(number), temp); + wchar_t temp[16]; + ConvertUInt32ToString(UInt32(number), temp); mappingName = L"7zCompressMapping"; mappingName += temp; if (!fileMapping.Create(INVALID_HANDLE_VALUE, NULL, @@ -252,8 +252,8 @@ HRESULT CompressFiles( params += mappingName; params += L":"; - wchar_t string[10]; - ConvertUInt64ToString(totalSize, string); + wchar_t string[16]; + ConvertUInt32ToString(totalSize, string); params += string; params += L":"; diff --git a/CPP/7zip/UI/Common/DirItem.h b/CPP/7zip/UI/Common/DirItem.h index 0f289483..29cc60d9 100755 --- a/CPP/7zip/UI/Common/DirItem.h +++ b/CPP/7zip/UI/Common/DirItem.h @@ -58,11 +58,12 @@ struct CArcItem UString Name; bool IsDir; bool SizeDefined; + bool MTimeDefined; bool Censored; UInt32 IndexInServer; int TimeType; - CArcItem(): IsDir(false), SizeDefined(false), Censored(false), TimeType(-1) {} + CArcItem(): IsDir(false), SizeDefined(false), MTimeDefined(false), Censored(false), TimeType(-1) {} }; #endif diff --git a/CPP/7zip/UI/Common/EnumDirItems.cpp b/CPP/7zip/UI/Common/EnumDirItems.cpp index b83edf2a..ba03ea35 100755 --- a/CPP/7zip/UI/Common/EnumDirItems.cpp +++ b/CPP/7zip/UI/Common/EnumDirItems.cpp @@ -2,12 +2,6 @@ #include "StdAfx.h" -#include <stdio.h> - -#include "Common/StringConvert.h" -#include "Common/Wildcard.h" -#include "Common/MyCom.h" - #include "EnumDirItems.h" using namespace NWindows; @@ -122,7 +116,7 @@ void CDirItems::EnumerateDirItems2(const UString &phyPrefix, const UString &logP const UString &filePath = filePaths[i]; NFind::CFileInfoW fi; const UString phyPath = phyPrefix + filePath; - if (!NFind::FindFile(phyPath, fi)) + if (!fi.Find(phyPath)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPath); @@ -218,7 +212,7 @@ static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, const UString &name = item.PathParts.Front(); const UString fullPath = phyPrefix + name; NFind::CFileInfoW fi; - if (!NFind::FindFile(fullPath, fi)) + if (!fi.Find(fullPath)) { errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); @@ -268,7 +262,7 @@ static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i]; const UString fullPath = phyPrefix + nextNode.Name; NFind::CFileInfoW fi; - if (!NFind::FindFile(fullPath, fi)) + if (!fi.Find(fullPath)) { if (!nextNode.AreThereIncludeItems()) continue; diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp index 3ac497f4..93329091 100755 --- a/CPP/7zip/UI/Common/Extract.cpp +++ b/CPP/7zip/UI/Common/Extract.cpp @@ -2,55 +2,65 @@ #include "StdAfx.h" -#include "Extract.h" +#include <stdio.h> -#include "Windows/Defs.h" #include "Windows/FileDir.h" +#include "Windows/PropVariant.h" +#include "Windows/PropVariantConversions.h" + +#include "../Common/ExtractingFilePath.h" -#include "OpenArchive.h" +#include "Extract.h" #include "SetProperties.h" using namespace NWindows; static HRESULT DecompressArchive( - IInArchive *archive, + const CArc &arc, UInt64 packSize, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IExtractCallbackUI *callback, CArchiveExtractCallback *extractCallbackSpec, - UString &errorMessage) + UString &errorMessage, + UInt64 &stdInProcessed) { + stdInProcessed = 0; + IInArchive *archive = arc.Archive; CRecordVector<UInt32> realIndices; - UInt32 numItems; - RINOK(archive->GetNumberOfItems(&numItems)); - - for(UInt32 i = 0; i < numItems; i++) - { - UString filePath; - RINOK(GetArchiveItemPath(archive, i, options.DefaultItemName, filePath)); - bool isFolder; - RINOK(IsArchiveItemFolder(archive, i, isFolder)); - if (!wildcardCensor.CheckPath(filePath, !isFolder)) - continue; - realIndices.Add(i); - } - if (realIndices.Size() == 0) + if (!options.StdInMode) { - callback->ThereAreNoFiles(); - return S_OK; + UInt32 numItems; + RINOK(archive->GetNumberOfItems(&numItems)); + + for (UInt32 i = 0; i < numItems; i++) + { + UString filePath; + RINOK(arc.GetItemPath(i, filePath)); + bool isFolder; + RINOK(IsArchiveItemFolder(archive, i, isFolder)); + if (!wildcardCensor.CheckPath(filePath, !isFolder)) + continue; + realIndices.Add(i); + } + if (realIndices.Size() == 0) + { + callback->ThereAreNoFiles(); + return S_OK; + } } UStringVector removePathParts; UString outDir = options.OutputDir; - outDir.Replace(L"*", options.DefaultItemName); + outDir.Replace(L"*", GetCorrectFsPath(arc.DefaultName)); #ifdef _WIN32 outDir.TrimRight(); + outDir = GetCorrectFullFsPath(outDir); #endif - if(!outDir.IsEmpty()) - if(!NFile::NDirectory::CreateComplexDirectory(outDir)) + if (!outDir.IsEmpty()) + if (!NFile::NDirectory::CreateComplexDirectory(outDir)) { HRESULT res = ::GetLastError(); if (res == S_OK) @@ -60,91 +70,108 @@ static HRESULT DecompressArchive( } extractCallbackSpec->Init( - archive, + options.StdInMode ? &wildcardCensor : NULL, + &arc, callback, - options.StdOutMode, + options.StdOutMode, options.TestMode, options.CalcCrc, outDir, removePathParts, - options.DefaultItemName, - options.ArchiveFileInfo.MTime, - options.ArchiveFileInfo.Attrib, packSize); #ifdef COMPRESS_MT RINOK(SetProperties(archive, options.Properties)); #endif - HRESULT result = archive->Extract(&realIndices.Front(), - realIndices.Size(), options.TestMode? 1: 0, extractCallbackSpec); + HRESULT result; + Int32 testMode = (options.TestMode && !options.CalcCrc) ? 1: 0; + if (options.StdInMode) + { + result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, extractCallbackSpec); + NCOM::CPropVariant prop; + if (archive->GetArchiveProperty(kpidPhySize, &prop) == S_OK) + if (prop.vt == VT_UI8 || prop.vt == VT_UI4) + stdInProcessed = ConvertPropVariantToUInt64(prop); + } + else + result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, extractCallbackSpec); return callback->ExtractResult(result); } HRESULT DecompressArchives( CCodecs *codecs, const CIntVector &formatIndices, - UStringVector &archivePaths, UStringVector &archivePathsFull, + UStringVector &arcPaths, UStringVector &arcPathsFull, const NWildcard::CCensorNode &wildcardCensor, - const CExtractOptions &optionsSpec, + const CExtractOptions &options, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, UString &errorMessage, CDecompressStat &stat) { stat.Clear(); - CExtractOptions options = optionsSpec; int i; UInt64 totalPackSize = 0; CRecordVector<UInt64> archiveSizes; - for (i = 0; i < archivePaths.Size(); i++) + + int numArcs = options.StdInMode ? 1 : arcPaths.Size(); + + for (i = 0; i < numArcs; i++) { - const UString &archivePath = archivePaths[i]; NFile::NFind::CFileInfoW fi; - if (!NFile::NFind::FindFile(archivePath, fi)) - throw "there is no such archive"; - if (fi.IsDir()) - throw "can't decompress folder"; + fi.Size = 0; + if (!options.StdInMode) + { + const UString &arcPath = arcPaths[i]; + if (!fi.Find(arcPath)) + throw "there is no such archive"; + if (fi.IsDir()) + throw "can't decompress folder"; + } archiveSizes.Add(fi.Size); totalPackSize += fi.Size; } CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> ec(extractCallbackSpec); - bool multi = (archivePaths.Size() > 1); + bool multi = (numArcs > 1); extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode); if (multi) { RINOK(extractCallback->SetTotal(totalPackSize)); } - for (i = 0; i < archivePaths.Size(); i++) + for (i = 0; i < numArcs; i++) { - const UString &archivePath = archivePaths[i]; + const UString &arcPath = arcPaths[i]; NFile::NFind::CFileInfoW fi; - if (!NFile::NFind::FindFile(archivePath, fi)) - throw "there is no such archive"; - - if (fi.IsDir()) - throw "there is no such archive"; - - options.ArchiveFileInfo = fi; + if (options.StdInMode) + { + fi.Size = 0; + fi.Attrib = 0; + } + else + { + if (!fi.Find(arcPath) || fi.IsDir()) + throw "there is no such archive"; + } #ifndef _NO_CRYPTO openCallback->Open_ClearPasswordWasAskedFlag(); #endif - RINOK(extractCallback->BeforeOpen(archivePath)); + RINOK(extractCallback->BeforeOpen(arcPath)); CArchiveLink archiveLink; CIntVector formatIndices2 = formatIndices; #ifndef _SFX if (formatIndices.IsEmpty()) { - int pos = archivePath.ReverseFind(L'.'); + int pos = arcPath.ReverseFind(L'.'); if (pos >= 0) { - UString s = archivePath.Mid(pos + 1); + UString s = arcPath.Mid(pos + 1); int index = codecs->FindFormatForExtension(s); if (index >= 0 && s == L"001") { - s = archivePath.Left(pos); + s = arcPath.Left(pos); pos = s.ReverseFind(L'.'); if (pos >= 0) { @@ -159,7 +186,7 @@ HRESULT DecompressArchives( } } #endif - HRESULT result = MyOpenArchive(codecs, formatIndices2, archivePath, archiveLink, openCallback); + HRESULT result = archiveLink.Open2(codecs, formatIndices2, options.StdInMode, NULL, arcPath, openCallback); if (result == E_ABORT) return result; @@ -168,19 +195,21 @@ HRESULT DecompressArchives( crypted = openCallback->Open_WasPasswordAsked(); #endif - RINOK(extractCallback->OpenResult(archivePath, result, crypted)); + RINOK(extractCallback->OpenResult(arcPath, result, crypted)); if (result != S_OK) continue; + if (!options.StdInMode) for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { - int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); + int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { - archivePaths.Delete(index); - archivePathsFull.Delete(index); + arcPaths.Delete(index); + arcPathsFull.Delete(index); totalPackSize -= archiveSizes[index]; archiveSizes.Delete(index); + numArcs = arcPaths.Size(); } } if (archiveLink.VolumePaths.Size() != 0) @@ -198,13 +227,17 @@ HRESULT DecompressArchives( } #endif - options.DefaultItemName = archiveLink.GetDefaultItemName(); - RINOK(DecompressArchive( - archiveLink.GetArchive(), + CArc &arc = archiveLink.Arcs.Back(); + arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice); + arc.MTime = fi.MTime; + + UInt64 packProcessed; + RINOK(DecompressArchive(arc, fi.Size + archiveLink.VolumesSize, - wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage)); - extractCallbackSpec->LocalProgressSpec->InSize += fi.Size + - archiveLink.VolumesSize; + wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage, packProcessed)); + if (!options.StdInMode) + packProcessed = fi.Size + archiveLink.VolumesSize; + extractCallbackSpec->LocalProgressSpec->InSize += packProcessed; extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize; if (!errorMessage.IsEmpty()) return E_FAIL; @@ -212,7 +245,9 @@ HRESULT DecompressArchives( stat.NumFolders = extractCallbackSpec->NumFolders; stat.NumFiles = extractCallbackSpec->NumFiles; stat.UnpackSize = extractCallbackSpec->UnpackSize; - stat.NumArchives = archivePaths.Size(); + stat.CrcSum = extractCallbackSpec->CrcSum; + + stat.NumArchives = arcPaths.Size(); stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize; return S_OK; } diff --git a/CPP/7zip/UI/Common/Extract.h b/CPP/7zip/UI/Common/Extract.h index 37add18b..442dd2b0 100755 --- a/CPP/7zip/UI/Common/Extract.h +++ b/CPP/7zip/UI/Common/Extract.h @@ -3,7 +3,6 @@ #ifndef __EXTRACT_H #define __EXTRACT_H -#include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" @@ -15,17 +14,16 @@ #include "../Common/LoadCodecs.h" -class CExtractOptions +struct CExtractOptions { -public: + bool StdInMode; bool StdOutMode; + bool YesToAll; bool TestMode; + bool CalcCrc; NExtract::NPathMode::EEnum PathMode; - + NExtract::NOverwriteMode::EEnum OverwriteMode; UString OutputDir; - bool YesToAll; - UString DefaultItemName; - NWindows::NFile::NFind::CFileInfoW ArchiveFileInfo; // bool ShowDialog; // bool PasswordEnabled; @@ -34,24 +32,19 @@ public: CObjectVector<CProperty> Properties; #endif - NExtract::NOverwriteMode::EEnum OverwriteMode; - #ifdef EXTERNAL_CODECS CCodecs *Codecs; #endif CExtractOptions(): + StdInMode(false), StdOutMode(false), YesToAll(false), TestMode(false), + CalcCrc(false), PathMode(NExtract::NPathMode::kFullPathnames), OverwriteMode(NExtract::NOverwriteMode::kAskBefore) {} - - /* - bool FullPathMode() const { return (ExtractMode == NExtractMode::kTest) || - (ExtractMode == NExtractMode::kFullPath); } - */ }; struct CDecompressStat @@ -61,7 +54,13 @@ struct CDecompressStat UInt64 PackSize; UInt64 NumFolders; UInt64 NumFiles; - void Clear() { NumArchives = PackSize = UnpackSize = NumFolders = NumFiles = 0; } + UInt32 CrcSum; + + void Clear() + { + NumArchives = UnpackSize = PackSize = NumFolders = NumFiles = 0; + CrcSum = 0; + } }; HRESULT DecompressArchives( diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/CPP/7zip/UI/Common/ExtractingFilePath.cpp index 5de388dd..67a58372 100755 --- a/CPP/7zip/UI/Common/ExtractingFilePath.cpp +++ b/CPP/7zip/UI/Common/ExtractingFilePath.cpp @@ -1,6 +1,9 @@ // ExtractingFilePath.cpp #include "StdAfx.h" + +#include "Common/Wildcard.h" + #include "ExtractingFilePath.h" static UString ReplaceIncorrectChars(const UString &s) @@ -15,6 +18,8 @@ static UString ReplaceIncorrectChars(const UString &s) res += c; } res.TrimRight(); + while (!res.IsEmpty() && res[res.Length() - 1] == '.') + res.Delete(res.Length() - 1); return res; #else return s; @@ -95,3 +100,41 @@ void MakeCorrectPath(UStringVector &pathParts) } } +UString MakePathNameFromParts(const UStringVector &parts) +{ + UString result; + for (int i = 0; i < parts.Size(); i++) + { + if (i != 0) + result += WCHAR_PATH_SEPARATOR; + result += parts[i]; + } + return result; +} + +UString GetCorrectFsPath(const UString &path) +{ + UString res = GetCorrectFileName(path); + #ifdef _WIN32 + if (!IsSupportedName(res)) + res = (UString)L"_" + res; + #endif + return res; +} + +UString GetCorrectFullFsPath(const UString &path) +{ + UStringVector parts; + SplitPathToParts(path, parts); + for (int i = 0; i < parts.Size(); i++) + { + UString &s = parts[i]; + #ifdef _WIN32 + while (!s.IsEmpty() && s[s.Length() - 1] == '.') + s.Delete(s.Length() - 1); + if (!IsSupportedName(s)) + s = (UString)L"_" + s; + #endif + } + return MakePathNameFromParts(parts); +} diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.h b/CPP/7zip/UI/Common/ExtractingFilePath.h index a86a6a9b..da28bfc2 100755 --- a/CPP/7zip/UI/Common/ExtractingFilePath.h +++ b/CPP/7zip/UI/Common/ExtractingFilePath.h @@ -1,10 +1,13 @@ // ExtractingFilePath.h -#ifndef __EXTRACTINGFILEPATH_H -#define __EXTRACTINGFILEPATH_H +#ifndef __EXTRACTING_FILE_PATH_H +#define __EXTRACTING_FILE_PATH_H #include "Common/MyString.h" +UString MakePathNameFromParts(const UStringVector &parts); void MakeCorrectPath(UStringVector &pathParts); +UString GetCorrectFsPath(const UString &path); +UString GetCorrectFullFsPath(const UString &path); #endif diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp index 4b5639ee..dac8c4d2 100755 --- a/CPP/7zip/UI/Common/LoadCodecs.cpp +++ b/CPP/7zip/UI/Common/LoadCodecs.cpp @@ -69,22 +69,17 @@ static bool ReadPathFromRegistry(HKEY baseKey, CSysString &path) CSysString GetBaseFolderPrefixFromRegistry() { CSysString moduleFolderPrefix = GetLibraryFolderPrefix(); - NFind::CFileInfo fi; - if (NFind::FindFile(moduleFolderPrefix + kMainDll, fi)) - if (!fi.IsDir()) - return moduleFolderPrefix; - if (NFind::FindFile(moduleFolderPrefix + kCodecsFolderName, fi)) - if (fi.IsDir()) - return moduleFolderPrefix; - if (NFind::FindFile(moduleFolderPrefix + kFormatsFolderName, fi)) - if (fi.IsDir()) - return moduleFolderPrefix; #ifdef _WIN32 - CSysString path; - if (ReadPathFromRegistry(HKEY_CURRENT_USER, path)) - return path; - if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path)) - return path; + if (!NFind::DoesFileExist(moduleFolderPrefix + kMainDll) && + !NFind::DoesDirExist(moduleFolderPrefix + kCodecsFolderName) && + !NFind::DoesDirExist(moduleFolderPrefix + kFormatsFolderName)) + { + CSysString path; + if (ReadPathFromRegistry(HKEY_CURRENT_USER, path)) + return path; + if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path)) + return path; + } #endif return moduleFolderPrefix; } @@ -181,7 +176,7 @@ static HRESULT ReadStringProp( #endif -static const unsigned int kNumArcsMax = 32; +static const unsigned int kNumArcsMax = 48; static unsigned int g_NumArcs = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) @@ -457,9 +452,7 @@ int CCodecs::FindFormatForArchiveName(const UString &arcPath) const const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; - // if (arc.FindExtension(ext) >= 0) - UString mainExt = arc.GetMainExt(); - if (!mainExt.IsEmpty() && ext.CompareNoCase(mainExt) == 0) + if (arc.FindExtension(ext) >= 0) return i; } return -1; diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp index 364ddff5..ec9f9a45 100755 --- a/CPP/7zip/UI/Common/OpenArchive.cpp +++ b/CPP/7zip/UI/Common/OpenArchive.cpp @@ -2,45 +2,56 @@ #include "StdAfx.h" -#include "OpenArchive.h" - #include "Common/Wildcard.h" -#include "Windows/FileName.h" #include "Windows/FileDir.h" -#include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" -#include "Common/StringConvert.h" - #include "DefaultName.h" +#include "OpenArchive.h" using namespace NWindows; -HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result) +// Static-SFX (for Linux) can be big. +const UInt64 kMaxCheckStartPosition = 1 << 22; + +HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) { NCOM::CPropVariant prop; - RINOK(archive->GetProperty(index, kpidPath, &prop)); - if(prop.vt == VT_BSTR) - result = prop.bstrVal; - else if (prop.vt == VT_EMPTY) - result.Empty(); - else + result = false; + RINOK(archive->GetProperty(index, propID, &prop)); + if (prop.vt == VT_BOOL) + result = VARIANT_BOOLToBool(prop.boolVal); + else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } -HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result) +HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) { - RINOK(GetArchiveItemPath(archive, index, result)); + return GetArchiveItemBoolProp(archive, index, kpidIsDir, result); +} + +HRESULT CArc::GetItemPath(UInt32 index, UString &result) const +{ + { + NCOM::CPropVariant prop; + RINOK(Archive->GetProperty(index, kpidPath, &prop)); + if (prop.vt == VT_BSTR) + result = prop.bstrVal; + else if (prop.vt == VT_EMPTY) + result.Empty(); + else + return E_FAIL; + } if (result.IsEmpty()) { - result = defaultName; + result = DefaultName; NCOM::CPropVariant prop; - RINOK(archive->GetProperty(index, kpidExtension, &prop)); + RINOK(Archive->GetProperty(index, kpidExtension, &prop)); if (prop.vt == VT_BSTR) { result += L'.'; @@ -52,54 +63,27 @@ HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &def return S_OK; } -HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, - const FILETIME &defaultFileTime, FILETIME &fileTime) +HRESULT CArc::GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const { NCOM::CPropVariant prop; - RINOK(archive->GetProperty(index, kpidMTime, &prop)); + defined = false; + ft.dwHighDateTime = ft.dwLowDateTime = 0; + RINOK(Archive->GetProperty(index, kpidMTime, &prop)); if (prop.vt == VT_FILETIME) - fileTime = prop.filetime; - else if (prop.vt == VT_EMPTY) - fileTime = defaultFileTime; - else - return E_FAIL; - return S_OK; -} - -HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) -{ - NCOM::CPropVariant prop; - RINOK(archive->GetProperty(index, propID, &prop)); - if(prop.vt == VT_BOOL) - result = VARIANT_BOOLToBool(prop.boolVal); - else if (prop.vt == VT_EMPTY) - result = false; - else + { + ft = prop.filetime; + defined = true; + } + else if (prop.vt != VT_EMPTY) return E_FAIL; + else if (MTimeDefined) + { + ft = MTime; + defined = true; + } return S_OK; } -HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) -{ - return IsArchiveItemProp(archive, index, kpidIsDir, result); -} - -HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result) -{ - return IsArchiveItemProp(archive, index, kpidIsAnti, result); -} - -// Static-SFX (for Linux) can be big. -const UInt64 kMaxCheckStartPosition = 1 << 22; - -HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName, IArchiveOpenCallback *openArchiveCallback) -{ - CInFileStream *inStreamSpec = new CInFileStream; - CMyComPtr<IInStream> inStream(inStreamSpec); - inStreamSpec->Open(fileName); - return archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback); -} - #ifndef _SFX static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size) { @@ -110,17 +94,15 @@ static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size) } #endif -HRESULT OpenArchive( +HRESULT CArc::OpenStream( CCodecs *codecs, - int arcTypeIndex, - IInStream *inStream, - const UString &fileName, - IInArchive **archiveResult, - int &formatIndex, - UString &defaultItemName, - IArchiveOpenCallback *openArchiveCallback) + int formatIndex, + IInStream *stream, + ISequentialInStream *seqStream, + IArchiveOpenCallback *callback) { - *archiveResult = NULL; + Archive.Release(); + const UString fileName = ExtractFileNameFromPath(Path); UString extension; { int dotPos = fileName.ReverseFind(L'.'); @@ -128,8 +110,8 @@ HRESULT OpenArchive( extension = fileName.Mid(dotPos + 1); } CIntVector orderIndices; - if (arcTypeIndex >= 0) - orderIndices.Add(arcTypeIndex); + if (formatIndex >= 0) + orderIndices.Add(formatIndex); else { @@ -141,16 +123,23 @@ HRESULT OpenArchive( else orderIndices.Add(i); + if (!stream) + { + if (numFinded != 1) + return E_NOTIMPL; + orderIndices.DeleteFrom(1); + } + #ifndef _SFX - if (numFinded != 1) + if (numFinded == 0) { CIntVector orderIndices2; CByteBuffer byteBuffer; const size_t kBufferSize = (1 << 21); byteBuffer.SetCapacity(kBufferSize); - RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); size_t processedSize = kBufferSize; - RINOK(ReadStream(inStream, byteBuffer, &processedSize)); + RINOK(ReadStream(stream, byteBuffer, &processedSize)); if (processedSize == 0) return S_FALSE; @@ -206,24 +195,6 @@ HRESULT OpenArchive( orderIndices2.Add(val); } orderIndices = orderIndices2; - - if (orderIndices.Size() >= 2) - { - int isoIndex = codecs->FindFormatForArchiveType(L"iso"); - int udfIndex = codecs->FindFormatForArchiveType(L"udf"); - int iIso = -1; - int iUdf = -1; - for (int i = 0; i < orderIndices.Size(); i++) - { - if (orderIndices[i] == isoIndex) iIso = i; - if (orderIndices[i] == udfIndex) iUdf = i; - } - if (iUdf == iIso + 1) - { - orderIndices[iUdf] = isoIndex; - orderIndices[iIso] = udfIndex; - } - } } else if (extension == L"000" || extension == L"001") { @@ -231,9 +202,9 @@ HRESULT OpenArchive( const size_t kBufferSize = (1 << 10); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; - RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); size_t processedSize = kBufferSize; - RINOK(ReadStream(inStream, buffer, &processedSize)); + RINOK(ReadStream(stream, buffer, &processedSize)); if (processedSize >= 16) { Byte kRarHeader[] = {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00}; @@ -252,17 +223,37 @@ HRESULT OpenArchive( } } } + if (orderIndices.Size() >= 2) + { + int isoIndex = codecs->FindFormatForArchiveType(L"iso"); + int udfIndex = codecs->FindFormatForArchiveType(L"udf"); + int iIso = -1; + int iUdf = -1; + for (int i = 0; i < orderIndices.Size(); i++) + { + if (orderIndices[i] == isoIndex) iIso = i; + if (orderIndices[i] == udfIndex) iUdf = i; + } + if (iUdf > iIso && iIso >= 0) + { + orderIndices[iUdf] = isoIndex; + orderIndices[iIso] = udfIndex; + } + } + #endif } - for(int i = 0; i < orderIndices.Size(); i++) + for (int i = 0; i < orderIndices.Size(); i++) { - inStream->Seek(0, STREAM_SEEK_SET, NULL); - + if (stream) + { + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + } CMyComPtr<IInArchive> archive; - formatIndex = orderIndices[i]; - RINOK(codecs->CreateInArchive(formatIndex, archive)); + FormatIndex = orderIndices[i]; + RINOK(codecs->CreateInArchive(FormatIndex, archive)); if (!archive) continue; @@ -277,274 +268,239 @@ HRESULT OpenArchive( } #endif - HRESULT result = archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback); + // OutputDebugStringW(codecs->Formats[FormatIndex].Name); + + HRESULT result; + if (stream) + result = archive->Open(stream, &kMaxCheckStartPosition, callback); + else + { + CMyComPtr<IArchiveOpenSeq> openSeq; + archive.QueryInterface(IID_IArchiveOpenSeq, (void **)&openSeq); + if (!openSeq) + return E_NOTIMPL; + result = openSeq->OpenSeq(seqStream); + } + if (result == S_FALSE) continue; RINOK(result); - *archiveResult = archive.Detach(); - const CArcInfoEx &format = codecs->Formats[formatIndex]; + + Archive = archive; + const CArcInfoEx &format = codecs->Formats[FormatIndex]; if (format.Exts.Size() == 0) - { - defaultItemName = GetDefaultName2(fileName, L"", L""); - } + DefaultName = GetDefaultName2(fileName, L"", L""); else { int subExtIndex = format.FindExtension(extension); if (subExtIndex < 0) subExtIndex = 0; - defaultItemName = GetDefaultName2(fileName, - format.Exts[subExtIndex].Ext, - format.Exts[subExtIndex].AddExt); + const CArcExtInfo &extInfo = format.Exts[subExtIndex]; + DefaultName = GetDefaultName2(fileName, extInfo.Ext, extInfo.AddExt); } return S_OK; } return S_FALSE; } -HRESULT OpenArchive( +HRESULT CArc::OpenStreamOrFile( CCodecs *codecs, - int arcTypeIndex, - const UString &filePath, - IInArchive **archiveResult, - int &formatIndex, - UString &defaultItemName, - IArchiveOpenCallback *openArchiveCallback) + int formatIndex, + bool stdInMode, + IInStream *stream, + IArchiveOpenCallback *callback) { - CInFileStream *inStreamSpec = new CInFileStream; - CMyComPtr<IInStream> inStream(inStreamSpec); - if (!inStreamSpec->Open(filePath)) - return GetLastError(); - return OpenArchive(codecs, arcTypeIndex, inStream, ExtractFileNameFromPath(filePath), - archiveResult, formatIndex, - defaultItemName, openArchiveCallback); + CMyComPtr<IInStream> fileStream; + CMyComPtr<ISequentialInStream> seqStream; + if (stdInMode) + seqStream = new CStdInFileStream; + else if (!stream) + { + CInFileStream *fileStreamSpec = new CInFileStream; + fileStream = fileStreamSpec; + if (!fileStreamSpec->Open(Path)) + return GetLastError(); + stream = fileStream; + } + + return OpenStream(codecs, formatIndex, stream, seqStream, callback); } -static void MakeDefaultName(UString &name) +HRESULT CArchiveLink::Close() { - int dotPos = name.ReverseFind(L'.'); - if (dotPos < 0) - return; - UString ext = name.Mid(dotPos + 1); - if (ext.IsEmpty()) - return; - for (int pos = 0; pos < ext.Length(); pos++) - if (ext[pos] < L'0' || ext[pos] > L'9') - return; - name = name.Left(dotPos); + for (int i = Arcs.Size() - 1; i >= 0; i--) + { + RINOK(Arcs[i].Archive->Close()); + } + IsOpen = false; + return S_OK; } -HRESULT OpenArchive( +void CArchiveLink::Release() +{ + while (!Arcs.IsEmpty()) + Arcs.DeleteBack(); +} + +HRESULT CArchiveLink::Open( CCodecs *codecs, const CIntVector &formatIndices, - const UString &fileName, - IInArchive **archive0, - IInArchive **archive1, - int &formatIndex0, - int &formatIndex1, - UString &defaultItemName0, - UString &defaultItemName1, - IArchiveOpenCallback *openArchiveCallback) + bool stdInMode, + IInStream *stream, + const UString &filePath, + IArchiveOpenCallback *callback) { - if (formatIndices.Size() >= 3) + Release(); + if (formatIndices.Size() >= 32) return E_NOTIMPL; - int arcTypeIndex = -1; - if (formatIndices.Size() >= 1) - arcTypeIndex = formatIndices[formatIndices.Size() - 1]; - - HRESULT result = OpenArchive(codecs, arcTypeIndex, fileName, - archive0, formatIndex0, defaultItemName0, openArchiveCallback); - RINOK(result); + HRESULT resSpec; - if (formatIndices.Size() == 1) - return S_OK; - arcTypeIndex = -1; - if (formatIndices.Size() >= 2) - arcTypeIndex = formatIndices[formatIndices.Size() - 2]; - - HRESULT resSpec = (formatIndices.Size() == 0 ? S_OK : E_NOTIMPL); - - CMyComPtr<IInArchiveGetStream> getStream; - result = (*archive0)->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream); - if (result != S_OK || !getStream) - return resSpec; - - CMyComPtr<ISequentialInStream> subSeqStream; - result = getStream->GetStream(0, &subSeqStream); - if (result != S_OK || !subSeqStream) - return resSpec; - - CMyComPtr<IInStream> subStream; - result = subSeqStream.QueryInterface(IID_IInStream, &subStream); - if (result != S_OK || !subStream) - return resSpec; - - UInt32 numItems; - RINOK((*archive0)->GetNumberOfItems(&numItems)); - if (numItems < 1) - return resSpec; - - UString subPath; - RINOK(GetArchiveItemPath(*archive0, 0, subPath)) - if (subPath.IsEmpty()) + for (;;) { - MakeDefaultName(defaultItemName0); - subPath = defaultItemName0; - const CArcInfoEx &format = codecs->Formats[formatIndex0]; - if (format.Name.CompareNoCase(L"7z") == 0) + resSpec = S_OK; + int formatIndex = -1; + if (formatIndices.Size() >= 1) + { + if (Arcs.Size() >= formatIndices.Size()) + break; + formatIndex = formatIndices[formatIndices.Size() - Arcs.Size() - 1]; + } + else if (Arcs.Size() >= 32) + break; + + if (Arcs.IsEmpty()) + { + CArc arc; + arc.Path = filePath; + arc.SubfileIndex = (UInt32)(Int32)-1; + RINOK(arc.OpenStreamOrFile(codecs, formatIndex, stdInMode, stream, callback)); + Arcs.Add(arc); + continue; + } + + const CArc &arc = Arcs.Back(); + + resSpec = (formatIndices.Size() == 0 ? S_OK : E_NOTIMPL); + + UInt32 mainSubfile; { - if (subPath.Right(3).CompareNoCase(L".7z") != 0) - subPath += L".7z"; + NCOM::CPropVariant prop; + RINOK(arc.Archive->GetArchiveProperty(kpidMainSubfile, &prop)); + if (prop.vt == VT_UI4) + mainSubfile = prop.ulVal; + else + break; + UInt32 numItems; + RINOK(arc.Archive->GetNumberOfItems(&numItems)); + if (mainSubfile >= numItems) + break; } + + + CMyComPtr<IInArchiveGetStream> getStream; + if (arc.Archive->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream) != S_OK || !getStream) + break; + + CMyComPtr<ISequentialInStream> subSeqStream; + if (getStream->GetStream(mainSubfile, &subSeqStream) != S_OK || !subSeqStream) + break; + + CMyComPtr<IInStream> subStream; + if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK || !subStream) + break; + + CArc arc2; + RINOK(arc.GetItemPath(mainSubfile, arc2.Path)); + + CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName; + callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); + if (setSubArchiveName) + setSubArchiveName->SetSubArchiveName(arc2.Path); + + arc2.SubfileIndex = mainSubfile; + HRESULT result = arc2.OpenStream(codecs, formatIndex, subStream, NULL, callback); + resSpec = (formatIndices.Size() == 0 ? S_OK : S_FALSE); + if (result == S_FALSE) + break; + RINOK(result); + RINOK(arc.GetItemMTime(mainSubfile, arc2.MTime, arc2.MTimeDefined)); + Arcs.Add(arc2); } - else - subPath = ExtractFileNameFromPath(subPath); - - CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName; - openArchiveCallback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); - if (setSubArchiveName) - setSubArchiveName->SetSubArchiveName(subPath); - - result = OpenArchive(codecs, arcTypeIndex, subStream, subPath, - archive1, formatIndex1, defaultItemName1, openArchiveCallback); - resSpec = (formatIndices.Size() == 0 ? S_OK : S_FALSE); - if (result != S_OK) - return resSpec; + IsOpen = !Arcs.IsEmpty(); return S_OK; } -static void SetCallback(const UString &archiveName, - IOpenCallbackUI *openCallbackUI, +static void SetCallback(const UString &filePath, + IOpenCallbackUI *callbackUI, IArchiveOpenCallback *reOpenCallback, - CMyComPtr<IArchiveOpenCallback> &openCallback) + CMyComPtr<IArchiveOpenCallback> &callback) { COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; - openCallback = openCallbackSpec; - openCallbackSpec->Callback = openCallbackUI; + callback = openCallbackSpec; + openCallbackSpec->Callback = callbackUI; openCallbackSpec->ReOpenCallback = reOpenCallback; UString fullName; int fileNamePartStartIndex; - NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex); + NFile::NDirectory::MyGetFullPathName(filePath, fullName, fileNamePartStartIndex); openCallbackSpec->Init( fullName.Left(fileNamePartStartIndex), fullName.Mid(fileNamePartStartIndex)); } -HRESULT MyOpenArchive( - CCodecs *codecs, - int arcTypeIndex, - const UString &archiveName, - IInArchive **archive, UString &defaultItemName, IOpenCallbackUI *openCallbackUI) -{ - CMyComPtr<IArchiveOpenCallback> openCallback; - SetCallback(archiveName, openCallbackUI, NULL, openCallback); - int formatInfo; - return OpenArchive(codecs, arcTypeIndex, archiveName, archive, formatInfo, defaultItemName, openCallback); -} - -HRESULT MyOpenArchive( - CCodecs *codecs, +HRESULT CArchiveLink::Open2(CCodecs *codecs, const CIntVector &formatIndices, - const UString &archiveName, - IInArchive **archive0, - IInArchive **archive1, - UString &defaultItemName0, - UString &defaultItemName1, - UStringVector &volumePaths, - UInt64 &volumesSize, - IOpenCallbackUI *openCallbackUI) + bool stdInMode, + IInStream *stream, + const UString &filePath, + IOpenCallbackUI *callbackUI) { - volumesSize = 0; + VolumesSize = 0; COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; - CMyComPtr<IArchiveOpenCallback> openCallback = openCallbackSpec; - openCallbackSpec->Callback = openCallbackUI; + CMyComPtr<IArchiveOpenCallback> callback = openCallbackSpec; + openCallbackSpec->Callback = callbackUI; - UString fullName; - int fileNamePartStartIndex; - NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex); - UString prefix = fullName.Left(fileNamePartStartIndex); - UString name = fullName.Mid(fileNamePartStartIndex); - openCallbackSpec->Init(prefix, name); - - int formatIndex0, formatIndex1; - RINOK(OpenArchive(codecs, formatIndices, archiveName, - archive0, - archive1, - formatIndex0, - formatIndex1, - defaultItemName0, - defaultItemName1, - openCallback)); - volumePaths.Add(prefix + name); - for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++) - volumePaths.Add(prefix + openCallbackSpec->FileNames[i]); - volumesSize = openCallbackSpec->TotalSize; - return S_OK; -} + UString fullName, prefix, name; + if (!stream && !stdInMode) + { + int fileNamePartStartIndex; + if (!NFile::NDirectory::MyGetFullPathName(filePath, fullName, fileNamePartStartIndex)) + return GetLastError(); + prefix = fullName.Left(fileNamePartStartIndex); + name = fullName.Mid(fileNamePartStartIndex); + openCallbackSpec->Init(prefix, name); + } + else + { + openCallbackSpec->SetSubArchiveName(filePath); + } -HRESULT CArchiveLink::Close() -{ - if (Archive1 != 0) - RINOK(Archive1->Close()); - if (Archive0 != 0) - RINOK(Archive0->Close()); - IsOpen = false; + RINOK(Open(codecs, formatIndices, stdInMode, stream, filePath, callback)); + VolumePaths.Add(prefix + name); + for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++) + VolumePaths.Add(prefix + openCallbackSpec->FileNames[i]); + VolumesSize = openCallbackSpec->TotalSize; return S_OK; } -void CArchiveLink::Release() -{ - IsOpen = false; - Archive1.Release(); - Archive0.Release(); -} - -HRESULT OpenArchive( - CCodecs *codecs, - const CIntVector &formatIndices, - const UString &archiveName, - CArchiveLink &archiveLink, - IArchiveOpenCallback *openCallback) -{ - HRESULT res = OpenArchive(codecs, formatIndices, archiveName, - &archiveLink.Archive0, &archiveLink.Archive1, - archiveLink.FormatIndex0, archiveLink.FormatIndex1, - archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, - openCallback); - archiveLink.IsOpen = (res == S_OK); - return res; -} - -HRESULT MyOpenArchive(CCodecs *codecs, - const CIntVector &formatIndices, - const UString &archiveName, - CArchiveLink &archiveLink, - IOpenCallbackUI *openCallbackUI) +HRESULT CArchiveLink::ReOpen(CCodecs *codecs, const UString &filePath, + IArchiveOpenCallback *callback) { - HRESULT res = MyOpenArchive(codecs, formatIndices, archiveName, - &archiveLink.Archive0, &archiveLink.Archive1, - archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, - archiveLink.VolumePaths, - archiveLink.VolumesSize, - openCallbackUI); - archiveLink.IsOpen = (res == S_OK); - return res; -} - -HRESULT ReOpenArchive(CCodecs *codecs, CArchiveLink &archiveLink, const UString &fileName, - IArchiveOpenCallback *openCallback) -{ - if (archiveLink.GetNumLevels() > 1) + if (Arcs.Size() > 1) return E_NOTIMPL; - if (archiveLink.GetNumLevels() == 0) - return MyOpenArchive(codecs, CIntVector(), fileName, archiveLink, 0); + if (Arcs.Size() == 0) + return Open2(codecs, CIntVector(), false, NULL, filePath, 0); CMyComPtr<IArchiveOpenCallback> openCallbackNew; - SetCallback(fileName, NULL, openCallback, openCallbackNew); + SetCallback(filePath, NULL, callback, openCallbackNew); - HRESULT res = ReOpenArchive(archiveLink.GetArchive(), fileName, openCallbackNew); - archiveLink.IsOpen = (res == S_OK); + CInFileStream *fileStreamSpec = new CInFileStream; + CMyComPtr<IInStream> stream(fileStreamSpec); + if (!fileStreamSpec->Open(filePath)) + return GetLastError(); + HRESULT res = GetArchive()->Open(stream, &kMaxCheckStartPosition, callback); + IsOpen = (res == S_OK); return res; } diff --git a/CPP/7zip/UI/Common/OpenArchive.h b/CPP/7zip/UI/Common/OpenArchive.h index f1b4fda7..92103623 100755 --- a/CPP/7zip/UI/Common/OpenArchive.h +++ b/CPP/7zip/UI/Common/OpenArchive.h @@ -1,117 +1,86 @@ // OpenArchive.h -#ifndef __OPENARCHIVE_H -#define __OPENARCHIVE_H +#ifndef __OPEN_ARCHIVE_H +#define __OPEN_ARCHIVE_H #include "Common/MyString.h" + #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" -#include "LoadCodecs.h" + #include "ArchiveOpenCallback.h" +#include "LoadCodecs.h" -HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result); -HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result); -HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, - const FILETIME &defaultFileTime, FILETIME &fileTime); -HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result); +HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result); HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result); -HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result); -struct ISetSubArchiveName +struct CArc { - virtual void SetSubArchiveName(const wchar_t *name) = 0; -}; - -HRESULT OpenArchive( + CMyComPtr<IInArchive> Archive; + UString Path; + UString DefaultName; + int FormatIndex; + int SubfileIndex; + FILETIME MTime; + bool MTimeDefined; + + CArc(): MTimeDefined(false) {} + + HRESULT GetItemPath(UInt32 index, UString &result) const; + HRESULT GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const; + HRESULT IsItemAnti(UInt32 index, bool &result) const + { return GetArchiveItemBoolProp(Archive, index, kpidIsAnti, result); } + + HRESULT OpenStream( CCodecs *codecs, - int arcTypeIndex, - IInStream *inStream, - const UString &fileName, - IInArchive **archiveResult, - int &formatIndex, - UString &defaultItemName, - IArchiveOpenCallback *openArchiveCallback); - -HRESULT OpenArchive( - CCodecs *codecs, - int arcTypeIndex, - const UString &filePath, - IInArchive **archive, - int &formatIndex, - UString &defaultItemName, - IArchiveOpenCallback *openArchiveCallback); + int formatIndex, + IInStream *stream, + ISequentialInStream *seqStream, + IArchiveOpenCallback *callback); -HRESULT OpenArchive( + HRESULT OpenStreamOrFile( CCodecs *codecs, - const CIntVector &formatIndices, - const UString &filePath, - IInArchive **archive0, - IInArchive **archive1, - int &formatIndex0, - int &formatIndex1, - UString &defaultItemName0, - UString &defaultItemName1, - IArchiveOpenCallback *openArchiveCallback); - - -HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName, IArchiveOpenCallback *openArchiveCallback); + int formatIndex, + bool stdInMode, + IInStream *stream, + IArchiveOpenCallback *callback); +}; struct CArchiveLink { - CMyComPtr<IInArchive> Archive0; - CMyComPtr<IInArchive> Archive1; - UString DefaultItemName0; - UString DefaultItemName1; - - int FormatIndex0; - int FormatIndex1; - + CObjectVector<CArc> Arcs; UStringVector VolumePaths; - - bool IsOpen; UInt64 VolumesSize; + bool IsOpen; - int GetNumLevels() const - { - int result = 0; - if (Archive0) - { - result++; - if (Archive1) - result++; - } - return result; - } - - CArchiveLink(): IsOpen(false), VolumesSize(0) {}; - - IInArchive *GetArchive() { return Archive1 != 0 ? Archive1: Archive0; } - UString GetDefaultItemName() { return Archive1 != 0 ? DefaultItemName1: DefaultItemName0; } - int GetArchiverIndex() const { return Archive1 != 0 ? FormatIndex1: FormatIndex0; } + CArchiveLink(): VolumesSize(0), IsOpen(false) {} HRESULT Close(); void Release(); -}; + ~CArchiveLink() { Release(); } + + IInArchive *GetArchive() const { return Arcs.Back().Archive; } -HRESULT OpenArchive( + HRESULT Open( CCodecs *codecs, const CIntVector &formatIndices, - const UString &archiveName, - CArchiveLink &archiveLink, - IArchiveOpenCallback *openCallback); + bool stdInMode, + IInStream *stream, + const UString &filePath, + IArchiveOpenCallback *callback); -HRESULT MyOpenArchive( + HRESULT Open2( CCodecs *codecs, const CIntVector &formatIndices, - const UString &archiveName, - CArchiveLink &archiveLink, - IOpenCallbackUI *openCallbackUI); + bool stdInMode, + IInStream *stream, + const UString &filePath, + IOpenCallbackUI *callbackUI); -HRESULT ReOpenArchive( + HRESULT ReOpen( CCodecs *codecs, - CArchiveLink &archiveLink, - const UString &fileName, - IArchiveOpenCallback *openCallback); + const UString &filePath, + IArchiveOpenCallback *callback); +}; #endif - diff --git a/CPP/7zip/UI/Common/PropIDUtils.cpp b/CPP/7zip/UI/Common/PropIDUtils.cpp index bf11ea15..d8c0e7d6 100755 --- a/CPP/7zip/UI/Common/PropIDUtils.cpp +++ b/CPP/7zip/UI/Common/PropIDUtils.cpp @@ -2,26 +2,18 @@ #include "StdAfx.h" -#include "PropIDUtils.h" - #include "Common/IntToString.h" -#include "Common/StringConvert.h" #include "Windows/FileFind.h" #include "Windows/PropVariantConversions.h" #include "../../PropID.h" -using namespace NWindows; +#include "PropIDUtils.h" -static UString ConvertUInt32ToString(UInt32 value) -{ - wchar_t buffer[32]; - ConvertUInt64ToString(value, buffer); - return buffer; -} +using namespace NWindows; -static void ConvertUInt32ToHex(UInt32 value, wchar_t *s) +void ConvertUInt32ToHex(UInt32 value, wchar_t *s) { for (int i = 0; i < 8; i++) { @@ -32,7 +24,9 @@ static void ConvertUInt32ToHex(UInt32 value, wchar_t *s) s[8] = L'\0'; } -UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full) +#define MY_ATTR_CHAR(a, n, c) ((a )& (1 << (n))) ? c : L'-'; + +UString ConvertPropertyToString(const PROPVARIANT &prop, PROPID propID, bool full) { switch(propID) { @@ -40,50 +34,63 @@ UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, b case kpidATime: case kpidMTime: { - if (propVariant.vt != VT_FILETIME) - return UString(); // It is error; + if (prop.vt != VT_FILETIME) + break; FILETIME localFileTime; - if (propVariant.filetime.dwHighDateTime == 0 && - propVariant.filetime.dwLowDateTime == 0) + if ((prop.filetime.dwHighDateTime == 0 && + prop.filetime.dwLowDateTime == 0) || + !::FileTimeToLocalFileTime(&prop.filetime, &localFileTime)) return UString(); - if (!::FileTimeToLocalFileTime(&propVariant.filetime, &localFileTime)) - return UString(); // It is error; return ConvertFileTimeToString(localFileTime, true, full); } case kpidCRC: { - if(propVariant.vt != VT_UI4) + if (prop.vt != VT_UI4) break; wchar_t temp[12]; - ConvertUInt32ToHex(propVariant.ulVal, temp); + ConvertUInt32ToHex(prop.ulVal, temp); return temp; } case kpidAttrib: { - if(propVariant.vt != VT_UI4) + if (prop.vt != VT_UI4) break; - UString result; - UInt32 attributes = propVariant.ulVal; - if (NFile::NFind::NAttributes::IsReadOnly(attributes)) result += L'R'; - if (NFile::NFind::NAttributes::IsHidden(attributes)) result += L'H'; - if (NFile::NFind::NAttributes::IsSystem(attributes)) result += L'S'; - if (NFile::NFind::NAttributes::IsDir(attributes)) result += L'D'; - if (NFile::NFind::NAttributes::IsArchived(attributes)) result += L'A'; - if (NFile::NFind::NAttributes::IsCompressed(attributes)) result += L'C'; - if (NFile::NFind::NAttributes::IsEncrypted(attributes)) result += L'E'; - return result; + UString res; + UInt32 a = prop.ulVal; + if (NFile::NFind::NAttributes::IsReadOnly(a)) res += L'R'; + if (NFile::NFind::NAttributes::IsHidden(a)) res += L'H'; + if (NFile::NFind::NAttributes::IsSystem(a)) res += L'S'; + if (NFile::NFind::NAttributes::IsDir(a)) res += L'D'; + if (NFile::NFind::NAttributes::IsArchived(a)) res += L'A'; + if (NFile::NFind::NAttributes::IsCompressed(a)) res += L'C'; + if (NFile::NFind::NAttributes::IsEncrypted(a)) res += L'E'; + return res; } - case kpidDictionarySize: + case kpidPosixAttrib: { - if(propVariant.vt != VT_UI4) + if (prop.vt != VT_UI4) break; - UInt32 size = propVariant.ulVal; - if (size % (1 << 20) == 0) - return ConvertUInt32ToString(size >> 20) + L"MB"; - if (size % (1 << 10) == 0) - return ConvertUInt32ToString(size >> 10) + L"KB"; - return ConvertUInt32ToString(size); + UString res; + UInt32 a = prop.ulVal; + wchar_t temp[16]; + temp[0] = MY_ATTR_CHAR(a, 14, L'd'); + for (int i = 6; i >= 0; i -= 3) + { + temp[7 - i] = MY_ATTR_CHAR(a, i + 2, L'r'); + temp[8 - i] = MY_ATTR_CHAR(a, i + 1, L'w'); + temp[9 - i] = MY_ATTR_CHAR(a, i + 0, L'x'); + } + temp[10] = 0; + res = temp; + a &= ~0x1FF; + a &= ~0xC000; + if (a != 0) + { + ConvertUInt32ToHex(a, temp); + res = UString(temp) + L' ' + res; + } + return res; } } - return ConvertPropVariantToString(propVariant); + return ConvertPropVariantToString(prop); } diff --git a/CPP/7zip/UI/Common/PropIDUtils.h b/CPP/7zip/UI/Common/PropIDUtils.h index 1d820976..ca14d091 100755 --- a/CPP/7zip/UI/Common/PropIDUtils.h +++ b/CPP/7zip/UI/Common/PropIDUtils.h @@ -1,10 +1,12 @@ // PropIDUtils.h -#ifndef __PROPIDUTILS_H -#define __PROPIDUTILS_H +#ifndef __PROPID_UTILS_H +#define __PROPID_UTILS_H #include "Common/MyString.h" +#include "Common/Types.h" +void ConvertUInt32ToHex(UInt32 value, wchar_t *s); UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full = true); #endif diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp index d8fee28b..8c8db8de 100755 --- a/CPP/7zip/UI/Common/Update.cpp +++ b/CPP/7zip/UI/Common/Update.cpp @@ -44,12 +44,6 @@ static const wchar_t *kTempFolderPrefix = L"7zE"; using namespace NUpdateArchive; -static HRESULT CopyBlock(ISequentialInStream *inStream, ISequentialOutStream *outStream) -{ - CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder; - return copyCoder->Code(inStream, outStream, NULL, NULL, NULL); -} - class COutMultiVolStream: public IOutStream, public CMyUnknownImp @@ -111,7 +105,7 @@ HRESULT COutMultiVolStream::Close() STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { - if(processedSize != NULL) + if (processedSize != NULL) *processedSize = 0; while(size > 0) { @@ -119,15 +113,15 @@ STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr { CSubStreamInfo subStream; - wchar_t temp[32]; - ConvertUInt64ToString(_streamIndex + 1, temp); + wchar_t temp[16]; + ConvertUInt32ToString(_streamIndex + 1, temp); UString res = temp; while (res.Length() < 3) res = UString(L'0') + res; UString name = Prefix + res; subStream.StreamSpec = new COutFileStream; subStream.Stream = subStream.StreamSpec; - if(!subStream.StreamSpec->Create(name, false)) + if (!subStream.StreamSpec->Create(name, false)) return ::GetLastError(); { // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS); @@ -173,7 +167,7 @@ STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr _length = _absPos; if (_offsetPos > subStream.RealSize) subStream.RealSize = _offsetPos; - if(processedSize != NULL) + if (processedSize != NULL) *processedSize += realProcessed; if (subStream.Pos == volSize) { @@ -189,7 +183,7 @@ STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - if(seekOrigin >= 3) + if (seekOrigin >= 3) return STG_E_INVALIDFUNCTION; switch(seekOrigin) { @@ -261,6 +255,7 @@ bool CUpdateOptions::Init(const CCodecs *codecs, const CIntVector &formatIndices else { MethodMode.FormatIndex = codecs->FindFormatForArchiveName(arcPath); + // It works incorrectly for update command if archive has some non-default extension! if (MethodMode.FormatIndex < 0) MethodMode.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArchiveType); } @@ -292,7 +287,7 @@ struct CUpdateProduceCallbackImp: public IUpdateProduceCallback const CObjectVector<CArcItem> *_arcItems; IUpdateCallbackUI *_callback; - CUpdateProduceCallbackImp(const CObjectVector<CArcItem> *a, + CUpdateProduceCallbackImp(const CObjectVector<CArcItem> *a, IUpdateCallbackUI *callback): _arcItems(a), _callback(callback) {} virtual HRESULT ShowDeleteFile(int arcIndex); }; @@ -323,11 +318,11 @@ static HRESULT Compress( IUpdateCallbackUI *callback) { CMyComPtr<IOutArchive> outArchive; - if(archive != NULL) + if (archive != NULL) { CMyComPtr<IInArchive> archive2 = archive; HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive); - if(result != S_OK) + if (result != S_OK) throw kUpdateIsNotSupoorted; } else @@ -397,7 +392,7 @@ static HRESULT Compress( { UString resultPath; int pos; - if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos)) + if (!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos)) throw 1417161; NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos)); } @@ -421,8 +416,8 @@ static HRESULT Compress( { if (i > 0) { - wchar_t s[32]; - ConvertUInt64ToString(i, s); + wchar_t s[16]; + ConvertUInt32ToString(i, s); archivePath.TempPostfix = s; } realPath = archivePath.GetTempPath(); @@ -499,7 +494,7 @@ static HRESULT Compress( return E_FAIL; } } - RINOK(CopyBlock(sfxStream, sfxOutStream)); + RINOK(NCompress::CopyStream(sfxStream, sfxOutStream, NULL)); if (outStreamSpec) { RINOK(outStreamSpec->Close()); @@ -517,26 +512,22 @@ static HRESULT Compress( } HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor, - IInArchive *archive, - const UString &defaultItemName, - const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo, + const CArc &arc, CObjectVector<CArcItem> &arcItems) { arcItems.Clear(); UInt32 numItems; + IInArchive *archive = arc.Archive; RINOK(archive->GetNumberOfItems(&numItems)); arcItems.Reserve(numItems); for (UInt32 i = 0; i < numItems; i++) { CArcItem ai; - RINOK(GetArchiveItemPath(archive, i, ai.Name)); - // check it: defaultItemName !!! - if (ai.Name.IsEmpty()) - ai.Name = defaultItemName; + RINOK(arc.GetItemPath(i, ai.Name)); RINOK(IsArchiveItemFolder(archive, i, ai.IsDir)); ai.Censored = censor.CheckPath(ai.Name, !ai.IsDir); - RINOK(GetArchiveItemFileTime(archive, i, archiveFileInfo.MTime, ai.MTime)); + RINOK(arc.GetItemMTime(i, ai.MTime, ai.MTimeDefined)); { CPropVariant prop; @@ -586,7 +577,7 @@ static HRESULT UpdateWithItemLists( CUpdateArchiveCommand &command = options.Commands[i]; if (options.StdOutMode) { - RINOK(callback->StartArchive(0, archive != 0)); + RINOK(callback->StartArchive(L"stdout", archive != 0)); } else { @@ -684,12 +675,10 @@ HRESULT UpdateArchive( const UString archiveName = options.ArchivePath.GetFinalPath(); - UString defaultItemName; + CArchiveLink archiveLink; NFind::CFileInfoW archiveFileInfo; - CArchiveLink archiveLink; - IInArchive *archive = 0; - if (NFind::FindFile(archiveName, archiveFileInfo)) + if (archiveFileInfo.Find(archiveName)) { if (archiveFileInfo.IsDir()) throw "there is no such archive"; @@ -698,7 +687,7 @@ HRESULT UpdateArchive( CIntVector formatIndices; if (options.MethodMode.FormatIndex >= 0) formatIndices.Add(options.MethodMode.FormatIndex); - HRESULT result = MyOpenArchive(codecs, formatIndices, archiveName, archiveLink, openCallback); + HRESULT result = archiveLink.Open2(codecs, formatIndices, false, NULL, archiveName, openCallback); if (result == E_ABORT) return result; RINOK(callback->OpenResult(archiveName, result)); @@ -709,8 +698,10 @@ HRESULT UpdateArchive( errorInfo.Message = L"Updating for multivolume archives is not implemented"; return E_NOTIMPL; } - archive = archiveLink.GetArchive(); - defaultItemName = archiveLink.GetDefaultItemName(); + + CArc &arc = archiveLink.Arcs.Back(); + arc.MTimeDefined = !archiveFileInfo.IsDevice; + arc.MTime = archiveFileInfo.MTime; } else { @@ -777,12 +768,15 @@ HRESULT UpdateArchive( CTempFiles tempFiles; bool createTempFile = false; - if(!options.StdOutMode && options.UpdateArchiveItself) + + bool thereIsInArchive = archiveLink.IsOpen; + + if (!options.StdOutMode && options.UpdateArchiveItself) { CArchivePath &ap = options.Commands[0].ArchivePath; ap = options.ArchivePath; // if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty()) - if ((archive != 0 || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0) + if ((thereIsInArchive || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0) { createTempFile = true; ap.Temp = true; @@ -807,7 +801,7 @@ HRESULT UpdateArchive( if (i > 0 || !createTempFile) { const UString &path = ap.GetFinalPath(); - if (NFind::DoesFileExist(path)) + if (NFind::DoesFileOrDirExist(path)) { errorInfo.SystemError = 0; errorInfo.Message = L"File already exists"; @@ -818,29 +812,30 @@ HRESULT UpdateArchive( } CObjectVector<CArcItem> arcItems; - if (archive != NULL) + if (thereIsInArchive) { - RINOK(EnumerateInArchiveItems(censor, - archive, defaultItemName, archiveFileInfo, arcItems)); + RINOK(EnumerateInArchiveItems(censor, archiveLink.Arcs.Back(), arcItems)); } - RINOK(UpdateWithItemLists(codecs, options, archive, arcItems, dirItems, + RINOK(UpdateWithItemLists(codecs, options, + thereIsInArchive ? archiveLink.GetArchive() : 0, + arcItems, dirItems, tempFiles, errorInfo, callback)); - if (archive != NULL) + if (thereIsInArchive) { RINOK(archiveLink.Close()); archiveLink.Release(); } tempFiles.Paths.Clear(); - if(createTempFile) + if (createTempFile) { try { CArchivePath &ap = options.Commands[0].ArchivePath; const UString &tempPath = ap.GetTempPath(); - if (archive != NULL) + if (thereIsInArchive) if (!NDirectory::DeleteFileAlways(archiveName)) { errorInfo.SystemError = ::GetLastError(); @@ -887,7 +882,7 @@ HRESULT UpdateArchive( { CArchivePath &ap = options.Commands[i].ArchivePath; UString arcPath; - if(!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath)) + if (!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath)) { errorInfo.SystemError = ::GetLastError(); return E_FAIL; diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp index dcca2a1a..0f229058 100755 --- a/CPP/7zip/UI/Common/UpdateCallback.cpp +++ b/CPP/7zip/UI/Common/UpdateCallback.cpp @@ -2,17 +2,17 @@ #include "StdAfx.h" -#include "UpdateCallback.h" - -#include "Common/StringConvert.h" -#include "Common/IntToString.h" -#include "Common/Defs.h" #include "Common/ComTry.h" +#include "Common/Defs.h" +#include "Common/IntToString.h" +#include "Common/StringConvert.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" +#include "UpdateCallback.h" + using namespace NWindows; CArchiveUpdateCallback::CArchiveUpdateCallback(): @@ -216,8 +216,8 @@ STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) { COM_TRY_BEGIN - wchar_t temp[32]; - ConvertUInt64ToString(index + 1, temp); + wchar_t temp[16]; + ConvertUInt32ToString(index + 1, temp); UString res = temp; while (res.Length() < 2) res = UString(L'0') + res; @@ -240,3 +240,10 @@ STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDef return Callback->CryptoGetTextPassword2(passwordIsDefined, password); COM_TRY_END } + +STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword(BSTR *password) +{ + COM_TRY_BEGIN + return Callback->CryptoGetTextPassword(password); + COM_TRY_END +} diff --git a/CPP/7zip/UI/Common/UpdateCallback.h b/CPP/7zip/UI/Common/UpdateCallback.h index 2a814b37..50803f52 100755 --- a/CPP/7zip/UI/Common/UpdateCallback.h +++ b/CPP/7zip/UI/Common/UpdateCallback.h @@ -23,6 +23,7 @@ virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \ virtual HRESULT SetOperationResult(Int32 operationResult) x; \ virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \ + virtual HRESULT CryptoGetTextPassword(BSTR *password) x; \ // virtual HRESULT ShowDeleteFile(const wchar_t *name) x; \ // virtual HRESULT CloseProgress() { return S_OK; }; @@ -34,13 +35,15 @@ struct IUpdateCallbackUI class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, + public ICryptoGetTextPassword, public ICompressProgressInfo, public CMyUnknownImp { public: - MY_UNKNOWN_IMP3( + MY_UNKNOWN_IMP4( IArchiveUpdateCallback2, ICryptoGetTextPassword2, + ICryptoGetTextPassword, ICompressProgressInfo) STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); @@ -48,6 +51,7 @@ public: INTERFACE_IArchiveUpdateCallback2(;) STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); + STDMETHOD(CryptoGetTextPassword)(BSTR *password); public: CRecordVector<UInt64> VolumesSizes; diff --git a/CPP/7zip/UI/Common/UpdatePair.cpp b/CPP/7zip/UI/Common/UpdatePair.cpp index f6727cbf..a43a9e77 100755 --- a/CPP/7zip/UI/Common/UpdatePair.cpp +++ b/CPP/7zip/UI/Common/UpdatePair.cpp @@ -6,10 +6,11 @@ #include "Common/Defs.h" #include "Common/Wildcard.h" + #include "Windows/Time.h" -#include "UpdatePair.h" #include "SortUtils.h" +#include "UpdatePair.h" using namespace NWindows; using namespace NTime; @@ -117,20 +118,16 @@ void GetUpdatePairInfoList( ThrowError(kNotCensoredCollisionMessaged, dirNames[dirIndex2], ai.Name); pair.DirIndex = dirIndex2; pair.ArcIndex = arcIndex2; - switch (MyCompareTime( + switch (ai.MTimeDefined ? MyCompareTime( ai.TimeType != - 1 ? (NFileTimeType::EEnum)ai.TimeType : fileTimeType, - di.MTime, ai.MTime)) + di.MTime, ai.MTime): 0) { case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break; case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break; default: - if (ai.SizeDefined) - if (di.Size != ai.Size) - pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles; - else - pair.State = NUpdateArchive::NPairState::kSameFiles; - else - pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles; + pair.State = (ai.SizeDefined && di.Size == ai.Size) ? + NUpdateArchive::NPairState::kSameFiles : + NUpdateArchive::NPairState::kUnknowNewerFiles; } dirIndex++; arcIndex++; diff --git a/CPP/7zip/UI/Common/ZipRegistry.cpp b/CPP/7zip/UI/Common/ZipRegistry.cpp index 4bba19f8..16df878f 100755 --- a/CPP/7zip/UI/Common/ZipRegistry.cpp +++ b/CPP/7zip/UI/Common/ZipRegistry.cpp @@ -46,7 +46,7 @@ void SaveExtractionInfo(const NExtract::CInfo &info) for(int i = 0; i < info.Paths.Size(); i++) { wchar_t numberString[16]; - ConvertUInt64ToString(i, numberString); + ConvertUInt32ToString(i, numberString); pathHistoryKey.SetValue(numberString, info.Paths[i]); } } @@ -75,7 +75,7 @@ void ReadExtractionInfo(NExtract::CInfo &info) for (;;) { wchar_t numberString[16]; - ConvertUInt64ToString(info.Paths.Size(), numberString); + ConvertUInt32ToString(info.Paths.Size(), numberString); UString path; if (pathHistoryKey.QueryValue(numberString, path) != ERROR_SUCCESS) break; @@ -180,7 +180,7 @@ void SaveCompressionInfo(const NCompression::CInfo &info) for(int i = 0; i < info.HistoryArchives.Size(); i++) { wchar_t numberString[16]; - ConvertUInt64ToString(i, numberString); + ConvertUInt32ToString(i, numberString); historyArchivesKey.SetValue(numberString, info.HistoryArchives[i]); } } @@ -246,7 +246,7 @@ void ReadCompressionInfo(NCompression::CInfo &info) for (;;) { wchar_t numberString[16]; - ConvertUInt64ToString(info.HistoryArchives.Size(), numberString); + ConvertUInt32ToString(info.HistoryArchives.Size(), numberString); UString path; if (historyArchivesKey.QueryValue(numberString, path) != ERROR_SUCCESS) break; diff --git a/CPP/7zip/UI/Console/Console.dsp b/CPP/7zip/UI/Console/Console.dsp index bb2f0e1d..c6aeefed 100755 --- a/CPP/7zip/UI/Console/Console.dsp +++ b/CPP/7zip/UI/Console/Console.dsp @@ -44,7 +44,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "../../../" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MT" /D "WIN_LONG_PATH" /D "EXTERNAL_LZMA" /D "EXTERNAL_CODECS" /D "BREAK_HANDLER" /D "BENCH_MT" /D "_7ZIP_LARGE_PAGES" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "../../../" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MT" /D "WIN_LONG_PATH" /D "EXTERNAL_LZMA" /D "EXTERNAL_CODECS" /D "BREAK_HANDLER" /D "BENCH_MT" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe @@ -69,7 +69,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "../../../" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MT" /D "WIN_LONG_PATH" /D "EXTERNAL_LZMA" /D "EXTERNAL_CODECS" /D "BREAK_HANDLER" /D "BENCH_MT" /D "_7ZIP_LARGE_PAGES" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "../../../" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MT" /D "WIN_LONG_PATH" /D "EXTERNAL_LZMA" /D "EXTERNAL_CODECS" /D "BREAK_HANDLER" /D "BENCH_MT" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe @@ -94,7 +94,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /Gz /MD /W3 /GX /O1 /I "../../../" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /c -# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "../../../" /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MT" /D "WIN_LONG_PATH" /D "EXTERNAL_LZMA" /D "EXTERNAL_CODECS" /D "BREAK_HANDLER" /D "BENCH_MT" /D "_7ZIP_LARGE_PAGES" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "../../../" /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MT" /D "WIN_LONG_PATH" /D "EXTERNAL_LZMA" /D "EXTERNAL_CODECS" /D "BREAK_HANDLER" /D "BENCH_MT" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe @@ -120,7 +120,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /Gz /W3 /Gm /GX /ZI /Od /I "../../../" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c -# ADD CPP /nologo /Gz /W3 /Gm /GX /ZI /Od /I "../../../" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MT" /D "WIN_LONG_PATH" /D "EXTERNAL_LZMA" /D "EXTERNAL_CODECS" /D "BREAK_HANDLER" /D "BENCH_MT" /D "_7ZIP_LARGE_PAGES" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gz /W3 /Gm /GX /ZI /Od /I "../../../" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MT" /D "WIN_LONG_PATH" /D "EXTERNAL_LZMA" /D "EXTERNAL_CODECS" /D "BREAK_HANDLER" /D "BENCH_MT" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe @@ -734,5 +734,17 @@ SOURCE=..\..\..\..\C\Threads.c SOURCE=..\..\..\..\C\Threads.h # End Source File # End Group +# Begin Group "ArchiveCommon" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\OutStreamWithCRC.h +# End Source File +# End Group # End Target # End Project diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp index 82a08f2f..4352bc71 100755 --- a/CPP/7zip/UI/Console/List.cpp +++ b/CPP/7zip/UI/Console/List.cpp @@ -2,25 +2,23 @@ #include "StdAfx.h" -#include "List.h" -#include "ConsoleClose.h" - -#include "Common/StringConvert.h" -#include "Common/StdOutStream.h" #include "Common/IntToString.h" #include "Common/MyCom.h" +#include "Common/StdOutStream.h" +#include "Common/StringConvert.h" +#include "Windows/Error.h" +#include "Windows/FileDir.h" #include "Windows/PropVariant.h" -#include "Windows/Defs.h" #include "Windows/PropVariantConversions.h" -#include "Windows/FileDir.h" -#include "Windows/Error.h" #include "../../Archive/IArchive.h" -#include "../Common/PropIDUtils.h" #include "../Common/OpenArchive.h" +#include "../Common/PropIDUtils.h" +#include "ConsoleClose.h" +#include "List.h" #include "OpenCallbackConsole.h" using namespace NWindows; @@ -78,8 +76,17 @@ static CPropIdToName kPropIdToName[] = { kpidChecksum, L"Checksum" }, { kpidCharacts, L"Characteristics" }, { kpidVa, L"Virtual Address" }, + { kpidId, L"ID" }, + { kpidShortName, L"Short Name" }, + { kpidCreatorApp, L"Creator Application"}, + { kpidSectorSize, L"Sector Size" }, + { kpidPosixAttrib, L"Mode" }, + { kpidLink, L"Link" }, + + { kpidTotalSize, L"Total Size" }, { kpidFreeSpace, L"Free Space" }, - { kpidClusterSize, L"Cluster Size" } + { kpidClusterSize, L"Cluster Size" }, + { kpidVolumeName, L"Label" } }; static const char kEmptyAttribChar = '.'; @@ -125,7 +132,7 @@ struct CFieldInfoInit int Width; }; -CFieldInfoInit kStandardFieldTable[] = +static CFieldInfoInit kStandardFieldTable[] = { { kpidMTime, L" Date Time", kLeft, kLeft, 0, 19 }, { kpidAttrib, L"Attr", kRight, kCenter, 1, 5 }, @@ -134,13 +141,13 @@ CFieldInfoInit kStandardFieldTable[] = { kpidPath, L"Name", kLeft, kLeft, 2, 24 } }; -void PrintSpaces(int numSpaces) +static void PrintSpaces(int numSpaces) { for (int i = 0; i < numSpaces; i++) g_StdOut << ' '; } -void PrintString(EAdjustment adjustment, int width, const UString &textString) +static void PrintString(EAdjustment adjustment, int width, const UString &textString) { const int numSpaces = width - textString.Length(); int numLeftSpaces = 0; @@ -170,10 +177,7 @@ public: HRESULT Init(IInArchive *archive); void PrintTitle(); void PrintTitleLines(); - HRESULT PrintItemInfo(IInArchive *archive, - const UString &defaultItemName, - UInt32 index, - bool techMode); + HRESULT PrintItemInfo(const CArc &arc, UInt32 index, bool techMode); HRESULT PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, const UInt64 *size, const UInt64 *compressedSize); }; @@ -205,8 +209,8 @@ static UString GetPropName(PROPID propID, BSTR name) } if (name) return name; - wchar_t s[32]; - ConvertUInt64ToString(propID, s); + wchar_t s[16]; + ConvertUInt32ToString(propID, s); return s; } @@ -252,13 +256,13 @@ void CFieldPrinter::PrintTitleLines() } -BOOL IsFileTimeZero(CONST FILETIME *lpFileTime) +static BOOL IsFileTimeZero(CONST FILETIME *lpFileTime) { return (lpFileTime->dwLowDateTime == 0) && (lpFileTime->dwHighDateTime == 0); } static const char *kEmptyTimeString = " "; -void PrintTime(const NCOM::CPropVariant &prop) +static void PrintTime(const NCOM::CPropVariant &prop) { if (prop.vt != VT_FILETIME) throw "incorrect item"; @@ -277,10 +281,7 @@ void PrintTime(const NCOM::CPropVariant &prop) } } -HRESULT CFieldPrinter::PrintItemInfo(IInArchive *archive, - const UString &defaultItemName, - UInt32 index, - bool techMode) +HRESULT CFieldPrinter::PrintItemInfo(const CArc &arc, UInt32 index, bool techMode) { /* if (techMode) @@ -300,45 +301,35 @@ HRESULT CFieldPrinter::PrintItemInfo(IInArchive *archive, if (fieldInfo.PropID == kpidPath) { UString s; - RINOK(GetArchiveItemPath(archive, index, defaultItemName, s)); + RINOK(arc.GetItemPath(index, s)); prop = s; } else { - RINOK(archive->GetProperty(index, fieldInfo.PropID, &prop)); + RINOK(arc.Archive->GetProperty(index, fieldInfo.PropID, &prop)); } if (techMode) { g_StdOut << fieldInfo.Name << " = "; } int width = (fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width; - if (prop.vt == VT_EMPTY) + if (fieldInfo.PropID == kpidAttrib && (prop.vt == VT_EMPTY || prop.vt == VT_UI4)) { - switch(fieldInfo.PropID) - { - case kpidPath: prop = defaultItemName; break; - default: - if (techMode) - g_StdOut << endl; - else - PrintSpaces(width); - continue; - } + UInt32 attrib = (prop.vt == VT_EMPTY) ? 0 : prop.ulVal; + bool isFolder; + RINOK(IsArchiveItemFolder(arc.Archive, index, isFolder)); + char s[8]; + GetAttribString(attrib, isFolder, s); + g_StdOut << s; } - if (fieldInfo.PropID == kpidMTime) + else if (prop.vt == VT_EMPTY) { - PrintTime(prop); + if (!techMode) + PrintSpaces(width); } - else if (fieldInfo.PropID == kpidAttrib) + else if (fieldInfo.PropID == kpidMTime) { - if (prop.vt != VT_UI4) - throw "incorrect item"; - UInt32 attributes = prop.ulVal; - bool isFolder; - RINOK(IsArchiveItemFolder(archive, index, isFolder)); - char s[8]; - GetAttribString(attributes, isFolder, s); - g_StdOut << s; + PrintTime(prop); } else if (prop.vt == VT_BSTR) { @@ -364,7 +355,7 @@ HRESULT CFieldPrinter::PrintItemInfo(IInArchive *archive, return S_OK; } -void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value) +static void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value) { wchar_t textString[32] = { 0 }; if (value != NULL) @@ -416,8 +407,14 @@ bool GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &va return true; } +static void PrintPropPair(const wchar_t *name, const wchar_t *value) +{ + g_StdOut << name << " = " << value << endl; +} + HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, - UStringVector &archivePaths, UStringVector &archivePathsFull, + bool stdInMode, + UStringVector &arcPaths, UStringVector &arcPathsFull, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, #ifndef _NO_CRYPTO @@ -432,15 +429,19 @@ HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0; UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0; - for (int i = 0; i < archivePaths.Size(); i++) + int numArcs = /* stdInMode ? 1 : */ arcPaths.Size(); + for (int i = 0; i < numArcs; i++) { - const UString &archiveName = archivePaths[i]; - NFile::NFind::CFileInfoW fi; - if (!NFile::NFind::FindFile(archiveName, fi) || fi.IsDir()) + const UString &archiveName = arcPaths[i]; + if (!stdInMode) { - g_StdOut << endl << "Error: " << archiveName << " is not file" << endl; - numErrors++; - continue; + NFile::NFind::CFileInfoW fi; + if (!fi.Find(archiveName) || fi.IsDir()) + { + g_StdOut << endl << "Error: " << archiveName << " is not file" << endl; + numErrors++; + continue; + } } CArchiveLink archiveLink; @@ -455,14 +456,21 @@ HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, #endif - HRESULT result = MyOpenArchive(codecs, formatIndices, archiveName, archiveLink, &openCallback); + HRESULT result = archiveLink.Open2(codecs, formatIndices, stdInMode, NULL, archiveName, &openCallback); if (result != S_OK) { if (result == E_ABORT) return result; g_StdOut << endl << "Error: " << archiveName << ": "; if (result == S_FALSE) - g_StdOut << "is not supported archive"; + { + #ifndef _NO_CRYPTO + if (openCallback.Open_WasPasswordAsked()) + g_StdOut << "Can not open encrypted archive. Wrong password?"; + else + #endif + g_StdOut << "Can not open file as archive"; + } else if (result == E_OUTOFMEMORY) g_StdOut << "Can't allocate required memory"; else @@ -472,45 +480,52 @@ HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, continue; } + if (!stdInMode) for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { - int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); + int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { - archivePaths.Delete(index); - archivePathsFull.Delete(index); + arcPaths.Delete(index); + arcPathsFull.Delete(index); + numArcs = arcPaths.Size(); } } - IInArchive *archive = archiveLink.GetArchive(); - const UString defaultItemName = archiveLink.GetDefaultItemName(); - if (enableHeaders) { g_StdOut << endl << kListing << archiveName << endl << endl; - UInt32 numProps; - if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK) + for (int i = 0; i < archiveLink.Arcs.Size(); i++) { - for (UInt32 i = 0; i < numProps; i++) + const CArc &arc = archiveLink.Arcs[i]; + + g_StdOut << "----\n"; + PrintPropPair(L"Path", arc.Path); + PrintPropPair(L"Type", codecs->Formats[arc.FormatIndex].Name); + UInt32 numProps; + IInArchive *archive = arc.Archive; + if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK) { - CMyComBSTR name; - PROPID propID; - VARTYPE vt; - if (archive->GetArchivePropertyInfo(i, &name, &propID, &vt) != S_OK) - continue; - NCOM::CPropVariant prop; - if (archive->GetArchiveProperty(propID, &prop) != S_OK) - continue; - UString s = ConvertPropertyToString(prop, propID); - if (!s.IsEmpty()) - g_StdOut << GetPropName(propID, name) << " = " << s << endl; + for (UInt32 j = 0; j < numProps; j++) + { + CMyComBSTR name; + PROPID propID; + VARTYPE vt; + if (archive->GetArchivePropertyInfo(j, &name, &propID, &vt) != S_OK) + continue; + NCOM::CPropVariant prop; + if (archive->GetArchiveProperty(propID, &prop) != S_OK) + continue; + UString s = ConvertPropertyToString(prop, propID); + if (!s.IsEmpty()) + PrintPropPair(GetPropName(propID, name), s); + } } } + g_StdOut << endl; if (techMode) g_StdOut << "----------\n"; - if (numProps > 0) - g_StdOut << endl; } if (enableHeaders && !techMode) @@ -521,6 +536,8 @@ HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, g_StdOut << endl; } + const CArc &arc = archiveLink.Arcs.Back(); + IInArchive *archive = arc.Archive; if (techMode) { RINOK(fieldPrinter.Init(archive)); @@ -529,20 +546,23 @@ HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); - for(UInt32 i = 0; i < numItems; i++) + for (UInt32 i = 0; i < numItems; i++) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; UString filePath; - RINOK(GetArchiveItemPath(archive, i, defaultItemName, filePath)); + HRESULT res = arc.GetItemPath(i, filePath); + if (stdInMode && res == E_INVALIDARG) + break; + RINOK(res); bool isFolder; RINOK(IsArchiveItemFolder(archive, i, isFolder)); if (!wildcardCensor.CheckPath(filePath, !isFolder)) continue; - fieldPrinter.PrintItemInfo(archive, defaultItemName, i, techMode); + fieldPrinter.PrintItemInfo(arc, i, techMode); UInt64 packSize, unpackSize; if (!GetUInt64Value(archive, i, kpidSize, unpackSize)) @@ -583,14 +603,14 @@ HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, numFiles2 += numFiles; numDirs2 += numDirs; } - if (enableHeaders && !techMode && archivePaths.Size() > 1) + if (enableHeaders && !techMode && numArcs > 1) { g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2); g_StdOut << endl; - g_StdOut << "Archives: " << archivePaths.Size() << endl; + g_StdOut << "Archives: " << numArcs << endl; } return S_OK; } diff --git a/CPP/7zip/UI/Console/List.h b/CPP/7zip/UI/Console/List.h index bb4287e6..97d9fb15 100755 --- a/CPP/7zip/UI/Console/List.h +++ b/CPP/7zip/UI/Console/List.h @@ -7,6 +7,7 @@ #include "../Common/LoadCodecs.h" HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, + bool stdInMode, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp index 87d48e95..368a9667 100755 --- a/CPP/7zip/UI/Console/Main.cpp +++ b/CPP/7zip/UI/Console/Main.cpp @@ -5,45 +5,44 @@ #include "Common/MyInitGuid.h" #include "Common/CommandLineParser.h" -#include "Common/MyException.h" #include "Common/IntToString.h" +#include "Common/MyException.h" #include "Common/StdOutStream.h" #include "Common/StringConvert.h" #include "Common/StringToInt.h" -#include "Windows/FileDir.h" -#include "Windows/FileName.h" #include "Windows/Defs.h" #include "Windows/Error.h" +#include "Windows/FileDir.h" +#include "Windows/FileName.h" #ifdef _WIN32 #include "Windows/MemoryLock.h" #endif -#include "../../IPassword.h" #include "../../ICoder.h" -#include "../Common/UpdateAction.h" -#include "../Common/Update.h" -#include "../Common/Extract.h" +#include "../../IPassword.h" + #include "../Common/ArchiveCommandLine.h" #include "../Common/ExitCode.h" +#include "../Common/Extract.h" #ifdef EXTERNAL_CODECS #include "../Common/LoadCodecs.h" #endif +#include "../Common/PropIDUtils.h" +#include "../Common/Update.h" +#include "../Common/UpdateAction.h" #include "../../Compress/LZMA_Alone/LzmaBenchCon.h" +#include "ExtractCallbackConsole.h" #include "List.h" #include "OpenCallbackConsole.h" -#include "ExtractCallbackConsole.h" #include "UpdateCallbackConsole.h" #include "../../MyVersion.h" #if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES) -extern "C" -{ #include "../../../../C/Alloc.h" -} #endif using namespace NWindows; @@ -108,8 +107,8 @@ static const char *kHelpString = " -ssc[-]: set sensitive case mode\n" " -ssw: compress shared files\n" " -t{Type}: Set type of archive\n" - " -v{Size}[b|k|m|g]: Create volumes\n" " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]: Update options\n" + " -v{Size}[b|k|m|g]: Create volumes\n" " -w[{path}]: assign Work directory. Empty path means a temporary directory\n" " -x[r[-|0]]]{@listfile|!wildcard}: eXclude filenames\n" " -y: assume Yes on all queries\n"; @@ -197,7 +196,7 @@ int Main2( GetArguments(numArguments, arguments, commandStrings); #endif - if(commandStrings.Size() == 1) + if (commandStrings.Size() == 1) { ShowCopyrightAndHelp(g_StdOut, true); return 0; @@ -210,7 +209,7 @@ int Main2( parser.Parse1(commandStrings, options); - if(options.HelpMode) + if (options.HelpMode) { ShowCopyrightAndHelp(g_StdOut, true); return 0; @@ -266,8 +265,8 @@ int Main2( #ifdef EXTERNAL_CODECS if (arc.LibIndex >= 0) { - char s[32]; - ConvertUInt64ToString(arc.LibIndex, s); + char s[16]; + ConvertUInt32ToString(arc.LibIndex, s); PrintString(stdStream, s, 2); } else @@ -321,8 +320,8 @@ int Main2( int libIndex = codecs->GetCodecLibIndex(j); if (libIndex >= 0) { - char s[32]; - ConvertUInt64ToString(libIndex, s); + char s[16]; + ConvertUInt32ToString(libIndex, s); PrintString(stdStream, s, 2); } else @@ -383,7 +382,7 @@ int Main2( } else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) { - if(isExtractGroupCommand) + if (isExtractGroupCommand) { CExtractCallbackConsole *ecs = new CExtractCallbackConsole; CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; @@ -406,12 +405,14 @@ int Main2( #endif CExtractOptions eo; + eo.StdInMode = options.StdInMode; eo.StdOutMode = options.StdOutMode; eo.PathMode = options.Command.GetPathMode(); eo.TestMode = options.Command.IsTestMode(); eo.OverwriteMode = options.OverwriteMode; eo.OutputDir = options.OutputDir; eo.YesToAll = options.YesToAll; + eo.CalcCrc = options.CalcCrc; #ifdef COMPRESS_MT eo.Properties = options.ExtractProperties; #endif @@ -457,6 +458,12 @@ int Main2( stdStream << "Size: " << stat.UnpackSize << endl << "Compressed: " << stat.PackSize << endl; + if (options.CalcCrc) + { + wchar_t s[16]; + ConvertUInt32ToHex(stat.CrcSum, s); + stdStream << "CRC: " << s << endl; + } } else { @@ -464,6 +471,7 @@ int Main2( HRESULT result = ListArchives( codecs, formatIndices, + options.StdInMode, options.ArchivePathsSorted, options.ArchivePathsFullSorted, options.WildcardCensor.Pairs.Front().Head, @@ -483,10 +491,8 @@ int Main2( throw CSystemException(result); } } - else if(options.Command.IsFromUpdateGroup()) + else if (options.Command.IsFromUpdateGroup()) { - UString workingDir; - CUpdateOptions &uo = options.UpdateOptions; if (uo.SfxMode && uo.SfxModule.IsEmpty()) uo.SfxModule = kDefaultSfxModule; diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp index bf22d34b..ccb6c866 100755 --- a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp +++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp @@ -196,10 +196,12 @@ HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 ) HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { + *password = NULL; + #ifdef _NO_CRYPTO *passwordIsDefined = false; - return StringToBstr(L"", password); + return S_OK; #else @@ -215,7 +217,28 @@ HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, return StringToBstr(Password, password); #endif +} + +HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password) +{ + *password = NULL; + + #ifdef _NO_CRYPTO + + return E_NOTIMPL; + + #else + if (!PasswordIsDefined) + { + { + Password = GetPassword(OutStream); + PasswordIsDefined = true; + } + } + return StringToBstr(Password, password); + + #endif } /* diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.h b/CPP/7zip/UI/Console/UpdateCallbackConsole.h index da8d8cc2..5ffe3eb7 100755 --- a/CPP/7zip/UI/Console/UpdateCallbackConsole.h +++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.h @@ -1,13 +1,14 @@ // UpdateCallbackConsole.h -#ifndef __UPDATECALLBACKCONSOLE_H -#define __UPDATECALLBACKCONSOLE_H +#ifndef __UPDATE_CALLBACK_CONSOLE_H +#define __UPDATE_CALLBACK_CONSOLE_H -#include "Common/MyString.h" #include "Common/StdOutStream.h" -#include "PercentPrinter.h" + #include "../Common/Update.h" +#include "PercentPrinter.h" + class CUpdateCallbackConsole: public IUpdateCallbackUI2 { CPercentPrinter m_PercentPrinter; diff --git a/CPP/7zip/UI/Console/UserInputUtils.cpp b/CPP/7zip/UI/Console/UserInputUtils.cpp index b85cd594..798486e7 100755 --- a/CPP/7zip/UI/Console/UserInputUtils.cpp +++ b/CPP/7zip/UI/Console/UserInputUtils.cpp @@ -51,6 +51,5 @@ UString GetPassword(CStdOutStream *outStream) { (*outStream) << "\nEnter password:"; outStream->Flush(); - AString oemPassword = g_StdIn.ScanStringUntilNewLine(); - return MultiByteToUnicodeString(oemPassword, CP_OEMCP); + return g_StdIn.ScanUStringUntilNewLine(); } diff --git a/CPP/7zip/UI/Console/makefile b/CPP/7zip/UI/Console/makefile index 01682e9a..a0d56615 100755 --- a/CPP/7zip/UI/Console/makefile +++ b/CPP/7zip/UI/Console/makefile @@ -8,6 +8,7 @@ CFLAGS = $(CFLAGS) -I ../../../ \ -DBREAK_HANDLER \ -DBENCH_MT \ -D_7ZIP_LARGE_PAGES \ + -DSUPPORT_DEVICE_FILE \ CONSOLE_OBJS = \ $O\ConsoleClose.obj \ @@ -76,6 +77,9 @@ UI_COMMON_OBJS = \ $O\UpdateProduce.obj \ $O\WorkDir.obj \ +AR_COMMON_OBJS = \ + $O\OutStreamWithCRC.obj \ + LZMA_BENCH_OBJS = \ $O\LzmaBench.obj \ $O\LzmaBenchCon.obj \ @@ -93,6 +97,7 @@ OBJS = \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(UI_COMMON_OBJS) \ + $(AR_COMMON_OBJS) \ $O\CopyCoder.obj \ $(LZMA_BENCH_OBJS) \ $(C_OBJS) \ @@ -111,6 +116,8 @@ $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(UI_COMMON_OBJS): ../Common/$(*B).cpp $(COMPL) +$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp + $(COMPL) $O\CopyCoder.obj: ../../Compress/$(*B).cpp $(COMPL) $(LZMA_BENCH_OBJS): ../../Compress/LZMA_Alone/$(*B).cpp diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp index 3ba8f3eb..efe8ad44 100755 --- a/CPP/7zip/UI/Explorer/ContextMenu.cpp +++ b/CPP/7zip/UI/Explorer/ContextMenu.cpp @@ -5,40 +5,30 @@ #include "ContextMenu.h" #include "Common/StringConvert.h" -#include "Common/MyCom.h" -#include "Windows/Shell.h" -#include "Windows/Memory.h" #include "Windows/COM.h" -#include "Windows/FileFind.h" #include "Windows/FileDir.h" -#include "Windows/FileName.h" -#include "Windows/Thread.h" -#include "Windows/Window.h" - +#include "Windows/FileFind.h" +#include "Windows/Memory.h" #include "Windows/Menu.h" -#include "Windows/ResourceString.h" +#include "Windows/Shell.h" + +#include "../Common/ArchiveName.h" +#include "../Common/CompressCall.h" +#include "../Common/ExtractingFilePath.h" +#include "../Common/ZipRegistry.h" #include "../FileManager/FormatUtils.h" #include "../FileManager/ProgramLocation.h" -#include "../Common/ZipRegistry.h" -#include "../Common/ArchiveName.h" - #ifdef LANG #include "../FileManager/LangUtils.h" #endif -#include "resource.h" #include "ContextMenuFlags.h" - -// #include "ExtractEngine.h" -// #include "TestEngine.h" -// #include "CompressEngine.h" #include "MyMessages.h" -#include "../GUI/ExtractRes.h" -#include "../Common/CompressCall.h" +#include "resource.h" using namespace NWindows; @@ -297,7 +287,7 @@ static UString GetSubFolderNameForExtract(const UString &archiveName) res = res.Left(dotPos); res.TrimRight(); } - return res; + return GetCorrectFullFsPath(res); } static UString GetReducedString(const UString &s) @@ -316,27 +306,34 @@ static UString GetQuotedString(const UString &s) static UString GetQuotedReducedString(const UString &s) { - return GetQuotedString(GetReducedString(s)); + UString s2 = GetReducedString(s); + s2.Replace(L"&", L"&&"); + return GetQuotedString(s2); } -static const wchar_t *kExtractExludeExtensions[] = -{ - L"txt", L"htm", L"html", L"xml", L"xsd", L"xsl", L"xslt", L"asp", L"aspx", L"css", L"shtml", - L"bmp", L"gif", L"jpeg", L"jpg", L"png", L"tiff", L"ico", - L"3gp", L"avi", L"mov", L"mpeg", L"mpg", L"mpe", L"wmv", - L"aac", L"ape", L"fla", L"flac", L"la", L"mp3", L"m4a", L"mp4", L"ofr", L"ogg", - L"pac", L"ra", L"rm", L"rka", L"shn", L"swa", L"tta", L"wv", L"wma", L"wav", - L"ps", L"eps", - L"inl", L"inc", L"idl", L"h", L"hpp", L"hxx", L"c", L"cpp", L"cxx", L"rc", L"java", - L"cs", L"pas", L"bas", L"vb", L"cls", L"ctl", L"frm", L"dlg", L"def", - L"f77", L"f", L"f90", L"f95", - L"asm", L"sql", L"manifest", L"dep", - L"mak", L"clw", L"csproj", L"vcproj", L"sln", L"dsp", L"dsw", - L"bat", L"cmd", - L"awk", L"sed", L"hta", L"js", L"php", L"php3", L"php4", L"php5", - L"phptml", L"pl", L"pm", L"py", L"pyo", L"rb", L"sh", L"tcl", L"vbs", - L"tex", L"ans", L"asc", L"srt", L"reg", L"ini", L"rtf", L"pdf" -}; +static const char *kExtractExludeExtensions = + " 3gp" + " aac ans ape asc asm asp aspx avi awk" + " bas bat bmp" + " c cs cls clw cmd cpp csproj css ctl cxx" + " def dep dlg dsp dsw" + " eps" + " f f77 f90 f95 fla flac frm" + " gif" + " h hpp hta htm html hxx" + " ico idl inc ini inl" + " java jpeg jpg js" + " la" + " mak manifest wmv mov mp3 mp4 mpe mpeg mpg m4a" + " ofr ogg" + " pac pas pdf php php3 php4 php5 phptml pl pm png ps py pyo" + " ra rb rc reg rka rm rtf" + " sed sh shn shtml sln sql srt swa" + " tcl tex tiff tta txt" + " vb vcproj vbs" + " wav wma wv" + " xml xsd xsl xslt" + " "; static bool DoNeedExtract(const UString &name) { @@ -345,9 +342,16 @@ static bool DoNeedExtract(const UString &name) return true; UString ext = name.Mid(extPos + 1); ext.MakeLower(); - for (int i = 0; i < sizeof(kExtractExludeExtensions) / sizeof(kExtractExludeExtensions[0]); i++) - if (ext.Compare(kExtractExludeExtensions[i]) == 0) + AString ext2 = UnicodeStringToMultiByte(ext); + const char *p = kExtractExludeExtensions; + for (int i = 0; p[i] != 0;) + { + int j; + for (j = i; p[j] != ' '; j++); + if (ext2.Length() == j - i && memcmp(p + i, (const char *)ext2, ext2.Length()) == 0) return false; + i = j + 1; + } return true; } @@ -402,7 +406,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, NFile::NDirectory::GetOnlyDirPrefix(fileName, folderPrefix); NFile::NFind::CFileInfoW fileInfo; - if (!NFile::NFind::FindFile(fileName, fileInfo)) + if (!fileInfo.Find(fileName)) return E_FAIL; if (!fileInfo.IsDir() && DoNeedExtract(fileInfo.Name)) { @@ -423,7 +427,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, for(int i = 0; i < _fileNames.Size(); i++) { NFile::NFind::CFileInfoW fileInfo; - if (!NFile::NFind::FindFile(_fileNames[i], fileInfo)) + if (!fileInfo.Find(_fileNames[i])) return E_FAIL; if (!fileInfo.IsDir() && DoNeedExtract(fileInfo.Name)) needExtract = true; @@ -434,7 +438,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UString folderPrefix; NFile::NDirectory::GetOnlyDirPrefix(fileName, folderPrefix); NFile::NFind::CFileInfoW fileInfo; - if (!NFile::NFind::FindFile(fileName, fileInfo)) + if (!fileInfo.Find(fileName)) return E_FAIL; // Extract if ((contextMenuFlags & NContextMenuFlags::kExtract) != 0) diff --git a/CPP/7zip/UI/Explorer/Explorer.dsp b/CPP/7zip/UI/Explorer/Explorer.dsp index a4c99ed6..832a153a 100755 --- a/CPP/7zip/UI/Explorer/Explorer.dsp +++ b/CPP/7zip/UI/Explorer/Explorer.dsp @@ -198,6 +198,14 @@ SOURCE=..\Common\CompressCall.h # End Source File # Begin Source File +SOURCE=..\Common\ExtractingFilePath.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ExtractingFilePath.h +# End Source File +# Begin Source File + SOURCE=..\Common\ZipRegistry.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/UI/Explorer/makefile b/CPP/7zip/UI/Explorer/makefile index ab9aff10..d9366ffe 100755 --- a/CPP/7zip/UI/Explorer/makefile +++ b/CPP/7zip/UI/Explorer/makefile @@ -49,6 +49,7 @@ WIN_CTRL_OBJS = \ UI_COMMON_OBJS = \ $O\ArchiveName.obj \ $O\CompressCall.obj \ + $O\ExtractingFilePath.obj \ $O\ZipRegistry.obj \ FM_COMMON_OBJS = \ diff --git a/CPP/7zip/UI/Far/ExtractEngine.cpp b/CPP/7zip/UI/Far/ExtractEngine.cpp index 55994ed6..677cac79 100755 --- a/CPP/7zip/UI/Far/ExtractEngine.cpp +++ b/CPP/7zip/UI/Far/ExtractEngine.cpp @@ -2,15 +2,9 @@ #include "StdAfx.h" -#include <stdio.h> - -#include "ExtractEngine.h" - -#include "Common/Wildcard.h" #include "Common/StringConvert.h" -#include "Windows/Defs.h" - +#include "ExtractEngine.h" #include "FarUtils.h" #include "Messages.h" #include "OverwriteDialog.h" @@ -60,7 +54,7 @@ STDMETHODIMP CExtractCallBackImp::SetCompleted(const UInt64 *completeValue) STDMETHODIMP CExtractCallBackImp::AskOverwrite( const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, - INT32 *answer) + Int32 *answer) { NOverwriteDialog::CFileInfo oldFileInfo, newFileInfo; oldFileInfo.Time = *existTime; @@ -108,7 +102,7 @@ STDMETHODIMP CExtractCallBackImp::AskOverwrite( return S_OK; } -STDMETHODIMP CExtractCallBackImp::PrepareOperation(const wchar_t *name, bool /* isFolder */, INT32 /* askExtractMode */, const UInt64 * /* position */) +STDMETHODIMP CExtractCallBackImp::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 /* askExtractMode */, const UInt64 * /* position */) { if (WasEscPressed()) return E_ABORT; @@ -124,7 +118,7 @@ STDMETHODIMP CExtractCallBackImp::MessageError(const wchar_t *message) return S_OK; } -STDMETHODIMP CExtractCallBackImp::SetOperationResult(INT32 operationResult, bool encrypted) +STDMETHODIMP CExtractCallBackImp::SetOperationResult(Int32 operationResult, bool encrypted) { switch(operationResult) { diff --git a/CPP/7zip/UI/Far/ExtractEngine.h b/CPP/7zip/UI/Far/ExtractEngine.h index 62486fb1..5676103a 100755 --- a/CPP/7zip/UI/Far/ExtractEngine.h +++ b/CPP/7zip/UI/Far/ExtractEngine.h @@ -27,11 +27,11 @@ public: STDMETHOD(AskOverwrite)( const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, - INT32 *result); - STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, INT32 askExtractMode, const UInt64 *position); + Int32 *result); + STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position); STDMETHOD(MessageError)(const wchar_t *message); - STDMETHOD(SetOperationResult)(INT32 resultEOperationResult, bool encrypted); + STDMETHOD(SetOperationResult)(Int32 resultEOperationResult, bool encrypted); // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *password); @@ -44,15 +44,6 @@ private: UString m_CurrentFilePath; - /* - struct CProcessedFileInfo - { - FILETIME MTime; - bool isDir; - UINT32 Attributes; - } m_ProcessedFileInfo; - */ - CProgressBox *m_ProgressBox; UINT m_CodePage; diff --git a/CPP/7zip/UI/Far/Far.dsp b/CPP/7zip/UI/Far/Far.dsp index 7bb43ef7..229035f9 100755 --- a/CPP/7zip/UI/Far/Far.dsp +++ b/CPP/7zip/UI/Far/Far.dsp @@ -118,6 +118,10 @@ SOURCE=.\StdAfx.h # PROP Default_Filter "" # Begin Source File +SOURCE=..\..\..\Common\CRC.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File @@ -566,6 +570,15 @@ SOURCE=..\..\Common\StreamUtils.h # PROP Default_Filter "" # Begin Source File +SOURCE=..\..\..\..\C\7zCrc.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrc.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File @@ -592,5 +605,17 @@ SOURCE=..\..\..\..\C\Threads.c SOURCE=..\..\..\..\C\Threads.h # End Source File # End Group +# Begin Group "Arc Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\OutStreamWithCRC.h +# End Source File +# End Group # End Target # End Project diff --git a/CPP/7zip/UI/Far/Main.cpp b/CPP/7zip/UI/Far/Main.cpp index f042a785..46a16a9f 100755 --- a/CPP/7zip/UI/Far/Main.cpp +++ b/CPP/7zip/UI/Far/Main.cpp @@ -173,11 +173,10 @@ public: } void ShowMessage(); - void LoadFileInfo(const UString &folderPrefix, - const UString &fileName) + void LoadFileInfo(const UString &folderPrefix, const UString &fileName) { _folderPrefix = folderPrefix; - if (!NWindows::NFile::NFind::FindFile(_folderPrefix + fileName, _fileInfo)) + if (!_fileInfo.Find(_folderPrefix + fileName)) throw 1; } }; @@ -297,7 +296,7 @@ STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, return E_ABORT; *inStream = NULL; UString fullPath = _folderPrefix + name; - if (!NWindows::NFile::NFind::FindFile(fullPath, _fileInfo)) + if (!_fileInfo.Find(fullPath)) return S_FALSE; if (_fileInfo.IsDir()) return S_FALSE; @@ -386,7 +385,7 @@ static HANDLE MyOpenFilePlugin(const char *name) int fileNamePartStartIndex; NFile::NDirectory::MyGetFullPathName(normalizedName, fullName, fileNamePartStartIndex); NFile::NFind::CFileInfoW fileInfo; - if (!NFile::NFind::FindFile(fullName, fileInfo)) + if (!fileInfo.Find(fullName)) return INVALID_HANDLE_VALUE; if (fileInfo.IsDir()) return INVALID_HANDLE_VALUE; @@ -415,7 +414,7 @@ static HANDLE MyOpenFilePlugin(const char *name) archiveHandler = new CAgent; CMyComBSTR archiveType; - HRESULT result = archiveHandler->Open( + HRESULT result = archiveHandler->Open(NULL, GetUnicodeString(fullName, CP_OEMCP), &archiveType, openArchiveCallback); /* HRESULT result = ::OpenArchive(fullName, &archiveHandler, diff --git a/CPP/7zip/UI/Far/Messages.h b/CPP/7zip/UI/Far/Messages.h index 1281b235..9c7c69fb 100755 --- a/CPP/7zip/UI/Far/Messages.h +++ b/CPP/7zip/UI/Far/Messages.h @@ -64,6 +64,17 @@ enum EEnum kChecksum, kCharacts, kVa, + kId, + kShortName, + kCreatorApp, + kSectorSize, + kPosixAttrib, + kLink, + + kTotalSize, + kFreeSpace, + kClusterSize, + kLabel, kGetPasswordTitle, kEnterPasswordForFile, diff --git a/CPP/7zip/UI/Far/Plugin.cpp b/CPP/7zip/UI/Far/Plugin.cpp index dc2a3ed1..c1e45a62 100755 --- a/CPP/7zip/UI/Far/Plugin.cpp +++ b/CPP/7zip/UI/Far/Plugin.cpp @@ -21,17 +21,14 @@ using namespace NWindows; using namespace NFar; CPlugin::CPlugin(const UString &fileName, - // const UString &defaultName, IInFolderArchive *archiveHandler, UString archiveTypeName ): m_ArchiveHandler(archiveHandler), m_FileName(fileName), _archiveTypeName(archiveTypeName) - // , m_DefaultName(defaultName) - // , m_ArchiverInfo(archiverInfo) { - if (!NFile::NFind::FindFile(m_FileName, m_FileInfo)) + if (!m_FileInfo.Find(m_FileName)) throw "error"; archiveHandler->BindToRootFolder(&_folder); } @@ -324,7 +321,18 @@ static CPROPIDToName kPROPIDToName[] = { kpidHeadersSize, NMessageID::kHeadersSize }, { kpidChecksum, NMessageID::kChecksum }, { kpidCharacts, NMessageID::kCharacts }, - { kpidVa, NMessageID::kVa } + { kpidVa, NMessageID::kVa }, + { kpidId, NMessageID::kId }, + { kpidShortName, NMessageID::kShortName}, + { kpidCreatorApp, NMessageID::kCreatorApp }, + { kpidSectorSize, NMessageID::kSectorSize }, + { kpidPosixAttrib, NMessageID::kPosixAttrib }, + { kpidLink, NMessageID::kLink }, + + { kpidTotalSize, NMessageID::kTotalSize }, + { kpidFreeSpace, NMessageID::kFreeSpace }, + { kpidClusterSize, NMessageID::kClusterSize }, + { kpidVolumeName, NMessageID::kLabel } }; static const int kNumPROPIDToName = sizeof(kPROPIDToName) / sizeof(kPROPIDToName[0]); diff --git a/CPP/7zip/UI/Far/Plugin.h b/CPP/7zip/UI/Far/Plugin.h index 034b1556..06003ba5 100755 --- a/CPP/7zip/UI/Far/Plugin.h +++ b/CPP/7zip/UI/Far/Plugin.h @@ -40,7 +40,6 @@ class CPlugin void GetCurrentDir(); public: UString m_FileName; - // UString m_DefaultName; NWindows::NFile::NFind::CFileInfoW m_FileInfo; CMyComPtr<IInFolderArchive> m_ArchiveHandler; diff --git a/CPP/7zip/UI/Far/PluginWrite.cpp b/CPP/7zip/UI/Far/PluginWrite.cpp index 2f7fbc83..44c6fecd 100755 --- a/CPP/7zip/UI/Far/PluginWrite.cpp +++ b/CPP/7zip/UI/Far/PluginWrite.cpp @@ -683,7 +683,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) CMyComPtr<IOutFolderArchive> outArchive; CMyComPtr<IInFolderArchive> archiveHandler; - if(NFind::FindFile(fullArchiveName, fileInfo)) + if(fileInfo.Find(fullArchiveName)) { if (fileInfo.IsDir()) throw "There is Directory with such name"; @@ -692,7 +692,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) archiveHandler = agentSpec; // CLSID realClassID; CMyComBSTR archiveType; - RINOK(agentSpec->Open( + RINOK(agentSpec->Open(NULL, GetUnicodeString(fullArchiveName, CP_OEMCP), // &realClassID, &archiveType, diff --git a/CPP/7zip/UI/Far/UpdateCallback100.cpp b/CPP/7zip/UI/Far/UpdateCallback100.cpp index dc90c810..0785f55b 100755 --- a/CPP/7zip/UI/Far/UpdateCallback100.cpp +++ b/CPP/7zip/UI/Far/UpdateCallback100.cpp @@ -52,3 +52,15 @@ STDMETHODIMP CUpdateCallback100Imp::UpdateErrorMessage(const wchar_t *message) return S_OK; } +extern HRESULT GetPassword(UString &password); + +STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword(BSTR *password) +{ + *password = NULL; + if (!m_PasswordIsDefined) + { + RINOK(GetPassword(m_Password)); + m_PasswordIsDefined = true; + } + return StringToBstr(m_Password, password); +} diff --git a/CPP/7zip/UI/Far/UpdateCallback100.h b/CPP/7zip/UI/Far/UpdateCallback100.h index 45f4daea..bfe8419a 100755 --- a/CPP/7zip/UI/Far/UpdateCallback100.h +++ b/CPP/7zip/UI/Far/UpdateCallback100.h @@ -1,33 +1,40 @@ // UpdateCallback.h -#ifndef __UPDATECALLBACK100_H -#define __UPDATECALLBACK100_H +#ifndef __UPDATE_CALLBACK_H +#define __UPDATE_CALLBACK_H #include "Common/MyCom.h" #include "../Agent/IFolderArchive.h" +#include "../../IPassword.h" + #include "ProgressBox.h" class CUpdateCallback100Imp: public IFolderArchiveUpdateCallback, + public ICryptoGetTextPassword, public CMyUnknownImp { // CMyComPtr<IInFolderArchive> _archiveHandler; CProgressBox *_progressBox; UInt64 _total; + bool m_PasswordIsDefined; + UString m_Password; public: - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(ICryptoGetTextPassword) INTERFACE_IProgress(;) INTERFACE_IFolderArchiveUpdateCallback(;) + STDMETHOD(CryptoGetTextPassword)(BSTR *password); CUpdateCallback100Imp(): _total(0) {} void Init(/* IInFolderArchive *archiveHandler, */ CProgressBox *progressBox) { // _archiveHandler = archiveHandler; _progressBox = progressBox; + m_PasswordIsDefined = false; } }; diff --git a/CPP/7zip/UI/Far/makefile b/CPP/7zip/UI/Far/makefile index dba62d63..01c77ded 100755 --- a/CPP/7zip/UI/Far/makefile +++ b/CPP/7zip/UI/Far/makefile @@ -64,6 +64,9 @@ UI_COMMON_OBJS = \ $O\WorkDir.obj \ $O\ZipRegistry.obj \ +AR_COMMON_OBJS = \ + $O\OutStreamWithCRC.obj \ + AGENT_OBJS = \ $O\Agent.obj \ $O\AgentOut.obj \ @@ -75,6 +78,8 @@ C_OBJS = \ $O\Sort.obj \ $O\Threads.obj \ +!include "../../Crc2.mak" + OBJS = \ $O\StdAfx.obj \ $(FAR_OBJS) \ @@ -82,9 +87,11 @@ OBJS = \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(UI_COMMON_OBJS) \ + $(AR_COMMON_OBJS) \ $(AGENT_OBJS) \ $(C_OBJS) \ $O\CopyCoder.obj \ + $(CRC_OBJS) \ $O\resource.res !include "../../../Build.mak" @@ -99,9 +106,12 @@ $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(UI_COMMON_OBJS): ../Common/$(*B).cpp $(COMPL) +$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp + $(COMPL) $(AGENT_OBJS): ../Agent/$(*B).cpp $(COMPL) $O\CopyCoder.obj: ../../Compress/$(*B).cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) +!include "../../Crc.mak" diff --git a/CPP/7zip/UI/FileManager/App.cpp b/CPP/7zip/UI/FileManager/App.cpp index f4f0bde7..21942065 100755 --- a/CPP/7zip/UI/FileManager/App.cpp +++ b/CPP/7zip/UI/FileManager/App.cpp @@ -157,12 +157,12 @@ static void CreateToolbar( struct CButtonInfo { - UINT commandID; + int CommandID; UINT BitmapResID; UINT Bitmap2ResID; UINT StringResID; - UINT32 LangID; - UString GetText()const { return LangString(StringResID, LangID); }; + UInt32 LangID; + UString GetText() const { return LangString(StringResID, LangID); }; }; static CButtonInfo g_StandardButtons[] = @@ -180,12 +180,12 @@ static CButtonInfo g_ArchiveButtons[] = { kTestCommand , IDB_TEST, IDB_TEST2, IDS_TEST, 0x03020402} }; -bool SetButtonText(UINT32 commandID, CButtonInfo *buttons, int numButtons, UString &s) +static bool SetButtonText(int commandID, CButtonInfo *buttons, int numButtons, UString &s) { for (int i = 0; i < numButtons; i++) { const CButtonInfo &b = buttons[i]; - if (b.commandID == commandID) + if (b.CommandID == commandID) { s = b.GetText(); return true; @@ -194,7 +194,7 @@ bool SetButtonText(UINT32 commandID, CButtonInfo *buttons, int numButtons, UStri return false; } -void SetButtonText(UINT32 commandID, UString &s) +static void SetButtonText(int commandID, UString &s) { if (SetButtonText(commandID, g_StandardButtons, sizeof(g_StandardButtons) / sizeof(g_StandardButtons[0]), s)) @@ -212,7 +212,7 @@ static void AddButton( { TBBUTTON but; but.iBitmap = 0; - but.idCommand = butInfo.commandID; + but.idCommand = butInfo.CommandID; but.fsState = TBSTATE_ENABLED; but.fsStyle = BTNS_BUTTON // | BTNS_AUTOSIZE @@ -428,20 +428,12 @@ void CApp::Release() Panels[i].Release(); } -static bool IsThereFolderOfPath(const UString &path) -{ - CFileInfoW fi; - if (!FindFile(path, fi)) - return false; - return fi.IsDir(); -} - // reduces path to part that exists on disk static void ReducePathToRealFileSystemPath(UString &path) { while (!path.IsEmpty()) { - if (IsThereFolderOfPath(path)) + if (NFind::DoesDirExist(path)) { NName::NormalizeDirPathPrefix(path); break; @@ -663,7 +655,7 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) } if (indices.Size() > 1 || (destPath.Length() > 0 && destPath.ReverseFind(WCHAR_PATH_SEPARATOR) == destPath.Length() - 1) || - IsThereFolderOfPath(destPath)) + NFind::DoesDirExist(destPath)) { NDirectory::CreateComplexDirectory(destPath); NName::NormalizeDirPathPrefix(destPath); @@ -698,7 +690,15 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) SaveCopyHistory(copyFolders); } - bool useSrcPanel = (!useDestPanel || !srcPanel.IsFSFolder() || destPanel.IsFSFolder()); + /* + if (destPath == destPanel._currentFolderPrefix) + { + if (destPanel.GetFolderTypeID() == L"PhysDrive") + useDestPanel = true; + } + */ + + bool useSrcPanel = (!useDestPanel || !srcPanel.IsFsOrDrivesFolder() || destPanel.IsFSFolder()); bool useTemp = useSrcPanel && useDestPanel; NFile::NDirectory::CTempDirectoryW tempDirectory; UString tempDirPrefix; @@ -857,7 +857,7 @@ void CApp::OnNotify(int /* ctrlID */, LPNMHDR pnmh) LPNMTTDISPINFO info = (LPNMTTDISPINFO)pnmh; info->hinst = 0; g_ToolTipBuffer.Empty(); - SetButtonText((UINT32)info->hdr.idFrom, g_ToolTipBuffer); + SetButtonText((int)info->hdr.idFrom, g_ToolTipBuffer); g_ToolTipBufferSys = GetSystemString(g_ToolTipBuffer); info->lpszText = (LPTSTR)(LPCTSTR)g_ToolTipBufferSys; return; @@ -868,7 +868,7 @@ void CApp::OnNotify(int /* ctrlID */, LPNMHDR pnmh) LPNMTTDISPINFOW info = (LPNMTTDISPINFOW)pnmh; info->hinst = 0; g_ToolTipBuffer.Empty(); - SetButtonText((UINT32)info->hdr.idFrom, g_ToolTipBuffer); + SetButtonText((int)info->hdr.idFrom, g_ToolTipBuffer); info->lpszText = (LPWSTR)(LPCWSTR)g_ToolTipBuffer; return; } @@ -893,4 +893,3 @@ void CApp::RefreshTitle(int panelIndex, bool always) return; RefreshTitle(always); } - diff --git a/CPP/7zip/UI/FileManager/App.h b/CPP/7zip/UI/FileManager/App.h index d30e1151..1fc77138 100755 --- a/CPP/7zip/UI/FileManager/App.h +++ b/CPP/7zip/UI/FileManager/App.h @@ -204,6 +204,7 @@ public: void Delete(bool toRecycleBin) { GetFocusedPanel().DeleteItems(toRecycleBin); } void CalculateCrc(); + void DiffFiles(); void Split(); void Combine(); void Properties() diff --git a/CPP/7zip/UI/FileManager/AppState.h b/CPP/7zip/UI/FileManager/AppState.h index 5ba0d47f..4f8b7bbe 100755 --- a/CPP/7zip/UI/FileManager/AppState.h +++ b/CPP/7zip/UI/FileManager/AppState.h @@ -1,10 +1,12 @@ // AppState.h -#ifndef __APPSTATE_H -#define __APPSTATE_H +#ifndef __APP_STATE_H +#define __APP_STATE_H #include "Windows/Synchronization.h" +#include "ViewSettings.h" + void inline AddUniqueStringToHead(UStringVector &list, const UString &string) { diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.cpp b/CPP/7zip/UI/FileManager/ExtractCallback.cpp index b5e70d02..9902e9a1 100755 --- a/CPP/7zip/UI/FileManager/ExtractCallback.cpp +++ b/CPP/7zip/UI/FileManager/ExtractCallback.cpp @@ -2,27 +2,26 @@ #include "StdAfx.h" -#include "ExtractCallback.h" +#include "Common/Wildcard.h" +#include "Common/StringConvert.h" #include "Windows/Error.h" -#include "Windows/FileFind.h" #include "Windows/FileDir.h" +#include "Windows/FileFind.h" #include "Windows/ResourceString.h" -#include "OverwriteDialog.h" -#ifndef _NO_CRYPTO -#include "PasswordDialog.h" -#endif -#include "MessagesDialog.h" +#include "../../Common/FilePathAutoRename.h" + #include "../GUI/ExtractRes.h" #include "../GUI/resource.h" -#include "Common/Wildcard.h" -#include "Common/StringConvert.h" - +#include "ExtractCallback.h" #include "FormatUtils.h" - -#include "../../Common/FilePathAutoRename.h" +#include "MessagesDialog.h" +#include "OverwriteDialog.h" +#ifndef _NO_CRYPTO +#include "PasswordDialog.h" +#endif using namespace NWindows; using namespace NFile; @@ -351,6 +350,8 @@ HRESULT CExtractCallbackImp::ExtractResult(HRESULT result) return S_OK; } +#ifndef _NO_CRYPTO + HRESULT CExtractCallbackImp::SetPassword(const UString &password) { PasswordIsDefined = true; @@ -372,6 +373,7 @@ STDMETHODIMP CExtractCallbackImp::CryptoGetTextPassword(BSTR *password) return StringToBstr(Password, password); } +#endif // IExtractCallBack3 STDMETHODIMP CExtractCallbackImp::AskWrite( @@ -392,7 +394,7 @@ STDMETHODIMP CExtractCallbackImp::AskWrite( UString destPathSys = destPathSpec; bool srcIsFolderSpec = IntToBool(srcIsFolder); CFileInfoW destFileInfo; - if (FindFile(destPathSys, destFileInfo)) + if (destFileInfo.Find(destPathSys)) { if (srcIsFolderSpec) { @@ -474,4 +476,3 @@ STDMETHODIMP CExtractCallbackImp::AskWrite( *writeAnswer = BoolToInt(true); return StringToBstr(destPathResultTemp, destPathResult); } - diff --git a/CPP/7zip/UI/FileManager/FM.cpp b/CPP/7zip/UI/FileManager/FM.cpp index fc94bcbf..e4bcc998 100755 --- a/CPP/7zip/UI/FileManager/FM.cpp +++ b/CPP/7zip/UI/FileManager/FM.cpp @@ -2,40 +2,28 @@ #include "StdAfx.h" -#include "resource.h" -#include "Panel.h" - -extern "C" -{ - #include "../../../../C/Alloc.h" -} +#include "../../../../C/Alloc.h" -#include "Common/Defs.h" -#include "Common/StringConvert.h" -// #include "Common/CommandLineParser.h" - -#include "Windows/Control/Toolbar.h" #include "Windows/Error.h" -#include "Windows/COM.h" -#include "Windows/DLL.h" -#include "Windows/Security.h" #include "Windows/MemoryLock.h" +#include "Windows/Security.h" -#include "ViewSettings.h" #include "../GUI/ExtractRes.h" -#include "App.h" -#include "StringUtils.h" +#include "resource.h" -#include "MyLoadMenu.h" -#include "LangUtils.h" +#include "App.h" #include "FormatUtils.h" +#include "LangUtils.h" +#include "MyLoadMenu.h" +#include "Panel.h" #include "RegistryUtils.h" +#include "StringUtils.h" +#include "ViewSettings.h" using namespace NWindows; using namespace NFile; using namespace NFind; -// using namespace NCommandLineParser; #define MAX_LOADSTRING 100 @@ -617,10 +605,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) bool needOpenFile = false; if (!g_MainPath.IsEmpty() /* && g_OpenArchive */) { - NFile::NFind::CFileInfoW fileInfo; - if (NFile::NFind::FindFile(g_MainPath, fileInfo)) - if (!fileInfo.IsDir()) - needOpenFile = true; + if (NFile::NFind::DoesFileExist(g_MainPath)) + needOpenFile = true; } HRESULT res = g_App.Create(hWnd, g_MainPath, xSizes, archiveIsOpened, encrypted); diff --git a/CPP/7zip/UI/FileManager/FM.dsp b/CPP/7zip/UI/FileManager/FM.dsp index 6727b085..2c3ab6c8 100755 --- a/CPP/7zip/UI/FileManager/FM.dsp +++ b/CPP/7zip/UI/FileManager/FM.dsp @@ -45,7 +45,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -72,7 +72,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" @@ -99,7 +99,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"StdAfx.h" /FD /c -# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -127,7 +127,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c -# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" @@ -210,13 +210,21 @@ SOURCE=.\StdAfx.h SOURCE=.\Test.bmp # End Source File # End Group -# Begin Group "Archive Interfaces" +# Begin Group "Archive" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\IArchive.h # End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\OutStreamWithCRC.h +# End Source File # End Group # Begin Group "Folders" @@ -255,14 +263,6 @@ SOURCE=.\NetFolder.h # End Source File # Begin Source File -SOURCE=.\PhysDriveFolder.cpp -# End Source File -# Begin Source File - -SOURCE=.\PhysDriveFolder.h -# End Source File -# Begin Source File - SOURCE=.\RootFolder.cpp # End Source File # Begin Source File @@ -831,14 +831,6 @@ SOURCE=..\..\..\Windows\Error.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\FileDevice.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\..\Windows\FileDevice.h -# End Source File -# Begin Source File - SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/UI/FileManager/FSDrives.cpp b/CPP/7zip/UI/FileManager/FSDrives.cpp index f2d7ac93..87ee3fc9 100755 --- a/CPP/7zip/UI/FileManager/FSDrives.cpp +++ b/CPP/7zip/UI/FileManager/FSDrives.cpp @@ -2,48 +2,118 @@ #include "StdAfx.h" -#include "resource.h" - -#include "FSDrives.h" +#include "../../../../C/Alloc.h" -#include "Common/StringConvert.h" #include "Common/ComTry.h" -#include "../../PropID.h" +#include "Common/StringConvert.h" + #include "Windows/Defs.h" -#include "Windows/PropVariant.h" #include "Windows/FileDir.h" +#include "Windows/FileIO.h" #include "Windows/FileSystem.h" +#include "Windows/PropVariant.h" -#include "SysIconUtils.h" +#include "../../PropID.h" + +#include "FSDrives.h" #include "FSFolder.h" -#include "PhysDriveFolder.h" #include "LangUtils.h" +#include "SysIconUtils.h" + +#include "resource.h" using namespace NWindows; using namespace NFile; using namespace NFind; -static const STATPROPSTG kProperties[] = +static const wchar_t *kVolPrefix = L"\\\\.\\"; + +UString CDriveInfo::GetDeviceFileIoName() const +{ + return kVolPrefix + Name; +} + +struct CPhysTempBuffer +{ + void *buffer; + CPhysTempBuffer(): buffer(0) {} + ~CPhysTempBuffer() { MidFree(buffer); } +}; + +static HRESULT CopyFileSpec(LPCWSTR fromPath, LPCWSTR toPath, bool writeToDisk, UInt64 fileSize, + UInt32 bufferSize, UInt64 progressStart, IProgress *progress) +{ + NFile::NIO::CInFile inFile; + if (!inFile.Open(fromPath)) + return GetLastError(); + if (fileSize == (UInt64)(Int64)-1) + { + if (!inFile.GetLength(fileSize)) + ::GetLastError(); + } + NFile::NIO::COutFile outFile; + if (writeToDisk) + { + if (!outFile.Open(toPath, FILE_SHARE_WRITE, OPEN_EXISTING, 0)) + return GetLastError(); + } + else + if (!outFile.Create(toPath, true)) + return GetLastError(); + CPhysTempBuffer tempBuffer; + tempBuffer.buffer = MidAlloc(bufferSize); + if (tempBuffer.buffer == 0) + return E_OUTOFMEMORY; + + for (UInt64 pos = 0; pos < fileSize;) + { + UInt64 progressCur = progressStart + pos; + RINOK(progress->SetCompleted(&progressCur)); + UInt64 rem = fileSize - pos; + UInt32 curSize = (UInt32)MyMin(rem, (UInt64)bufferSize); + UInt32 processedSize; + if (!inFile.Read(tempBuffer.buffer, curSize, processedSize)) + return GetLastError(); + if (processedSize == 0) + break; + curSize = processedSize; + if (writeToDisk) + { + const UInt32 kMask = 0x1FF; + curSize = (curSize + kMask) & ~kMask; + if (curSize > bufferSize) + return E_FAIL; + } + + if (!outFile.Write(tempBuffer.buffer, curSize, processedSize)) + return GetLastError(); + if (curSize != processedSize) + return E_FAIL; + pos += curSize; + } + return S_OK; +} + +static const STATPROPSTG kProps[] = { { NULL, kpidName, VT_BSTR}, - // { NULL, kpidIsDir, VT_BOOL}, - { L"Total Size", kpidTotalSize, VT_UI8}, - { L"Free Space", kpidFreeSpace, VT_UI8}, + { NULL, kpidTotalSize, VT_UI8}, + { NULL, kpidFreeSpace, VT_UI8}, { NULL, kpidType, VT_BSTR}, - { L"Label", kpidVolumeName, VT_BSTR}, - { L"File system", kpidFileSystem, VT_BSTR}, - { L"Cluster Size", kpidClusterSize, VT_UI8} + { NULL, kpidVolumeName, VT_BSTR}, + { NULL, kpidFileSystem, VT_BSTR}, + { NULL, kpidClusterSize, VT_UI8} }; -static const wchar_t *kDriveTypes[] = +static const char *kDriveTypes[] = { - L"Unknown", - L"No Root Dir", - L"Removable", - L"Fixed", - L"Remote", - L"CD-ROM", - L"RAM disk" + "Unknown", + "No Root Dir", + "Removable", + "Fixed", + "Remote", + "CD-ROM", + "RAM disk" }; STDMETHODIMP CFSDrives::LoadItems() @@ -60,18 +130,13 @@ STDMETHODIMP CFSDrives::LoadItems() di.FullSystemName = driveName; - di.Name = di.FullSystemName.Left( - di.FullSystemName.Length() - 1); + di.Name = di.FullSystemName.Left(di.FullSystemName.Length() - 1); di.ClusterSize = 0; di.DriveSize = 0; di.FreeSpace = 0; - UINT driveType = NFile::NSystem::MyGetDriveType(driveName); - if (driveType < sizeof(kDriveTypes) / sizeof(kDriveTypes[0])) - { - di.Type = kDriveTypes[driveType]; - } + di.DriveType = NFile::NSystem::MyGetDriveType(driveName); bool needRead = true; - if (driveType == DRIVE_CDROM || driveType == DRIVE_REMOVABLE) + if (di.DriveType == DRIVE_CDROM || di.DriveType == DRIVE_REMOVABLE) { /* DWORD dwSerialNumber;` @@ -117,12 +182,15 @@ STDMETHODIMP CFSDrives::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT const CDriveInfo &di = _drives[itemIndex]; switch(propID) { - case kpidIsDir: prop = true; break; + case kpidIsDir: prop = !_volumeMode; break; case kpidName: prop = di.Name; break; case kpidTotalSize: if (di.KnownSizes) prop = di.DriveSize; break; case kpidFreeSpace: if (di.KnownSizes) prop = di.FreeSpace; break; case kpidClusterSize: if (di.KnownSizes) prop = di.ClusterSize; break; - case kpidType: prop = di.Type; break; + case kpidType: + if (di.DriveType < sizeof(kDriveTypes) / sizeof(kDriveTypes[0])) + prop = kDriveTypes[di.DriveType]; + break; case kpidVolumeName: prop = di.VolumeName; break; case kpidFileSystem: prop = di.FileSystemName; break; } @@ -133,6 +201,8 @@ STDMETHODIMP CFSDrives::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT HRESULT CFSDrives::BindToFolderSpec(const wchar_t *name, IFolderFolder **resultFolder) { *resultFolder = 0; + if (_volumeMode) + return S_OK; NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder; CMyComPtr<IFolderFolder> subFolder = fsFolderSpec; RINOK(fsFolderSpec->Init(name, 0)); @@ -146,6 +216,7 @@ STDMETHODIMP CFSDrives::BindToFolder(UInt32 index, IFolderFolder **resultFolder) if (index >= (UInt32)_drives.Size()) return E_INVALIDARG; const CDriveInfo &di = _drives[index]; + /* if (_volumeMode) { *resultFolder = 0; @@ -155,6 +226,7 @@ STDMETHODIMP CFSDrives::BindToFolder(UInt32 index, IFolderFolder **resultFolder) *resultFolder = subFolder.Detach(); return S_OK; } + */ return BindToFolderSpec(di.FullSystemName, resultFolder); } @@ -169,24 +241,7 @@ STDMETHODIMP CFSDrives::BindToParentFolder(IFolderFolder **resultFolder) return S_OK; } -STDMETHODIMP CFSDrives::GetNumberOfProperties(UInt32 *numProperties) -{ - *numProperties = sizeof(kProperties) / sizeof(kProperties[0]); - return S_OK; -} - -STDMETHODIMP CFSDrives::GetPropertyInfo(UInt32 index, - BSTR *name, PROPID *propID, VARTYPE *varType) -{ - if (index >= sizeof(kProperties) / sizeof(kProperties[0])) - return E_INVALIDARG; - const STATPROPSTG &prop = kProperties[index]; - *propID = prop.propid; - *varType = prop.vt; - *name = 0; - return S_OK; -} - +IMP_IFolderFolder_Props(CFSDrives) STDMETHODIMP CFSDrives::GetFolderProperty(PROPID propID, PROPVARIANT *value) { @@ -195,14 +250,20 @@ STDMETHODIMP CFSDrives::GetFolderProperty(PROPID propID, PROPVARIANT *value) switch(propID) { case kpidType: prop = L"FSDrives"; break; - case kpidPath: prop = LangString(IDS_COMPUTER, 0x03020300) + UString(WCHAR_PATH_SEPARATOR); break; + case kpidPath: + if (_volumeMode) + prop = kVolPrefix; + else + prop = LangString(IDS_COMPUTER, 0x03020300) + UString(WCHAR_PATH_SEPARATOR); + break; } prop.Detach(value); return S_OK; COM_TRY_END } -STDMETHODIMP CFSDrives::GetSystemIconIndex(UInt32 index, INT32 *iconIndex) + +STDMETHODIMP CFSDrives::GetSystemIconIndex(UInt32 index, Int32 *iconIndex) { *iconIndex = 0; const CDriveInfo &di = _drives[index]; @@ -215,3 +276,145 @@ STDMETHODIMP CFSDrives::GetSystemIconIndex(UInt32 index, INT32 *iconIndex) return GetLastError(); } +UString CFSDrives::GetExt(int index) const +{ + const CDriveInfo &di = _drives[index]; + const wchar_t *ext = NULL; + if (di.DriveType == DRIVE_CDROM) + ext = L"iso"; + else if (di.FileSystemName.Find(L"NTFS") >= 0) + ext = L"ntfs"; + else if (di.FileSystemName.Find(L"FAT") >= 0) + ext = L"fat"; + else + ext = L"img"; + return (UString)L'.' + ext; +} + +HRESULT CFSDrives::GetLength(int index, UInt64 &length) const +{ + NFile::NIO::CInFile inFile; + if (!inFile.Open(_drives[index].GetDeviceFileIoName())) + return GetLastError(); + if (!inFile.LengthDefined) + return E_FAIL; + length = inFile.Length; + return S_OK; +} + +STDMETHODIMP CFSDrives::CopyTo(const UInt32 *indices, UInt32 numItems, + const wchar_t *path, IFolderOperationsExtractCallback *callback) +{ + if (numItems == 0) + return S_OK; + + if (!_volumeMode) + return E_NOTIMPL; + + UInt64 totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + { + const CDriveInfo &di = _drives[indices[i]]; + if (di.KnownSizes) + totalSize += di.DriveSize; + } + RINOK(callback->SetTotal(totalSize)); + RINOK(callback->SetNumFiles(numItems)); + + UString destPath = path; + if (destPath.IsEmpty()) + return E_INVALIDARG; + bool directName = (destPath[destPath.Length() - 1] != WCHAR_PATH_SEPARATOR); + if (directName) + { + if (numItems > 1) + return E_INVALIDARG; + } + + UInt64 completedSize = 0; + RINOK(callback->SetCompleted(&completedSize)); + for (i = 0; i < numItems; i++) + { + int index = indices[i]; + const CDriveInfo &di = _drives[index]; + UString destPath2 = destPath; + UString name = di.Name; + if (!directName) + { + UString destName = name; + if (!destName.IsEmpty() && destName[destName.Length() - 1] == L':') + { + destName.Delete(destName.Length() - 1); + destName += GetExt(index); + } + destPath2 += destName; + } + UString srcPath = di.GetDeviceFileIoName(); + + UInt64 fileSize = 0; + if (GetLength(index, fileSize) != S_OK) + { + return E_FAIL; + } + if (!di.KnownSizes) + totalSize += fileSize; + RINOK(callback->SetTotal(totalSize)); + + Int32 writeAskResult; + CMyComBSTR destPathResult; + RINOK(callback->AskWrite(srcPath, BoolToInt(false), NULL, &fileSize, + destPath2, &destPathResult, &writeAskResult)); + if (!IntToBool(writeAskResult)) + continue; + + RINOK(callback->SetCurrentFilePath(srcPath)); + + static const UInt32 kBufferSize = (4 << 20); + UInt32 bufferSize = (di.DriveType == DRIVE_REMOVABLE) ? (18 << 10) * 4 : kBufferSize; + RINOK(CopyFileSpec(srcPath, destPathResult, false, fileSize, bufferSize, completedSize, callback)); + completedSize += fileSize; + } + return S_OK; +} + +STDMETHODIMP CFSDrives::MoveTo( + const UInt32 * /* indices */, + UInt32 /* numItems */, + const wchar_t * /* path */, + IFolderOperationsExtractCallback * /* callback */) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CFSDrives::CopyFrom(const wchar_t * /* fromFolderPath */, + const wchar_t ** /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CFSDrives::CreateFolder(const wchar_t * /* name */, IProgress * /* progress */) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CFSDrives::CreateFile(const wchar_t * /* name */, IProgress * /* progress */) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CFSDrives::Rename(UInt32 /* index */, const wchar_t * /* newName */, IProgress * /* progress */) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CFSDrives::Delete(const UInt32 * /* indices */, UInt32 /* numItems */, IProgress * /* progress */) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CFSDrives::SetProperty(UInt32 /* index */, PROPID /* propID */, + const PROPVARIANT * /* value */, IProgress * /* progress */) +{ + return E_NOTIMPL; +} diff --git a/CPP/7zip/UI/FileManager/FSDrives.h b/CPP/7zip/UI/FileManager/FSDrives.h index 84db5b7e..fc99bce7 100755 --- a/CPP/7zip/UI/FileManager/FSDrives.h +++ b/CPP/7zip/UI/FileManager/FSDrives.h @@ -1,13 +1,10 @@ // FSDrives.h -#ifndef __FSDRIVES_H -#define __FSDRIVES_H +#ifndef __FS_DRIVES_H +#define __FS_DRIVES_H -#include "Common/MyString.h" -#include "Common/Types.h" #include "Common/MyCom.h" -#include "Windows/FileFind.h" -#include "Windows/PropVariant.h" +#include "Common/MyString.h" #include "IFolder.h" @@ -19,31 +16,38 @@ struct CDriveInfo UInt64 DriveSize; UInt64 FreeSpace; UInt64 ClusterSize; - UString Type; + // UString Type; UString VolumeName; UString FileSystemName; + UINT DriveType; + + UString GetDeviceFileIoName() const; }; class CFSDrives: public IFolderFolder, + public IFolderOperations, public IFolderGetSystemIconIndex, public CMyUnknownImp { + CObjectVector<CDriveInfo> _drives; + bool _volumeMode; + + HRESULT BindToFolderSpec(const wchar_t *name, IFolderFolder **resultFolder); + UString GetExt(int index) const; + HRESULT GetLength(int index, UInt64 &length) const; public: - MY_UNKNOWN_IMP1( - IFolderGetSystemIconIndex - ) + MY_UNKNOWN_IMP2(IFolderGetSystemIconIndex, IFolderOperations) INTERFACE_FolderFolder(;) + INTERFACE_FolderOperations(;) - STDMETHOD(GetSystemIconIndex)(UInt32 index, INT32 *iconIndex); + STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex); -private: - HRESULT BindToFolderSpec(const wchar_t *name, IFolderFolder **resultFolder); - CObjectVector<CDriveInfo> _drives; - bool _volumeMode; -public: - void Init() { _volumeMode = false;} + void Init(bool volMode = false) + { + _volumeMode = volMode; + } }; #endif diff --git a/CPP/7zip/UI/FileManager/FSFolder.cpp b/CPP/7zip/UI/FileManager/FSFolder.cpp index 604c9b9c..5951fc09 100755 --- a/CPP/7zip/UI/FileManager/FSFolder.cpp +++ b/CPP/7zip/UI/FileManager/FSFolder.cpp @@ -2,22 +2,20 @@ #include "StdAfx.h" -#include "FSFolder.h" - +#include "Common/ComTry.h" #include "Common/StringConvert.h" #include "Common/UTFConvert.h" -#include "Common/ComTry.h" -#include "Windows/Defs.h" -#include "Windows/PropVariant.h" #include "Windows/FileDir.h" #include "Windows/FileIO.h" +#include "Windows/PropVariant.h" #include "../../PropID.h" -#include "SysIconUtils.h" #include "FSDrives.h" +#include "FSFolder.h" #include "NetFolder.h" +#include "SysIconUtils.h" namespace NWindows { namespace NFile { @@ -32,10 +30,9 @@ using namespace NFind; namespace NFsFolder { -static STATPROPSTG kProperties[] = +static STATPROPSTG kProps[] = { { NULL, kpidName, VT_BSTR}, - // { NULL, kpidIsDir, VT_BOOL}, { NULL, kpidSize, VT_UI8}, { NULL, kpidMTime, VT_FILETIME}, { NULL, kpidCTime, VT_FILETIME}, @@ -152,7 +149,7 @@ void CFSFolder::AddRefs(CDirItem &dirItem) STDMETHODIMP CFSFolder::LoadItems() { // OutputDebugString(TEXT("Start\n")); - INT32 dummy; + Int32 dummy; WasChanged(&dummy); Clear(); RINOK(LoadSubItems(_root, _path)); @@ -394,24 +391,13 @@ STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder) STDMETHODIMP CFSFolder::GetNumberOfProperties(UInt32 *numProperties) { - *numProperties = sizeof(kProperties) / sizeof(kProperties[0]); + *numProperties = sizeof(kProps) / sizeof(kProps[0]); if (!_flatMode) (*numProperties)--; return S_OK; } -STDMETHODIMP CFSFolder::GetPropertyInfo(UInt32 index, - BSTR *name, PROPID *propID, VARTYPE *varType) -{ - if (index >= sizeof(kProperties) / sizeof(kProperties[0])) - return E_INVALIDARG; - const STATPROPSTG &prop = kProperties[index]; - *propID = prop.propid; - *varType = prop.vt; - *name = 0; - return S_OK; -} - +STDMETHODIMP CFSFolder::GetPropertyInfo IMP_IFolderFolder_GetProp(kProps) STDMETHODIMP CFSFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) { @@ -427,7 +413,7 @@ STDMETHODIMP CFSFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) COM_TRY_END } -STDMETHODIMP CFSFolder::WasChanged(INT32 *wasChanged) +STDMETHODIMP CFSFolder::WasChanged(Int32 *wasChanged) { bool wasChangedMain = false; for (;;) @@ -640,7 +626,7 @@ STDMETHODIMP CFSFolder::SetProperty(UInt32 index, PROPID propID, return S_OK; } -STDMETHODIMP CFSFolder::GetSystemIconIndex(UInt32 index, INT32 *iconIndex) +STDMETHODIMP CFSFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex) { if (index >= (UInt32)_refs.Size()) return E_INVALIDARG; diff --git a/CPP/7zip/UI/FileManager/FSFolder.h b/CPP/7zip/UI/FileManager/FSFolder.h index ca229055..95f40bb3 100755 --- a/CPP/7zip/UI/FileManager/FSFolder.h +++ b/CPP/7zip/UI/FileManager/FSFolder.h @@ -5,11 +5,10 @@ #include "Common/MyString.h" #include "Common/MyCom.h" + #include "Windows/FileFind.h" -#include "Windows/PropVariant.h" #include "IFolder.h" - #include "TextPairs.h" namespace NFsFolder { @@ -65,13 +64,13 @@ public: INTERFACE_FolderFolder(;) INTERFACE_FolderOperations(;) - STDMETHOD(WasChanged)(INT32 *wasChanged); + STDMETHOD(WasChanged)(Int32 *wasChanged); STDMETHOD(Clone)(IFolderFolder **resultFolder); STDMETHOD(GetItemFullSize)(UInt32 index, PROPVARIANT *value, IProgress *progress); STDMETHOD(SetFlatMode)(Int32 flatMode); - STDMETHOD(GetSystemIconIndex)(UInt32 index, INT32 *iconIndex); + STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex); private: UString _path; diff --git a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp index b2d057df..9711616c 100755 --- a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp +++ b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp @@ -4,14 +4,15 @@ #include <Winbase.h> -#include "FSFolder.h" +#include "Common/StringConvert.h" + #include "Windows/FileDir.h" #include "Windows/Error.h" -#include "Common/StringConvert.h" - #include "../../Common/FilePathAutoRename.h" +#include "FSFolder.h" + using namespace NWindows; using namespace NFile; using namespace NFind; @@ -189,7 +190,7 @@ static HRESULT MyCopyFile( return E_ABORT; } - INT32 writeAskResult; + Int32 writeAskResult; CMyComBSTR destPathResult; RINOK(callback->AskWrite( srcPath, @@ -340,7 +341,7 @@ HRESULT MyMoveFile( return E_ABORT; } - INT32 writeAskResult; + Int32 writeAskResult; CMyComBSTR destPathResult; RINOK(callback->AskWrite( srcPath, @@ -510,5 +511,5 @@ STDMETHODIMP CFSFolder::CopyFrom(const wchar_t * /* fromFolderPath */, */ return E_NOTIMPL; } - + } diff --git a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp index 3cd79da0..992fbd8c 100755 --- a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp +++ b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp @@ -4,21 +4,15 @@ #include "resource.h" -#include "Common/StringConvert.h" -#include "Windows/Defs.h" -#include "Windows/FileDir.h" -#include "Windows/FileName.h" -#include "Windows/DLL.h" #include "Windows/Thread.h" -#include "IFolder.h" -#include "RegistryAssociations.h" -#include "RegistryPlugins.h" +#include "../Agent/Agent.h" +#include "LangUtils.h" #include "OpenCallback.h" #include "PluginLoader.h" -#include "LangUtils.h" -#include "../Agent/Agent.h" +#include "RegistryAssociations.h" +#include "RegistryPlugins.h" using namespace NWindows; using namespace NRegistryAssociations; @@ -26,6 +20,7 @@ using namespace NRegistryAssociations; struct CThreadArchiveOpen { UString Path; + CMyComPtr<IInStream> InStream; CMyComPtr<IFolderManager> FolderManager; CMyComPtr<IProgress> OpenCallback; COpenArchiveCallback *OpenCallbackSpec; @@ -36,7 +31,7 @@ struct CThreadArchiveOpen void Process() { OpenCallbackSpec->ProgressDialog.WaitCreating(); - Result = FolderManager->OpenFolderFile(Path, &Folder, OpenCallback); + Result = FolderManager->OpenFolderFile(InStream, Path, &Folder, OpenCallback); OpenCallbackSpec->ProgressDialog.MyClose(); } @@ -57,6 +52,7 @@ static int FindPlugin(const CObjectVector<CPluginInfo> &plugins, } HRESULT OpenFileFolderPlugin( + IInStream *inStream, const UString &path, HMODULE *module, IFolderFolder **resultFolder, @@ -66,13 +62,7 @@ HRESULT OpenFileFolderPlugin( CObjectVector<CPluginInfo> plugins; ReadFileFolderPluginInfoList(plugins); - UString extension; - UString name, pureName, dot; - - if(!NFile::NDirectory::GetOnlyName(path, name)) - return E_FAIL; - NFile::NName::SplitNameToPureNameAndExtension(name, pureName, dot, extension); - + UString extension, name, pureName, dot; int slashPos = path.ReverseFind(WCHAR_PATH_SEPARATOR); UString dirPrefix; @@ -85,6 +75,8 @@ HRESULT OpenFileFolderPlugin( else fileName = path; + NFile::NName::SplitNameToPureNameAndExtension(fileName, pureName, dot, extension); + if (!extension.IsEmpty()) { CExtInfo extInfo; @@ -122,8 +114,13 @@ HRESULT OpenFileFolderPlugin( t.OpenCallbackSpec->PasswordIsDefined = encrypted; t.OpenCallbackSpec->Password = password; t.OpenCallbackSpec->ParentWindow = parentWindow; - t.OpenCallbackSpec->LoadFileInfo(dirPrefix, fileName); + if (inStream) + t.OpenCallbackSpec->SetSubArchiveName(fileName); + else + t.OpenCallbackSpec->LoadFileInfo(dirPrefix, fileName); + + t.InStream = inStream; t.Path = path; UString progressTitle = LangString(IDS_OPENNING, 0x03020283); diff --git a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h index 9e5c66c7..692417ba 100755 --- a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h +++ b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h @@ -1,9 +1,9 @@ // FileFolderPluginOpen.h -#ifndef __FILEFOLDERPLUGINOPEN_H -#define __FILEFOLDERPLUGINOPEN_H +#ifndef __FILE_FOLDER_PLUGIN_OPEN_H +#define __FILE_FOLDER_PLUGIN_OPEN_H -HRESULT OpenFileFolderPlugin(const UString &path, +HRESULT OpenFileFolderPlugin(IInStream *inStream, const UString &path, HMODULE *module, IFolderFolder **resultFolder, HWND parentWindow, bool &encrypted, UString &password); #endif diff --git a/CPP/7zip/UI/FileManager/IFolder.h b/CPP/7zip/UI/FileManager/IFolder.h index 6709cd1e..b301f513 100755 --- a/CPP/7zip/UI/FileManager/IFolder.h +++ b/CPP/7zip/UI/FileManager/IFolder.h @@ -4,6 +4,7 @@ #define __IFOLDER_H #include "../../IProgress.h" +#include "../../IStream.h" #define FOLDER_INTERFACE_SUB(i, b, x) DECL_INTERFACE_SUB(i, b, 8, x) #define FOLDER_INTERFACE(i, x) FOLDER_INTERFACE_SUB(i, IUnknown, x) @@ -106,7 +107,7 @@ FOLDER_INTERFACE(IFolderSetFlatMode, 0x0A) STDMETHOD(GetNumberOfFolderProperties)(UInt32 *numProperties) x; \ STDMETHOD(GetFolderPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \ -FOLDER_INTERFACE(IFolderProperties, 0x0B) +FOLDER_INTERFACE(IFolderProperties, 0x0E) { INTERFACE_FolderProperties(PURE) }; @@ -129,17 +130,28 @@ FOLDER_INTERFACE(IGetFolderArchiveProperties, 0x0D) #define FOLDER_MANAGER_INTERFACE(i, x) DECL_INTERFACE(i, 9, x) #define INTERFACE_IFolderManager(x) \ - STDMETHOD(OpenFolderFile)(const wchar_t *filePath, IFolderFolder **resultFolder, IProgress *progress) x; \ + STDMETHOD(OpenFolderFile)(IInStream *inStream, const wchar_t *filePath, IFolderFolder **resultFolder, IProgress *progress) x; \ STDMETHOD(GetExtensions)(BSTR *extensions) x; \ STDMETHOD(GetIconPath)(const wchar_t *ext, BSTR *iconPath, Int32 *iconIndex) x; \ // STDMETHOD(GetTypes)(BSTR *types) PURE; // STDMETHOD(CreateFolderFile)(const wchar_t *type, const wchar_t *filePath, IProgress *progress) PURE; -FOLDER_MANAGER_INTERFACE(IFolderManager, 0x03) +FOLDER_MANAGER_INTERFACE(IFolderManager, 0x04) { INTERFACE_IFolderManager(PURE); }; +#define IMP_IFolderFolder_GetProp(k) \ + (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ + { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ + const STATPROPSTG &srcItem = k[index]; \ + *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \ + +#define IMP_IFolderFolder_Props(c) \ + STDMETHODIMP c::GetNumberOfProperties(UInt32 *numProperties) \ + { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ + STDMETHODIMP c::GetPropertyInfo IMP_IFolderFolder_GetProp(kProps) + #endif diff --git a/CPP/7zip/UI/FileManager/LangPage.rc b/CPP/7zip/UI/FileManager/LangPage.rc index 0e06406c..bd4d83d8 100755 --- a/CPP/7zip/UI/FileManager/LangPage.rc +++ b/CPP/7zip/UI/FileManager/LangPage.rc @@ -1,8 +1,8 @@ #include "LangPageRes.h" #include "../../GuiCommon.rc" -#define xSize2 238 -#define ySize2 204 +#define xSize2 196 +#define ySize2 140 #define xSize (xSize2 + marg + marg) #define ySize (ySize2 + marg + marg) diff --git a/CPP/7zip/UI/FileManager/LangUtils.cpp b/CPP/7zip/UI/FileManager/LangUtils.cpp index 0591c73c..52f85348 100755 --- a/CPP/7zip/UI/FileManager/LangUtils.cpp +++ b/CPP/7zip/UI/FileManager/LangUtils.cpp @@ -104,7 +104,8 @@ void LoadLangs(CObjectVector<CLangEx> &langs) CLangEx lang; UString filePath = folderPath + fileInfo.Name; const int kExtSize = 4; - if (fileInfo.Name.Right(kExtSize) != L".txt") + const UString ext = fileInfo.Name.Right(kExtSize); + if (ext.CompareNoCase(L".txt") != 0) continue; lang.ShortName = fileInfo.Name.Left(fileInfo.Name.Length() - kExtSize); if (lang.Lang.Open(filePath)) diff --git a/CPP/7zip/UI/FileManager/ListViewDialog.cpp b/CPP/7zip/UI/FileManager/ListViewDialog.cpp index 7a78fcde..e8001cf6 100755 --- a/CPP/7zip/UI/FileManager/ListViewDialog.cpp +++ b/CPP/7zip/UI/FileManager/ListViewDialog.cpp @@ -43,6 +43,9 @@ bool CListViewDialog::OnNotify(UINT /* controlID */, LPNMHDR header) return false; switch(header->code) { + case NM_DBLCLK: + OnOK(); + return true; case LVN_KEYDOWN: { LPNMLVKEYDOWN keyDownInfo = LPNMLVKEYDOWN(header); diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp index c6f57f9e..f98325a0 100755 --- a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp +++ b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp @@ -1,23 +1,20 @@ -// MyLoadMenu +// MyLoadMenu.cpp #include "StdAfx.h" -#include "Common/StringConvert.h" - #include "Windows/Menu.h" -#include "Windows/Error.h" -#include "Windows/Clipboard.h" #include "../../PropID.h" -#include "resource.h" -#include "App.h" -#include "AboutDialog.h" #include "../Common/CompressCall.h" +#include "AboutDialog.h" +#include "App.h" #include "HelpUtils.h" #include "LangUtils.h" -#include "PluginInterface.h" +#include "RegistryUtils.h" + +#include "resource.h" static const UINT kOpenBookmarkMenuID = 730; static const UINT kSetBookmarkMenuID = 740; @@ -428,6 +425,9 @@ void LoadFileMenu(HMENU hMenu, int startPos, bool programMenu, CMenu destMenu; destMenu.Attach(hMenu); + + UString diffPath; + ReadRegDiff(diffPath); for (int i = 0; i < g_FileMenu.GetItemCount(); i++) { @@ -440,6 +440,10 @@ void LoadFileMenu(HMENU hMenu, int startPos, bool programMenu, if (!programMenu) if (item.wID == IDCLOSE) continue; + + if (item.wID == IDM_FILE_DIFF && diffPath.IsEmpty()) + continue; + bool isOneFsFile = (isFsFolder && numItems == 1 && allAreFiles); if ((item.wID == IDM_FILE_SPLIT || item.wID == IDM_FILE_COMBINE) && !isOneFsFile) item.fState |= MFS_DISABLED; @@ -522,6 +526,9 @@ bool ExecuteFileCommand(int id) case IDM_FILE_CRC: g_App.CalculateCrc(); break; + case IDM_FILE_DIFF: + g_App.DiffFiles(); + break; case IDM_FILE_SPLIT: g_App.Split(); break; diff --git a/CPP/7zip/UI/FileManager/NetFolder.cpp b/CPP/7zip/UI/FileManager/NetFolder.cpp index d3298c62..e1fa1965 100755 --- a/CPP/7zip/UI/FileManager/NetFolder.cpp +++ b/CPP/7zip/UI/FileManager/NetFolder.cpp @@ -2,21 +2,18 @@ #include "StdAfx.h" -#include "NetFolder.h" +#include "Windows/PropVariant.h" -#include "Common/StringConvert.h" #include "../../PropID.h" -#include "Windows/Defs.h" -#include "Windows/PropVariant.h" -#include "Windows/FileFind.h" -#include "SysIconUtils.h" #include "FSFolder.h" +#include "NetFolder.h" +#include "SysIconUtils.h" using namespace NWindows; using namespace NNet; -static const STATPROPSTG kProperties[] = +static const STATPROPSTG kProps[] = { { NULL, kpidName, VT_BSTR}, { NULL, kpidLocalName, VT_BSTR}, @@ -232,23 +229,7 @@ STDMETHODIMP CNetFolder::BindToParentFolder(IFolderFolder **resultFolder) return S_OK; } -STDMETHODIMP CNetFolder::GetNumberOfProperties(UInt32 *numProperties) -{ - *numProperties = sizeof(kProperties) / sizeof(kProperties[0]); - return S_OK; -} - -STDMETHODIMP CNetFolder::GetPropertyInfo(UInt32 index, - BSTR *name, PROPID *propID, VARTYPE *varType) -{ - if (index >= sizeof(kProperties) / sizeof(kProperties[0])) - return E_INVALIDARG; - const STATPROPSTG &prop = kProperties[index]; - *propID = prop.propid; - *varType = prop.vt; - *name = 0; - return S_OK; -} +IMP_IFolderFolder_Props(CNetFolder) STDMETHODIMP CNetFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) { @@ -262,7 +243,7 @@ STDMETHODIMP CNetFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) return S_OK; } -STDMETHODIMP CNetFolder::GetSystemIconIndex(UInt32 index, INT32 *iconIndex) +STDMETHODIMP CNetFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex) { if (index >= (UInt32)_items.Size()) return E_INVALIDARG; diff --git a/CPP/7zip/UI/FileManager/NetFolder.h b/CPP/7zip/UI/FileManager/NetFolder.h index 92471ec6..9962845c 100755 --- a/CPP/7zip/UI/FileManager/NetFolder.h +++ b/CPP/7zip/UI/FileManager/NetFolder.h @@ -1,12 +1,10 @@ // NetFolder.h -#ifndef __NETFOLDER_H -#define __NETFOLDER_H +#ifndef __NET_FOLDER_H +#define __NET_FOLDER_H -#include "Common/MyString.h" -#include "Common/Buffer.h" #include "Common/MyCom.h" -#include "Windows/PropVariant.h" + #include "Windows/Net.h" #include "IFolder.h" @@ -21,16 +19,6 @@ class CNetFolder: public IFolderGetSystemIconIndex, public CMyUnknownImp { -public: - MY_UNKNOWN_IMP1( - IFolderGetSystemIconIndex - ) - - INTERFACE_FolderFolder(;) - - STDMETHOD(GetSystemIconIndex)(UInt32 index, INT32 *iconIndex); - -private: NWindows::NNet::CResourceW _netResource; NWindows::NNet::CResourceW *_netResourcePointer; @@ -38,12 +26,15 @@ private: CMyComPtr<IFolderFolder> _parentFolder; UString _path; - public: + MY_UNKNOWN_IMP1(IFolderGetSystemIconIndex) + INTERFACE_FolderFolder(;) + STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex); + + CNetFolder(): _netResourcePointer(0) {} void Init(const UString &path); void Init(const NWindows::NNet::CResourceW *netResource, IFolderFolder *parentFolder, const UString &path); - CNetFolder(): _netResourcePointer(0) {} }; #endif diff --git a/CPP/7zip/UI/FileManager/OpenCallback.cpp b/CPP/7zip/UI/FileManager/OpenCallback.cpp index 9c71a291..a275f89b 100755 --- a/CPP/7zip/UI/FileManager/OpenCallback.cpp +++ b/CPP/7zip/UI/FileManager/OpenCallback.cpp @@ -2,50 +2,48 @@ #include "StdAfx.h" -#include "OpenCallback.h" - #include "Common/StringConvert.h" + #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" +#include "OpenCallback.h" #include "PasswordDialog.h" +using namespace NWindows; + STDMETHODIMP COpenArchiveCallback::SetTotal(const UInt64 *numFiles, const UInt64 *numBytes) { + RINOK(ProgressDialog.ProgressSynch.ProcessStopAndPause()); { - NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); - _numFilesTotalDefined = (numFiles != NULL); - _numBytesTotalDefined = (numBytes != NULL); - if (_numFilesTotalDefined) + NSynchronization::CCriticalSectionLock lock(_criticalSection); + if (numFiles != NULL) { ProgressDialog.ProgressSynch.SetNumFilesTotal(*numFiles); - ProgressDialog.ProgressSynch.SetProgress(*numFiles, 0); + ProgressDialog.ProgressSynch.SetBytesProgressMode(false); } - else if (_numBytesTotalDefined) - ProgressDialog.ProgressSynch.SetProgress(*numBytes, 0); + if (numBytes != NULL) + ProgressDialog.ProgressSynch.SetNumBytesTotal(*numBytes); } return S_OK; } STDMETHODIMP COpenArchiveCallback::SetCompleted(const UInt64 *numFiles, const UInt64 *numBytes) { - NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); RINOK(ProgressDialog.ProgressSynch.ProcessStopAndPause()); + NSynchronization::CCriticalSectionLock lock(_criticalSection); if (numFiles != NULL) - { ProgressDialog.ProgressSynch.SetNumFilesCur(*numFiles); - if (_numFilesTotalDefined) - ProgressDialog.ProgressSynch.SetPos(*numFiles); - } - if (numBytes != NULL && _numBytesTotalDefined) + if (numBytes != NULL) ProgressDialog.ProgressSynch.SetPos(*numBytes); return S_OK; } STDMETHODIMP COpenArchiveCallback::SetTotal(const UInt64 total) { - ProgressDialog.ProgressSynch.SetProgress(total, 0); + RINOK(ProgressDialog.ProgressSynch.ProcessStopAndPause()); + ProgressDialog.ProgressSynch.SetNumBytesTotal(total); return S_OK; } @@ -59,7 +57,7 @@ STDMETHODIMP COpenArchiveCallback::SetCompleted(const UInt64 *completed) STDMETHODIMP COpenArchiveCallback::GetProperty(PROPID propID, PROPVARIANT *value) { - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; if (_subArchiveMode) { switch(propID) @@ -91,10 +89,10 @@ STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, if (_subArchiveMode) return S_FALSE; - NWindows::NFile::NFind::CFileInfoW fileInfo; + NFile::NFind::CFileInfoW fileInfo; UString fullPath = _folderPrefix + name; - if (!NWindows::NFile::NFind::FindFile(fullPath, fileInfo)) + if (!fileInfo.Find(fullPath)) return S_FALSE; _fileInfo = fileInfo; if (_fileInfo.IsDir()) diff --git a/CPP/7zip/UI/FileManager/OpenCallback.h b/CPP/7zip/UI/FileManager/OpenCallback.h index 168f171b..5f0fbefc 100755 --- a/CPP/7zip/UI/FileManager/OpenCallback.h +++ b/CPP/7zip/UI/FileManager/OpenCallback.h @@ -3,15 +3,15 @@ #ifndef __OPENCALLBACK_H #define __OPENCALLBACK_H -#include "Common/MyString.h" #include "Common/MyCom.h" +#include "Common/MyString.h" + #include "Windows/FileFind.h" #include "../../IPassword.h" #include "../../Archive/IArchive.h" - #ifdef _SFX #include "ProgressDialog.h" #else @@ -29,21 +29,15 @@ class COpenArchiveCallback: { UString _folderPrefix; NWindows::NFile::NFind::CFileInfoW _fileInfo; - - bool _numFilesTotalDefined; - bool _numBytesTotalDefined; NWindows::NSynchronization::CCriticalSection _criticalSection; + bool _subArchiveMode; + UString _subArchiveName; public: bool PasswordIsDefined; - UString Password; bool PasswordWasAsked; + UString Password; HWND ParentWindow; - - bool _subArchiveMode; - UString _subArchiveName; - -public: CProgressDialog ProgressDialog; MY_UNKNOWN_IMP5( @@ -70,9 +64,6 @@ public: COpenArchiveCallback(): ParentWindow(0) { - _numFilesTotalDefined = false; - _numBytesTotalDefined = false; - _subArchiveMode = false; PasswordIsDefined = false; PasswordWasAsked = false; @@ -87,7 +78,7 @@ public: void LoadFileInfo(const UString &folderPrefix, const UString &fileName) { _folderPrefix = folderPrefix; - if (!NWindows::NFile::NFind::FindFile(_folderPrefix + fileName, _fileInfo)) + if (!_fileInfo.Find(_folderPrefix + fileName)) throw 1; } void ShowMessage(const UInt64 *completed); @@ -96,7 +87,6 @@ public: { return ProgressDialog.Create(title, ParentWindow); } - }; #endif diff --git a/CPP/7zip/UI/FileManager/Panel.cpp b/CPP/7zip/UI/FileManager/Panel.cpp index 40192c5f..9255b117 100755 --- a/CPP/7zip/UI/FileManager/Panel.cpp +++ b/CPP/7zip/UI/FileManager/Panel.cpp @@ -5,28 +5,30 @@ #include <Windowsx.h> #include "Common/Defs.h" -#include "Common/StringConvert.h" #include "Common/IntToString.h" +#include "Common/StringConvert.h" + #include "Windows/Error.h" #include "Windows/PropVariant.h" #include "Windows/Thread.h" #include "../../PropID.h" -#include "Panel.h" -#include "RootFolder.h" -#include "FSFolder.h" -#include "FormatUtils.h" -#include "App.h" -#include "ExtractCallback.h" - #include "resource.h" -#include "..\GUI\ExtractRes.h" +#include "../GUI/ExtractRes.h" + +#include "../Common/ArchiveName.h" +#include "../Common/CompressCall.h" #include "../Agent/IFolderArchive.h" -#include "../Common/CompressCall.h" -#include "../Common/ArchiveName.h" +#include "App.h" +#include "ExtractCallback.h" +#include "FSFolder.h" +#include "FormatUtils.h" +#include "Panel.h" +#include "RootFolder.h" + using namespace NWindows; using namespace NControl; @@ -707,7 +709,7 @@ bool CPanel::IsFSDrivesFolder() const UString CPanel::GetFsPath() const { - if (IsFSDrivesFolder()) + if (IsFSDrivesFolder() && !IsDeviceDrivesPrefix()) return UString(); return _currentFolderPrefix; } @@ -773,7 +775,7 @@ void CPanel::AddToArchive() { CRecordVector<UInt32> indices; GetOperatedItemIndices(indices); - if (!IsFSFolder()) + if (!IsFsOrDrivesFolder()) { MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); return; @@ -784,14 +786,25 @@ void CPanel::AddToArchive() return; } UStringVector names; + + UString curPrefix = _currentFolderPrefix; + UString destCurDirPrefix = _currentFolderPrefix; + if (IsFSDrivesFolder()) + { + destCurDirPrefix = L"C:\\"; + if (!IsDeviceDrivesPrefix()) + curPrefix.Empty(); + } + for (int i = 0; i < indices.Size(); i++) { int index = indices[i]; - names.Add(_currentFolderPrefix + GetItemRelPath(index)); + names.Add(curPrefix + GetItemRelPath(index)); } const UString archiveName = CreateArchiveName( names.Front(), (names.Size() > 1), false); - HRESULT res = CompressFiles(_currentFolderPrefix, archiveName, L"", names, false, true, false); + + HRESULT res = CompressFiles(destCurDirPrefix, archiveName, L"", names, false, true, false); if (res != S_OK) { if (_currentFolderPrefix.Length() >= MAX_PATH) @@ -823,7 +836,7 @@ void CPanel::GetFilePaths(const CRecordVector<UInt32> &indices, UStringVector &p paths.Clear(); break; } - paths.Add(_currentFolderPrefix + GetItemRelPath(index)); + paths.Add(GetItemFullPath(index)); } if (paths.Size() == 0) { diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h index 4ba36a71..ed157634 100755 --- a/CPP/7zip/UI/FileManager/Panel.h +++ b/CPP/7zip/UI/FileManager/Panel.h @@ -6,25 +6,24 @@ #include "Common/MyCom.h" #include "Windows/DLL.h" -#include "Windows/FileFind.h" #include "Windows/FileDir.h" -#include "Windows/Synchronization.h" +#include "Windows/FileFind.h" #include "Windows/Handle.h" +#include "Windows/Synchronization.h" -#include "Windows/Control/ToolBar.h" -#include "Windows/Control/ReBar.h" +#include "Windows/Control/ComboBox.h" +#include "Windows/Control/Edit.h" #include "Windows/Control/ListView.h" +#include "Windows/Control/ReBar.h" #include "Windows/Control/Static.h" -#include "Windows/Control/Edit.h" -#include "Windows/Control/ComboBox.h" -#include "Windows/Control/Window2.h" #include "Windows/Control/StatusBar.h" +#include "Windows/Control/ToolBar.h" +#include "Windows/Control/Window2.h" -#include "SysIconUtils.h" -#include "IFolder.h" -#include "ViewSettings.h" #include "AppState.h" +#include "IFolder.h" #include "MyCom2.h" +#include "SysIconUtils.h" const int kParentFolderID = 100; const int kPluginMenuStartID = 1000; @@ -81,10 +80,21 @@ struct CTempFileInfo UString FolderPath; UString FilePath; NWindows::NFile::NFind::CFileInfoW FileInfo; - void DeleteDirAndFile() + bool NeedDelete; + + CTempFileInfo(): NeedDelete(false) {} + void DeleteDirAndFile() const { - NWindows::NFile::NDirectory::DeleteFileAlways(FilePath); - NWindows::NFile::NDirectory::MyRemoveDirectory(FolderPath); + if (NeedDelete) + { + NWindows::NFile::NDirectory::DeleteFileAlways(FilePath); + NWindows::NFile::NDirectory::MyRemoveDirectory(FolderPath); + } + } + bool WasChanged(const NWindows::NFile::NFind::CFileInfoW &newFileInfo) const + { + return newFileInfo.Size != FileInfo.Size || + CompareFileTime(&newFileInfo.MTime, &FileInfo.MTime) != 0; } }; @@ -94,9 +104,16 @@ struct CFolderLink: public CTempFileInfo CMyComPtr<IFolderFolder> ParentFolder; bool UsePassword; UString Password; + bool IsVirtual; UString VirtualPath; - CFolderLink(): UsePassword(false) {} + CFolderLink(): UsePassword(false), IsVirtual(false) {} + + bool WasChanged(const NWindows::NFile::NFind::CFileInfoW &newFileInfo) const + { + return IsVirtual || CTempFileInfo::WasChanged(newFileInfo); + } + }; enum MyMessages @@ -294,6 +311,7 @@ public: UString GetItemName(int itemIndex) const; UString GetItemPrefix(int itemIndex) const; UString GetItemRelPath(int itemIndex) const; + UString GetItemFullPath(int itemIndex) const; bool IsItemFolder(int itemIndex) const; UInt64 GetItemSize(int itemIndex) const; @@ -419,6 +437,9 @@ public: bool IsRootFolder() const; bool IsFSFolder() const; bool IsFSDrivesFolder() const; + bool IsFsOrDrivesFolder() const { return IsFSFolder() || IsFSDrivesFolder(); } + bool IsDeviceDrivesPrefix() const { return _currentFolderPrefix == L"\\\\.\\"; } + bool IsFsOrPureDrivesFolder() const { return IsFSFolder() || (IsFSDrivesFolder() && !IsDeviceDrivesPrefix()); } UString GetFsPath() const; UString GetDriveOrNetworkPrefix() const; @@ -482,12 +503,11 @@ public: void OpenFolder(int index); HRESULT OpenParentArchiveFolder(); - HRESULT OpenItemAsArchive(const UString &name, - const UString &folderPath, - const UString &filePath, + HRESULT OpenItemAsArchive(IInStream *inStream, + const CTempFileInfo &tempFileInfo, const UString &virtualFilePath, bool &encrypted); - HRESULT OpenItemAsArchive(const UString &name); + HRESULT OpenItemAsArchive(const UString &name, bool &encrypted); HRESULT OpenItemAsArchive(int index); void OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bool editMode); diff --git a/CPP/7zip/UI/FileManager/PanelCrc.cpp b/CPP/7zip/UI/FileManager/PanelCrc.cpp index 61a84050..aaa645cf 100755 --- a/CPP/7zip/UI/FileManager/PanelCrc.cpp +++ b/CPP/7zip/UI/FileManager/PanelCrc.cpp @@ -2,15 +2,11 @@ #include "StdAfx.h" -extern "C" -{ - #include "../../../../C/Alloc.h" - #include "../../../../C/7zCrc.h" - #include "../../../../C/Sha256.h" -} +#include "../../../../C/7zCrc.h" +#include "../../../../C/Alloc.h" +#include "../../../../C/Sha256.h" #include "Common/IntToString.h" -#include "Common/StringConvert.h" #include "Windows/Error.h" #include "Windows/FileFind.h" @@ -25,6 +21,8 @@ extern "C" #include "FormatUtils.h" #include "LangUtils.h" +#include "../Common/PropIDUtils.h" + #include "resource.h" using namespace NWindows; @@ -69,7 +67,18 @@ bool CDirEnumerator::GetNextFile(NFind::CFileInfoW &fileInfo, bool &filled, UStr resPath.Empty(); if (pos >= 0) resPath = path.Left(pos + 1); - if (!NFind::FindFile(BasePrefix + path, fileInfo)) + + #ifdef _WIN32 + // it's for "c:" paths/ + if (BasePrefix.IsEmpty() && path.Length() == 2 && path[1] == ':') + { + fileInfo.Name = path; + fileInfo.Attrib = FILE_ATTRIBUTE_DIRECTORY; + fileInfo.Size = 0; + } + else + #endif + if (!fileInfo.Find(BasePrefix + path)) { errorCode = ::GetLastError(); resPath = path; @@ -285,21 +294,11 @@ static void ConvertByteToHex(unsigned value, wchar_t *s) } } -static void ConvertUInt32ToHex(UInt32 value, wchar_t *s) -{ - for (int i = 6; i >= 0; i -= 2) - { - ConvertByteToHex(value & 0xFF, s + i); - value >>= 8; - } - s[8] = L'\0'; -} - void CApp::CalculateCrc() { int srcPanelIndex = GetFocusedPanelIndex(); CPanel &srcPanel = Panels[srcPanelIndex]; - if (!srcPanel.IsFSFolder()) + if (!srcPanel.IsFsOrDrivesFolder()) { srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); return; @@ -312,7 +311,7 @@ void CApp::CalculateCrc() CThreadCrc combiner; for (int i = 0; i < indices.Size(); i++) combiner.DirEnumerator.FileNames.Add(srcPanel.GetItemRelPath(indices[i])); - combiner.DirEnumerator.BasePrefix = srcPanel._currentFolderPrefix; + combiner.DirEnumerator.BasePrefix = srcPanel.GetFsPath(); combiner.DirEnumerator.FlatMode = GetFlatMode(); { diff --git a/CPP/7zip/UI/FileManager/PanelDrag.cpp b/CPP/7zip/UI/FileManager/PanelDrag.cpp index 6cae36fe..6d1c9a29 100755 --- a/CPP/7zip/UI/FileManager/PanelDrag.cpp +++ b/CPP/7zip/UI/FileManager/PanelDrag.cpp @@ -459,7 +459,7 @@ void CDropTarget::PositionCursor(POINTL ptl) return; */ - if (!m_Panel->IsFSFolder() && !m_Panel->IsFSDrivesFolder()) + if (!m_Panel->IsFsOrPureDrivesFolder()) return; if (WindowFromPoint(pt) != (HWND)m_Panel->_listView) diff --git a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp index 01fec329..e6336f31 100755 --- a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp +++ b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp @@ -4,16 +4,18 @@ #include "Common/StringConvert.h" #include "Common/Wildcard.h" -#include "Windows/FileDir.h" + +#include "Windows/PropVariant.h" #include "../../PropID.h" -#include "Panel.h" +#include "FSDrives.h" +#include "LangUtils.h" #include "ListViewDialog.h" +#include "Panel.h" #include "RootFolder.h" #include "ViewSettings.h" -#include "FSDrives.h" -#include "LangUtils.h" + #include "resource.h" using namespace NWindows; @@ -71,7 +73,7 @@ HRESULT CPanel::BindToPath(const UString &fullPath, bool &archiveIsOpened, bool UStringVector reducedParts; while (!sysPath.IsEmpty()) { - if (FindFile(sysPath, fileInfo)) + if (fileInfo.Find(sysPath)) break; int pos = sysPath.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos < 0) @@ -108,11 +110,7 @@ HRESULT CPanel::BindToPath(const UString &fullPath, bool &archiveIsOpened, bool UString fileName; if (NDirectory::GetOnlyName(sysPath, fileName)) { - HRESULT res = - OpenItemAsArchive(fileName, _currentFolderPrefix, - _currentFolderPrefix + fileName, - _currentFolderPrefix + fileName, - encrypted); + HRESULT res = OpenItemAsArchive(fileName, encrypted); if (res != S_FALSE) { RINOK(res); @@ -210,7 +208,7 @@ void CPanel::LoadFullPathAndShow() CFileInfoW info; DWORD attrib = FILE_ATTRIBUTE_DIRECTORY; - if (NFile::NFind::FindFile(path, info)) + if (info.Find(path)) attrib = info.Attrib; item.iImage = GetRealIconIndex(path, attrib); @@ -343,7 +341,7 @@ bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result) curName += WCHAR_PATH_SEPARATOR; CFileInfoW info; DWORD attrib = FILE_ATTRIBUTE_DIRECTORY; - if (NFile::NFind::FindFile(sumPass, info)) + if (info.Find(sumPass)) attrib = info.Attrib; sumPass += WCHAR_PATH_SEPARATOR; AddComboBoxItem(name, GetRealIconIndex(curName, attrib), i, false); @@ -498,7 +496,7 @@ void CPanel::OpenParentFolder() _folder = link.ParentFolder; _library.Attach(link.Library.Detach()); focucedName = link.ItemName; - if (_parentFolders.Size () > 1) + if (_parentFolders.Size() > 1) OpenParentArchiveFolder(); _parentFolders.DeleteBack(); if (_parentFolders.IsEmpty()) @@ -526,7 +524,7 @@ void CPanel::CloseOpenFolders() _library.Free(); _folder = _parentFolders.Back().ParentFolder; _library.Attach(_parentFolders.Back().Library.Detach()); - if (_parentFolders.Size () > 1) + if (_parentFolders.Size() > 1) OpenParentArchiveFolder(); _parentFolders.DeleteBack(); } diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp index c40b0d18..2aab2aae 100755 --- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp +++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp @@ -2,27 +2,29 @@ #include "StdAfx.h" -#include "resource.h" - -#include "Common/StringConvert.h" -#include "Common/Random.h" -#include "Common/StringConvert.h" #include "Common/AutoPtr.h" +#include "Common/StringConvert.h" +#include "Windows/Error.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" -#include "Windows/Thread.h" #include "Windows/Synchronization.h" -#include "Windows/Error.h" +#include "Windows/Thread.h" #include "ExtractCallback.h" -#include "UpdateCallback100.h" -#include "IFolder.h" #include "FileFolderPluginOpen.h" #include "FormatUtils.h" +#include "IFolder.h" +#include "LangUtils.h" #include "Panel.h" #include "RegistryUtils.h" -#include "LangUtils.h" +#include "UpdateCallback100.h" + +#include "App.h" + +#include "../Common/ExtractingFilePath.h" + +#include "resource.h" using namespace NWindows; using namespace NSynchronization; @@ -66,20 +68,25 @@ public: } }; -HRESULT CPanel::OpenItemAsArchive(const UString &name, - const UString &folderPath, const UString &filePath, +HRESULT CPanel::OpenItemAsArchive(IInStream *inStream, + const CTempFileInfo &tempFileInfo, const UString &virtualFilePath, bool &encrypted) { encrypted = false; CFolderLink folderLink; - if (!NFile::NFind::FindFile(filePath, folderLink.FileInfo)) - return E_FAIL; - if (folderLink.FileInfo.IsDir()) - return S_FALSE; + (CTempFileInfo &)folderLink = tempFileInfo; + if (inStream) + folderLink.IsVirtual = true; + else + { + if (!folderLink.FileInfo.Find(folderLink.FilePath)) + return ::GetLastError(); + if (folderLink.FileInfo.IsDir()) + return S_FALSE; + folderLink.IsVirtual = false; + } - folderLink.FilePath = filePath; - folderLink.FolderPath = folderPath; folderLink.VirtualPath = virtualFilePath; CMyComPtr<IFolderFolder> newFolder; @@ -90,13 +97,14 @@ HRESULT CPanel::OpenItemAsArchive(const UString &name, NDLL::CLibrary library; UString password; - RINOK(OpenFileFolderPlugin(filePath, &library, &newFolder, GetParent(), encrypted, password)); + RINOK(OpenFileFolderPlugin(inStream, + folderLink.FilePath.IsEmpty() ? virtualFilePath : folderLink.FilePath, + &library, &newFolder, GetParent(), encrypted, password)); folderLink.Password = password; folderLink.UsePassword = encrypted; folderLink.ParentFolder = _folder; - folderLink.ItemName = name; _parentFolders.Add(folderLink); _parentFolders.Back().Library.Attach(_library.Detach()); @@ -110,19 +118,20 @@ HRESULT CPanel::OpenItemAsArchive(const UString &name, return S_OK; } -HRESULT CPanel::OpenItemAsArchive(const UString &name) +HRESULT CPanel::OpenItemAsArchive(const UString &name, bool &encrypted) { - bool encrypted; - return OpenItemAsArchive(name, _currentFolderPrefix, - _currentFolderPrefix + name, - _currentFolderPrefix + name, - encrypted); + CTempFileInfo tfi; + tfi.ItemName = name; + tfi.FolderPath = _currentFolderPrefix; + tfi.FilePath = _currentFolderPrefix + name; + return OpenItemAsArchive(NULL, tfi, _currentFolderPrefix + name, encrypted); } HRESULT CPanel::OpenItemAsArchive(int index) { CDisableTimerProcessing disableTimerProcessing1(*this); - RINOK(OpenItemAsArchive(GetItemRelPath(index))); + bool encrypted; + RINOK(OpenItemAsArchive(GetItemRelPath(index), encrypted)); RefreshListCtrl(); return S_OK; } @@ -132,12 +141,11 @@ HRESULT CPanel::OpenParentArchiveFolder() CDisableTimerProcessing disableTimerProcessing1(*this); if (_parentFolders.Size() < 2) return S_OK; - CFolderLink &folderLink = _parentFolders.Back(); + const CFolderLink &folderLink = _parentFolders.Back(); NFind::CFileInfoW newFileInfo; - if (NFind::FindFile(folderLink.FilePath, newFileInfo)) + if (newFileInfo.Find(folderLink.FilePath)) { - if (newFileInfo.Size != folderLink.FileInfo.Size || - CompareFileTime(&newFileInfo.MTime, &folderLink.FileInfo.MTime) != 0) + if (folderLink.WasChanged(newFileInfo)) { UString message = MyFormatNew(IDS_WANT_UPDATE_MODIFIED_FILE, 0x03020280, folderLink.ItemName); @@ -166,7 +174,7 @@ static const wchar_t *kStartExtensions[] = L"docx", L"docm", L"dotx", L"dotm", L"xlsx", L"xlsm", L"xltx", L"xltm", L"xlsb", L"xlam", L"pptx", L"pptm", L"potx", L"potm", L"ppam", L"ppsx", L"ppsm", L"xsn", - L"dwf", + L"dwf", L"odt", L"ods", L"wb3", @@ -186,22 +194,8 @@ static bool DoItemAlwaysStart(const UString &name) return false; } -static HANDLE StartEditApplication(const UString &path, HWND window) +static HRESULT MyCreateProcess(const UString &command, HANDLE *hProcess) { - UString command; - ReadRegEditor(command); - if (command.IsEmpty()) - { - if (!MyGetWindowsDirectory(command)) - return 0; - NFile::NName::NormalizeDirPathPrefix(command); - command += L"notepad.exe"; - } - command = UString(L"\"") + command + UString(L"\""); - command += L" \""; - command += UString(path); - command += L"\""; - PROCESS_INFORMATION processInformation; BOOL result; #ifndef _UNICODE @@ -235,16 +229,96 @@ static HANDLE StartEditApplication(const UString &path, HWND window) NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInformation); } - if (result != FALSE) + if (result == 0) + return ::GetLastError(); + + ::CloseHandle(processInformation.hThread); + *hProcess = processInformation.hProcess; + return S_OK; +} + +static HRESULT MyCreateProcess(const UString &command) +{ + HANDLE hProcess; + HRESULT res = MyCreateProcess(command, &hProcess); + if (res == SZ_OK) + ::CloseHandle(hProcess); + return res; +} + +static HANDLE StartEditApplication(const UString &path, HWND window) +{ + UString command; + ReadRegEditor(command); + if (command.IsEmpty()) { - ::CloseHandle(processInformation.hThread); - return processInformation.hProcess; + if (!MyGetWindowsDirectory(command)) + return 0; + NFile::NName::NormalizeDirPathPrefix(command); + command += L"notepad.exe"; } + command = UString(L"\"") + command + UString(L"\""); + command += L" \""; + command += path; + command += L"\""; + + HANDLE hProcess; + HRESULT res = MyCreateProcess(command, &hProcess); + if (res == SZ_OK) + return hProcess; ::MessageBoxW(window, LangString(IDS_CANNOT_START_EDITOR, 0x03020282), L"7-Zip", MB_OK | MB_ICONSTOP); return 0; } +void CApp::DiffFiles() +{ + const CPanel &panel = GetFocusedPanel(); + + CRecordVector<UInt32> indices; + panel.GetSelectedItemsIndices(indices); + + UString path1, path2; + if (indices.Size() == 2) + { + path1 = panel.GetItemFullPath(indices[0]); + path2 = panel.GetItemFullPath(indices[1]); + } + else if (indices.Size() == 1 && NumPanels >= 2) + { + const CPanel &destPanel = Panels[1 - LastFocusedPanel]; + path1 = panel.GetItemFullPath(indices[0]); + const UString relPath = panel.GetItemRelPath(indices[0]); + CRecordVector<UInt32> indices2; + destPanel.GetSelectedItemsIndices(indices2); + if (indices2.Size() == 1) + path2 = destPanel.GetItemFullPath(indices2[0]); + else + path2 = destPanel._currentFolderPrefix + relPath; + } + else + return; + + UString command; + ReadRegDiff(command); + if (command.IsEmpty()) + return; + + command = UString(L"\"") + command + UString(L"\""); + command += L" \""; + command += path1; + command += L"\""; + + command += L" \""; + command += path2; + command += L"\""; + + HRESULT res = MyCreateProcess(command); + if (res == SZ_OK) + return; + ::MessageBoxW(_window, LangString(IDS_CANNOT_START_EDITOR, 0x03020282), L"7-Zip", MB_OK | MB_ICONSTOP); +} + #ifndef _UNICODE typedef BOOL (WINAPI * ShellExecuteExWP)(LPSHELLEXECUTEINFOW lpExecInfo); #endif @@ -314,14 +388,16 @@ void CPanel::EditItem(int index) OpenItemInArchive(index, false, true, true); return; } - HANDLE hProcess = StartEditApplication(_currentFolderPrefix + GetItemRelPath(index), (HWND)*this); + HANDLE hProcess = StartEditApplication(GetItemFullPath(index), (HWND)*this); if (hProcess != 0) ::CloseHandle(hProcess); } void CPanel::OpenFolderExternal(int index) { - HANDLE hProcess = StartApplication(GetFsPath(), GetFsPath() + GetItemRelPath(index), (HWND)*this); + UString fsPrefix = GetFsPath(); + HANDLE hProcess = StartApplication(fsPrefix, + fsPrefix + GetItemRelPath(index) + WCHAR_PATH_SEPARATOR, (HWND)*this); if (hProcess != 0) ::CloseHandle(hProcess); } @@ -428,7 +504,7 @@ public: static THREAD_FUNC_DECL MyThreadFunction(void *param) { CMyAutoPtr<CTmpProcessInfo> tmpProcessInfoPtr((CTmpProcessInfo *)param); - CTmpProcessInfo *tmpProcessInfo = tmpProcessInfoPtr.get(); + const CTmpProcessInfo *tmpProcessInfo = tmpProcessInfoPtr.get(); HANDLE hProcess = tmpProcessInfo->ProcessHandle; HANDLE events[2] = { g_ExitEventLauncher._exitEvent, hProcess}; @@ -440,10 +516,9 @@ static THREAD_FUNC_DECL MyThreadFunction(void *param) return 1; Sleep(200); NFind::CFileInfoW newFileInfo; - if (NFind::FindFile(tmpProcessInfo->FilePath, newFileInfo)) + if (newFileInfo.Find(tmpProcessInfo->FilePath)) { - if (newFileInfo.Size != tmpProcessInfo->FileInfo.Size || - CompareFileTime(&newFileInfo.MTime, &tmpProcessInfo->FileInfo.MTime) != 0) + if (tmpProcessInfo->WasChanged(newFileInfo)) { UString message = MyFormatNew(IDS_WANT_UPDATE_MODIFIED_FILE, 0x03020280, tmpProcessInfo->ItemName); @@ -478,12 +553,51 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo return; } + bool tryAsArchive = tryInternal && (!tryExternal || !DoItemAlwaysStart(name)); + + UString fullVirtPath = _currentFolderPrefix + name; + NFile::NDirectory::CTempDirectoryW tempDirectory; tempDirectory.Create(kTempDirPrefix); UString tempDir = tempDirectory.GetPath(); UString tempDirNorm = tempDir; NFile::NName::NormalizeDirPathPrefix(tempDirNorm); + UString tempFilePath = tempDirNorm + GetCorrectFsPath(name); + + CTempFileInfo tempFileInfo; + tempFileInfo.ItemName = name; + tempFileInfo.FolderPath = tempDir; + tempFileInfo.FilePath = tempFilePath; + tempFileInfo.NeedDelete = true; + + if (tryAsArchive) + { + CMyComPtr<IInArchiveGetStream> getStream; + _folder.QueryInterface(IID_IInArchiveGetStream, &getStream); + if (getStream) + { + CMyComPtr<ISequentialInStream> subSeqStream; + getStream->GetStream(index, &subSeqStream); + if (subSeqStream) + { + CMyComPtr<IInStream> subStream; + subSeqStream.QueryInterface(IID_IInStream, &subStream); + if (subStream) + { + bool encrypted; + if (OpenItemAsArchive(subStream, tempFileInfo, fullVirtPath, encrypted) == S_OK) + { + tempDirectory.DisableDeleting(); + RefreshListCtrl(); + return; + } + } + } + } + } + + CRecordVector<UInt32> indices; indices.Add(index); @@ -516,32 +630,29 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo return; } - UString tempFilePath = tempDirNorm + name; + + if (tryAsArchive) + { + bool encrypted; + if (OpenItemAsArchive(NULL, tempFileInfo, fullVirtPath, encrypted) == S_OK) + { + tempDirectory.DisableDeleting(); + RefreshListCtrl(); + return; + } + } CMyAutoPtr<CTmpProcessInfo> tmpProcessInfoPtr(new CTmpProcessInfo()); CTmpProcessInfo *tmpProcessInfo = tmpProcessInfoPtr.get(); tmpProcessInfo->FolderPath = tempDir; tmpProcessInfo->FilePath = tempFilePath; + tmpProcessInfo->NeedDelete = true; tmpProcessInfo->UsePassword = usePassword; tmpProcessInfo->Password = password; - if (!NFind::FindFile(tempFilePath, tmpProcessInfo->FileInfo)) + if (!tmpProcessInfo->FileInfo.Find(tempFilePath)) return; - if (tryInternal) - { - if (!tryExternal || !DoItemAlwaysStart(name)) - { - bool encrypted; - if (OpenItemAsArchive(name, tempDir, tempFilePath, - _currentFolderPrefix + name, encrypted) == S_OK) - { - RefreshListCtrl(); - return; - } - } - } - CTmpProcessInfoRelease tmpProcessInfoRelease(*tmpProcessInfo); if (!tryExternal) diff --git a/CPP/7zip/UI/FileManager/PanelItems.cpp b/CPP/7zip/UI/FileManager/PanelItems.cpp index 58e14759..7ea9585a 100755 --- a/CPP/7zip/UI/FileManager/PanelItems.cpp +++ b/CPP/7zip/UI/FileManager/PanelItems.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../../../C/Sort.h" + #include "Common/StringConvert.h" #include "Windows/Menu.h" @@ -17,11 +19,6 @@ #include "PropertyName.h" #include "RootFolder.h" -extern "C" -{ - #include "../../../../C/Sort.h" -} - using namespace NWindows; static int GetColumnAlign(PROPID propID, VARTYPE varType) @@ -137,9 +134,9 @@ void CPanel::InitColumns() _visibleProperties.Clear(); for (i = 0; i < _properties.Size(); i++) { - const CItemProperty &property = _properties[i]; - if (property.IsVisible) - _visibleProperties.Add(property); + const CItemProperty &prop = _properties[i]; + if (prop.IsVisible) + _visibleProperties.Add(prop); } // _sortIndex = 0; @@ -162,14 +159,14 @@ void CPanel::InitColumns() void CPanel::InsertColumn(int index) { - const CItemProperty &property = _visibleProperties[index]; + const CItemProperty &prop = _visibleProperties[index]; LV_COLUMNW column; column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_ORDER; - column.cx = property.Width; - column.fmt = GetColumnAlign(property.ID, property.Type); - column.iOrder = property.Order; + column.cx = prop.Width; + column.fmt = GetColumnAlign(prop.ID, prop.Type); + column.iOrder = prop.Order; column.iSubItem = index; - column.pszText = (wchar_t *)(const wchar_t *)property.Name; + column.pszText = (wchar_t *)(const wchar_t *)prop.Name; _listView.InsertColumn(index, &column); } @@ -344,8 +341,8 @@ void CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool se item.iSubItem = subItem++; item.lParam = kParentIndex; item.pszText = (wchar_t *)(const wchar_t *)itemName; - UInt32 attributes = FILE_ATTRIBUTE_DIRECTORY; - item.iImage = _extToIconMap.GetIconIndex(attributes, itemName); + UInt32 attrib = FILE_ATTRIBUTE_DIRECTORY; + item.iImage = _extToIconMap.GetIconIndex(attrib, itemName); if (item.iImage < 0) item.iImage = 0; if(_listView.InsertItem(&item) == -1) @@ -402,16 +399,13 @@ void CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool se else item.pszText = (wchar_t *)(const wchar_t *)itemName; - NCOM::CPropVariant propVariant; - _folder->GetProperty(i, kpidAttrib, &propVariant); - UInt32 attributes = 0; - if (propVariant.vt == VT_UI4) - attributes = propVariant.ulVal; - else - { - if (IsItemFolder(i)) - attributes |= FILE_ATTRIBUTE_DIRECTORY; - } + NCOM::CPropVariant prop; + _folder->GetProperty(i, kpidAttrib, &prop); + UInt32 attrib = 0; + if (prop.vt == VT_UI4) + attrib = prop.ulVal; + else if (IsItemFolder(i)) + attrib |= FILE_ATTRIBUTE_DIRECTORY; bool defined = false; @@ -425,12 +419,12 @@ void CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool se if (_currentFolderPrefix.IsEmpty()) { int iconIndexTemp; - GetRealIconIndex(itemName + WCHAR_PATH_SEPARATOR, attributes, iconIndexTemp); + GetRealIconIndex(itemName + WCHAR_PATH_SEPARATOR, attrib, iconIndexTemp); item.iImage = iconIndexTemp; } else { - item.iImage = _extToIconMap.GetIconIndex(attributes, itemName); + item.iImage = _extToIconMap.GetIconIndex(attrib, itemName); } } if (item.iImage < 0) @@ -572,7 +566,7 @@ void CPanel::OpenSelectedItems(bool tryInternal) if (focusedItem >= 0) { int realIndex = GetRealItemIndex(focusedItem); - if (realIndex == kParentIndex && (tryInternal || indices.Size() == 0) && + if (realIndex == kParentIndex && (tryInternal || indices.Size() == 0) && _listView.GetItemState(focusedItem, LVIS_SELECTED) == LVIS_SELECTED) indices.Insert(0, realIndex); } @@ -605,24 +599,24 @@ UString CPanel::GetItemName(int itemIndex) const { if (itemIndex == kParentIndex) return L".."; - NCOM::CPropVariant propVariant; - if (_folder->GetProperty(itemIndex, kpidName, &propVariant) != S_OK) + NCOM::CPropVariant prop; + if (_folder->GetProperty(itemIndex, kpidName, &prop) != S_OK) throw 2723400; - if (propVariant.vt != VT_BSTR) + if (prop.vt != VT_BSTR) throw 2723401; - return (propVariant.bstrVal); + return prop.bstrVal; } UString CPanel::GetItemPrefix(int itemIndex) const { if (itemIndex == kParentIndex) return UString(); - NCOM::CPropVariant propVariant; - if (_folder->GetProperty(itemIndex, kpidPrefix, &propVariant) != S_OK) + NCOM::CPropVariant prop; + if (_folder->GetProperty(itemIndex, kpidPrefix, &prop) != S_OK) throw 2723400; UString prefix; - if (propVariant.vt == VT_BSTR) - prefix = propVariant.bstrVal; + if (prop.vt == VT_BSTR) + prefix = prop.bstrVal; return prefix; } @@ -631,17 +625,21 @@ UString CPanel::GetItemRelPath(int itemIndex) const return GetItemPrefix(itemIndex) + GetItemName(itemIndex); } +UString CPanel::GetItemFullPath(int itemIndex) const +{ + return _currentFolderPrefix + GetItemRelPath(itemIndex); +} bool CPanel::IsItemFolder(int itemIndex) const { if (itemIndex == kParentIndex) return true; - NCOM::CPropVariant propVariant; - if (_folder->GetProperty(itemIndex, kpidIsDir, &propVariant) != S_OK) + NCOM::CPropVariant prop; + if (_folder->GetProperty(itemIndex, kpidIsDir, &prop) != S_OK) throw 2723400; - if (propVariant.vt == VT_BOOL) - return VARIANT_BOOLToBool(propVariant.boolVal); - if (propVariant.vt == VT_EMPTY) + if (prop.vt == VT_BOOL) + return VARIANT_BOOLToBool(prop.boolVal); + if (prop.vt == VT_EMPTY) return false; return false; } @@ -650,12 +648,12 @@ UINT64 CPanel::GetItemSize(int itemIndex) const { if (itemIndex == kParentIndex) return 0; - NCOM::CPropVariant propVariant; - if (_folder->GetProperty(itemIndex, kpidSize, &propVariant) != S_OK) + NCOM::CPropVariant prop; + if (_folder->GetProperty(itemIndex, kpidSize, &prop) != S_OK) throw 2723400; - if (propVariant.vt == VT_EMPTY) + if (prop.vt == VT_EMPTY) return 0; - return ConvertPropVariantToUInt64(propVariant); + return ConvertPropVariantToUInt64(prop); } void CPanel::ReadListViewInfo() @@ -670,13 +668,13 @@ void CPanel::SaveListViewInfo() int i; for(i = 0; i < _visibleProperties.Size(); i++) { - CItemProperty &property = _visibleProperties[i]; + CItemProperty &prop = _visibleProperties[i]; LVCOLUMN winColumnInfo; winColumnInfo.mask = LVCF_ORDER | LVCF_WIDTH; if (!_listView.GetColumn(i, &winColumnInfo)) throw 1; - property.Order = winColumnInfo.iOrder; - property.Width = winColumnInfo.cx; + prop.Order = winColumnInfo.iOrder; + prop.Width = winColumnInfo.cx; } CListViewInfo viewInfo; @@ -687,22 +685,22 @@ void CPanel::SaveListViewInfo() _visibleProperties.Sort(); for(i = 0; i < _visibleProperties.Size(); i++) { - const CItemProperty &property = _visibleProperties[i]; + const CItemProperty &prop = _visibleProperties[i]; CColumnInfo columnInfo; - columnInfo.IsVisible = property.IsVisible; - columnInfo.PropID = property.ID; - columnInfo.Width = property.Width; + columnInfo.IsVisible = prop.IsVisible; + columnInfo.PropID = prop.ID; + columnInfo.Width = prop.Width; viewInfo.Columns.Add(columnInfo); } for(i = 0; i < _properties.Size(); i++) { - const CItemProperty &property = _properties[i]; - if (!property.IsVisible) + const CItemProperty &prop = _properties[i]; + if (!prop.IsVisible) { CColumnInfo columnInfo; - columnInfo.IsVisible = property.IsVisible; - columnInfo.PropID = property.ID; - columnInfo.Width = property.Width; + columnInfo.IsVisible = prop.IsVisible; + columnInfo.PropID = prop.ID; + columnInfo.Width = prop.Width; viewInfo.Columns.Add(columnInfo); } } @@ -734,32 +732,32 @@ bool CPanel::OnRightClick(LPNMITEMACTIVATE itemActiveate, LRESULT &result) const int kCommandStart = 100; for(int i = 0; i < _properties.Size(); i++) { - const CItemProperty &property = _properties[i]; + const CItemProperty &prop = _properties[i]; UINT flags = MF_STRING; - if (property.IsVisible) + if (prop.IsVisible) flags |= MF_CHECKED; if (i == 0) flags |= MF_GRAYED; - menu.AppendItem(flags, kCommandStart + i, GetSystemString(property.Name)); + menu.AppendItem(flags, kCommandStart + i, prop.Name); } int menuResult = menu.Track(TPM_LEFTALIGN | TPM_RETURNCMD | TPM_NONOTIFY, point.x, point.y, _listView); if (menuResult >= kCommandStart && menuResult <= kCommandStart + _properties.Size()) { int index = menuResult - kCommandStart; - CItemProperty &property = _properties[index]; - property.IsVisible = !property.IsVisible; + CItemProperty &prop = _properties[index]; + prop.IsVisible = !prop.IsVisible; - if (property.IsVisible) + if (prop.IsVisible) { int prevVisibleSize = _visibleProperties.Size(); - property.Order = prevVisibleSize; - _visibleProperties.Add(property); + prop.Order = prevVisibleSize; + _visibleProperties.Add(prop); InsertColumn(prevVisibleSize); } else { - int visibleIndex = _visibleProperties.FindItemWithID(property.ID); + int visibleIndex = _visibleProperties.FindItemWithID(prop.ID); _visibleProperties.Delete(visibleIndex); /* if (_sortIndex == index) @@ -768,7 +766,7 @@ bool CPanel::OnRightClick(LPNMITEMACTIVATE itemActiveate, LRESULT &result) _ascending = true; } */ - if (_sortID == property.ID) + if (_sortID == prop.ID) { _sortID = kpidName; _ascending = true; @@ -794,11 +792,10 @@ void CPanel::OnTimer() CMyComPtr<IFolderWasChanged> folderWasChanged; if (_folder.QueryInterface(IID_IFolderWasChanged, &folderWasChanged) != S_OK) return; - INT32 wasChanged; + Int32 wasChanged; if (folderWasChanged->WasChanged(&wasChanged) != S_OK) return; if (wasChanged == 0) return; OnReload(); } - diff --git a/CPP/7zip/UI/FileManager/PanelListNotify.cpp b/CPP/7zip/UI/FileManager/PanelListNotify.cpp index 21600a68..aee4759e 100755 --- a/CPP/7zip/UI/FileManager/PanelListNotify.cpp +++ b/CPP/7zip/UI/FileManager/PanelListNotify.cpp @@ -18,6 +18,7 @@ using namespace NWindows; +/* static UString ConvertSizeToStringShort(UInt64 value) { wchar_t s[32]; @@ -50,6 +51,7 @@ static UString ConvertSizeToStringShort(UInt64 value) s[p++] = L'\0'; return s; } +*/ UString ConvertSizeToString(UInt64 value) { @@ -116,7 +118,7 @@ LRESULT CPanel::SetItemText(LVITEMW &item) /* { NCOM::CPropVariant property; - if(propID == kpidType) + if (propID == kpidType) string = GetFileType(index); else { @@ -150,13 +152,18 @@ LRESULT CPanel::SetItemText(LVITEMW &item) if (_folder->GetProperty(realIndex, propID, &prop) != S_OK) throw 2723407; - if ((propID == kpidSize || propID == kpidPackSize || propID == kpidClusterSize || - propID == kpidNumSubDirs || propID == kpidNumSubFiles) && - (prop.vt == VT_UI8 || prop.vt == VT_UI4)) + if ((prop.vt == VT_UI8 || prop.vt == VT_UI4) && ( + propID == kpidSize || + propID == kpidPackSize || + propID == kpidNumSubDirs || + propID == kpidNumSubFiles || + propID == kpidPosition || + propID == kpidNumBlocks || + propID == kpidClusterSize || + propID == kpidTotalSize || + propID == kpidFreeSpace + )) s = ConvertSizeToString(ConvertPropVariantToUInt64(prop)); - else if ((propID == kpidTotalSize || propID == kpidFreeSpace) && - (prop.vt == VT_UI8 || prop.vt == VT_UI4)) - s = ConvertSizeToStringShort(ConvertPropVariantToUInt64(prop)); else { s = ConvertPropertyToString(prop, propID, false); @@ -164,9 +171,9 @@ LRESULT CPanel::SetItemText(LVITEMW &item) s.Replace(wchar_t(0xD), L' '); } int size = item.cchTextMax; - if(size > 0) + if (size > 0) { - if(s.Length() + 1 > size) + if (s.Length() + 1 > size) s = s.Left(size - 1); MyStringCopy(item.pszText, (const wchar_t *)s); } @@ -183,7 +190,7 @@ void CPanel::OnItemChanged(NMLISTVIEW *item) bool oldSelected = (item->uOldState & LVIS_SELECTED) != 0; bool newSelected = (item->uNewState & LVIS_SELECTED) != 0; // Don't change this code. It works only with such check - if(oldSelected != newSelected) + if (oldSelected != newSelected) _selectedStatusVector[index] = newSelected; } @@ -218,7 +225,7 @@ bool CPanel::OnNotifyList(LPNMHDR header, LRESULT &result) //is the sub-item information being requested? - if((dispInfo->item.mask & LVIF_TEXT) != 0 || + if ((dispInfo->item.mask & LVIF_TEXT) != 0 || (dispInfo->item.mask & LVIF_IMAGE) != 0) SetItemText(dispInfo->item); return false; @@ -290,8 +297,8 @@ bool CPanel::OnNotifyList(LPNMHDR header, LRESULT &result) // we need SetFocusToList, if we drag-select items from other panel. SetFocusToList(); RefreshStatusBar(); - if(_mySelectMode) - if(g_ComCtl32Version >= MAKELONG(71, 4)) + if (_mySelectMode) + if (g_ComCtl32Version >= MAKELONG(71, 4)) OnLeftClick((LPNMITEMACTIVATE)header); return false; } diff --git a/CPP/7zip/UI/FileManager/PanelMenu.cpp b/CPP/7zip/UI/FileManager/PanelMenu.cpp index ab48bbc7..2672f694 100755 --- a/CPP/7zip/UI/FileManager/PanelMenu.cpp +++ b/CPP/7zip/UI/FileManager/PanelMenu.cpp @@ -1,21 +1,23 @@ #include "StdAfx.h" #include "Common/StringConvert.h" -#include "Windows/Menu.h" + #include "Windows/COM.h" -#include "Windows/PropVariant.h" #include "Windows/Clipboard.h" +#include "Windows/Menu.h" +#include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" + #include "../Common/PropIDUtils.h" #include "../../PropID.h" -#include "Panel.h" -#include "PluginInterface.h" -#include "MyLoadMenu.h" #include "App.h" #include "LangUtils.h" -#include "resource.h" +#include "MyLoadMenu.h" +#include "PluginInterface.h" #include "PropertyName.h" + +#include "resource.h" #include "PropertyNameRes.h" using namespace NWindows; @@ -30,7 +32,7 @@ static const UINT kSystemStartMenuID = kPluginMenuStartID + 100; void CPanel::InvokeSystemCommand(const char *command) { NCOM::CComInitializer comInitializer; - if (!IsFSFolder() && !IsFSDrivesFolder()) + if (!IsFsOrPureDrivesFolder()) return; CRecordVector<UInt32> operatedIndices; GetOperatedItemIndices(operatedIndices); @@ -58,26 +60,28 @@ static void AddPropertyString(PROPID propID, const wchar_t *nameBSTR, { if (prop.vt != VT_EMPTY) { - const UString name = GetNameOfProperty(propID, nameBSTR); UString val; - if (( + if ((prop.vt == VT_UI8 || prop.vt == VT_UI4) && ( propID == kpidSize || propID == kpidPackSize || propID == kpidNumSubDirs || propID == kpidNumSubFiles || propID == kpidNumBlocks || + propID == kpidClusterSize || + propID == kpidTotalSize || + propID == kpidFreeSpace || propID == kpidPhySize || propID == kpidHeadersSize || - propID == kpidClusterSize - ) && (prop.vt == VT_UI8 || prop.vt == VT_UI4)) + propID == kpidFreeSpace + )) val = ConvertSizeToString(ConvertPropVariantToUInt64(prop)); else val = ConvertPropertyToString(prop, propID); if (!val.IsEmpty()) { - s += name; + s += GetNameOfProperty(propID, nameBSTR); s += kPropValueSeparator; /* if (propID == kpidComment) @@ -129,7 +133,7 @@ void CPanel::Properties() message += kSeparator; } - message += LangString(IDS_PROPERTY_FILE_TYPE, 0x02000214); + message += LangString(IDS_PROP_FILE_TYPE, 0x02000214); message += kPropValueSeparator; message += GetFolderTypeID(); message += L"\n"; diff --git a/CPP/7zip/UI/FileManager/PanelOperations.cpp b/CPP/7zip/UI/FileManager/PanelOperations.cpp index c3b5d69d..9a60fb1a 100755 --- a/CPP/7zip/UI/FileManager/PanelOperations.cpp +++ b/CPP/7zip/UI/FileManager/PanelOperations.cpp @@ -2,25 +2,25 @@ #include "StdAfx.h" -#include "resource.h" - -#include "Panel.h" - -#include "Common/StringConvert.h" #include "Common/DynamicBuffer.h" +#include "Common/StringConvert.h" + +#include "Windows/COM.h" #include "Windows/FileDir.h" +#include "Windows/PropVariant.h" #include "Windows/ResourceString.h" #include "Windows/Thread.h" -#include "Windows/COM.h" #include "ComboDialog.h" #include "FSFolder.h" -#include "LangUtils.h" #include "FormatUtils.h" - +#include "LangUtils.h" +#include "Panel.h" #include "UpdateCallback100.h" +#include "resource.h" + using namespace NWindows; using namespace NFile; diff --git a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp index 36146d7a..d1531957 100755 --- a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp +++ b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp @@ -2,30 +2,25 @@ #include "StdAfx.h" -#include "resource.h" - -extern "C" -{ - #include "../../../../C/Alloc.h" -} +#include "../../../../C/Alloc.h" -#include "Common/Types.h" #include "Common/IntToString.h" -// #include "Windows/COM.h" #include "Windows/FileIO.h" #include "Windows/FileFind.h" #include "Windows/Thread.h" -#include "ProgressDialog2.h" -#include "SplitDialog.h" -#include "CopyDialog.h" #include "../GUI/ExtractRes.h" -#include "SplitUtils.h" +#include "resource.h" + #include "App.h" +#include "CopyDialog.h" #include "FormatUtils.h" #include "LangUtils.h" +#include "ProgressDialog2.h" +#include "SplitDialog.h" +#include "SplitUtils.h" using namespace NWindows; @@ -227,7 +222,7 @@ void CApp::Split() return; NFile::NFind::CFileInfoW fileInfo; - if (!NFile::NFind::FindFile(srcPath + itemName, fileInfo)) + if (!fileInfo.Find(srcPath + itemName)) { srcPanel.MessageBoxMyError(L"Can not find file"); return; @@ -422,7 +417,7 @@ void CApp::Combine() for (;;) { NFile::NFind::CFileInfoW fileInfo; - if (!NFile::NFind::FindFile(srcPath + nextName, fileInfo) || fileInfo.IsDir()) + if (!fileInfo.Find(srcPath + nextName) || fileInfo.IsDir()) break; combiner.Names.Add(nextName); combiner.TotalSize += fileInfo.Size; @@ -490,7 +485,7 @@ void CApp::Combine() NFile::NFind::CFileInfoW fileInfo; UString destFilePath = path + outName; combiner.OutputPath = destFilePath; - if (NFile::NFind::FindFile(destFilePath, fileInfo)) + if (fileInfo.Find(destFilePath)) { srcPanel.MessageBoxMyError(MyFormatNew(IDS_FILE_EXIST, 0x03020A04, destFilePath)); return; diff --git a/CPP/7zip/UI/FileManager/PhysDriveFolder.cpp b/CPP/7zip/UI/FileManager/PhysDriveFolder.cpp index 750f2e02..12b7dce8 100755 --- a/CPP/7zip/UI/FileManager/PhysDriveFolder.cpp +++ b/CPP/7zip/UI/FileManager/PhysDriveFolder.cpp @@ -2,22 +2,21 @@ #include "StdAfx.h" -extern "C" -{ - #include "../../../../C/Alloc.h" -} +#include "../../../../C/Alloc.h" + +#include "Common/Buffer.h" -#include "PhysDriveFolder.h" #include "Windows/PropVariant.h" #include "Windows/FileDevice.h" #include "Windows/FileSystem.h" #include "../../PropID.h" +#include "PhysDriveFolder.h" + using namespace NWindows; static const UInt32 kBufferSize = (4 << 20); - static STATPROPSTG kProperties[] = { { NULL, kpidName, VT_BSTR}, @@ -177,7 +176,8 @@ struct CPhysTempBuffer ~CPhysTempBuffer() { MyFree(buffer); } }; -HRESULT CopyFileSpec(LPCWSTR fromPath, LPCWSTR toPath, bool writeToDisk, UInt64 fileSize, UInt32 bufferSize, IProgress *progress) +HRESULT CopyFileSpec(LPCWSTR fromPath, LPCWSTR toPath, bool writeToDisk, UInt64 fileSize, + UInt32 bufferSize, UInt64 progressStart, IProgress *progress) { NFile::NIO::CInFile inFile; if (!inFile.Open(fromPath)) @@ -203,7 +203,8 @@ HRESULT CopyFileSpec(LPCWSTR fromPath, LPCWSTR toPath, bool writeToDisk, UInt64 for (UInt64 pos = 0; pos < fileSize;) { - RINOK(progress->SetCompleted(&pos)); + UInt64 progressCur = progressStart + pos; + RINOK(progress->SetCompleted(&progressCur)); UInt64 rem = fileSize - pos; UInt32 curSize = (UInt32)MyMin(rem, (UInt64)bufferSize); UInt32 processedSize; @@ -262,7 +263,7 @@ STDMETHODIMP CPhysDriveFolder::CopyTo(const UInt32 * /* indices */, UInt32 numIt RINOK(callback->SetCurrentFilePath(GetFullPathWithName())); UInt32 bufferSize = (_driveType == DRIVE_REMOVABLE) ? (18 << 10) * 4 : kBufferSize; - return CopyFileSpec(GetFullPath(), destPathResult, false, fileSize, bufferSize, callback); + return CopyFileSpec(GetFullPath(), destPathResult, false, fileSize, bufferSize, 0, callback); } ///////////////////////////////////////////////// @@ -289,5 +290,6 @@ STDMETHODIMP CPhysDriveFolder::CopyFrom( return E_NOTIMPL; UInt32 bufferSize = (_driveType == DRIVE_REMOVABLE) ? (18 << 10) * 4 : kBufferSize; // MessageBoxW(0, fromFolderPath, itemsPaths[0], 0); - return CopyFileSpec((UString)fromFolderPath + itemsPaths[0], GetFullPath(), true, (UInt64)(Int64)-1, bufferSize, callback); + return CopyFileSpec((UString)fromFolderPath + itemsPaths[0], GetFullPath(), true, (UInt64)(Int64)-1, bufferSize, 0, callback); } + diff --git a/CPP/7zip/UI/FileManager/PhysDriveFolder.h b/CPP/7zip/UI/FileManager/PhysDriveFolder.h index 1f327966..64a36b91 100755 --- a/CPP/7zip/UI/FileManager/PhysDriveFolder.h +++ b/CPP/7zip/UI/FileManager/PhysDriveFolder.h @@ -5,6 +5,7 @@ #include "Common/MyString.h" #include "Common/MyCom.h" +#include "../../Archive/IArchive.h" #include "IFolder.h" @@ -32,11 +33,11 @@ public: INTERFACE_FolderFolder(;) INTERFACE_FolderOperations(;) - STDMETHOD(WasChanged)(INT32 *wasChanged); - STDMETHOD(Clone)(IFolderFolder **resultFolder); + STDMETHOD(WasChanged)(Int32 *wasChanged); STDMETHOD(GetItemFullSize)(UInt32 index, PROPVARIANT *value, IProgress *progress); + STDMETHOD(Clone)(IFolderFolder **resultFolder); - // STDMETHOD(GetSystemIconIndex)(UInt32 index, INT32 *iconIndex); + // STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex); private: UString _name; diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp index e8846e68..87a1521d 100755 --- a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp @@ -1,10 +1,11 @@ // ProgressDialog2.cpp #include "StdAfx.h" -#include "resource.h" -#include "ProgressDialog2.h" + #include "Common/IntToString.h" +#include "ProgressDialog2.h" + using namespace NWindows; static const UINT_PTR kTimerID = 3; @@ -67,8 +68,8 @@ void CProgressDialog::AddToTitle(LPCWSTR s) } } -static const int kTitleFileNameSizeLimit = 36; -static const int kCurrentFileNameSizeLimit = 70; +static const int kTitleFileNameSizeLimit = 40; +static const int kCurrentFileNameSizeLimit = 82; static void ReduceString(UString &s, int size) { @@ -143,11 +144,7 @@ void CProgressDialog::SetRange(UInt64 range) _range = range; _previousPos = (UInt64)(Int64)-1; _converter.Init(range); - m_ProgressBar.SetRange32(0 , _converter.Count(range)); // Test it for 100% - - wchar_t s[32]; - ConvertSizeToString(_range, s); - SetItemText(IDC_PROGRESS_TOTAL_VALUE, s); + m_ProgressBar.SetRange32(0, _converter.Count(range)); // Test it for 100% } void CProgressDialog::SetPos(UInt64 pos) @@ -187,19 +184,28 @@ bool CProgressDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */) if (ProgressSynch.GetPaused()) return true; UInt64 total, completed, totalFiles, completedFiles, inSize, outSize; - ProgressSynch.GetProgress(total, completed, totalFiles, completedFiles, inSize, outSize); + bool bytesProgressMode; + ProgressSynch.GetProgress(total, completed, totalFiles, completedFiles, inSize, outSize, bytesProgressMode); UInt32 curTime = ::GetTickCount(); - if (total != _range) - SetRange(total); - if (total == (UInt64)(Int64)-1) + UInt64 progressTotal = bytesProgressMode ? total : totalFiles; + UInt64 progressCompleted = bytesProgressMode ? completed : completedFiles; + + if (progressTotal != _range) + SetRange(progressTotal); + if (progressTotal == (UInt64)(Int64)-1) { SetPos(0); - SetRange(completed); + SetRange(progressCompleted); } else - SetPos(completed); + SetPos(progressCompleted); + + wchar_t s[32] = { 0 }; + if (total != (UInt64)(Int64)-1) + ConvertSizeToString(total, s); + SetItemText(IDC_PROGRESS_TOTAL_VALUE, s); _elapsedTime += (curTime - _prevTime); _prevTime = curTime; diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.h b/CPP/7zip/UI/FileManager/ProgressDialog2.h index e838ae25..3ab9f4c0 100755 --- a/CPP/7zip/UI/FileManager/ProgressDialog2.h +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.h @@ -1,9 +1,7 @@ // ProgressDialog2.h -#ifndef __PROGRESSDIALOG2_H -#define __PROGRESSDIALOG2_H - -#include "ProgressDialog2Res.h" +#ifndef __PROGRESS_DIALOG2_H +#define __PROGRESS_DIALOG2_H #include "Common/Types.h" @@ -11,59 +9,69 @@ #include "Windows/Control/ProgressBar.h" #include "Windows/Synchronization.h" +#include "ProgressDialog2Res.h" + class CProgressSynch { - NWindows::NSynchronization::CCriticalSection _criticalSection; + NWindows::NSynchronization::CCriticalSection _cs; bool _stopped; bool _paused; - UInt64 _total; - UInt64 _completed; + bool _bytesProgressMode; + + UInt64 _totalBytes; + UInt64 _curBytes; + UInt64 _totalFiles; + UInt64 _curFiles; UInt64 _inSize; UInt64 _outSize; - UInt64 _totalFiles; - UInt64 _completedFiles; + UString TitleFileName; UString CurrentFileName; + public: CProgressSynch(): _stopped(false), _paused(false), - _total((UInt64)(Int64)-1), - _completed(0), - _totalFiles((UInt64)(Int64)-1), - _completedFiles(0), + _totalBytes((UInt64)(Int64)-1), _curBytes(0), + _totalFiles((UInt64)(Int64)-1), _curFiles(0), _inSize((UInt64)(Int64)-1), - _outSize((UInt64)(Int64)-1) + _outSize((UInt64)(Int64)-1), + _bytesProgressMode(true) {} bool GetStopped() { - NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); return _stopped; } void SetStopped(bool value) { - NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); _stopped = value; } bool GetPaused() { - NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); return _paused; } void SetPaused(bool value) { - NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); _paused = value; } + void SetBytesProgressMode(bool bytesProgressMode) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + _bytesProgressMode = bytesProgressMode; + } void SetProgress(UInt64 total, UInt64 completed) { - NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); - _total = total; - _completed = completed; + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + _totalBytes = total; + _curBytes = completed; } void SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { - NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); if (inSize) _inSize = *inSize; if (outSize) @@ -71,51 +79,58 @@ public: } void SetPos(UInt64 completed) { - NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); - _completed = completed; + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + _curBytes = completed; + } + void SetNumBytesTotal(UInt64 value) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + _totalBytes = value; } void SetNumFilesTotal(UInt64 value) { - NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); _totalFiles = value; } void SetNumFilesCur(UInt64 value) { - NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); - _completedFiles = value; + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + _curFiles = value; } HRESULT ProcessStopAndPause(); HRESULT SetPosAndCheckPaused(UInt64 completed); void GetProgress(UInt64 &total, UInt64 &completed, - UInt64 &totalFiles, UInt64 &completedFiles, - UInt64 &inSize, UInt64 &outSize) + UInt64 &totalFiles, UInt64 &curFiles, + UInt64 &inSize, UInt64 &outSize, + bool &bytesProgressMode) { - NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); - total = _total; - completed = _completed; + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + total = _totalBytes; + completed = _curBytes; totalFiles = _totalFiles; - completedFiles = _completedFiles; + curFiles = _curFiles; inSize = _inSize; outSize = _outSize; + bytesProgressMode = _bytesProgressMode; } void SetTitleFileName(const UString &fileName) { - NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); TitleFileName = fileName; } void GetTitleFileName(UString &fileName) { - NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); fileName = TitleFileName; } void SetCurrentFileName(const UString &fileName) { - NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); CurrentFileName = fileName; } void GetCurrentFileName(UString &fileName) { - NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); fileName = CurrentFileName; } }; diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.rc b/CPP/7zip/UI/FileManager/ProgressDialog2.rc index 92b970f6..2b707451 100755 --- a/CPP/7zip/UI/FileManager/ProgressDialog2.rc +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.rc @@ -1,7 +1,7 @@ #include "ProgressDialog2Res.h" #include "../../GuiCommon.rc" -#define xSize2 320 +#define xSize2 350 #define ySize2 110 #define xSize (xSize2 + marg + marg) @@ -20,7 +20,7 @@ #define x1 (marg + x0Size) #define x1Size 70 -#define x3Size 40 +#define x3Size 60 #define x3 (xSize - marg - x3Size) #define x2Size 90 diff --git a/CPP/7zip/UI/FileManager/PropertyName.cpp b/CPP/7zip/UI/FileManager/PropertyName.cpp index cb4edfc2..48090d38 100755 --- a/CPP/7zip/UI/FileManager/PropertyName.cpp +++ b/CPP/7zip/UI/FileManager/PropertyName.cpp @@ -3,15 +3,17 @@ #include "StdAfx.h" #include "Common/IntToString.h" + #include "Windows/ResourceString.h" #include "../../PropID.h" -#include "resource.h" -#include "PropertyNameRes.h" #include "LangUtils.h" #include "PropertyName.h" +#include "resource.h" +#include "PropertyNameRes.h" + struct CPropertyIDNamePair { PROPID PropID; @@ -21,60 +23,66 @@ struct CPropertyIDNamePair static CPropertyIDNamePair kPropertyIDNamePairs[] = { - { kpidPath, IDS_PROPERTY_PATH, 0x02000203 }, - { kpidName, IDS_PROPERTY_NAME, 0x02000204 }, - { kpidExtension, IDS_PROPERTY_EXTENSION, 0x02000205 }, - { kpidIsDir, IDS_PROPERTY_IS_FOLDER, 0x02000206}, - { kpidSize, IDS_PROPERTY_SIZE, 0x02000207}, - { kpidPackSize, IDS_PROPERTY_PACKED_SIZE, 0x02000208 }, - { kpidAttrib, IDS_PROPERTY_ATTRIBUTES, 0x02000209 }, - { kpidCTime, IDS_PROPERTY_CTIME, 0x0200020A }, - { kpidATime, IDS_PROPERTY_ATIME, 0x0200020B }, - { kpidMTime, IDS_PROPERTY_MTIME, 0x0200020C }, - { kpidSolid, IDS_PROPERTY_SOLID, 0x0200020D }, - { kpidCommented, IDS_PROPERTY_C0MMENTED, 0x0200020E }, - { kpidEncrypted, IDS_PROPERTY_ENCRYPTED, 0x0200020F }, - { kpidSplitBefore, IDS_PROPERTY_SPLIT_BEFORE, 0x02000210 }, - { kpidSplitAfter, IDS_PROPERTY_SPLIT_AFTER, 0x02000211 }, - { kpidDictionarySize, IDS_PROPERTY_DICTIONARY_SIZE, 0x02000212 }, - { kpidCRC, IDS_PROPERTY_CRC, 0x02000213 }, - { kpidType, IDS_PROPERTY_FILE_TYPE, 0x02000214}, - { kpidIsAnti, IDS_PROPERTY_ANTI, 0x02000215 }, - { kpidMethod, IDS_PROPERTY_METHOD, 0x02000216 }, - { kpidHostOS, IDS_PROPERTY_HOST_OS, 0x02000217 }, - { kpidFileSystem, IDS_PROPERTY_FILE_SYSTEM, 0x02000218}, - { kpidUser, IDS_PROPERTY_USER, 0x02000219}, - { kpidGroup, IDS_PROPERTY_GROUP, 0x0200021A}, - { kpidBlock, IDS_PROPERTY_BLOCK, 0x0200021B }, - { kpidComment, IDS_PROPERTY_COMMENT, 0x0200021C }, - { kpidPosition, IDS_PROPERTY_POSITION, 0x0200021D }, - { kpidPrefix, IDS_PROPERTY_PREFIX, 0x0200021E }, - { kpidNumSubDirs, IDS_PROPERTY_FOLDERS, 0x0200021F }, - { kpidNumSubFiles, IDS_PROPERTY_FILES, 0x02000220 }, - { kpidUnpackVer, IDS_PROPERTY_VERSION, 0x02000221}, - { kpidVolume, IDS_PROPERTY_VOLUME, 0x02000222}, - { kpidIsVolume, IDS_PROPERTY_IS_VOLUME, 0x02000223}, - { kpidOffset, IDS_PROPERTY_OFFSET, 0x02000224}, - { kpidLinks, IDS_PROPERTY_LINKS, 0x02000225}, - { kpidNumBlocks, IDS_PROPERTY_NUM_BLOCKS, 0x02000226}, - { kpidNumVolumes, IDS_PROPERTY_NUM_VOLUMES, 0x02000227}, - - { kpidBit64, IDS_PROPERTY_BIT64, 0x02000229}, - { kpidBigEndian, IDS_PROPERTY_BIG_ENDIAN, 0x0200022A}, - { kpidCpu, IDS_PROPERTY_CPU, 0x0200022B}, - { kpidPhySize, IDS_PROPERTY_PHY_SIZE, 0x0200022C}, - { kpidHeadersSize, IDS_PROPERTY_HEADERS_SIZE, 0x0200022D}, - { kpidChecksum, IDS_PROPERTY_CHECKSUM, 0x0200022E}, - { kpidCharacts, IDS_PROPERTY_CHARACTS, 0x0200022F}, - { kpidVa, IDS_PROPERTY_VA, 0x02000230}, + { kpidPath, IDS_PROP_PATH, 0x02000203 }, + { kpidName, IDS_PROP_NAME, 0x02000204 }, + { kpidExtension, IDS_PROP_EXTENSION, 0x02000205 }, + { kpidIsDir, IDS_PROP_IS_FOLDER, 0x02000206}, + { kpidSize, IDS_PROP_SIZE, 0x02000207}, + { kpidPackSize, IDS_PROP_PACKED_SIZE, 0x02000208 }, + { kpidAttrib, IDS_PROP_ATTRIBUTES, 0x02000209 }, + { kpidCTime, IDS_PROP_CTIME, 0x0200020A }, + { kpidATime, IDS_PROP_ATIME, 0x0200020B }, + { kpidMTime, IDS_PROP_MTIME, 0x0200020C }, + { kpidSolid, IDS_PROP_SOLID, 0x0200020D }, + { kpidCommented, IDS_PROP_C0MMENTED, 0x0200020E }, + { kpidEncrypted, IDS_PROP_ENCRYPTED, 0x0200020F }, + { kpidSplitBefore, IDS_PROP_SPLIT_BEFORE, 0x02000210 }, + { kpidSplitAfter, IDS_PROP_SPLIT_AFTER, 0x02000211 }, + { kpidDictionarySize, IDS_PROP_DICTIONARY_SIZE, 0x02000212 }, + { kpidCRC, IDS_PROP_CRC, 0x02000213 }, + { kpidType, IDS_PROP_FILE_TYPE, 0x02000214}, + { kpidIsAnti, IDS_PROP_ANTI, 0x02000215 }, + { kpidMethod, IDS_PROP_METHOD, 0x02000216 }, + { kpidHostOS, IDS_PROP_HOST_OS, 0x02000217 }, + { kpidFileSystem, IDS_PROP_FILE_SYSTEM, 0x02000218}, + { kpidUser, IDS_PROP_USER, 0x02000219}, + { kpidGroup, IDS_PROP_GROUP, 0x0200021A}, + { kpidBlock, IDS_PROP_BLOCK, 0x0200021B }, + { kpidComment, IDS_PROP_COMMENT, 0x0200021C }, + { kpidPosition, IDS_PROP_POSITION, 0x0200021D }, + { kpidPrefix, IDS_PROP_PREFIX, 0x0200021E }, + { kpidNumSubDirs, IDS_PROP_FOLDERS, 0x0200021F }, + { kpidNumSubFiles, IDS_PROP_FILES, 0x02000220 }, + { kpidUnpackVer, IDS_PROP_VERSION, 0x02000221}, + { kpidVolume, IDS_PROP_VOLUME, 0x02000222}, + { kpidIsVolume, IDS_PROP_IS_VOLUME, 0x02000223}, + { kpidOffset, IDS_PROP_OFFSET, 0x02000224}, + { kpidLinks, IDS_PROP_LINKS, 0x02000225}, + { kpidNumBlocks, IDS_PROP_NUM_BLOCKS, 0x02000226}, + { kpidNumVolumes, IDS_PROP_NUM_VOLUMES, 0x02000227}, - { kpidTotalSize, IDS_PROPERTY_TOTAL_SIZE, 0x03031100 }, - { kpidFreeSpace, IDS_PROPERTY_FREE_SPACE, 0x03031101 }, - { kpidClusterSize, IDS_PROPERTY_CLUSTER_SIZE, 0x03031102}, - { kpidVolumeName, IDS_PROPERTY_VOLUME_NAME, 0x03031103 }, + { kpidBit64, IDS_PROP_BIT64, 0x02000229}, + { kpidBigEndian, IDS_PROP_BIG_ENDIAN, 0x0200022A}, + { kpidCpu, IDS_PROP_CPU, 0x0200022B}, + { kpidPhySize, IDS_PROP_PHY_SIZE, 0x0200022C}, + { kpidHeadersSize, IDS_PROP_HEADERS_SIZE, 0x0200022D}, + { kpidChecksum, IDS_PROP_CHECKSUM, 0x0200022E}, + { kpidCharacts, IDS_PROP_CHARACTS, 0x0200022F}, + { kpidVa, IDS_PROP_VA, 0x02000230}, + { kpidId, IDS_PROP_ID, 0x02000231 }, + { kpidShortName, IDS_PROP_SHORT_NAME, 0x02000232 }, + { kpidCreatorApp, IDS_PROP_CREATOR_APP, 0x02000233 }, + { kpidSectorSize, IDS_PROP_SECTOR_SIZE, 0x02000234 }, + { kpidPosixAttrib, IDS_PROP_POSIX_ATTRIB, 0x02000235 }, + { kpidLink, IDS_PROP_LINK, 0x02000236 }, + + { kpidTotalSize, IDS_PROP_TOTAL_SIZE, 0x03031100 }, + { kpidFreeSpace, IDS_PROP_FREE_SPACE, 0x03031101 }, + { kpidClusterSize, IDS_PROP_CLUSTER_SIZE, 0x03031102}, + { kpidVolumeName, IDS_PROP_VOLUME_NAME, 0x03031103 }, - { kpidLocalName, IDS_PROPERTY_LOCAL_NAME, 0x03031200 }, - { kpidProvider, IDS_PROPERTY_PROVIDER, 0x03031201 } + { kpidLocalName, IDS_PROP_LOCAL_NAME, 0x03031200 }, + { kpidProvider, IDS_PROP_PROVIDER, 0x03031201 } }; int FindProperty(PROPID propID) @@ -92,8 +100,8 @@ UString GetNameOfProperty(PROPID propID, const wchar_t *name) { if (name) return name; - wchar_t s[32]; - ConvertUInt64ToString(propID, s); + wchar_t s[16]; + ConvertUInt32ToString(propID, s); return s; } const CPropertyIDNamePair &pair = kPropertyIDNamePairs[index]; diff --git a/CPP/7zip/UI/FileManager/PropertyName.rc b/CPP/7zip/UI/FileManager/PropertyName.rc index ad8a9012..576b52cb 100755 --- a/CPP/7zip/UI/FileManager/PropertyName.rc +++ b/CPP/7zip/UI/FileManager/PropertyName.rc @@ -4,50 +4,56 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US STRINGTABLE BEGIN - IDS_PROPERTY_PATH "Path" - IDS_PROPERTY_NAME "Name" - IDS_PROPERTY_EXTENSION "Extension" - IDS_PROPERTY_IS_FOLDER "Folder" - IDS_PROPERTY_SIZE "Size" - IDS_PROPERTY_PACKED_SIZE "Packed Size" - IDS_PROPERTY_ATTRIBUTES "Attributes" - IDS_PROPERTY_CTIME "Created" - IDS_PROPERTY_ATIME "Accessed" - IDS_PROPERTY_MTIME "Modified" - IDS_PROPERTY_SOLID "Solid" - IDS_PROPERTY_C0MMENTED "Commented" - IDS_PROPERTY_ENCRYPTED "Encrypted" - IDS_PROPERTY_DICTIONARY_SIZE "Dictionary Size" - IDS_PROPERTY_SPLIT_BEFORE "Split Before" - IDS_PROPERTY_SPLIT_AFTER "Split After" - IDS_PROPERTY_CRC "CRC" - IDS_PROPERTY_FILE_TYPE "Type" - IDS_PROPERTY_ANTI "Anti" - IDS_PROPERTY_METHOD "Method" - IDS_PROPERTY_HOST_OS "Host OS" - IDS_PROPERTY_FILE_SYSTEM "File System" - IDS_PROPERTY_USER "User" - IDS_PROPERTY_GROUP "Group" - IDS_PROPERTY_BLOCK "Block" - IDS_PROPERTY_COMMENT "Comment" - IDS_PROPERTY_POSITION "Position" - IDS_PROPERTY_PREFIX "Path Prefix" - IDS_PROPERTY_FOLDERS "Folders" - IDS_PROPERTY_FILES "Files" - IDS_PROPERTY_VERSION "Version" - IDS_PROPERTY_VOLUME "Volume" - IDS_PROPERTY_IS_VOLUME "Multivolume" - IDS_PROPERTY_OFFSET "Offset" - IDS_PROPERTY_LINKS "Links" - IDS_PROPERTY_NUM_BLOCKS "Blocks" - IDS_PROPERTY_NUM_VOLUMES "Volumes" + IDS_PROP_PATH "Path" + IDS_PROP_NAME "Name" + IDS_PROP_EXTENSION "Extension" + IDS_PROP_IS_FOLDER "Folder" + IDS_PROP_SIZE "Size" + IDS_PROP_PACKED_SIZE "Packed Size" + IDS_PROP_ATTRIBUTES "Attributes" + IDS_PROP_CTIME "Created" + IDS_PROP_ATIME "Accessed" + IDS_PROP_MTIME "Modified" + IDS_PROP_SOLID "Solid" + IDS_PROP_C0MMENTED "Commented" + IDS_PROP_ENCRYPTED "Encrypted" + IDS_PROP_DICTIONARY_SIZE "Dictionary Size" + IDS_PROP_SPLIT_BEFORE "Split Before" + IDS_PROP_SPLIT_AFTER "Split After" + IDS_PROP_CRC "CRC" + IDS_PROP_FILE_TYPE "Type" + IDS_PROP_ANTI "Anti" + IDS_PROP_METHOD "Method" + IDS_PROP_HOST_OS "Host OS" + IDS_PROP_FILE_SYSTEM "File System" + IDS_PROP_USER "User" + IDS_PROP_GROUP "Group" + IDS_PROP_BLOCK "Block" + IDS_PROP_COMMENT "Comment" + IDS_PROP_POSITION "Position" + IDS_PROP_PREFIX "Path Prefix" + IDS_PROP_FOLDERS "Folders" + IDS_PROP_FILES "Files" + IDS_PROP_VERSION "Version" + IDS_PROP_VOLUME "Volume" + IDS_PROP_IS_VOLUME "Multivolume" + IDS_PROP_OFFSET "Offset" + IDS_PROP_LINKS "Links" + IDS_PROP_NUM_BLOCKS "Blocks" + IDS_PROP_NUM_VOLUMES "Volumes" - IDS_PROPERTY_BIT64 "64-bit" - IDS_PROPERTY_BIG_ENDIAN "Big-endian" - IDS_PROPERTY_CPU "CPU" - IDS_PROPERTY_PHY_SIZE "Physical Size" - IDS_PROPERTY_HEADERS_SIZE "Headers Size" - IDS_PROPERTY_CHECKSUM "Checksum" - IDS_PROPERTY_CHARACTS "Characteristics" - IDS_PROPERTY_VA "Va" + IDS_PROP_BIT64 "64-bit" + IDS_PROP_BIG_ENDIAN "Big-endian" + IDS_PROP_CPU "CPU" + IDS_PROP_PHY_SIZE "Physical Size" + IDS_PROP_HEADERS_SIZE "Headers Size" + IDS_PROP_CHECKSUM "Checksum" + IDS_PROP_CHARACTS "Characteristics" + IDS_PROP_VA "Virtual Address" + IDS_PROP_ID "ID" + IDS_PROP_SHORT_NAME "Short Name" + IDS_PROP_CREATOR_APP "Creator Application" + IDS_PROP_SECTOR_SIZE "Sector Size" + IDS_PROP_POSIX_ATTRIB "Mode" + IDS_PROP_LINK "Link" END diff --git a/CPP/7zip/UI/FileManager/PropertyNameRes.h b/CPP/7zip/UI/FileManager/PropertyNameRes.h index 74d535ac..00458a24 100755 --- a/CPP/7zip/UI/FileManager/PropertyNameRes.h +++ b/CPP/7zip/UI/FileManager/PropertyNameRes.h @@ -1,46 +1,52 @@ -#define IDS_PROPERTY_PATH 3 -#define IDS_PROPERTY_NAME 4 -#define IDS_PROPERTY_EXTENSION 5 -#define IDS_PROPERTY_IS_FOLDER 6 -#define IDS_PROPERTY_SIZE 7 -#define IDS_PROPERTY_PACKED_SIZE 8 -#define IDS_PROPERTY_ATTRIBUTES 9 -#define IDS_PROPERTY_CTIME 10 -#define IDS_PROPERTY_ATIME 11 -#define IDS_PROPERTY_MTIME 12 -#define IDS_PROPERTY_SOLID 13 -#define IDS_PROPERTY_C0MMENTED 14 -#define IDS_PROPERTY_ENCRYPTED 15 -#define IDS_PROPERTY_DICTIONARY_SIZE 16 -#define IDS_PROPERTY_SPLIT_BEFORE 17 -#define IDS_PROPERTY_SPLIT_AFTER 18 -#define IDS_PROPERTY_CRC 19 -#define IDS_PROPERTY_FILE_TYPE 20 -#define IDS_PROPERTY_ANTI 21 -#define IDS_PROPERTY_METHOD 22 -#define IDS_PROPERTY_HOST_OS 23 -#define IDS_PROPERTY_FILE_SYSTEM 24 -#define IDS_PROPERTY_USER 25 -#define IDS_PROPERTY_GROUP 26 -#define IDS_PROPERTY_BLOCK 27 -#define IDS_PROPERTY_COMMENT 28 -#define IDS_PROPERTY_POSITION 29 -#define IDS_PROPERTY_PREFIX 30 -#define IDS_PROPERTY_FOLDERS 31 -#define IDS_PROPERTY_FILES 32 -#define IDS_PROPERTY_VERSION 33 -#define IDS_PROPERTY_VOLUME 34 -#define IDS_PROPERTY_IS_VOLUME 35 -#define IDS_PROPERTY_OFFSET 36 -#define IDS_PROPERTY_LINKS 37 -#define IDS_PROPERTY_NUM_BLOCKS 38 -#define IDS_PROPERTY_NUM_VOLUMES 39 +#define IDS_PROP_PATH 3 +#define IDS_PROP_NAME 4 +#define IDS_PROP_EXTENSION 5 +#define IDS_PROP_IS_FOLDER 6 +#define IDS_PROP_SIZE 7 +#define IDS_PROP_PACKED_SIZE 8 +#define IDS_PROP_ATTRIBUTES 9 +#define IDS_PROP_CTIME 10 +#define IDS_PROP_ATIME 11 +#define IDS_PROP_MTIME 12 +#define IDS_PROP_SOLID 13 +#define IDS_PROP_C0MMENTED 14 +#define IDS_PROP_ENCRYPTED 15 +#define IDS_PROP_DICTIONARY_SIZE 16 +#define IDS_PROP_SPLIT_BEFORE 17 +#define IDS_PROP_SPLIT_AFTER 18 +#define IDS_PROP_CRC 19 +#define IDS_PROP_FILE_TYPE 20 +#define IDS_PROP_ANTI 21 +#define IDS_PROP_METHOD 22 +#define IDS_PROP_HOST_OS 23 +#define IDS_PROP_FILE_SYSTEM 24 +#define IDS_PROP_USER 25 +#define IDS_PROP_GROUP 26 +#define IDS_PROP_BLOCK 27 +#define IDS_PROP_COMMENT 28 +#define IDS_PROP_POSITION 29 +#define IDS_PROP_PREFIX 30 +#define IDS_PROP_FOLDERS 31 +#define IDS_PROP_FILES 32 +#define IDS_PROP_VERSION 33 +#define IDS_PROP_VOLUME 34 +#define IDS_PROP_IS_VOLUME 35 +#define IDS_PROP_OFFSET 36 +#define IDS_PROP_LINKS 37 +#define IDS_PROP_NUM_BLOCKS 38 +#define IDS_PROP_NUM_VOLUMES 39 -#define IDS_PROPERTY_BIT64 41 -#define IDS_PROPERTY_BIG_ENDIAN 42 -#define IDS_PROPERTY_CPU 43 -#define IDS_PROPERTY_PHY_SIZE 44 -#define IDS_PROPERTY_HEADERS_SIZE 45 -#define IDS_PROPERTY_CHECKSUM 46 -#define IDS_PROPERTY_CHARACTS 47 -#define IDS_PROPERTY_VA 48 +#define IDS_PROP_BIT64 41 +#define IDS_PROP_BIG_ENDIAN 42 +#define IDS_PROP_CPU 43 +#define IDS_PROP_PHY_SIZE 44 +#define IDS_PROP_HEADERS_SIZE 45 +#define IDS_PROP_CHECKSUM 46 +#define IDS_PROP_CHARACTS 47 +#define IDS_PROP_VA 48 +#define IDS_PROP_ID 49 +#define IDS_PROP_SHORT_NAME 50 +#define IDS_PROP_CREATOR_APP 51 +#define IDS_PROP_SECTOR_SIZE 52 +#define IDS_PROP_POSIX_ATTRIB 53 +#define IDS_PROP_LINK 54 diff --git a/CPP/7zip/UI/FileManager/RegistryAssociations.cpp b/CPP/7zip/UI/FileManager/RegistryAssociations.cpp index 8c6e6ae8..d4fbfe13 100755 --- a/CPP/7zip/UI/FileManager/RegistryAssociations.cpp +++ b/CPP/7zip/UI/FileManager/RegistryAssociations.cpp @@ -4,21 +4,18 @@ #include "RegistryAssociations.h" -#include "Common/StringConvert.h" #include "Common/IntToString.h" +#include "Common/StringConvert.h" #include "Common/StringToInt.h" -#include "Windows/Synchronization.h" #include "Windows/Registry.h" - -#include "Windows/FileName.h" +#include "Windows/Synchronization.h" #include "StringUtils.h" using namespace NWindows; using namespace NRegistry; - namespace NRegistryAssociations { static NSynchronization::CCriticalSection g_CriticalSection; @@ -218,8 +215,8 @@ void AddShellExtensionInfo(const CSysString &extension, if (iconIndex >= 0) { iconPathFull += L","; - wchar_t s[32]; - ConvertUInt64ToString((UInt64)iconIndex, s); + wchar_t s[16]; + ConvertUInt32ToString(iconIndex, s); iconPathFull += s; } iconKey.SetValue(NULL, iconPathFull); diff --git a/CPP/7zip/UI/FileManager/RegistryUtils.cpp b/CPP/7zip/UI/FileManager/RegistryUtils.cpp index ed118457..bd1248a2 100755 --- a/CPP/7zip/UI/FileManager/RegistryUtils.cpp +++ b/CPP/7zip/UI/FileManager/RegistryUtils.cpp @@ -2,10 +2,12 @@ #include "StdAfx.h" -#include "RegistryUtils.h" #include "Common/IntToString.h" + #include "Windows/Registry.h" +#include "RegistryUtils.h" + using namespace NWindows; using namespace NRegistry; @@ -17,6 +19,7 @@ static const TCHAR *kCU_FMPath = REG_PATH_7Z TEXT(STRING_PATH_SEPARATOR) TEXT("F static const WCHAR *kLangValueName = L"Lang"; static const WCHAR *kEditor = L"Editor"; +static const WCHAR *kDiff = L"Diff"; static const TCHAR *kShowDots = TEXT("ShowDots"); static const TCHAR *kShowRealFileIcons = TEXT("ShowRealFileIcons"); static const TCHAR *kShowSystemMenu = TEXT("ShowSystemMenu"); @@ -31,35 +34,29 @@ static const TCHAR *kLargePagesEnable = TEXT("LargePages"); static const TCHAR *kFlatViewName = TEXT("FlatViewArc"); -void SaveRegLang(const UString &langFile) +static void SaveCuString(LPCTSTR keyPath, LPCWSTR valuePath, LPCWSTR value) { CKey key; - key.Create(HKEY_CURRENT_USER, kCUBasePath); - key.SetValue(kLangValueName, langFile); + key.Create(HKEY_CURRENT_USER, keyPath); + key.SetValue(valuePath, value); } -void ReadRegLang(UString &langFile) +static void ReadCuString(LPCTSTR keyPath, LPCWSTR valuePath, UString &res) { - langFile.Empty(); + res.Empty(); CKey key; - if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) == ERROR_SUCCESS) - key.QueryValue(kLangValueName, langFile); + if (key.Open(HKEY_CURRENT_USER, keyPath, KEY_READ) == ERROR_SUCCESS) + key.QueryValue(valuePath, res); } -void SaveRegEditor(const UString &editorPath) -{ - CKey key; - key.Create(HKEY_CURRENT_USER, kCU_FMPath); - key.SetValue(kEditor, editorPath); -} +void SaveRegLang(const UString &path) { SaveCuString(kCUBasePath, kLangValueName, path); } +void ReadRegLang(UString &path) { ReadCuString(kCUBasePath, kLangValueName, path); } -void ReadRegEditor(UString &editorPath) -{ - editorPath.Empty(); - CKey key; - if (key.Open(HKEY_CURRENT_USER, kCU_FMPath, KEY_READ) == ERROR_SUCCESS) - key.QueryValue(kEditor, editorPath); -} +void SaveRegEditor(const UString &path) { SaveCuString(kCU_FMPath, kEditor, path); } +void ReadRegEditor(UString &path) { ReadCuString(kCU_FMPath, kEditor, path); } + +void SaveRegDiff(const UString &path) { SaveCuString(kCU_FMPath, kDiff, path); } +void ReadRegDiff(UString &path) { ReadCuString(kCU_FMPath, kDiff, path); } static void Save7ZipOption(const TCHAR *value, bool enabled) { @@ -154,8 +151,8 @@ bool ReadLockMemoryEnable() { return Read7ZipOption(kLargePagesEnable, false); } static CSysString GetFlatViewName(UInt32 panelIndex) { - TCHAR panelString[32]; - ConvertUInt64ToString(panelIndex, panelString); + TCHAR panelString[16]; + ConvertUInt32ToString(panelIndex, panelString); return (CSysString)kFlatViewName + panelString; } diff --git a/CPP/7zip/UI/FileManager/RegistryUtils.h b/CPP/7zip/UI/FileManager/RegistryUtils.h index 9b9c91cf..5469f401 100755 --- a/CPP/7zip/UI/FileManager/RegistryUtils.h +++ b/CPP/7zip/UI/FileManager/RegistryUtils.h @@ -1,15 +1,18 @@ // RegistryUtils.h -#include "Common/StringConvert.h" +#ifndef __REGISTRY_UTILS_H +#define __REGISTRY_UTILS_H -#ifndef __REGISTRYUTILS_H -#define __REGISTRYUTILS_H +#include "Common/MyString.h" -void SaveRegLang(const UString &langFile); -void ReadRegLang(UString &langFile); +void SaveRegLang(const UString &path); +void ReadRegLang(UString &path); -void SaveRegEditor(const UString &editorPath); -void ReadRegEditor(UString &editorPath); +void SaveRegEditor(const UString &path); +void ReadRegEditor(UString &path); + +void SaveRegDiff(const UString &path); +void ReadRegDiff(UString &path); void SaveShowDots(bool showDots); bool ReadShowDots(); diff --git a/CPP/7zip/UI/FileManager/RootFolder.cpp b/CPP/7zip/UI/FileManager/RootFolder.cpp index 1cb71e5f..ea6f5080 100755 --- a/CPP/7zip/UI/FileManager/RootFolder.cpp +++ b/CPP/7zip/UI/FileManager/RootFolder.cpp @@ -2,32 +2,28 @@ #include "StdAfx.h" -#include "resource.h" +#include "Common/StringConvert.h" -#include "RootFolder.h" +#include "Windows/PropVariant.h" -#include "Common/StringConvert.h" #include "../../PropID.h" -#include "Windows/Defs.h" -#include "Windows/PropVariant.h" #include "FSDrives.h" -#include "PhysDriveFolder.h" +#include "FSFolder.h" +#include "LangUtils.h" #include "NetFolder.h" +#include "RootFolder.h" #include "SysIconUtils.h" -#include "LangUtils.h" -using namespace NWindows; +#include "resource.h" +using namespace NWindows; -static const STATPROPSTG kProperties[] = +static const STATPROPSTG kProps[] = { { NULL, kpidName, VT_BSTR} }; -// static const wchar_t *kMyComputerTitle = L"Computer"; -// static const wchar_t *kMyNetworkTitle = L"Network"; - UString RootFolder_GetName_Computer(int &iconIndex) { iconIndex = GetIconIndexForCSIDL(CSIDL_DRIVES); @@ -49,12 +45,17 @@ UString RootFolder_GetName_Documents(int &iconIndex) const int ROOT_INDEX_COMPUTER = 0; const int ROOT_INDEX_DOCUMENTS = 1; const int ROOT_INDEX_NETWORK = 2; +const int ROOT_INDEX_VOLUMES = 3; + +static const wchar_t *kVolPrefix = L"\\\\.\\"; void CRootFolder::Init() { _names[ROOT_INDEX_COMPUTER] = RootFolder_GetName_Computer(_iconIndices[ROOT_INDEX_COMPUTER]); _names[ROOT_INDEX_DOCUMENTS] = RootFolder_GetName_Documents(_iconIndices[ROOT_INDEX_DOCUMENTS]); _names[ROOT_INDEX_NETWORK] = RootFolder_GetName_Network(_iconIndices[ROOT_INDEX_NETWORK]); + _names[ROOT_INDEX_VOLUMES] = kVolPrefix; + _iconIndices[ROOT_INDEX_VOLUMES] = GetIconIndexForCSIDL(CSIDL_DRIVES); }; STDMETHODIMP CRootFolder::LoadItems() @@ -109,19 +110,19 @@ UString GetMyDocsPath() STDMETHODIMP CRootFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder) { - if (index == ROOT_INDEX_COMPUTER) + *resultFolder = NULL; + CMyComPtr<IFolderFolder> subFolder; + if (index == ROOT_INDEX_COMPUTER || index == ROOT_INDEX_VOLUMES) { CFSDrives *fsDrivesSpec = new CFSDrives; - CMyComPtr<IFolderFolder> subFolder = fsDrivesSpec; - fsDrivesSpec->Init(); - *resultFolder = subFolder.Detach(); + subFolder = fsDrivesSpec; + fsDrivesSpec->Init(index == ROOT_INDEX_VOLUMES); } else if (index == ROOT_INDEX_NETWORK) { CNetFolder *netFolderSpec = new CNetFolder; - CMyComPtr<IFolderFolder> subFolder = netFolderSpec; + subFolder = netFolderSpec; netFolderSpec->Init(0, 0, _names[ROOT_INDEX_NETWORK] + WCHAR_PATH_SEPARATOR); - *resultFolder = subFolder.Detach(); } else if (index == ROOT_INDEX_DOCUMENTS) { @@ -129,13 +130,13 @@ STDMETHODIMP CRootFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolde if (!s.IsEmpty()) { NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder; - CMyComPtr<IFolderFolder> subFolder = fsFolderSpec; + subFolder = fsFolderSpec; RINOK(fsFolderSpec->Init(s, NULL)); - *resultFolder = subFolder.Detach(); } } else return E_INVALIDARG; + *resultFolder = subFolder.Detach(); return S_OK; } @@ -178,11 +179,11 @@ STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resu CMyComPtr<IFolderFolder> subFolder; - if (name2.Left(4) == L"\\\\.\\") + if (name2.Left(4) == kVolPrefix) { - CPhysDriveFolder *folderSpec = new CPhysDriveFolder; + CFSDrives *folderSpec = new CFSDrives; subFolder = folderSpec; - RINOK(folderSpec->Init(name2.Mid(4, 2))); + folderSpec->Init(true); } else { @@ -212,23 +213,7 @@ STDMETHODIMP CRootFolder::BindToParentFolder(IFolderFolder **resultFolder) return S_OK; } -STDMETHODIMP CRootFolder::GetNumberOfProperties(UInt32 *numProperties) -{ - *numProperties = sizeof(kProperties) / sizeof(kProperties[0]); - return S_OK; -} - -STDMETHODIMP CRootFolder::GetPropertyInfo(UInt32 index, - BSTR *name, PROPID *propID, VARTYPE *varType) -{ - if (index >= sizeof(kProperties) / sizeof(kProperties[0])) - return E_INVALIDARG; - const STATPROPSTG &prop = kProperties[index]; - *propID = prop.propid; - *varType = prop.vt; - *name = 0; - return S_OK; -} +IMP_IFolderFolder_Props(CRootFolder) STDMETHODIMP CRootFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) { @@ -242,7 +227,7 @@ STDMETHODIMP CRootFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) return S_OK; } -STDMETHODIMP CRootFolder::GetSystemIconIndex(UInt32 index, INT32 *iconIndex) +STDMETHODIMP CRootFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex) { *iconIndex = _iconIndices[index]; return S_OK; diff --git a/CPP/7zip/UI/FileManager/RootFolder.h b/CPP/7zip/UI/FileManager/RootFolder.h index f17a0783..9f08e601 100755 --- a/CPP/7zip/UI/FileManager/RootFolder.h +++ b/CPP/7zip/UI/FileManager/RootFolder.h @@ -1,34 +1,27 @@ // RootFolder.h -#ifndef __ROOTFOLDER_H -#define __ROOTFOLDER_H +#ifndef __ROOT_FOLDER_H +#define __ROOT_FOLDER_H #include "Common/MyString.h" -#include "Windows/PropVariant.h" +#include "IFolder.h" -#include "FSFolder.h" - -const int kNumRootFolderItems = 3; +const int kNumRootFolderItems = 4; class CRootFolder: public IFolderFolder, public IFolderGetSystemIconIndex, public CMyUnknownImp { -public: - MY_UNKNOWN_IMP1( - IFolderGetSystemIconIndex - ) + UString _names[kNumRootFolderItems]; + int _iconIndices[kNumRootFolderItems]; +public: + MY_UNKNOWN_IMP1(IFolderGetSystemIconIndex) INTERFACE_FolderFolder(;) - - STDMETHOD(GetSystemIconIndex)(UInt32 index, INT32 *iconIndex); - + STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex); void Init(); -private: - UString _names[kNumRootFolderItems]; - int _iconIndices[kNumRootFolderItems]; }; #endif diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.cpp b/CPP/7zip/UI/FileManager/SysIconUtils.cpp index 5af6f850..3e5de7aa 100755 --- a/CPP/7zip/UI/FileManager/SysIconUtils.cpp +++ b/CPP/7zip/UI/FileManager/SysIconUtils.cpp @@ -131,10 +131,7 @@ int CExtToIconMap::GetIconIndex(UINT32 attributes, const UString &fileNameSpec, { fileName = L"__File__"; if (_noExtIconIndex < 0) - { - int iconIndexTemp; - GetRealIconIndex(fileName, attributes, iconIndexTemp, _noExtTypeName); - } + GetRealIconIndex(fileName, attributes, _noExtIconIndex, _noExtTypeName); typeName = _noExtTypeName; return _noExtIconIndex; } diff --git a/CPP/7zip/UI/FileManager/SystemPage.cpp b/CPP/7zip/UI/FileManager/SystemPage.cpp index f8605ea8..1cd7ce15 100755 --- a/CPP/7zip/UI/FileManager/SystemPage.cpp +++ b/CPP/7zip/UI/FileManager/SystemPage.cpp @@ -52,7 +52,7 @@ bool CSystemPage::OnInit() _listViewExt.SetExtendedListViewStyle(newFlags, newFlags); _listViewPlugins.SetExtendedListViewStyle(newFlags, newFlags); - _listViewExt.InsertColumn(0, LangString(IDS_PROPERTY_EXTENSION, 0x02000205), 70); + _listViewExt.InsertColumn(0, LangString(IDS_PROP_EXTENSION, 0x02000205), 70); const UString s = LangString(IDS_PLUGIN, 0x03010310); _listViewExt.InsertColumn(1, s, 70); diff --git a/CPP/7zip/UI/FileManager/SystemPage.rc b/CPP/7zip/UI/FileManager/SystemPage.rc index 1cf9405f..9b4e808d 100755 --- a/CPP/7zip/UI/FileManager/SystemPage.rc +++ b/CPP/7zip/UI/FileManager/SystemPage.rc @@ -1,12 +1,11 @@ #include "SystemPageRes.h" #include "../../GuiCommon.rc" -#define xSize2 238 -#define ySize2 214 +#define xSize2 196 +#define ySize2 200 #define xSize (xSize2 + marg + marg) #define ySize (ySize2 + marg + marg) -#define gSpace 30 -#define g0Size 160 +#define g0Size xSize2 #define gYSize (ySize2 - 20 - bYSize) diff --git a/CPP/7zip/UI/FileManager/TextPairs.cpp b/CPP/7zip/UI/FileManager/TextPairs.cpp index 74df1c62..cc57c0d5 100755 --- a/CPP/7zip/UI/FileManager/TextPairs.cpp +++ b/CPP/7zip/UI/FileManager/TextPairs.cpp @@ -1,28 +1,20 @@ -// Common/TextPairs.cpp +// TextPairs.cpp #include "StdAfx.h" #include "TextPairs.h" -#include "Common/Defs.h" -#include "Common/UTFConvert.h" - static const wchar_t kNewLineChar = '\n'; +static const wchar_t kQuoteChar = '\"'; -static const wchar_t kSpaceChar = ' '; -static const wchar_t kTabChar = '\t'; - -static const wchar_t kQuoteChar = '\"'; -static const wchar_t kEndOfLine = '\0'; - -static const wchar_t kBOM = wchar_t(0xFEFF); +static const wchar_t kBOM = (wchar_t)0xFEFF; static bool IsSeparatorChar(wchar_t c) { - return (c == kSpaceChar || c == kTabChar); + return (c == ' ' || c == '\t'); } -void RemoveCr(UString &s) +static void RemoveCr(UString &s) { s.Replace(L"\x0D", L""); } @@ -34,7 +26,7 @@ static UString GetIDString(const wchar_t *srcString, int &finishPos) for (finishPos = 0;;) { wchar_t c = srcString[finishPos]; - if (c == kEndOfLine) + if (c == 0) break; finishPos++; bool isSeparatorChar = IsSeparatorChar(c); @@ -57,7 +49,7 @@ static UString GetValueString(const wchar_t *srcString, int &finishPos) for (finishPos = 0;;) { wchar_t c = srcString[finishPos]; - if (c == kEndOfLine) + if (c == 0) break; finishPos++; if (c == kNewLineChar) @@ -99,42 +91,22 @@ static bool GetTextPairs(const UString &srcString, CObjectVector<CTextPair> &pai return true; } -int FindItem(const CObjectVector<CTextPair> &pairs, const UString &id) -{ - for (int i = 0; i < pairs.Size(); i++) - if (pairs[i].ID.CompareNoCase(id) == 0) - return i; - return -1; -} - -UString GetTextConfigValue(const CObjectVector<CTextPair> &pairs, const UString &id) -{ - int index = FindItem(pairs, id); - if (index < 0) - return UString(); - return pairs[index].Value; -} - static int ComparePairIDs(const UString &s1, const UString &s2) { return s1.CompareNoCase(s2); } static int ComparePairItems(const CTextPair &p1, const CTextPair &p2) { return ComparePairIDs(p1.ID, p2.ID); } -// typedef void* MY_PVOID; - -// static int ComparePairItems(const MY_PVOID *a1, const MY_PVOID *a2, void *param) static int ComparePairItems(void *const *a1, void *const *a2, void * /* param */) { return ComparePairItems(**(const CTextPair **)a1, **(const CTextPair **)a2); } -void CPairsStorage::Sort() - { Pairs.Sort(ComparePairItems, 0); } +void CPairsStorage::Sort() { Pairs.Sort(ComparePairItems, 0); } int CPairsStorage::FindID(const UString &id, int &insertPos) { int left = 0, right = Pairs.Size(); while (left != right) { - UINT32 mid = (left + right) / 2; + int mid = (left + right) / 2; int compResult = ComparePairIDs(id, Pairs[mid].ID); if (compResult == 0) return mid; diff --git a/CPP/7zip/UI/FileManager/TextPairs.h b/CPP/7zip/UI/FileManager/TextPairs.h index b75d9c72..2670e030 100755 --- a/CPP/7zip/UI/FileManager/TextPairs.h +++ b/CPP/7zip/UI/FileManager/TextPairs.h @@ -1,7 +1,7 @@ -// Common/TextPairs.h +// TextPairs.h -#ifndef __COMMON_TEXTPAIRS_H -#define __COMMON_TEXTPAIRS_H +#ifndef __FM_TEXT_PAIRS_H +#define __FM_TEXT_PAIRS_H #include "Common/MyString.h" diff --git a/CPP/7zip/UI/FileManager/UpdateCallback100.cpp b/CPP/7zip/UI/FileManager/UpdateCallback100.cpp index e23c7d34..3701d2bb 100755 --- a/CPP/7zip/UI/FileManager/UpdateCallback100.cpp +++ b/CPP/7zip/UI/FileManager/UpdateCallback100.cpp @@ -1,17 +1,10 @@ -// UpdateCallback.h +// UpdateCallback100.cpp #include "StdAfx.h" -#include "Common/StringConvert.h" - -#include "UpdateCallback100.h" -// #include "Windows/ProcessMessages.h" -// #include "Resource/PasswordDialog/PasswordDialog.h" #include "MessagesDialog.h" - -#include "Common/Defs.h" - -using namespace NWindows; +#include "PasswordDialog.h" +#include "UpdateCallback100.h" CUpdateCallback100Imp::~CUpdateCallback100Imp() { @@ -81,19 +74,10 @@ STDMETHODIMP CUpdateCallback100Imp::UpdateErrorMessage(const wchar_t *message) STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { + *password = NULL; *passwordIsDefined = BoolToInt(_passwordIsDefined); if (!_passwordIsDefined) - { return S_OK; - /* - CPasswordDialog dialog; - if (dialog.Create(_parentWindow) == IDCANCEL) - return E_ABORT; - _password = dialog._password; - _passwordIsDefined = true; - */ - } - *passwordIsDefined = BoolToInt(_passwordIsDefined); return StringToBstr(_password, password); } @@ -109,7 +93,14 @@ STDMETHODIMP CUpdateCallback100Imp::SetCompleted(const UInt64 * /* files */, con STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword(BSTR *password) { + *password = NULL; if (!_passwordIsDefined) - return S_FALSE; + { + CPasswordDialog dialog; + if (dialog.Create(_parentWindow) == IDCANCEL) + return E_ABORT; + _password = dialog.Password; + _passwordIsDefined = true; + } return StringToBstr(_password, password); } diff --git a/CPP/7zip/UI/FileManager/ViewSettings.cpp b/CPP/7zip/UI/FileManager/ViewSettings.cpp index 6c611dad..0f98c217 100755 --- a/CPP/7zip/UI/FileManager/ViewSettings.cpp +++ b/CPP/7zip/UI/FileManager/ViewSettings.cpp @@ -297,8 +297,8 @@ UInt32 ReadToolbarsMask() static UString GetPanelPathName(UInt32 panelIndex) { - WCHAR panelString[32]; - ConvertUInt64ToString(panelIndex, panelString); + WCHAR panelString[16]; + ConvertUInt32ToString(panelIndex, panelString); return UString(kPanelPathValueName) + panelString; } diff --git a/CPP/7zip/UI/FileManager/makefile b/CPP/7zip/UI/FileManager/makefile index 86bdd85f..fea2d39a 100755 --- a/CPP/7zip/UI/FileManager/makefile +++ b/CPP/7zip/UI/FileManager/makefile @@ -5,6 +5,7 @@ CFLAGS = $(CFLAGS) -I ../../../ \ -DWIN_LONG_PATH \ -DNEW_FOLDER_INTERFACE \ -DEXTERNAL_CODECS \ + -DSUPPORT_DEVICE_FILE \ FM_OBJS = \ $O\App.obj \ @@ -38,7 +39,6 @@ FM_OBJS = \ $O\PanelSelect.obj \ $O\PanelSort.obj \ $O\PanelSplitFile.obj \ - $O\PhysDriveFolder.obj \ $O\ProgramLocation.obj \ $O\PropertyName.obj \ $O\RegistryAssociations.obj \ @@ -85,7 +85,6 @@ WIN_OBJS = \ $O\CommonDialog.obj \ $O\DLL.obj \ $O\Error.obj \ - $O\FileDevice.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ @@ -138,6 +137,9 @@ UI_COMMON_OBJS = \ $O\WorkDir.obj \ $O\ZipRegistry.obj \ +AR_COMMON_OBJS = \ + $O\OutStreamWithCRC.obj \ + AGENT_OBJS = \ $O\Agent.obj \ $O\AgentOut.obj \ @@ -163,6 +165,7 @@ OBJS = \ $(WIN_CTRL_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(UI_COMMON_OBJS) \ + $(AR_COMMON_OBJS) \ $(AGENT_OBJS) \ $O\CopyCoder.obj \ $(CRC_OBJS) \ @@ -183,6 +186,8 @@ $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(UI_COMMON_OBJS): ../Common/$(*B).cpp $(COMPL) +$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp + $(COMPL) $(AGENT_OBJS): ../Agent/$(*B).cpp $(COMPL) diff --git a/CPP/7zip/UI/FileManager/resource.h b/CPP/7zip/UI/FileManager/resource.h index edd351b6..72121c89 100755 --- a/CPP/7zip/UI/FileManager/resource.h +++ b/CPP/7zip/UI/FileManager/resource.h @@ -17,6 +17,7 @@ #define IDM_FILE_PROPERTIES 240 #define IDM_FILE_COMMENT 241 #define IDM_FILE_CRC 242 +#define IDM_FILE_DIFF 243 #define IDM_CREATE_FOLDER 250 #define IDM_CREATE_FILE 251 #define IDM_EDIT_CUT 320 @@ -128,12 +129,12 @@ #define IDS_BUTTON_MOVE 2421 #define IDS_BUTTON_DELETE 2422 #define IDS_BUTTON_INFO 2423 -#define IDS_PROPERTY_TOTAL_SIZE 3100 -#define IDS_PROPERTY_FREE_SPACE 3101 -#define IDS_PROPERTY_CLUSTER_SIZE 3102 -#define IDS_PROPERTY_VOLUME_NAME 3103 -#define IDS_PROPERTY_LOCAL_NAME 3200 -#define IDS_PROPERTY_PROVIDER 3201 +#define IDS_PROP_TOTAL_SIZE 3100 +#define IDS_PROP_FREE_SPACE 3101 +#define IDS_PROP_CLUSTER_SIZE 3102 +#define IDS_PROP_VOLUME_NAME 3103 +#define IDS_PROP_LOCAL_NAME 3200 +#define IDS_PROP_PROVIDER 3201 #define IDS_OPTIONS 4000 #define IDS_COMMENT 4001 #define IDS_COMMENT2 4002 diff --git a/CPP/7zip/UI/FileManager/resource.rc b/CPP/7zip/UI/FileManager/resource.rc index 3ec3bb32..cdfed0b6 100755 --- a/CPP/7zip/UI/FileManager/resource.rc +++ b/CPP/7zip/UI/FileManager/resource.rc @@ -34,6 +34,7 @@ BEGIN MENUITEM "P&roperties\tAlt+Enter", IDM_FILE_PROPERTIES MENUITEM "Comme&nt\tCtrl+Z", IDM_FILE_COMMENT MENUITEM "Calculate checksum", IDM_FILE_CRC + MENUITEM "Di&ff", IDM_FILE_DIFF MENUITEM SEPARATOR MENUITEM "Create Folder\tF7", IDM_CREATE_FOLDER MENUITEM "Create File\tCtrl+N", IDM_CREATE_FILE @@ -190,12 +191,12 @@ BEGIN IDS_FOLDERS_COLON "Folders:" IDS_SIZE_COLON "Size:" - IDS_PROPERTY_TOTAL_SIZE "Total Size" - IDS_PROPERTY_FREE_SPACE "Free Space" - IDS_PROPERTY_CLUSTER_SIZE "Cluster Size" - IDS_PROPERTY_VOLUME_NAME "Label" - IDS_PROPERTY_LOCAL_NAME "Local Name" - IDS_PROPERTY_PROVIDER "Provider" + IDS_PROP_TOTAL_SIZE "Total Size" + IDS_PROP_FREE_SPACE "Free Space" + IDS_PROP_CLUSTER_SIZE "Cluster Size" + IDS_PROP_VOLUME_NAME "Label" + IDS_PROP_LOCAL_NAME "Local Name" + IDS_PROP_PROVIDER "Provider" IDS_OPTIONS "Options" IDS_COMMENT "Comment" IDS_COMMENT2 "&Comment:" diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp index 64ee31d8..04a40a43 100755 --- a/CPP/7zip/UI/GUI/CompressDialog.cpp +++ b/CPP/7zip/UI/GUI/CompressDialog.cpp @@ -2,19 +2,19 @@ #include "StdAfx.h" -#include "resource.h" #include "Common/Defs.h" -#include "Common/StringConvert.h" #include "Common/IntToString.h" +#include "Common/StringConvert.h" + #include "Windows/CommonDialog.h" #include "Windows/FileDir.h" #include "Windows/FileName.h" #include "Windows/ResourceString.h" #include "Windows/System.h" +#include "../FileManager/FormatUtils.h" #include "../FileManager/HelpUtils.h" #include "../FileManager/SplitUtils.h" -#include "../FileManager/FormatUtils.h" #include "../Explorer/MyMessages.h" @@ -22,6 +22,8 @@ #include "CompressDialog.h" +#include "resource.h" + #ifndef _UNICODE extern bool g_IsNT; #endif @@ -112,6 +114,7 @@ enum EMethodID { kCopy, kLZMA, + kLZMA2, kPPMd, kBZip2, kDeflate, @@ -122,6 +125,7 @@ static const LPCWSTR kMethodsNames[] = { L"Copy", L"LZMA", + L"LZMA2", L"PPMd", L"BZip2", L"Deflate", @@ -131,6 +135,7 @@ static const LPCWSTR kMethodsNames[] = static const EMethodID g_7zMethods[] = { kLZMA, + kLZMA2, kPPMd, kBZip2 }; @@ -139,6 +144,7 @@ static const EMethodID g_7zSfxMethods[] = { kCopy, kLZMA, + kLZMA2, kPPMd }; @@ -160,6 +166,11 @@ static EMethodID g_BZip2Methods[] = kBZip2 }; +static EMethodID g_XzMethods[] = +{ + kLZMA2 +}; + struct CFormatInfo { LPCWSTR Name; @@ -206,7 +217,13 @@ static const CFormatInfo g_Formats[] = L"BZip2", (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), METHODS_PAIR(g_BZip2Methods), - false, false, true, false, false + false, false, true, false, false, false + }, + { + L"xz", + (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), + METHODS_PAIR(g_XzMethods), + false, false, true, false, false, false }, { L"Tar", @@ -273,20 +290,23 @@ bool CCompressDialog::OnInit() Info.ArchiverInfoIndex = 0; int i; - for(i = 0; i < m_ArchiverInfoList.Size(); i++) + for (i = 0; i < m_ArchiverInfoList.Size(); i++) { const CArcInfoEx &ai = m_ArchiverInfoList[i]; - m_Format.AddString(ai.Name); - if (ai.Name.CompareNoCase(m_RegistryInfo.ArchiveType) == 0) + int index = (int)m_Format.AddString(ai.Name); + m_Format.SetItemData(index, i); + if (ai.Name.CompareNoCase(m_RegistryInfo.ArchiveType) == 0 || i == 0) + { + m_Format.SetCurSel(index); Info.ArchiverInfoIndex = i; + } } - m_Format.SetCurSel(Info.ArchiverInfoIndex); SetArchiveName(Info.ArchiveName); SetLevel(); SetParams(); - for(i = 0; i < m_RegistryInfo.HistoryArchives.Size() && i < kHistorySize; i++) + for (i = 0; i < m_RegistryInfo.HistoryArchives.Size() && i < kHistorySize; i++) m_ArchivePath.AddString(m_RegistryInfo.HistoryArchives[i]); m_UpdateMode.AddString(LangString(IDS_COMPRESS_UPDATE_MODE_ADD, 0x02000DA1)); @@ -300,7 +320,7 @@ bool CCompressDialog::OnInit() SetNumThreads(); TCHAR s[40] = { TEXT('/'), TEXT(' '), 0 }; - ConvertUInt64ToString(NSystem::GetNumberOfProcessors(), s + 2); + ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2); SetItemText(IDC_COMPRESS_HARDWARE_THREADS, s); CheckButton(IDC_COMPRESS_SFX, Info.SFXMode); @@ -423,7 +443,7 @@ bool CCompressDialog::IsSFX() void CCompressDialog::OnButtonSFX() { - SetMethod(); + SetMethod(GetMethodID()); UString fileName; m_ArchivePath.GetText(fileName); @@ -431,8 +451,7 @@ void CCompressDialog::OnButtonSFX() int slashPos = fileName.ReverseFind(WCHAR_PATH_SEPARATOR); if (dotPos < 0 || dotPos <= slashPos) dotPos = -1; - bool isSFX = IsSFX(); - if (isSFX) + if (IsSFX()) { if (dotPos >= 0) fileName = fileName.Left(dotPos); @@ -545,7 +564,7 @@ void CCompressDialog::OnOK() Info.Method = GetMethodSpec(); Info.EncryptionMethod = GetEncryptionMethodSpec(); - Info.ArchiverInfoIndex = m_Format.GetCurSel(); + Info.ArchiverInfoIndex = GetFormatIndex(); Info.SFXMode = IsSFX(); Info.OpenShareForWrite = IsButtonCheckedBool(IDC_COMPRESS_SHARED); @@ -577,7 +596,7 @@ void CCompressDialog::OnOK() } } - for(int i = 0; i < m_ArchivePath.GetCount(); i++) + for (int i = 0; i < m_ArchivePath.GetCount(); i++) { UString sTemp; m_ArchivePath.GetLBText(i, sTemp); @@ -624,7 +643,7 @@ bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam) } case IDC_COMPRESS_COMBO_LEVEL: { - const CArcInfoEx &ai = m_ArchiverInfoList[m_Format.GetCurSel()]; + const CArcInfoEx &ai = m_ArchiverInfoList[GetFormatIndex()]; int index = FindRegistryFormatAlways(ai.Name); NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index]; fo.ResetForLevelChange(); @@ -697,7 +716,7 @@ void CCompressDialog::SetArchiveName2(bool prevWasSFX) void CCompressDialog::SetArchiveName(const UString &name) { UString fileName = name; - Info.ArchiverInfoIndex = m_Format.GetCurSel(); + Info.ArchiverInfoIndex = GetFormatIndex(); const CArcInfoEx &ai = m_ArchiverInfoList[Info.ArchiverInfoIndex]; m_PrevFormat = Info.ArchiverInfoIndex; if (ai.KeepName) @@ -750,7 +769,7 @@ int CCompressDialog::FindRegistryFormatAlways(const UString &name) int CCompressDialog::GetStaticFormatIndex() { - int formatIndex = m_Format.GetCurSel(); + int formatIndex = GetFormatIndex(); const CArcInfoEx &ai = m_ArchiverInfoList[formatIndex]; for (int i = 0; i < MY_SIZE_OF_ARRAY(g_Formats); i++) if (ai.Name.CompareNoCase(g_Formats[i].Name) == 0) @@ -774,7 +793,7 @@ void CCompressDialog::SetLevel() { m_Level.ResetContent(); const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; - const CArcInfoEx &ai = m_ArchiverInfoList[m_Format.GetCurSel()]; + const CArcInfoEx &ai = m_ArchiverInfoList[GetFormatIndex()]; int index = FindRegistryFormat(ai.Name); UInt32 level = kNormal; if (index >= 0) @@ -799,7 +818,7 @@ void CCompressDialog::SetLevel() SetMethod(); } -void CCompressDialog::SetMethod() +void CCompressDialog::SetMethod(int keepMethodId) { m_Method.ResetContent(); UInt32 level = GetLevel(); @@ -810,7 +829,7 @@ void CCompressDialog::SetMethod() return; } const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; - const CArcInfoEx &ai = m_ArchiverInfoList[m_Format.GetCurSel()]; + const CArcInfoEx &ai = m_ArchiverInfoList[GetFormatIndex()]; int index = FindRegistryFormat(ai.Name); UString defaultMethod; if (index >= 0) @@ -819,7 +838,8 @@ void CCompressDialog::SetMethod() defaultMethod = fo.Method; } bool isSfx = IsSFX(); - for(int m = 0; m < fi.NumMethods; m++) + bool weUseSameMethod = false; + for (int m = 0; m < fi.NumMethods; m++) { EMethodID methodID = fi.MathodIDs[m]; if (isSfx) @@ -827,23 +847,32 @@ void CCompressDialog::SetMethod() continue; const LPCWSTR method = kMethodsNames[methodID]; int itemIndex = (int)m_Method.AddString(GetSystemString(method)); - if (defaultMethod.CompareNoCase(method) == 0 || m == 0) + if (keepMethodId == methodID) + { m_Method.SetCurSel(itemIndex); + weUseSameMethod = true; + continue; + } + if ((defaultMethod.CompareNoCase(method) == 0 || m == 0) && !weUseSameMethod) + m_Method.SetCurSel(itemIndex); + } + if (!weUseSameMethod) + { + SetDictionary(); + SetOrder(); } - SetDictionary(); - SetOrder(); } bool CCompressDialog::IsZipFormat() { - const CArcInfoEx &ai = m_ArchiverInfoList[m_Format.GetCurSel()]; + const CArcInfoEx &ai = m_ArchiverInfoList[GetFormatIndex()]; return (ai.Name.CompareNoCase(L"zip") == 0); } void CCompressDialog::SetEncryptionMethod() { _encryptionMethod.ResetContent(); - const CArcInfoEx &ai = m_ArchiverInfoList[m_Format.GetCurSel()]; + const CArcInfoEx &ai = m_ArchiverInfoList[GetFormatIndex()]; if (ai.Name.CompareNoCase(L"7z") == 0) { _encryptionMethod.AddString(TEXT("AES-256")); @@ -903,7 +932,7 @@ int CCompressDialog::AddDictionarySize(UInt32 size, bool kilo, bool maga) else if (maga) sizePrint >>= 20; TCHAR s[40]; - ConvertUInt64ToString(sizePrint, s); + ConvertUInt32ToString(sizePrint, s); if (kilo) lstrcat(s, TEXT(" K")); else if (maga) @@ -931,7 +960,7 @@ int CCompressDialog::AddDictionarySize(UInt32 size) void CCompressDialog::SetDictionary() { m_Dictionary.ResetContent(); - const CArcInfoEx &ai = m_ArchiverInfoList[m_Format.GetCurSel()]; + const CArcInfoEx &ai = m_ArchiverInfoList[GetFormatIndex()]; int index = FindRegistryFormat(ai.Name); UInt32 defaultDictionary = UInt32(-1); if (index >= 0) @@ -948,6 +977,7 @@ void CCompressDialog::SetDictionary() switch (methodID) { case kLZMA: + case kLZMA2: { static const UInt32 kMinDicSize = (1 << 16); if (defaultDictionary == UInt32(-1)) @@ -1066,7 +1096,7 @@ UInt32 CCompressDialog::GetLevel2() int CCompressDialog::AddOrder(UInt32 size) { TCHAR s[40]; - ConvertUInt64ToString(size, s); + ConvertUInt32ToString(size, s); int index = (int)m_Order.AddString(s); m_Order.SetItemData(index, size); return index; @@ -1075,7 +1105,7 @@ int CCompressDialog::AddOrder(UInt32 size) void CCompressDialog::SetOrder() { m_Order.ResetContent(); - const CArcInfoEx &ai = m_ArchiverInfoList[m_Format.GetCurSel()]; + const CArcInfoEx &ai = m_ArchiverInfoList[GetFormatIndex()]; int index = FindRegistryFormat(ai.Name); UInt32 defaultOrder = UInt32(-1); if (index >= 0) @@ -1091,6 +1121,7 @@ void CCompressDialog::SetOrder() switch (methodID) { case kLZMA: + case kLZMA2: { if (defaultOrder == UInt32(-1)) defaultOrder = (level >= 7) ? 64 : 32; @@ -1193,7 +1224,7 @@ void CCompressDialog::SetSolidBlockSize() UInt32 defaultBlockSize = (UInt32)-1; - const CArcInfoEx &ai = m_ArchiverInfoList[m_Format.GetCurSel()]; + const CArcInfoEx &ai = m_ArchiverInfoList[GetFormatIndex()]; int index = FindRegistryFormat(ai.Name); if (index >= 0) { @@ -1211,7 +1242,7 @@ void CCompressDialog::SetSolidBlockSize() if (needSet && dictionary >= (((UInt64)1 << (i - 7))) && i <= 32) defaultBlockSize = i; TCHAR s[40]; - ConvertUInt64ToString(1 << (i % 10), s); + ConvertUInt32ToString(1 << (i % 10), s); if (i < 30) lstrcat(s, TEXT(" M")); else lstrcat(s, TEXT(" G")); lstrcat(s, TEXT("B")); @@ -1237,7 +1268,7 @@ void CCompressDialog::SetNumThreads() UInt32 numHardwareThreads = NSystem::GetNumberOfProcessors(); UInt32 defaultValue = numHardwareThreads; - const CArcInfoEx &ai = m_ArchiverInfoList[m_Format.GetCurSel()]; + const CArcInfoEx &ai = m_ArchiverInfoList[GetFormatIndex()]; int index = FindRegistryFormat(ai.Name); if (index >= 0) { @@ -1250,23 +1281,16 @@ void CCompressDialog::SetNumThreads() int methodID = GetMethodID(); switch (methodID) { - case kLZMA: - { - numAlgoThreadsMax = 2; - break; - } - case kBZip2: - { - numAlgoThreadsMax = 32; - break; - } + case kLZMA: numAlgoThreadsMax = 2; break; + case kLZMA2: numAlgoThreadsMax = 32; break; + case kBZip2: numAlgoThreadsMax = 32; break; } if (IsZipFormat()) numAlgoThreadsMax = 128; for (UInt32 i = 1; i <= numHardwareThreads * 2 && i <= numAlgoThreadsMax; i++) { TCHAR s[40]; - ConvertUInt64ToString(i, s); + ConvertUInt32ToString(i, s); int index = (int)m_NumThreads.AddString(s); m_NumThreads.SetItemData(index, (UInt32)i); } @@ -1298,9 +1322,11 @@ UInt64 CCompressDialog::GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemo if (numMainThreads > 1) size += (UInt64)numMainThreads << 25; } - switch (GetMethodID()) + int methidId = GetMethodID(); + switch (methidId) { case kLZMA: + case kLZMA2: { UInt32 hs = dictionary - 1; hs |= (hs >> 1); @@ -1313,7 +1339,7 @@ UInt64 CCompressDialog::GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemo hs >>= 1; hs++; UInt64 size1 = (UInt64)hs * 4; - size1 += (UInt64)dictionary * 11 / 2; + size1 += (UInt64)dictionary * 4; if (level >= 5) size1 += (UInt64)dictionary * 4; size1 += (2 << 20); @@ -1324,7 +1350,18 @@ UInt64 CCompressDialog::GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemo size1 += (2 << 20) + (4 << 20); numThreads1 = 2; } - size += size1 * numThreads / numThreads1; + UInt32 numBlockThreads = numThreads / numThreads1; + if (methidId == kLZMA || numBlockThreads == 1) + size1 += (UInt64)dictionary * 3 / 2; + else + { + UInt64 chunkSize = (UInt64)dictionary << 2; + chunkSize = MyMax(chunkSize, (UInt64)(1 << 20)); + chunkSize = MyMin(chunkSize, (UInt64)(1 << 28)); + chunkSize = MyMax(chunkSize, (UInt64)dictionary); + size1 += chunkSize * 2; + } + size += size1 * numBlockThreads; decompressMemory = dictionary + (2 << 20); return size; @@ -1363,7 +1400,7 @@ UInt64 CCompressDialog::GetMemoryUsage(UInt64 &decompressMemory) void CCompressDialog::PrintMemUsage(UINT res, UInt64 value) { - if (value == (UInt64)Int64(-1)) + if (value == (UInt64)(Int64)-1) { SetItemText(res, TEXT("?")); return; @@ -1385,7 +1422,7 @@ void CCompressDialog::SetMemoryUsage() void CCompressDialog::SetParams() { - const CArcInfoEx &ai = m_ArchiverInfoList[m_Format.GetCurSel()]; + const CArcInfoEx &ai = m_ArchiverInfoList[GetFormatIndex()]; m_Params.SetText(TEXT("")); int index = FindRegistryFormat(ai.Name); if (index >= 0) @@ -1411,3 +1448,8 @@ void CCompressDialog::SaveOptionsInMem() fo.NumThreads = GetNumThreadsSpec(); fo.BlockLogSize = GetBlockSizeSpec(); } + +int CCompressDialog::GetFormatIndex() +{ + return (int)m_Format.GetItemData(m_Format.GetCurSel()); +} diff --git a/CPP/7zip/UI/GUI/CompressDialog.h b/CPP/7zip/UI/GUI/CompressDialog.h index a88d472c..75eeeee8 100755 --- a/CPP/7zip/UI/GUI/CompressDialog.h +++ b/CPP/7zip/UI/GUI/CompressDialog.h @@ -1,15 +1,16 @@ // CompressDialog.h -#ifndef __COMPRESSDIALOG_H -#define __COMPRESSDIALOG_H - -#include "../Common/ZipRegistry.h" -#include "../Common/LoadCodecs.h" -#include "CompressDialogRes.h" +#ifndef __COMPRESS_DIALOG_H +#define __COMPRESS_DIALOG_H +#include "Windows/Control/ComboBox.h" #include "Windows/Control/Dialog.h" #include "Windows/Control/Edit.h" -#include "Windows/Control/ComboBox.h" + +#include "../Common/LoadCodecs.h" +#include "../Common/ZipRegistry.h" + +#include "CompressDialogRes.h" namespace NCompressDialog { @@ -107,7 +108,7 @@ class CCompressDialog: public NWindows::NControl::CModalDialog void SetLevel(); - void SetMethod(); + void SetMethod(int keepMethodId = -1); int GetMethodID(); UString GetMethodSpec(); UString GetEncryptionMethodSpec(); @@ -151,6 +152,8 @@ class CCompressDialog: public NWindows::NControl::CModalDialog void UpdatePasswordControl(); bool IsShowPasswordChecked() const { return IsButtonChecked(IDC_COMPRESS_CHECK_SHOW_PASSWORD) == BST_CHECKED; } + + int GetFormatIndex(); public: CObjectVector<CArcInfoEx> m_ArchiverInfoList; diff --git a/CPP/7zip/UI/GUI/CompressDialog.rc b/CPP/7zip/UI/GUI/CompressDialog.rc index 397a2756..8e79f1bf 100755 --- a/CPP/7zip/UI/GUI/CompressDialog.rc +++ b/CPP/7zip/UI/GUI/CompressDialog.rc @@ -58,7 +58,7 @@ BEGIN PUSHBUTTON "...", IDC_COMPRESS_BUTTON_SET_ARCHIVE, xSize - marg - bDotsSize, 17, bDotsSize, bYSize, WS_GROUP LTEXT "Archive &format:", IDC_STATIC_COMPRESS_FORMAT, marg, 41, g0XSize, 8 - COMBOBOX IDC_COMPRESS_COMBO_FORMAT, g1XPos, 39, g1XSize , 80,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_COMPRESS_COMBO_FORMAT, g1XPos, 39, g1XSize , 80,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP LTEXT "Compression &level:",IDC_STATIC_COMPRESS_LEVEL, marg, 62, g0XSize, 8 COMBOBOX IDC_COMPRESS_COMBO_LEVEL, g1XPos, 60, g1XSize, 80,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP diff --git a/CPP/7zip/UI/GUI/ExtractGUI.cpp b/CPP/7zip/UI/GUI/ExtractGUI.cpp index a03bd77a..95864d2c 100755 --- a/CPP/7zip/UI/GUI/ExtractGUI.cpp +++ b/CPP/7zip/UI/GUI/ExtractGUI.cpp @@ -2,26 +2,27 @@ #include "StdAfx.h" -#include "ExtractGUI.h" - -#include "Common/StringConvert.h" #include "Common/IntToString.h" +#include "Common/StringConvert.h" -#include "Windows/FileDir.h" #include "Windows/Error.h" +#include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/Thread.h" -#include "../FileManager/FormatUtils.h" #include "../FileManager/ExtractCallback.h" +#include "../FileManager/FormatUtils.h" #include "../FileManager/LangUtils.h" #include "../Common/ArchiveExtractCallback.h" +#include "../Common/PropIDUtils.h" + #include "../Explorer/MyMessages.h" + #include "resource.h" #include "ExtractRes.h" - #include "ExtractDialog.h" +#include "ExtractGUI.h" using namespace NWindows; @@ -198,6 +199,16 @@ HRESULT ExtractGUI( AddValuePair(IDS_FILES_COLON, 0x02000320, extracter.Stat.NumFiles, s); AddSizePair(IDS_SIZE_COLON, 0x02000322, extracter.Stat.UnpackSize, s); AddSizePair(IDS_COMPRESSED_COLON, 0x02000323, extracter.Stat.PackSize, s); + + if (options.CalcCrc) + { + wchar_t temp[16]; + ConvertUInt32ToHex(extracter.Stat.CrcSum, temp); + s += L"CRC: "; + s += temp; + s += L"\n"; + } + s += L"\n"; s += LangString(IDS_MESSAGE_NO_ERRORS, 0x02000608); @@ -209,5 +220,3 @@ HRESULT ExtractGUI( throw extracter.ErrorMessage; return extracter.Result; } - - diff --git a/CPP/7zip/UI/GUI/GUI.cpp b/CPP/7zip/UI/GUI/GUI.cpp index e1117188..3a1a633e 100755 --- a/CPP/7zip/UI/GUI/GUI.cpp +++ b/CPP/7zip/UI/GUI/GUI.cpp @@ -4,31 +4,27 @@ #include <initguid.h> -extern "C" -{ - #include "../../../../C/Alloc.h" -} +#include "../../../../C/Alloc.h" -#include "Common/NewHandler.h" -#include "Common/StringConvert.h" #include "Common/CommandLineParser.h" #include "Common/MyException.h" +#include "Common/StringConvert.h" #include "Windows/Error.h" #ifdef _WIN32 #include "Windows/MemoryLock.h" #endif -#include "../FileManager/StringUtils.h" - -#include "../Common/ExitCode.h" #include "../Common/ArchiveCommandLine.h" +#include "../Common/ExitCode.h" -#include "ExtractRes.h" +#include "../FileManager/StringUtils.h" +#include "BenchmarkDialog.h" #include "ExtractGUI.h" #include "UpdateGUI.h" -#include "BenchmarkDialog.h" + +#include "ExtractRes.h" using namespace NWindows; @@ -119,8 +115,12 @@ static int Main2() CExtractCallbackImp *ecs = new CExtractCallbackImp; CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; ecs->ProgressDialog.CompressingMode = false; + + #ifndef _NO_CRYPTO ecs->PasswordIsDefined = options.PasswordEnabled; ecs->Password = options.Password; + #endif + ecs->Init(); CExtractOptions eo; @@ -130,6 +130,7 @@ static int Main2() eo.OverwriteMode = options.OverwriteMode; eo.PathMode = options.Command.GetPathMode(); eo.TestMode = options.Command.IsTestMode(); + eo.CalcCrc = options.CalcCrc; #ifdef COMPRESS_MT eo.Properties = options.ExtractProperties; #endif @@ -146,14 +147,19 @@ static int Main2() } else if (options.Command.IsFromUpdateGroup()) { - bool passwordIsDefined = - options.PasswordEnabled && !options.Password.IsEmpty(); + #ifndef _NO_CRYPTO + bool passwordIsDefined = options.PasswordEnabled && !options.Password.IsEmpty(); + #endif CUpdateCallbackGUI callback; // callback.EnablePercents = options.EnablePercents; + + #ifndef _NO_CRYPTO callback.PasswordIsDefined = passwordIsDefined; callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty(); callback.Password = options.Password; + #endif + // callback.StdOutMode = options.UpdateOptions.StdOutMode; callback.Init(); diff --git a/CPP/7zip/UI/GUI/GUI.dsp b/CPP/7zip/UI/GUI/GUI.dsp index e5fbec0e..42c83c60 100755 --- a/CPP/7zip/UI/GUI/GUI.dsp +++ b/CPP/7zip/UI/GUI/GUI.dsp @@ -45,7 +45,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c -# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "COMPRESS_MT" /D "WIN_LONG_PATH" /D "EXTERNAL_LZMA" /D "EXTERNAL_CODECS" /D "BENCH_MT" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "COMPRESS_MT" /D "WIN_LONG_PATH" /D "EXTERNAL_LZMA" /D "EXTERNAL_CODECS" /D "BENCH_MT" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -72,7 +72,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c -# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "COMPRESS_MT" /D "WIN_LONG_PATH" /D "EXTERNAL_LZMA" /D "EXTERNAL_CODECS" /D "BENCH_MT" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "COMPRESS_MT" /D "WIN_LONG_PATH" /D "EXTERNAL_LZMA" /D "EXTERNAL_CODECS" /D "BENCH_MT" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" @@ -99,7 +99,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c -# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "COMPRESS_MT" /D "WIN_LONG_PATH" /D "EXTERNAL_LZMA" /D "EXTERNAL_CODECS" /D "BENCH_MT" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "COMPRESS_MT" /D "WIN_LONG_PATH" /D "EXTERNAL_LZMA" /D "EXTERNAL_CODECS" /D "BENCH_MT" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -127,7 +127,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c -# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "COMPRESS_MT" /D "WIN_LONG_PATH" /D "EXTERNAL_LZMA" /D "EXTERNAL_CODECS" /D "BENCH_MT" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "COMPRESS_MT" /D "WIN_LONG_PATH" /D "EXTERNAL_LZMA" /D "EXTERNAL_CODECS" /D "BENCH_MT" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" @@ -379,91 +379,63 @@ SOURCE=..\Explorer\MyMessages.h # Begin Group "Dialogs" # PROP Default_Filter "" -# Begin Group "Progress" - -# PROP Default_Filter "" # Begin Source File -SOURCE=..\FileManager\ProgressDialog2.cpp +SOURCE=.\BenchmarkDialog.cpp # End Source File # Begin Source File -SOURCE=..\FileManager\ProgressDialog2.h +SOURCE=.\BenchmarkDialog.h # End Source File -# End Group -# Begin Group "Messages" - -# PROP Default_Filter "" # Begin Source File -SOURCE=..\FileManager\MessagesDialog.cpp +SOURCE=.\CompressDialog.cpp # End Source File # Begin Source File -SOURCE=..\FileManager\MessagesDialog.h +SOURCE=.\CompressDialog.h # End Source File -# End Group -# Begin Group "Overwtite" - -# PROP Default_Filter "" # Begin Source File -SOURCE=..\FileManager\OverwriteDialog.cpp +SOURCE=.\ExtractDialog.cpp # End Source File # Begin Source File -SOURCE=..\FileManager\OverwriteDialog.h +SOURCE=.\ExtractDialog.h # End Source File -# End Group -# Begin Group "Password" - -# PROP Default_Filter "" # Begin Source File -SOURCE=..\FileManager\PasswordDialog.cpp +SOURCE=..\FileManager\MessagesDialog.cpp # End Source File # Begin Source File -SOURCE=..\FileManager\PasswordDialog.h +SOURCE=..\FileManager\MessagesDialog.h # End Source File -# End Group -# Begin Group "Compress Dialog" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\CompressDialog.cpp +SOURCE=..\FileManager\OverwriteDialog.cpp # End Source File # Begin Source File -SOURCE=.\CompressDialog.h +SOURCE=..\FileManager\OverwriteDialog.h # End Source File -# End Group -# Begin Group "Extract Dialog" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\ExtractDialog.cpp +SOURCE=..\FileManager\PasswordDialog.cpp # End Source File # Begin Source File -SOURCE=.\ExtractDialog.h +SOURCE=..\FileManager\PasswordDialog.h # End Source File -# End Group -# Begin Group "Benchmark Dialog" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\BenchmarkDialog.cpp +SOURCE=..\FileManager\ProgressDialog2.cpp # End Source File # Begin Source File -SOURCE=.\BenchmarkDialog.h +SOURCE=..\FileManager\ProgressDialog2.h # End Source File # End Group -# End Group # Begin Group "FM Common" # PROP Default_Filter "" @@ -962,5 +934,17 @@ SOURCE=..\..\..\Windows\Window.cpp SOURCE=..\..\..\Windows\Window.h # End Source File # End Group +# Begin Group "Archive Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\OutStreamWithCRC.h +# End Source File +# End Group # End Target # End Project diff --git a/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp b/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp index 10c0a798..07c74e9b 100755 --- a/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp +++ b/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp @@ -156,6 +156,7 @@ HRESULT CUpdateCallbackGUI::SetOperationResult(Int32 /* operationResult */) HRESULT CUpdateCallbackGUI::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { + *password = NULL; if (!PasswordIsDefined) { if (AskPassword) @@ -171,6 +172,20 @@ HRESULT CUpdateCallbackGUI::CryptoGetTextPassword2(Int32 *passwordIsDefined, BST return StringToBstr(Password, password); } +HRESULT CUpdateCallbackGUI::CryptoGetTextPassword(BSTR *password) +{ + *password = NULL; + if (!PasswordIsDefined) + { + CPasswordDialog dialog; + if (dialog.Create(ProgressDialog) == IDCANCEL) + return E_ABORT; + Password = dialog.Password; + PasswordIsDefined = true; + } + return StringToBstr(Password, password); +} + /* It doesn't work, since main stream waits Dialog HRESULT CUpdateCallbackGUI::CloseProgress() diff --git a/CPP/7zip/UI/GUI/UpdateGUI.cpp b/CPP/7zip/UI/GUI/UpdateGUI.cpp index ef9a2d70..2d4dbbc2 100755 --- a/CPP/7zip/UI/GUI/UpdateGUI.cpp +++ b/CPP/7zip/UI/GUI/UpdateGUI.cpp @@ -4,32 +4,28 @@ #include "UpdateGUI.h" -#include "resource.h" -#include "Common/StringConvert.h" #include "Common/IntToString.h" +#include "Common/StringConvert.h" #include "Common/StringToInt.h" -#include "Windows/FileDir.h" #include "Windows/Error.h" -#include "Windows/FileFind.h" +#include "Windows/FileDir.h" #include "Windows/Thread.h" -#include "../FileManager/FormatUtils.h" -#include "../FileManager/ExtractCallback.h" -#include "../FileManager/StringUtils.h" - -#include "../Common/ArchiveExtractCallback.h" #include "../Common/WorkDir.h" + #include "../Explorer/MyMessages.h" -#include "ExtractRes.h" + +#include "../FileManager/StringUtils.h" #include "CompressDialog.h" #include "UpdateGUI.h" +#include "resource.h" + using namespace NWindows; using namespace NFile; -// static const wchar_t *kIncorrectOutDir = L"Incorrect output directory path"; static const wchar_t *kDefaultSfxModule = L"7z.sfx"; static const wchar_t *kSFXExtension = L"exe"; @@ -242,7 +238,7 @@ static HRESULT ShowDialog( name += WCHAR_PATH_SEPARATOR; name += item.PathParts[i]; } - if (NFind::FindFile(name, fileInfo)) + if (fileInfo.Find(name)) { if (censor.Pairs.Size() == 1 && pair.Head.IncludeItems.Size() == 1) oneFile = !fileInfo.IsDir(); @@ -355,7 +351,7 @@ static HRESULT ShowDialog( UString fullPath; NDirectory::MyGetFullPathName(di.ArchiveName, fullPath); options.WorkingDir = GetWorkDir(workDirInfo, fullPath); - NFile::NDirectory::CreateComplexDirectory(options.WorkingDir); + NDirectory::CreateComplexDirectory(options.WorkingDir); } return S_OK; } diff --git a/CPP/7zip/UI/GUI/makefile b/CPP/7zip/UI/GUI/makefile index b92935ab..233e2ee2 100755 --- a/CPP/7zip/UI/GUI/makefile +++ b/CPP/7zip/UI/GUI/makefile @@ -8,6 +8,7 @@ CFLAGS = $(CFLAGS) -I ../../../ \ -DEXTERNAL_CODECS \ -DBENCH_MT \ -D_7ZIP_LARGE_PAGES \ + -DSUPPORT_DEVICE_FILE \ GUI_OBJS = \ $O\BenchmarkDialog.obj \ @@ -85,6 +86,9 @@ UI_COMMON_OBJS = \ $O\WorkDir.obj \ $O\ZipRegistry.obj \ +AR_COMMON_OBJS = \ + $O\OutStreamWithCRC.obj \ + LZMA_BENCH_OBJS = \ $O\LzmaBench.obj \ @@ -117,6 +121,7 @@ OBJS = \ $(WIN_CTRL_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(UI_COMMON_OBJS) \ + $(AR_COMMON_OBJS) \ $(FM_OBJS)\ $O\MyMessages.obj \ $O\CopyCoder.obj \ @@ -139,6 +144,8 @@ $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(UI_COMMON_OBJS): ../Common/$(*B).cpp $(COMPL) +$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp + $(COMPL) $(FM_OBJS): ../FileManager/$(*B).cpp $(COMPL) $O\MyMessages.obj: ../Explorer/MyMessages.cpp diff --git a/CPP/Common/CRC.cpp b/CPP/Common/CRC.cpp index a1e54ec9..9a9f81fb 100755 --- a/CPP/Common/CRC.cpp +++ b/CPP/Common/CRC.cpp @@ -2,9 +2,6 @@ #include "StdAfx.h" -extern "C" -{ #include "../../C/7zCrc.h" -} struct CCRCTableInit { CCRCTableInit() { CrcGenerateTable(); } } g_CRCTableInit; diff --git a/CPP/Common/IntToString.cpp b/CPP/Common/IntToString.cpp index beda203d..31070b41 100755 --- a/CPP/Common/IntToString.cpp +++ b/CPP/Common/IntToString.cpp @@ -42,6 +42,9 @@ void ConvertUInt64ToString(UInt64 value, wchar_t *s) *s = L'\0'; } +void ConvertUInt32ToString(UInt32 value, char *s) { ConvertUInt64ToString(value, s); } +void ConvertUInt32ToString(UInt32 value, wchar_t *s) { ConvertUInt64ToString(value, s); } + void ConvertInt64ToString(Int64 value, char *s) { if (value < 0) diff --git a/CPP/Common/IntToString.h b/CPP/Common/IntToString.h index cf86090f..bad17e4a 100755 --- a/CPP/Common/IntToString.h +++ b/CPP/Common/IntToString.h @@ -1,15 +1,17 @@ // Common/IntToString.h -#ifndef __COMMON_INTTOSTRING_H -#define __COMMON_INTTOSTRING_H +#ifndef __COMMON_INT_TO_STRING_H +#define __COMMON_INT_TO_STRING_H #include <stddef.h> #include "Types.h" void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base = 10); void ConvertUInt64ToString(UInt64 value, wchar_t *s); - void ConvertInt64ToString(Int64 value, char *s); void ConvertInt64ToString(Int64 value, wchar_t *s); +void ConvertUInt32ToString(UInt32 value, char *s); +void ConvertUInt32ToString(UInt32 value, wchar_t *s); + #endif diff --git a/CPP/Common/MyXml.cpp b/CPP/Common/MyXml.cpp index 1d5d836a..8aa9ce8c 100755 --- a/CPP/Common/MyXml.cpp +++ b/CPP/Common/MyXml.cpp @@ -18,7 +18,7 @@ static bool IsSpaceChar(char c) return (c == ' ' || c == '\t' || c == 0x0D || c == 0x0A); } -#define SKEEP_SPACES(s, pos) while (IsSpaceChar(s[pos])) pos++; +#define SKIP_SPACES(s, pos) while (IsSpaceChar(s[pos])) pos++; static bool ReadProperty(const AString &s, int &pos, CXmlProp &prop) { @@ -35,11 +35,11 @@ static bool ReadProperty(const AString &s, int &pos, CXmlProp &prop) if (prop.Name.IsEmpty()) return false; - SKEEP_SPACES(s, pos); + SKIP_SPACES(s, pos); if (s[pos++] != '=') return false; - SKEEP_SPACES(s, pos); + SKIP_SPACES(s, pos); if (s[pos++] != '\"') return false; @@ -109,7 +109,7 @@ bool CXmlItem::ParseItems(const AString &s, int &pos, int numAllowedLevels) AString finishString = "</"; for (;;) { - SKEEP_SPACES(s, pos); + SKIP_SPACES(s, pos); if (s.Mid(pos, finishString.Length()) == finishString) return true; @@ -123,7 +123,7 @@ bool CXmlItem::ParseItems(const AString &s, int &pos, int numAllowedLevels) bool CXmlItem::ParseItem(const AString &s, int &pos, int numAllowedLevels) { - SKEEP_SPACES(s, pos); + SKIP_SPACES(s, pos); int pos2 = s.Find('<', pos); if (pos2 < 0) @@ -138,7 +138,7 @@ bool CXmlItem::ParseItem(const AString &s, int &pos, int numAllowedLevels) IsTag = true; pos++; - SKEEP_SPACES(s, pos); + SKIP_SPACES(s, pos); for (; pos < s.Length(); pos++) { @@ -153,11 +153,11 @@ bool CXmlItem::ParseItem(const AString &s, int &pos, int numAllowedLevels) int posTemp = pos; for (;;) { - SKEEP_SPACES(s, pos); + SKIP_SPACES(s, pos); if (s[pos] == '/') { pos++; - // SKEEP_SPACES(s, pos); + // SKIP_SPACES(s, pos); return (s[pos++] == '>'); } if (s[pos] == '>') @@ -181,16 +181,16 @@ bool CXmlItem::ParseItem(const AString &s, int &pos, int numAllowedLevels) } } -bool SkeepHeader(const AString &s, int &pos, const AString &startString, const AString &endString) +static bool SkipHeader(const AString &s, int &pos, const AString &startString, const AString &endString) { - SKEEP_SPACES(s, pos); + SKIP_SPACES(s, pos); if (s.Mid(pos, startString.Length()) == startString) { pos = s.Find(endString, pos); if (pos < 0) return false; pos += endString.Length(); - SKEEP_SPACES(s, pos); + SKIP_SPACES(s, pos); } return true; } @@ -198,12 +198,12 @@ bool SkeepHeader(const AString &s, int &pos, const AString &startString, const A bool CXml::Parse(const AString &s) { int pos = 0; - if (!SkeepHeader(s, pos, "<?xml", "?>")) + if (!SkipHeader(s, pos, "<?xml", "?>")) return false; - if (!SkeepHeader(s, pos, "<!DOCTYPE", ">")) + if (!SkipHeader(s, pos, "<!DOCTYPE", ">")) return false; if (!Root.ParseItem(s, pos, 1000)) return false; - SKEEP_SPACES(s, pos); + SKIP_SPACES(s, pos); return (pos == s.Length() && Root.IsTag); } diff --git a/CPP/Common/StdInStream.cpp b/CPP/Common/StdInStream.cpp index b3d00920..f3dcb85f 100755 --- a/CPP/Common/StdInStream.cpp +++ b/CPP/Common/StdInStream.cpp @@ -3,7 +3,10 @@ #include "StdAfx.h" #include <tchar.h> + #include "StdInStream.h" +#include "StringConvert.h" +#include "UTFConvert.h" #ifdef _MSC_VER // "was declared deprecated" disabling @@ -19,6 +22,8 @@ static const char *kIllegalCharMessage = "Illegal character in input stream"; static LPCTSTR kFileOpenMode = TEXT("r"); +extern int g_CodePage; + CStdInStream g_StdIn(stdin); bool CStdInStream::Open(LPCTSTR fileName) @@ -42,14 +47,18 @@ CStdInStream::~CStdInStream() Close(); } -AString CStdInStream::ScanStringUntilNewLine() +AString CStdInStream::ScanStringUntilNewLine(bool allowEOF) { AString s; for (;;) { int intChar = GetChar(); if (intChar == EOF) + { + if (allowEOF) + break; throw kEOFMessage; + } char c = char(intChar); if (c == kIllegalChar) throw kIllegalCharMessage; @@ -60,6 +69,20 @@ AString CStdInStream::ScanStringUntilNewLine() return s; } +UString CStdInStream::ScanUStringUntilNewLine() +{ + AString s = ScanStringUntilNewLine(true); + int codePage = g_CodePage; + if (codePage == -1) + codePage = CP_OEMCP; + UString dest; + if (codePage == CP_UTF8) + ConvertUTF8ToUnicode(s, dest); + else + dest = MultiByteToUnicodeString(s, (UINT)codePage); + return dest; +} + void CStdInStream::ReadToString(AString &resultString) { resultString.Empty(); diff --git a/CPP/Common/StdInStream.h b/CPP/Common/StdInStream.h index 4b08c7c5..0d182cc3 100755 --- a/CPP/Common/StdInStream.h +++ b/CPP/Common/StdInStream.h @@ -19,8 +19,9 @@ public: bool Open(LPCTSTR fileName); bool Close(); - AString ScanStringUntilNewLine(); + AString ScanStringUntilNewLine(bool allowEOF = false); void ReadToString(AString &resultString); + UString ScanUStringUntilNewLine(); bool Eof(); int GetChar(); diff --git a/CPP/Common/StdOutStream.cpp b/CPP/Common/StdOutStream.cpp index b93e255f..061a7606 100755 --- a/CPP/Common/StdOutStream.cpp +++ b/CPP/Common/StdOutStream.cpp @@ -4,9 +4,10 @@ #include <tchar.h> -#include "StdOutStream.h" #include "IntToString.h" +#include "StdOutStream.h" #include "StringConvert.h" +#include "UTFConvert.h" #ifdef _MSC_VER // "was declared deprecated" disabling @@ -17,6 +18,8 @@ static const char kNewLineChar = '\n'; static const char *kFileOpenMode = "wt"; +extern int g_CodePage; + CStdOutStream g_StdOut(stdout); CStdOutStream g_StdErr(stderr); @@ -60,15 +63,23 @@ CStdOutStream & endl(CStdOutStream & outStream) return outStream << kNewLineChar; } -CStdOutStream & CStdOutStream::operator<<(const char *string) +CStdOutStream & CStdOutStream::operator<<(const char *s) { - fputs(string, _stream); + fputs(s, _stream); return *this; } -CStdOutStream & CStdOutStream::operator<<(const wchar_t *string) +CStdOutStream & CStdOutStream::operator<<(const wchar_t *s) { - *this << (const char *)UnicodeStringToMultiByte(string, CP_OEMCP); + int codePage = g_CodePage; + if (codePage == -1) + codePage = CP_OEMCP; + AString dest; + if (codePage == CP_UTF8) + ConvertUnicodeToUTF8(s, dest); + else + dest = UnicodeStringToMultiByte(s, (UINT)codePage); + *this << (const char *)dest; return *this; } diff --git a/CPP/Common/Types.h b/CPP/Common/Types.h index 4bb85410..9365b327 100755 --- a/CPP/Common/Types.h +++ b/CPP/Common/Types.h @@ -3,10 +3,7 @@ #ifndef __COMMON_TYPES_H #define __COMMON_TYPES_H -extern "C" -{ #include "../../C/Types.h" -} typedef int HRes; diff --git a/CPP/Windows/FileDevice.cpp b/CPP/Windows/FileDevice.cpp deleted file mode 100755 index 76f1aa7a..00000000 --- a/CPP/Windows/FileDevice.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// Windows/FileDevice.cpp - -#include "StdAfx.h" - -#include "FileDevice.h" - -namespace NWindows { -namespace NFile { -namespace NDevice { - -bool CFileBase::GetLengthSmart(UInt64 &length) -{ - PARTITION_INFORMATION partInfo; - if (GetPartitionInfo(&partInfo)) - { - length = partInfo.PartitionLength.QuadPart; - return true; - } - DISK_GEOMETRY geom; - if (!GetGeometry(&geom)) - if (!GetCdRomGeometry(&geom)) - return false; - length = geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector; - return true; -} - -bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) - { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } - -bool CInFile::Open(LPCTSTR fileName) - { return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } - -#ifndef _UNICODE -bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) - { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } - -bool CInFile::Open(LPCWSTR fileName) - { return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } -#endif - -bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) -{ - DWORD processedLoc = 0; - bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); - processedSize = (UInt32)processedLoc; - return res; -} - -}}} diff --git a/CPP/Windows/FileDevice.h b/CPP/Windows/FileDevice.h deleted file mode 100755 index 0aa9bc5b..00000000 --- a/CPP/Windows/FileDevice.h +++ /dev/null @@ -1,123 +0,0 @@ -// Windows/FileDevice.h - -#ifndef __WINDOWS_FILEDEVICE_H -#define __WINDOWS_FILEDEVICE_H - -#include "FileIO.h" -#include "Defs.h" - -namespace NWindows { -namespace NFile { -namespace NDevice { - -typedef struct _GET_LENGTH_INFORMATION -{ - LARGE_INTEGER Length; -} GET_LENGTH_INFORMATION, *PGET_LENGTH_INFORMATION; - -#define IOCTL_DISK_GET_LENGTH_INFO CTL_CODE(IOCTL_DISK_BASE, 0x0017, METHOD_BUFFERED, FILE_READ_ACCESS) - -/* -typedef struct _DISK_GEOMETRY_EX { - DISK_GEOMETRY Geometry; // Standard disk geometry: may be faked by driver. - LARGE_INTEGER DiskSize; // Must always be correct - BYTE Data[1]; // Partition, Detect info -} DISK_GEOMETRY_EX, *PDISK_GEOMETRY_EX; -*/ - -#define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM -#define IOCTL_CDROM_GET_DRIVE_GEOMETRY CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_MEDIA_REMOVAL CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS) - -class CFileBase: public NIO::CFileBase -{ -public: - bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, DWORD inSize, - LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned, LPOVERLAPPED overlapped) const - { - return BOOLToBool(::DeviceIoControl(_handle, controlCode, inBuffer, inSize, - outBuffer, outSize, bytesReturned, overlapped)); - } - - bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, - DWORD inSize, LPVOID outBuffer, DWORD outSize) const - { - DWORD ret; - return DeviceIoControl(controlCode, inBuffer, inSize, outBuffer, outSize, &ret, 0); - } - - bool DeviceIoControlIn(DWORD controlCode, LPVOID inBuffer, DWORD inSize) const - { return DeviceIoControl(controlCode, inBuffer, inSize, NULL, 0); } - - bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize) const - { return DeviceIoControl(controlCode, NULL, 0, outBuffer, outSize); } - - bool GetGeometry(DISK_GEOMETRY *res) const - { return DeviceIoControlOut(IOCTL_DISK_GET_DRIVE_GEOMETRY, res, sizeof(*res)); } - - bool GetCdRomGeometry(DISK_GEOMETRY *res) const - { return DeviceIoControlOut(IOCTL_CDROM_GET_DRIVE_GEOMETRY, res, sizeof(*res)); } - - /* - bool GetCdRomGeometryEx(DISK_GEOMETRY_EX *res) const - { return DeviceIoControlOut(IOCTL_CDROM_GET_DRIVE_GEOMETRY, res, sizeof(*res)); } - */ - - bool CdRomLock(bool lock) const - { - PREVENT_MEDIA_REMOVAL rem; - rem.PreventMediaRemoval = (BOOLEAN)(lock ? TRUE : FALSE); - return DeviceIoControlIn(IOCTL_CDROM_MEDIA_REMOVAL, &rem, sizeof(rem)); - } - - bool GetLengthInfo(UInt64 &length) const - { - GET_LENGTH_INFORMATION lengthInfo; - bool res = DeviceIoControlOut(IOCTL_DISK_GET_LENGTH_INFO, &lengthInfo, sizeof(lengthInfo)); - length = lengthInfo.Length.QuadPart; - return res; - } - - bool GetLengthSmart(UInt64 &length); - - - /* - bool FormatTracks(const FORMAT_PARAMETERS *formatParams, - BAD_TRACK_NUMBER *badTrackNumbers, DWORD numBadTrackNumbers, - DWORD &numBadTrackNumbersReturned) - { - DWORD ret; - // Check params, Probabably error - bool res = DeviceIoControl(IOCTL_DISK_FORMAT_TRACKS, badTrackNumbers, sizeof(*formatParams), - badTrackNumbers, numBadTrackNumbers * sizeof(*badTrackNumbers), &ret, NULL); - numBadTrackNumbersReturned = ret / sizeof(*badTrackNumbers); - return res; - } - */ - - - bool Performance(DISK_PERFORMANCE *res) - { return DeviceIoControlOut(IOCTL_DISK_PERFORMANCE, LPVOID(res), sizeof(*res)); } - - bool GetPartitionInfo(PARTITION_INFORMATION *res) - { return DeviceIoControlOut(IOCTL_DISK_GET_PARTITION_INFO, LPVOID(res), sizeof(*res)); } - - bool Verify(const VERIFY_INFORMATION *verifyInformation) - { return DeviceIoControlIn(IOCTL_DISK_VERIFY, LPVOID(verifyInformation), sizeof(*verifyInformation)); } -}; - -class CInFile: public CFileBase -{ -public: - bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); - bool Open(LPCTSTR fileName); - #ifndef _UNICODE - bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); - bool Open(LPCWSTR fileName); - #endif - bool Read(void *data, UInt32 size, UInt32 &processedSize); -}; - -}}} - -#endif diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp index 4224d6fa..cffce7f0 100755 --- a/CPP/Windows/FileDir.cpp +++ b/CPP/Windows/FileDir.cpp @@ -2,14 +2,14 @@ #include "StdAfx.h" -#include "FileDir.h" -#include "FileName.h" -#include "FileFind.h" -#include "Defs.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif +#include "FileDir.h" +#include "FileFind.h" +#include "FileName.h" + #ifndef _UNICODE extern bool g_IsNT; #endif @@ -291,7 +291,7 @@ bool CreateComplexDirectory(LPCTSTR _aPathName) if (::GetLastError() == ERROR_ALREADY_EXISTS) { NFind::CFileInfo fileInfo; - if (!NFind::FindFile(pathName, fileInfo)) // For network folders + if (!fileInfo.Find(pathName)) // For network folders return true; if (!fileInfo.IsDir()) return false; @@ -337,7 +337,7 @@ bool CreateComplexDirectory(LPCWSTR _aPathName) if (::GetLastError() == ERROR_ALREADY_EXISTS) { NFind::CFileInfoW fileInfo; - if (!NFind::FindFile(pathName, fileInfo)) // For network folders + if (!fileInfo.Find(pathName)) // For network folders return true; if (!fileInfo.IsDir()) return false; @@ -773,18 +773,20 @@ bool CreateTempDirectory(LPCTSTR prefix, CSysString &dirName) */ for (;;) { - CTempFile tempFile; - if (!tempFile.Create(prefix, dirName)) - return false; - if (!::DeleteFile(dirName)) - return false; + { + CTempFile tempFile; + if (!tempFile.Create(prefix, dirName)) + return false; + if (!tempFile.Remove()) + return false; + } /* UINT32 randomNumber = random.Generate(); TCHAR randomNumberString[32]; _stprintf(randomNumberString, _T("%04X"), randomNumber); dirName = prefix + randomNumberString; */ - if (NFind::DoesFileExist(dirName)) + if (NFind::DoesFileOrDirExist(dirName)) continue; if (MyCreateDirectory(dirName)) return true; @@ -810,18 +812,20 @@ bool CreateTempDirectory(LPCWSTR prefix, UString &dirName) */ for (;;) { - CTempFileW tempFile; - if (!tempFile.Create(prefix, dirName)) - return false; - if (!DeleteFileAlways(dirName)) - return false; + { + CTempFileW tempFile; + if (!tempFile.Create(prefix, dirName)) + return false; + if (!tempFile.Remove()) + return false; + } /* UINT32 randomNumber = random.Generate(); TCHAR randomNumberString[32]; _stprintf(randomNumberString, _T("%04X"), randomNumber); dirName = prefix + randomNumberString; */ - if (NFind::DoesFileExist(dirName)) + if (NFind::DoesFileOrDirExist(dirName)) continue; if (MyCreateDirectory(dirName)) return true; diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp index f33ec961..d0cb2327 100755 --- a/CPP/Windows/FileFind.cpp +++ b/CPP/Windows/FileFind.cpp @@ -3,6 +3,7 @@ #include "StdAfx.h" #include "FileFind.h" +#include "FileIO.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif @@ -14,6 +15,13 @@ extern bool g_IsNT; namespace NWindows { namespace NFile { +#ifdef SUPPORT_DEVICE_FILE +bool IsDeviceName(LPCTSTR n); +#ifndef _UNICODE +bool IsDeviceName(LPCWSTR n); +#endif +#endif + #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif @@ -44,19 +52,26 @@ bool CFileInfoW::IsDots() const } #endif -static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi) -{ - fi.Attrib = fd.dwFileAttributes; - fi.CTime = fd.ftCreationTime; - fi.ATime = fd.ftLastAccessTime; - fi.MTime = fd.ftLastWriteTime; - fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; - fi.Name = fd.cFileName; +#define WIN_FD_TO_MY_FI(fi, fd) \ + fi.Attrib = fd.dwFileAttributes; \ + fi.CTime = fd.ftCreationTime; \ + fi.ATime = fd.ftLastAccessTime; \ + fi.MTime = fd.ftLastWriteTime; \ + fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; \ + fi.IsDevice = false; + + /* #ifndef _WIN32_WCE fi.ReparseTag = fd.dwReserved0; #else fi.ObjectID = fd.dwOID; #endif + */ + +static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi) +{ + WIN_FD_TO_MY_FI(fi, fd); + fi.Name = fd.cFileName; } #ifndef _UNICODE @@ -65,32 +80,14 @@ static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfoW &fi) { - fi.Attrib = fd.dwFileAttributes; - fi.CTime = fd.ftCreationTime; - fi.ATime = fd.ftLastAccessTime; - fi.MTime = fd.ftLastWriteTime; - fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; + WIN_FD_TO_MY_FI(fi, fd); fi.Name = fd.cFileName; - #ifndef _WIN32_WCE - fi.ReparseTag = fd.dwReserved0; - #else - fi.ObjectID = fd.dwOID; - #endif } static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfoW &fi) { - fi.Attrib = fd.dwFileAttributes; - fi.CTime = fd.ftCreationTime; - fi.ATime = fd.ftLastAccessTime; - fi.MTime = fd.ftLastWriteTime; - fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; + WIN_FD_TO_MY_FI(fi, fd); fi.Name = GetUnicodeString(fd.cFileName, GetCurrentCodePage()); - #ifndef _WIN32_WCE - fi.ReparseTag = fd.dwReserved0; - #else - fi.ObjectID = fd.dwOID; - #endif } #endif @@ -108,7 +105,7 @@ bool CFindFile::Close() } -bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo) +bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fi) { if (!Close()) return false; @@ -124,12 +121,12 @@ bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo) #endif if (_handle == INVALID_HANDLE_VALUE) return false; - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); + ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); return true; } #ifndef _UNICODE -bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo) +bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fi) { if (!Close()) return false; @@ -146,7 +143,7 @@ bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo) } #endif if (_handle != INVALID_HANDLE_VALUE) - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); + ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); } else { @@ -154,95 +151,158 @@ bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo) _handle = ::FindFirstFileA(UnicodeStringToMultiByte(wildcard, GetCurrentCodePage()), &fd); if (_handle != INVALID_HANDLE_VALUE) - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); + ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); } return (_handle != INVALID_HANDLE_VALUE); } #endif -bool CFindFile::FindNext(CFileInfo &fileInfo) +bool CFindFile::FindNext(CFileInfo &fi) { WIN32_FIND_DATA fd; bool result = BOOLToBool(::FindNextFile(_handle, &fd)); if (result) - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); + ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); return result; } #ifndef _UNICODE -bool CFindFile::FindNext(CFileInfoW &fileInfo) +bool CFindFile::FindNext(CFileInfoW &fi) { if (g_IsNT) { WIN32_FIND_DATAW fd; if (!::FindNextFileW(_handle, &fd)) return false; - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); + ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); } else { WIN32_FIND_DATAA fd; if (!::FindNextFileA(_handle, &fd)) return false; - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); + ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); } return true; } #endif -bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo) +#define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0; + +void CFileInfoBase::Clear() +{ + Size = 0; + MY_CLEAR_FILETIME(CTime); + MY_CLEAR_FILETIME(ATime); + MY_CLEAR_FILETIME(MTime); + Attrib = 0; +} + +bool CFileInfo::Find(LPCTSTR wildcard) { + #ifdef SUPPORT_DEVICE_FILE + if (IsDeviceName(wildcard)) + { + Clear(); + IsDevice = true; + NIO::CInFile inFile; + if (!inFile.Open(wildcard)) + return false; + Name = wildcard + 4; + if (inFile.LengthDefined) + Size = inFile.Length; + return true; + } + #endif CFindFile finder; - return finder.FindFirst(wildcard, fileInfo); + return finder.FindFirst(wildcard, *this); } + #ifndef _UNICODE -bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo) +bool CFileInfoW::Find(LPCWSTR wildcard) { + #ifdef SUPPORT_DEVICE_FILE + if (IsDeviceName(wildcard)) + { + Clear(); + IsDevice = true; + NIO::CInFile inFile; + if (!inFile.Open(wildcard)) + return false; + Name = wildcard + 4; + if (inFile.LengthDefined) + Size = inFile.Length; + return true; + } + #endif CFindFile finder; - return finder.FindFirst(wildcard, fileInfo); + return finder.FindFirst(wildcard, *this); } #endif bool DoesFileExist(LPCTSTR name) { - CFileInfo fileInfo; - return FindFile(name, fileInfo); + CFileInfo fi; + return fi.Find(name) && !fi.IsDir(); +} + +bool DoesDirExist(LPCTSTR name) +{ + CFileInfo fi; + return fi.Find(name) && fi.IsDir(); +} + +bool DoesFileOrDirExist(LPCTSTR name) +{ + CFileInfo fi; + return fi.Find(name); } #ifndef _UNICODE bool DoesFileExist(LPCWSTR name) { - CFileInfoW fileInfo; - return FindFile(name, fileInfo); + CFileInfoW fi; + return fi.Find(name) && !fi.IsDir(); +} + +bool DoesDirExist(LPCWSTR name) +{ + CFileInfoW fi; + return fi.Find(name) && fi.IsDir(); +} +bool DoesFileOrDirExist(LPCWSTR name) +{ + CFileInfoW fi; + return fi.Find(name); } #endif ///////////////////////////////////// // CEnumerator -bool CEnumerator::NextAny(CFileInfo &fileInfo) +bool CEnumerator::NextAny(CFileInfo &fi) { if (_findFile.IsHandleAllocated()) - return _findFile.FindNext(fileInfo); + return _findFile.FindNext(fi); else - return _findFile.FindFirst(_wildcard, fileInfo); + return _findFile.FindFirst(_wildcard, fi); } -bool CEnumerator::Next(CFileInfo &fileInfo) +bool CEnumerator::Next(CFileInfo &fi) { for (;;) { - if (!NextAny(fileInfo)) + if (!NextAny(fi)) return false; - if (!fileInfo.IsDots()) + if (!fi.IsDots()) return true; } } -bool CEnumerator::Next(CFileInfo &fileInfo, bool &found) +bool CEnumerator::Next(CFileInfo &fi, bool &found) { - if (Next(fileInfo)) + if (Next(fi)) { found = true; return true; @@ -252,28 +312,28 @@ bool CEnumerator::Next(CFileInfo &fileInfo, bool &found) } #ifndef _UNICODE -bool CEnumeratorW::NextAny(CFileInfoW &fileInfo) +bool CEnumeratorW::NextAny(CFileInfoW &fi) { if (_findFile.IsHandleAllocated()) - return _findFile.FindNext(fileInfo); + return _findFile.FindNext(fi); else - return _findFile.FindFirst(_wildcard, fileInfo); + return _findFile.FindFirst(_wildcard, fi); } -bool CEnumeratorW::Next(CFileInfoW &fileInfo) +bool CEnumeratorW::Next(CFileInfoW &fi) { for (;;) { - if (!NextAny(fileInfo)) + if (!NextAny(fi)) return false; - if (!fileInfo.IsDots()) + if (!fi.IsDots()) return true; } } -bool CEnumeratorW::Next(CFileInfoW &fileInfo, bool &found) +bool CEnumeratorW::Next(CFileInfoW &fi, bool &found) { - if (Next(fileInfo)) + if (Next(fi)) { found = true; return true; diff --git a/CPP/Windows/FileFind.h b/CPP/Windows/FileFind.h index 09b99243..4644d048 100755 --- a/CPP/Windows/FileFind.h +++ b/CPP/Windows/FileFind.h @@ -5,8 +5,8 @@ #include "../Common/MyString.h" #include "../Common/Types.h" -#include "FileName.h" #include "Defs.h" +#include "FileName.h" namespace NWindows { namespace NFile { @@ -26,18 +26,23 @@ namespace NAttributes class CFileInfoBase { bool MatchesMask(UINT32 mask) const { return ((Attrib & mask) != 0); } +protected: + void Clear(); public: UInt64 Size; FILETIME CTime; FILETIME ATime; FILETIME MTime; DWORD Attrib; - + bool IsDevice; + + /* #ifndef _WIN32_WCE UINT32 ReparseTag; #else DWORD ObjectID; #endif + */ bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); } bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); } @@ -53,21 +58,23 @@ public: bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); } }; -class CFileInfo: public CFileInfoBase +struct CFileInfo: public CFileInfoBase { -public: CSysString Name; + bool IsDots() const; + bool Find(LPCTSTR wildcard); }; #ifdef _UNICODE typedef CFileInfo CFileInfoW; #else -class CFileInfoW: public CFileInfoBase +struct CFileInfoW: public CFileInfoBase { -public: UString Name; + bool IsDots() const; + bool Find(LPCWSTR wildcard); }; #endif @@ -88,12 +95,13 @@ public: bool Close(); }; -bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo); - bool DoesFileExist(LPCTSTR name); +bool DoesDirExist(LPCTSTR name); +bool DoesFileOrDirExist(LPCTSTR name); #ifndef _UNICODE -bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo); bool DoesFileExist(LPCWSTR name); +bool DoesDirExist(LPCWSTR name); +bool DoesFileOrDirExist(LPCWSTR name); #endif class CEnumerator diff --git a/CPP/Windows/FileIO.cpp b/CPP/Windows/FileIO.cpp index 5646d0a3..7279ea15 100755 --- a/CPP/Windows/FileIO.cpp +++ b/CPP/Windows/FileIO.cpp @@ -3,8 +3,8 @@ #include "StdAfx.h" #include "FileIO.h" -#include "Defs.h" -#ifdef WIN_LONG_PATH + +#if defined(WIN_LONG_PATH) || defined(SUPPORT_DEVICE_FILE) #include "../Common/MyString.h" #endif #ifndef _UNICODE @@ -18,6 +18,40 @@ extern bool g_IsNT; namespace NWindows { namespace NFile { +#ifdef SUPPORT_DEVICE_FILE +bool IsDeviceName(LPCTSTR n) +{ + if (n[0] != '\\' || n[1] != '\\' || n[2] != '.' || n[3] != '\\') + return false; + int len = (int)MyStringLen(n); + if (len == 6 && n[5] == ':') + return true; + if (len < 18 || len > 22 || memcmp(n + 4, TEXT("PhysicalDrive"), 13 * sizeof(TCHAR)) != 0) + return false; + for (int i = 17; i < len; i++) + if (n[i] < '0' || n[i] > '9') + return false; + return true; +} + +#ifndef _UNICODE +bool IsDeviceName(LPCWSTR n) +{ + if (n[0] != '\\' || n[1] != '\\' || n[2] != '.' || n[3] != '\\') + return false; + int len = (int)wcslen(n); + if (len == 6 && n[5] == ':') + return true; + if (len < 18 || len > 22 || wcsncmp(n + 4, L"PhysicalDrive", 13) != 0) + return false; + for (int i = 17; i < len; i++) + if (n[i] < '0' || n[i] > '9') + return false; + return true; +} +#endif +#endif + #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif @@ -78,6 +112,9 @@ bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess, flagsAndAttributes, (HANDLE)NULL); } #endif + #ifdef SUPPORT_DEVICE_FILE + IsDeviceFile = false; + #endif return (_handle != INVALID_HANDLE_VALUE); } @@ -103,6 +140,9 @@ bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess, flagsAndAttributes, (HANDLE)NULL); } #endif + #ifdef SUPPORT_DEVICE_FILE + IsDeviceFile = false; + #endif return (_handle != INVALID_HANDLE_VALUE); } #endif @@ -124,6 +164,14 @@ bool CFileBase::GetPosition(UInt64 &position) const bool CFileBase::GetLength(UInt64 &length) const { + #ifdef SUPPORT_DEVICE_FILE + if (IsDeviceFile && LengthDefined) + { + length = Length; + return true; + } + #endif + DWORD sizeHigh; DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh); if (sizeLow == 0xFFFFFFFF) @@ -135,6 +183,14 @@ bool CFileBase::GetLength(UInt64 &length) const bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const { + #ifdef SUPPORT_DEVICE_FILE + if (IsDeviceFile && LengthDefined && moveMethod == FILE_END) + { + distanceToMove += Length; + moveMethod = FILE_BEGIN; + } + #endif + LARGE_INTEGER value; value.QuadPart = distanceToMove; value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod); @@ -166,7 +222,7 @@ bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const BY_HANDLE_FILE_INFORMATION winFileInfo; if (!::GetFileInformationByHandle(_handle, &winFileInfo)) return false; - fileInfo.Attributes = winFileInfo.dwFileAttributes; + fileInfo.Attrib = winFileInfo.dwFileAttributes; fileInfo.CTime = winFileInfo.ftCreationTime; fileInfo.ATime = winFileInfo.ftLastAccessTime; fileInfo.MTime = winFileInfo.ftLastWriteTime; @@ -180,8 +236,45 @@ bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const ///////////////////////// // CInFile +#ifdef SUPPORT_DEVICE_FILE +void CInFile::GetDeviceLength() +{ + if (_handle != INVALID_HANDLE_VALUE && IsDeviceFile) + { + PARTITION_INFORMATION partInfo; + LengthDefined = true; + Length = 0; + + if (GetPartitionInfo(&partInfo)) + Length = partInfo.PartitionLength.QuadPart; + else + { + DISK_GEOMETRY geom; + if (!GetGeometry(&geom)) + if (!GetCdRomGeometry(&geom)) + LengthDefined = false; + if (LengthDefined) + Length = geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector; + } + // SeekToBegin(); + } +} + +// ((desiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE)) == 0 && + +#define MY_DEVICE_EXTRA_CODE \ + IsDeviceFile = IsDeviceName(fileName); \ + GetDeviceLength(); +#else +#define MY_DEVICE_EXTRA_CODE +#endif + bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) - { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } +{ + bool res = Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); + MY_DEVICE_EXTRA_CODE + return res; +} bool CInFile::OpenShared(LPCTSTR fileName, bool shareForWrite) { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } @@ -191,7 +284,11 @@ bool CInFile::Open(LPCTSTR fileName) #ifndef _UNICODE bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) - { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } +{ + bool res = Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); + MY_DEVICE_EXTRA_CODE + return res; +} bool CInFile::OpenShared(LPCWSTR fileName, bool shareForWrite) { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } @@ -211,16 +308,21 @@ bool CInFile::Open(LPCWSTR fileName) static UInt32 kChunkSizeMax = (1 << 22); -bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) +bool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize) { - if (size > kChunkSizeMax) - size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } +bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) +{ + if (size > kChunkSizeMax) + size = kChunkSizeMax; + return Read1(data, size, processedSize); +} + bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; diff --git a/CPP/Windows/FileIO.h b/CPP/Windows/FileIO.h index f1e600ec..4e7308c7 100755 --- a/CPP/Windows/FileIO.h +++ b/CPP/Windows/FileIO.h @@ -5,26 +5,29 @@ #include "../Common/Types.h" +#include "Defs.h" + namespace NWindows { namespace NFile { namespace NIO { struct CByHandleFileInfo { - DWORD Attributes; + DWORD Attrib; FILETIME CTime; FILETIME ATime; FILETIME MTime; - DWORD VolumeSerialNumber; - UInt64 Size; - DWORD NumberOfLinks; - UInt64 FileIndex; + DWORD VolumeSerialNumber; + UInt64 Size; + DWORD NumberOfLinks; + UInt64 FileIndex; }; class CFileBase { protected: HANDLE _handle; + bool Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #ifndef _UNICODE @@ -33,7 +36,13 @@ protected: #endif public: - CFileBase(): _handle(INVALID_HANDLE_VALUE){}; + #ifdef SUPPORT_DEVICE_FILE + bool IsDeviceFile; + bool LengthDefined; + UInt64 Length; + #endif + + CFileBase(): _handle(INVALID_HANDLE_VALUE) {}; ~CFileBase(); bool Close(); @@ -49,8 +58,42 @@ public: bool GetFileInformation(CByHandleFileInfo &fileInfo) const; }; +#define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM +#define IOCTL_CDROM_GET_DRIVE_GEOMETRY CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_MEDIA_REMOVAL CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS) + class CInFile: public CFileBase { + #ifdef SUPPORT_DEVICE_FILE + bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, DWORD inSize, + LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned, LPOVERLAPPED overlapped) const + { + return BOOLToBool(::DeviceIoControl(_handle, controlCode, inBuffer, inSize, + outBuffer, outSize, bytesReturned, overlapped)); + } + + bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, + DWORD inSize, LPVOID outBuffer, DWORD outSize) const + { + DWORD ret; + return DeviceIoControl(controlCode, inBuffer, inSize, outBuffer, outSize, &ret, 0); + } + + bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize) const + { return DeviceIoControl(controlCode, NULL, 0, outBuffer, outSize); } + + bool GetGeometry(DISK_GEOMETRY *res) const + { return DeviceIoControlOut(IOCTL_DISK_GET_DRIVE_GEOMETRY, res, sizeof(*res)); } + + bool GetCdRomGeometry(DISK_GEOMETRY *res) const + { return DeviceIoControlOut(IOCTL_CDROM_GET_DRIVE_GEOMETRY, res, sizeof(*res)); } + + bool GetPartitionInfo(PARTITION_INFORMATION *res) + { return DeviceIoControlOut(IOCTL_DISK_GET_PARTITION_INFO, LPVOID(res), sizeof(*res)); } + + void GetDeviceLength(); + #endif + public: bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool OpenShared(LPCTSTR fileName, bool shareForWrite); @@ -60,15 +103,14 @@ public: bool OpenShared(LPCWSTR fileName, bool shareForWrite); bool Open(LPCWSTR fileName); #endif + bool Read1(void *data, UInt32 size, UInt32 &processedSize); bool ReadPart(void *data, UInt32 size, UInt32 &processedSize); bool Read(void *data, UInt32 size, UInt32 &processedSize); }; class COutFile: public CFileBase { - // DWORD m_CreationDisposition; public: - // COutFile(): m_CreationDisposition(CREATE_NEW){}; bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCTSTR fileName, DWORD creationDisposition); bool Create(LPCTSTR fileName, bool createAlways); @@ -79,13 +121,6 @@ public: bool Create(LPCWSTR fileName, bool createAlways); #endif - /* - void SetOpenCreationDisposition(DWORD creationDisposition) - { m_CreationDisposition = creationDisposition; } - void SetOpenCreationDispositionCreateAlways() - { m_CreationDisposition = CREATE_ALWAYS; } - */ - bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); bool SetMTime(const FILETIME *mTime); bool WritePart(const void *data, UInt32 size, UInt32 &processedSize); diff --git a/CPP/Windows/PropVariant.cpp b/CPP/Windows/PropVariant.cpp index ae2e6cd1..1db6c236 100755 --- a/CPP/Windows/PropVariant.cpp +++ b/CPP/Windows/PropVariant.cpp @@ -65,6 +65,26 @@ CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) } +CPropVariant& CPropVariant::operator=(const char *s) +{ + InternalClear(); + vt = VT_BSTR; + wReserved1 = 0; + UINT len = (UINT)strlen(s); + bstrVal = ::SysAllocStringByteLen(0, (UINT)len * sizeof(OLECHAR)); + if (bstrVal == NULL) + { + vt = VT_ERROR; + scode = E_OUTOFMEMORY; + } + else + { + for (UINT i = 0; i <= len; i++) + bstrVal[i] = s[i]; + } + return *this; +} + CPropVariant& CPropVariant::operator=(bool bSrc) { if (vt != VT_BOOL) diff --git a/CPP/Windows/PropVariant.h b/CPP/Windows/PropVariant.h index d44215f0..5552bbe2 100755 --- a/CPP/Windows/PropVariant.h +++ b/CPP/Windows/PropVariant.h @@ -31,6 +31,7 @@ public: CPropVariant& operator=(const PROPVARIANT& varSrc); CPropVariant& operator=(BSTR bstrSrc); CPropVariant& operator=(LPCOLESTR lpszSrc); + CPropVariant& operator=(const char *s); CPropVariant& operator=(bool bSrc); CPropVariant& operator=(UInt32 value); CPropVariant& operator=(UInt64 value); diff --git a/CPP/Windows/Security.cpp b/CPP/Windows/Security.cpp index bb8c3a9a..6f5bcad3 100755 --- a/CPP/Windows/Security.cpp +++ b/CPP/Windows/Security.cpp @@ -121,8 +121,7 @@ bool AddLockMemoryPrivilege() != 0) return false; LSA_UNICODE_STRING userRights; - wchar_t s[128]; - wcscpy(s, MY__SE_LOCK_MEMORY_NAME); + wchar_t s[128] = MY__SE_LOCK_MEMORY_NAME; SetLsaString(s, &userRights); WCHAR userName[256 + 2]; DWORD size = 256; diff --git a/CPP/Windows/Synchronization.h b/CPP/Windows/Synchronization.h index 8d34ae9d..54fcf952 100755 --- a/CPP/Windows/Synchronization.h +++ b/CPP/Windows/Synchronization.h @@ -3,12 +3,9 @@ #ifndef __WINDOWS_SYNCHRONIZATION_H #define __WINDOWS_SYNCHRONIZATION_H -#include "Defs.h" - -extern "C" -{ #include "../../C/Threads.h" -} + +#include "Defs.h" #ifdef _WIN32 #include "Handle.h" @@ -23,7 +20,7 @@ protected: ::CEvent _object; public: bool IsCreated() { return Event_IsCreated(&_object) != 0; } - operator HANDLE() { return _object.handle; } + operator HANDLE() { return _object; } CBaseEvent() { Event_Construct(&_object); } ~CBaseEvent() { Close(); } WRes Close() { return Event_Close(&_object); } @@ -31,16 +28,16 @@ public: WRes Create(bool manualReset, bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES securityAttributes = NULL) { - _object.handle = ::CreateEvent(securityAttributes, BoolToBOOL(manualReset), + _object = ::CreateEvent(securityAttributes, BoolToBOOL(manualReset), BoolToBOOL(initiallyOwn), name); - if (_object.handle != 0) + if (_object != 0) return 0; return ::GetLastError(); } WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { - _object.handle = ::OpenEvent(desiredAccess, BoolToBOOL(inheritHandle), name); - if (_object.handle != 0) + _object = ::OpenEvent(desiredAccess, BoolToBOOL(inheritHandle), name); + if (_object != 0) return 0; return ::GetLastError(); } @@ -134,7 +131,7 @@ public: CSemaphore() { Semaphore_Construct(&_object); } ~CSemaphore() { Close(); } WRes Close() { return Semaphore_Close(&_object); } - operator HANDLE() { return _object.handle; } + operator HANDLE() { return _object; } WRes Create(UInt32 initiallyCount, UInt32 maxCount) { return Semaphore_Create(&_object, initiallyCount, maxCount); diff --git a/CPP/Windows/Thread.h b/CPP/Windows/Thread.h index 39104f4a..16a509d4 100755 --- a/CPP/Windows/Thread.h +++ b/CPP/Windows/Thread.h @@ -3,12 +3,9 @@ #ifndef __WINDOWS_THREAD_H #define __WINDOWS_THREAD_H -#include "Defs.h" - -extern "C" -{ #include "../../C/Threads.h" -} + +#include "Defs.h" namespace NWindows { @@ -25,14 +22,14 @@ public: WRes Wait() { return Thread_Wait(&thread); } #ifdef _WIN32 - operator HANDLE() { return thread.handle; } - void Attach(HANDLE handle) { thread.handle = handle; } - HANDLE Detach() { HANDLE h = thread.handle; thread.handle = NULL; return h; } - DWORD Resume() { return ::ResumeThread(thread.handle); } - DWORD Suspend() { return ::SuspendThread(thread.handle); } - bool Terminate(DWORD exitCode) { return BOOLToBool(::TerminateThread(thread.handle, exitCode)); } - int GetPriority() { return ::GetThreadPriority(thread.handle); } - bool SetPriority(int priority) { return BOOLToBool(::SetThreadPriority(thread.handle, priority)); } + operator HANDLE() { return thread; } + void Attach(HANDLE handle) { thread = handle; } + HANDLE Detach() { HANDLE h = thread; thread = NULL; return h; } + DWORD Resume() { return ::ResumeThread(thread); } + DWORD Suspend() { return ::SuspendThread(thread); } + bool Terminate(DWORD exitCode) { return BOOLToBool(::TerminateThread(thread, exitCode)); } + int GetPriority() { return ::GetThreadPriority(thread); } + bool SetPriority(int priority) { return BOOLToBool(::SetThreadPriority(thread, priority)); } #endif }; diff --git a/DOC/7zip.hhp b/DOC/7zip.hhp index 24da5b89..9af0db78 100755 --- a/DOC/7zip.hhp +++ b/DOC/7zip.hhp @@ -38,6 +38,7 @@ cmdline\switches\method.htm cmdline\switches\ar_include.htm cmdline\switches\ar_exclude.htm cmdline\switches\ar_no.htm +cmdline\switches\scc.htm cmdline\switches\charset.htm cmdline\switches\email.htm cmdline\switches\list_tech.htm diff --git a/DOC/7zip.nsi b/DOC/7zip.nsi index 901872a7..0ae546e8 100755 --- a/DOC/7zip.nsi +++ b/DOC/7zip.nsi @@ -1,9 +1,9 @@ ;-------------------------------- ;Defines -!define VERSION_MAJOR 4 -!define VERSION_MINOR 65 -!define VERSION_POSTFIX_FULL "" +!define VERSION_MAJOR 9 +!define VERSION_MINOR 04 +!define VERSION_POSTFIX_FULL " beta" !ifdef WIN64 !ifdef IA64 !define VERSION_SYS_POSTFIX_FULL " for Windows IA-64" @@ -159,11 +159,7 @@ Section File descript.ion File History.txt File License.txt - File copying.txt File readme.txt - !ifndef WIN64 - File 7zip_pad.xml - !endif # File 7-zip.dll # File 7-zipn.dll diff --git a/DOC/7zip.wxs b/DOC/7zip.wxs index a6e3f957..312da6ce 100755 --- a/DOC/7zip.wxs +++ b/DOC/7zip.wxs @@ -1,7 +1,7 @@ <?xml version="1.0"?> -<?define VerMajor = "4" ?> -<?define VerMinor = "65" ?> +<?define VerMajor = "9" ?> +<?define VerMinor = "04" ?> <?define VerBuild = "00" ?> <?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?> <?define MmHex = "0$(var.VerMajor)$(var.VerMinor)" ?> @@ -206,7 +206,6 @@ </Component> <Component Id="Docs" Guid="$(var.CompDocs)" DiskId="1" Win64="$(var.Is64)"> - <File Id="copying.txt" Name="copying.txt" /> <File Id="descript.ion" Name="descript.ion" /> <File Id="History.txt" Name="History.txt" /> <File Id="License.txt" Name="License.txt" /> diff --git a/DOC/License.txt b/DOC/License.txt index 9331efb4..a2f6df0b 100755 --- a/DOC/License.txt +++ b/DOC/License.txt @@ -7,7 +7,7 @@ Licenses for files are: - 1) CPP/7zip/Compress/Rar files: GNU LGPL + unRAR restriction + 1) CPP/7zip/Compress/Rar* files: GNU LGPL + unRAR restriction 2) All other files: GNU LGPL The GNU LGPL + unRAR restriction means that you must follow both diff --git a/DOC/history.txt b/DOC/history.txt index 896f3913..bf2b4ca4 100755 --- a/DOC/history.txt +++ b/DOC/history.txt @@ -1,6 +1,16 @@ Sources history of the 7-Zip ---------------------------- +9.04 2009-05-30 +------------------------- +- ICoder.h: NCoderPropID::EEnum values were changed + + +9.02 2009-04-23 +------------------------- +- Bug was fixed: if swap2 filter was requests at compression, + 7-zip used swap4 filter instead (but id was swap2), so archives were incorrect. + 4.61 2008-11-23 ------------------------- - Bug in ver. 4.58+ was fixed: diff --git a/DOC/lzma.txt b/DOC/lzma.txt index 715792d6..026b850d 100755 --- a/DOC/lzma.txt +++ b/DOC/lzma.txt @@ -1,4 +1,4 @@ -LZMA SDK 4.65 +LZMA SDK 9.04 ------------- LZMA SDK provides the documentation, samples, header files, libraries, @@ -49,6 +49,7 @@ lzma.txt - LZMA SDK description (this file) 7zC.txt - 7z ANSI-C Decoder description methods.txt - Compression method IDs for .7z lzma.exe - Compiled file->file LZMA encoder/decoder for Windows +7zr.exe - 7-Zip with 7z/lzma/xz support. history.txt - history of the LZMA SDK @@ -66,7 +67,7 @@ C/ - C files LzmaEnc.* - LZMA encoding LzmaLib.* - LZMA Library for DLL calling Types.h - Basic types for another .c files - Threads.* - The code for multithreading. + Threads.* - The code for multithreading. LzmaLib - LZMA Library (.DLL for Windows) @@ -86,11 +87,7 @@ CPP/ -- CPP files Compress - files related to compression/decompression - Copy - Copy coder - RangeCoder - Range Coder (special code of compression/decompression) - LZMA - LZMA compression/decompression on C++ LZMA_Alone - file->file LZMA compression/decompression - Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code Archive - files related to archiving @@ -369,8 +366,8 @@ Interface: propData - LZMA properties (5 bytes) propSize - size of propData buffer (5 bytes) finishMode - It has meaning only if the decoding reaches output limit (*destLen). - LZMA_FINISH_ANY - Decode just destLen bytes. - LZMA_FINISH_END - Stream must be finished after (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). You can use LZMA_FINISH_END, when you know that current output buffer covers last bytes of stream. alloc - Memory allocator. @@ -431,7 +428,7 @@ Memory Requirements: { ... int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, - const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode); + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode); ... } diff --git a/DOC/readme.txt b/DOC/readme.txt index 13a30611..f8706e4c 100755 --- a/DOC/readme.txt +++ b/DOC/readme.txt @@ -1,4 +1,4 @@ -7-Zip 4.65 Sources +7-Zip 9.04 Sources ------------------ 7-Zip is a file archiver for Windows 95/98/ME/NT/2000/2003/XP/Vista. |