From c65230d8585317f7cd58ae2982067385269fdee9 Mon Sep 17 00:00:00 2001 From: Igor Pavlov Date: Tue, 2 Nov 2010 00:00:00 +0000 Subject: 9.18 --- C/7zAlloc.c | 76 ++ C/7zAlloc.h | 15 + C/7zDec.c | 60 +- C/7zIn.c | 16 +- C/7zVersion.h | 6 +- C/CpuArch.c | 16 +- C/CpuArch.h | 16 +- C/Types.h | 18 +- C/Util/7z/7z.dsp | 20 +- C/Util/7z/7zAlloc.c | 77 -- C/Util/7z/7zAlloc.h | 23 - C/Util/7z/7zMain.c | 20 +- C/Util/7z/makefile | 3 +- C/Util/7z/makefile.gcc | 7 +- C/Util/SfxSetup/SfxSetup.c | 591 ++++++++ C/Util/SfxSetup/SfxSetup.dsp | 198 +++ C/Util/SfxSetup/SfxSetup.dsw | 29 + C/Util/SfxSetup/makefile | 35 + C/Util/SfxSetup/makefile_con | 35 + C/Util/SfxSetup/resource.rc | 6 + C/Util/SfxSetup/setup.ico | Bin 0 -> 1078 bytes CPP/7zip/Archive/7z/7zEncode.cpp | 15 +- CPP/7zip/Archive/7z/7zIn.cpp | 53 +- CPP/7zip/Archive/Common/ItemNameUtils.cpp | 2 + CPP/7zip/Archive/Common/MultiStream.cpp | 99 +- CPP/7zip/Archive/Common/MultiStream.h | 32 +- CPP/7zip/Archive/CramfsHandler.cpp | 644 +++++++++ CPP/7zip/Archive/ElfHandler.cpp | 6 +- CPP/7zip/Archive/Icons/squashfs.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Iso/IsoHandler.cpp | 86 +- CPP/7zip/Archive/Iso/IsoIn.cpp | 3 +- CPP/7zip/Archive/Iso/IsoIn.h | 15 + CPP/7zip/Archive/LzhHandler.cpp | 2 +- CPP/7zip/Archive/MachoHandler.cpp | 20 +- CPP/7zip/Archive/PeHandler.cpp | 86 +- CPP/7zip/Archive/Rar/RarHandler.cpp | 19 +- CPP/7zip/Archive/Rar/RarHandler.h | 1 + CPP/7zip/Archive/Rar/RarHeader.h | 20 +- CPP/7zip/Archive/Rar/RarIn.cpp | 9 +- CPP/7zip/Archive/Rar/RarIn.h | 2 +- CPP/7zip/Archive/RpmHandler.cpp | 6 +- CPP/7zip/Archive/SplitHandler.cpp | 1 - CPP/7zip/Archive/SquashfsHandler.cpp | 1959 +++++++++++++++++++++++++++ CPP/7zip/Archive/Tar/TarHandler.cpp | 107 +- CPP/7zip/Archive/Tar/TarHandler.h | 4 +- CPP/7zip/Archive/Tar/TarHandlerOut.cpp | 2 +- CPP/7zip/Archive/Tar/TarIn.cpp | 104 +- CPP/7zip/Archive/Tar/TarIn.h | 5 +- CPP/7zip/Archive/Tar/TarItem.h | 11 +- CPP/7zip/Archive/Tar/TarUpdate.cpp | 12 +- CPP/7zip/Archive/Wim/WimHandlerOut.cpp | 16 +- CPP/7zip/Archive/Wim/WimIn.cpp | 2 +- CPP/7zip/Archive/XarHandler.cpp | 2 +- CPP/7zip/Archive/Zip/ZipAddCommon.cpp | 7 +- CPP/7zip/Bundles/Fm/makefile | 2 + CPP/7zip/Bundles/Format7zF/Format7z.dsp | 14 +- CPP/7zip/Bundles/Format7zF/makefile | 2 + CPP/7zip/Bundles/Format7zF/resource.rc | 3 +- CPP/7zip/Common/LimitedStreams.h | 1 + CPP/7zip/Common/StreamObjects.cpp | 187 ++- CPP/7zip/Common/StreamObjects.h | 86 +- CPP/7zip/Guid.txt | 2 + CPP/7zip/MyVersion.h | 8 +- CPP/7zip/PropID.h | 1 + CPP/7zip/UI/Agent/Agent.cpp | 2 +- CPP/7zip/UI/Agent/Agent.h | 21 + CPP/7zip/UI/Common/Extract.cpp | 9 + CPP/7zip/UI/Common/ExtractingFilePath.cpp | 2 + CPP/7zip/UI/Common/OpenArchive.cpp | 8 + CPP/7zip/UI/Common/OpenArchive.h | 1 + CPP/7zip/UI/Common/PropIDUtils.cpp | 11 +- CPP/7zip/UI/Console/List.cpp | 5 +- CPP/7zip/UI/Console/Main.cpp | 5 +- CPP/7zip/UI/Far/Far.dsp | 4 +- CPP/7zip/UI/Far/FarPlugin.h | 58 +- CPP/7zip/UI/Far/Main.cpp | 7 +- CPP/7zip/UI/Far/Plugin.cpp | 20 +- CPP/7zip/UI/FileManager/PanelItemOpen.cpp | 41 + CPP/7zip/UI/FileManager/PanelMenu.cpp | 17 +- CPP/7zip/UI/FileManager/PanelSort.cpp | 18 +- CPP/7zip/UI/FileManager/ProgramLocation.cpp | 3 +- CPP/7zip/UI/FileManager/PropertyName.cpp | 1 + CPP/7zip/UI/FileManager/PropertyName.rc | 1 + CPP/7zip/UI/FileManager/PropertyNameRes.h | 1 + CPP/7zip/UI/GUI/CompressDialog.cpp | 8 +- CPP/Common/DynamicBuffer.h | 9 +- CPP/Common/IntToString.cpp | 11 + CPP/Common/IntToString.h | 2 + CPP/Common/MyString.h | 4 - CPP/Common/MyVector.h | 16 + CPP/Common/MyWindows.h | 10 - CPP/Common/Wildcard.cpp | 2 + CPP/Windows/Control/Dialog.cpp | 4 +- CPP/Windows/FileName.h | 2 + CPP/Windows/PropVariant.cpp | 2 +- CPP/Windows/PropVariantUtils.cpp | 5 +- DOC/7zip.inf | 6 +- DOC/7zip.nsi | 2 +- DOC/7zip.wxs | 2 +- DOC/Methods.txt | 8 +- DOC/history.txt | 5 + DOC/lzma.txt | 2 +- DOC/readme.txt | 2 +- 103 files changed, 4639 insertions(+), 623 deletions(-) create mode 100755 C/7zAlloc.c create mode 100755 C/7zAlloc.h delete mode 100755 C/Util/7z/7zAlloc.c delete mode 100755 C/Util/7z/7zAlloc.h create mode 100755 C/Util/SfxSetup/SfxSetup.c create mode 100755 C/Util/SfxSetup/SfxSetup.dsp create mode 100755 C/Util/SfxSetup/SfxSetup.dsw create mode 100755 C/Util/SfxSetup/makefile create mode 100755 C/Util/SfxSetup/makefile_con create mode 100755 C/Util/SfxSetup/resource.rc create mode 100755 C/Util/SfxSetup/setup.ico create mode 100755 CPP/7zip/Archive/CramfsHandler.cpp create mode 100755 CPP/7zip/Archive/Icons/squashfs.ico create mode 100755 CPP/7zip/Archive/SquashfsHandler.cpp diff --git a/C/7zAlloc.c b/C/7zAlloc.c new file mode 100755 index 00000000..964b28db --- /dev/null +++ b/C/7zAlloc.c @@ -0,0 +1,76 @@ +/* 7zAlloc.c -- Allocation functions +2010-10-29 : Igor Pavlov : Public domain */ + +#include "7zAlloc.h" + +/* #define _SZ_ALLOC_DEBUG */ +/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ + +#ifdef _SZ_ALLOC_DEBUG + +#ifdef _WIN32 +#include +#endif + +#include +int g_allocCount = 0; +int g_allocCountTemp = 0; + +#endif + +void *SzAlloc(void *p, size_t size) +{ + p = p; + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); + g_allocCount++; + #endif + return malloc(size); +} + +void SzFree(void *p, void *address) +{ + p = p; + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + { + g_allocCount--; + fprintf(stderr, "\nFree; count = %10d", g_allocCount); + } + #endif + free(address); +} + +void *SzAllocTemp(void *p, size_t size) +{ + p = p; + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); + g_allocCountTemp++; + #ifdef _WIN32 + return HeapAlloc(GetProcessHeap(), 0, size); + #endif + #endif + return malloc(size); +} + +void SzFreeTemp(void *p, void *address) +{ + p = p; + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + { + g_allocCountTemp--; + fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); + } + #ifdef _WIN32 + HeapFree(GetProcessHeap(), 0, address); + return; + #endif + #endif + free(address); +} diff --git a/C/7zAlloc.h b/C/7zAlloc.h new file mode 100755 index 00000000..3344e937 --- /dev/null +++ b/C/7zAlloc.h @@ -0,0 +1,15 @@ +/* 7zAlloc.h -- Allocation functions +2010-10-29 : Igor Pavlov : Public domain */ + +#ifndef __7Z_ALLOC_H +#define __7Z_ALLOC_H + +#include + +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); + +#endif diff --git a/C/7zDec.c b/C/7zDec.c index 0df807b1..b6d80995 100755 --- a/C/7zDec.c +++ b/C/7zDec.c @@ -1,5 +1,5 @@ /* 7zDec.c -- Decoding from 7z folder -2010-03-15 : Igor Pavlov : Public domain */ +2010-11-02 : Igor Pavlov : Public domain */ #include @@ -18,9 +18,13 @@ #define k_Copy 0 #define k_LZMA2 0x21 -#define k_LZMA 0x30101 -#define k_BCJ 0x03030103 -#define k_BCJ2 0x0303011B +#define k_LZMA 0x30101 +#define k_BCJ 0x03030103 +#define k_PPC 0x03030205 +#define k_ARM 0x03030501 +#define k_ARMT 0x03030701 +#define k_SPARC 0x03030805 +#define k_BCJ2 0x0303011B #ifdef _7ZIP_PPMD_SUPPPORT @@ -260,7 +264,6 @@ static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c) IS_MAIN_METHOD((UInt32)c->MethodID); } -#define IS_BCJ(c) ((c)->MethodID == k_BCJ && (c)->NumInStreams == 1 && (c)->NumOutStreams == 1) #define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1) static SRes CheckSupportedFolder(const CSzFolder *f) @@ -277,11 +280,24 @@ static SRes CheckSupportedFolder(const CSzFolder *f) } if (f->NumCoders == 2) { - if (!IS_BCJ(&f->Coders[1]) || - f->NumPackStreams != 1 || f->PackStreams[0] != 0 || + CSzCoderInfo *c = &f->Coders[1]; + if (c->MethodID > (UInt32)0xFFFFFFFF || + c->NumInStreams != 1 || + c->NumOutStreams != 1 || + f->NumPackStreams != 1 || + f->PackStreams[0] != 0 || f->NumBindPairs != 1 || - f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0) + f->BindPairs[0].InIndex != 1 || + f->BindPairs[0].OutIndex != 0) return SZ_ERROR_UNSUPPORTED; + switch ((UInt32)c->MethodID) + { + case k_BCJ: + case k_ARM: + break; + default: + return SZ_ERROR_UNSUPPORTED; + } return SZ_OK; } if (f->NumCoders == 4) @@ -314,6 +330,8 @@ static UInt64 GetSum(const UInt64 *values, UInt32 index) return sum; } +#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break; + static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes, ILookInStream *inStream, UInt64 startPos, Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, @@ -391,14 +409,6 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes, #endif } } - else if (coder->MethodID == k_BCJ) - { - UInt32 state; - if (ci != 1) - return SZ_ERROR_UNSUPPORTED; - x86_Convert_Init(state); - x86_Convert(outBuffer, outSize, 0, &state, 0); - } else if (coder->MethodID == k_BCJ2) { UInt64 offset = GetSum(packSizes, 1); @@ -425,7 +435,23 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes, RINOK(res) } else - return SZ_ERROR_UNSUPPORTED; + { + if (ci != 1) + return SZ_ERROR_UNSUPPORTED; + switch(coder->MethodID) + { + case k_BCJ: + { + UInt32 state; + x86_Convert_Init(state); + x86_Convert(outBuffer, outSize, 0, &state, 0); + break; + } + CASE_BRA_CONV(ARM) + default: + return SZ_ERROR_UNSUPPORTED; + } + } } return SZ_OK; } diff --git a/C/7zIn.c b/C/7zIn.c index 35c056d6..ec93a43f 100755 --- a/C/7zIn.c +++ b/C/7zIn.c @@ -1,5 +1,5 @@ /* 7zIn.c -- 7z Input functions -2010-03-11 : Igor Pavlov : Public domain */ +2010-10-29 : Igor Pavlov : Public domain */ #include @@ -1218,12 +1218,16 @@ static SRes SzArEx_Open2( ISzAlloc *allocTemp) { Byte header[k7zStartHeaderSize]; + Int64 startArcPos; UInt64 nextHeaderOffset, nextHeaderSize; size_t nextHeaderSizeT; UInt32 nextHeaderCRC; CBuf buffer; SRes res; + startArcPos = 0; + RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR)); + RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)); if (!TestSignatureCandidate(header)) @@ -1235,7 +1239,7 @@ static SRes SzArEx_Open2( nextHeaderSize = GetUi64(header + 20); nextHeaderCRC = GetUi32(header + 28); - p->startPosAfterHeader = k7zStartHeaderSize; + p->startPosAfterHeader = startArcPos + k7zStartHeaderSize; if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) return SZ_ERROR_CRC; @@ -1252,13 +1256,13 @@ static SRes SzArEx_Open2( { Int64 pos = 0; RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END)); - if ((UInt64)pos < nextHeaderOffset || - (UInt64)pos < k7zStartHeaderSize + nextHeaderOffset || - (UInt64)pos < k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) + if ((UInt64)pos < startArcPos + nextHeaderOffset || + (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset || + (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) return SZ_ERROR_INPUT_EOF; } - RINOK(LookInStream_SeekTo(inStream, k7zStartHeaderSize + nextHeaderOffset)); + RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset)); if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp)) return SZ_ERROR_MEM; diff --git a/C/7zVersion.h b/C/7zVersion.h index 1ac7a662..eee6be7d 100755 --- a/C/7zVersion.h +++ b/C/7zVersion.h @@ -1,7 +1,7 @@ #define MY_VER_MAJOR 9 -#define MY_VER_MINOR 17 +#define MY_VER_MINOR 18 #define MY_VER_BUILD 0 -#define MY_VERSION "9.17 beta" -#define MY_DATE "2010-10-04" +#define MY_VERSION "9.18 beta" +#define MY_DATE "2010-11-02" #define MY_COPYRIGHT ": Igor Pavlov : Public domain" #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE diff --git a/C/CpuArch.c b/C/CpuArch.c index 5298e006..260cc1f4 100755 --- a/C/CpuArch.c +++ b/C/CpuArch.c @@ -1,5 +1,5 @@ /* CpuArch.c -- CPU specific code -2009-12-12: Igor Pavlov : Public domain */ +2010-10-26: Igor Pavlov : Public domain */ #include "CpuArch.h" @@ -72,13 +72,13 @@ static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) #else - __asm__ __volatile__ ( - "cpuid" - : "=a" (*a) , - "=b" (*b) , - "=c" (*c) , - "=d" (*d) - : "0" (function)) ; + __asm__ __volatile__ ( + "cpuid" + : "=a" (*a) , + "=b" (*b) , + "=c" (*c) , + "=d" (*d) + : "0" (function)) ; #endif diff --git a/C/CpuArch.h b/C/CpuArch.h index aec3c416..01930c7e 100755 --- a/C/CpuArch.h +++ b/C/CpuArch.h @@ -1,5 +1,5 @@ /* CpuArch.h -- CPU specific code -2010-05-20: Igor Pavlov : Public domain */ +2010-10-26: Igor Pavlov : Public domain */ #ifndef __CPU_ARCH_H #define __CPU_ARCH_H @@ -40,14 +40,26 @@ If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of pla #define MY_CPU_ARM_LE #endif +#if defined(_WIN32) && defined(_M_IA64) +#define MY_CPU_IA64_LE +#endif + #if defined(MY_CPU_X86_OR_AMD64) #define MY_CPU_LE_UNALIGN #endif -#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE) +#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE) || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__) #define MY_CPU_LE #endif +#if defined(__BIG_ENDIAN__) +#define MY_CPU_BE +#endif + +#if defined(MY_CPU_LE) && defined(MY_CPU_BE) +Stop_Compiling_Bad_Endian +#endif + #ifdef MY_CPU_LE_UNALIGN #define GetUi16(p) (*(const UInt16 *)(p)) diff --git a/C/Types.h b/C/Types.h index 07e1aa78..7732c240 100755 --- a/C/Types.h +++ b/C/Types.h @@ -1,5 +1,5 @@ /* Types.h -- Basic types -2010-04-16 : Igor Pavlov : Public domain */ +2010-10-09 : Igor Pavlov : Public domain */ #ifndef __7Z_TYPES_H #define __7Z_TYPES_H @@ -233,6 +233,22 @@ typedef struct #define IAlloc_Alloc(p, size) (p)->Alloc((p), size) #define IAlloc_Free(p, a) (p)->Free((p), a) +#ifdef _WIN32 + +#define CHAR_PATH_SEPARATOR '\\' +#define WCHAR_PATH_SEPARATOR L'\\' +#define STRING_PATH_SEPARATOR "\\" +#define WSTRING_PATH_SEPARATOR L"\\" + +#else + +#define CHAR_PATH_SEPARATOR '/' +#define WCHAR_PATH_SEPARATOR L'/' +#define STRING_PATH_SEPARATOR "/" +#define WSTRING_PATH_SEPARATOR L"/" + +#endif + EXTERN_C_END #endif diff --git a/C/Util/7z/7z.dsp b/C/Util/7z/7z.dsp index 0d4d04c8..21dd5995 100755 --- a/C/Util/7z/7z.dsp +++ b/C/Util/7z/7z.dsp @@ -92,6 +92,14 @@ SOURCE=..\..\7z.h # End Source File # Begin Source File +SOURCE=..\..\7zAlloc.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zAlloc.h +# End Source File +# Begin Source File + SOURCE=..\..\7zBuf.c # End Source File # Begin Source File @@ -141,6 +149,10 @@ SOURCE=..\..\Bcj2.h # End Source File # Begin Source File +SOURCE=..\..\Bra.c +# End Source File +# Begin Source File + SOURCE=..\..\Bra.h # End Source File # Begin Source File @@ -196,14 +208,6 @@ SOURCE=..\..\Types.h # End Group # Begin Source File -SOURCE=.\7zAlloc.c -# End Source File -# Begin Source File - -SOURCE=.\7zAlloc.h -# End Source File -# Begin Source File - SOURCE=.\7zMain.c # End Source File # End Target diff --git a/C/Util/7z/7zAlloc.c b/C/Util/7z/7zAlloc.c deleted file mode 100755 index 4bfaf42a..00000000 --- a/C/Util/7z/7zAlloc.c +++ /dev/null @@ -1,77 +0,0 @@ -/* 7zAlloc.c -- Allocation functions -2008-10-04 : Igor Pavlov : Public domain */ - -#include -#include "7zAlloc.h" - -/* #define _SZ_ALLOC_DEBUG */ -/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ - -#ifdef _SZ_ALLOC_DEBUG - -#ifdef _WIN32 -#include -#endif - -#include -int g_allocCount = 0; -int g_allocCountTemp = 0; - -#endif - -void *SzAlloc(void *p, size_t size) -{ - p = p; - if (size == 0) - return 0; - #ifdef _SZ_ALLOC_DEBUG - fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); - g_allocCount++; - #endif - return malloc(size); -} - -void SzFree(void *p, void *address) -{ - p = p; - #ifdef _SZ_ALLOC_DEBUG - if (address != 0) - { - g_allocCount--; - fprintf(stderr, "\nFree; count = %10d", g_allocCount); - } - #endif - free(address); -} - -void *SzAllocTemp(void *p, size_t size) -{ - p = p; - if (size == 0) - return 0; - #ifdef _SZ_ALLOC_DEBUG - fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); - g_allocCountTemp++; - #ifdef _WIN32 - return HeapAlloc(GetProcessHeap(), 0, size); - #endif - #endif - return malloc(size); -} - -void SzFreeTemp(void *p, void *address) -{ - p = p; - #ifdef _SZ_ALLOC_DEBUG - if (address != 0) - { - g_allocCountTemp--; - fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); - } - #ifdef _WIN32 - HeapFree(GetProcessHeap(), 0, address); - return; - #endif - #endif - free(address); -} diff --git a/C/Util/7z/7zAlloc.h b/C/Util/7z/7zAlloc.h deleted file mode 100755 index a5e88e47..00000000 --- a/C/Util/7z/7zAlloc.h +++ /dev/null @@ -1,23 +0,0 @@ -/* 7zAlloc.h -- Allocation functions -2009-02-07 : Igor Pavlov : Public domain */ - -#ifndef __7Z_ALLOC_H -#define __7Z_ALLOC_H - -#include - -#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/Util/7z/7zMain.c b/C/Util/7z/7zMain.c index 2e6c6622..9496dc07 100755 --- a/C/Util/7z/7zMain.c +++ b/C/Util/7z/7zMain.c @@ -1,16 +1,15 @@ /* 7zMain.c - Test application for 7z Decoder -2010-09-20 : Igor Pavlov : Public domain */ +2010-10-28 : Igor Pavlov : Public domain */ #include #include #include "../../7z.h" +#include "../../7zAlloc.h" #include "../../7zCrc.h" #include "../../7zFile.h" #include "../../7zVersion.h" -#include "7zAlloc.h" - #ifndef USE_WINDOWS_FILE /* for mkdir */ #ifdef _WIN32 @@ -21,12 +20,6 @@ #endif #endif -#ifdef _WIN32 -#define CHAR_PATH_SEPARATOR '\\' -#else -#define CHAR_PATH_SEPARATOR '/' -#endif - static ISzAlloc g_Alloc = { SzAlloc, SzFree }; static int Buf_EnsureSize(CBuf *dest, size_t size) @@ -117,7 +110,14 @@ static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s, int fileMode) { char defaultChar = '_'; BOOL defUsed; - int numChars = WideCharToMultiByte(fileMode ? (AreFileApisANSI() ? CP_ACP : CP_OEMCP) : CP_OEMCP, + int numChars = WideCharToMultiByte(fileMode ? + ( + #ifdef UNDER_CE + CP_ACP + #else + AreFileApisANSI() ? CP_ACP : CP_OEMCP + #endif + ) : CP_OEMCP, 0, s, len, (char *)buf->data, size, &defaultChar, &defUsed); if (numChars == 0 || numChars >= size) return SZ_ERROR_FAIL; diff --git a/C/Util/7z/makefile b/C/Util/7z/makefile index 3b762e65..96edda42 100755 --- a/C/Util/7z/makefile +++ b/C/Util/7z/makefile @@ -4,6 +4,7 @@ CFLAGS = $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT PROG = 7zDec.exe C_OBJS = \ + $O\7zAlloc.obj \ $O\7zBuf.obj \ $O\7zBuf2.obj \ $O\7zCrc.obj \ @@ -13,6 +14,7 @@ C_OBJS = \ $O\7zIn.obj \ $O\7zStream.obj \ $O\Bcj2.obj \ + $O\Bra.obj \ $O\Bra86.obj \ $O\CpuArch.obj \ $O\Lzma2Dec.obj \ @@ -21,7 +23,6 @@ C_OBJS = \ $O\Ppmd7Dec.obj \ 7Z_OBJS = \ - $O\7zAlloc.obj \ $O\7zMain.obj \ OBJS = \ diff --git a/C/Util/7z/makefile.gcc b/C/Util/7z/makefile.gcc index 8f95f890..364c6474 100755 --- a/C/Util/7z/makefile.gcc +++ b/C/Util/7z/makefile.gcc @@ -4,7 +4,7 @@ LIB = RM = rm -f CFLAGS = -c -O2 -Wall -OBJS = 7zMain.o 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zCrcOpt.o 7zDec.o 7zIn.o CpuArch.o LzmaDec.o Lzma2Dec.o Bra86.o Bcj2.o Ppmd7.o Ppmd7Dec.o 7zFile.o 7zStream.o +OBJS = 7zMain.o 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zCrcOpt.o 7zDec.o 7zIn.o CpuArch.o LzmaDec.o Lzma2Dec.o Bra.o Bra86.o Bcj2.o Ppmd7.o Ppmd7Dec.o 7zFile.o 7zStream.o all: $(PROG) @@ -15,7 +15,7 @@ $(PROG): $(OBJS) $(CXX) $(CFLAGS) 7zMain.c 7zAlloc.o: 7zAlloc.c - $(CXX) $(CFLAGS) 7zAlloc.c + $(CXX) $(CFLAGS) ../../7zAlloc.c 7zBuf.o: ../../7zBuf.c $(CXX) $(CFLAGS) ../../7zBuf.c @@ -44,6 +44,9 @@ LzmaDec.o: ../../LzmaDec.c Lzma2Dec.o: ../../Lzma2Dec.c $(CXX) $(CFLAGS) ../../Lzma2Dec.c +Bra.o: ../../Bra.c + $(CXX) $(CFLAGS) ../../Bra.c + Bra86.o: ../../Bra86.c $(CXX) $(CFLAGS) ../../Bra86.c diff --git a/C/Util/SfxSetup/SfxSetup.c b/C/Util/SfxSetup/SfxSetup.c new file mode 100755 index 00000000..1a64c6e8 --- /dev/null +++ b/C/Util/SfxSetup/SfxSetup.c @@ -0,0 +1,591 @@ +/* SfxSetup.c - 7z SFX Setup +2010-11-02 : Igor Pavlov : Public domain */ + +#ifndef UNICODE +#define UNICODE +#endif + +#ifndef _UNICODE +#define _UNICODE +#endif + +#ifdef _CONSOLE +#include +#endif + +#include "../../7z.h" +#include "../../7zAlloc.h" +#include "../../7zCrc.h" +#include "../../7zFile.h" +#include "../../CpuArch.h" + +#define k_EXE_ExtIndex 1 + +static const char *kExts[] = +{ + "bat", + "exe", + "inf", + "msi", + #ifdef UNDER_CE + "cab", + #endif + "html", + "htm" +}; + +static const char *kNames[] = +{ + "setup", + "install", + "run", + "start" +}; + +static unsigned FindExt(const wchar_t *s, unsigned *extLen) +{ + unsigned len = (unsigned)wcslen(s); + unsigned i; + for (i = len; i > 0; i--) + { + if (s[i - 1] == '.') + { + *extLen = len - i; + return i - 1; + } + } + *extLen = 0; + return len; +} + +#define MAKE_CHAR_UPPER(c) ((((c) >= 'a' && (c) <= 'z') ? (c) -= 0x20 : (c))) + +static unsigned FindItem(const char **items, unsigned num, const wchar_t *s, unsigned len) +{ + unsigned i; + for (i = 0; i < num; i++) + { + const char *item = items[i]; + unsigned itemLen = (unsigned)strlen(item); + unsigned j; + if (len != itemLen) + continue; + for (j = 0; j < len; j++) + { + unsigned c = item[j]; + if (c != s[j] && MAKE_CHAR_UPPER(c) != s[j]) + break; + } + if (j == len) + return i; + } + return i; +} + +#ifdef _CONSOLE +static BOOL WINAPI HandlerRoutine(DWORD ctrlType) +{ + ctrlType = ctrlType; + return TRUE; +} +#endif + +static void PrintErrorMessage(const char *message) +{ + #ifdef _CONSOLE + printf("\n7-Zip Error: %s\n", message); + #else + #ifdef UNDER_CE + WCHAR messageW[256 + 4]; + unsigned i; + for (i = 0; i < 256 && message[i] != 0; i++) + messageW[i] = message[i]; + messageW[i] = 0; + MessageBoxW(0, messageW, L"7-Zip Error", MB_ICONERROR); + #else + MessageBoxA(0, message, "7-Zip Error", MB_ICONERROR); + #endif + #endif +} + +static WRes MyCreateDir(const WCHAR *name) +{ + return CreateDirectoryW(name, NULL) ? 0 : GetLastError(); +} + +#ifdef UNDER_CE +#define kBufferSize (1 << 13) +#else +#define kBufferSize (1 << 15) +#endif + +#define kSignatureSearchLimit (1 << 22) + +static Bool FindSignature(CSzFile *stream, UInt64 *resPos) +{ + Byte buf[kBufferSize]; + size_t numPrevBytes = 0; + *resPos = 0; + for (;;) + { + size_t numTests, pos; + if (*resPos > kSignatureSearchLimit) + return False; + + do + { + size_t processed = kBufferSize - numPrevBytes; + if (File_Read(stream, buf + numPrevBytes, &processed) != 0) + return False; + if (processed == 0) + return False; + numPrevBytes += processed; + } + while (numPrevBytes <= k7zStartHeaderSize); + + numTests = numPrevBytes - k7zStartHeaderSize; + for (pos = 0; pos < numTests; pos++) + { + for (; buf[pos] != '7' && pos < numTests; pos++); + if (pos == numTests) + break; + if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0) + if (CrcCalc(buf + pos + 12, 20) == GetUi32(buf + pos + 8)) + { + *resPos += pos; + return True; + } + } + *resPos += numTests; + numPrevBytes -= numTests; + memmove(buf, buf + numTests, numPrevBytes); + } +} + +static Bool DoesFileOrDirExist(const WCHAR *path) +{ + WIN32_FIND_DATAW fd; + HANDLE handle; + handle = FindFirstFileW(path, &fd); + if (handle == INVALID_HANDLE_VALUE) + return False; + FindClose(handle); + return True; +} + +static WRes RemoveDirWithSubItems(WCHAR *path) +{ + WIN32_FIND_DATAW fd; + HANDLE handle; + WRes res = 0; + size_t len = wcslen(path); + wcscpy(path + len, L"*"); + handle = FindFirstFileW(path, &fd); + path[len] = L'\0'; + if (handle == INVALID_HANDLE_VALUE) + return GetLastError(); + for (;;) + { + if (wcscmp(fd.cFileName, L".") != 0 && + wcscmp(fd.cFileName, L"..") != 0) + { + wcscpy(path + len, fd.cFileName); + if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) + { + wcscat(path, L"\\"); + res = RemoveDirWithSubItems(path); + } + else + { + SetFileAttributesW(path, 0); + if (DeleteFileW(path) == 0) + res = GetLastError(); + } + if (res != 0) + break; + } + if (!FindNextFileW(handle, &fd)) + { + res = GetLastError(); + if (res == ERROR_NO_MORE_FILES) + res = 0; + break; + } + } + path[len] = L'\0'; + FindClose(handle); + if (res == 0) + { + if (!RemoveDirectoryW(path)) + res = GetLastError(); + } + return res; +} + +#ifdef _CONSOLE +int MY_CDECL main() +#else +int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + #ifdef UNDER_CE + LPWSTR + #else + LPSTR + #endif + lpCmdLine, int nCmdShow) +#endif +{ + CFileInStream archiveStream; + CLookToRead lookStream; + CSzArEx db; + SRes res = SZ_OK; + ISzAlloc allocImp; + ISzAlloc allocTempImp; + WCHAR sfxPath[MAX_PATH + 2]; + WCHAR path[MAX_PATH * 3 + 2]; + size_t pathLen; + DWORD winRes; + const wchar_t *cmdLineParams; + const char *errorMessage = NULL; + Bool useShellExecute = True; + + #ifdef _CONSOLE + SetConsoleCtrlHandler(HandlerRoutine, TRUE); + #else + hInstance = hInstance; + hPrevInstance = hPrevInstance; + lpCmdLine = lpCmdLine; + nCmdShow = nCmdShow; + #endif + + CrcGenerateTable(); + + allocImp.Alloc = SzAlloc; + allocImp.Free = SzFree; + + allocTempImp.Alloc = SzAllocTemp; + allocTempImp.Free = SzFreeTemp; + + FileInStream_CreateVTable(&archiveStream); + LookToRead_CreateVTable(&lookStream, False); + + winRes = GetModuleFileNameW(NULL, sfxPath, MAX_PATH); + if (winRes == 0 || winRes > MAX_PATH) + return 1; + { + cmdLineParams = GetCommandLineW(); + #ifndef UNDER_CE + { + Bool quoteMode = False; + for (;; cmdLineParams++) + { + wchar_t c = *cmdLineParams; + if (c == L'\"') + quoteMode = !quoteMode; + else if (c == 0 || (c == L' ' && !quoteMode)) + break; + } + } + #endif + } + + { + unsigned i; + DWORD d; + winRes = GetTempPathW(MAX_PATH, path); + if (winRes == 0 || winRes > MAX_PATH) + return 1; + pathLen = wcslen(path); + d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId(); + for (i = 0;; i++, d += GetTickCount()) + { + if (i >= 100) + { + res = SZ_ERROR_FAIL; + break; + } + wcscpy(path + pathLen, L"7z"); + + { + wchar_t *s = path + wcslen(path); + UInt32 value = d; + unsigned k; + for (k = 0; k < 8; k++) + { + unsigned t = value & 0xF; + value >>= 4; + s[7 - k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } + s[k] = '\0'; + } + + if (DoesFileOrDirExist(path)) + continue; + if (CreateDirectoryW(path, NULL)) + { + wcscat(path, L"\\"); + pathLen = wcslen(path); + break; + } + if (GetLastError() != ERROR_ALREADY_EXISTS) + { + res = SZ_ERROR_FAIL; + break; + } + } + if (res != SZ_OK) + errorMessage = "Can't create temp folder"; + } + + if (res != SZ_OK) + { + if (!errorMessage) + errorMessage = "Error"; + PrintErrorMessage(errorMessage); + return 1; + } + + if (InFile_OpenW(&archiveStream.file, sfxPath) != 0) + { + errorMessage = "can not open input file"; + res = SZ_ERROR_FAIL; + } + else + { + UInt64 pos = 0; + if (!FindSignature(&archiveStream.file, &pos)) + res = SZ_ERROR_FAIL; + else if (File_Seek(&archiveStream.file, (Int64 *)&pos, SZ_SEEK_SET) != 0) + res = SZ_ERROR_FAIL; + if (res != 0) + errorMessage = "Can't find 7z archive"; + } + + if (res == SZ_OK) + { + lookStream.realStream = &archiveStream.s; + LookToRead_Init(&lookStream); + } + + SzArEx_Init(&db); + if (res == SZ_OK) + { + res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); + } + if (res == SZ_OK) + { + UInt32 executeFileIndex = (UInt32)(Int32)-1; + UInt32 minPrice = 1 << 30; + UInt32 i; + UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ + 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) */ + + for (i = 0; i < db.db.NumFiles; i++) + { + size_t offset = 0; + size_t outSizeProcessed = 0; + const CSzFileItem *f = db.db.Files + i; + size_t len; + WCHAR *temp; + len = SzArEx_GetFileNameUtf16(&db, i, NULL); + + if (len >= MAX_PATH) + { + res = SZ_ERROR_FAIL; + break; + } + + temp = path + pathLen; + + SzArEx_GetFileNameUtf16(&db, i, temp); + { + res = SzArEx_Extract(&db, &lookStream.s, i, + &blockIndex, &outBuffer, &outBufferSize, + &offset, &outSizeProcessed, + &allocImp, &allocTempImp); + if (res != SZ_OK) + break; + } + { + CSzFile outFile; + size_t processedSize; + size_t j; + size_t nameStartPos = 0; + for (j = 0; temp[j] != 0; j++) + { + if (temp[j] == '/') + { + temp[j] = 0; + MyCreateDir(path); + temp[j] = CHAR_PATH_SEPARATOR; + nameStartPos = j + 1; + } + } + + if (f->IsDir) + { + MyCreateDir(path); + continue; + } + else + { + unsigned extLen; + const WCHAR *name = temp + nameStartPos; + unsigned len = (unsigned)wcslen(name); + unsigned nameLen = FindExt(temp + nameStartPos, &extLen); + unsigned extPrice = FindItem(kExts, sizeof(kExts) / sizeof(kExts[0]), name + len - extLen, extLen); + unsigned namePrice = FindItem(kNames, sizeof(kNames) / sizeof(kNames[0]), name, nameLen); + + unsigned price = namePrice + extPrice * 64 + (nameStartPos == 0 ? 0 : (1 << 12)); + if (minPrice > price) + { + minPrice = price; + executeFileIndex = i; + useShellExecute = (extPrice != k_EXE_ExtIndex); + } + + if (DoesFileOrDirExist(path)) + { + errorMessage = "Duplicate file"; + res = SZ_ERROR_FAIL; + break; + } + if (OutFile_OpenW(&outFile, path)) + { + errorMessage = "Can't open output file"; + res = SZ_ERROR_FAIL; + break; + } + } + processedSize = outSizeProcessed; + if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed) + { + errorMessage = "Can't write output file"; + res = SZ_ERROR_FAIL; + } + + #ifdef USE_WINDOWS_FILE + if (f->MTimeDefined) + { + FILETIME mTime; + mTime.dwLowDateTime = f->MTime.Low; + mTime.dwHighDateTime = f->MTime.High; + SetFileTime(outFile.handle, NULL, NULL, &mTime); + } + #endif + + { + SRes res2 = File_Close(&outFile); + if (res != SZ_OK) + break; + if (res2 != SZ_OK) + { + res = res2; + break; + } + } + #ifdef USE_WINDOWS_FILE + if (f->AttribDefined) + SetFileAttributesW(path, f->Attrib); + #endif + } + } + + if (res == SZ_OK) + { + if (executeFileIndex == (UInt32)(Int32)-1) + { + errorMessage = "There is no file to execute"; + res = SZ_ERROR_FAIL; + } + else + { + WCHAR *temp = path + pathLen; + UInt32 j; + SzArEx_GetFileNameUtf16(&db, executeFileIndex, temp); + for (j = 0; temp[j] != 0; j++) + if (temp[j] == '/') + temp[j] = CHAR_PATH_SEPARATOR; + } + } + IAlloc_Free(&allocImp, outBuffer); + } + SzArEx_Free(&db, &allocImp); + + File_Close(&archiveStream.file); + + if (res == SZ_OK) + { + HANDLE hProcess = 0; + if (useShellExecute) + { + SHELLEXECUTEINFO ei; + UINT32 executeRes; + BOOL success; + + memset(&ei, 0, sizeof(ei)); + ei.cbSize = sizeof(ei); + ei.lpFile = path; + ei.fMask = SEE_MASK_NOCLOSEPROCESS + #ifndef UNDER_CE + | SEE_MASK_FLAG_DDEWAIT + #endif + ; + if (wcslen(cmdLineParams) != 0) + ei.lpParameters = cmdLineParams; + ei.nShow = SW_SHOWNORMAL; + success = ShellExecuteEx(&ei); + executeRes = (UINT32)(UINT_PTR)ei.hInstApp; + if (!success || (executeRes <= 32 && executeRes != 0)) /* executeRes = 0 in Windows CE */ + res = SZ_ERROR_FAIL; + else + hProcess = ei.hProcess; + } + else + { + STARTUPINFOW si; + PROCESS_INFORMATION pi; + WCHAR cmdLine[MAX_PATH * 3]; + + wcscpy(cmdLine, path); + wcscat(cmdLine, cmdLineParams); + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + if (CreateProcessW(NULL, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) == 0) + res = SZ_ERROR_FAIL; + else + { + CloseHandle(pi.hThread); + hProcess = pi.hProcess; + } + } + if (hProcess != 0) + { + WaitForSingleObject(hProcess, INFINITE); + CloseHandle(hProcess); + } + } + + path[pathLen] = L'\0'; + RemoveDirWithSubItems(path); + + if (res == SZ_OK) + return 0; + + { + if (res == SZ_ERROR_UNSUPPORTED) + errorMessage = "Decoder doesn't support this archive"; + else if (res == SZ_ERROR_MEM) + errorMessage = "Can't allocate required memory"; + else if (res == SZ_ERROR_CRC) + errorMessage = "CRC error"; + else + { + if (!errorMessage) + errorMessage = "ERROR"; + } + if (errorMessage) + PrintErrorMessage(errorMessage); + } + return 1; +} diff --git a/C/Util/SfxSetup/SfxSetup.dsp b/C/Util/SfxSetup/SfxSetup.dsp new file mode 100755 index 00000000..39f876d4 --- /dev/null +++ b/C/Util/SfxSetup/SfxSetup.dsp @@ -0,0 +1,198 @@ +# Microsoft Developer Studio Project File - Name="SfxSetup" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=SfxSetup - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "SfxSetup.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "SfxSetup.mak" CFG="SfxSetup - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "SfxSetup - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "SfxSetup - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "SfxSetup - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 + +!ELSEIF "$(CFG)" == "SfxSetup - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# 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 /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /YX /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" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "SfxSetup - Win32 Release" +# Name "SfxSetup - Win32 Debug" +# Begin Group "Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\7z.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zAlloc.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zAlloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zBuf.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zBuf.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zCrc.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zCrc.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zCrcOpt.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zDec.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zFile.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zFile.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zIn.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zStream.c +# End Source File +# Begin Source File + +SOURCE=..\..\Bcj2.c +# End Source File +# Begin Source File + +SOURCE=..\..\Bcj2.h +# End Source File +# Begin Source File + +SOURCE=..\..\Bra.c +# End Source File +# Begin Source File + +SOURCE=..\..\Bra.h +# End Source File +# Begin Source File + +SOURCE=..\..\Bra86.c +# End Source File +# Begin Source File + +SOURCE=..\..\CpuArch.c +# End Source File +# Begin Source File + +SOURCE=..\..\CpuArch.h +# 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 + +SOURCE=..\..\LzmaDec.h +# End Source File +# Begin Source File + +SOURCE=..\..\Types.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\SfxSetup.c +# End Source File +# End Target +# End Project diff --git a/C/Util/SfxSetup/SfxSetup.dsw b/C/Util/SfxSetup/SfxSetup.dsw new file mode 100755 index 00000000..ea231112 --- /dev/null +++ b/C/Util/SfxSetup/SfxSetup.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "SfxSetup"=.\SfxSetup.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/C/Util/SfxSetup/makefile b/C/Util/SfxSetup/makefile new file mode 100755 index 00000000..f3f78c81 --- /dev/null +++ b/C/Util/SfxSetup/makefile @@ -0,0 +1,35 @@ +PROG = 7zS2.sfx +LIBS = $(LIBS) +CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE + +C_OBJS = \ + $O\7zAlloc.obj \ + $O\7zBuf.obj \ + $O\7zBuf2.obj \ + $O\7zCrc.obj \ + $O\7zCrcOpt.obj \ + $O\7zFile.obj \ + $O\7zDec.obj \ + $O\7zIn.obj \ + $O\7zStream.obj \ + $O\Bcj2.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\CpuArch.obj \ + $O\Lzma2Dec.obj \ + $O\LzmaDec.obj \ + +7Z_OBJS = \ + $O\SfxSetup.obj \ + +OBJS = \ + $(7Z_OBJS) \ + $(C_OBJS) \ + $O\resource.res + +!include "../../../CPP/Build.mak" + +$(7Z_OBJS): $(*B).c + $(COMPL_O1) +$(C_OBJS): ../../$(*B).c + $(COMPL_O1) diff --git a/C/Util/SfxSetup/makefile_con b/C/Util/SfxSetup/makefile_con new file mode 100755 index 00000000..8e1a050d --- /dev/null +++ b/C/Util/SfxSetup/makefile_con @@ -0,0 +1,35 @@ +PROG = 7zS2con.sfx +LIBS = $(LIBS) +CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE -D_CONSOLE + +C_OBJS = \ + $O\7zAlloc.obj \ + $O\7zBuf.obj \ + $O\7zBuf2.obj \ + $O\7zCrc.obj \ + $O\7zCrcOpt.obj \ + $O\7zFile.obj \ + $O\7zDec.obj \ + $O\7zIn.obj \ + $O\7zStream.obj \ + $O\Bcj2.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\CpuArch.obj \ + $O\Lzma2Dec.obj \ + $O\LzmaDec.obj \ + +7Z_OBJS = \ + $O\SfxSetup.obj \ + +OBJS = \ + $(7Z_OBJS) \ + $(C_OBJS) \ + $O\resource.res + +!include "../../../CPP/Build.mak" + +$(7Z_OBJS): $(*B).c + $(COMPL_O1) +$(C_OBJS): ../../$(*B).c + $(COMPL_O1) diff --git a/C/Util/SfxSetup/resource.rc b/C/Util/SfxSetup/resource.rc new file mode 100755 index 00000000..fc1f014e --- /dev/null +++ b/C/Util/SfxSetup/resource.rc @@ -0,0 +1,6 @@ +#include "../../../CPP/7zip/MyVersionInfo.rc" + +MY_VERSION_INFO_APP("7z Setup SFX small", "7zS2.sfx") + +1 ICON "setup.ico" + diff --git a/C/Util/SfxSetup/setup.ico b/C/Util/SfxSetup/setup.ico new file mode 100755 index 00000000..dbb6ca8b Binary files /dev/null and b/C/Util/SfxSetup/setup.ico differ diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp index ec0b5af4..87996bc0 100755 --- a/CPP/7zip/Archive/7z/7zEncode.cpp +++ b/CPP/7zip/Archive/7z/7zEncode.cpp @@ -193,11 +193,9 @@ HRESULT CEncoder::Encode( // UInt64 outStreamStartPos; // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos)); - CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = - new CSequentialInStreamSizeCount2; + CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2; CMyComPtr inStreamSizeCount = inStreamSizeCountSpec; - CSequentialOutStreamSizeCount *outStreamSizeCountSpec = - new CSequentialOutStreamSizeCount; + CSequentialOutStreamSizeCount *outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; CMyComPtr outStreamSizeCount = outStreamSizeCountSpec; inStreamSizeCountSpec->Init(inStream); @@ -226,13 +224,11 @@ HRESULT CEncoder::Encode( _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); if (writeCoderProperties != NULL) { - CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; + CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream; CMyComPtr outStream(outStreamSpec); outStreamSpec->Init(); writeCoderProperties->WriteCoderProperties(outStream); - size_t size = outStreamSpec->GetSize(); - encodingInfo.Props.SetCapacity(size); - memmove(encodingInfo.Props, outStreamSpec->GetBuffer(), size); + outStreamSpec->CopyToBuffer(encodingInfo.Props); } } @@ -250,8 +246,7 @@ HRESULT CEncoder::Encode( RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1, &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress)); - ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, - folderItem); + ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem); packSizes.Add(outStreamSizeCountSpec->GetSize()); diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp index 686bb288..0feb81d2 100755 --- a/CPP/7zip/Archive/7z/7zIn.cpp +++ b/CPP/7zip/Archive/7z/7zIn.cpp @@ -280,28 +280,46 @@ void CInByte2::ReadString(UString &s) _pos += rem + 2; } -static inline bool TestSignatureCandidate(const Byte *p) +static inline bool TestSignature(const Byte *p) { for (int i = 0; i < kSignatureSize; i++) if (p[i] != kSignature[i]) return false; - return (p[0x1A] == 0 && p[0x1B] == 0); + return CrcCalc(p + 12, 20) == GetUi32(p + 8); } +#ifdef FORMAT_7Z_RECOVERY +static inline bool TestSignature2(const Byte *p) +{ + int i; + for (i = 0; i < kSignatureSize; i++) + if (p[i] != kSignature[i]) + return false; + if (CrcCalc(p + 12, 20) == GetUi32(p + 8)) + return true; + for (i = 8; i < kHeaderSize; i++) + if (p[i] != 0) + return false; + return (p[6] != 0 || p[7] != 0); +} +#else +#define TestSignature2(p) TestSignature(p) +#endif + HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { RINOK(ReadStream_FALSE(stream, _header, kHeaderSize)); - if (TestSignatureCandidate(_header)) + if (TestSignature2(_header)) return S_OK; CByteBuffer byteBuffer; const UInt32 kBufferSize = (1 << 16); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; - UInt32 numPrevBytes = kHeaderSize - 1; - memcpy(buffer, _header + 1, numPrevBytes); - UInt64 curTestPos = _arhiveBeginStreamPosition + 1; + UInt32 numPrevBytes = kHeaderSize; + memcpy(buffer, _header, kHeaderSize); + UInt64 curTestPos = _arhiveBeginStreamPosition; for (;;) { if (searchHeaderSizeLimit != NULL) @@ -316,14 +334,14 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search if (processedSize == 0) return S_FALSE; } - while (numPrevBytes < kHeaderSize); - UInt32 numTests = numPrevBytes - kHeaderSize + 1; + while (numPrevBytes <= kHeaderSize); + UInt32 numTests = numPrevBytes - kHeaderSize; for (UInt32 pos = 0; pos < numTests; pos++) { for (; buffer[pos] != '7' && pos < numTests; pos++); if (pos == numTests) break; - if (TestSignatureCandidate(buffer + pos)) + if (TestSignature(buffer + pos)) { memcpy(_header, buffer + pos, kHeaderSize); curTestPos += pos; @@ -812,7 +830,7 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( ThrowUnsupported(); data.SetCapacity(unpackSize); - CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2; + CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream; CMyComPtr outStream = outStreamSpec; outStreamSpec->Init(data, unpackSize); @@ -1164,23 +1182,24 @@ HRESULT CInArchive::ReadDatabase2( nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL)); } + else #endif - - #ifdef FORMAT_7Z_RECOVERY - crcFromArchive = crc; - #endif + { + if (crc != crcFromArchive) + ThrowIncorrect(); + } db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; - if (crc != crcFromArchive) - ThrowIncorrect(); - if (nextHeaderSize == 0) return S_OK; if (nextHeaderSize > (UInt64)0xFFFFFFFF) return S_FALSE; + if ((Int64)nextHeaderOffset < 0) + return S_FALSE; + RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL)); CByteBuffer buffer2; diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/CPP/7zip/Archive/Common/ItemNameUtils.cpp index 71996a63..a5e0dc0b 100755 --- a/CPP/7zip/Archive/Common/ItemNameUtils.cpp +++ b/CPP/7zip/Archive/Common/ItemNameUtils.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../../../C/Types.h" + #include "ItemNameUtils.h" namespace NArchive { diff --git a/CPP/7zip/Archive/Common/MultiStream.cpp b/CPP/7zip/Archive/Common/MultiStream.cpp index cf7dc050..04d11caf 100755 --- a/CPP/7zip/Archive/Common/MultiStream.cpp +++ b/CPP/7zip/Archive/Common/MultiStream.cpp @@ -6,72 +6,61 @@ STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize) { - if(processedSize != NULL) + if (processedSize) *processedSize = 0; - while(_streamIndex < Streams.Size() && size > 0) + if (size == 0) + return S_OK; + if (_pos >= _totalLength) + return (_pos == _totalLength) ? S_OK : E_FAIL; + { - CSubStreamInfo &s = Streams[_streamIndex]; - if (_pos == s.Size) + int left = 0, mid = _streamIndex, right = Streams.Size(); + for (;;) { - _streamIndex++; - _pos = 0; - continue; + CSubStreamInfo &m = Streams[mid]; + if (_pos < m.GlobalOffset) + right = mid; + else if (_pos >= m.GlobalOffset + m.Size) + left = mid + 1; + else + { + _streamIndex = mid; + break; + } + mid = (left + right) / 2; } - RINOK(s.Stream->Seek(s.Pos + _pos, STREAM_SEEK_SET, 0)); - UInt32 sizeToRead = UInt32(MyMin((UInt64)size, s.Size - _pos)); - UInt32 realProcessed; - HRESULT result = s.Stream->Read(data, sizeToRead, &realProcessed); - data = (void *)((Byte *)data + realProcessed); - size -= realProcessed; - if(processedSize != NULL) - *processedSize += realProcessed; - _pos += realProcessed; - _seekPos += realProcessed; - RINOK(result); - break; + _streamIndex = mid; } - return S_OK; + + CSubStreamInfo &s = Streams[_streamIndex]; + UInt64 localPos = _pos - s.GlobalOffset; + if (localPos != s.LocalPos) + { + RINOK(s.Stream->Seek(localPos, STREAM_SEEK_SET, &s.LocalPos)); + } + UInt64 rem = s.Size - localPos; + if (size > rem) + size = (UInt32)rem; + HRESULT result = s.Stream->Read(data, size, &size); + _pos += size; + s.LocalPos += size; + if (processedSize) + *processedSize = size; + return result; } -STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, - UInt64 *newPosition) +STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - UInt64 newPos; switch(seekOrigin) { - case STREAM_SEEK_SET: - newPos = offset; - break; - case STREAM_SEEK_CUR: - newPos = _seekPos + offset; - break; - case STREAM_SEEK_END: - newPos = _totalLength + offset; - break; - default: - return STG_E_INVALIDFUNCTION; - } - _seekPos = 0; - for (_streamIndex = 0; _streamIndex < Streams.Size(); _streamIndex++) - { - UInt64 size = Streams[_streamIndex].Size; - if (newPos < _seekPos + size) - { - _pos = newPos - _seekPos; - _seekPos += _pos; - if (newPosition != 0) - *newPosition = newPos; - return S_OK; - } - _seekPos += size; + case STREAM_SEEK_SET: _pos = offset; break; + case STREAM_SEEK_CUR: _pos = _pos + offset; break; + case STREAM_SEEK_END: _pos = _totalLength + offset; break; + default: return STG_E_INVALIDFUNCTION; } - if (newPos == _seekPos) - { - if (newPosition != 0) - *newPosition = newPos; - return S_OK; - } - return E_FAIL; + if (newPosition != 0) + *newPosition = _pos; + return S_OK; } diff --git a/CPP/7zip/Archive/Common/MultiStream.h b/CPP/7zip/Archive/Common/MultiStream.h index 137c9400..3fceb7cc 100755 --- a/CPP/7zip/Archive/Common/MultiStream.h +++ b/CPP/7zip/Archive/Common/MultiStream.h @@ -1,36 +1,44 @@ // MultiStream.h -#ifndef __MULTISTREAM_H -#define __MULTISTREAM_H +#ifndef __MULTI_STREAM_H +#define __MULTI_STREAM_H #include "../../../Common/MyCom.h" #include "../../../Common/MyVector.h" -#include "../../Archive/IArchive.h" + +#include "../../IStream.h" class CMultiStream: public IInStream, public CMyUnknownImp { - int _streamIndex; UInt64 _pos; - UInt64 _seekPos; UInt64 _totalLength; + int _streamIndex; public: struct CSubStreamInfo { CMyComPtr Stream; - UInt64 Pos; UInt64 Size; + UInt64 GlobalOffset; + UInt64 LocalPos; }; CObjectVector Streams; - void Init() + + HRESULT Init() { - _streamIndex = 0; - _pos = 0; - _seekPos = 0; - _totalLength = 0; + UInt64 total = 0; for (int i = 0; i < Streams.Size(); i++) - _totalLength += Streams[i].Size; + { + CSubStreamInfo &s = Streams[i]; + s.GlobalOffset = total; + total += Streams[i].Size; + RINOK(s.Stream->Seek(0, STREAM_SEEK_CUR, &s.LocalPos)); + } + _totalLength = total; + _pos = 0; + _streamIndex = 0; + return S_OK; } MY_UNKNOWN_IMP1(IInStream) diff --git a/CPP/7zip/Archive/CramfsHandler.cpp b/CPP/7zip/Archive/CramfsHandler.cpp new file mode 100755 index 00000000..a55e3743 --- /dev/null +++ b/CPP/7zip/Archive/CramfsHandler.cpp @@ -0,0 +1,644 @@ +// CramfsHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/7zCrc.h" +#include "../../../C/CpuArch.h" +#include "../../../C/Alloc.h" + +#include "Common/ComTry.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariantUtils.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamObjects.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" +#include "../Compress/ZlibDecoder.h" + +namespace NArchive { +namespace NCramfs { + +#define SIGNATURE { 'C','o','m','p','r','e','s','s','e','d',' ','R','O','M','F','S' } + +static const UInt32 kSignatureSize = 16; +static const char kSignature[kSignatureSize] = SIGNATURE; + +static const UInt32 kArcSizeMax = (256 + 16) << 20; +static const UInt32 kNumFilesMax = (1 << 19); +static const unsigned kNumDirLevelsMax = (1 << 8); + +static const UInt32 kHeaderSize = 0x40; +static const unsigned kHeaderNameSize = 16; +static const UInt32 kNodeSize = 12; + +static const UInt32 kFlag_FsVer2 = (1 << 0); + +static const CUInt32PCharPair k_Flags[] = +{ + { 0, "Ver2" }, + { 1, "SortedDirs" }, + { 8, "Holes" }, + { 9, "WrongSignature" }, + { 10, "ShiftedRootOffset" } +}; + +static const unsigned kBlockSizeLog = 12; +static const UInt32 kBlockSize = 1 << kBlockSizeLog; + +/* +struct CNode +{ + UInt16 Mode; + UInt16 Uid; + UInt32 Size; + Byte Gid; + UInt32 NameLen; + UInt32 Offset; + + void Parse(const Byte *p) + { + Mode = GetUi16(p); + Uid = GetUi16(p + 2); + Size = Get32(p + 4) & 0xFFFFFF; + Gid = p[7]; + NameLen = p[8] & 0x3F; + Offset = Get32(p + 8) >> 6; + } +}; +*/ + +#define Get32(p) (be ? GetBe32(p) : GetUi32(p)) + +static UInt32 GetMode(const Byte *p, bool be) { return be ? GetBe16(p) : GetUi16(p); } +static bool IsDir(const Byte *p, bool be) { return (GetMode(p, be) & 0xF000) == 0x4000; } + +static UInt32 GetSize(const Byte *p, bool be) +{ + if (be) + return GetBe32(p + 4) >> 8; + else + return GetUi32(p + 4) & 0xFFFFFF; +} + +static UInt32 GetNameLen(const Byte *p, bool be) +{ + if (be) + return (p[8] & 0xFC); + else + return (p[8] & 0x3F) << 2; +} + +static UInt32 GetOffset(const Byte *p, bool be) +{ + if (be) + return (GetBe32(p + 8) & 0x03FFFFFF) << 2; + else + return GetUi32(p + 8) >> 6 << 2; +} + +struct CItem +{ + UInt32 Offset; + int Parent; +}; + +struct CHeader +{ + bool be; + UInt32 Size; + UInt32 Flags; + // UInt32 Future; + UInt32 Crc; + // UInt32 Edition; + UInt32 NumBlocks; + UInt32 NumFiles; + char Name[kHeaderNameSize]; + + bool Parse(const Byte *p) + { + if (memcmp(p + 16, kSignature, kSignatureSize) != 0) + return false; + switch(GetUi32(p)) + { + case 0x28CD3D45: be = false; break; + case 0x453DCD28: be = true; break; + default: return false; + } + Size = Get32(p + 4); + Flags = Get32(p + 8); + // Future = Get32(p + 0xC); + Crc = Get32(p + 0x20); + // Edition = Get32(p + 0x24); + NumBlocks = Get32(p + 0x28); + NumFiles = Get32(p + 0x2C); + memcpy(Name, p + 0x30, kHeaderNameSize); + return true; + } + + bool IsVer2() const { return (Flags & kFlag_FsVer2) != 0; } +}; + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + CRecordVector _items; + CMyComPtr _stream; + Byte *_data; + UInt32 _size; + UInt32 _headersSize; + AString _errorMessage; + CHeader _h; + + // Current file + + NCompress::NZlib::CDecoder *_zlibDecoderSpec; + CMyComPtr _zlibDecoder; + + CBufInStream *_inStreamSpec; + CMyComPtr _inStream; + + CBufPtrSeqOutStream *_outStreamSpec; + CMyComPtr _outStream; + + UInt32 _curBlocksOffset; + UInt32 _curNumBlocks; + + HRESULT OpenDir(int parent, UInt32 baseOffsetBase, unsigned level); + HRESULT Open2(IInStream *inStream); + AString GetPath(int index) const; + bool GetPackSize(int index, UInt32 &res) const; + void Free(); +public: + CHandler(): _data(0) {} + ~CHandler() { Free(); } + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); + HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize); +}; + +static const STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI4}, + { NULL, kpidPackSize, VT_UI4}, + { NULL, kpidPosixAttrib, VT_UI4} + // { NULL, kpidOffset, VT_UI4} +}; + +static const STATPROPSTG kArcProps[] = +{ + { NULL, kpidName, VT_BSTR}, + { NULL, kpidBigEndian, VT_BOOL}, + { NULL, kpidCharacts, VT_BSTR}, + { NULL, kpidPhySize, VT_UI4}, + { NULL, kpidHeadersSize, VT_UI4}, + { NULL, kpidNumSubFiles, VT_UI4}, + { NULL, kpidNumBlocks, VT_UI4} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +HRESULT CHandler::OpenDir(int parent, UInt32 baseOffset, unsigned level) +{ + const Byte *p = _data + baseOffset; + bool be = _h.be; + if (!IsDir(p, be)) + return S_OK; + UInt32 offset = GetOffset(p, be); + UInt32 size = GetSize(p, be); + if (offset == 0 && size == 0) + return S_OK; + UInt32 end = offset + size; + if (offset < kHeaderSize || end > _size || level > kNumDirLevelsMax) + return S_FALSE; + if (end > _headersSize) + _headersSize = end; + + int startIndex = _items.Size(); + + while (size != 0) + { + if (size < kNodeSize || (UInt32)_items.Size() >= kNumFilesMax) + return S_FALSE; + CItem item; + item.Parent = parent; + item.Offset = offset; + _items.Add(item); + UInt32 nodeLen = kNodeSize + GetNameLen(_data + offset, be); + if (size < nodeLen) + return S_FALSE; + offset += nodeLen; + size -= nodeLen; + } + + int endIndex = _items.Size(); + for (int i = startIndex; i < endIndex; i++) + { + RINOK(OpenDir(i, _items[i].Offset, level + 1)); + } + return S_OK; +} + +HRESULT CHandler::Open2(IInStream *inStream) +{ + Byte buf[kHeaderSize]; + RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize)); + if (!_h.Parse(buf)) + return S_FALSE; + if (_h.IsVer2()) + { + if (_h.Size < kHeaderSize || _h.Size > kArcSizeMax || _h.NumFiles > kNumFilesMax) + return S_FALSE; + } + else + { + UInt64 size; + RINOK(inStream->Seek(0, STREAM_SEEK_END, &size)); + if (size > kArcSizeMax) + return S_FALSE; + _h.Size = (UInt32)size; + RINOK(inStream->Seek(kHeaderSize, STREAM_SEEK_SET, NULL)); + } + _data = (Byte *)MidAlloc(_h.Size); + if (_data == 0) + return E_OUTOFMEMORY; + memcpy(_data, buf, kHeaderSize); + size_t processed = _h.Size - kHeaderSize; + RINOK(ReadStream(inStream, _data + kHeaderSize, &processed)); + if (processed < kNodeSize) + return S_FALSE; + _size = kHeaderSize + (UInt32)processed; + if (_size != _h.Size) + _errorMessage = "Unexpected end of archive"; + else + { + SetUi32(_data + 0x20, 0); + if (_h.IsVer2()) + if (CrcCalc(_data, _h.Size) != _h.Crc) + _errorMessage = "CRC error"; + } + if (_h.IsVer2()) + _items.Reserve(_h.NumFiles - 1); + return OpenDir(-1, kHeaderSize, 0); +} + +AString CHandler::GetPath(int index) const +{ + unsigned len = 0; + int indexMem = index; + do + { + const CItem &item = _items[index]; + index = item.Parent; + const Byte *p = _data + item.Offset; + unsigned size = GetNameLen(p, _h.be); + p += kNodeSize; + unsigned i; + for (i = 0; i < size && p[i]; i++); + len += i + 1; + } + while (index >= 0); + len--; + + AString path; + char *dest = path.GetBuffer(len) + len; + index = indexMem; + for (;;) + { + const CItem &item = _items[index]; + index = item.Parent; + const Byte *p = _data + item.Offset; + unsigned size = GetNameLen(p, _h.be); + p += kNodeSize; + unsigned i; + for (i = 0; i < size && p[i]; i++); + dest -= i; + memcpy(dest, p, i); + if (index < 0) + break; + *(--dest) = CHAR_PATH_SEPARATOR; + } + path.ReleaseBuffer(len); + return path; +} + +bool CHandler::GetPackSize(int index, UInt32 &res) const +{ + const CItem &item = _items[index]; + const Byte *p = _data + item.Offset; + bool be = _h.be; + UInt32 offset = GetOffset(p, be); + if (offset < kHeaderSize) + return false; + UInt32 numBlocks = (GetSize(p, be) + kBlockSize - 1) >> kBlockSizeLog; + UInt32 start = offset + numBlocks * 4; + if (start > _size) + return false; + UInt32 end = Get32(_data + start - 4); + if (end < start) + return false; + res = end - start; + return true; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* callback */) +{ + COM_TRY_BEGIN + { + Close(); + RINOK(Open2(stream)); + _stream = stream; + } + return S_OK; + COM_TRY_END +} + +void CHandler::Free() +{ + MidFree(_data); + _data = 0; +} + +STDMETHODIMP CHandler::Close() +{ + _headersSize = 0; + _items.Clear(); + _stream.Release(); + _errorMessage.Empty(); + Free(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _items.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidName: + { + char dest[kHeaderNameSize + 4]; + memcpy(dest, _h.Name, kHeaderNameSize); + dest[kHeaderNameSize] = 0; + prop = dest; + break; + } + case kpidBigEndian: prop = _h.be; break; + case kpidCharacts: FLAGS_TO_PROP(k_Flags, _h.Flags, prop); break; + case kpidNumBlocks: if (_h.IsVer2()) prop = _h.NumBlocks; break; + case kpidNumSubFiles: if (_h.IsVer2()) prop = _h.NumFiles; break; + case kpidPhySize: if (_h.IsVer2()) prop = _h.Size; break; + case kpidHeadersSize: prop = _headersSize; break; + case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; 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 Byte *p = _data + item.Offset; + bool be = _h.be; + bool isDir = IsDir(p, be); + switch(propID) + { + case kpidPath: prop = MultiByteToUnicodeString(GetPath(index), CP_OEMCP); break; + case kpidIsDir: prop = isDir; break; + // case kpidOffset: prop = (UInt32)GetOffset(p, be); break; + case kpidSize: if (!isDir) prop = GetSize(p, be); break; + case kpidPackSize: + if (!isDir) + { + UInt32 size; + if (GetPackSize(index, size)) + prop = size; + } + break; + case kpidPosixAttrib: prop = (UInt32)GetMode(p, be); break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +class CCramfsInStream: public CCachedInStream +{ + HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize); +public: + CHandler *Handler; +}; + +HRESULT CCramfsInStream::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) +{ + return Handler->ReadBlock(blockIndex, dest, blockSize); +} + +HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) +{ + if (!_zlibDecoder) + { + _zlibDecoderSpec = new NCompress::NZlib::CDecoder(); + _zlibDecoder = _zlibDecoderSpec; + } + if (!_inStream) + { + _inStreamSpec = new CBufInStream(); + _inStream = _inStreamSpec; + } + if (!_outStream) + { + _outStreamSpec = new CBufPtrSeqOutStream(); + _outStream = _outStreamSpec; + } + bool be = _h.be; + const Byte *p = _data + (_curBlocksOffset + (UInt32)blockIndex * 4); + UInt32 start = (blockIndex == 0 ? _curBlocksOffset + _curNumBlocks * 4: Get32(p - 4)); + UInt32 end = Get32(p); + if (end < start || end > _size) + return S_FALSE; + UInt32 inSize = end - start; + _inStreamSpec->Init(_data + start, inSize); + _outStreamSpec->Init(dest, blockSize); + RINOK(_zlibDecoder->Code(_inStream, _outStream, NULL, NULL, NULL)); + return (_zlibDecoderSpec->GetInputProcessedSize() == inSize && + _outStreamSpec->GetPos() == blockSize) ? S_OK : S_FALSE; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _items.Size(); + if (numItems == 0) + return S_OK; + bool be = _h.be; + UInt64 totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + { + const Byte *p = _data + _items[allFilesMode ? i : indices[i]].Offset; + if (!IsDir(p, be)) + totalSize += GetSize(p, be); + } + extractCallback->SetTotal(totalSize); + + UInt64 totalPackSize; + totalSize = totalPackSize = 0; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(streamSpec); + streamSpec->SetStream(_stream); + + for (i = 0; i < numItems; i++) + { + lps->InSize = totalPackSize; + lps->OutSize = totalSize; + RINOK(lps->SetCur()); + CMyComPtr outStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + UInt32 index = allFilesMode ? i : indices[i]; + const CItem &item = _items[index]; + RINOK(extractCallback->GetStream(index, &outStream, askMode)); + const Byte *p = _data + item.Offset; + + if (IsDir(p, be)) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + UInt32 curSize = GetSize(p, be); + totalSize += curSize; + UInt32 packSize; + if (GetPackSize(index, packSize)) + totalPackSize += packSize; + + if (!testMode && !outStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + + UInt32 offset = GetOffset(p, be); + if (offset < kHeaderSize) + curSize = 0; + + int res = NExtract::NOperationResult::kDataError; + { + CMyComPtr inSeqStream; + CMyComPtr inStream; + HRESULT hres = GetStream(index, &inSeqStream); + if (inSeqStream) + inSeqStream.QueryInterface(IID_IInStream, &inStream); + if (hres == E_OUTOFMEMORY) + return E_OUTOFMEMORY; + if (hres == S_FALSE || !inStream) + res = 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 == curSize && hres == S_OK) + res = NExtract::NOperationResult::kOK; + } + } + } + RINOK(extractCallback->SetOperationResult(res)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + + const CItem &item = _items[index]; + const Byte *p = _data + item.Offset; + + bool be = _h.be; + if (IsDir(p, be)) + return E_FAIL; + + UInt32 size = GetSize(p, be); + UInt32 numBlocks = (size + kBlockSize - 1) >> kBlockSizeLog; + UInt32 offset = GetOffset(p, be); + if (offset < kHeaderSize) + { + if (offset != 0) + return S_FALSE; + CBufInStream *streamSpec = new CBufInStream; + CMyComPtr streamTemp = streamSpec; + streamSpec->Init(NULL, 0); + *stream = streamTemp.Detach(); + return S_OK; + } + + if (offset + numBlocks * 4 > _size) + return S_FALSE; + UInt32 prev = offset; + for (UInt32 i = 0; i < numBlocks; i++) + { + UInt32 next = Get32(_data + offset + i * 4); + if (next < prev || next > _size) + return S_FALSE; + prev = next; + } + + CCramfsInStream *streamSpec = new CCramfsInStream; + CMyComPtr streamTemp = streamSpec; + _curNumBlocks = numBlocks; + _curBlocksOffset = offset; + streamSpec->Handler = this; + if (!streamSpec->Alloc(kBlockSizeLog, 21 - kBlockSizeLog)) + return E_OUTOFMEMORY; + streamSpec->Init(size); + *stream = streamTemp.Detach(); + + return S_OK; + COM_TRY_END +} + +static IInArchive *CreateArc() { return new NArchive::NCramfs::CHandler; } + +static CArcInfo g_ArcInfo = + { L"CramFS", L"cramfs", 0, 0xD3, SIGNATURE, kSignatureSize, false, CreateArc, 0 }; + +REGISTER_ARC(Cramfs) + +}} diff --git a/CPP/7zip/Archive/ElfHandler.cpp b/CPP/7zip/Archive/ElfHandler.cpp index 6f5a6776..c4ad78e9 100755 --- a/CPP/7zip/Archive/ElfHandler.cpp +++ b/CPP/7zip/Archive/ElfHandler.cpp @@ -277,9 +277,9 @@ static const CUInt32PCharPair g_AbiOS[] = static const CUInt32PCharPair g_SegmentFlags[] = { - { 1 << 0, "Execute" }, - { 1 << 1, "Write" }, - { 1 << 2, "Read" } + { 0, "Execute" }, + { 1, "Write" }, + { 2, "Read" } }; static const char *g_Types[] = diff --git a/CPP/7zip/Archive/Icons/squashfs.ico b/CPP/7zip/Archive/Icons/squashfs.ico new file mode 100755 index 00000000..551a7439 Binary files /dev/null and b/CPP/7zip/Archive/Icons/squashfs.ico differ diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp index dc20c240..4bfb7dc6 100755 --- a/CPP/7zip/Archive/Iso/IsoHandler.cpp +++ b/CPP/7zip/Archive/Iso/IsoHandler.cpp @@ -24,7 +24,7 @@ using namespace NTime; namespace NArchive { namespace NIso { -static STATPROPSTG kProps[] = +static const STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidIsDir, VT_BOOL}, @@ -33,8 +33,17 @@ static STATPROPSTG kProps[] = { NULL, kpidMTime, VT_FILETIME} }; +static const STATPROPSTG kArcProps[] = +{ + { NULL, kpidComment, VT_BSTR}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidMTime, VT_FILETIME} + // { NULL, kpidPhySize, VT_UI8}, + // { NULL, kpidHeadersSize, VT_UI8} +}; + IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO +IMP_IInArchive_ArcProps STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * /* maxCheckStartPosition */, @@ -66,6 +75,58 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } +static void AddString(AString &s, const char *name, const Byte *p, int size) +{ + int i; + for (i = 0; i < size && p[i]; i++); + for (; i > 0 && p[i - 1] == ' '; i--); + if (i != 0) + { + AString d; + memcpy(d.GetBuffer(i), p, i); + d.ReleaseBuffer(i); + s += '\n'; + s += name; + s += ": "; + s += d; + } +} + +#define ADD_STRING(n, v) AddString(s, n, vol. ## v, sizeof(vol. ## v)) + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CVolumeDescriptor &vol = _archive.VolDescs[_archive.MainVolDescIndex]; + switch(propID) + { + case kpidComment: + { + AString s; + ADD_STRING("System", SystemId); + ADD_STRING("Volume", VolumeId); + ADD_STRING("VolumeSet", VolumeSetId); + ADD_STRING("Publisher", PublisherId); + ADD_STRING("Preparer", DataPreparerId); + ADD_STRING("Application", ApplicationId); + ADD_STRING("Copyright", CopyrightFileId); + ADD_STRING("Abstract", AbstractFileId); + ADD_STRING("Bib", BibFileId); + prop = s; + break; + } + case kpidCTime: { FILETIME utc; if (vol.CTime.GetFileTime(utc)) prop = utc; break; } + case kpidMTime: { FILETIME utc; if (vol.MTime.GetFileTime(utc)) prop = utc; break; } + // case kpidPhySize: break; + // case kpidHeadersSize: break; + case kpidError: if (_archive.IncorrectBigEndian) prop = "Incorrect big-endian headers"; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN @@ -87,9 +148,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val prop = (const wchar_t *)s; break; } - case kpidIsDir: - prop = false; - break; + case kpidIsDir: prop = false; break; case kpidSize: case kpidPackSize: prop = (UInt64)_archive.GetBootItemSize(index); @@ -121,9 +180,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val prop = (const wchar_t *)NItemName::GetOSName2(s); } break; - case kpidIsDir: - prop = item.IsDir(); - break; + case kpidIsDir: prop = item.IsDir(); break; case kpidSize: case kpidPackSize: if (!item.IsDir()) @@ -131,16 +188,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val break; case kpidMTime: { - FILETIME utcFileTime; - if (item.DateTime.GetFileTime(utcFileTime)) - prop = utcFileTime; - /* - else - { - utcFileTime.dwLowDateTime = 0; - utcFileTime.dwHighDateTime = 0; - } - */ + FILETIME utc; + if (item.DateTime.GetFileTime(utc)) + prop = utc; break; } } diff --git a/CPP/7zip/Archive/Iso/IsoIn.cpp b/CPP/7zip/Archive/Iso/IsoIn.cpp index 84143348..7ed618d2 100755 --- a/CPP/7zip/Archive/Iso/IsoIn.cpp +++ b/CPP/7zip/Archive/Iso/IsoIn.cpp @@ -65,7 +65,7 @@ UInt16 CInArchive::ReadUInt16() for (int i = 0; i < 2; i++) { if (b[i] != b[3 - i]) - throw 1; + IncorrectBigEndian = true; value |= ((UInt16)(b[i]) << (8 * i)); } return (UInt16)value; @@ -440,6 +440,7 @@ HRESULT CInArchive::Open(IInStream *inStream) void CInArchive::Clear() { + IncorrectBigEndian = false; Refs.Clear(); _rootDir.Clear(); VolDescs.Clear(); diff --git a/CPP/7zip/Archive/Iso/IsoIn.h b/CPP/7zip/Archive/Iso/IsoIn.h index 49687e27..f9c6f640 100755 --- a/CPP/7zip/Archive/Iso/IsoIn.h +++ b/CPP/7zip/Archive/Iso/IsoIn.h @@ -111,6 +111,20 @@ struct CDateTime signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded. bool NotSpecified() const { return Year == 0 && Month == 0 && Day == 0 && Hour == 0 && Minute == 0 && Second == 0 && GmtOffset == 0; } + + bool GetFileTime(FILETIME &ft) const + { + UInt64 value; + bool res = NWindows::NTime::GetSecondsSince1601(Year, Month, Day, Hour, Minute, Second, value); + if (res) + { + value -= (UInt64)((Int64)GmtOffset * 15 * 60); + value *= 10000000; + } + ft.dwLowDateTime = (DWORD)value; + ft.dwHighDateTime = (DWORD)(value >> 32); + return res; + } }; struct CBootRecordDescriptor @@ -268,6 +282,7 @@ public: int MainVolDescIndex; UInt32 BlockSize; CObjectVector BootEntries; + bool IncorrectBigEndian; bool IsJoliet() const { return VolDescs[MainVolDescIndex].IsJoliet(); } diff --git a/CPP/7zip/Archive/LzhHandler.cpp b/CPP/7zip/Archive/LzhHandler.cpp index c568ee4c..95efc501 100755 --- a/CPP/7zip/Archive/LzhHandler.cpp +++ b/CPP/7zip/Archive/LzhHandler.cpp @@ -266,7 +266,7 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) return (startHeader[0] == 0) ? S_OK: S_FALSE; const Byte *p = header; - memmove(item.Method, p, kMethodIdSize); + memcpy(item.Method, p, kMethodIdSize); if (!item.IsValidMethod()) return S_OK; p += kMethodIdSize; diff --git a/CPP/7zip/Archive/MachoHandler.cpp b/CPP/7zip/Archive/MachoHandler.cpp index ad4a5afb..a6261f34 100755 --- a/CPP/7zip/Archive/MachoHandler.cpp +++ b/CPP/7zip/Archive/MachoHandler.cpp @@ -77,16 +77,16 @@ static const char *g_FileTypes[] = static const CUInt32PCharPair g_Flags[] = { - { (UInt32)1 << 31, "PURE_INSTRUCTIONS" }, - { 1 << 30, "NO_TOC" }, - { 1 << 29, "STRIP_STATIC_SYMS" }, - { 1 << 28, "NO_DEAD_STRIP" }, - { 1 << 27, "LIVE_SUPPORT" }, - { 1 << 26, "SELF_MODIFYING_CODE" }, - { 1 << 25, "DEBUG" }, - { 1 << 10, "SOME_INSTRUCTIONS" }, - { 1 << 9, "EXT_RELOC" }, - { 1 << 8, "LOC_RELOC" } + { 31, "PURE_INSTRUCTIONS" }, + { 30, "NO_TOC" }, + { 29, "STRIP_STATIC_SYMS" }, + { 28, "NO_DEAD_STRIP" }, + { 27, "LIVE_SUPPORT" }, + { 26, "SELF_MODIFYING_CODE" }, + { 25, "DEBUG" }, + { 10, "SOME_INSTRUCTIONS" }, + { 9, "EXT_RELOC" }, + { 8, "LOC_RELOC" } }; static const CUInt32PCharPair g_MachinePairs[] = diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp index 506e944a..c64067aa 100755 --- a/CPP/7zip/Archive/PeHandler.cpp +++ b/CPP/7zip/Archive/PeHandler.cpp @@ -300,53 +300,53 @@ void CSection::Parse(const Byte *p) static const CUInt32PCharPair g_HeaderCharacts[] = { - { 1 << 1, "Executable" }, - { 1 << 13, "DLL" }, - { 1 << 8, "32-bit" }, - { 1 << 5, "LargeAddress" }, - { 1 << 0, "NoRelocs" }, - { 1 << 2, "NoLineNums" }, - { 1 << 3, "NoLocalSyms" }, - { 1 << 4, "AggressiveWsTrim" }, - { 1 << 9, "NoDebugInfo" }, - { 1 << 10, "RemovableRun" }, - { 1 << 11, "NetRun" }, - { 1 << 12, "System" }, - { 1 << 14, "UniCPU" }, - { 1 << 7, "Little-Endian" }, - { 1 << 15, "Big-Endian" } + { 1, "Executable" }, + { 13, "DLL" }, + { 8, "32-bit" }, + { 5, "LargeAddress" }, + { 0, "NoRelocs" }, + { 2, "NoLineNums" }, + { 3, "NoLocalSyms" }, + { 4, "AggressiveWsTrim" }, + { 9, "NoDebugInfo" }, + { 10, "RemovableRun" }, + { 11, "NetRun" }, + { 12, "System" }, + { 14, "UniCPU" }, + { 7, "Little-Endian" }, + { 15, "Big-Endian" } }; static const CUInt32PCharPair g_DllCharacts[] = { - { 1 << 6, "Relocated" }, - { 1 << 7, "Integrity" }, - { 1 << 8, "NX-Compatible" }, - { 1 << 9, "NoIsolation" }, - { 1 << 10, "NoSEH" }, - { 1 << 11, "NoBind" }, - { 1 << 13, "WDM" }, - { 1 << 15, "TerminalServerAware" } + { 6, "Relocated" }, + { 7, "Integrity" }, + { 8, "NX-Compatible" }, + { 9, "NoIsolation" }, + { 10, "NoSEH" }, + { 11, "NoBind" }, + { 13, "WDM" }, + { 15, "TerminalServerAware" } }; static const CUInt32PCharPair g_SectFlags[] = { - { 1 << 3, "NoPad" }, - { 1 << 5, "Code" }, - { 1 << 6, "InitializedData" }, - { 1 << 7, "UninitializedData" }, - { 1 << 9, "Comments" }, - { 1 << 11, "Remove" }, - { 1 << 12, "COMDAT" }, - { 1 << 15, "GP" }, - { 1 << 24, "ExtendedRelocations" }, - { 1 << 25, "Discardable" }, - { 1 << 26, "NotCached" }, - { 1 << 27, "NotPaged" }, - { 1 << 28, "Shared" }, - { 1 << 29, "Execute" }, - { 1 << 30, "Read" }, - { (UInt32)1 << 31, "Write" } + { 3, "NoPad" }, + { 5, "Code" }, + { 6, "InitializedData" }, + { 7, "UninitializedData" }, + { 9, "Comments" }, + { 11, "Remove" }, + { 12, "COMDAT" }, + { 15, "GP" }, + { 24, "ExtendedRelocations" }, + { 25, "Discardable" }, + { 26, "NotCached" }, + { 27, "NotPaged" }, + { 28, "Shared" }, + { 29, "Execute" }, + { 30, "Read" }, + { 31, "Write" } }; static const CUInt32PCharPair g_MachinePairs[] = @@ -1723,6 +1723,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) size_t offset = item.Offset - sect.Va; if (!CheckItem(sect, item, offset)) return S_FALSE; + if (item.HeaderSize == 0) + { + CBufInStream *streamSpec = new CBufInStream; + CMyComPtr streamTemp2 = streamSpec; + streamSpec->Init(_buf + offset, item.Size, (IInArchive *)this); + *stream = streamTemp2.Detach(); + return S_OK; + } referenceBuf->Buf.SetCapacity(item.HeaderSize + item.Size); memcpy(referenceBuf->Buf, item.Header, item.HeaderSize); memcpy(referenceBuf->Buf + item.HeaderSize, _buf + offset, item.Size); diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp index 8906614a..54709f6c 100755 --- a/CPP/7zip/Archive/Rar/RarHandler.cpp +++ b/CPP/7zip/Archive/Rar/RarHandler.cpp @@ -46,7 +46,7 @@ static const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]); static const wchar_t *kUnknownOS = L"Unknown"; -STATPROPSTG kProps[] = +static const STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidIsDir, VT_BOOL}, @@ -68,7 +68,7 @@ STATPROPSTG kProps[] = { NULL, kpidUnpackVer, VT_UI1} }; -STATPROPSTG kArcProps[] = +static const STATPROPSTG kArcProps[] = { { NULL, kpidSolid, VT_BOOL}, { NULL, kpidNumBlocks, VT_UI4}, @@ -93,7 +93,7 @@ UInt64 CHandler::GetPackSize(int refIndex) const STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { - // COM_TRY_BEGIN + COM_TRY_BEGIN NWindows::NCOM::CPropVariant prop; switch(propID) { @@ -112,10 +112,11 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) prop = (UInt32)numBlocks; break; } + case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break; } prop.Detach(value); return S_OK; - // COM_TRY_END + COM_TRY_END } STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) @@ -396,7 +397,14 @@ HRESULT CHandler::Open2(IInStream *stream, for (;;) { bool decryptionError; - HRESULT result = archive.GetNextItem(item, getTextPassword, decryptionError); + AString errorMessageLoc; + HRESULT result = archive.GetNextItem(item, getTextPassword, decryptionError, errorMessageLoc); + if (errorMessageLoc) + { + if (!_errorMessage.IsEmpty()) + _errorMessage += '\n'; + _errorMessage += errorMessageLoc; + } if (result == S_FALSE) { if (decryptionError && _items.IsEmpty()) @@ -461,6 +469,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, STDMETHODIMP CHandler::Close() { COM_TRY_BEGIN + _errorMessage.Empty(); _refItems.Clear(); _items.Clear(); _archives.Clear(); diff --git a/CPP/7zip/Archive/Rar/RarHandler.h b/CPP/7zip/Archive/Rar/RarHandler.h index 58e3fefc..c8015b2a 100755 --- a/CPP/7zip/Archive/Rar/RarHandler.h +++ b/CPP/7zip/Archive/Rar/RarHandler.h @@ -32,6 +32,7 @@ private: CObjectVector _items; CObjectVector _archives; NArchive::NRar::CInArchiveInfo _archiveInfo; + AString _errorMessage; DECL_EXTERNAL_CODECS_VARS diff --git a/CPP/7zip/Archive/Rar/RarHeader.h b/CPP/7zip/Archive/Rar/RarHeader.h index 4df42e62..8bb1da21 100755 --- a/CPP/7zip/Archive/Rar/RarHeader.h +++ b/CPP/7zip/Archive/Rar/RarHeader.h @@ -18,16 +18,16 @@ namespace NBlockType { enum EBlockType { - kMarker = 0x72, - kArchiveHeader = 0x73, - kFileHeader = 0x74, - kCommentHeader = 0x75, - kOldAuthenticity = 0x76, - kSubBlock = 0x77, - kRecoveryRecord = 0x78, - kAuthenticity = 0x79, - - kEndOfArchive = 0x7B // Is not safe + kMarker = 0x72, + kArchiveHeader, + kFileHeader, + kCommentHeader, + kOldAuthenticity, + kOldSubBlock, + kRecoveryRecord, + kAuthenticity, + kSubBlock, + kEndOfArchive }; } diff --git a/CPP/7zip/Archive/Rar/RarIn.cpp b/CPP/7zip/Archive/Rar/RarIn.cpp index c5d30fac..7d64c6fd 100755 --- a/CPP/7zip/Archive/Rar/RarIn.cpp +++ b/CPP/7zip/Archive/Rar/RarIn.cpp @@ -372,14 +372,14 @@ void CInArchive::AddToSeekValue(UInt64 addValue) m_Position += addValue; } -HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError) +HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError, AString &errorMessage) { decryptionError = false; if (m_SeekOnArchiveComment) SkipArchiveComment(); for (;;) { - if(!SeekInArchive(m_Position)) + if (!SeekInArchive(m_Position)) return S_FALSE; if (!m_CryptoMode && (m_ArchiveHeader.Flags & NHeader::NArchive::kBlockHeadersAreEncrypted) != 0) @@ -438,8 +438,11 @@ HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPa } m_FileHeaderData.EnsureCapacity(7); - if(!ReadBytesAndTestSize((Byte *)m_FileHeaderData, 7)) + if (!ReadBytesAndTestSize((Byte *)m_FileHeaderData, 7)) + { + errorMessage = "Unexpected end of archive"; return S_FALSE; + } m_CurData = (Byte *)m_FileHeaderData; m_CurPos = 0; diff --git a/CPP/7zip/Archive/Rar/RarIn.h b/CPP/7zip/Archive/Rar/RarIn.h index 5d9f67a3..75c98cc4 100755 --- a/CPP/7zip/Archive/Rar/RarIn.h +++ b/CPP/7zip/Archive/Rar/RarIn.h @@ -110,7 +110,7 @@ class CInArchive public: HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit); void Close(); - HRESULT GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError); + HRESULT GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError, AString &errorMessage); void SkipArchiveComment(); diff --git a/CPP/7zip/Archive/RpmHandler.cpp b/CPP/7zip/Archive/RpmHandler.cpp index f533e78f..1d31d451 100755 --- a/CPP/7zip/Archive/RpmHandler.cpp +++ b/CPP/7zip/Archive/RpmHandler.cpp @@ -79,7 +79,7 @@ static HRESULT RedSigHeaderSig(IInStream *inStream, CSigHeaderSig &h) char dat[kCSigHeaderSigSize]; char *cur = dat; RINOK(ReadStream_FALSE(inStream, dat, kCSigHeaderSigSize)); - memmove(h.Magic, cur, 4); + memcpy(h.Magic, cur, 4); cur += 4; cur += 4; h.IndexLen = Get32(cur); @@ -95,7 +95,7 @@ HRESULT OpenArchive(IInStream *inStream) char *cur = leadData; CLead lead; RINOK(ReadStream_FALSE(inStream, leadData, kLeadSize)); - memmove(lead.Magic, cur, 4); + memcpy(lead.Magic, cur, 4); cur += 4; lead.Major = *cur++; lead.Minor = *cur++; @@ -103,7 +103,7 @@ HRESULT OpenArchive(IInStream *inStream) cur += 2; lead.ArchNum = Get16(cur); cur += 2; - memmove(lead.Name, cur, sizeof(lead.Name)); + memcpy(lead.Name, cur, sizeof(lead.Name)); cur += sizeof(lead.Name); lead.OSNum = Get16(cur); cur += 2; diff --git a/CPP/7zip/Archive/SplitHandler.cpp b/CPP/7zip/Archive/SplitHandler.cpp index e3129c6a..5d84de4e 100755 --- a/CPP/7zip/Archive/SplitHandler.cpp +++ b/CPP/7zip/Archive/SplitHandler.cpp @@ -347,7 +347,6 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) { CMultiStream::CSubStreamInfo subStreamInfo; subStreamInfo.Stream = _streams[i]; - subStreamInfo.Pos = 0; subStreamInfo.Size = _sizes[i]; streamSpec->Streams.Add(subStreamInfo); } diff --git a/CPP/7zip/Archive/SquashfsHandler.cpp b/CPP/7zip/Archive/SquashfsHandler.cpp new file mode 100755 index 00000000..e09c09de --- /dev/null +++ b/CPP/7zip/Archive/SquashfsHandler.cpp @@ -0,0 +1,1959 @@ +// SquashfsHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/7zCrc.h" +#include "../../../C/Alloc.h" +#include "../../../C/CpuArch.h" + +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariantUtils.h" +#include "Windows/Time.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamObjects.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" +#include "../Compress/ZlibDecoder.h" +#include "../Compress/LzmaDecoder.h" + +namespace NArchive { +namespace NSquashfs { + +static const UInt32 kNumFilesMax = (1 << 28); +static const unsigned kNumDirLevelsMax = (1 << 10); + +// Layout: Header, Data, inodes, Directories, Fragments, UIDs, GIDs + +/* +#define Get16(p) (be ? GetBe16(p) : GetUi16(p)) +#define Get32(p) (be ? GetBe32(p) : GetUi32(p)) +#define Get64(p) (be ? GetBe64(p) : GetUi64(p)) +*/ + +UInt16 Get16b(const Byte *p, bool be) { return be ? GetBe16(p) : GetUi16(p); } +UInt32 Get32b(const Byte *p, bool be) { return be ? GetBe32(p) : GetUi32(p); } +UInt64 Get64b(const Byte *p, bool be) { return be ? GetBe64(p) : GetUi64(p); } + +#define Get16(p) Get16b(p, be) +#define Get32(p) Get32b(p, be) +#define Get64(p) Get64b(p, be) + +#define LE_16(offs, dest) dest = GetUi16(p + (offs)); +#define LE_32(offs, dest) dest = GetUi32(p + (offs)); +#define LE_64(offs, dest) dest = GetUi64(p + (offs)); + +#define GET_16(offs, dest) dest = Get16(p + (offs)); +#define GET_32(offs, dest) dest = Get32(p + (offs)); +#define GET_64(offs, dest) dest = Get64(p + (offs)); + +static const UInt32 kSignatureSize = 4; +#define SIGNATURE { 'h', 's', 'q', 's' } +static const UInt32 kSignature32_LE = 0x73717368; +static const UInt32 kSignature32_BE = 0x68737173; +static const UInt32 kSignature32_LZ = 0x71736873; + +#define kMethod_ZLIB 1 +#define kMethod_LZMA 2 +#define kMethod_LZO 3 + +static const char *k_Methods[] = +{ + "Unknown", + "ZLIB", + "LZMA", + "LZO" +}; + +static const UInt32 kMetadataBlockSizeLog = 13; +static const UInt32 kMetadataBlockSize = (1 << kMetadataBlockSizeLog); + +#define MY_S_IFIFO 0x1000 +#define MY_S_IFCHR 0x2000 +#define MY_S_IFDIR 0x4000 +#define MY_S_IFBLK 0x6000 +#define MY_S_IFREG 0x8000 +#define MY_S_IFLNK 0xA000 +#define MY_S_IFSOCK 0xC000 + +enum +{ + kType_IPC, + kType_DIR, + kType_FILE, + kType_LNK, + kType_BLK, + kType_CHR, + kType_FIFO, + kType_SOCK +}; + +static const UInt32 k_TypeToMode[] = +{ + 0, + MY_S_IFDIR, MY_S_IFREG, MY_S_IFLNK, MY_S_IFBLK, MY_S_IFCHR, MY_S_IFIFO, MY_S_IFSOCK, + MY_S_IFDIR, MY_S_IFREG, MY_S_IFLNK, MY_S_IFBLK, MY_S_IFCHR, MY_S_IFIFO, MY_S_IFSOCK +}; + + +enum +{ + kFlag_UNC_INODES, + kFlag_UNC_DATA, + kFlag_CHECK, + kFlag_UNC_FRAGS, + kFlag_NO_FRAGS, + kFlag_ALWAYS_FRAG, + kFlag_DUPLICATE, + kFlag_EXPORT +}; + +static const CUInt32PCharPair k_Flags[] = +{ + { kFlag_UNC_INODES, "UNCOMPRESSED_INODES" }, + { kFlag_UNC_DATA, "UNCOMPRESSED_DATA" }, + { kFlag_CHECK, "CHECK" }, + { kFlag_UNC_FRAGS, "UNCOMPRESSED_FRAGMENTS" }, + { kFlag_NO_FRAGS, "NO_FRAGMENTS" }, + { kFlag_ALWAYS_FRAG, "ALWAYS_FRAGMENTS" }, + { kFlag_DUPLICATE, "DUPLICATES_REMOVED" }, + { kFlag_EXPORT, "EXPORTABLE" } +}; + +static const UInt32 kNotCompressedBit16 = (1 << 15); +static const UInt32 kNotCompressedBit32 = (1 << 24); + +#define GET_COMPRESSED_BLOCK_SIZE(size) ((size) & ~kNotCompressedBit32) +#define IS_COMPRESSED_BLOCK(size) (((size) & kNotCompressedBit32) == 0) + +static const UInt32 kHeaderSize1 = 0x33; +static const UInt32 kHeaderSize2 = 0x3F; +static const UInt32 kHeaderSize3 = 0x77; +static const UInt32 kHeaderSize4 = 0x60; + +struct CHeader +{ + bool be; + bool SeveralMethods; + Byte NumUids; + Byte NumGids; + + UInt32 NumInodes; + UInt32 CTime; + UInt32 BlockSize; + UInt32 NumFrags; + UInt16 Method; + UInt16 BlockSizeLog; + UInt16 Flags; + UInt16 NumIDs; + UInt16 Major; + UInt16 Minor; + UInt64 RootInode; + UInt64 Size; + UInt64 UidTable; + UInt64 GidTable; + UInt64 XattrIdTable; + UInt64 InodeTable; + UInt64 DirTable; + UInt64 FragTable; + UInt64 LookupTable; + + void Parse3(const Byte *p) + { + Method = kMethod_ZLIB; + GET_32 (0x08, Size); + GET_32 (0x0C, UidTable); + GET_32 (0x10, GidTable); + GET_32 (0x14, InodeTable); + GET_32 (0x18, DirTable); + GET_16 (0x20, BlockSize); + GET_16 (0x22, BlockSizeLog); + Flags = p[0x24]; + NumUids = p[0x25]; + NumGids = p[0x26]; + GET_32 (0x27, CTime); + GET_64 (0x2B, RootInode); + NumFrags = 0; + FragTable = UidTable; + + if (Major >= 2) + { + GET_32 (0x33, BlockSize); + GET_32 (0x37, NumFrags); + GET_32 (0x3B, FragTable); + if (Major == 3) + { + GET_64 (0x3F, Size); + GET_64 (0x47, UidTable); + GET_64 (0x4F, GidTable); + GET_64 (0x57, InodeTable); + GET_64 (0x5F, DirTable); + GET_64 (0x67, FragTable); + GET_64 (0x6F, LookupTable); + } + } + } + + void Parse4(const Byte *p) + { + LE_32 (0x08, CTime); + LE_32 (0x0C, BlockSize); + LE_32 (0x10, NumFrags); + LE_16 (0x14, Method); + LE_16 (0x16, BlockSizeLog); + LE_16 (0x18, Flags); + LE_16 (0x1A, NumIDs); + LE_64 (0x20, RootInode); + LE_64 (0x28, Size); + LE_64 (0x30, UidTable); + LE_64 (0x38, XattrIdTable); + LE_64 (0x40, InodeTable); + LE_64 (0x48, DirTable); + LE_64 (0x50, FragTable); + LE_64 (0x58, LookupTable); + GidTable = 0; + } + + bool Parse(const Byte *p) + { + be = false; + SeveralMethods = false; + switch (GetUi32(p)) + { + case kSignature32_LE: break; + case kSignature32_BE: be = true; break; + case kSignature32_LZ: SeveralMethods = true; break; + default: return false; + } + GET_32 (4, NumInodes); + GET_16 (0x1C, Major); + GET_16 (0x1E, Minor); + if (Major <= 3) + Parse3(p); + else + { + if (be) + return false; + Parse4(p); + } + return + InodeTable < DirTable && + DirTable <= FragTable && + FragTable <= Size && + UidTable <= Size && + BlockSizeLog >= 12 && + BlockSizeLog < 31 && + BlockSize == ((UInt32)1 << BlockSizeLog); + } + + bool IsSupported() const { return Major > 0 && Major <= 4 && BlockSizeLog <= 23; } + bool IsOldVersion() const { return Major < 4; } + bool NeedCheckData() const { return (Flags & (1 << kFlag_CHECK)) != 0; } + unsigned GetFileNameOffset() const { return Major <= 2 ? 3 : (Major == 3 ? 5 : 8); } + unsigned GetSymLinkOffset() const { return Major <= 1 ? 5: (Major <= 2 ? 6: (Major == 3 ? 18 : 24)); } + unsigned GetSpecGuidIndex() const { return Major <= 1 ? 0xF: 0xFF; } +}; + +static const UInt32 kFrag_Empty = (UInt32)(Int32)-1; +// static const UInt32 kXattr_Empty = (UInt32)(Int32)-1; + +struct CNode +{ + UInt16 Type; + UInt16 Mode; + UInt16 Uid; + UInt16 Gid; + UInt32 Frag; + UInt32 Offset; + // UInt32 MTime; + // UInt32 Number; + // UInt32 NumLinks; + // UInt32 RDev; + // UInt32 Xattr; + // UInt32 Parent; + + UInt64 FileSize; + UInt64 StartBlock; + // UInt64 Sparse; + + UInt32 Parse1(const Byte *p, UInt32 size, const CHeader &_h); + UInt32 Parse2(const Byte *p, UInt32 size, const CHeader &_h); + UInt32 Parse3(const Byte *p, UInt32 size, const CHeader &_h); + UInt32 Parse4(const Byte *p, UInt32 size, const CHeader &_h); + + bool IsDir() const { return (Type == kType_DIR || Type == kType_DIR + 7); } + bool IsLink() const { return (Type == kType_LNK || Type == kType_LNK + 7); } + UInt64 GetSize() const { return IsDir() ? 0 : FileSize; } + + bool ThereAreFrags() const { return Frag != kFrag_Empty; } + UInt64 GetNumBlocks(const CHeader &_h) const + { + return (FileSize >> _h.BlockSizeLog) + + (!ThereAreFrags() && (FileSize & (_h.BlockSize - 1)) != 0); + } +}; + +UInt32 CNode::Parse1(const Byte *p, UInt32 size, const CHeader &_h) +{ + bool be = _h.be; + if (size < 4) + return 0; + UInt16 t = Get16(p); + if (be) + { + Type = t >> 12; + Mode = t & 0xFFF; + Uid = p[2] >> 4; + Gid = p[2] & 0xF; + } + else + { + Type = t & 0xF; + Mode = t >> 4; + Uid = p[2] & 0xF; + Gid = p[2] >> 4; + } + + // Xattr = kXattr_Empty; + // MTime = 0; + FileSize = 0; + StartBlock = 0; + Frag = kFrag_Empty; + + if (Type == 0) + { + Byte t = p[3]; + if (be) + { + Type = t >> 4; + Offset = t & 0xF; + } + else + { + Type = t & 0xF; + Offset = t >> 4; + } + return (Type == kType_FIFO || Type == kType_SOCK) ? 4 : 0; + } + + Type--; + Uid += (Type / 5) * 16; + Type = (Type % 5) + 1; + + if (Type == kType_FILE) + { + if (size < 15) + return 0; + // GET_32 (3, MTime); + GET_32 (7, StartBlock); + UInt32 t; + GET_32 (11, t); + FileSize = t; + UInt32 numBlocks = t >> _h.BlockSizeLog; + if ((t & (_h.BlockSize - 1)) != 0) + numBlocks++; + UInt32 pos = numBlocks * 2 + 15; + return (pos <= size) ? pos : 0; + } + + if (Type == kType_DIR) + { + if (size < 14) + return 0; + UInt32 t = Get32(p + 3); + if (be) + { + FileSize = t >> 13; + Offset = t & 0x1FFF; + } + else + { + FileSize = t & 0x7FFFF; + Offset = t >> 19; + } + // GET_32 (7, MTime); + GET_32 (10, StartBlock); + if (be) + StartBlock &= 0xFFFFFF; + else + StartBlock >>= 8; + return 14; + } + + if (size < 5) + return 0; + + if (Type == kType_LNK) + { + UInt32 len; + GET_16 (3, len); + FileSize = len; + len += 5; + return (len <= size) ? len : 0; + } + + // GET_32 (3, RDev); + return 5; +} + +UInt32 CNode::Parse2(const Byte *p, UInt32 size, const CHeader &_h) +{ + bool be = _h.be; + if (size < 4) + return 0; + UInt16 t = Get16(p); + if (be) + { + Type = t >> 12; + Mode = t & 0xFFF; + } + else + { + Type = t & 0xF; + Mode = t >> 4; + } + Uid = p[2]; + Gid = p[3]; + + // Xattr = kXattr_Empty; + + if (Type == kType_FILE) + { + if (size < 24) + return 0; + // GET_32 (4, MTime); + GET_32 (8, StartBlock); + GET_32 (12, Frag); + GET_32 (16, Offset); + UInt32 t; + GET_32 (20, t); + FileSize = t; + UInt32 numBlocks = t >> _h.BlockSizeLog; + if (!ThereAreFrags() && (t & (_h.BlockSize - 1)) != 0) + numBlocks++; + UInt32 pos = numBlocks * 4 + 24; + return (pos <= size) ? (UInt32)pos : 0; + } + + FileSize = 0; + // MTime = 0; + StartBlock = 0; + Frag = kFrag_Empty; + + if (Type == kType_DIR) + { + if (size < 15) + return 0; + UInt32 t = Get32(p + 4); + if (be) + { + FileSize = t >> 13; + Offset = t & 0x1FFF; + } + else + { + FileSize = t & 0x7FFFF; + Offset = t >> 19; + } + // GET_32 (8, MTime); + GET_32 (11, StartBlock); + if (be) + StartBlock &= 0xFFFFFF; + else + StartBlock >>= 8; + return 15; + } + + if (Type == kType_DIR + 7) + { + if (size < 18) + return 0; + UInt32 t = Get32(p + 4); + UInt32 t2 = Get16(p + 7); + if (be) + { + FileSize = t >> 5; + Offset = t2 & 0x1FFF; + } + else + { + FileSize = t & 0x7FFFFFF; + Offset = t2 >> 3; + } + // GET_32 (9, MTime); + GET_32 (12, StartBlock); + if (be) + StartBlock &= 0xFFFFFF; + else + StartBlock >>= 8; + UInt32 iCount; + GET_16 (16, iCount); + UInt32 pos = 18; + for (UInt32 i = 0; i < iCount; i++) + { + // 27 bits: index + // 29 bits: startBlock + if (pos + 8 > size) + return 0; + pos += 8 + (UInt32)p[pos + 7] + 1; // nameSize + if (pos > size) + return 0; + } + return pos; + } + + if (Type == kType_FIFO || Type == kType_SOCK) + return 4; + + if (size < 6) + return 0; + + if (Type == kType_LNK) + { + UInt32 len; + GET_16 (4, len); + FileSize = len; + len += 6; + return (len <= size) ? len : 0; + } + + if (Type == kType_BLK || Type == kType_CHR) + { + // GET_16 (4, RDev); + return 6; + } + + return 0; +} + +UInt32 CNode::Parse3(const Byte *p, UInt32 size, const CHeader &_h) +{ + bool be = _h.be; + if (size < 12) + return 0; + UInt16 t = Get16(p); + if (be) + { + Type = t >> 12; + Mode = t & 0xFFF; + } + else + { + Type = t & 0xF; + Mode = t >> 4; + } + Uid = p[2]; + Gid = p[3]; + // GET_32 (4, MTime); + // GET_32 (8, Number); + // Xattr = kXattr_Empty; + FileSize = 0; + StartBlock = 0; + + if (Type == kType_FILE || Type == kType_FILE + 7) + { + UInt32 offset; + if (Type == kType_FILE) + { + if (size < 32) + return 0; + GET_64 (12, StartBlock); + GET_32 (20, Frag); + GET_32 (24, Offset); + GET_32 (28, FileSize); + offset = 32; + } + else + { + if (size < 40) + return 0; + // GET_32 (12, NumLinks); + GET_64 (16, StartBlock); + GET_32 (24, Frag); + GET_32 (28, Offset); + GET_64 (32, FileSize); + offset = 40; + } + UInt64 pos = GetNumBlocks(_h) * 4 + offset; + return (pos <= size) ? (UInt32)pos : 0; + } + + if (size < 16) + return 0; + // GET_32 (12, NumLinks); + + if (Type == kType_DIR) + { + if (size < 28) + return 0; + UInt32 t = Get32(p + 16); + if (be) + { + FileSize = t >> 13; + Offset = t & 0x1FFF; + } + else + { + FileSize = t & 0x7FFFF; + Offset = t >> 19; + } + GET_32 (20, StartBlock); + // GET_32 (24, Parent); + return 28; + } + + if (Type == kType_DIR + 7) + { + if (size < 31) + return 0; + UInt32 t = Get32(p + 16); + UInt32 t2 = Get16(p + 19); + if (be) + { + FileSize = t >> 5; + Offset = t2 & 0x1FFF; + } + else + { + FileSize = t & 0x7FFFFFF; + Offset = t2 >> 3; + } + GET_32 (21, StartBlock); + UInt32 iCount; + GET_16 (25, iCount); + // GET_32 (27, Parent); + UInt32 pos = 31; + for (UInt32 i = 0; i < iCount; i++) + { + // UInt32 index + // UInt32 startBlock + if (pos + 9 > size) + return 0; + pos += 9 + (unsigned)p[pos + 8] + 1; // nameSize + if (pos > size) + return 0; + } + return pos; + } + + if (Type == kType_FIFO || Type == kType_SOCK) + return 16; + + if (size < 18) + return 0; + if (Type == kType_LNK) + { + UInt32 len; + GET_16 (16, len); + FileSize = len; + len += 18; + return (len <= size) ? len : 0; + } + + if (Type == kType_BLK || Type == kType_CHR) + { + // GET_16 (16, RDev); + return 18; + } + + return 0; +} + +UInt32 CNode::Parse4(const Byte *p, UInt32 size, const CHeader &_h) +{ + if (size < 20) + return 0; + LE_16 (0, Type); + LE_16 (2, Mode); + LE_16 (4, Uid); + LE_16 (6, Gid); + // LE_32 (8, MTime); + // LE_32 (12, Number); + + // Xattr = kXattr_Empty; + FileSize = 0; + StartBlock = 0; + + if (Type == kType_FILE || Type == kType_FILE + 7) + { + UInt32 offset; + if (Type == kType_FILE) + { + if (size < 32) + return 0; + LE_32 (16, StartBlock); + LE_32 (20, Frag); + LE_32 (24, Offset); + LE_32 (28, FileSize); + offset = 32; + } + else + { + if (size < 56) + return 0; + LE_64 (16, StartBlock); + LE_64 (24, FileSize); + // LE_64 (32, Sparse); + // LE_32 (40, NumLinks); + LE_32 (44, Frag); + LE_32 (48, Offset); + // LE_32 (52, Xattr); + offset = 56; + } + UInt64 pos = GetNumBlocks(_h) * 4 + offset; + return (pos <= size) ? (UInt32)pos : 0; + } + + if (Type == kType_DIR) + { + if (size < 32) + return 0; + LE_32 (16, StartBlock); + // LE_32 (20, NumLinks); + LE_16 (24, FileSize); + LE_16 (26, Offset); + // LE_32 (28, Parent); + return 32; + } + + // LE_32 (16, NumLinks); + + if (Type == kType_DIR + 7) + { + if (size < 40) + return 0; + LE_32 (20, FileSize); + LE_32 (24, StartBlock); + // LE_32 (28, Parent); + UInt32 iCount; + LE_16 (32, iCount); + LE_16 (34, Offset); + // LE_32 (36, Xattr); + + UInt32 pos = 40; + for (UInt32 i = 0; i < iCount; i++) + { + // UInt32 index + // UInt32 startBlock + if (pos + 12 > size) + return 0; + UInt32 nameLen = GetUi32(p + pos + 8); + pos += 12 + nameLen + 1; + if (pos > size || nameLen > (1 << 10)) + return 0; + } + return pos; + } + + unsigned offset = 20; + switch(Type) + { + case kType_FIFO: case kType_FIFO + 7: + case kType_SOCK: case kType_SOCK + 7: + break; + case kType_LNK: case kType_LNK + 7: + { + if (size < 24) + return 0; + UInt32 len; + LE_32 (20, len); + FileSize = len; + offset = len + 24; + if (size < offset || len > (1 << 30)) + return 0; + break; + } + case kType_BLK: case kType_BLK + 7: + case kType_CHR: case kType_CHR + 7: + if (size < 24) + return 0; + // LE_32 (20, RDev); + offset = 24; + break; + default: + return 0; + } + + if (Type >= 8) + { + if (size < offset + 4) + return 0; + // LE_32 (offset, Xattr); + offset += 4; + } + return offset; +} + +struct CItem +{ + int Node; + int Parent; + UInt32 Ptr; +}; + +struct CData +{ + CByteBuffer Data; + CRecordVector PackPos; + CRecordVector UnpackPos; // additional item at the end contains TotalUnpackSize + + UInt32 GetNumBlocks() const { return PackPos.Size(); } + void Clear() + { + Data.Free(); + PackPos.Clear(); + UnpackPos.Clear(); + } +}; + +struct CFrag +{ + UInt64 StartBlock; + UInt32 Size; +}; + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + CRecordVector _items; + CRecordVector _nodes; + CRecordVector _nodesPos; + CRecordVector _blockToNode; + CData _inodesData; + CData _dirs; + CRecordVector _frags; + // CByteBuffer _uids; + // CByteBuffer _gids; + CHeader _h; + + CMyComPtr _stream; + UInt64 _sizeCalculated; + + IArchiveOpenCallback *_openCallback; + + int _nodeIndex; + CRecordVector _blockCompressed; + CRecordVector _blockOffsets; + + CByteBuffer _cachedBlock; + UInt64 _cachedBlockStartPos; + UInt32 _cachedPackBlockSize; + UInt32 _cachedUnpackBlockSize; + + CLimitedSequentialInStream *_limitedInStreamSpec; + CMyComPtr _limitedInStream; + + CBufPtrSeqOutStream *_outStreamSpec; + CMyComPtr _outStream; + + NCompress::NLzma::CDecoder *_lzmaDecoderSpec; + CMyComPtr _lzmaDecoder; + + NCompress::NZlib::CDecoder *_zlibDecoderSpec; + CMyComPtr _zlibDecoder; + + CDynBufSeqOutStream *_dynOutStreamSpec; + CMyComPtr _dynOutStream; + + void ClearCache() + { + _cachedBlockStartPos = 0; + _cachedPackBlockSize = 0; + _cachedUnpackBlockSize = 0; + } + + HRESULT Decompress(ISequentialOutStream *outStream, UInt32 inSize, UInt32 outSizeMax); + HRESULT ReadMetadataBlock(UInt32 &packSize); + HRESULT ReadData(CData &data, UInt64 start, UInt64 end); + + HRESULT OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned level, int &nodeIndex); + HRESULT ScanInodes(UInt64 ptr); + // HRESULT ReadUids(UInt64 start, UInt32 num, CByteBuffer &ids); + HRESULT Open2(IInStream *inStream); + AString GetPath(int index) const; + bool GetPackSize(int index, UInt64 &res, bool fillOffsets); + +public: + CHandler(); + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); + + HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize); +}; + +CHandler::CHandler() +{ + _limitedInStreamSpec = new CLimitedSequentialInStream; + _limitedInStream = _limitedInStreamSpec; + + _outStreamSpec = new CBufPtrSeqOutStream(); + _outStream = _outStreamSpec; + + _dynOutStreamSpec = new CDynBufSeqOutStream; + _dynOutStream = _dynOutStreamSpec; +} + +static const 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} + // { NULL, kpidUser, VT_BSTR}, + // { NULL, kpidGroup, VT_BSTR}, + // { NULL, kpidLinks, VT_UI4}, + // { NULL, kpidOffset, VT_UI4} +}; + +static const STATPROPSTG kArcProps[] = +{ + { NULL, kpidFileSystem, VT_BSTR}, + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidBlock, VT_UI4}, + { NULL, kpidPhySize, VT_UI8}, + { NULL, kpidHeadersSize, VT_UI8}, + { NULL, kpidBigEndian, VT_BOOL}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidCharacts, VT_BSTR} + // { NULL, kpidNumBlocks, VT_UI4} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +HRESULT CHandler::Decompress(ISequentialOutStream *outStream, UInt32 inSize, UInt32 outSizeMax) +{ + UInt32 method = _h.Method; + if (_h.SeveralMethods) + { + Byte props[1]; + RINOK(ReadStream_FALSE(_stream, props, 1)); + method = (props[0] == 0x5D ? kMethod_LZMA : kMethod_ZLIB); + RINOK(_stream->Seek(-1, STREAM_SEEK_CUR, NULL)); + } + + if (method == kMethod_LZMA) + { + if (!_lzmaDecoder) + { + _lzmaDecoderSpec = new NCompress::NLzma::CDecoder(); + _lzmaDecoder = _lzmaDecoderSpec; + } + const UInt32 kPropsSize = 5 + 8; + Byte props[kPropsSize]; + ReadStream_FALSE(_limitedInStream, props, kPropsSize); + RINOK(_lzmaDecoderSpec->SetDecoderProperties2(props, 5)); + UInt64 outSize = GetUi64(props + 5); + if (outSize > outSizeMax) + return S_FALSE; + RINOK(_lzmaDecoder->Code(_limitedInStream, outStream, NULL, &outSize, NULL)); + if (inSize != kPropsSize + _lzmaDecoderSpec->GetInputProcessedSize()) + return S_FALSE; + } + else + { + if (!_zlibDecoder) + { + _zlibDecoderSpec = new NCompress::NZlib::CDecoder(); + _zlibDecoder = _zlibDecoderSpec; + } + RINOK(_zlibDecoder->Code(_limitedInStream, outStream, NULL, NULL, NULL)); + if (inSize != _zlibDecoderSpec->GetInputProcessedSize()) + return S_FALSE; + } + return S_OK; +} + +HRESULT CHandler::ReadMetadataBlock(UInt32 &packSize) +{ + Byte temp[3]; + unsigned offset = _h.NeedCheckData() ? 3 : 2; + if (offset > packSize) + return S_FALSE; + RINOK(ReadStream_FALSE(_stream, temp, offset)); + // if (NeedCheckData && Major < 4) checkByte must be = 0xFF + bool be = _h.be; + UInt32 size = Get16(temp); + bool isCompressed = ((size & kNotCompressedBit16) == 0); + if (size != kNotCompressedBit16) + size &= ~kNotCompressedBit16; + + if (size > kMetadataBlockSize || offset + size > packSize) + return S_FALSE; + packSize = offset + size; + if (isCompressed) + { + _limitedInStreamSpec->Init(size); + RINOK(Decompress(_dynOutStream, size, kMetadataBlockSize)); + } + else + { + // size != 0 here + Byte *buf = _dynOutStreamSpec->GetBufPtrForWriting(size); + if (!buf) + return E_OUTOFMEMORY; + RINOK(ReadStream_FALSE(_stream, buf, size)); + _dynOutStreamSpec->UpdateSize(size); + } + return S_OK; +} + +HRESULT CHandler::ReadData(CData &data, UInt64 start, UInt64 end) +{ + if (end < start || end - start >= ((UInt64)1 << 32)) + return S_FALSE; + UInt32 size = (UInt32)(end - start); + RINOK(_stream->Seek(start, STREAM_SEEK_SET, NULL)); + _dynOutStreamSpec->Init(); + UInt32 packPos = 0; + while (packPos != size) + { + data.PackPos.Add(packPos); + data.UnpackPos.Add((UInt32)_dynOutStreamSpec->GetSize()); + if (packPos > size) + return S_FALSE; + UInt32 packSize = size - packPos; + RINOK(ReadMetadataBlock(packSize)); + if (_dynOutStreamSpec->GetSize() >= ((UInt64)1 << 32)) + return S_FALSE; + packPos += packSize; + } + data.UnpackPos.Add((UInt32)_dynOutStreamSpec->GetSize()); + _dynOutStreamSpec->CopyToBuffer(data.Data); + return S_OK; +} + +struct CTempItem +{ + UInt32 StartBlock; + // UInt32 iNodeNumber1; + UInt32 Offset; + // UInt16 iNodeNumber2; + UInt16 Type; +}; + +HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned level, int &nodeIndex) +{ + if (level > kNumDirLevelsMax) + return S_FALSE; + + int blockIndex = _inodesData.PackPos.FindInSorted(startBlock); + if (blockIndex < 0) + return S_FALSE; + UInt32 unpackPos = _inodesData.UnpackPos[blockIndex] + offset; + if (unpackPos < offset) + return S_FALSE; + + nodeIndex = _nodesPos.FindInSorted(unpackPos, _blockToNode[blockIndex], _blockToNode[blockIndex + 1]); + // nodeIndex = _nodesPos.FindInSorted(unpackPos); + if (nodeIndex < 0) + return S_FALSE; + + const CNode &n = _nodes[nodeIndex]; + if (!n.IsDir()) + return S_OK; + blockIndex = _dirs.PackPos.FindInSorted((UInt32)n.StartBlock); + if (blockIndex < 0) + return S_FALSE; + unpackPos = _dirs.UnpackPos[blockIndex] + n.Offset; + if (unpackPos < n.Offset || unpackPos > _dirs.Data.GetCapacity()) + return S_FALSE; + + UInt32 rem = (UInt32)_dirs.Data.GetCapacity() - unpackPos; + const Byte *p = _dirs.Data + unpackPos; + UInt32 fileSize = (UInt32)n.FileSize; + + if (fileSize > rem) + return S_FALSE; + rem = fileSize; + if (_h.Major >= 3) + { + if (rem < 3) + return S_FALSE; + rem -= 3; + } + + CRecordVector tempItems; + while (rem != 0) + { + bool be = _h.be; + UInt32 count; + CTempItem tempItem; + if (_h.Major <= 2) + { + if (rem < 4) + return S_FALSE; + count = p[0]; + tempItem.StartBlock = Get32(p); + if (be) + tempItem.StartBlock &= 0xFFFFFF; + else + tempItem.StartBlock >>= 8; + p += 4; + rem -= 4; + } + else + { + if (_h.Major == 3) + { + if (rem < 9) + return S_FALSE; + count = p[0]; + p += 1; + rem -= 1; + } + else + { + if (rem < 12) + return S_FALSE; + count = GetUi32(p); + p += 4; + rem -= 4; + } + GET_32 (0, tempItem.StartBlock); + // GET_32 (4, tempItem.iNodeNumber1); + p += 8; + rem -= 8; + } + count++; + + for (UInt32 i = 0; i < count; i++) + { + if (rem == 0) + return S_FALSE; + + UInt32 nameOffset = _h.GetFileNameOffset(); + if (rem < nameOffset) + return S_FALSE; + + if ((UInt32)_items.Size() >= kNumFilesMax) + return S_FALSE; + if (_openCallback) + { + UInt64 numFiles = _items.Size(); + if ((numFiles & 0xFFFF) == 0) + { + RINOK(_openCallback->SetCompleted(&numFiles, NULL)); + } + } + + CItem item; + item.Ptr = (UInt32)(p - _dirs.Data); + + UInt32 size; + if (_h.IsOldVersion()) + { + UInt32 t = Get16(p); + if (be) + { + tempItem.Offset = t >> 3; + tempItem.Type = (UInt16)(t & 0x7); + } + else + { + tempItem.Offset = t & 0x1FFF; + tempItem.Type = (UInt16)(t >> 13); + } + size = (UInt32)p[2]; + /* + if (_h.Major > 2) + tempItem.iNodeNumber2 = Get16(p + 3); + */ + } + else + { + GET_16 (0, tempItem.Offset); + // GET_16 (2, tempItem.iNodeNumber2); + GET_16 (4, tempItem.Type); + GET_16 (6, size); + } + p += nameOffset; + rem -= nameOffset; + size++; + if (rem < size) + return S_FALSE; + p += size; + rem -= size; + item.Parent = parent; + _items.Add(item); + tempItems.Add(tempItem); + } + } + + int startItemIndex = _items.Size() - tempItems.Size(); + for (int i = 0; i < tempItems.Size(); i++) + { + const CTempItem &tempItem = tempItems[i]; + int index = startItemIndex + i; + CItem &item = _items[index]; + RINOK(OpenDir(index, tempItem.StartBlock, tempItem.Offset, level + 1, item.Node)); + } + + return S_OK; +} + +/* +HRESULT CHandler::ReadUids(UInt64 start, UInt32 num, CByteBuffer &ids) +{ + size_t size = num * 4; + ids.SetCapacity(size); + RINOK(_stream->Seek(start, STREAM_SEEK_SET, NULL)); + return ReadStream_FALSE(_stream, ids, size); +} +*/ + +HRESULT CHandler::Open2(IInStream *inStream) +{ + { + Byte buf[kHeaderSize3]; + RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize3)); + if (!_h.Parse(buf)) + return S_FALSE; + if (!_h.IsSupported()) + return E_NOTIMPL; + + switch (_h.Method) + { + case kMethod_ZLIB: + case kMethod_LZMA: + break; + default: + return E_NOTIMPL; + } + } + + _stream = inStream; + + if (_h.NumFrags != 0) + { + if (_h.NumFrags > kNumFilesMax) + return S_FALSE; + _frags.Reserve(_h.NumFrags); + CByteBuffer data; + unsigned bigFrag = (_h.Major > 2); + + unsigned fragPtrsInBlockLog = kMetadataBlockSizeLog - (3 + bigFrag); + UInt32 numBlocks = (_h.NumFrags + (1 << fragPtrsInBlockLog) - 1) >> fragPtrsInBlockLog; + size_t numBlocksBytes = (size_t)numBlocks << (2 + bigFrag); + data.SetCapacity(numBlocksBytes); + RINOK(inStream->Seek(_h.FragTable, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream_FALSE(inStream, data, numBlocksBytes)); + bool be = _h.be; + + for (UInt32 i = 0; i < numBlocks; i++) + { + UInt64 offset = bigFrag ? Get64(data + i * 8) : Get32(data + i * 4); + RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); + _dynOutStreamSpec->Init(); + UInt32 packSize = kMetadataBlockSize + 3; + RINOK(ReadMetadataBlock(packSize)); + UInt32 unpackSize = (UInt32)_dynOutStreamSpec->GetSize(); + if (unpackSize != kMetadataBlockSize) + if (i != numBlocks - 1 || unpackSize != ((_h.NumFrags << (3 + bigFrag)) & (kMetadataBlockSize - 1))) + return S_FALSE; + const Byte *buf = _dynOutStreamSpec->GetBuffer(); + for (UInt32 j = 0; j < kMetadataBlockSize && j < unpackSize;) + { + CFrag frag; + if (bigFrag) + { + frag.StartBlock = Get64(buf + j); + frag.Size = Get32(buf + j + 8); + // some archives contain nonzero in unused (buf + j + 12) + j += 16; + } + else + { + frag.StartBlock = Get32(buf + j); + frag.Size = Get32(buf + j + 4); + j += 8; + } + _frags.Add(frag); + } + } + if ((UInt32)_frags.Size() != _h.NumFrags) + return S_FALSE; + } + + // RINOK(inStream->Seek(_h.InodeTable, STREAM_SEEK_SET, NULL)); + + RINOK(ReadData(_inodesData, _h.InodeTable, _h.DirTable)); + RINOK(ReadData(_dirs, _h.DirTable, _h.FragTable)); + + UInt64 absOffset = _h.RootInode >> 16; + if (absOffset >= ((UInt64)1 << 32)) + return S_FALSE; + { + UInt32 pos = 0; + UInt32 totalSize = (UInt32)_inodesData.Data.GetCapacity(); + _nodesPos.Reserve(_h.NumInodes); + _nodes.Reserve(_h.NumInodes); + // we use _blockToNode for binary search seed optimizations + _blockToNode.Reserve(_inodesData.GetNumBlocks() + 1); + int curBlock = 0; + for (UInt32 i = 0; i < _h.NumInodes; i++) + { + CNode n; + const Byte *p = _inodesData.Data + pos; + UInt32 size = totalSize - pos; + + switch(_h.Major) + { + case 1: size = n.Parse1(p, size, _h); break; + case 2: size = n.Parse2(p, size, _h); break; + case 3: size = n.Parse3(p, size, _h); break; + default: size = n.Parse4(p, size, _h); break; + } + if (size == 0) + return S_FALSE; + while (pos >= _inodesData.UnpackPos[curBlock]) + { + _blockToNode.Add(_nodesPos.Size()); + curBlock++; + } + _nodesPos.Add(pos); + _nodes.Add(n); + pos += size; + } + _blockToNode.Add(_nodesPos.Size()); + if (pos != totalSize) + return S_FALSE; + } + int rootNodeIndex; + RINOK(OpenDir(-1, (UInt32)absOffset, (UInt32)_h.RootInode & 0xFFFF, 0, rootNodeIndex)); + + /* + if (_h.Major < 4) + { + RINOK(ReadUids(_h.UidTable, _h.NumUids, _uids)); + RINOK(ReadUids(_h.GidTable, _h.NumGids, _gids)); + } + else + { + UInt32 size = _h.NumIDs * 4; + _uids.SetCapacity(size); + + UInt32 numBlocks = (size + kMetadataBlockSize - 1) / kMetadataBlockSize; + UInt32 numBlocksBytes = numBlocks << 3; + CByteBuffer data; + data.SetCapacity(numBlocksBytes); + RINOK(inStream->Seek(_h.UidTable, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream_FALSE(inStream, data, numBlocksBytes)); + + for (UInt32 i = 0; i < numBlocks; i++) + { + UInt64 offset = GetUi64(data + i * 8); + UInt32 unpackSize, packSize; + RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); + RINOK(ReadMetadataBlock(NULL, _uids + kMetadataBlockSize * i, packSize, unpackSize)); + if (unpackSize != kMetadataBlockSize) + if (i != numBlocks - 1 || unpackSize != (size & (kMetadataBlockSize - 1))) + return S_FALSE; + } + } + */ + + { + const UInt32 alignSize = 1 << 12; + Byte buf[alignSize]; + RINOK(inStream->Seek(_h.Size, STREAM_SEEK_SET, NULL)); + UInt32 rem = (UInt32)(0 - _h.Size) & (alignSize - 1); + _sizeCalculated = _h.Size; + if (rem != 0) + { + if (ReadStream_FALSE(_stream, buf, rem) == S_OK) + { + size_t i; + for (i = 0; i < rem && buf[i] == 0; i++); + if (i == rem) + _sizeCalculated = _h.Size + rem; + } + } + } + return S_OK; +} + +AString CHandler::GetPath(int index) const +{ + unsigned len = 0; + int indexMem = index; + bool be = _h.be; + do + { + const CItem &item = _items[index]; + index = item.Parent; + const Byte *p = _dirs.Data + item.Ptr; + unsigned size = (_h.IsOldVersion() ? (unsigned)p[2] : (unsigned)Get16(p + 6)) + 1; + p += _h.GetFileNameOffset(); + unsigned i; + for (i = 0; i < size && p[i]; i++); + len += i + 1; + } + while (index >= 0); + len--; + + AString path; + char *dest = path.GetBuffer(len) + len; + index = indexMem; + for (;;) + { + const CItem &item = _items[index]; + index = item.Parent; + + const Byte *p = _dirs.Data + item.Ptr; + unsigned size = (_h.IsOldVersion() ? (unsigned)p[2] : (unsigned)Get16(p + 6)) + 1; + p += _h.GetFileNameOffset(); + unsigned i; + for (i = 0; i < size && p[i]; i++); + dest -= i; + memcpy(dest, p, i); + if (index < 0) + break; + *(--dest) = CHAR_PATH_SEPARATOR; + } + path.ReleaseBuffer(len); + return path; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + { + Close(); + _limitedInStreamSpec->SetStream(stream); + HRESULT res; + try + { + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + _openCallback = callback; + res = Open2(stream); + } + catch(...) + { + Close(); + throw; + } + if (res != S_OK) + { + Close(); + return res; + } + _stream = stream; + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _limitedInStreamSpec->ReleaseStream(); + _stream.Release(); + + _items.Clear(); + _nodes.Clear(); + _nodesPos.Clear(); + _blockToNode.Clear(); + _frags.Clear(); + _inodesData.Clear(); + _dirs.Clear(); + + // _uids.Free(); + // _gids.Free();; + + _cachedBlock.Free(); + ClearCache(); + + return S_OK; +} + +bool CHandler::GetPackSize(int index, UInt64 &totalPack, bool fillOffsets) +{ + totalPack = 0; + const CItem &item = _items[index]; + const CNode &node = _nodes[item.Node]; + UInt32 ptr = _nodesPos[item.Node]; + const Byte *p = _inodesData.Data + ptr; + bool be = _h.be; + + UInt32 type = node.Type; + UInt32 offset; + if (node.IsLink() || node.FileSize == 0) + { + totalPack = node.FileSize; + return true; + } + + UInt32 numBlocks = (UInt32)node.GetNumBlocks(_h); + + if (fillOffsets) + { + _blockOffsets.Clear(); + _blockCompressed.Clear(); + _blockOffsets.Add(totalPack); + } + + if (_h.Major <= 1) + { + offset = 15; + p += offset; + + for (UInt32 i = 0; i < numBlocks; i++) + { + UInt32 t = Get16(p + i * 2); + if (fillOffsets) + _blockCompressed.Add((t & kNotCompressedBit16) == 0); + if (t != kNotCompressedBit16) + t &= ~kNotCompressedBit16; + totalPack += t; + if (fillOffsets) + _blockOffsets.Add(totalPack); + } + } + else + { + if (_h.Major <= 2) + offset = 24; + else if (type == kType_FILE) + offset = 32; + else if (type == kType_FILE + 7) + offset = (_h.Major <= 3 ? 40 : 56); + else + return false; + + p += offset; + + for (UInt64 i = 0; i < numBlocks; i++) + { + UInt32 t = Get32(p + i * 4); + if (fillOffsets) + _blockCompressed.Add(IS_COMPRESSED_BLOCK(t)); + UInt32 size = GET_COMPRESSED_BLOCK_SIZE(t); + if (size > _h.BlockSize) + return false; + totalPack += size; + if (fillOffsets) + _blockOffsets.Add(totalPack); + } + + if (node.ThereAreFrags()) + { + if (node.Frag >= (UInt32)_frags.Size()) + return false; + const CFrag &frag = _frags[node.Frag]; + if (node.Offset == 0) + { + UInt32 size = GET_COMPRESSED_BLOCK_SIZE(frag.Size); + if (size > _h.BlockSize) + return false; + totalPack += size; + } + } + } + return true; +} + + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _items.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidMethod: + { + const char *s; + if (_h.SeveralMethods) + s = "LZMA ZLIB"; + else + { + s = k_Methods[0]; + if (_h.Method < sizeof(k_Methods) / sizeof(k_Methods[0])) + s = k_Methods[_h.Method]; + } + prop = s; + break; + } + case kpidFileSystem: + { + AString res = "SquashFS"; + if (_h.SeveralMethods) + res += "-LZMA"; + res += ' '; + char s[16]; + ConvertUInt32ToString(_h.Major, s); + res += s; + res += '.'; + ConvertUInt32ToString(_h.Minor, s); + res += s; + prop = res; + break; + } + case kpidBlock: prop = _h.BlockSize; break; + case kpidBigEndian: prop = _h.be; break; + case kpidCTime: + if (_h.CTime != 0) + { + FILETIME ft; + NWindows::NTime::UnixTimeToFileTime(_h.CTime, ft); + prop = ft; + } + break; + case kpidCharacts: FLAGS_TO_PROP(k_Flags, _h.Flags, prop); break; + // case kpidNumBlocks: prop = _h.NumFrags; break; + case kpidPhySize: prop = _sizeCalculated; break; + case kpidHeadersSize: + if (_sizeCalculated >= _h.InodeTable) + prop = _sizeCalculated - _h.InodeTable; + 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 CNode &node = _nodes[item.Node]; + bool isDir = node.IsDir(); + bool be = _h.be; + + switch(propID) + { + case kpidPath: prop = MultiByteToUnicodeString(GetPath(index), CP_OEMCP); break; + case kpidIsDir: prop = isDir; break; + // case kpidOffset: if (!node.IsLink()) prop = (UInt64)node.StartBlock; break; + case kpidSize: if (!isDir) prop = node.GetSize(); break; + case kpidPackSize: + if (!isDir) + { + UInt64 size; + if (GetPackSize(index, size, false)) + prop = size; + } + break; + case kpidMTime: + { + UInt32 offset = 0; + switch(_h.Major) + { + case 1: + if (node.Type == kType_FILE) + offset = 3; + else if (node.Type == kType_DIR) + offset = 7; + break; + case 2: + if (node.Type == kType_FILE) + offset = 4; + else if (node.Type == kType_DIR) + offset = 8; + else if (node.Type == kType_DIR + 7) + offset = 9; + break; + case 3: offset = 4; break; + case 4: offset = 8; break; + } + if (offset != 0) + { + const Byte *p = _inodesData.Data + _nodesPos[item.Node] + offset; + FILETIME ft; + NWindows::NTime::UnixTimeToFileTime(Get32(p), ft); + prop = ft; + } + break; + } + case kpidPosixAttrib: + { + if (node.Type != 0 && node.Type < sizeof(k_TypeToMode) / sizeof(k_TypeToMode[0])) + prop = (UInt32)(node.Mode & 0xFFF) | k_TypeToMode[node.Type]; + break; + } + /* + case kpidUser: + { + UInt32 offset = node.Uid * 4; + if (offset < _uids.GetCapacity()) + prop = (UInt32)Get32(_uids + offset); + break; + } + case kpidGroup: + { + if (_h.Major == 4 || node.Gid == _h.GetSpecGuidIndex()) + { + UInt32 offset = node.Uid * 4; + if (offset < _uids.GetCapacity()) + prop = (UInt32)Get32(_uids + offset); + } + else + { + UInt32 offset = node.Gid * 4; + if (offset < _gids.GetCapacity()) + prop = (UInt32)Get32(_gids + offset); + } + break; + } + */ + /* + case kpidLinks: + if (_h.Major >= 3 && node.Type != kType_FILE) + prop = node.NumLinks; + break; + */ + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +class CSquashfsInStream: public CCachedInStream +{ + HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize); +public: + CHandler *Handler; +}; + +HRESULT CSquashfsInStream::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) +{ + return Handler->ReadBlock(blockIndex, dest, blockSize); +} + +HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) +{ + const CNode &node = _nodes[_nodeIndex]; + UInt64 blockOffset; + UInt32 packBlockSize; + UInt32 offsetInBlock = 0; + bool compressed; + if (blockIndex < _blockCompressed.Size()) + { + compressed = _blockCompressed[(int)blockIndex]; + blockOffset = _blockOffsets[(int)blockIndex]; + packBlockSize = (UInt32)(_blockOffsets[(int)blockIndex + 1] - blockOffset); + blockOffset += node.StartBlock; + } + else + { + if (!node.ThereAreFrags()) + return S_FALSE; + const CFrag &frag = _frags[node.Frag]; + offsetInBlock = node.Offset; + blockOffset = frag.StartBlock; + packBlockSize = GET_COMPRESSED_BLOCK_SIZE(frag.Size); + compressed = IS_COMPRESSED_BLOCK(frag.Size); + } + + if (packBlockSize == 0) + { + // sparse file ??? + memset(dest, 0, blockSize); + return S_OK; + } + + if (blockOffset != _cachedBlockStartPos || + packBlockSize != _cachedPackBlockSize) + { + ClearCache(); + RINOK(_stream->Seek(blockOffset, STREAM_SEEK_SET, NULL)); + _limitedInStreamSpec->Init(packBlockSize); + + if (compressed) + { + _outStreamSpec->Init((Byte *)_cachedBlock, _h.BlockSize); + HRESULT res = Decompress(_outStream, packBlockSize, _h.BlockSize); + _cachedUnpackBlockSize = (UInt32)_outStreamSpec->GetPos(); + RINOK(res); + } + else + { + RINOK(ReadStream_FALSE(_limitedInStream, _cachedBlock, packBlockSize)); + _cachedUnpackBlockSize = packBlockSize; + } + _cachedBlockStartPos = blockOffset; + _cachedPackBlockSize = packBlockSize; + } + if (offsetInBlock + blockSize > _cachedUnpackBlockSize) + return S_FALSE; + memcpy(dest, _cachedBlock + offsetInBlock, blockSize); + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _items.Size(); + if (numItems == 0) + return S_OK; + UInt64 totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + { + const CItem &item = _items[allFilesMode ? i : indices[i]]; + const CNode &node = _nodes[item.Node]; + totalSize += node.GetSize(); + } + extractCallback->SetTotal(totalSize); + + UInt64 totalPackSize; + totalSize = totalPackSize = 0; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + for (i = 0; i < numItems; i++) + { + lps->InSize = totalPackSize; + lps->OutSize = totalSize; + RINOK(lps->SetCur()); + CMyComPtr outStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + UInt32 index = allFilesMode ? i : indices[i]; + const CItem &item = _items[index]; + const CNode &node = _nodes[item.Node]; + RINOK(extractCallback->GetStream(index, &outStream, askMode)); + // const Byte *p = _data + item.Offset; + + if (node.IsDir()) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + UInt64 unpackSize = node.GetSize(); + totalSize += unpackSize; + UInt64 packSize; + if (GetPackSize(index, packSize, false)) + totalPackSize += packSize; + + if (!testMode && !outStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + + int res = NExtract::NOperationResult::kDataError; + { + CMyComPtr inSeqStream; + CMyComPtr inStream; + HRESULT hres = GetStream(index, &inSeqStream); + if (inSeqStream) + inSeqStream.QueryInterface(IID_IInStream, &inStream); + if (hres == S_FALSE || !inStream) + { + if (hres == E_OUTOFMEMORY) + return hres; + res = 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 == unpackSize && hres == S_OK) + res = NExtract::NOperationResult::kOK; + else + { + res = res; + } + } + } + } + RINOK(extractCallback->SetOperationResult(res)); + } + return S_OK; + COM_TRY_END +} + + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + + const CItem &item = _items[index]; + const CNode &node = _nodes[item.Node]; + + if (node.IsDir()) + return E_FAIL; + + const Byte *p = _inodesData.Data + _nodesPos[item.Node]; + + if (node.FileSize == 0 || node.IsLink()) + { + CBufInStream *streamSpec = new CBufInStream; + CMyComPtr streamTemp = streamSpec; + if (node.IsLink()) + streamSpec->Init(p + _h.GetSymLinkOffset(), (size_t)node.FileSize); + else + streamSpec->Init(NULL, 0); + *stream = streamTemp.Detach(); + return S_OK; + } + + UInt64 packSize; + if (!GetPackSize(index, packSize, true)) + return S_FALSE; + + _nodeIndex = item.Node; + + size_t cacheSize = _h.BlockSize; + if (_cachedBlock.GetCapacity() != cacheSize) + { + ClearCache(); + _cachedBlock.SetCapacity(cacheSize); + } + + CSquashfsInStream *streamSpec = new CSquashfsInStream; + CMyComPtr streamTemp = streamSpec; + streamSpec->Handler = this; + unsigned cacheSizeLog = 22; + if (cacheSizeLog <= _h.BlockSizeLog) + cacheSizeLog = _h.BlockSizeLog + 1; + if (!streamSpec->Alloc(_h.BlockSizeLog, cacheSizeLog - _h.BlockSizeLog)) + return E_OUTOFMEMORY; + streamSpec->Init(node.FileSize); + *stream = streamTemp.Detach(); + + return S_OK; + + COM_TRY_END +} + +static IInArchive *CreateArc() { return new NArchive::NSquashfs::CHandler; } + +static CArcInfo g_ArcInfo = + { L"SquashFS", L"squashfs", 0, 0xD2, SIGNATURE, kSignatureSize, false, CreateArc, 0 }; + +REGISTER_ARC(Cramfs) + +}} diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp index e25463de..4db0cae8 100755 --- a/CPP/7zip/Archive/Tar/TarHandler.cpp +++ b/CPP/7zip/Archive/Tar/TarHandler.cpp @@ -10,6 +10,8 @@ #include "../../Common/LimitedStreams.h" #include "../../Common/ProgressUtils.h" +#include "../../Common/StreamObjects.h" +#include "../../Common/StreamUtils.h" #include "../Common/ItemNameUtils.h" @@ -21,7 +23,9 @@ using namespace NWindows; namespace NArchive { namespace NTar { -static STATPROPSTG kProps[] = +static const char *kUnexpectedEnd = "Unexpected end of archive"; + +static const STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidIsDir, VT_BOOL}, @@ -34,8 +38,14 @@ static STATPROPSTG kProps[] = { NULL, kpidLink, VT_BSTR} }; +static const STATPROPSTG kArcProps[] = +{ + { NULL, kpidPhySize, VT_UI8}, + { NULL, kpidHeadersSize, VT_UI8} +}; + IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO_Table +IMP_IInArchive_ArcProps STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { @@ -43,11 +53,22 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) switch(propID) { case kpidPhySize: if (_phySizeDefined) prop = _phySize; break; + case kpidHeadersSize: if (_phySizeDefined) prop = _headersSize; break; + case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break; } prop.Detach(value); return S_OK; } +HRESULT CHandler::ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx &item) +{ + item.HeaderPos = _phySize; + RINOK(ReadItem(stream, filled, item, _errorMessage)); + _phySize += item.HeaderSize; + _headersSize += item.HeaderSize; + return S_OK; +} + HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) { UInt64 endPos = 0; @@ -56,26 +77,29 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); } - _isGood = true; - UInt64 pos = 0; + _phySizeDefined = true; for (;;) { CItemEx item; bool filled; - item.HeaderPosition = pos; - RINOK(ReadItem(stream, filled, item)); + RINOK(ReadItem2(stream, filled, item)); if (!filled) break; _items.Add(item); - RINOK(stream->Seek(item.GetPackSize(), STREAM_SEEK_CUR, &pos)); - if (pos > endPos) - return S_FALSE; - if (pos == endPos) + RINOK(stream->Seek(item.GetPackSize(), STREAM_SEEK_CUR, &_phySize)); + if (_phySize > endPos) + { + _errorMessage = kUnexpectedEnd; + break; + } + /* + if (_phySize == endPos) { - _isGood = false; + _errorMessage = "There are no trailing zero-filled records"; break; } + */ if (callback != NULL) { if (_items.Size() == 1) @@ -85,7 +109,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) if (_items.Size() % 100 == 0) { UInt64 numFiles = _items.Size(); - RINOK(callback->SetCompleted(&numFiles, &pos)); + RINOK(callback->SetCompleted(&numFiles, &_phySize)); } } } @@ -132,7 +156,10 @@ STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) STDMETHODIMP CHandler::Close() { + _errorMessage.Empty(); _phySizeDefined = false; + _phySize = 0; + _headersSize = 0; _curIndex = 0; _latestIsRead = false; _items.Clear(); @@ -161,16 +188,24 @@ HRESULT CHandler::SkipTo(UInt32 index) { UInt64 packSize = _latestItem.GetPackSize(); RINOK(copyCoderSpec->Code(_seqStream, NULL, &packSize, &packSize, NULL)); + _phySize += copyCoderSpec->TotalSize; + if (copyCoderSpec->TotalSize != packSize) + { + _errorMessage = kUnexpectedEnd; + return S_FALSE; + } _latestIsRead = false; _curIndex++; } else { bool filled; - // item.HeaderPosition = pos; - RINOK(ReadItem(_seqStream, filled, _latestItem)); + RINOK(ReadItem2(_seqStream, filled, _latestItem)); if (!filled) + { + _phySizeDefined = true; return E_INVALIDARG; + } _latestIsRead = true; } } @@ -203,10 +238,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val switch(propID) { - 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 kpidPath: prop = NItemName::GetOSName2(TarStringToUnicode(item->Name)); break; + case kpidIsDir: prop = item->IsDir(); break; + case kpidSize: prop = item->GetUnpackSize(); break; + case kpidPackSize: prop = item->GetPackSize(); break; case kpidMTime: if (item->MTime != 0) { @@ -216,9 +251,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } 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; + 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; @@ -242,7 +277,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, UInt64 totalSize = 0; UInt32 i; for (i = 0; i < numItems; i++) - totalSize += _items[allFilesMode ? i : indices[i]].Size; + totalSize += _items[allFilesMode ? i : indices[i]].GetUnpackSize(); extractCallback->SetTotal(totalSize); UInt64 totalPackSize; @@ -282,7 +317,8 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, item = &_items[index]; RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - totalSize += item->Size; + UInt64 unpackSize = item->GetUnpackSize(); + totalSize += unpackSize; totalPackSize += item->GetPackSize(); if (item->IsDir()) { @@ -302,14 +338,21 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, outStreamSpec->SetStream(realOutStream); realOutStream.Release(); - outStreamSpec->Init(skipMode ? 0 : item->Size, true); + outStreamSpec->Init(skipMode ? 0 : unpackSize, true); - if (!seqMode) + if (item->IsLink()) + { + RINOK(WriteStream(outStreamSpec, (const char *)item->LinkName, item->LinkName.Length())); + } + else { - RINOK(_stream->Seek(item->GetDataPosition(), STREAM_SEEK_SET, NULL)); + if (!seqMode) + { + RINOK(_stream->Seek(item->GetDataPosition(), STREAM_SEEK_SET, NULL)); + } + streamSpec->Init(item->GetPackSize()); + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); } - streamSpec->Init(item->GetPackSize()); - RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); if (seqMode) { _latestIsRead = false; @@ -328,6 +371,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) { COM_TRY_BEGIN const CItemEx &item = _items[index]; + if (item.IsLink()) + { + CBufInStream *streamSpec = new CBufInStream; + CMyComPtr streamTemp = streamSpec; + streamSpec->Init((const Byte *)(const char *)item.LinkName, item.LinkName.Length(), (IInArchive *)this); + *stream = streamTemp.Detach(); + return S_OK; + } 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 d2def9a1..b1967061 100755 --- a/CPP/7zip/Archive/Tar/TarHandler.h +++ b/CPP/7zip/Archive/Tar/TarHandler.h @@ -23,18 +23,20 @@ class CHandler: CObjectVector _items; CMyComPtr _stream; CMyComPtr _seqStream; - bool _isGood; UInt32 _curIndex; bool _latestIsRead; CItemEx _latestItem; UInt64 _phySize; + UInt64 _headersSize; bool _phySizeDefined; + AString _errorMessage; NCompress::CCopyCoder *copyCoderSpec; CMyComPtr copyCoder; + HRESULT ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx &itemInfo); HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); HRESULT SkipTo(UInt32 index); diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp index a999f838..ffdf2b13 100755 --- a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp +++ b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp @@ -37,7 +37,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt IArchiveUpdateCallback *callback) { COM_TRY_BEGIN - if ((_stream && !_isGood) || _seqStream) + if ((_stream && !_errorMessage.IsEmpty()) || _seqStream) return E_NOTIMPL; CObjectVector updateItems; for (UInt32 i = 0; i < numItems; i++) diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp index c9c3c422..5ceaa509 100755 --- a/CPP/7zip/Archive/Tar/TarIn.cpp +++ b/CPP/7zip/Archive/Tar/TarIn.cpp @@ -63,29 +63,40 @@ static void ReadString(const char *s, int size, AString &result) result = temp; } -static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemEx &item, size_t &processedSize) +static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemEx &item, AString &error) { - item.LongLinkSize = 0; char buf[NFileHeader::kRecordSize]; char *p = buf; + error.Empty(); filled = false; bool thereAreEmptyRecords = false; for (;;) { - processedSize = NFileHeader::kRecordSize; + size_t processedSize = NFileHeader::kRecordSize; RINOK(ReadStream(stream, buf, &processedSize)); if (processedSize == 0) + { + if (!thereAreEmptyRecords ) + error = "There are no trailing zero-filled records"; return S_OK; + } if (processedSize != NFileHeader::kRecordSize) - return S_FALSE; + { + error = "There is no correct record at the end of archive"; + return S_OK; + } + item.HeaderSize += NFileHeader::kRecordSize; if (!IsRecordLast(buf)) break; thereAreEmptyRecords = true; } if (thereAreEmptyRecords) - return S_FALSE; + { + error = "There are data after end of archive"; + return S_OK; + } ReadString(p, NFileHeader::kNameSize, item.Name); p += NFileHeader::kNameSize; @@ -143,59 +154,54 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE return S_OK; } -HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item) +HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, AString &error) { - size_t processedSize; - RINOK(GetNextItemReal(stream, filled, item, processedSize)); - if (!filled) - return S_OK; - // GNUtar extension - if (item.LinkFlag == 'L' || // NEXT file has a long name - item.LinkFlag == 'K') // NEXT file has a long linkname + item.HeaderSize = 0; + bool flagL = false; + bool flagK = false; + AString nameL; + AString nameK; + for (;;) { - if (item.Name.Compare(NFileHeader::kLongLink) != 0) - if (item.Name.Compare(NFileHeader::kLongLink2) != 0) + RINOK(GetNextItemReal(stream, filled, item, error)); + if (!filled) + return S_OK; + if (item.LinkFlag == 'L' || // NEXT file has a long name + item.LinkFlag == 'K') // NEXT file has a long linkname + { + AString *name; + if (item.LinkFlag == 'L') + { if (flagL) return S_FALSE; flagL = true; name = &nameL; } + else + { if (flagK) return S_FALSE; flagK = true; name = &nameK; } + + if (item.Name.Compare(NFileHeader::kLongLink) != 0 && + item.Name.Compare(NFileHeader::kLongLink2) != 0) return S_FALSE; - - AString fullName; - if (item.Size > (1 << 15)) - return S_FALSE; - int packSize = (int)item.GetPackSize(); - char *buffer = fullName.GetBuffer(packSize + 1); - - RINOK(ReadStream_FALSE(stream, buffer, packSize)); - processedSize += packSize; - buffer[item.Size] = '\0'; - fullName.ReleaseBuffer(); - - UInt64 headerPosition = item.HeaderPosition; - if (item.LinkFlag == 'L') + if (item.Size > (1 << 14)) + return S_FALSE; + int packSize = (int)item.GetPackSize(); + char *buf = name->GetBuffer(packSize); + RINOK(ReadStream_FALSE(stream, buf, packSize)); + item.HeaderSize += packSize; + buf[(size_t)item.Size] = '\0'; + name->ReleaseBuffer(); + continue; + } + if (item.LinkFlag == 'g' || item.LinkFlag == 'x' || item.LinkFlag == 'X') { - size_t processedSize2; - RINOK(GetNextItemReal(stream, filled, item, processedSize2)); - item.LongLinkSize = (unsigned)processedSize; + // pax Extended Header } - else + else if (item.LinkFlag == NFileHeader::NLinkFlag::kDumpDir) { - item.LongLinkSize = (unsigned)processedSize - NFileHeader::kRecordSize; - item.Size = 0; + // GNU Extensions to the Archive Format } - item.Name = fullName; - item.HeaderPosition = headerPosition; - } - else if (item.LinkFlag == 'g' || item.LinkFlag == 'x' || item.LinkFlag == 'X') - { - // pax Extended Header - return S_OK; - } - else if (item.LinkFlag == NFileHeader::NLinkFlag::kDumpDir) - { - // GNU Extensions to the Archive Format + else if (item.LinkFlag > '7' || (item.LinkFlag < '0' && item.LinkFlag != 0)) + return S_FALSE; + if (flagL) item.Name = nameL; + if (flagK) item.LinkName = nameK; return S_OK; } - else if (item.LinkFlag > '7' || (item.LinkFlag < '0' && item.LinkFlag != 0)) - return S_FALSE; - return S_OK; } }} diff --git a/CPP/7zip/Archive/Tar/TarIn.h b/CPP/7zip/Archive/Tar/TarIn.h index cc6e3f5b..a5491ebe 100755 --- a/CPP/7zip/Archive/Tar/TarIn.h +++ b/CPP/7zip/Archive/Tar/TarIn.h @@ -1,9 +1,8 @@ -// Archive/TarIn.h +// TarIn.h #ifndef __ARCHIVE_TAR_IN_H #define __ARCHIVE_TAR_IN_H -#include "Common/MyCom.h" #include "../../IStream.h" #include "TarItem.h" @@ -11,7 +10,7 @@ namespace NArchive { namespace NTar { -HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &itemInfo); +HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &itemInfo, AString &error); }} diff --git a/CPP/7zip/Archive/Tar/TarItem.h b/CPP/7zip/Archive/Tar/TarItem.h index afe8997d..859e66dd 100755 --- a/CPP/7zip/Archive/Tar/TarItem.h +++ b/CPP/7zip/Archive/Tar/TarItem.h @@ -31,6 +31,9 @@ struct CItem bool DeviceMajorDefined; bool DeviceMinorDefined; + bool IsLink() const { return LinkFlag == NFileHeader::NLinkFlag::kSymbolicLink && (Size == 0); } + UInt64 GetUnpackSize() const { return IsLink() ? LinkName.Length() : Size; } + bool IsDir() const { switch(LinkFlag) @@ -58,10 +61,10 @@ struct CItem struct CItemEx: public CItem { - UInt64 HeaderPosition; - unsigned LongLinkSize; - UInt64 GetDataPosition() const { return HeaderPosition + LongLinkSize + NFileHeader::kRecordSize; } - UInt64 GetFullSize() const { return LongLinkSize + NFileHeader::kRecordSize + Size; } + UInt64 HeaderPos; + unsigned HeaderSize; + UInt64 GetDataPosition() const { return HeaderPos + HeaderSize; } + UInt64 GetFullSize() const { return HeaderSize + Size; } }; }} diff --git a/CPP/7zip/Archive/Tar/TarUpdate.cpp b/CPP/7zip/Archive/Tar/TarUpdate.cpp index 0577848f..c1633218 100755 --- a/CPP/7zip/Archive/Tar/TarUpdate.cpp +++ b/CPP/7zip/Archive/Tar/TarUpdate.cpp @@ -111,25 +111,25 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, } else { - const CItemEx &existItemInfo = inputItems[ui.IndexInArchive]; + const CItemEx &existItem = inputItems[ui.IndexInArchive]; UInt64 size; if (ui.NewProps) { RINOK(outArchive.WriteHeader(item)); - RINOK(inStream->Seek(existItemInfo.GetDataPosition(), STREAM_SEEK_SET, NULL)); - size = existItemInfo.Size; + RINOK(inStream->Seek(existItem.GetDataPosition(), STREAM_SEEK_SET, NULL)); + size = existItem.Size; } else { - RINOK(inStream->Seek(existItemInfo.HeaderPosition, STREAM_SEEK_SET, NULL)); - size = existItemInfo.GetFullSize(); + RINOK(inStream->Seek(existItem.HeaderPos, STREAM_SEEK_SET, NULL)); + size = existItem.GetFullSize(); } streamSpec->Init(size); RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)); if (copyCoderSpec->TotalSize != size) return E_FAIL; - RINOK(outArchive.FillDataResidual(existItemInfo.Size)); + RINOK(outArchive.FillDataResidual(existItem.Size)); complexity += size; } } diff --git a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp index c7eb9980..50b879e7 100755 --- a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp +++ b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp @@ -323,25 +323,13 @@ static void AddTagUInt64(AString &s, const char *name, UInt64 value) AddTag(s, name, temp); } -static void ConvertUInt32ToHex(UInt32 value, char *s) -{ - for (int i = 0; i < 8; i++) - { - int t = value & 0xF; - value >>= 4; - s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); - } - s[8] = '\0'; -} - - static AString TimeToXml(FILETIME &ft) { AString res; char temp[16] = { '0', 'x' }; - ConvertUInt32ToHex(ft.dwHighDateTime, temp + 2); + ConvertUInt32ToHexWithZeros(ft.dwHighDateTime, temp + 2); AddTag(res, "HIGHPART", temp); - ConvertUInt32ToHex(ft.dwLowDateTime, temp + 2); + ConvertUInt32ToHexWithZeros(ft.dwLowDateTime, temp + 2); AddTag(res, "LOWPART", temp); return res; } diff --git a/CPP/7zip/Archive/Wim/WimIn.cpp b/CPP/7zip/Archive/Wim/WimIn.cpp index 5edfacc5..c210804d 100755 --- a/CPP/7zip/Archive/Wim/WimIn.cpp +++ b/CPP/7zip/Archive/Wim/WimIn.cpp @@ -240,7 +240,7 @@ static HRESULT UnpackData(IInStream *inStream, const CResource &resource, bool l buf.Free(); buf.SetCapacity(size); - CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2(); + CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream(); CMyComPtr outStream = outStreamSpec; outStreamSpec->Init((Byte *)buf, size); diff --git a/CPP/7zip/Archive/XarHandler.cpp b/CPP/7zip/Archive/XarHandler.cpp index 56570230..e7d88b6c 100755 --- a/CPP/7zip/Archive/XarHandler.cpp +++ b/CPP/7zip/Archive/XarHandler.cpp @@ -268,7 +268,7 @@ HRESULT CHandler::Open2(IInStream *stream) inStreamLimSpec->SetStream(stream); inStreamLimSpec->Init(packSize); - CSequentialOutStreamImp2 *outStreamLimSpec = new CSequentialOutStreamImp2; + CBufPtrSeqOutStream *outStreamLimSpec = new CBufPtrSeqOutStream; CMyComPtr outStreamLim(outStreamLimSpec); outStreamLimSpec->Init((Byte *)ss, (size_t)unpackSize); diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp index ae75a1a2..4c5fd38d 100755 --- a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp @@ -53,18 +53,17 @@ HRESULT CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIAN EncoderSpec = new NCompress::NLzma::CEncoder; Encoder = EncoderSpec; } - CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; + CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream; CMyComPtr outStream(outStreamSpec); - outStreamSpec->Init(); + outStreamSpec->Init(Header + 4, kLzmaPropsSize); RINOK(EncoderSpec->SetCoderProperties(propIDs, props, numProps)); RINOK(EncoderSpec->WriteCoderProperties(outStream)); - if (outStreamSpec->GetSize() != kLzmaPropsSize) + if (outStreamSpec->GetPos() != kLzmaPropsSize) return E_FAIL; Header[0] = MY_VER_MAJOR; Header[1] = MY_VER_MINOR; Header[2] = kLzmaPropsSize; Header[3] = 0; - memcpy(Header + 4, outStreamSpec->GetBuffer(), kLzmaPropsSize); return S_OK; } diff --git a/CPP/7zip/Bundles/Fm/makefile b/CPP/7zip/Bundles/Fm/makefile index e9e30d6f..02ee7af1 100755 --- a/CPP/7zip/Bundles/Fm/makefile +++ b/CPP/7zip/Bundles/Fm/makefile @@ -160,6 +160,7 @@ AR_OBJS = \ $O\ArjHandler.obj \ $O\Bz2Handler.obj \ $O\CpioHandler.obj \ + $O\CramfsHandler.obj \ $O\DebHandler.obj \ $O\DeflateProps.obj \ $O\DmgHandler.obj \ @@ -178,6 +179,7 @@ AR_OBJS = \ $O\PpmdHandler.obj \ $O\RpmHandler.obj \ $O\SplitHandler.obj \ + $O\SquashfsHandler.obj \ $O\SwfHandler.obj \ $O\VhdHandler.obj \ $O\XarHandler.obj \ diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsp b/CPP/7zip/Bundles/Format7zF/Format7z.dsp index 52edc93f..b13ea42a 100755 --- a/CPP/7zip/Bundles/Format7zF/Format7z.dsp +++ b/CPP/7zip/Bundles/Format7zF/Format7z.dsp @@ -43,7 +43,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 1 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /YX /FD /c -# ADD CPP /nologo /Gr /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "NO_REGISTRY" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /FAcs /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gr /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "NO_REGISTRY" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /FAs /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" @@ -164,6 +164,10 @@ SOURCE=..\..\Archive\Icons\split.ico # End Source File # Begin Source File +SOURCE=..\..\Archive\Icons\squashfs.ico +# End Source File +# Begin Source File + SOURCE=..\..\Archive\Icons\tar.ico # End Source File # Begin Source File @@ -2330,6 +2334,10 @@ SOURCE=..\..\Archive\CpioHandler.cpp # End Source File # Begin Source File +SOURCE=..\..\Archive\CramfsHandler.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Archive\DebHandler.cpp # End Source File # Begin Source File @@ -2420,6 +2428,10 @@ SOURCE=..\..\Archive\SplitHandler.cpp # End Source File # Begin Source File +SOURCE=..\..\Archive\SquashfsHandler.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Archive\SwfHandler.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/Bundles/Format7zF/makefile b/CPP/7zip/Bundles/Format7zF/makefile index 8199dd79..11c74872 100755 --- a/CPP/7zip/Bundles/Format7zF/makefile +++ b/CPP/7zip/Bundles/Format7zF/makefile @@ -58,6 +58,7 @@ AR_OBJS = \ $O\ArjHandler.obj \ $O\Bz2Handler.obj \ $O\CpioHandler.obj \ + $O\CramfsHandler.obj \ $O\DebHandler.obj \ $O\DeflateProps.obj \ $O\DmgHandler.obj \ @@ -77,6 +78,7 @@ AR_OBJS = \ $O\RpmHandler.obj \ $O\SplitHandler.obj \ $O\SwfHandler.obj \ + $O\SquashfsHandler.obj \ $O\VhdHandler.obj \ $O\XarHandler.obj \ $O\XzHandler.obj \ diff --git a/CPP/7zip/Bundles/Format7zF/resource.rc b/CPP/7zip/Bundles/Format7zF/resource.rc index c6edfecc..df492020 100755 --- a/CPP/7zip/Bundles/Format7zF/resource.rc +++ b/CPP/7zip/Bundles/Format7zF/resource.rc @@ -27,10 +27,11 @@ MY_VERSION_INFO_DLL("7z Standalone Plugin", "7za") 21 ICON "../../Archive/Icons/fat.ico" 22 ICON "../../Archive/Icons/ntfs.ico" 23 ICON "../../Archive/Icons/xz.ico" +24 ICON "../../Archive/Icons/squashfs.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 001:9 rpm:10 deb:11 cpio:12 tar:13 gz:14 gzip:14 tgz:14 tpz:14 wim:15 swm:15 lzma:16 dmg:17 hfs:18 xar:19 vhd:20 fat:21 ntfs:22 xz:23 txz:23" + 100 "7z:0 zip:1 bz2:2 bzip2:2 tbz2:2 tbz:2 rar:3 arj:4 z:5 taz:5 lzh:6 lha:6 cab:7 iso:8 001:9 rpm:10 deb:11 cpio:12 tar:13 gz:14 gzip:14 tgz:14 tpz:14 wim:15 swm:15 lzma:16 dmg:17 hfs:18 xar:19 vhd:20 fat:21 ntfs:22 xz:23 txz:23 squashfs:24" END diff --git a/CPP/7zip/Common/LimitedStreams.h b/CPP/7zip/Common/LimitedStreams.h index f6900d51..2cbe18e4 100755 --- a/CPP/7zip/Common/LimitedStreams.h +++ b/CPP/7zip/Common/LimitedStreams.h @@ -17,6 +17,7 @@ class CLimitedSequentialInStream: bool _wasFinished; public: void SetStream(ISequentialInStream *stream) { _stream = stream; } + void ReleaseStream() { _stream.Release(); } void Init(UInt64 streamSize) { _size = streamSize; diff --git a/CPP/7zip/Common/StreamObjects.cpp b/CPP/7zip/Common/StreamObjects.cpp index 2237b930..3c86c3ae 100755 --- a/CPP/7zip/Common/StreamObjects.cpp +++ b/CPP/7zip/Common/StreamObjects.cpp @@ -2,20 +2,24 @@ #include "StdAfx.h" +#include "../../../C/Alloc.h" + #include "StreamObjects.h" STDMETHODIMP CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { - if (processedSize != NULL) + if (processedSize) *processedSize = 0; + if (size == 0) + return S_OK; if (_pos > _size) return E_FAIL; size_t rem = _size - (size_t)_pos; - if (size < rem) + if (rem > size) rem = (size_t)size; memcpy(data, _data + (size_t)_pos, rem); _pos += rem; - if (processedSize != NULL) + if (processedSize) *processedSize = (UInt32)rem; return S_OK; } @@ -34,51 +38,184 @@ STDMETHODIMP CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosi return S_OK; } +void CByteDynBuffer::Free() +{ + free(_buf); + _buf = 0; + _capacity = 0; +} + +bool CByteDynBuffer::EnsureCapacity(size_t cap) +{ + if (cap <= _capacity) + return true; + size_t delta; + if (_capacity > 64) + delta = _capacity / 4; + else if (_capacity > 8) + delta = 16; + else + delta = 4; + cap = MyMax(_capacity + delta, cap); + Byte *buf = (Byte *)realloc(_buf, cap); + if (!buf) + return false; + _buf = buf; + _capacity = cap; + return true; +} + +Byte *CDynBufSeqOutStream::GetBufPtrForWriting(size_t addSize) +{ + addSize += _size; + if (addSize < _size) + return NULL; + if (!_buffer.EnsureCapacity(addSize)) + return NULL; + return (Byte *)_buffer + _size; +} -void CWriteBuffer::Write(const void *data, size_t size) +void CDynBufSeqOutStream::CopyToBuffer(CByteBuffer &dest) const { - size_t newCapacity = _size + size; - _buffer.EnsureCapacity(newCapacity); - memcpy(_buffer + _size, data, size); - _size += size; + dest.SetCapacity(_size); + memcpy(dest, _buffer, _size); } -STDMETHODIMP CSequentialOutStreamImp::Write(const void *data, UInt32 size, UInt32 *processedSize) +STDMETHODIMP CDynBufSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { - _writeBuffer.Write(data, (size_t)size); - if(processedSize != NULL) + if (processedSize) + *processedSize = 0; + if (size == 0) + return S_OK; + Byte *buf = GetBufPtrForWriting(size); + if (!buf) + return E_OUTOFMEMORY; + memcpy(buf, data, size); + UpdateSize(size); + if (processedSize) *processedSize = size; return S_OK; } -STDMETHODIMP CSequentialOutStreamImp2::Write(const void *data, UInt32 size, UInt32 *processedSize) +STDMETHODIMP CBufPtrSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { size_t rem = _size - _pos; - if (size < rem) + if (rem > size) rem = (size_t)size; memcpy(_buffer + _pos, data, rem); _pos += rem; - if (processedSize != NULL) + if (processedSize) *processedSize = (UInt32)rem; - return (rem == size ? S_OK : E_FAIL); + return (rem != 0 || size == 0) ? S_OK : E_FAIL; } -STDMETHODIMP CSequentialInStreamSizeCount::Read(void *data, UInt32 size, UInt32 *processedSize) +STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; - HRESULT result = _stream->Read(data, size, &realProcessedSize); + HRESULT result = _stream->Write(data, size, &realProcessedSize); _size += realProcessedSize; - if (processedSize != 0) + if (processedSize) *processedSize = realProcessedSize; return result; } -STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize) +static const UInt64 kEmptyTag = (UInt64)(Int64)-1; + +void CCachedInStream::Free() { - UInt32 realProcessedSize; - HRESULT result = _stream->Write(data, size, &realProcessedSize); - _size += realProcessedSize; - if (processedSize != 0) - *processedSize = realProcessedSize; - return result; + MyFree(_tags); + _tags = 0; + MidFree(_data); + _data = 0; +} + +bool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog) +{ + unsigned sizeLog = blockSizeLog + numBlocksLog; + if (sizeLog >= sizeof(size_t) * 8) + return false; + size_t dataSize = (size_t)1 << sizeLog; + if (_data == 0 || dataSize != _dataSize) + { + MidFree(_data); + _data = (Byte *)MidAlloc(dataSize); + if (_data == 0) + return false; + _dataSize = dataSize; + } + if (_tags == 0 || numBlocksLog != _numBlocksLog) + { + MyFree(_tags); + _tags = (UInt64 *)MyAlloc(sizeof(UInt64) << numBlocksLog); + if (_tags == 0) + return false; + _numBlocksLog = numBlocksLog; + } + _blockSizeLog = blockSizeLog; + return true; +} + +void CCachedInStream::Init(UInt64 size) +{ + _size = size; + _pos = 0; + size_t numBlocks = (size_t)1 << _numBlocksLog; + for (size_t i = 0; i < numBlocks; i++) + _tags[i] = kEmptyTag; +} + +STDMETHODIMP CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (size == 0) + return S_OK; + if (_pos > _size) + return E_FAIL; + + { + UInt64 rem = _size - _pos; + if (size > rem) + size = (UInt32)rem; + } + + while (size != 0) + { + UInt64 cacheTag = _pos >> _blockSizeLog; + size_t cacheIndex = (size_t)cacheTag & (((size_t)1 << _numBlocksLog) - 1); + Byte *p = _data + (cacheIndex << _blockSizeLog); + if (_tags[cacheIndex] != cacheTag) + { + UInt64 remInBlock = _size - (cacheTag << _blockSizeLog); + size_t blockSize = (size_t)1 << _blockSizeLog; + if (blockSize > remInBlock) + blockSize = (size_t)remInBlock; + RINOK(ReadBlock(cacheTag, p, blockSize)); + _tags[cacheIndex] = cacheTag; + } + size_t offset = (size_t)_pos & (((size_t)1 << _blockSizeLog) - 1); + UInt32 cur = (UInt32)MyMin(((size_t)1 << _blockSizeLog) - offset, (size_t)size); + memcpy(data, p + offset, cur); + if (processedSize) + *processedSize += cur; + data = (void *)((const Byte *)data + cur); + _pos += cur; + size -= cur; + } + + return S_OK; +} + +STDMETHODIMP CCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch(seekOrigin) + { + case STREAM_SEEK_SET: _pos = offset; break; + case STREAM_SEEK_CUR: _pos = _pos + offset; break; + case STREAM_SEEK_END: _pos = _size + offset; break; + default: return STG_E_INVALIDFUNCTION; + } + if (newPosition != 0) + *newPosition = _pos; + return S_OK; } diff --git a/CPP/7zip/Common/StreamObjects.h b/CPP/7zip/Common/StreamObjects.h index e94513ee..8cd95c70 100755 --- a/CPP/7zip/Common/StreamObjects.h +++ b/CPP/7zip/Common/StreamObjects.h @@ -3,7 +3,7 @@ #ifndef __STREAM_OBJECTS_H #define __STREAM_OBJECTS_H -#include "../../Common/DynamicBuffer.h" +#include "../../Common/Buffer.h" #include "../../Common/MyCom.h" #include "../IStream.h" @@ -34,39 +34,45 @@ public: void Init(CReferenceBuf *ref) { Init(ref->Buf, ref->Buf.GetCapacity(), ref); } MY_UNKNOWN_IMP1(IInStream) - STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; -class CWriteBuffer +class CByteDynBuffer { - CByteDynamicBuffer _buffer; - size_t _size; + size_t _capacity; + Byte *_buf; public: - CWriteBuffer(): _size(0) {} - void Init() { _size = 0; } - void Write(const void *data, size_t size); - size_t GetSize() const { return _size; } - const CByteDynamicBuffer& GetBuffer() const { return _buffer; } + CByteDynBuffer(): _capacity(0), _buf(0) {}; + // there is no copy constructor. So don't copy this object. + ~CByteDynBuffer() { Free(); } + void Free(); + size_t GetCapacity() const { return _capacity; } + operator Byte*() const { return _buf; }; + operator const Byte*() const { return _buf; }; + bool EnsureCapacity(size_t capacity); }; -class CSequentialOutStreamImp: +class CDynBufSeqOutStream: public ISequentialOutStream, public CMyUnknownImp { - CWriteBuffer _writeBuffer; + CByteDynBuffer _buffer; + size_t _size; public: - void Init() { _writeBuffer.Init(); } - size_t GetSize() const { return _writeBuffer.GetSize(); } - const CByteDynamicBuffer& GetBuffer() const { return _writeBuffer.GetBuffer(); } + CDynBufSeqOutStream(): _size(0) {} + void Init() { _size = 0; } + size_t GetSize() const { return _size; } + const Byte *GetBuffer() const { return _buffer; } + void CopyToBuffer(CByteBuffer &dest) const; + Byte *GetBufPtrForWriting(size_t addSize); + void UpdateSize(size_t addSize) { _size += addSize; } MY_UNKNOWN_IMP - STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; -class CSequentialOutStreamImp2: +class CBufPtrSeqOutStream: public ISequentialOutStream, public CMyUnknownImp { @@ -74,54 +80,56 @@ class CSequentialOutStreamImp2: size_t _size; size_t _pos; public: - void Init(Byte *buffer, size_t size) { _buffer = buffer; _pos = 0; _size = size; } - size_t GetPos() const { return _pos; } MY_UNKNOWN_IMP - STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; -class CSequentialInStreamSizeCount: - public ISequentialInStream, +class CSequentialOutStreamSizeCount: + public ISequentialOutStream, public CMyUnknownImp { - CMyComPtr _stream; + CMyComPtr _stream; UInt64 _size; public: - void Init(ISequentialInStream *stream) - { - _stream = stream; - _size = 0; - } + void SetStream(ISequentialOutStream *stream) { _stream = stream; } + void Init() { _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP - - STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; -class CSequentialOutStreamSizeCount: - public ISequentialOutStream, +class CCachedInStream: + public IInStream, public CMyUnknownImp { - CMyComPtr _stream; + UInt64 *_tags; + Byte *_data; + size_t _dataSize; + unsigned _blockSizeLog; + unsigned _numBlocksLog; UInt64 _size; + UInt64 _pos; +protected: + virtual HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) = 0; public: - void SetStream(ISequentialOutStream *stream) { _stream = stream; } - void Init() { _size = 0; } - UInt64 GetSize() const { return _size; } - - MY_UNKNOWN_IMP + CCachedInStream(): _tags(0), _data(0) {} + virtual ~CCachedInStream() { Free(); } // the destructor must be virtual (release calls it) !!! + void Free(); + bool Alloc(unsigned blockSizeLog, unsigned numBlocksLog); + void Init(UInt64 size); - STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; #endif diff --git a/CPP/7zip/Guid.txt b/CPP/7zip/Guid.txt index 7876a1da..59a743b9 100755 --- a/CPP/7zip/Guid.txt +++ b/CPP/7zip/Guid.txt @@ -128,6 +128,8 @@ Handler GUIDs: 0C xz 0D ppmd + D2 SquashFS + D3 CramFS D4 APM D5 Mslz D6 Flv diff --git a/CPP/7zip/MyVersion.h b/CPP/7zip/MyVersion.h index 41e5ddbd..2ca5dbc2 100755 --- a/CPP/7zip/MyVersion.h +++ b/CPP/7zip/MyVersion.h @@ -1,8 +1,8 @@ #define MY_VER_MAJOR 9 -#define MY_VER_MINOR 17 +#define MY_VER_MINOR 18 #define MY_VER_BUILD 0 -#define MY_VERSION "9.17 beta" -#define MY_7ZIP_VERSION "7-Zip 9.17 beta" -#define MY_DATE "2010-10-04" +#define MY_VERSION "9.18 beta" +#define MY_7ZIP_VERSION "7-Zip 9.18 beta" +#define MY_DATE "2010-11-02" #define MY_COPYRIGHT "Copyright (c) 1999-2010 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 d6f3a7c1..8f888526 100755 --- a/CPP/7zip/PropID.h +++ b/CPP/7zip/PropID.h @@ -60,6 +60,7 @@ enum kpidSectorSize, kpidPosixAttrib, kpidLink, + kpidError, kpidTotalSize = 0x1100, kpidFreeSpace, diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp index 4db95c87..4a099308 100755 --- a/CPP/7zip/UI/Agent/Agent.cpp +++ b/CPP/7zip/UI/Agent/Agent.cpp @@ -609,7 +609,7 @@ STDMETHODIMP CAgent::GetArcProp(UInt32 level, PROPID propID, PROPVARIANT *value) CArc &arc = _archiveLink.Arcs[level]; switch(propID) { - case kpidType: prop = _codecs->Formats[arc.FormatIndex].Name; break; + case kpidType: prop = GetTypeOfArc(arc); break; case kpidPath: prop = arc.Path; break; default: return arc.Archive->GetArchiveProperty(propID, value); } diff --git a/CPP/7zip/UI/Agent/Agent.h b/CPP/7zip/UI/Agent/Agent.h index c5efb411..454964bc 100755 --- a/CPP/7zip/UI/Agent/Agent.h +++ b/CPP/7zip/UI/Agent/Agent.h @@ -206,6 +206,27 @@ public: const CArc &GetArc() { return _archiveLink.Arcs.Back(); } IInArchive *GetArchive() { if ( _archiveLink.Arcs.IsEmpty()) return 0; return GetArc().Archive; } bool CanUpdate() const { return _archiveLink.Arcs.Size() <= 1; } + + UString GetTypeOfArc(const CArc &arc) const { return _codecs->Formats[arc.FormatIndex].Name; } + UString GetErrorMessage() const + { + UString s; + for (int i = _archiveLink.Arcs.Size() - 1; i >= 0; i--) + { + const CArc &arc = _archiveLink.Arcs[i]; + if (arc.ErrorMessage.IsEmpty()) + continue; + if (!s.IsEmpty()) + s += L"--------------------\n"; + s += arc.ErrorMessage; + s += L"\n\n["; + s += GetTypeOfArc(arc); + s += L"] "; + s += arc.Path; + s += L"\n"; + } + return s; + } }; #ifdef NEW_FOLDER_INTERFACE diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp index f4c126a4..ca2c8c73 100755 --- a/CPP/7zip/UI/Common/Extract.cpp +++ b/CPP/7zip/UI/Common/Extract.cpp @@ -228,6 +228,15 @@ HRESULT DecompressArchives( } #endif + for (int v = 0; v < archiveLink.Arcs.Size(); v++) + { + const UString &s = archiveLink.Arcs[v].ErrorMessage; + if (!s.IsEmpty()) + { + RINOK(extractCallback->MessageError(s)); + } + } + CArc &arc = archiveLink.Arcs.Back(); arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice); arc.MTime = fi.MTime; diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/CPP/7zip/UI/Common/ExtractingFilePath.cpp index 67a58372..8f31708b 100755 --- a/CPP/7zip/UI/Common/ExtractingFilePath.cpp +++ b/CPP/7zip/UI/Common/ExtractingFilePath.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../../../C/Types.h" + #include "Common/Wildcard.h" #include "ExtractingFilePath.h" diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp index d61c7f17..56a63046 100755 --- a/CPP/7zip/UI/Common/OpenArchive.cpp +++ b/CPP/7zip/UI/Common/OpenArchive.cpp @@ -111,6 +111,7 @@ HRESULT CArc::OpenStream( IArchiveOpenCallback *callback) { Archive.Release(); + ErrorMessage.Empty(); const UString fileName = ExtractFileNameFromPath(Path); UString extension; { @@ -298,6 +299,13 @@ HRESULT CArc::OpenStream( if (result == S_FALSE) continue; RINOK(result); + + { + NCOM::CPropVariant prop; + archive->GetArchiveProperty(kpidError, &prop); + if (prop.vt != VT_EMPTY) + ErrorMessage = (prop.vt == VT_BSTR) ? prop.bstrVal : L"Unknown error"; + } Archive = archive; const CArcInfoEx &format = codecs->Formats[FormatIndex]; diff --git a/CPP/7zip/UI/Common/OpenArchive.h b/CPP/7zip/UI/Common/OpenArchive.h index 92103623..4a003ee6 100755 --- a/CPP/7zip/UI/Common/OpenArchive.h +++ b/CPP/7zip/UI/Common/OpenArchive.h @@ -24,6 +24,7 @@ struct CArc int SubfileIndex; FILETIME MTime; bool MTimeDefined; + UString ErrorMessage; CArc(): MTimeDefined(false) {} diff --git a/CPP/7zip/UI/Common/PropIDUtils.cpp b/CPP/7zip/UI/Common/PropIDUtils.cpp index daa57ef6..dacaca5f 100755 --- a/CPP/7zip/UI/Common/PropIDUtils.cpp +++ b/CPP/7zip/UI/Common/PropIDUtils.cpp @@ -45,6 +45,7 @@ static const char g_WinAttrib[17] = "RHS8DAdNTsrCOnE_"; 16 VIRTUAL */ +static const char kPosixTypes[16] = { '0', 'p', 'c', '3', 'd', '5', 'b', '7', '-', '9', 'l', 'B', 's', 'D', 'E', 'F' }; #define MY_ATTR_CHAR(a, n, c) ((a )& (1 << (n))) ? c : L'-'; UString ConvertPropertyToString(const PROPVARIANT &prop, PROPID propID, bool full) @@ -92,17 +93,21 @@ UString ConvertPropertyToString(const PROPVARIANT &prop, PROPID propID, bool ful UString res; UInt32 a = prop.ulVal; wchar_t temp[16]; - temp[0] = MY_ATTR_CHAR(a, 14, L'd'); + + temp[0] = kPosixTypes[(a >> 12) & 0xF]; 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'); } + if ((a & 0x800) != 0) temp[3] = ((a & (1 << 6)) ? 's' : 'S'); + if ((a & 0x400) != 0) temp[6] = ((a & (1 << 3)) ? 's' : 'S'); + if ((a & 0x200) != 0) temp[9] = ((a & (1 << 0)) ? 't' : 'T'); temp[10] = 0; res = temp; - a &= ~0x1FF; - a &= ~0xC000; + + a &= ~(UInt32)0xFFFF; if (a != 0) { ConvertUInt32ToHex(a, temp); diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp index b06641f2..f747cfda 100755 --- a/CPP/7zip/UI/Console/List.cpp +++ b/CPP/7zip/UI/Console/List.cpp @@ -29,7 +29,7 @@ struct CPropIdToName const wchar_t *Name; }; -static CPropIdToName kPropIdToName[] = +static const CPropIdToName kPropIdToName[] = { { kpidPath, L"Path" }, { kpidName, L"Name" }, @@ -82,6 +82,7 @@ static CPropIdToName kPropIdToName[] = { kpidSectorSize, L"Sector Size" }, { kpidPosixAttrib, L"Mode" }, { kpidLink, L"Link" }, + { kpidError, L"Error" }, { kpidTotalSize, L"Total Size" }, { kpidFreeSpace, L"Free Space" }, @@ -505,6 +506,8 @@ HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, g_StdOut << "--\n"; PrintPropPair(L"Path", arc.Path); PrintPropPair(L"Type", codecs->Formats[arc.FormatIndex].Name); + if (!arc.ErrorMessage.IsEmpty()) + PrintPropPair(L"Error", arc.ErrorMessage); UInt32 numProps; IInArchive *archive = arc.Archive; if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK) diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp index 7cb2a396..9bd451f8 100755 --- a/CPP/7zip/UI/Console/Main.cpp +++ b/CPP/7zip/UI/Console/Main.cpp @@ -26,7 +26,6 @@ #ifdef EXTERNAL_CODECS #include "../Common/LoadCodecs.h" #endif -#include "../Common/PropIDUtils.h" #include "BenchCon.h" #include "ExtractCallbackConsole.h" @@ -457,8 +456,8 @@ int Main2( << "Compressed: " << stat.PackSize << endl; if (options.CalcCrc) { - wchar_t s[16]; - ConvertUInt32ToHex(stat.CrcSum, s); + char s[16]; + ConvertUInt32ToHexWithZeros(stat.CrcSum, s); stdStream << "CRC: " << s << endl; } } diff --git a/CPP/7zip/UI/Far/Far.dsp b/CPP/7zip/UI/Far/Far.dsp index 4609c82c..394977bb 100755 --- a/CPP/7zip/UI/Far/Far.dsp +++ b/CPP/7zip/UI/Far/Far.dsp @@ -53,7 +53,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Program Files\Far2\Plugins\7-Zip\7-ZipFar.dll" /opt:NOWIN98 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Program Files\Far\Plugins\7-Zip\7-ZipFar.dll" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Far - Win32 Debug" @@ -80,7 +80,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\Far2\Plugins\7-Zip\7-ZipFar.dll" /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\Far\Plugins\7-Zip\7-ZipFar.dll" /pdbtype:sept !ENDIF diff --git a/CPP/7zip/UI/Far/FarPlugin.h b/CPP/7zip/UI/Far/FarPlugin.h index 1408ef21..d9ea6dca 100755 --- a/CPP/7zip/UI/Far/FarPlugin.h +++ b/CPP/7zip/UI/Far/FarPlugin.h @@ -61,7 +61,7 @@ struct PluginPanelItem char **CustomColumnData; int CustomColumnNumber; DWORD_PTR UserData; - DWORD CRC32; + DWORD CRC32; DWORD_PTR Reserved[2]; }; @@ -484,34 +484,34 @@ enum OPERATION_MODES { /* EXTERN_C_BEGIN - void WINAPI _export ClosePluginW(HANDLE hPlugin); - int WINAPI _export CompareW(HANDLE hPlugin,const struct PluginPanelItem *Item1,const struct PluginPanelItem *Item2,unsigned int Mode); - int WINAPI _export ConfigureW(int ItemNumber); - int WINAPI _export DeleteFilesW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode); - void WINAPI _export ExitFARW(void); - void WINAPI _export FreeFindDataW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber); - void WINAPI _export FreeVirtualFindDataW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber); - int WINAPI _export GetFilesW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int Move,const wchar_t **DestPath,int OpMode); - int WINAPI _export GetFindDataW(HANDLE hPlugin,struct PluginPanelItem **pPanelItem,int *pItemsNumber,int OpMode); - int WINAPI _export GetMinFarVersionW(void); - void WINAPI _export GetOpenPluginInfoW(HANDLE hPlugin,struct OpenPluginInfo *Info); - void WINAPI _export GetPluginInfoW(struct PluginInfo *Info); - int WINAPI _export GetVirtualFindDataW(HANDLE hPlugin,struct PluginPanelItem **pPanelItem,int *pItemsNumber,const wchar_t *Path); - int WINAPI _export MakeDirectoryW(HANDLE hPlugin,const wchar_t **Name,int OpMode); - HANDLE WINAPI _export OpenFilePluginW(const wchar_t *Name,const unsigned char *Data,int DataSize,int OpMode); - HANDLE WINAPI _export OpenPluginW(int OpenFrom,INT_PTR Item); - int WINAPI _export ProcessDialogEventW(int Event,void *Param); - int WINAPI _export ProcessEditorEventW(int Event,void *Param); - int WINAPI _export ProcessEditorInputW(const INPUT_RECORD *Rec); - int WINAPI _export ProcessEventW(HANDLE hPlugin,int Event,void *Param); - int WINAPI _export ProcessHostFileW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode); - int WINAPI _export ProcessKeyW(HANDLE hPlugin,int Key,unsigned int ControlState); - int WINAPI _export ProcessSynchroEventW(int Event,void *Param); - int WINAPI _export ProcessViewerEventW(int Event,void *Param); - int WINAPI _export PutFilesW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int Move,const wchar_t *SrcPath,int OpMode); - int WINAPI _export SetDirectoryW(HANDLE hPlugin,const wchar_t *Dir,int OpMode); - int WINAPI _export SetFindListW(HANDLE hPlugin,const struct PluginPanelItem *PanelItem,int ItemsNumber); - void WINAPI _export SetStartupInfoW(const struct PluginStartupInfo *Info); + void WINAPI _export ClosePluginW(HANDLE hPlugin); + int WINAPI _export CompareW(HANDLE hPlugin,const struct PluginPanelItem *Item1,const struct PluginPanelItem *Item2,unsigned int Mode); + int WINAPI _export ConfigureW(int ItemNumber); + int WINAPI _export DeleteFilesW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode); + void WINAPI _export ExitFARW(void); + void WINAPI _export FreeFindDataW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber); + void WINAPI _export FreeVirtualFindDataW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber); + int WINAPI _export GetFilesW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int Move,const wchar_t **DestPath,int OpMode); + int WINAPI _export GetFindDataW(HANDLE hPlugin,struct PluginPanelItem **pPanelItem,int *pItemsNumber,int OpMode); + int WINAPI _export GetMinFarVersionW(void); + void WINAPI _export GetOpenPluginInfoW(HANDLE hPlugin,struct OpenPluginInfo *Info); + void WINAPI _export GetPluginInfoW(struct PluginInfo *Info); + int WINAPI _export GetVirtualFindDataW(HANDLE hPlugin,struct PluginPanelItem **pPanelItem,int *pItemsNumber,const wchar_t *Path); + int WINAPI _export MakeDirectoryW(HANDLE hPlugin,const wchar_t **Name,int OpMode); + HANDLE WINAPI _export OpenFilePluginW(const wchar_t *Name,const unsigned char *Data,int DataSize,int OpMode); + HANDLE WINAPI _export OpenPluginW(int OpenFrom,INT_PTR Item); + int WINAPI _export ProcessDialogEventW(int Event,void *Param); + int WINAPI _export ProcessEditorEventW(int Event,void *Param); + int WINAPI _export ProcessEditorInputW(const INPUT_RECORD *Rec); + int WINAPI _export ProcessEventW(HANDLE hPlugin,int Event,void *Param); + int WINAPI _export ProcessHostFileW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode); + int WINAPI _export ProcessKeyW(HANDLE hPlugin,int Key,unsigned int ControlState); + int WINAPI _export ProcessSynchroEventW(int Event,void *Param); + int WINAPI _export ProcessViewerEventW(int Event,void *Param); + int WINAPI _export PutFilesW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int Move,const wchar_t *SrcPath,int OpMode); + int WINAPI _export SetDirectoryW(HANDLE hPlugin,const wchar_t *Dir,int OpMode); + int WINAPI _export SetFindListW(HANDLE hPlugin,const struct PluginPanelItem *PanelItem,int ItemsNumber); + void WINAPI _export SetStartupInfoW(const struct PluginStartupInfo *Info); EXTERN_C_END */ diff --git a/CPP/7zip/UI/Far/Main.cpp b/CPP/7zip/UI/Far/Main.cpp index 7cd7d5ee..5e017b80 100755 --- a/CPP/7zip/UI/Far/Main.cpp +++ b/CPP/7zip/UI/Far/Main.cpp @@ -366,7 +366,8 @@ static HANDLE MyOpenFilePluginW(const wchar_t *name) // ::OutputDebugStringA("before OpenArchive\n"); - archiveHandler = new CAgent; + CAgent *agent = new CAgent; + archiveHandler = agent; CMyComBSTR archiveType; HRESULT result = archiveHandler->Open(NULL, GetUnicodeString(fullName, CP_OEMCP), UString(), &archiveType, openArchiveCallback); @@ -381,6 +382,10 @@ static HANDLE MyOpenFilePluginW(const wchar_t *name) return INVALID_HANDLE_VALUE; } + UString errorMessage = agent->GetErrorMessage(); + if (!errorMessage.IsEmpty()) + PrintErrorMessage("7-Zip", UnicodeStringToMultiByte(errorMessage, CP_OEMCP)); + // ::OutputDebugStringA("after OpenArchive\n"); CPlugin *plugin = new CPlugin( diff --git a/CPP/7zip/UI/Far/Plugin.cpp b/CPP/7zip/UI/Far/Plugin.cpp index 97627517..a19b037c 100755 --- a/CPP/7zip/UI/Far/Plugin.cpp +++ b/CPP/7zip/UI/Far/Plugin.cpp @@ -326,7 +326,8 @@ static CPROPIDToName kPROPIDToName[] = { kpidSectorSize, NMessageID::kSectorSize }, { kpidPosixAttrib, NMessageID::kPosixAttrib }, { kpidLink, NMessageID::kLink }, - + { kpidError, NMessageID::kError }, + { kpidTotalSize, NMessageID::kTotalSize }, { kpidFreeSpace, NMessageID::kFreeSpace }, { kpidClusterSize, NMessageID::kClusterSize }, @@ -628,17 +629,20 @@ void CPlugin::GetOpenPluginInfo(struct OpenPluginInfo *info) if (getProps->GetArcNumProps(level, &numProps) == S_OK) { InsertSeparator(m_InfoLines, numItems); - for (Int32 i = -2; i < (Int32)numProps && numItems < kNumInfoLinesMax; i++) + for (Int32 i = -3; i < (Int32)numProps && numItems < kNumInfoLinesMax; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; - if (i == -2) - propID = kpidPath; - else if (i == -1) - propID = kpidType; - else if (getProps->GetArcPropInfo(level, i, &name, &propID, &vt) != S_OK) - continue; + switch (i) + { + case -3: propID = kpidPath; break; + case -2: propID = kpidType; break; + case -1: propID = kpidError; break; + default: + if (getProps->GetArcPropInfo(level, i, &name, &propID, &vt) != S_OK) + continue; + } NCOM::CPropVariant prop; if (getProps->GetArcProp(level, propID, &prop) != S_OK) continue; diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp index 29c99bfd..6b8fdba2 100755 --- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp +++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp @@ -9,6 +9,7 @@ #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/Process.h" +#include "Windows/PropVariant.h" #include "Windows/Thread.h" #include "../Common/ExtractingFilePath.h" @@ -113,6 +114,46 @@ HRESULT CPanel::OpenItemAsArchive(IInStream *inStream, _flatMode = _flatModeForArc; + CMyComPtr getFolderArcProps; + _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps); + if (getFolderArcProps) + { + CMyComPtr arcProps; + getFolderArcProps->GetFolderArcProps(&arcProps); + if (arcProps) + { + UString s; + UInt32 numLevels; + if (arcProps->GetArcNumLevels(&numLevels) != S_OK) + numLevels = 0; + for (UInt32 level2 = 0; level2 < numLevels; level2++) + { + UInt32 level = numLevels - 1 - level2; + PROPID propIDs[] = { kpidError, kpidPath, kpidType } ; + UString values[3]; + for (Int32 i = 0; i < 3; i++) + { + CMyComBSTR name; + NCOM::CPropVariant prop; + if (arcProps->GetArcProp(level, propIDs[i], &prop) != S_OK) + continue; + if (prop.vt != VT_EMPTY) + values[i] = (prop.vt == VT_BSTR) ? prop.bstrVal : L"?"; + } + if (!values[0].IsEmpty()) + { + if (!s.IsEmpty()) + s += L"--------------------\n"; + s += values[0]; s += L"\n\n["; + s += values[2]; s += L"] "; + s += values[1]; s += L"\n"; + } + } + if (!s.IsEmpty()) + MessageBox(s); + } + } + return S_OK; } diff --git a/CPP/7zip/UI/FileManager/PanelMenu.cpp b/CPP/7zip/UI/FileManager/PanelMenu.cpp index c60751b5..549b28da 100755 --- a/CPP/7zip/UI/FileManager/PanelMenu.cpp +++ b/CPP/7zip/UI/FileManager/PanelMenu.cpp @@ -188,17 +188,20 @@ void CPanel::Properties() if (getProps->GetArcNumProps(level, &numProps) == S_OK) { message += kSeparator; - for (Int32 i = -2; i < (Int32)numProps; i++) + for (Int32 i = -3; i < (Int32)numProps; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; - if (i == -2) - propID = kpidPath; - else if (i == -1) - propID = kpidType; - else if (getProps->GetArcPropInfo(level, i, &name, &propID, &vt) != S_OK) - continue; + switch (i) + { + case -3: propID = kpidPath; break; + case -2: propID = kpidType; break; + case -1: propID = kpidError; break; + default: + if (getProps->GetArcPropInfo(level, i, &name, &propID, &vt) != S_OK) + continue; + } NCOM::CPropVariant prop; if (getProps->GetArcProp(level, propID, &prop) != S_OK) continue; diff --git a/CPP/7zip/UI/FileManager/PanelSort.cpp b/CPP/7zip/UI/FileManager/PanelSort.cpp index 7eabc9ef..186315b3 100755 --- a/CPP/7zip/UI/FileManager/PanelSort.cpp +++ b/CPP/7zip/UI/FileManager/PanelSort.cpp @@ -61,17 +61,19 @@ int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) // PROPID propID = panel->_properties[panel->_sortIndex].ID; PROPID propID = panel->_sortID; - NCOM::CPropVariant propVariant1, propVariant2; + NCOM::CPropVariant prop1, prop2; // Name must be first property - panel->_folder->GetProperty((UINT32)lParam1, propID, &propVariant1); - panel->_folder->GetProperty((UINT32)lParam2, propID, &propVariant2); - if (propVariant1.vt != propVariant2.vt) - return 0; // It means some BUG - if (propVariant1.vt == VT_BSTR) + panel->_folder->GetProperty((UINT32)lParam1, propID, &prop1); + panel->_folder->GetProperty((UINT32)lParam2, propID, &prop2); + if (prop1.vt != prop2.vt) { - return _wcsicmp(propVariant1.bstrVal, propVariant2.bstrVal); + return MyCompare(prop1.vt, prop2.vt); } - return propVariant1.Compare(propVariant2); + if (prop1.vt == VT_BSTR) + { + return _wcsicmp(prop1.bstrVal, prop2.bstrVal); + } + return prop1.Compare(prop2); // return 0; } diff --git a/CPP/7zip/UI/FileManager/ProgramLocation.cpp b/CPP/7zip/UI/FileManager/ProgramLocation.cpp index 04c2c98c..ce2d178e 100755 --- a/CPP/7zip/UI/FileManager/ProgramLocation.cpp +++ b/CPP/7zip/UI/FileManager/ProgramLocation.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../../../C/Types.h" + #include "ProgramLocation.h" #include "Windows/DLL.h" @@ -20,4 +22,3 @@ bool GetProgramFolderPath(UString &folder) folder = folder.Left(pos + 1); return true; } - diff --git a/CPP/7zip/UI/FileManager/PropertyName.cpp b/CPP/7zip/UI/FileManager/PropertyName.cpp index 79b09300..098bc47d 100755 --- a/CPP/7zip/UI/FileManager/PropertyName.cpp +++ b/CPP/7zip/UI/FileManager/PropertyName.cpp @@ -75,6 +75,7 @@ static CPropertyIDNamePair kPropertyIDNamePairs[] = { kpidSectorSize, IDS_PROP_SECTOR_SIZE, 0x02000234 }, { kpidPosixAttrib, IDS_PROP_POSIX_ATTRIB, 0x02000235 }, { kpidLink, IDS_PROP_LINK, 0x02000236 }, + { kpidError, IDS_PROP_ERROR, 0x02000605 }, { kpidTotalSize, IDS_PROP_TOTAL_SIZE, 0x03031100 }, { kpidFreeSpace, IDS_PROP_FREE_SPACE, 0x03031101 }, diff --git a/CPP/7zip/UI/FileManager/PropertyName.rc b/CPP/7zip/UI/FileManager/PropertyName.rc index 576b52cb..bdd6c8ed 100755 --- a/CPP/7zip/UI/FileManager/PropertyName.rc +++ b/CPP/7zip/UI/FileManager/PropertyName.rc @@ -56,4 +56,5 @@ BEGIN IDS_PROP_SECTOR_SIZE "Sector Size" IDS_PROP_POSIX_ATTRIB "Mode" IDS_PROP_LINK "Link" + IDS_PROP_ERROR "Error" END diff --git a/CPP/7zip/UI/FileManager/PropertyNameRes.h b/CPP/7zip/UI/FileManager/PropertyNameRes.h index 00458a24..9cc9f7c5 100755 --- a/CPP/7zip/UI/FileManager/PropertyNameRes.h +++ b/CPP/7zip/UI/FileManager/PropertyNameRes.h @@ -50,3 +50,4 @@ #define IDS_PROP_SECTOR_SIZE 52 #define IDS_PROP_POSIX_ATTRIB 53 #define IDS_PROP_LINK 54 +#define IDS_PROP_ERROR 55 diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp index ea9d9c2c..da2b7924 100755 --- a/CPP/7zip/UI/GUI/CompressDialog.cpp +++ b/CPP/7zip/UI/GUI/CompressDialog.cpp @@ -1038,7 +1038,13 @@ void CCompressDialog::SetDictionary() if (i == 20 && j > 0) continue; UInt32 dictionary = (1 << i) + (j << (i - 1)); - if (dictionary > (1 << 30)) + if (dictionary > + #ifdef _WIN64 + (1 << 30) + #else + (1 << 29) + #endif + ) continue; AddDictionarySize(dictionary); UInt64 decomprSize; diff --git a/CPP/Common/DynamicBuffer.h b/CPP/Common/DynamicBuffer.h index fd33cec3..bf52a742 100755 --- a/CPP/Common/DynamicBuffer.h +++ b/CPP/Common/DynamicBuffer.h @@ -1,7 +1,7 @@ // Common/DynamicBuffer.h -#ifndef __COMMON_DYNAMICBUFFER_H -#define __COMMON_DYNAMICBUFFER_H +#ifndef __COMMON_DYNAMIC_BUFFER_H +#define __COMMON_DYNAMIC_BUFFER_H #include "Buffer.h" @@ -17,7 +17,10 @@ template class CDynamicBuffer: public CBuffer else delta = 4; delta = MyMax(delta, size); - SetCapacity(this->_capacity + delta); + size_t newCap = this->_capacity + delta; + if (newCap < delta) + newCap = this->_capacity + size; + SetCapacity(newCap); } public: CDynamicBuffer(): CBuffer() {}; diff --git a/CPP/Common/IntToString.cpp b/CPP/Common/IntToString.cpp index 31070b41..013fee52 100755 --- a/CPP/Common/IntToString.cpp +++ b/CPP/Common/IntToString.cpp @@ -64,3 +64,14 @@ void ConvertInt64ToString(Int64 value, wchar_t *s) } ConvertUInt64ToString(value, s); } + +void ConvertUInt32ToHexWithZeros(UInt32 value, char *s) +{ + for (int i = 0; i < 8; i++) + { + int t = value & 0xF; + value >>= 4; + s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } + s[8] = '\0'; +} diff --git a/CPP/Common/IntToString.h b/CPP/Common/IntToString.h index bad17e4a..782f930c 100755 --- a/CPP/Common/IntToString.h +++ b/CPP/Common/IntToString.h @@ -14,4 +14,6 @@ void ConvertInt64ToString(Int64 value, wchar_t *s); void ConvertUInt32ToString(UInt32 value, char *s); void ConvertUInt32ToString(UInt32 value, wchar_t *s); +void ConvertUInt32ToHexWithZeros(UInt32 value, char *s); + #endif diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h index e8830092..eb3c52dc 100755 --- a/CPP/Common/MyString.h +++ b/CPP/Common/MyString.h @@ -7,10 +7,6 @@ #include "MyVector.h" -#ifdef _WIN32 -#include "MyWindows.h" -#endif - template inline int MyStringLen(const T *s) { diff --git a/CPP/Common/MyVector.h b/CPP/Common/MyVector.h index 28b7e3c8..781b648b 100755 --- a/CPP/Common/MyVector.h +++ b/CPP/Common/MyVector.h @@ -78,6 +78,22 @@ public: operator[](j) = temp; } + int FindInSorted(const T& item, int left, int right) const + { + while (left != right) + { + int mid = (left + right) / 2; + const T& midValue = (*this)[mid]; + if (item == midValue) + return mid; + if (item < midValue) + right = mid; + else + left = mid + 1; + } + return -1; + } + int FindInSorted(const T& item) const { int left = 0, right = Size(); diff --git a/CPP/Common/MyWindows.h b/CPP/Common/MyWindows.h index 2861ba04..8b0e5c06 100755 --- a/CPP/Common/MyWindows.h +++ b/CPP/Common/MyWindows.h @@ -7,18 +7,8 @@ #include -#define CHAR_PATH_SEPARATOR '\\' -#define WCHAR_PATH_SEPARATOR L'\\' -#define STRING_PATH_SEPARATOR "\\" -#define WSTRING_PATH_SEPARATOR L"\\" - #else -#define CHAR_PATH_SEPARATOR '/' -#define WCHAR_PATH_SEPARATOR L'/' -#define STRING_PATH_SEPARATOR "/" -#define WSTRING_PATH_SEPARATOR L"/" - #include // for wchar_t #include diff --git a/CPP/Common/Wildcard.cpp b/CPP/Common/Wildcard.cpp index 141c5dd6..ac77e39b 100755 --- a/CPP/Common/Wildcard.cpp +++ b/CPP/Common/Wildcard.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../C/Types.h" + #include "Wildcard.h" bool g_CaseSensitive = diff --git a/CPP/Windows/Control/Dialog.cpp b/CPP/Windows/Control/Dialog.cpp index dd0cf066..3cfa517a 100755 --- a/CPP/Windows/Control/Dialog.cpp +++ b/CPP/Windows/Control/Dialog.cpp @@ -103,7 +103,7 @@ bool IsDialogSizeOK(int xSize, int ySize) void CDialog::NormalizeSize(bool fullNormalize) { RECT workRect; - GetWorkAreaRect(&workRect); + GetWorkAreaRect(&workRect); int xSize = RECT_SIZE_X(workRect); int ySize = RECT_SIZE_Y(workRect); RECT rect; @@ -135,7 +135,7 @@ void CDialog::NormalizeSize(bool fullNormalize) void CDialog::NormalizePosition() { RECT workRect, rect; - GetWorkAreaRect(&workRect); + GetWorkAreaRect(&workRect); GetWindowRect(&rect); if (rect.bottom > workRect.bottom && rect.top > workRect.top) Move(rect.left, workRect.top, RECT_SIZE_X(rect), RECT_SIZE_Y(rect), true); diff --git a/CPP/Windows/FileName.h b/CPP/Windows/FileName.h index 20786e00..d9807902 100755 --- a/CPP/Windows/FileName.h +++ b/CPP/Windows/FileName.h @@ -3,6 +3,8 @@ #ifndef __WINDOWS_FILENAME_H #define __WINDOWS_FILENAME_H +#include "../../C/Types.h" + #include "../Common/MyString.h" namespace NWindows { diff --git a/CPP/Windows/PropVariant.cpp b/CPP/Windows/PropVariant.cpp index 3675778d..90212e08 100755 --- a/CPP/Windows/PropVariant.cpp +++ b/CPP/Windows/PropVariant.cpp @@ -218,7 +218,7 @@ void CPropVariant::InternalCopy(const PROPVARIANT *pSrc) int CPropVariant::Compare(const CPropVariant &a) { if (vt != a.vt) - return 0; // it's bug case + return MyCompare(vt, a.vt); switch (vt) { case VT_EMPTY: return 0; diff --git a/CPP/Windows/PropVariantUtils.cpp b/CPP/Windows/PropVariantUtils.cpp index 0c9e8f34..0a9cfab7 100755 --- a/CPP/Windows/PropVariantUtils.cpp +++ b/CPP/Windows/PropVariantUtils.cpp @@ -53,13 +53,14 @@ AString FlagsToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags) for (unsigned i = 0; i < num; i++) { const CUInt32PCharPair &p = pairs[i]; - if ((flags & p.Value) != 0) + UInt32 flag = (UInt32)1 << (unsigned)p.Value; + if ((flags & flag) != 0) { if (!s.IsEmpty()) s += ' '; s += p.Name; } - flags &= ~p.Value; + flags &= ~flag; } if (flags != 0) { diff --git a/DOC/7zip.inf b/DOC/7zip.inf index 400f7f96..5bceb480 100755 --- a/DOC/7zip.inf +++ b/DOC/7zip.inf @@ -10,8 +10,8 @@ AppName = "7-Zip" InstallDir = %CE1%\%AppName% [Strings] -AppVer = "9.17" -AppDate = "2010-10-04" +AppVer = "9.18" +AppDate = "2010-11-02" [CEDevice] ; ProcessorType = 2577 ; ARM @@ -32,6 +32,7 @@ CEShortcuts = Shortcuts [SourceDisksFiles] 7zFM.exe = 1 7z.sfx = 1 +7zS2.sfx = 1 ru.txt = 2 [DestinationDirs] @@ -43,6 +44,7 @@ Shortcuts = ,%CE11% [CopyFilesSection] 7zFM.exe 7z.sfx +7zS2.sfx [CopyFilesSection.Lang] ru.txt diff --git a/DOC/7zip.nsi b/DOC/7zip.nsi index 54ed3424..42c60aad 100755 --- a/DOC/7zip.nsi +++ b/DOC/7zip.nsi @@ -2,7 +2,7 @@ ;Defines !define VERSION_MAJOR 9 -!define VERSION_MINOR 17 +!define VERSION_MINOR 18 !define VERSION_POSTFIX_FULL " beta" !ifdef WIN64 !ifdef IA64 diff --git a/DOC/7zip.wxs b/DOC/7zip.wxs index 83465d43..ec6d00e4 100755 --- a/DOC/7zip.wxs +++ b/DOC/7zip.wxs @@ -1,7 +1,7 @@ - + diff --git a/DOC/Methods.txt b/DOC/Methods.txt index 0415a126..f52e7c31 100755 --- a/DOC/Methods.txt +++ b/DOC/Methods.txt @@ -1,4 +1,4 @@ -7-Zip method IDs (9.04) +7-Zip method IDs (9.18) ----------------------- Each compression or crypto method in 7z has unique binary value (ID). @@ -77,7 +77,13 @@ List of defined IDs 06 - Implode 08 - Deflate 09 - Deflate64 + 10 - Imploding 12 - BZip2 (not used). Use {04 02 02} instead + 14 - LZMA + 60 - Jpeg + 61 - WavPack + 62 - PPMd + 63 - wzAES 02 - BZip 02 - BZip2 03 - Rar diff --git a/DOC/history.txt b/DOC/history.txt index aa383647..05a9a216 100755 --- a/DOC/history.txt +++ b/DOC/history.txt @@ -1,6 +1,11 @@ Sources history of the 7-Zip ---------------------------- +9.18 2010-11-02 +------------------------- +- New small SFX module for installers (C/Util/SfxSetup). + + 9.17 2010-10-04 ------------------------- - IStream.h::IOutStream:: diff --git a/DOC/lzma.txt b/DOC/lzma.txt index 47369042..ae872f3d 100755 --- a/DOC/lzma.txt +++ b/DOC/lzma.txt @@ -1,4 +1,4 @@ -LZMA SDK 9.17 +LZMA SDK 9.18 ------------- LZMA SDK provides the documentation, samples, header files, libraries, diff --git a/DOC/readme.txt b/DOC/readme.txt index a6d781ca..7e959dc6 100755 --- a/DOC/readme.txt +++ b/DOC/readme.txt @@ -1,4 +1,4 @@ -7-Zip 9.17 Sources +7-Zip 9.18 Sources ------------------ 7-Zip is a file archiver for Windows. -- cgit v1.2.3