From 4677d362982a38c6e2aabb667e33aaa7f921f018 Mon Sep 17 00:00:00 2001 From: Karsten Heimrich Date: Tue, 9 Jun 2015 16:04:24 +0200 Subject: Update source tree with version 9.38.beta of LZMA SDK. - Remove unused files. - Split in .pri files. - Add HEADERS section. - Adjust lib7z_facade. Change-Id: I31e7bafbfe1a9346364bd58c391601955f98ad3a Reviewed-by: Kai Koehne --- src/libs/7zip/unix/CPP/7zip/7zip.pri | 6 + src/libs/7zip/unix/CPP/7zip/Archive/7z/7z.pri | 29 + .../unix/CPP/7zip/Archive/7z/7zCompressionMode.cpp | 3 - .../unix/CPP/7zip/Archive/7z/7zCompressionMode.h | 9 +- .../7zip/unix/CPP/7zip/Archive/7z/7zDecode.cpp | 153 +- src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.h | 13 +- .../7zip/unix/CPP/7zip/Archive/7z/7zEncode.cpp | 136 +- src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.h | 2 + .../7zip/unix/CPP/7zip/Archive/7z/7zExtract.cpp | 58 +- .../unix/CPP/7zip/Archive/7z/7zFolderInStream.cpp | 4 +- .../unix/CPP/7zip/Archive/7z/7zFolderInStream.h | 2 +- .../unix/CPP/7zip/Archive/7z/7zFolderOutStream.cpp | 2 +- .../unix/CPP/7zip/Archive/7z/7zFolderOutStream.h | 6 +- .../7zip/unix/CPP/7zip/Archive/7z/7zHandler.cpp | 717 +++-- src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.h | 84 +- .../7zip/unix/CPP/7zip/Archive/7z/7zHandlerOut.cpp | 708 ++++- .../7zip/unix/CPP/7zip/Archive/7z/7zHeader.cpp | 5 + src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.h | 14 +- src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.cpp | 1459 +++++---- src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.h | 359 ++- src/libs/7zip/unix/CPP/7zip/Archive/7z/7zItem.h | 214 +- src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.cpp | 481 +-- src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.h | 211 +- .../7zip/unix/CPP/7zip/Archive/7z/7zProperties.cpp | 56 +- .../7zip/unix/CPP/7zip/Archive/7z/7zRegister.cpp | 23 +- .../7zip/unix/CPP/7zip/Archive/7z/7zSpecStream.cpp | 10 +- .../7zip/unix/CPP/7zip/Archive/7z/7zUpdate.cpp | 712 +++-- src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.h | 44 +- src/libs/7zip/unix/CPP/7zip/Archive/Archive.pri | 5 + .../7zip/unix/CPP/7zip/Archive/ArchiveExports.cpp | 135 - .../unix/CPP/7zip/Archive/Common/CoderMixer2.cpp | 74 +- .../unix/CPP/7zip/Archive/Common/CoderMixer2.h | 19 +- .../unix/CPP/7zip/Archive/Common/CoderMixer2MT.cpp | 60 +- .../unix/CPP/7zip/Archive/Common/CoderMixer2MT.h | 15 +- .../7zip/unix/CPP/7zip/Archive/Common/Common.pri | 18 + .../7zip/Archive/Common/CrossThreadProgress.cpp | 15 - .../CPP/7zip/Archive/Common/CrossThreadProgress.h | 37 - .../CPP/7zip/Archive/Common/DummyOutStream.cpp | 19 +- .../unix/CPP/7zip/Archive/Common/DummyOutStream.h | 7 +- .../unix/CPP/7zip/Archive/Common/HandlerOut.cpp | 618 +--- .../7zip/unix/CPP/7zip/Archive/Common/HandlerOut.h | 80 +- .../CPP/7zip/Archive/Common/InStreamWithCRC.cpp | 32 +- .../unix/CPP/7zip/Archive/Common/ItemNameUtils.cpp | 41 +- .../unix/CPP/7zip/Archive/Common/ItemNameUtils.h | 7 +- .../unix/CPP/7zip/Archive/Common/MultiStream.cpp | 57 +- .../unix/CPP/7zip/Archive/Common/MultiStream.h | 13 +- .../CPP/7zip/Archive/Common/OutStreamWithCRC.h | 1 + .../CPP/7zip/Archive/Common/ParseProperties.cpp | 177 -- .../unix/CPP/7zip/Archive/Common/ParseProperties.h | 16 +- .../7zip/unix/CPP/7zip/Archive/DllExports2.cpp | 76 - src/libs/7zip/unix/CPP/7zip/Archive/IArchive.h | 325 +- .../7zip/unix/CPP/7zip/Archive/LzmaHandler.cpp | 348 ++- .../7zip/unix/CPP/7zip/Archive/SplitHandler.cpp | 267 +- src/libs/7zip/unix/CPP/7zip/Archive/XzHandler.cpp | 752 +++-- src/libs/7zip/unix/CPP/7zip/Common/CWrappers.cpp | 44 +- src/libs/7zip/unix/CPP/7zip/Common/CWrappers.h | 37 +- src/libs/7zip/unix/CPP/7zip/Common/Common.pri | 39 + src/libs/7zip/unix/CPP/7zip/Common/CreateCoder.cpp | 218 +- src/libs/7zip/unix/CPP/7zip/Common/CreateCoder.h | 41 +- .../unix/CPP/7zip/Common/FilePathAutoRename.cpp | 28 +- .../7zip/unix/CPP/7zip/Common/FilePathAutoRename.h | 10 +- src/libs/7zip/unix/CPP/7zip/Common/FileStreams.cpp | 318 +- src/libs/7zip/unix/CPP/7zip/Common/FileStreams.h | 80 +- src/libs/7zip/unix/CPP/7zip/Common/FilterCoder.cpp | 24 +- src/libs/7zip/unix/CPP/7zip/Common/FilterCoder.h | 22 +- src/libs/7zip/unix/CPP/7zip/Common/InBuffer.cpp | 122 +- src/libs/7zip/unix/CPP/7zip/Common/InBuffer.h | 101 +- .../7zip/unix/CPP/7zip/Common/InOutTempBuffer.cpp | 15 +- .../7zip/unix/CPP/7zip/Common/InOutTempBuffer.h | 4 +- .../7zip/unix/CPP/7zip/Common/LimitedStreams.cpp | 255 +- .../7zip/unix/CPP/7zip/Common/LimitedStreams.h | 142 +- src/libs/7zip/unix/CPP/7zip/Common/MethodId.cpp | 27 - src/libs/7zip/unix/CPP/7zip/Common/MethodId.h | 2 +- src/libs/7zip/unix/CPP/7zip/Common/MethodProps.cpp | 484 ++- src/libs/7zip/unix/CPP/7zip/Common/MethodProps.h | 178 +- .../7zip/unix/CPP/7zip/Common/OffsetStream.cpp | 35 - src/libs/7zip/unix/CPP/7zip/Common/OffsetStream.h | 25 - src/libs/7zip/unix/CPP/7zip/Common/OutBuffer.cpp | 57 +- src/libs/7zip/unix/CPP/7zip/Common/OutBuffer.h | 37 +- .../7zip/unix/CPP/7zip/Common/ProgressUtils.cpp | 2 +- src/libs/7zip/unix/CPP/7zip/Common/PropId.cpp | 99 + src/libs/7zip/unix/CPP/7zip/Common/RegisterArc.h | 67 +- src/libs/7zip/unix/CPP/7zip/Common/RegisterCodec.h | 48 +- .../7zip/unix/CPP/7zip/Common/StreamBinder.cpp | 153 +- src/libs/7zip/unix/CPP/7zip/Common/StreamBinder.h | 43 +- .../7zip/unix/CPP/7zip/Common/StreamObjects.cpp | 75 +- src/libs/7zip/unix/CPP/7zip/Common/StreamObjects.h | 31 +- src/libs/7zip/unix/CPP/7zip/Common/StreamUtils.cpp | 8 +- src/libs/7zip/unix/CPP/7zip/Common/StreamUtils.h | 12 +- src/libs/7zip/unix/CPP/7zip/Common/UniqBlocks.cpp | 56 + src/libs/7zip/unix/CPP/7zip/Common/UniqBlocks.h | 30 + src/libs/7zip/unix/CPP/7zip/Common/VirtThread.cpp | 14 +- src/libs/7zip/unix/CPP/7zip/Common/VirtThread.h | 11 +- src/libs/7zip/unix/CPP/7zip/Compress/Bcj2Coder.cpp | 176 +- src/libs/7zip/unix/CPP/7zip/Compress/Bcj2Coder.h | 55 +- .../7zip/unix/CPP/7zip/Compress/BranchMisc.cpp | 42 +- .../7zip/unix/CPP/7zip/Compress/CodecExports.cpp | 160 - src/libs/7zip/unix/CPP/7zip/Compress/Compress.pri | 29 + src/libs/7zip/unix/CPP/7zip/Compress/CopyCoder.cpp | 21 +- src/libs/7zip/unix/CPP/7zip/Compress/CopyCoder.h | 1 + .../7zip/unix/CPP/7zip/Compress/DeltaFilter.cpp | 17 +- .../7zip/unix/CPP/7zip/Compress/Lzma2Decoder.cpp | 4 +- .../7zip/unix/CPP/7zip/Compress/Lzma2Encoder.cpp | 2 +- .../7zip/unix/CPP/7zip/Compress/Lzma2Encoder.h | 2 +- .../7zip/unix/CPP/7zip/Compress/LzmaDecoder.cpp | 18 +- src/libs/7zip/unix/CPP/7zip/Compress/LzmaDecoder.h | 8 +- .../7zip/unix/CPP/7zip/Compress/LzmaEncoder.cpp | 34 +- src/libs/7zip/unix/CPP/7zip/Compress/LzmaEncoder.h | 4 +- src/libs/7zip/unix/CPP/7zip/Compress/RangeCoder.h | 30 +- .../7zip/unix/CPP/7zip/Compress/RangeCoderBit.h | 16 +- src/libs/7zip/unix/CPP/7zip/Guid.txt | 38 +- src/libs/7zip/unix/CPP/7zip/ICoder.h | 29 +- src/libs/7zip/unix/CPP/7zip/IPassword.h | 3 +- src/libs/7zip/unix/CPP/7zip/IProgress.h | 2 +- src/libs/7zip/unix/CPP/7zip/IStream.h | 89 +- src/libs/7zip/unix/CPP/7zip/MyVersion.h | 11 - src/libs/7zip/unix/CPP/7zip/PropID.h | 66 +- .../unix/CPP/7zip/UI/Common/ArchiveCommandLine.cpp | 1216 +++++--- .../unix/CPP/7zip/UI/Common/ArchiveCommandLine.h | 79 +- .../CPP/7zip/UI/Common/ArchiveExtractCallback.cpp | 999 +++++- .../CPP/7zip/UI/Common/ArchiveExtractCallback.h | 208 +- .../7zip/unix/CPP/7zip/UI/Common/ArchiveName.cpp | 54 - .../7zip/unix/CPP/7zip/UI/Common/ArchiveName.h | 10 - .../CPP/7zip/UI/Common/ArchiveOpenCallback.cpp | 46 +- .../unix/CPP/7zip/UI/Common/ArchiveOpenCallback.h | 38 +- src/libs/7zip/unix/CPP/7zip/UI/Common/Bench.cpp | 1028 ------- src/libs/7zip/unix/CPP/7zip/UI/Common/Bench.h | 42 - src/libs/7zip/unix/CPP/7zip/UI/Common/Common.pri | 43 + .../7zip/unix/CPP/7zip/UI/Common/DefaultName.cpp | 6 +- .../7zip/unix/CPP/7zip/UI/Common/DefaultName.h | 6 +- src/libs/7zip/unix/CPP/7zip/UI/Common/DirItem.h | 91 +- .../7zip/unix/CPP/7zip/UI/Common/EnumDirItems.cpp | 678 +++- .../7zip/unix/CPP/7zip/UI/Common/EnumDirItems.h | 18 +- src/libs/7zip/unix/CPP/7zip/UI/Common/ExitCode.h | 27 - src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.cpp | 370 ++- src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.h | 54 +- .../7zip/unix/CPP/7zip/UI/Common/ExtractMode.h | 42 +- .../unix/CPP/7zip/UI/Common/ExtractingFilePath.cpp | 114 +- .../unix/CPP/7zip/UI/Common/ExtractingFilePath.h | 12 +- src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.cpp | 361 +++ src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.h | 107 + .../unix/CPP/7zip/UI/Common/IFileExtractCallback.h | 32 +- .../7zip/unix/CPP/7zip/UI/Common/LoadCodecs.cpp | 796 +++-- src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.h | 190 +- .../7zip/unix/CPP/7zip/UI/Common/OpenArchive.cpp | 3248 ++++++++++++++++++-- .../7zip/unix/CPP/7zip/UI/Common/OpenArchive.h | 351 ++- .../7zip/unix/CPP/7zip/UI/Common/PropIDUtils.cpp | 549 +++- .../7zip/unix/CPP/7zip/UI/Common/PropIDUtils.h | 13 +- src/libs/7zip/unix/CPP/7zip/UI/Common/Property.h | 6 +- .../7zip/unix/CPP/7zip/UI/Common/SetProperties.cpp | 31 +- .../7zip/unix/CPP/7zip/UI/Common/SortUtils.cpp | 17 +- src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.h | 8 +- .../7zip/unix/CPP/7zip/UI/Common/TempFiles.cpp | 9 +- src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.h | 8 +- src/libs/7zip/unix/CPP/7zip/UI/Common/Update.cpp | 1124 +++++-- src/libs/7zip/unix/CPP/7zip/UI/Common/Update.h | 145 +- .../7zip/unix/CPP/7zip/UI/Common/UpdateAction.cpp | 10 +- .../7zip/unix/CPP/7zip/UI/Common/UpdateAction.h | 29 +- .../unix/CPP/7zip/UI/Common/UpdateCallback.cpp | 455 ++- .../7zip/unix/CPP/7zip/UI/Common/UpdateCallback.h | 64 +- .../7zip/unix/CPP/7zip/UI/Common/UpdatePair.cpp | 214 +- src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.h | 4 +- .../7zip/unix/CPP/7zip/UI/Common/UpdateProduce.cpp | 27 +- .../7zip/unix/CPP/7zip/UI/Common/UpdateProduce.h | 26 +- src/libs/7zip/unix/CPP/7zip/UI/Common/WorkDir.cpp | 59 - src/libs/7zip/unix/CPP/7zip/UI/Common/WorkDir.h | 10 - .../7zip/unix/CPP/7zip/UI/Common/ZipRegistry.h | 105 - .../7zip/unix/CPP/7zip/UI/Console/BenchCon.cpp | 297 -- src/libs/7zip/unix/CPP/7zip/UI/Console/BenchCon.h | 16 - src/libs/7zip/unix/CPP/7zip/UI/Console/Console.pri | 2 + .../7zip/unix/CPP/7zip/UI/Console/ConsoleClose.cpp | 49 - .../7zip/unix/CPP/7zip/UI/Console/ConsoleClose.h | 26 - .../CPP/7zip/UI/Console/ExtractCallbackConsole.cpp | 228 -- .../CPP/7zip/UI/Console/ExtractCallbackConsole.h | 73 - src/libs/7zip/unix/CPP/7zip/UI/Console/List.cpp | 654 ---- src/libs/7zip/unix/CPP/7zip/UI/Console/List.h | 20 - src/libs/7zip/unix/CPP/7zip/UI/Console/Main.cpp | 628 ---- src/libs/7zip/unix/CPP/7zip/UI/Console/MainAr.cpp | 127 - .../CPP/7zip/UI/Console/OpenCallbackConsole.cpp | 58 - .../unix/CPP/7zip/UI/Console/OpenCallbackConsole.h | 24 - .../unix/CPP/7zip/UI/Console/PercentPrinter.cpp | 40 +- .../7zip/unix/CPP/7zip/UI/Console/PercentPrinter.h | 11 +- .../CPP/7zip/UI/Console/UpdateCallbackConsole.cpp | 261 -- .../CPP/7zip/UI/Console/UpdateCallbackConsole.h | 62 - .../unix/CPP/7zip/UI/Console/UserInputUtils.cpp | 96 - .../7zip/unix/CPP/7zip/UI/Console/UserInputUtils.h | 24 - 186 files changed, 17267 insertions(+), 11193 deletions(-) create mode 100644 src/libs/7zip/unix/CPP/7zip/7zip.pri create mode 100644 src/libs/7zip/unix/CPP/7zip/Archive/7z/7z.pri delete mode 100644 src/libs/7zip/unix/CPP/7zip/Archive/7z/7zCompressionMode.cpp create mode 100644 src/libs/7zip/unix/CPP/7zip/Archive/Archive.pri delete mode 100644 src/libs/7zip/unix/CPP/7zip/Archive/ArchiveExports.cpp create mode 100644 src/libs/7zip/unix/CPP/7zip/Archive/Common/Common.pri delete mode 100644 src/libs/7zip/unix/CPP/7zip/Archive/Common/CrossThreadProgress.cpp delete mode 100644 src/libs/7zip/unix/CPP/7zip/Archive/Common/CrossThreadProgress.h delete mode 100644 src/libs/7zip/unix/CPP/7zip/Archive/Common/ParseProperties.cpp delete mode 100644 src/libs/7zip/unix/CPP/7zip/Archive/DllExports2.cpp create mode 100644 src/libs/7zip/unix/CPP/7zip/Common/Common.pri delete mode 100644 src/libs/7zip/unix/CPP/7zip/Common/MethodId.cpp delete mode 100644 src/libs/7zip/unix/CPP/7zip/Common/OffsetStream.cpp delete mode 100644 src/libs/7zip/unix/CPP/7zip/Common/OffsetStream.h create mode 100644 src/libs/7zip/unix/CPP/7zip/Common/PropId.cpp create mode 100644 src/libs/7zip/unix/CPP/7zip/Common/UniqBlocks.cpp create mode 100644 src/libs/7zip/unix/CPP/7zip/Common/UniqBlocks.h delete mode 100644 src/libs/7zip/unix/CPP/7zip/Compress/CodecExports.cpp create mode 100644 src/libs/7zip/unix/CPP/7zip/Compress/Compress.pri delete mode 100644 src/libs/7zip/unix/CPP/7zip/MyVersion.h delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveName.cpp delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveName.h delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Common/Bench.cpp delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Common/Bench.h create mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Common/Common.pri delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Common/ExitCode.h create mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.cpp create mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.h delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Common/WorkDir.cpp delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Common/WorkDir.h delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Common/ZipRegistry.h delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Console/BenchCon.cpp delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Console/BenchCon.h create mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Console/Console.pri delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Console/ConsoleClose.cpp delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Console/ConsoleClose.h delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Console/ExtractCallbackConsole.h delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Console/List.cpp delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Console/List.h delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Console/Main.cpp delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Console/MainAr.cpp delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Console/OpenCallbackConsole.cpp delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Console/OpenCallbackConsole.h delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Console/UpdateCallbackConsole.h delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Console/UserInputUtils.cpp delete mode 100644 src/libs/7zip/unix/CPP/7zip/UI/Console/UserInputUtils.h (limited to 'src/libs/7zip/unix/CPP/7zip') diff --git a/src/libs/7zip/unix/CPP/7zip/7zip.pri b/src/libs/7zip/unix/CPP/7zip/7zip.pri new file mode 100644 index 000000000..a2b70a1f2 --- /dev/null +++ b/src/libs/7zip/unix/CPP/7zip/7zip.pri @@ -0,0 +1,6 @@ +HEADERS += $$7ZIP_BASE/CPP/7zip/ICoder.h \ + $$7ZIP_BASE/CPP/7zip/IDecl.h \ + $$7ZIP_BASE/CPP/7zip/IPassword.h \ + $$7ZIP_BASE/CPP/7zip/IProgress.h \ + $$7ZIP_BASE/CPP/7zip/IStream.h \ + $$7ZIP_BASE/CPP/7zip/PropID.h diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7z.pri b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7z.pri new file mode 100644 index 000000000..60211faae --- /dev/null +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7z.pri @@ -0,0 +1,29 @@ +HEADERS += $$7ZIP_BASE/CPP/7zip/Archive/7z/7zCompressionMode.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zDecode.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zEncode.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zFolderInStream.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zFolderOutStream.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zHandler.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zHeader.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zIn.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zItem.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zOut.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zProperties.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zSpecStream.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zUpdate.h + +SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/7z/7zDecode.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zEncode.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zExtract.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zFolderInStream.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zFolderOutStream.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zHandler.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zHandlerOut.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zHeader.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zIn.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zOut.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zProperties.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zRegister.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zSpecStream.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zUpdate.cpp + diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zCompressionMode.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zCompressionMode.cpp deleted file mode 100644 index 6774fc482..000000000 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zCompressionMode.cpp +++ /dev/null @@ -1,3 +0,0 @@ -// CompressionMethod.cpp - -#include "StdAfx.h" diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zCompressionMode.h b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zCompressionMode.h index 55bbc68ee..5cde97c38 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zCompressionMode.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zCompressionMode.h @@ -3,19 +3,18 @@ #ifndef __7Z_COMPRESSION_MODE_H #define __7Z_COMPRESSION_MODE_H -#include "../../../Common/MyString.h" - -#include "../../../Windows/PropVariant.h" - +#include "../../Common/MethodId.h" #include "../../Common/MethodProps.h" namespace NArchive { namespace N7z { -struct CMethodFull: public CMethod +struct CMethodFull: public CProps { + CMethodId Id; UInt32 NumInStreams; UInt32 NumOutStreams; + bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } }; diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.cpp index 425a34157..973966bd3 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.cpp @@ -16,29 +16,33 @@ static void ConvertFolderItemInfoToBindInfo(const CFolder &folder, CBindInfoEx &bindInfo) { bindInfo.Clear(); - int i; + bindInfo.BindPairs.ClearAndSetSize(folder.BindPairs.Size()); + unsigned i; for (i = 0; i < folder.BindPairs.Size(); i++) { - NCoderMixer::CBindPair bindPair; + NCoderMixer::CBindPair &bindPair = bindInfo.BindPairs[i]; bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex; bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex; - bindInfo.BindPairs.Add(bindPair); } + + bindInfo.Coders.ClearAndSetSize(folder.Coders.Size()); + bindInfo.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size()); + UInt32 outStreamIndex = 0; for (i = 0; i < folder.Coders.Size(); i++) { - NCoderMixer::CCoderStreamsInfo coderStreamsInfo; + NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i]; const CCoderInfo &coderInfo = folder.Coders[i]; coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams; coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams; - bindInfo.Coders.Add(coderStreamsInfo); - bindInfo.CoderMethodIDs.Add(coderInfo.MethodID); + bindInfo.CoderMethodIDs[i] = coderInfo.MethodID; for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++) if (folder.FindBindPairForOutStream(outStreamIndex) < 0) bindInfo.OutStreams.Add(outStreamIndex); } + bindInfo.InStreams.ClearAndSetSize(folder.PackStreams.Size()); for (i = 0; i < folder.PackStreams.Size(); i++) - bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]); + bindInfo.InStreams[i] = (UInt32)folder.PackStreams[i]; } static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1, @@ -58,7 +62,7 @@ static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2) { if (a1.Coders.Size() != a2.Coders.Size()) return false; - int i; + unsigned i; for (i = 0; i < a1.Coders.Size(); i++) if (!AreCodersEqual(a1.Coders[i], a2.Coders[i])) return false; @@ -90,46 +94,50 @@ HRESULT CDecoder::Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, - const UInt64 *packSizes, - const CFolder &folderInfo, + const CFolders &folders, int folderIndex, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress - #ifndef _NO_CRYPTO - , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS_DECL #if !defined(_7ZIP_ST) && !defined(_SFX) , bool mtMode, UInt32 numThreads #endif ) { - if (!folderInfo.CheckStructure()) + const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]]; + CFolder folderInfo; + folders.ParseFolderInfo(folderIndex, folderInfo); + + if (!folderInfo.CheckStructure(folders.GetNumFolderUnpackSizes(folderIndex))) return E_NOTIMPL; + + /* + We don't need to init isEncrypted and passwordIsDefined + We must upgrade them only #ifndef _NO_CRYPTO + isEncrypted = false; passwordIsDefined = false; #endif + */ + CObjectVector< CMyComPtr > inStreams; - + CLockedInStream lockedInStream; lockedInStream.Init(inStream); - - for (int j = 0; j < folderInfo.PackStreams.Size(); j++) + + for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++) { - CLockedSequentialInStreamImp *lockedStreamImpSpec = new - CLockedSequentialInStreamImp; + CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp; CMyComPtr lockedStreamImp = lockedStreamImpSpec; - lockedStreamImpSpec->Init(&lockedInStream, startPos); - startPos += packSizes[j]; - - CLimitedSequentialInStream *streamSpec = new - CLimitedSequentialInStream; + lockedStreamImpSpec->Init(&lockedInStream, startPos + packPositions[j]); + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr inStream = streamSpec; streamSpec->SetStream(lockedStreamImp); - streamSpec->Init(packSizes[j]); + streamSpec->Init(packPositions[j + 1] - packPositions[j]); inStreams.Add(inStream); } - - int numCoders = folderInfo.Coders.Size(); - + + unsigned numCoders = folderInfo.Coders.Size(); + CBindInfoEx bindInfo; ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo); bool createNewCoders; @@ -139,10 +147,10 @@ HRESULT CDecoder::Decode( createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev); if (createNewCoders) { - int i; + unsigned i; _decoders.Clear(); // _decoders2.Clear(); - + _mixerCoder.Release(); if (_multiThread) @@ -160,12 +168,12 @@ HRESULT CDecoder::Decode( #endif } RINOK(_mixerCoderCommon->SetBindInfo(bindInfo)); - + for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; - + CMyComPtr decoder; CMyComPtr decoder2; RINOK(CreateCoder( @@ -178,7 +186,7 @@ HRESULT CDecoder::Decode( return E_NOTIMPL; decoderUnknown = (IUnknown *)decoder; - + if (_multiThread) _mixerCoderMTSpec->AddCoder(decoder); #ifdef _ST_MODE @@ -204,32 +212,34 @@ HRESULT CDecoder::Decode( decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { - RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); + RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs)); } #endif } _bindInfoExPrev = bindInfo; _bindInfoExPrevIsDefined = true; } - int i; + unsigned i; _mixerCoderCommon->ReInit(); - - UInt32 packStreamIndex = 0, unpackStreamIndex = 0; + + UInt32 packStreamIndex = 0; + UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex]; + UInt32 unpackStreamIndex = unpackStreamIndexStart; UInt32 coderIndex = 0; // UInt32 coder2Index = 0; - + for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; CMyComPtr &decoder = _decoders[coderIndex]; - + { CMyComPtr setDecoderProperties; decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); if (setDecoderProperties) { const CByteBuffer &props = coderInfo.Props; - size_t size = props.GetCapacity(); + size_t size = props.Size(); if (size > 0xFFFFFFFF) return E_NOTIMPL; // if (size > 0) @@ -257,56 +267,55 @@ HRESULT CDecoder::Decode( decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { - if (getTextPassword == 0) - return E_FAIL; + isEncrypted = true; + if (!getTextPassword) + return E_NOTIMPL; CMyComBSTR passwordBSTR; RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR)); - CByteBuffer buffer; passwordIsDefined = true; - const UString password(passwordBSTR); - const UInt32 sizeInBytes = password.Length() * 2; - buffer.SetCapacity(sizeInBytes); - for (int i = 0; i < password.Length(); i++) + size_t len = 0; + if (passwordBSTR) + len = MyStringLen((BSTR)passwordBSTR); + CByteBuffer buffer(len * 2); + for (size_t i = 0; i < len; i++) { - wchar_t c = password[i]; + wchar_t c = passwordBSTR[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } - RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); + RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size())); } } #endif coderIndex++; - + UInt32 numInStreams = (UInt32)coderInfo.NumInStreams; UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams; - CRecordVector packSizesPointers; - CRecordVector unpackSizesPointers; - packSizesPointers.Reserve(numInStreams); - unpackSizesPointers.Reserve(numOutStreams); + CObjArray packSizes(numInStreams); + CObjArray packSizesPointers(numInStreams); + CObjArray unpackSizesPointers(numOutStreams); UInt32 j; + for (j = 0; j < numOutStreams; j++, unpackStreamIndex++) - unpackSizesPointers.Add(&folderInfo.UnpackSizes[unpackStreamIndex]); - + unpackSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndex]; + for (j = 0; j < numInStreams; j++, packStreamIndex++) { int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex); if (bindPairIndex >= 0) - packSizesPointers.Add( - &folderInfo.UnpackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]); + packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + (UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]; else { int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex); if (index < 0) - return E_FAIL; - packSizesPointers.Add(&packSizes[index]); + return S_FALSE; // check it + packSizes[j] = packPositions[index + 1] - packPositions[index]; + packSizesPointers[j] = &packSizes[j]; } } - - _mixerCoderCommon->SetCoderInfo(i, - &packSizesPointers.Front(), - &unpackSizesPointers.Front()); + + _mixerCoderCommon->SetCoderInfo(i, packSizesPointers, unpackSizesPointers); } UInt32 mainCoder, temp; bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp); @@ -317,16 +326,18 @@ HRESULT CDecoder::Decode( else _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);; */ - + if (numCoders == 0) return 0; - CRecordVector inStreamPointers; - inStreamPointers.Reserve(inStreams.Size()); - for (i = 0; i < inStreams.Size(); i++) - inStreamPointers.Add(inStreams[i]); + unsigned num = inStreams.Size(); + CObjArray inStreamPointers(num); + for (i = 0; i < num; i++) + inStreamPointers[i] = inStreams[i]; ISequentialOutStream *outStreamPointer = outStream; - return _mixerCoder->Code(&inStreamPointers.Front(), NULL, - inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress); + return _mixerCoder->Code( + inStreamPointers, NULL, num, + &outStreamPointer, NULL, 1, + compressProgress); } }} diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.h b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.h index d8a424a36..54e9d2b52 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.h @@ -14,7 +14,7 @@ #include "../../Common/CreateCoder.h" -#include "7zItem.h" +#include "7zIn.h" namespace NArchive { namespace N7z { @@ -33,14 +33,14 @@ class CDecoder { bool _bindInfoExPrevIsDefined; CBindInfoEx _bindInfoExPrev; - + bool _multiThread; #ifdef _ST_MODE NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec; #endif NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec; NCoderMixer::CCoderMixer2 *_mixerCoderCommon; - + CMyComPtr _mixerCoder; CObjectVector > _decoders; // CObjectVector > _decoders2; @@ -50,13 +50,10 @@ public: DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, - const UInt64 *packSizes, - const CFolder &folder, + const CFolders &folders, int folderIndex, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress - #ifndef _NO_CRYPTO - , ICryptoGetTextPassword *getTextPasswordSpec, bool &passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS_DECL #if !defined(_7ZIP_ST) && !defined(_SFX) , bool mtMode, UInt32 numThreads #endif diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.cpp index 87996bc0e..5f1436fc7 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.cpp @@ -23,30 +23,39 @@ static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindIn const CRecordVector decompressionMethods, CFolder &folder) { - folder.Coders.Clear(); // bindInfo.CoderMethodIDs.Clear(); // folder.OutStreams.Clear(); - folder.PackStreams.Clear(); - folder.BindPairs.Clear(); - int i; + folder.BindPairs.SetSize(bindInfo.BindPairs.Size()); + unsigned i; for (i = 0; i < bindInfo.BindPairs.Size(); i++) { - CBindPair bindPair; - bindPair.InIndex = bindInfo.BindPairs[i].InIndex; - bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex; - folder.BindPairs.Add(bindPair); + CBindPair &bp = folder.BindPairs[i]; + const NCoderMixer::CBindPair &mixerBp = bindInfo.BindPairs[i]; + bp.InIndex = mixerBp.InIndex; + bp.OutIndex = mixerBp.OutIndex; } + folder.Coders.SetSize(bindInfo.Coders.Size()); for (i = 0; i < bindInfo.Coders.Size(); i++) { - CCoderInfo coderInfo; + CCoderInfo &coderInfo = folder.Coders[i]; const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i]; coderInfo.NumInStreams = coderStreamsInfo.NumInStreams; coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams; coderInfo.MethodID = decompressionMethods[i]; - folder.Coders.Add(coderInfo); + // coderInfo.Props can be nonFree; } + folder.PackStreams.SetSize(bindInfo.InStreams.Size()); for (i = 0; i < bindInfo.InStreams.Size(); i++) - folder.PackStreams.Add(bindInfo.InStreams[i]); + folder.PackStreams[i] = bindInfo.InStreams[i]; +} + +static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder) +{ + CMyComPtr setCoderProperties; + coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); + if (setCoderProperties) + return props.SetCoderProps(setCoderProperties, dataSizeReduce); + return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK; } HRESULT CEncoder::CreateMixerCoder( @@ -56,15 +65,14 @@ HRESULT CEncoder::CreateMixerCoder( _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT; _mixerCoder = _mixerCoderSpec; RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo)); - for (int i = 0; i < _options.Methods.Size(); i++) + FOR_VECTOR (i, _options.Methods) { const CMethodFull &methodFull = _options.Methods[i]; - _codersInfo.Add(CCoderInfo()); - CCoderInfo &encodingInfo = _codersInfo.Back(); + CCoderInfo &encodingInfo = _codersInfo.AddNew(); encodingInfo.MethodID = methodFull.Id; CMyComPtr encoder; CMyComPtr encoder2; - + RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS @@ -74,7 +82,7 @@ HRESULT CEncoder::CreateMixerCoder( return E_FAIL; CMyComPtr encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2; - + #ifndef _7ZIP_ST { CMyComPtr setCoderMt; @@ -85,14 +93,13 @@ HRESULT CEncoder::CreateMixerCoder( } } #endif - - RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon)); + RINOK(SetCoderProps2(methodFull, inSizeForReduce, encoderCommon)); /* CMyComPtr resetSalt; encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt); - if (resetSalt != NULL) + if (resetSalt) { resetSalt->ResetSalt(); } @@ -103,19 +110,18 @@ HRESULT CEncoder::CreateMixerCoder( encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { - RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); + RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs)); } #endif - + CMyComPtr cryptoSetPassword; encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { - CByteBuffer buffer; - const UInt32 sizeInBytes = _options.Password.Length() * 2; - buffer.SetCapacity(sizeInBytes); - for (int i = 0; i < _options.Password.Length(); i++) + const UInt32 sizeInBytes = _options.Password.Len() * 2; + CByteBuffer buffer(sizeInBytes); + for (unsigned i = 0; i < _options.Password.Len(); i++) { wchar_t c = _options.Password[i]; ((Byte *)buffer)[i * 2] = (Byte)c; @@ -137,13 +143,15 @@ HRESULT CEncoder::Encode( ISequentialInStream *inStream, const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, CFolder &folderItem, + CRecordVector &coderUnpackSizes, + UInt64 &unpackSize, ISequentialOutStream *outStream, CRecordVector &packSizes, ICompressProgressInfo *compressProgress) { RINOK(EncoderConstr()); - if (_mixerCoderSpec == NULL) + if (!_mixerCoderSpec) { RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce)); } @@ -153,13 +161,13 @@ HRESULT CEncoder::Encode( CObjectVector inOutTempBuffers; CObjectVector tempBufferSpecs; CObjectVector > tempBuffers; - int numMethods = _bindInfo.Coders.Size(); - int i; + unsigned numMethods = _bindInfo.Coders.Size(); + unsigned i; for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { - inOutTempBuffers.Add(CInOutTempBuffer()); - inOutTempBuffers.Back().Create(); - inOutTempBuffers.Back().InitWriting(); + CInOutTempBuffer &iotb = inOutTempBuffers.AddNew(); + iotb.Create(); + iotb.InitWriting(); } for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { @@ -177,8 +185,8 @@ HRESULT CEncoder::Encode( return E_FAIL; UInt32 mainCoderIndex, mainStreamIndex; _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex); - - if (inStreamSize != NULL) + + if (inStreamSize) { CRecordVector sizePointers; for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++) @@ -189,40 +197,47 @@ HRESULT CEncoder::Encode( _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL); } - + // UInt64 outStreamStartPos; // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos)); - + CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2; CMyComPtr inStreamSizeCount = inStreamSizeCountSpec; - CSequentialOutStreamSizeCount *outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; - CMyComPtr outStreamSizeCount = outStreamSizeCountSpec; + CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL; + CMyComPtr outStreamSizeCount; inStreamSizeCountSpec->Init(inStream); - outStreamSizeCountSpec->SetStream(outStream); - outStreamSizeCountSpec->Init(); CRecordVector inStreamPointers; CRecordVector outStreamPointers; inStreamPointers.Add(inStreamSizeCount); - outStreamPointers.Add(outStreamSizeCount); + + if (_bindInfo.OutStreams.Size() != 0) + { + outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; + outStreamSizeCount = outStreamSizeCountSpec; + outStreamSizeCountSpec->SetStream(outStream); + outStreamSizeCountSpec->Init(); + outStreamPointers.Add(outStreamSizeCount); + } + for (i = 1; i < _bindInfo.OutStreams.Size(); i++) outStreamPointers.Add(tempBuffers[i - 1]); for (i = 0; i < _codersInfo.Size(); i++) { CCoderInfo &encodingInfo = _codersInfo[i]; - + CMyComPtr resetInitVector; _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector); - if (resetInitVector != NULL) + if (resetInitVector) { resetInitVector->ResetInitVector(); } CMyComPtr writeCoderProperties; _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); - if (writeCoderProperties != NULL) + if (writeCoderProperties) { CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream; CMyComPtr outStream(outStreamSpec); @@ -242,33 +257,38 @@ HRESULT CEncoder::Encode( } _mixerCoderSpec->SetProgressCoderIndex(progressIndex); - + RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1, &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress)); - + ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem); - - packSizes.Add(outStreamSizeCountSpec->GetSize()); - + + if (_bindInfo.OutStreams.Size() != 0) + packSizes.Add(outStreamSizeCountSpec->GetSize()); + for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1]; RINOK(inOutTempBuffer.WriteToStream(outStream)); packSizes.Add(inOutTempBuffer.GetDataSize()); } - + + unpackSize = 0; for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++) { int binder = _bindInfo.FindBinderForInStream( _bindReverseConverter->DestOutToSrcInMap[i]); UInt64 streamSize; if (binder < 0) + { streamSize = inStreamSizeCountSpec->GetSize(); + unpackSize = streamSize; + } else streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder); - folderItem.UnpackSizes.Add(streamSize); + coderUnpackSizes.Add(streamSize); } - for (i = numMethods - 1; i >= 0; i--) + for (i = 0; i < numMethods; i++) folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props; return S_OK; } @@ -298,16 +318,16 @@ HRESULT CEncoder::EncoderConstr() throw 1; NCoderMixer::CCoderStreamsInfo coderStreamsInfo; CMethodFull method; - + method.NumInStreams = 1; method.NumOutStreams = 1; coderStreamsInfo.NumInStreams = 1; coderStreamsInfo.NumOutStreams = 1; method.Id = k_AES; - + _options.Methods.Add(method); _bindInfo.Coders.Add(coderStreamsInfo); - + _bindInfo.InStreams.Add(0); _bindInfo.OutStreams.Add(0); } @@ -315,7 +335,7 @@ HRESULT CEncoder::EncoderConstr() { UInt32 numInStreams = 0, numOutStreams = 0; - int i; + unsigned i; for (i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; @@ -331,12 +351,12 @@ HRESULT CEncoder::EncoderConstr() bindPair.OutIndex = numOutStreams; _bindInfo.BindPairs.Add(bindPair); } - else + else if (coderStreamsInfo.NumOutStreams != 0) _bindInfo.OutStreams.Insert(0, numOutStreams); for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++) _bindInfo.OutStreams.Add(numOutStreams + j); } - + numInStreams += coderStreamsInfo.NumInStreams; numOutStreams += coderStreamsInfo.NumOutStreams; @@ -390,7 +410,7 @@ HRESULT CEncoder::EncoderConstr() if (_options.PasswordIsDefined) { - int numCryptoStreams = _bindInfo.OutStreams.Size(); + unsigned numCryptoStreams = _bindInfo.OutStreams.Size(); for (i = 0; i < numCryptoStreams; i++) { diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.h b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.h index 4909a6e89..8e20bdb5f 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.h @@ -45,6 +45,8 @@ public: ISequentialInStream *inStream, const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, CFolder &folderItem, + CRecordVector &coderUnpackSizes, + UInt64 &unpackSize, ISequentialOutStream *outStream, CRecordVector &packSizes, ICompressProgressInfo *compressProgress); diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zExtract.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zExtract.cpp index d55f38e13..bb350455c 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zExtract.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zExtract.cpp @@ -37,8 +37,8 @@ struct CExtractFolderInfo { if (fileIndex != kNumNoIndex) { - ExtractStatuses.Reserve(1); - ExtractStatuses.Add(true); + ExtractStatuses.ClearAndSetSize(1); + ExtractStatuses[0] = true; } }; }; @@ -51,7 +51,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CMyComPtr extractCallback = extractCallbackSpec; UInt64 importantTotalUnpacked = 0; - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = #ifdef _7Z_VOL @@ -60,17 +60,17 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, _db.Files.Size(); #endif - if(numItems == 0) + if (numItems == 0) return S_OK; /* - if(_volumes.Size() != 1) + if (_volumes.Size() != 1) return E_FAIL; const CVolume &volume = _volumes.Front(); - const CArchiveDatabaseEx &_db = volume.Database; + const CDbEx &_db = volume.Database; IInStream *_inStream = volume.Stream; */ - + CObjectVector extractFolderInfoVector; for (UInt32 ii = 0; ii < numItems; ii++) { @@ -86,10 +86,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, int volumeIndex = ref.VolumeIndex; const CVolume &volume = _volumes[volumeIndex]; - const CArchiveDatabaseEx &db = volume.Database; + const CDbEx &db = volume.Database; UInt32 fileIndex = ref.ItemIndex; #else - const CArchiveDatabaseEx &db = _db; + const CDbEx &db = _db; UInt32 fileIndex = ref2Index; #endif @@ -115,14 +115,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, volumeIndex, #endif kNumNoIndex, folderIndex)); - const CFolder &folderInfo = db.Folders[folderIndex]; - UInt64 unpackSize = folderInfo.GetUnpackSize(); + UInt64 unpackSize = db.GetFolderUnpackSize(folderIndex); importantTotalUnpacked += unpackSize; extractFolderInfoVector.Back().UnpackSize = unpackSize; } - + CExtractFolderInfo &efi = extractFolderInfoVector.Back(); - + // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex]; CNum startIndex = db.FolderStartFileIndex[folderIndex]; for (CNum index = efi.ExtractStatuses.Size(); @@ -156,7 +155,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CMyComPtr progress = lps; lps->Init(extractCallback, false); - for (int i = 0;; i++, totalUnpacked += curUnpacked, totalPacked += curPacked) + for (unsigned i = 0;; i++, totalUnpacked += curUnpacked, totalPacked += curPacked) { lps->OutSize = totalUnpacked; lps->InSize = totalPacked; @@ -164,7 +163,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (i >= extractFolderInfoVector.Size()) break; - + const CExtractFolderInfo &efi = extractFolderInfoVector[i]; curUnpacked = efi.UnpackSize; curPacked = 0; @@ -174,9 +173,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, #ifdef _7Z_VOL const CVolume &volume = _volumes[efi.VolumeIndex]; - const CArchiveDatabaseEx &db = volume.Database; + const CDbEx &db = volume.Database; #else - const CArchiveDatabaseEx &db = _db; + const CDbEx &db = _db; #endif CNum startIndex; @@ -200,13 +199,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, continue; CNum folderIndex = efi.FolderIndex; - const CFolder &folderInfo = db.Folders[folderIndex]; - curPacked = _db.GetFolderFullPackSize(folderIndex); - CNum packStreamIndex = db.FolderStartPackStreamIndex[folderIndex]; - UInt64 folderStartPackPos = db.GetFolderStreamPos(folderIndex, 0); - #ifndef _NO_CRYPTO CMyComPtr getTextPassword; if (extractCallback) @@ -216,26 +210,24 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, try { #ifndef _NO_CRYPTO - bool passwordIsDefined; + bool isEncrypted = false; + bool passwordIsDefined = false; #endif HRESULT result = decoder.Decode( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL - volume.Stream, + volume.Stream, #else - _inStream, + _inStream, #endif - folderStartPackPos, - &db.PackSizes[packStreamIndex], - folderInfo, + db.ArcInfo.DataStartPosition, + db, folderIndex, outStream, progress - #ifndef _NO_CRYPTO - , getTextPassword, passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS #if !defined(_7ZIP_ST) && !defined(_SFX) - , true, _numThreads + , true, _numThreads #endif ); @@ -246,7 +238,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } if (result == E_NOTIMPL) { - RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kUnSupportedMethod)); + RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kUnsupportedMethod)); continue; } if (result != S_OK) diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.cpp index edd276bc1..3f420a513 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.cpp @@ -106,8 +106,8 @@ STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSiz STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value) { *value = 0; - int index2 = (int)subStream; - if (index2 < 0 || subStream > Sizes.Size()) + unsigned index2 = (unsigned)subStream; + if (subStream > Sizes.Size()) return E_FAIL; if (index2 < Sizes.Size()) { diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.h b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.h index 6df3672a1..4ed4b2dd2 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.h @@ -47,7 +47,7 @@ public: UInt64 GetFullSize() const { UInt64 size = 0; - for (int i = 0; i < Sizes.Size(); i++) + FOR_VECTOR (i, Sizes) size += Sizes[i]; return size; } diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.cpp index 22c4600ec..847f65bf2 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.cpp @@ -14,7 +14,7 @@ CFolderOutStream::CFolderOutStream() } HRESULT CFolderOutStream::Init( - const CArchiveDatabaseEx *db, + const CDbEx *db, UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.h b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.h index f9bb1af42..cc2d77343 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.h @@ -19,12 +19,12 @@ class CFolderOutStream: { COutStreamWithCRC *_crcStreamSpec; CMyComPtr _crcStream; - const CArchiveDatabaseEx *_db; + const CDbEx *_db; const CBoolVector *_extractStatuses; CMyComPtr _extractCallback; UInt32 _ref2Offset; UInt32 _startIndex; - int _currentIndex; + unsigned _currentIndex; bool _testMode; bool _checkCrc; bool _fileIsOpen; @@ -43,7 +43,7 @@ public: STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); HRESULT Init( - const CArchiveDatabaseEx *db, + const CDbEx *db, UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.cpp index 4ab7afa87..ed65dc20c 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.cpp @@ -23,26 +23,23 @@ #endif using namespace NWindows; - -extern UString ConvertMethodIdToString(UInt64 id); +using namespace NCOM; namespace NArchive { namespace N7z { CHandler::CHandler() { - _crcSize = 4; - #ifndef _NO_CRYPTO + _isEncrypted = false; _passwordIsDefined = false; #endif #ifdef EXTRACT_ONLY + _crcSize = 4; #ifdef __7Z_SET_PROPERTIES _numThreads = NSystem::GetNumberOfProcessors(); #endif - #else - Init(); #endif } @@ -54,11 +51,12 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) #ifdef _SFX -IMP_IInArchive_ArcProps_NO +IMP_IInArchive_ArcProps_NO_Table -STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */) +STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) { - return E_NOTIMPL; + *numProps = 0; + return S_OK; } STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */, @@ -67,162 +65,502 @@ STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */, return E_NOTIMPL; } - #else -STATPROPSTG kArcProps[] = +static const Byte kArcProps[] = { - { NULL, kpidMethod, VT_BSTR}, - { NULL, kpidSolid, VT_BOOL}, - { NULL, kpidNumBlocks, VT_UI4}, - { NULL, kpidPhySize, VT_UI8}, - { NULL, kpidHeadersSize, VT_UI8}, - { NULL, kpidOffset, VT_UI8} + kpidHeadersSize, + kpidMethod, + kpidSolid, + kpidNumBlocks + // , kpidIsTree }; +IMP_IInArchive_ArcProps + +static inline char GetHex(unsigned value) +{ + return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} + +static unsigned ConvertMethodIdToString_Back(char *s, UInt64 id) +{ + int len = 0; + do + { + s[--len] = GetHex((unsigned)id & 0xF); id >>= 4; + s[--len] = GetHex((unsigned)id & 0xF); id >>= 4; + } + while (id != 0); + return (unsigned)-len; +} + +static void ConvertMethodIdToString(AString &res, UInt64 id) +{ + const unsigned kLen = 32; + char s[kLen]; + unsigned len = kLen - 1; + s[len] = 0; + res += s + len - ConvertMethodIdToString_Back(s + len, id); +} + +static unsigned GetStringForSizeValue(char *s, UInt32 val) +{ + unsigned i; + for (i = 0; i <= 31; i++) + if (((UInt32)1 << i) == val) + { + if (i < 10) + { + s[0] = (char)('0' + i); + s[1] = 0; + return 1; + } + if (i < 20) { s[0] = '1'; s[1] = (char)('0' + i - 10); } + else if (i < 30) { s[0] = '2'; s[1] = (char)('0' + i - 20); } + else { s[0] = '3'; s[1] = (char)('0' + i - 30); } + s[2] = 0; + return 2; + } + char c = 'b'; + if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; } + else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; } + ::ConvertUInt32ToString(val, s); + unsigned pos = MyStringLen(s); + s[pos++] = c; + s[pos] = 0; + return pos; +} + +/* +static inline void AddHexToString(UString &res, Byte value) +{ + res += GetHex((Byte)(value >> 4)); + res += GetHex((Byte)(value & 0xF)); +} +*/ + +static char *AddProp32(char *s, const char *name, UInt32 v) +{ + *s++ = ':'; + s = MyStpCpy(s, name); + ::ConvertUInt32ToString(v, s); + return s + MyStringLen(s); +} + +void CHandler::AddMethodName(AString &s, UInt64 id) +{ + UString methodName; + FindMethod(EXTERNAL_CODECS_VARS id, methodName); + if (methodName.IsEmpty()) + { + for (unsigned i = 0; i < methodName.Len(); i++) + if (methodName[i] >= 0x80) + { + methodName.Empty(); + break; + } + } + if (methodName.IsEmpty()) + ConvertMethodIdToString(s, id); + else + for (unsigned i = 0; i < methodName.Len(); i++) + s += (char)methodName[i]; +} + +#endif + STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { + #ifndef _SFX COM_TRY_BEGIN + #endif NCOM::CPropVariant prop; - switch(propID) + switch (propID) { + #ifndef _SFX case kpidMethod: { - UString resString; - CRecordVector ids; - int i; - for (i = 0; i < _db.Folders.Size(); i++) - { - const CFolder &f = _db.Folders[i]; - for (int j = f.Coders.Size() - 1; j >= 0; j--) - ids.AddToUniqueSorted(f.Coders[j].MethodID); - } - - for (i = 0; i < ids.Size(); i++) + AString s; + const CParsedMethods &pm = _db.ParsedMethods; + FOR_VECTOR (i, pm.IDs) { - UInt64 id = ids[i]; - UString methodName; - /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName); - if (methodName.IsEmpty()) - methodName = ConvertMethodIdToString(id); - if (!resString.IsEmpty()) - resString += L' '; - resString += methodName; + UInt64 id = pm.IDs[i]; + if (!s.IsEmpty()) + s += ' '; + char temp[16]; + if (id == k_LZMA2) + { + s += "LZMA2:"; + if ((pm.Lzma2Prop & 1) == 0) + ConvertUInt32ToString((pm.Lzma2Prop >> 1) + 12, temp); + else + GetStringForSizeValue(temp, 3 << ((pm.Lzma2Prop >> 1) + 11)); + s += temp; + } + else if (id == k_LZMA) + { + s += "LZMA:"; + GetStringForSizeValue(temp, pm.LzmaDic); + s += temp; + } + else + AddMethodName(s, id); } - prop = resString; + prop = s; break; } case kpidSolid: prop = _db.IsSolid(); break; - case kpidNumBlocks: prop = (UInt32)_db.Folders.Size(); break; + case kpidNumBlocks: prop = (UInt32)_db.NumFolders; break; case kpidHeadersSize: prop = _db.HeadersSize; break; case kpidPhySize: prop = _db.PhySize; break; - case kpidOffset: if (_db.ArchiveInfo.StartPosition != 0) prop = _db.ArchiveInfo.StartPosition; break; + case kpidOffset: if (_db.ArcInfo.StartPosition != 0) prop = _db.ArcInfo.StartPosition; break; + /* + case kpidIsTree: if (_db.IsTree) prop = true; break; + case kpidIsAltStream: if (_db.ThereAreAltStreams) prop = true; break; + case kpidIsAux: if (_db.IsTree) prop = true; break; + */ + // case kpidError: if (_db.ThereIsHeaderError) prop = "Header error"; break; + #endif + + case kpidWarningFlags: + { + UInt32 v = 0; + if (_db.StartHeaderWasRecovered) v |= kpv_ErrorFlags_HeadersError; + if (_db.UnsupportedFeatureWarning) v |= kpv_ErrorFlags_UnsupportedFeature; + if (v != 0) + prop = v; + break; + } + + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_db.IsArc) v |= kpv_ErrorFlags_IsNotArc; + if (_db.ThereIsHeaderError) v |= kpv_ErrorFlags_HeadersError; + if (_db.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd; + // if (_db.UnsupportedVersion) v |= kpv_ErrorFlags_Unsupported; + if (_db.UnsupportedFeatureError) v |= kpv_ErrorFlags_UnsupportedFeature; + prop = v; + break; + } } prop.Detach(value); return S_OK; + #ifndef _SFX COM_TRY_END + #endif } -IMP_IInArchive_ArcProps - -#endif - -static void SetPropFromUInt64Def(CUInt64DefVector &v, int index, NCOM::CPropVariant &prop) +static void SetFileTimeProp_From_UInt64Def(PROPVARIANT *prop, const CUInt64DefVector &v, int index) { UInt64 value; if (v.GetItem(index, value)) + PropVarEm_Set_FileTime64(prop, value); +} + +bool CHandler::IsFolderEncrypted(CNum folderIndex) const +{ + if (folderIndex == kNumNoIndex) + return false; + size_t startPos = _db.FoCodersDataOffset[folderIndex]; + const Byte *p = _db.CodersData + startPos; + size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos; + CInByte2 inByte; + inByte.Init(p, size); + + CNum numCoders = inByte.ReadNum(); + for (; numCoders != 0; numCoders--) { - FILETIME ft; - ft.dwLowDateTime = (DWORD)value; - ft.dwHighDateTime = (DWORD)(value >> 32); - prop = ft; + Byte mainByte = inByte.ReadByte(); + unsigned idSize = (mainByte & 0xF); + const Byte *longID = inByte.GetPtr(); + UInt64 id64 = 0; + for (unsigned j = 0; j < idSize; j++) + id64 = ((id64 << 8) | longID[j]); + inByte.SkipDataNoCheck(idSize); + if (id64 == k_AES) + return true; + if ((mainByte & 0x20) != 0) + inByte.SkipDataNoCheck(inByte.ReadNum()); } + return false; } -#ifndef _SFX +STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps) +{ + *numProps = 0; + return S_OK; +} -static UString ConvertUInt32ToString(UInt32 value) +STDMETHODIMP CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID) { - wchar_t buffer[32]; - ConvertUInt64ToString(value, buffer); - return buffer; + *name = NULL; + *propID = kpidNtSecure; + return S_OK; } -static UString GetStringForSizeValue(UInt32 value) +STDMETHODIMP CHandler::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType) { - for (int i = 31; i >= 0; i--) - if ((UInt32(1) << i) == value) - return ConvertUInt32ToString(i); - UString result; - if (value % (1 << 20) == 0) - { - result += ConvertUInt32ToString(value >> 20); - result += L"m"; - } - else if (value % (1 << 10) == 0) + /* + const CFileItem &file = _db.Files[index]; + *parentType = (file.IsAltStream ? NParentType::kAltStream : NParentType::kDir); + *parent = (UInt32)(Int32)file.Parent; + */ + *parentType = NParentType::kDir; + *parent = (UInt32)(Int32)-1; + return S_OK; +} + +STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) +{ + *data = NULL; + *dataSize = 0; + *propType = 0; + + if (/* _db.IsTree && propID == kpidName || + !_db.IsTree && */ propID == kpidPath) { - result += ConvertUInt32ToString(value >> 10); - result += L"k"; + if (_db.NameOffsets && _db.NamesBuf) + { + size_t offset = _db.NameOffsets[index]; + size_t size = (_db.NameOffsets[index + 1] - offset) * 2; + if (size < ((UInt32)1 << 31)) + { + *data = (const void *)(_db.NamesBuf + offset * 2); + *dataSize = (UInt32)size; + *propType = NPropDataType::kUtf16z; + } + } + return S_OK; } - else + /* + if (propID == kpidNtSecure) { - result += ConvertUInt32ToString(value); - result += L"b"; + if (index < (UInt32)_db.SecureIDs.Size()) + { + int id = _db.SecureIDs[index]; + size_t offs = _db.SecureOffsets[id]; + size_t size = _db.SecureOffsets[id + 1] - offs; + if (size >= 0) + { + *data = _db.SecureBuf + offs; + *dataSize = (UInt32)size; + *propType = NPropDataType::kRaw; + } + } } - return result; + */ + return S_OK; } -static const UInt64 k_Copy = 0x0; -static const UInt64 k_Delta = 3; -static const UInt64 k_LZMA2 = 0x21; -static const UInt64 k_LZMA = 0x030101; -static const UInt64 k_PPMD = 0x030401; +#ifndef _SFX -static wchar_t GetHex(Byte value) -{ - return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10))); -} -static inline void AddHexToString(UString &res, Byte value) +HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const { - res += GetHex((Byte)(value >> 4)); - res += GetHex((Byte)(value & 0xF)); + PropVariant_Clear(prop); + if (folderIndex == kNumNoIndex) + return S_OK; + // for (int ttt = 0; ttt < 1; ttt++) { + const unsigned kTempSize = 256; + char temp[kTempSize]; + unsigned pos = kTempSize; + temp[--pos] = 0; + + size_t startPos = _db.FoCodersDataOffset[folderIndex]; + const Byte *p = _db.CodersData + startPos; + size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos; + CInByte2 inByte; + inByte.Init(p, size); + + // numCoders == 0 ??? + CNum numCoders = inByte.ReadNum(); + bool needSpace = false; + for (; numCoders != 0; numCoders--, needSpace = true) + { + if (pos < 32) // max size of property + break; + Byte mainByte = inByte.ReadByte(); + unsigned idSize = (mainByte & 0xF); + const Byte *longID = inByte.GetPtr(); + UInt64 id64 = 0; + for (unsigned j = 0; j < idSize; j++) + id64 = ((id64 << 8) | longID[j]); + inByte.SkipDataNoCheck(idSize); + + if ((mainByte & 0x10) != 0) + { + inByte.ReadNum(); // NumInStreams + inByte.ReadNum(); // NumOutStreams + } + + CNum propsSize = 0; + const Byte *props = NULL; + if ((mainByte & 0x20) != 0) + { + propsSize = inByte.ReadNum(); + props = inByte.GetPtr(); + inByte.SkipDataNoCheck(propsSize); + } + + const char *name = NULL; + char s[32]; + s[0] = 0; + + if (id64 <= (UInt32)0xFFFFFFFF) + { + UInt32 id = (UInt32)id64; + if (id == k_LZMA) + { + name = "LZMA"; + if (propsSize == 5) + { + UInt32 dicSize = GetUi32((const Byte *)props + 1); + char *dest = s + GetStringForSizeValue(s, dicSize); + UInt32 d = props[0]; + if (d != 0x5D) + { + UInt32 lc = d % 9; + d /= 9; + UInt32 pb = d / 5; + UInt32 lp = d % 5; + if (lc != 3) dest = AddProp32(dest, "lc", lc); + if (lp != 0) dest = AddProp32(dest, "lp", lp); + if (pb != 2) dest = AddProp32(dest, "pb", pb); + } + } + } + else if (id == k_LZMA2) + { + name = "LZMA2"; + if (propsSize == 1) + { + Byte p = props[0]; + if ((p & 1) == 0) + ConvertUInt32ToString((UInt32)((p >> 1) + 12), s); + else + GetStringForSizeValue(s, 3 << ((p >> 1) + 11)); + } + } + else if (id == k_PPMD) + { + name = "PPMD"; + if (propsSize == 5) + { + Byte order = *props; + char *dest = s; + *dest++ = 'o'; + ConvertUInt32ToString(order, dest); + dest += MyStringLen(dest); + dest = MyStpCpy(dest, ":mem"); + GetStringForSizeValue(dest, GetUi32(props + 1)); + } + } + else if (id == k_Delta) + { + name = "Delta"; + if (propsSize == 1) + ConvertUInt32ToString((UInt32)props[0] + 1, s); + } + else if (id == k_BCJ2) name = "BCJ2"; + else if (id == k_BCJ) name = "BCJ"; + else if (id == k_AES) + { + name = "7zAES"; + if (propsSize >= 1) + { + Byte firstByte = props[0]; + UInt32 numCyclesPower = firstByte & 0x3F; + ConvertUInt32ToString(numCyclesPower, s); + } + } + } + + if (name) + { + unsigned nameLen = MyStringLen(name); + unsigned propsLen = MyStringLen(s); + unsigned totalLen = nameLen + propsLen; + if (propsLen != 0) + totalLen++; + if (needSpace) + totalLen++; + if (totalLen + 5 >= pos) + break; + pos -= totalLen; + MyStringCopy(temp + pos, name); + if (propsLen != 0) + { + char *dest = temp + pos + nameLen; + *dest++ = ':'; + MyStringCopy(dest, s); + } + if (needSpace) + temp[pos + totalLen - 1] = ' '; + } + else + { + UString methodName; + FindMethod(EXTERNAL_CODECS_VARS id64, methodName); + if (methodName.IsEmpty()) + { + for (unsigned j = 0; j < methodName.Len(); j++) + if (methodName[j] >= 0x80) + { + methodName.Empty(); + break; + } + } + if (needSpace) + temp[--pos] = ' '; + if (methodName.IsEmpty()) + pos -= ConvertMethodIdToString_Back(temp + pos, id64); + else + { + unsigned len = methodName.Len(); + if (len + 5 > pos) + break; + pos -= len; + for (unsigned i = 0; i < len; i++) + temp[pos + i] = (char)methodName[i]; + } + } + } + if (numCoders != 0 && pos >= 4) + { + temp[--pos] = ' '; + temp[--pos] = '.'; + temp[--pos] = '.'; + temp[--pos] = '.'; + } + return PropVarEm_Set_Str(prop, temp + pos); + // } } #endif -bool CHandler::IsEncrypted(UInt32 index2) const +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { - CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; - if (folderIndex != kNumNoIndex) - return _db.Folders[folderIndex].IsEncrypted(); - return false; -} + PropVariant_Clear(value); + // COM_TRY_BEGIN + // NCOM::CPropVariant prop; -STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) -{ - COM_TRY_BEGIN - NCOM::CPropVariant prop; - /* const CRef2 &ref2 = _refs[index]; if (ref2.Refs.IsEmpty()) return E_FAIL; const CRef &ref = ref2.Refs.Front(); */ - + const CFileItem &item = _db.Files[index]; UInt32 index2 = index; switch(propID) { - case kpidPath: - if (!item.Name.IsEmpty()) - prop = NItemName::GetOSName(item.Name); - break; - case kpidIsDir: prop = item.IsDir; break; + case kpidIsDir: PropVarEm_Set_Bool(value, item.IsDir); break; case kpidSize: { - prop = item.Size; + PropVarEm_Set_UInt64(value, item.Size); // prop = ref2.Size; break; } @@ -234,122 +572,49 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va if (folderIndex != kNumNoIndex) { if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2) - prop = _db.GetFolderFullPackSize(folderIndex); + PropVarEm_Set_UInt64(value, _db.GetFolderFullPackSize(folderIndex)); /* else - prop = (UInt64)0; + PropVarEm_Set_UInt64(value, 0); */ } else - prop = (UInt64)0; + PropVarEm_Set_UInt64(value, 0); } break; } - case kpidPosition: { UInt64 v; if (_db.StartPos.GetItem(index2, v)) prop = v; break; } - case kpidCTime: SetPropFromUInt64Def(_db.CTime, index2, prop); break; - case kpidATime: SetPropFromUInt64Def(_db.ATime, index2, prop); break; - case kpidMTime: SetPropFromUInt64Def(_db.MTime, index2, prop); break; - case kpidAttrib: if (item.AttribDefined) prop = item.Attrib; break; - case kpidCRC: if (item.CrcDefined) prop = item.Crc; break; - case kpidEncrypted: prop = IsEncrypted(index2); break; - case kpidIsAnti: prop = _db.IsItemAnti(index2); break; - #ifndef _SFX - case kpidMethod: + // case kpidIsAux: prop = _db.IsItemAux(index2); break; + case kpidPosition: { UInt64 v; if (_db.StartPos.GetItem(index2, v)) PropVarEm_Set_UInt64(value, v); break; } + case kpidCTime: SetFileTimeProp_From_UInt64Def(value, _db.CTime, index2); break; + case kpidATime: SetFileTimeProp_From_UInt64Def(value, _db.ATime, index2); break; + case kpidMTime: SetFileTimeProp_From_UInt64Def(value, _db.MTime, index2); break; + case kpidAttrib: if (item.AttribDefined) PropVarEm_Set_UInt32(value, item.Attrib); break; + case kpidCRC: if (item.CrcDefined) PropVarEm_Set_UInt32(value, item.Crc); break; + case kpidEncrypted: PropVarEm_Set_Bool(value, IsFolderEncrypted(_db.FileIndexToFolderIndexMap[index2])); break; + case kpidIsAnti: PropVarEm_Set_Bool(value, _db.IsItemAnti(index2)); break; + /* + case kpidIsAltStream: prop = item.IsAltStream; break; + case kpidNtSecure: { - CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; - if (folderIndex != kNumNoIndex) + int id = _db.SecureIDs[index]; + size_t offs = _db.SecureOffsets[id]; + size_t size = _db.SecureOffsets[id + 1] - offs; + if (size >= 0) { - const CFolder &folderInfo = _db.Folders[folderIndex]; - UString methodsString; - for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) - { - const CCoderInfo &coder = folderInfo.Coders[i]; - if (!methodsString.IsEmpty()) - methodsString += L' '; - - UString methodName, propsString; - bool methodIsKnown = FindMethod( - EXTERNAL_CODECS_VARS - coder.MethodID, methodName); - - if (!methodIsKnown) - methodsString += ConvertMethodIdToString(coder.MethodID); - else - { - methodsString += methodName; - if (coder.MethodID == k_Delta && coder.Props.GetCapacity() == 1) - propsString = ConvertUInt32ToString((UInt32)coder.Props[0] + 1); - else if (coder.MethodID == k_LZMA && coder.Props.GetCapacity() == 5) - { - UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1); - propsString = GetStringForSizeValue(dicSize); - } - else if (coder.MethodID == k_LZMA2 && coder.Props.GetCapacity() == 1) - { - Byte p = coder.Props[0]; - UInt32 dicSize = (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)); - propsString = GetStringForSizeValue(dicSize); - } - else if (coder.MethodID == k_PPMD && coder.Props.GetCapacity() == 5) - { - Byte order = *(const Byte *)coder.Props; - propsString = L'o'; - propsString += ConvertUInt32ToString(order); - propsString += L":mem"; - UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1); - propsString += GetStringForSizeValue(dicSize); - } - else if (coder.MethodID == k_AES && coder.Props.GetCapacity() >= 1) - { - const Byte *data = (const Byte *)coder.Props; - Byte firstByte = *data++; - UInt32 numCyclesPower = firstByte & 0x3F; - propsString = ConvertUInt32ToString(numCyclesPower); - /* - if ((firstByte & 0xC0) != 0) - { - UInt32 saltSize = (firstByte >> 7) & 1; - UInt32 ivSize = (firstByte >> 6) & 1; - if (coder.Props.GetCapacity() >= 2) - { - Byte secondByte = *data++; - saltSize += (secondByte >> 4); - ivSize += (secondByte & 0x0F); - } - } - */ - } - } - if (!propsString.IsEmpty()) - { - methodsString += L':'; - methodsString += propsString; - } - else if (coder.Props.GetCapacity() > 0) - { - methodsString += L":["; - for (size_t bi = 0; bi < coder.Props.GetCapacity(); bi++) - { - if (bi > 5 && bi + 1 < coder.Props.GetCapacity()) - { - methodsString += L".."; - break; - } - else - AddHexToString(methodsString, coder.Props[bi]); - } - methodsString += L']'; - } - } - prop = methodsString; + prop.SetBlob(_db.SecureBuf + offs, (ULONG)size); } + break; } - break; + */ + + case kpidPath: return _db.GetPath_Prop(index, value); + #ifndef _SFX + case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value); case kpidBlock: { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) - prop = (UInt32)folderIndex; + PropVarEm_Set_UInt32(value, (UInt32)folderIndex); } break; case kpidPackedSize0: @@ -358,6 +623,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va case kpidPackedSize3: case kpidPackedSize4: { + /* CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { @@ -372,13 +638,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va } else prop = (UInt64)0; + */ } break; #endif } - prop.Detach(value); + // prop.Detach(value); return S_OK; - COM_TRY_END + // COM_TRY_END } STDMETHODIMP CHandler::Open(IInStream *stream, @@ -390,6 +657,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, #ifndef _SFX _fileInfoPopIDs.Clear(); #endif + try { CMyComPtr openArchiveCallbackTemp = openArchiveCallback; @@ -397,31 +665,30 @@ STDMETHODIMP CHandler::Open(IInStream *stream, #ifndef _NO_CRYPTO CMyComPtr getTextPassword; if (openArchiveCallback) - { - openArchiveCallbackTemp.QueryInterface( - IID_ICryptoGetTextPassword, &getTextPassword); - } + openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); #endif + CInArchive archive; + _db.IsArc = false; RINOK(archive.Open(stream, maxCheckStartPosition)); - #ifndef _NO_CRYPTO - _passwordIsDefined = false; - UString password; - #endif + _db.IsArc = true; + HRESULT result = archive.ReadDatabase( - EXTERNAL_CODECS_VARS - _db - #ifndef _NO_CRYPTO - , getTextPassword, _passwordIsDefined - #endif - ); + EXTERNAL_CODECS_VARS + _db + #ifndef _NO_CRYPTO + , getTextPassword, _isEncrypted, _passwordIsDefined + #endif + ); RINOK(result); - _db.Fill(); + _inStream = stream; } catch(...) { Close(); + // return E_INVALIDARG; + // we must return out_of_memory here return S_FALSE; } // _inStream = stream; @@ -437,6 +704,10 @@ STDMETHODIMP CHandler::Close() COM_TRY_BEGIN _inStream.Release(); _db.Clear(); + #ifndef _NO_CRYPTO + _isEncrypted = false; + _passwordIsDefined = false; + #endif return S_OK; COM_TRY_END } @@ -444,16 +715,16 @@ STDMETHODIMP CHandler::Close() #ifdef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) { COM_TRY_BEGIN const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); _numThreads = numProcessors; - for (int i = 0; i < numProperties; i++) + for (UInt32 i = 0; i < numProps; i++) { UString name = names[i]; - name.MakeUpper(); + name.MakeLower_Ascii(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; @@ -461,9 +732,9 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v int index = ParseStringToUInt32(name, number); if (index == 0) { - if(name.Left(2).CompareNoCase(L"MT") == 0) + if (name.IsPrefixedBy(L"mt")) { - RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); + RINOK(ParseMtProp(name.Ptr(2), value, numProcessors, _numThreads)); continue; } else diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.h b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.h index 56062d464..677a3e10a 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.h @@ -18,6 +18,16 @@ namespace NArchive { namespace N7z { +const UInt32 k_Copy = 0x0; +const UInt32 k_Delta = 3; +const UInt32 k_LZMA2 = 0x21; +const UInt32 k_LZMA = 0x030101; +const UInt32 k_PPMD = 0x030401; +const UInt32 k_BCJ = 0x03030103; +const UInt32 k_BCJ2 = 0x0303011B; +const UInt32 k_Deflate = 0x040108; +const UInt32 k_BZip2 = 0x040202; + #ifndef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY @@ -31,11 +41,53 @@ namespace N7z { #endif +#ifndef EXTRACT_ONLY + +class COutHandler: public CMultiMethodProps +{ + HRESULT SetSolidFromString(const UString &s); + HRESULT SetSolidFromPROPVARIANT(const PROPVARIANT &value); +public: + bool _removeSfxBlock; + + UInt64 _numSolidFiles; + UInt64 _numSolidBytes; + bool _numSolidBytesDefined; + bool _solidExtension; + + bool _compressHeaders; + bool _encryptHeadersSpecified; + bool _encryptHeaders; + // bool _useParents; 9.26 + + CBoolPair Write_CTime; + CBoolPair Write_ATime; + CBoolPair Write_MTime; + + bool _volumeMode; + + void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } + void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } + void InitSolid() + { + InitSolidFiles(); + InitSolidSize(); + _solidExtension = false; + _numSolidBytesDefined = false; + } + + void InitProps(); + + COutHandler() { InitProps(); } + + HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); +}; + +#endif + class CHandler: - #ifndef EXTRACT_ONLY - public NArchive::COutHandler, - #endif public IInArchive, + public IArchiveGetRawProps, #ifdef __7Z_SET_PROPERTIES public ISetProperties, #endif @@ -44,9 +96,13 @@ class CHandler: #endif PUBLIC_ISetCompressCodecsInfo public CMyUnknownImp + #ifndef EXTRACT_ONLY + , public COutHandler + #endif { public: MY_QUERYINTERFACE_BEGIN2(IInArchive) + MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps) #ifdef __7Z_SET_PROPERTIES MY_QUERYINTERFACE_ENTRY(ISetProperties) #endif @@ -58,9 +114,10 @@ public: MY_ADDREF_RELEASE INTERFACE_IInArchive(;) + INTERFACE_IArchiveGetRawProps(;) #ifdef __7Z_SET_PROPERTIES - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties); + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); #endif #ifndef EXTRACT_ONLY @@ -73,13 +130,14 @@ public: private: CMyComPtr _inStream; - NArchive::N7z::CArchiveDatabaseEx _db; + NArchive::N7z::CDbEx _db; #ifndef _NO_CRYPTO + bool _isEncrypted; bool _passwordIsDefined; #endif #ifdef EXTRACT_ONLY - + #ifdef __7Z_SET_PROPERTIES UInt32 _numThreads; #endif @@ -87,27 +145,29 @@ private: UInt32 _crcSize; #else - + CRecordVector _binds; - HRESULT SetCompressionMethod(CCompressionMethodMode &method, + HRESULT PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m); + HRESULT SetHeaderMethod(CCompressionMethodMode &headerMethod); + void AddDefaultMethod(); + HRESULT SetMainMethod(CCompressionMethodMode &method, CObjectVector &methodsInfo #ifndef _7ZIP_ST , UInt32 numThreads #endif ); - HRESULT SetCompressionMethod( - CCompressionMethodMode &method, - CCompressionMethodMode &headerMethod); #endif - bool IsEncrypted(UInt32 index2) const; + bool IsFolderEncrypted(CNum folderIndex) const; #ifndef _SFX CRecordVector _fileInfoPopIDs; void FillPopIDs(); + void AddMethodName(AString &s, UInt64 id); + HRESULT SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const; #endif diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandlerOut.cpp index a8ccab6df..7de5b8140 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandlerOut.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandlerOut.cpp @@ -2,12 +2,9 @@ #include "StdAfx.h" -#include "../../../Windows/PropVariant.h" - #include "../../../Common/ComTry.h" #include "../../../Common/StringToInt.h" - -#include "../../ICoder.h" +#include "../../../Common/Wildcard.h" #include "../Common/ItemNameUtils.h" #include "../Common/ParseProperties.h" @@ -21,24 +18,19 @@ using namespace NWindows; namespace NArchive { namespace N7z { -static const wchar_t *kLZMAMethodName = L"LZMA"; -static const wchar_t *kCopyMethod = L"Copy"; -static const wchar_t *kDefaultMethodName = kLZMAMethodName; +static const wchar_t *k_LZMA_Name = L"LZMA"; +static const wchar_t *kDefaultMethodName = L"LZMA2"; +static const wchar_t *k_Copy_Name = L"Copy"; -static const UInt32 kLzmaAlgorithmX5 = 1; -static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; -static const UInt32 kDictionaryForHeaders = +static const wchar_t *k_MatchFinder_ForHeaders = L"BT2"; +static const UInt32 k_NumFastBytes_ForHeaders = 273; +static const UInt32 k_Level_ForHeaders = 5; +static const UInt32 k_Dictionary_ForHeaders = #ifdef UNDER_CE - 1 << 18 + 1 << 18; #else - 1 << 20 + 1 << 20; #endif -; -static const UInt32 kNumFastBytesForHeaders = 273; -static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5; - -static inline bool IsCopyMethod(const UString &methodName) - { return (methodName.CompareNoCase(kCopyMethod) == 0); } STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) { @@ -46,132 +38,112 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) return S_OK; } -HRESULT CHandler::SetCompressionMethod( - CCompressionMethodMode &methodMode, - CCompressionMethodMode &headerMethod) +HRESULT CHandler::PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m) { - HRESULT res = SetCompressionMethod(methodMode, _methods - #ifndef _7ZIP_ST - , _numThreads - #endif - ); - RINOK(res); - methodMode.Binds = _binds; + if (!FindMethod( + EXTERNAL_CODECS_VARS + m.MethodName, dest.Id, dest.NumInStreams, dest.NumOutStreams)) + return E_INVALIDARG; + (CProps &)dest = (CProps &)m; + return S_OK; +} - if (_compressHeaders) - { - // headerMethod.Methods.Add(methodMode.Methods.Back()); +HRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod) +{ + if (!_compressHeaders) + return S_OK; + COneMethodInfo m; + m.MethodName = k_LZMA_Name; + m.AddPropString(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders); + m.AddProp32(NCoderPropID::kLevel, k_Level_ForHeaders); + m.AddProp32(NCoderPropID::kNumFastBytes, k_NumFastBytes_ForHeaders); + m.AddProp32(NCoderPropID::kDictionarySize, k_Dictionary_ForHeaders); + m.AddNumThreadsProp(1); + + CMethodFull methodFull; + RINOK(PropsMethod_To_FullMethod(methodFull, m)); + headerMethod.Methods.Add(methodFull); + return S_OK; +} - CObjectVector headerMethodInfoVector; - COneMethodInfo oneMethodInfo; - oneMethodInfo.MethodName = kLZMAMethodName; - { - CProp prop; - prop.Id = NCoderPropID::kMatchFinder; - prop.Value = kLzmaMatchFinderForHeaders; - oneMethodInfo.Props.Add(prop); - } - { - CProp prop; - prop.Id = NCoderPropID::kAlgorithm; - prop.Value = kAlgorithmForHeaders; - oneMethodInfo.Props.Add(prop); - } - { - CProp prop; - prop.Id = NCoderPropID::kNumFastBytes; - prop.Value = (UInt32)kNumFastBytesForHeaders; - oneMethodInfo.Props.Add(prop); - } - { - CProp prop; - prop.Id = NCoderPropID::kDictionarySize; - prop.Value = (UInt32)kDictionaryForHeaders; - oneMethodInfo.Props.Add(prop); - } - headerMethodInfoVector.Add(oneMethodInfo); - HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector - #ifndef _7ZIP_ST - , 1 - #endif - ); - RINOK(res); +void CHandler::AddDefaultMethod() +{ + FOR_VECTOR (i, _methods) + { + UString &methodName = _methods[i].MethodName; + if (methodName.IsEmpty()) + methodName = kDefaultMethodName; + } + if (_methods.IsEmpty()) + { + COneMethodInfo m; + m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName); + _methods.Add(m); } - return S_OK; } -HRESULT CHandler::SetCompressionMethod( +HRESULT CHandler::SetMainMethod( CCompressionMethodMode &methodMode, - CObjectVector &methodsInfo + CObjectVector &methods #ifndef _7ZIP_ST , UInt32 numThreads #endif ) { - UInt32 level = _level; - - if (methodsInfo.IsEmpty()) - { - COneMethodInfo oneMethodInfo; - oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName); - methodsInfo.Add(oneMethodInfo); - } + AddDefaultMethod(); + + const UInt64 kSolidBytes_Min = (1 << 24); + const UInt64 kSolidBytes_Max = ((UInt64)1 << 32) - 1; bool needSolid = false; - for(int i = 0; i < methodsInfo.Size(); i++) + FOR_VECTOR (i, methods) { - COneMethodInfo &oneMethodInfo = methodsInfo[i]; - SetCompressionMethod2(oneMethodInfo + COneMethodInfo &oneMethodInfo = methods[i]; + SetGlobalLevelAndThreads(oneMethodInfo #ifndef _7ZIP_ST , numThreads #endif ); - if (!IsCopyMethod(oneMethodInfo.MethodName)) - needSolid = true; - CMethodFull methodFull; - - if (!FindMethod( - EXTERNAL_CODECS_VARS - oneMethodInfo.MethodName, methodFull.Id, methodFull.NumInStreams, methodFull.NumOutStreams)) - return E_INVALIDARG; - methodFull.Props = oneMethodInfo.Props; + RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo)); methodMode.Methods.Add(methodFull); - if (!_numSolidBytesDefined) + if (methodFull.Id != k_Copy) + needSolid = true; + + if (_numSolidBytesDefined) + continue; + + UInt32 dicSize; + switch (methodFull.Id) { - for (int j = 0; j < methodFull.Props.Size(); j++) - { - const CProp &prop = methodFull.Props[j]; - if ((prop.Id == NCoderPropID::kDictionarySize || - prop.Id == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4) - { - _numSolidBytes = ((UInt64)prop.Value.ulVal) << 7; - const UInt64 kMinSize = (1 << 24); - if (_numSolidBytes < kMinSize) - _numSolidBytes = kMinSize; - _numSolidBytesDefined = true; - break; - } - } + case k_LZMA: + case k_LZMA2: dicSize = oneMethodInfo.Get_Lzma_DicSize(); break; + case k_PPMD: dicSize = oneMethodInfo.Get_Ppmd_MemSize(); break; + case k_Deflate: dicSize = (UInt32)1 << 15; break; + case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break; + default: continue; } - } - - if (!needSolid && !_numSolidBytesDefined) - { + _numSolidBytes = (UInt64)dicSize << 7; + if (_numSolidBytes < kSolidBytes_Min) _numSolidBytes = kSolidBytes_Min; + if (_numSolidBytes > kSolidBytes_Max) _numSolidBytes = kSolidBytes_Max; _numSolidBytesDefined = true; - _numSolidBytes = 0; } + + if (!_numSolidBytesDefined) + if (needSolid) + _numSolidBytes = kSolidBytes_Max; + else + _numSolidBytes = 0; + _numSolidBytesDefined = true; return S_OK; } -static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, bool writeTime, PROPID propID, UInt64 &ft, bool &ftDefined) +static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, PROPID propID, UInt64 &ft, bool &ftDefined) { - ft = 0; - ftDefined = false; - if (!writeTime) - return S_OK; + // ft = 0; + // ftDefined = false; NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(index, propID, &prop)); if (prop.vt == VT_FILETIME) @@ -181,15 +153,87 @@ static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, bool w } else if (prop.vt != VT_EMPTY) return E_INVALIDARG; + else + { + ft = 0; + ftDefined = false; + } return S_OK; } +/* + +#ifdef _WIN32 +static const wchar_t kDirDelimiter1 = L'\\'; +#endif +static const wchar_t kDirDelimiter2 = L'/'; + +static inline bool IsCharDirLimiter(wchar_t c) +{ + return ( + #ifdef _WIN32 + c == kDirDelimiter1 || + #endif + c == kDirDelimiter2); +} + +static int FillSortIndex(CObjectVector &treeFolders, int cur, int curSortIndex) +{ + CTreeFolder &tf = treeFolders[cur]; + tf.SortIndex = curSortIndex++; + for (int i = 0; i < tf.SubFolders.Size(); i++) + curSortIndex = FillSortIndex(treeFolders, tf.SubFolders[i], curSortIndex); + tf.SortIndexEnd = curSortIndex; + return curSortIndex; +} + +static int FindSubFolder(const CObjectVector &treeFolders, int cur, const UString &name, int &insertPos) +{ + const CIntVector &subFolders = treeFolders[cur].SubFolders; + int left = 0, right = subFolders.Size(); + insertPos = -1; + for (;;) + { + if (left == right) + { + insertPos = left; + return -1; + } + int mid = (left + right) / 2; + int midFolder = subFolders[mid]; + int compare = CompareFileNames(name, treeFolders[midFolder].Name); + if (compare == 0) + return midFolder; + if (compare < 0) + right = mid; + else + left = mid + 1; + } +} + +static int AddFolder(CObjectVector &treeFolders, int cur, const UString &name) +{ + int insertPos; + int folderIndex = FindSubFolder(treeFolders, cur, name, insertPos); + if (folderIndex < 0) + { + folderIndex = treeFolders.Size(); + CTreeFolder &newFolder = treeFolders.AddNew(); + newFolder.Parent = cur; + newFolder.Name = name; + treeFolders[cur].SubFolders.Insert(insertPos, folderIndex); + } + // else if (treeFolders[folderIndex].IsAltStreamFolder != isAltStreamFolder) throw 1123234234; + return folderIndex; +} +*/ + STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) { COM_TRY_BEGIN - const CArchiveDatabaseEx *db = 0; + const CDbEx *db = 0; #ifdef _7Z_VOL if (_volumes.Size() > 1) return E_FAIL; @@ -204,8 +248,35 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt db = &_db; #endif + /* + CMyComPtr getRawProps; + updateCallback->QueryInterface(IID_IArchiveGetRawProps, (void **)&getRawProps); + + CUniqBlocks secureBlocks; + secureBlocks.AddUniq(NULL, 0); + + CObjectVector treeFolders; + { + CTreeFolder folder; + folder.Parent = -1; + treeFolders.Add(folder); + } + */ + CObjectVector updateItems; - + + bool need_CTime = (Write_CTime.Def && Write_CTime.Val); + bool need_ATime = (Write_ATime.Def && Write_ATime.Val); + bool need_MTime = (Write_MTime.Def && Write_MTime.Val || !Write_MTime.Def); + if (db) + { + if (!Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty(); + if (!Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty(); + if (!Write_MTime.Def) need_MTime = !db->MTime.Defs.IsEmpty(); + } + + UString s; + for (UInt32 i = 0; i < numItems; i++) { Int32 newData, newProps; @@ -221,24 +292,32 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt ui.IsAnti = false; ui.Size = 0; + UString name; + // bool isAltStream = false; if (ui.IndexInArchive != -1) { - if (db == 0 || ui.IndexInArchive >= db->Files.Size()) + if (db == 0 || (unsigned)ui.IndexInArchive >= db->Files.Size()) return E_INVALIDARG; const CFileItem &fi = db->Files[ui.IndexInArchive]; - ui.Name = fi.Name; + if (!ui.NewProps) + { + _db.GetPath(ui.IndexInArchive, name); + } ui.IsDir = fi.IsDir; ui.Size = fi.Size; + // isAltStream = fi.IsAltStream; ui.IsAnti = db->IsItemAnti(ui.IndexInArchive); - - ui.CTimeDefined = db->CTime.GetItem(ui.IndexInArchive, ui.CTime); - ui.ATimeDefined = db->ATime.GetItem(ui.IndexInArchive, ui.ATime); - ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime); + + if (!ui.NewProps) + { + ui.CTimeDefined = db->CTime.GetItem(ui.IndexInArchive, ui.CTime); + ui.ATimeDefined = db->ATime.GetItem(ui.IndexInArchive, ui.ATime); + ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime); + } } if (ui.NewProps) { - bool nameIsDefined; bool folderStatusIsDefined; { NCOM::CPropVariant prop; @@ -253,23 +332,37 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt ui.AttribDefined = true; } } - + // we need MTime to sort files. - RINOK(GetTime(updateCallback, i, WriteCTime, kpidCTime, ui.CTime, ui.CTimeDefined)); - RINOK(GetTime(updateCallback, i, WriteATime, kpidATime, ui.ATime, ui.ATimeDefined)); - RINOK(GetTime(updateCallback, i, true, kpidMTime, ui.MTime, ui.MTimeDefined)); + if (need_CTime) RINOK(GetTime(updateCallback, i, kpidCTime, ui.CTime, ui.CTimeDefined)); + if (need_ATime) RINOK(GetTime(updateCallback, i, kpidATime, ui.ATime, ui.ATimeDefined)); + if (need_MTime) RINOK(GetTime(updateCallback, i, kpidMTime, ui.MTime, ui.MTimeDefined)); + + /* + if (getRawProps) + { + const void *data; + UInt32 dataSize; + UInt32 propType; + + getRawProps->GetRawProp(i, kpidNtSecure, &data, &dataSize, &propType); + if (dataSize != 0 && propType != NPropDataType::kRaw) + return E_FAIL; + ui.SecureIndex = secureBlocks.AddUniq((const Byte *)data, dataSize); + } + */ { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidPath, &prop)); if (prop.vt == VT_EMPTY) - nameIsDefined = false; + { + } else if (prop.vt != VT_BSTR) return E_INVALIDARG; else { - ui.Name = NItemName::MakeLegalName(prop.bstrVal); - nameIsDefined = true; + name = NItemName::MakeLegalName(prop.bstrVal); } } { @@ -297,6 +390,19 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt ui.IsAnti = (prop.boolVal != VARIANT_FALSE); } + /* + { + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(i, kpidIsAltStream, &prop)); + if (prop.vt == VT_EMPTY) + isAltStream = false; + else if (prop.vt != VT_BOOL) + return E_INVALIDARG; + else + isAltStream = (prop.boolVal != VARIANT_FALSE); + } + */ + if (ui.IsAnti) { ui.AttribDefined = false; @@ -304,13 +410,87 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt ui.CTimeDefined = false; ui.ATimeDefined = false; ui.MTimeDefined = false; - + ui.Size = 0; } if (!folderStatusIsDefined && ui.AttribDefined) ui.SetDirStatusFromAttrib(); } + else + { + /* + if (_db.SecureIDs.IsEmpty()) + ui.SecureIndex = secureBlocks.AddUniq(NULL, 0); + else + { + int id = _db.SecureIDs[ui.IndexInArchive]; + size_t offs = _db.SecureOffsets[id]; + size_t size = _db.SecureOffsets[id + 1] - offs; + ui.SecureIndex = secureBlocks.AddUniq(_db.SecureBuf + offs, size); + } + */ + } + + /* + { + int folderIndex = 0; + if (_useParents) + { + int j; + s.Empty(); + for (j = 0; j < name.Len(); j++) + { + wchar_t c = name[j]; + if (IsCharDirLimiter(c)) + { + folderIndex = AddFolder(treeFolders, folderIndex, s); + s.Empty(); + continue; + } + s += c; + } + if (isAltStream) + { + int colonPos = s.Find(':'); + if (colonPos < 0) + { + // isAltStream = false; + return E_INVALIDARG; + } + UString mainName = s.Left(colonPos); + int newFolderIndex = AddFolder(treeFolders, folderIndex, mainName); + if (treeFolders[newFolderIndex].UpdateItemIndex < 0) + { + for (int j = updateItems.Size() - 1; j >= 0; j--) + { + CUpdateItem &ui2 = updateItems[j]; + if (ui2.ParentFolderIndex == folderIndex + && ui2.Name == mainName) + { + ui2.TreeFolderIndex = newFolderIndex; + treeFolders[newFolderIndex].UpdateItemIndex = j; + } + } + } + folderIndex = newFolderIndex; + s.Delete(0, colonPos + 1); + } + ui.Name = s; + } + else + ui.Name = name; + ui.IsAltStream = isAltStream; + ui.ParentFolderIndex = folderIndex; + ui.TreeFolderIndex = -1; + if (ui.IsDir && !s.IsEmpty()) + { + ui.TreeFolderIndex = AddFolder(treeFolders, folderIndex, s); + treeFolders[ui.TreeFolderIndex].UpdateItemIndex = updateItems.Size(); + } + } + */ + ui.Name = name; if (ui.NewData) { @@ -325,8 +505,27 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt updateItems.Add(ui); } + /* + FillSortIndex(treeFolders, 0, 0); + for (i = 0; i < (UInt32)updateItems.Size(); i++) + { + CUpdateItem &ui = updateItems[i]; + ui.ParentSortIndex = treeFolders[ui.ParentFolderIndex].SortIndex; + ui.ParentSortIndexEnd = treeFolders[ui.ParentFolderIndex].SortIndexEnd; + } + */ + CCompressionMethodMode methodMode, headerMethod; - RINOK(SetCompressionMethod(methodMode, headerMethod)); + + HRESULT res = SetMainMethod(methodMode, _methods + #ifndef _7ZIP_ST + , _numThreads + #endif + ); + RINOK(res); + methodMode.Binds = _binds; + + RINOK(SetHeaderMethod(headerMethod)); #ifndef _7ZIP_ST methodMode.NumThreads = _numThreads; headerMethod.NumThreads = 1; @@ -335,17 +534,17 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt CMyComPtr getPassword2; updateCallback->QueryInterface(IID_ICryptoGetTextPassword2, (void **)&getPassword2); + methodMode.PasswordIsDefined = false; + methodMode.Password.Empty(); if (getPassword2) { CMyComBSTR password; Int32 passwordIsDefined; RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password)); methodMode.PasswordIsDefined = IntToBool(passwordIsDefined); - if (methodMode.PasswordIsDefined) + if (methodMode.PasswordIsDefined && (BSTR)password) methodMode.Password = password; } - else - methodMode.PasswordIsDefined = false; bool compressMainHeader = _compressHeaders; // check it @@ -373,14 +572,17 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt CUpdateOptions options; options.Method = &methodMode; options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : 0; - options.UseFilters = _level != 0 && _autoFilter; - options.MaxFilter = _level >= 8; + int level = GetLevel(); + options.UseFilters = level != 0 && _autoFilter; + options.MaxFilter = level >= 8; options.HeaderOptions.CompressMainHeader = compressMainHeader; - options.HeaderOptions.WriteCTime = WriteCTime; - options.HeaderOptions.WriteATime = WriteATime; - options.HeaderOptions.WriteMTime = WriteMTime; - + /* + options.HeaderOptions.WriteCTime = Write_CTime; + options.HeaderOptions.WriteATime = Write_ATime; + options.HeaderOptions.WriteMTime = Write_MTime; + */ + options.NumSolidFiles = _numSolidFiles; options.NumSolidBytes = _numSolidBytes; options.SolidExtension = _solidExtension; @@ -388,12 +590,24 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt options.VolumeMode = _volumeMode; COutArchive archive; - CArchiveDatabase newDatabase; + CArchiveDatabaseOut newDatabase; CMyComPtr getPassword; updateCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getPassword); - - HRESULT res = Update( + + /* + if (secureBlocks.Sorted.Size() > 1) + { + secureBlocks.GetReverseMap(); + for (int i = 0; i < updateItems.Size(); i++) + { + int &secureIndex = updateItems[i].SecureIndex; + secureIndex = secureBlocks.BufIndexToSortedIndex[secureIndex]; + } + } + */ + + res = Update( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL volume ? volume->Stream: 0, @@ -403,6 +617,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt db, #endif updateItems, + // treeFolders, + // secureBlocks, archive, newDatabase, outStream, updateCallback, options #ifndef _NO_CRYPTO , getPassword @@ -426,7 +642,7 @@ static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream if (index == 0) return E_INVALIDARG; srcString.Delete(0, index); - if (srcString[0] == 'S') + if (srcString[0] == 's') { srcString.Delete(0); int index = ParseStringToUInt32(srcString, stream); @@ -437,38 +653,173 @@ static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream return S_OK; } -static HRESULT GetBindInfo(UString &srcString, CBind &bind) +void COutHandler::InitProps() { - RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream)); - if (srcString[0] != ':') - return E_INVALIDARG; - srcString.Delete(0); - RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream)); - if (!srcString.IsEmpty()) - return E_INVALIDARG; + CMultiMethodProps::Init(); + + _removeSfxBlock = false; + _compressHeaders = true; + _encryptHeadersSpecified = false; + _encryptHeaders = false; + // _useParents = false; + + Write_CTime.Init(); + Write_ATime.Init(); + Write_MTime.Init(); + + _volumeMode = false; + InitSolid(); +} + +HRESULT COutHandler::SetSolidFromString(const UString &s) +{ + UString s2 = s; + s2.MakeLower_Ascii(); + for (unsigned i = 0; i < s2.Len();) + { + const wchar_t *start = ((const wchar_t *)s2) + i; + const wchar_t *end; + UInt64 v = ConvertStringToUInt64(start, &end); + if (start == end) + { + if (s2[i++] != 'e') + return E_INVALIDARG; + _solidExtension = true; + continue; + } + i += (int)(end - start); + if (i == s2.Len()) + return E_INVALIDARG; + wchar_t c = s2[i++]; + if (c == 'f') + { + if (v < 1) + v = 1; + _numSolidFiles = v; + } + else + { + unsigned numBits; + switch (c) + { + case 'b': numBits = 0; break; + case 'k': numBits = 10; break; + case 'm': numBits = 20; break; + case 'g': numBits = 30; break; + case 't': numBits = 40; break; + default: return E_INVALIDARG; + } + _numSolidBytes = (v << numBits); + _numSolidBytesDefined = true; + } + } return S_OK; } -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) +HRESULT COutHandler::SetSolidFromPROPVARIANT(const PROPVARIANT &value) +{ + bool isSolid; + switch (value.vt) + { + case VT_EMPTY: isSolid = true; break; + case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break; + case VT_BSTR: + if (StringToBool(value.bstrVal, isSolid)) + break; + return SetSolidFromString(value.bstrVal); + default: return E_INVALIDARG; + } + if (isSolid) + InitSolid(); + else + _numSolidFiles = 1; + return S_OK; +} + +static HRESULT PROPVARIANT_to_BoolPair(const PROPVARIANT &prop, CBoolPair &dest) +{ + RINOK(PROPVARIANT_to_bool(prop, dest.Val)); + dest.Def = true; + return S_OK; +} + +HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) +{ + UString name = nameSpec; + name.MakeLower_Ascii(); + if (name.IsEmpty()) + return E_INVALIDARG; + + if (name[0] == L's') + { + name.Delete(0); + if (name.IsEmpty()) + return SetSolidFromPROPVARIANT(value); + if (value.vt != VT_EMPTY) + return E_INVALIDARG; + return SetSolidFromString(name); + } + + UInt32 number; + int index = ParseStringToUInt32(name, number); + UString realName = name.Ptr(index); + if (index == 0) + { + if (name.IsEqualTo("rsfx")) return PROPVARIANT_to_bool(value, _removeSfxBlock); + if (name.IsEqualTo("hc")) return PROPVARIANT_to_bool(value, _compressHeaders); + // if (name.IsEqualToNoCase(L"HS")) return PROPVARIANT_to_bool(value, _useParents); + + if (name.IsEqualTo("hcf")) + { + bool compressHeadersFull = true; + RINOK(PROPVARIANT_to_bool(value, compressHeadersFull)); + return compressHeadersFull ? S_OK: E_INVALIDARG; + } + + if (name.IsEqualTo("he")) + { + RINOK(PROPVARIANT_to_bool(value, _encryptHeaders)); + _encryptHeadersSpecified = true; + return S_OK; + } + + if (name.IsEqualTo("tc")) return PROPVARIANT_to_BoolPair(value, Write_CTime); + if (name.IsEqualTo("ta")) return PROPVARIANT_to_BoolPair(value, Write_ATime); + if (name.IsEqualTo("tm")) return PROPVARIANT_to_BoolPair(value, Write_MTime); + + if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode); + } + return CMultiMethodProps::SetProperty(name, value); +} + +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) { COM_TRY_BEGIN _binds.Clear(); - BeforeSetProperty(); + InitProps(); - for (int i = 0; i < numProperties; i++) + for (UInt32 i = 0; i < numProps; i++) { UString name = names[i]; - name.MakeUpper(); + name.MakeLower_Ascii(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; - if (name[0] == 'B') + if (name[0] == 'b') { + if (value.vt != VT_EMPTY) + return E_INVALIDARG; name.Delete(0); CBind bind; - RINOK(GetBindInfo(name, bind)); + RINOK(GetBindInfoPart(name, bind.OutCoder, bind.OutStream)); + if (name[0] != ':') + return E_INVALIDARG; + name.Delete(0); + RINOK(GetBindInfoPart(name, bind.InCoder, bind.InStream)); + if (!name.IsEmpty()) + return E_INVALIDARG; _binds.Add(bind); continue; } @@ -476,6 +827,47 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v RINOK(SetProperty(name, value)); } + unsigned numEmptyMethods = GetNumEmptyMethods(); + if (numEmptyMethods > 0) + { + unsigned k; + for (k = 0; k < _binds.Size(); k++) + { + const CBind &bind = _binds[k]; + if (bind.InCoder < (UInt32)numEmptyMethods || + bind.OutCoder < (UInt32)numEmptyMethods) + return E_INVALIDARG; + } + for (k = 0; k < _binds.Size(); k++) + { + CBind &bind = _binds[k]; + bind.InCoder -= (UInt32)numEmptyMethods; + bind.OutCoder -= (UInt32)numEmptyMethods; + } + _methods.DeleteFrontal(numEmptyMethods); + } + + AddDefaultMethod(); + + if (!_filterMethod.MethodName.IsEmpty()) + { + FOR_VECTOR (k, _binds) + { + CBind &bind = _binds[k]; + bind.InCoder++; + bind.OutCoder++; + } + _methods.Insert(0, _filterMethod); + } + + FOR_VECTOR (k, _binds) + { + const CBind &bind = _binds[k]; + if (bind.InCoder >= (UInt32)_methods.Size() || + bind.OutCoder >= (UInt32)_methods.Size()) + return E_INVALIDARG; + } + return S_OK; COM_TRY_END } diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.cpp index 5b5f2fb37..acff2fdd8 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.cpp @@ -1,6 +1,7 @@ // 7zHeader.cpp #include "StdAfx.h" + #include "7zHeader.h" namespace NArchive { @@ -11,4 +12,8 @@ Byte kSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; Byte kFinishSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C + 1}; #endif +// We can change signature. So file doesn't contain correct signature. +// struct SignatureInitializer { SignatureInitializer() { kSignature[0]--; } }; +// static SignatureInitializer g_SignatureInitializer; + }} diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.h b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.h index 30622b90e..61dad655d 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.h @@ -3,12 +3,12 @@ #ifndef __7Z_HEADER_H #define __7Z_HEADER_H -#include "../../../Common/Types.h" +#include "../../../Common/MyTypes.h" namespace NArchive { namespace N7z { -const int kSignatureSize = 6; +const unsigned kSignatureSize = 6; extern Byte kSignature[kSignatureSize]; // #define _7Z_VOL @@ -57,11 +57,11 @@ namespace NID kHeader, kArchiveProperties, - + kAdditionalStreamsInfo, kMainStreamsInfo, kFilesInfo, - + kPackInfo, kUnpackInfo, kSubStreamsInfo, @@ -82,13 +82,17 @@ namespace NID kCTime, kATime, kMTime, - kWinAttributes, + kWinAttrib, kComment, kEncodedHeader, kStartPos, kDummy + + // kNtSecure, + // kParent, + // kIsAux }; } diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.cpp index b11819616..28ec5e083 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.cpp @@ -2,6 +2,12 @@ #include "StdAfx.h" +#ifdef _WIN32 +#include +#else +#include +#endif + #include "../../../../C/7zCrc.h" #include "../../../../C/CpuArch.h" @@ -20,15 +26,21 @@ #define FORMAT_7Z_RECOVERY #endif +using namespace NWindows; +using namespace NCOM; + namespace NArchive { namespace N7z { -static void BoolVector_Fill_False(CBoolVector &v, int size) +static const UInt32 k_LZMA2 = 0x21; +static const UInt32 k_LZMA = 0x030101; + +static void BoolVector_Fill_False(CBoolVector &v, unsigned size) { - v.Clear(); - v.Reserve(size); - for (int i = 0; i < size; i++) - v.Add(false); + v.ClearAndSetSize(size); + bool *p = &v[0]; + for (unsigned i = 0; i < size; i++) + p[i] = false; } static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index) @@ -40,11 +52,11 @@ static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index) return res; } -bool CFolder::CheckStructure() const +bool CFolder::CheckStructure(unsigned numUnpackSizes) const { - const int kNumCodersMax = sizeof(UInt32) * 8; // don't change it - const int kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax - const int kNumBindsMax = 32; + const unsigned kNumCodersMax = sizeof(UInt32) * 8; // don't change it + const unsigned kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax + const unsigned kNumBindsMax = 32; if (Coders.Size() > kNumCodersMax || BindPairs.Size() > kNumBindsMax) return false; @@ -52,28 +64,28 @@ bool CFolder::CheckStructure() const { CBoolVector v; BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size()); - - int i; + + unsigned i; for (i = 0; i < BindPairs.Size(); i++) if (BoolVector_GetAndSet(v, BindPairs[i].InIndex)) return false; for (i = 0; i < PackStreams.Size(); i++) if (BoolVector_GetAndSet(v, PackStreams[i])) return false; - - BoolVector_Fill_False(v, UnpackSizes.Size()); + + BoolVector_Fill_False(v, numUnpackSizes); for (i = 0; i < BindPairs.Size(); i++) if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex)) return false; } - + UInt32 mask[kMaskSize]; - int i; + unsigned i; for (i = 0; i < kMaskSize; i++) mask[i] = 0; { - CIntVector inStreamToCoder, outStreamToCoder; + CUIntVector inStreamToCoder, outStreamToCoder; for (i = 0; i < Coders.Size(); i++) { CNum j; @@ -83,16 +95,16 @@ bool CFolder::CheckStructure() const for (j = 0; j < coder.NumOutStreams; j++) outStreamToCoder.Add(i); } - + for (i = 0; i < BindPairs.Size(); i++) { const CBindPair &bp = BindPairs[i]; mask[inStreamToCoder[bp.InIndex]] |= (1 << outStreamToCoder[bp.OutIndex]); } } - + for (i = 0; i < kMaskSize; i++) - for (int j = 0; j < kMaskSize; j++) + for (unsigned j = 0; j < kMaskSize; j++) if (((1 << j) & mask[i]) != 0) mask[i] |= mask[j]; @@ -104,43 +116,23 @@ bool CFolder::CheckStructure() const } class CInArchiveException {}; +class CUnsupportedFeatureException: public CInArchiveException {}; static void ThrowException() { throw CInArchiveException(); } static inline void ThrowEndOfData() { ThrowException(); } -static inline void ThrowUnsupported() { ThrowException(); } +static inline void ThrowUnsupported() { throw CUnsupportedFeatureException(); } static inline void ThrowIncorrect() { ThrowException(); } -static inline void ThrowUnsupportedVersion() { ThrowException(); } - -/* -class CInArchiveException -{ -public: - enum CCauseType - { - kUnsupportedVersion = 0, - kUnsupported, - kIncorrect, - kEndOfData - } Cause; - CInArchiveException(CCauseType cause): Cause(cause) {}; -}; - -static void ThrowException(CInArchiveException::CCauseType c) { throw CInArchiveException(c); } -static void ThrowEndOfData() { ThrowException(CInArchiveException::kEndOfData); } -static void ThrowUnsupported() { ThrowException(CInArchiveException::kUnsupported); } -static void ThrowIncorrect() { ThrowException(CInArchiveException::kIncorrect); } -static void ThrowUnsupportedVersion() { ThrowException(CInArchiveException::kUnsupportedVersion); } -*/ class CStreamSwitch { CInArchive *_archive; bool _needRemove; + bool _needUpdatePos; public: - CStreamSwitch(): _needRemove(false) {} + CStreamSwitch(): _needRemove(false), _needUpdatePos(false) {} ~CStreamSwitch() { Remove(); } void Remove(); - void Set(CInArchive *archive, const Byte *data, size_t size); + void Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos); void Set(CInArchive *archive, const CByteBuffer &byteBuffer); void Set(CInArchive *archive, const CObjectVector *dataVector); }; @@ -149,22 +141,25 @@ void CStreamSwitch::Remove() { if (_needRemove) { - _archive->DeleteByteStream(); + if (_archive->_inByteBack->GetRem() != 0) + _archive->ThereIsHeaderError = true; + _archive->DeleteByteStream(_needUpdatePos); _needRemove = false; } } -void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size) +void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos) { Remove(); _archive = archive; _archive->AddByteStream(data, size); _needRemove = true; + _needUpdatePos = needUpdatePos; } void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer) { - Set(archive, byteBuffer, byteBuffer.GetCapacity()); + Set(archive, byteBuffer, byteBuffer.Size(), false); } void CStreamSwitch::Set(CInArchive *archive, const CObjectVector *dataVector) @@ -173,13 +168,22 @@ void CStreamSwitch::Set(CInArchive *archive, const CObjectVector *d Byte external = archive->ReadByte(); if (external != 0) { - int dataIndex = (int)archive->ReadNum(); - if (dataIndex < 0 || dataIndex >= dataVector->Size()) + CNum dataIndex = archive->ReadNum(); + if (dataIndex >= dataVector->Size()) ThrowIncorrect(); Set(archive, (*dataVector)[dataIndex]); } } +void CInArchive::AddByteStream(const Byte *buf, size_t size) +{ + if (_numInByteBufs == kNumBufLevelsMax) + ThrowIncorrect(); + _inByteBack = &_inByteVector[_numInByteBufs++]; + _inByteBack->Init(buf, size); +} + + Byte CInByte2::ReadByte() { if (_pos >= _size) @@ -191,8 +195,8 @@ void CInByte2::ReadBytes(Byte *data, size_t size) { if (size > _size - _pos) ThrowEndOfData(); - for (size_t i = 0; i < size; i++) - data[i] = _buffer[_pos++]; + memcpy(data, _buffer + _pos, size); + _pos += size; } void CInByte2::SkipData(UInt64 size) @@ -207,31 +211,75 @@ void CInByte2::SkipData() SkipData(ReadNumber()); } -UInt64 CInByte2::ReadNumber() +static UInt64 ReadNumberSpec(const Byte *p, size_t size, size_t &processed) { - if (_pos >= _size) - ThrowEndOfData(); - Byte firstByte = _buffer[_pos++]; - Byte mask = 0x80; - UInt64 value = 0; - for (int i = 0; i < 8; i++) + if (size == 0) + { + processed = 0; + return 0; + } + Byte firstByte = *p++; + size--; + if ((firstByte & 0x80) == 0) + { + processed = 1; + return firstByte; + } + Byte mask = 0x40; + if (size == 0) + { + processed = 0; + return 0; + } + UInt64 value = (UInt64)*p; + p++; + size--; + for (unsigned i = 1; i < 8; i++) { if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); value += (highPart << (i * 8)); + processed = i + 1; return value; } - if (_pos >= _size) - ThrowEndOfData(); - value |= ((UInt64)_buffer[_pos++] << (8 * i)); + if (size == 0) + { + processed = 0; + return 0; + } + value |= ((UInt64)*p << (i * 8)); + p++; + size--; mask >>= 1; } + processed = 9; return value; } +UInt64 CInByte2::ReadNumber() +{ + size_t processed; + UInt64 res = ReadNumberSpec(_buffer + _pos, _size - _pos, processed); + if (processed == 0) + ThrowEndOfData(); + _pos += processed; + return res; +} + CNum CInByte2::ReadNum() { + /* + if (_pos < _size) + { + Byte val = _buffer[_pos]; + if ((unsigned)val < 0x80) + { + _pos++; + return (unsigned)val; + } + } + */ UInt64 value = ReadNumber(); if (value > kNumMax) ThrowUnsupported(); @@ -256,48 +304,21 @@ UInt64 CInByte2::ReadUInt64() return res; } -void CInByte2::ReadString(UString &s) -{ - const Byte *buf = _buffer + _pos; - size_t rem = (_size - _pos) / 2 * 2; - { - size_t i; - for (i = 0; i < rem; i += 2) - if (buf[i] == 0 && buf[i + 1] == 0) - break; - if (i == rem) - ThrowEndOfData(); - rem = i; - } - int len = (int)(rem / 2); - if (len < 0 || (size_t)len * 2 != rem) - ThrowUnsupported(); - wchar_t *p = s.GetBuffer(len); - int i; - for (i = 0; i < len; i++, buf += 2) - p[i] = (wchar_t)Get16(buf); - s.ReleaseBuffer(len); - _pos += rem + 2; -} +#define CHECK_SIGNATURE if (p[0] != '7' || p[1] != 'z' || p[2] != 0xBC || p[3] != 0xAF || p[4] != 0x27 || p[5] != 0x1C) return false; static inline bool TestSignature(const Byte *p) { - for (int i = 0; i < kSignatureSize; i++) - if (p[i] != kSignature[i]) - return false; - return CrcCalc(p + 12, 20) == GetUi32(p + 8); + CHECK_SIGNATURE + return CrcCalc(p + 12, 20) == Get32(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)) + CHECK_SIGNATURE; + if (CrcCalc(p + 12, 20) == Get32(p + 8)) return true; - for (i = 8; i < kHeaderSize; i++) + for (unsigned i = 8; i < kHeaderSize; i++) if (p[i] != 0) return false; return (p[6] != 0 || p[7] != 0); @@ -312,48 +333,52 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search if (TestSignature2(_header)) return S_OK; + if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0) + return S_FALSE; + + const UInt32 kBufSize = 1 << 15; + CByteArr buf(kBufSize); + memcpy(buf, _header, kHeaderSize); + UInt64 offset = 0; - CByteBuffer byteBuffer; - const UInt32 kBufferSize = (1 << 16); - byteBuffer.SetCapacity(kBufferSize); - Byte *buffer = byteBuffer; - UInt32 numPrevBytes = kHeaderSize; - memcpy(buffer, _header, kHeaderSize); - UInt64 curTestPos = _arhiveBeginStreamPosition; for (;;) { - if (searchHeaderSizeLimit != NULL) - if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit) - break; - do + UInt32 readSize = kBufSize - kHeaderSize; { - UInt32 numReadBytes = kBufferSize - numPrevBytes; - UInt32 processedSize; - RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize)); - numPrevBytes += processedSize; - if (processedSize == 0) + UInt64 rem = *searchHeaderSizeLimit - offset; + if (readSize > rem) + readSize = (UInt32)rem; + if (readSize == 0) return S_FALSE; } - while (numPrevBytes <= kHeaderSize); - UInt32 numTests = numPrevBytes - kHeaderSize; - for (UInt32 pos = 0; pos < numTests; pos++) + UInt32 processed = 0; + RINOK(stream->Read(buf + kHeaderSize, readSize, &processed)); + if (processed == 0) + return S_FALSE; + for (UInt32 pos = 0;;) { - for (; buffer[pos] != '7' && pos < numTests; pos++) {} - if (pos == numTests) + const Byte *p = buf + pos + 1; + const Byte *lim = buf + processed; + for (; p <= lim; p += 4) + { + if (p[0] == '7') break; + if (p[1] == '7') { p += 1; break; } + if (p[2] == '7') { p += 2; break; } + if (p[3] == '7') { p += 3; break; } + }; + if (p > lim) break; - if (TestSignature(buffer + pos)) + pos = (UInt32)(p - buf); + if (TestSignature(p)) { - memcpy(_header, buffer + pos, kHeaderSize); - curTestPos += pos; - _arhiveBeginStreamPosition = curTestPos; - return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL); + memcpy(_header, p, kHeaderSize); + _arhiveBeginStreamPosition += offset + pos; + return stream->Seek(_arhiveBeginStreamPosition + kHeaderSize, STREAM_SEEK_SET, NULL); } } - curTestPos += numTests; - numPrevBytes -= numTests; - memmove(buffer, buffer + numTests, numPrevBytes); + offset += processed; + memmove(buf, buf + processed, kHeaderSize); } - return S_FALSE; } // S_FALSE means that file is not archive @@ -362,14 +387,18 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) HeadersSize = 0; Close(); RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition)) + RINOK(stream->Seek(0, STREAM_SEEK_END, &_fileEndPosition)) + RINOK(stream->Seek(_arhiveBeginStreamPosition, STREAM_SEEK_SET, NULL)) RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit)); _stream = stream; return S_OK; } - + void CInArchive::Close() { + _numInByteBufs = 0; _stream.Release(); + ThereIsHeaderError = false; } void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) @@ -382,30 +411,32 @@ void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) } } -void CInArchive::GetNextFolderItem(CFolder &folder) +// CFolder &folder can be non empty. So we must set all fields + +void CInByte2::ParseFolder(CFolder &folder) { CNum numCoders = ReadNum(); - folder.Coders.Clear(); - folder.Coders.Reserve((int)numCoders); + folder.Coders.SetSize(numCoders); + CNum numInStreams = 0; CNum numOutStreams = 0; CNum i; for (i = 0; i < numCoders; i++) { - folder.Coders.Add(CCoderInfo()); - CCoderInfo &coder = folder.Coders.Back(); - + CCoderInfo &coder = folder.Coders[i]; { Byte mainByte = ReadByte(); - int idSize = (mainByte & 0xF); - Byte longID[15]; - ReadBytes(longID, idSize); - if (idSize > 8) + if ((mainByte & 0xC0) != 0) ThrowUnsupported(); + unsigned idSize = (mainByte & 0xF); + if (idSize > 8 || idSize > GetRem()) + ThrowUnsupported(); + const Byte *longID = GetPtr(); UInt64 id = 0; - for (int j = 0; j < idSize; j++) - id |= (UInt64)longID[idSize - 1 - j] << (8 * j); + for (unsigned j = 0; j < idSize; j++) + id = ((id << 8) | longID[j]); + SkipDataNoCheck(idSize); coder.MethodID = id; if ((mainByte & 0x10) != 0) @@ -421,53 +452,171 @@ void CInArchive::GetNextFolderItem(CFolder &folder) if ((mainByte & 0x20) != 0) { CNum propsSize = ReadNum(); - coder.Props.SetCapacity((size_t)propsSize); + coder.Props.Alloc((size_t)propsSize); ReadBytes((Byte *)coder.Props, (size_t)propsSize); } - if ((mainByte & 0x80) != 0) - ThrowUnsupported(); + else + coder.Props.Free(); } numInStreams += coder.NumInStreams; numOutStreams += coder.NumOutStreams; } CNum numBindPairs = numOutStreams - 1; - folder.BindPairs.Clear(); - folder.BindPairs.Reserve(numBindPairs); + folder.BindPairs.SetSize(numBindPairs); for (i = 0; i < numBindPairs; i++) { - CBindPair bp; + CBindPair &bp = folder.BindPairs[i]; bp.InIndex = ReadNum(); bp.OutIndex = ReadNum(); - folder.BindPairs.Add(bp); } if (numInStreams < numBindPairs) ThrowUnsupported(); CNum numPackStreams = numInStreams - numBindPairs; - folder.PackStreams.Reserve(numPackStreams); + folder.PackStreams.SetSize(numPackStreams); if (numPackStreams == 1) { for (i = 0; i < numInStreams; i++) if (folder.FindBindPairForInStream(i) < 0) { - folder.PackStreams.Add(i); + folder.PackStreams[0] = i; break; } - if (folder.PackStreams.Size() != 1) + if (i == numInStreams) ThrowUnsupported(); } else for (i = 0; i < numPackStreams; i++) - folder.PackStreams.Add(ReadNum()); + folder.PackStreams[i] = ReadNum(); +} + +void CFolders::ParseFolderInfo(unsigned folderIndex, CFolder &folder) const +{ + size_t startPos = FoCodersDataOffset[folderIndex]; + CInByte2 inByte; + inByte.Init(CodersData + startPos, FoCodersDataOffset[folderIndex + 1] - startPos); + inByte.ParseFolder(folder); + if (inByte.GetRem() != 0) + throw 20120424; +} + + +void CDatabase::GetPath(unsigned index, UString &path) const +{ + path.Empty(); + if (!NameOffsets || !NamesBuf) + return; + + size_t offset = NameOffsets[index]; + size_t size = NameOffsets[index + 1] - offset - 1; + + if (size >= (1 << 20)) + return; + + wchar_t *s = path.GetBuffer((unsigned)size); + + const Byte *p = ((const Byte *)NamesBuf + offset * 2); + + #if defined(_WIN32) && defined(MY_CPU_LE) + + wmemcpy(s, (const wchar_t *)p, size); + + #else + + for (size_t i = 0; i < size; i++) + { + *s = Get16(p); + p += 2; + s++; + } + + #endif + + path.ReleaseBuffer((unsigned)size); +} + +HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw() +{ + PropVariant_Clear(path); + if (!NameOffsets || !NamesBuf) + return S_OK; + + size_t offset = NameOffsets[index]; + size_t size = NameOffsets[index + 1] - offset; + + if (size >= (1 << 14)) + return S_OK; + + RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size - 1)); + wchar_t *s = path->bstrVal; + + const Byte *p = ((const Byte *)NamesBuf + offset * 2); + + for (size_t i = 0; i < size; i++) + { + wchar_t c = Get16(p); + p += 2; + #if WCHAR_PATH_SEPARATOR != L'/' + if (c == L'/') + c = WCHAR_PATH_SEPARATOR; + #endif + *s++ = c; + } + + return S_OK; + + /* + unsigned cur = index; + unsigned size = 0; + + for (int i = 0;; i++) + { + size_t len = NameOffsets[cur + 1] - NameOffsets[cur]; + size += (unsigned)len; + if (i > 256 || len > (1 << 14) || size > (1 << 14)) + return PropVarEm_Set_Str(path, "[TOO-LONG]"); + cur = Files[cur].Parent; + if (cur < 0) + break; + } + size--; + + RINOK(PropVarEm_Alloc_Bstr(path, size)); + wchar_t *s = path->bstrVal; + s += size; + *s = 0; + cur = index; + + for (;;) + { + unsigned len = (unsigned)(NameOffsets[cur + 1] - NameOffsets[cur] - 1); + const Byte *p = (const Byte *)NamesBuf + (NameOffsets[cur + 1] * 2) - 2; + do + { + p -= 2; + --s; + wchar_t c = Get16(p); + if (c == '/') + c = WCHAR_PATH_SEPARATOR; + *s = c; + } + while (--len); + const CFileItem &file = Files[cur]; + cur = file.Parent; + if (cur < 0) + return S_OK; + *(--s) = (file.IsAltStream ? ':' : WCHAR_PATH_SEPARATOR); + } + */ } -void CInArchive::WaitAttribute(UInt64 attribute) +void CInArchive::WaitId(UInt64 id) { for (;;) { UInt64 type = ReadID(); - if (type == attribute) + if (type == id) return; if (type == NID::kEnd) ThrowIncorrect(); @@ -475,91 +624,210 @@ void CInArchive::WaitAttribute(UInt64 attribute) } } -void CInArchive::ReadHashDigests(int numItems, - CBoolVector &digestsDefined, - CRecordVector &digests) +void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs) { - ReadBoolVector2(numItems, digestsDefined); - digests.Clear(); - digests.Reserve(numItems); - for (int i = 0; i < numItems; i++) + ReadBoolVector2(numItems, crcs.Defs); + crcs.Vals.ClearAndSetSize(numItems); + UInt32 *p = &crcs.Vals[0]; + const bool *defs = &crcs.Defs[0]; + for (unsigned i = 0; i < numItems; i++) { UInt32 crc = 0; - if (digestsDefined[i]) + if (defs[i]) crc = ReadUInt32(); - digests.Add(crc); + p[i] = crc; } } -void CInArchive::ReadPackInfo( - UInt64 &dataOffset, - CRecordVector &packSizes, - CBoolVector &packCRCsDefined, - CRecordVector &packCRCs) +void CInArchive::ReadPackInfo(CFolders &f) { - dataOffset = ReadNumber(); CNum numPackStreams = ReadNum(); - WaitAttribute(NID::kSize); - packSizes.Clear(); - packSizes.Reserve(numPackStreams); + WaitId(NID::kSize); + f.PackPositions.Alloc(numPackStreams + 1); + f.NumPackStreams = numPackStreams; + UInt64 sum = 0; for (CNum i = 0; i < numPackStreams; i++) - packSizes.Add(ReadNumber()); + { + f.PackPositions[i] = sum; + UInt64 packSize = ReadNumber(); + sum += packSize; + if (sum < packSize) + ThrowIncorrect(); + } + f.PackPositions[numPackStreams] = sum; UInt64 type; for (;;) { type = ReadID(); if (type == NID::kEnd) - break; + return; if (type == NID::kCRC) { - ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs); + CUInt32DefVector PackCRCs; + ReadHashDigests(numPackStreams, PackCRCs); continue; } SkipData(); } - if (packCRCsDefined.IsEmpty()) - { - BoolVector_Fill_False(packCRCsDefined, numPackStreams); - packCRCs.Reserve(numPackStreams); - packCRCs.Clear(); - for (CNum i = 0; i < numPackStreams; i++) - packCRCs.Add(0); - } } void CInArchive::ReadUnpackInfo( const CObjectVector *dataVector, - CObjectVector &folders) + CFolders &folders) { - WaitAttribute(NID::kFolder); + WaitId(NID::kFolder); CNum numFolders = ReadNum(); + CNum numCodersOutStreams = 0; { CStreamSwitch streamSwitch; streamSwitch.Set(this, dataVector); - folders.Clear(); - folders.Reserve(numFolders); - for (CNum i = 0; i < numFolders; i++) + const Byte *startBufPtr = _inByteBack->GetPtr(); + folders.NumFolders = numFolders; + + folders.FoStartPackStreamIndex.Alloc(numFolders + 1); + folders.FoToMainUnpackSizeIndex.Alloc(numFolders); + folders.FoCodersDataOffset.Alloc(numFolders + 1); + folders.FoToCoderUnpackSizes.Alloc(numFolders + 1); + + CRecordVector InStreamUsed; + CRecordVector OutStreamUsed; + + CNum packStreamIndex = 0; + CNum fo; + CInByte2 *inByte = _inByteBack; + for (fo = 0; fo < numFolders; fo++) { - folders.Add(CFolder()); - GetNextFolderItem(folders.Back()); - } - } + UInt32 numOutStreams = 0; + UInt32 indexOfMainStream = 0; + UInt32 numPackStreams = 0; + folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr; + + numOutStreams = 0; + CNum numInStreams = 0; + CNum numCoders = inByte->ReadNum(); + for (CNum ci = 0; ci < numCoders; ci++) + { + Byte mainByte = inByte->ReadByte(); + if ((mainByte & 0xC0) != 0) + ThrowUnsupported(); + unsigned idSize = (mainByte & 0xF); + if (idSize > 8) + ThrowUnsupported(); + if (idSize > inByte->GetRem()) + ThrowEndOfData(); + const Byte *longID = inByte->GetPtr(); + UInt64 id = 0; + for (unsigned j = 0; j < idSize; j++) + id = ((id << 8) | longID[j]); + inByte->SkipDataNoCheck(idSize); + if (folders.ParsedMethods.IDs.Size() < 128) + folders.ParsedMethods.IDs.AddToUniqueSorted(id); + CNum coderInStreams = 1; + CNum coderOutStreams = 1; + if ((mainByte & 0x10) != 0) + { + coderInStreams = inByte->ReadNum(); + coderOutStreams = inByte->ReadNum(); + } + numInStreams += coderInStreams; + if (numInStreams < coderInStreams) + ThrowUnsupported(); + numOutStreams += coderOutStreams; + if (numOutStreams < coderOutStreams) + ThrowUnsupported(); + if ((mainByte & 0x20) != 0) + { + CNum propsSize = inByte->ReadNum(); + if (propsSize > inByte->GetRem()) + ThrowEndOfData(); + if (id == k_LZMA2 && propsSize == 1) + { + Byte v = *_inByteBack->GetPtr(); + if (folders.ParsedMethods.Lzma2Prop < v) + folders.ParsedMethods.Lzma2Prop = v; + } + else if (id == k_LZMA && propsSize == 5) + { + UInt32 dicSize = GetUi32(_inByteBack->GetPtr() + 1); + if (folders.ParsedMethods.LzmaDic < dicSize) + folders.ParsedMethods.LzmaDic = dicSize; + } + inByte->SkipDataNoCheck((size_t)propsSize); + } + } + + if (numOutStreams == 1 && numInStreams == 1) + { + indexOfMainStream = 0; + numPackStreams = 1; + } + else + { + UInt32 i; + if (numOutStreams == 0) + ThrowUnsupported(); + CNum numBindPairs = numOutStreams - 1; + if (numInStreams < numBindPairs) + ThrowUnsupported(); + if (numInStreams >= 256 || numOutStreams >= 256) + ThrowUnsupported(); + + InStreamUsed.ClearAndSetSize(numInStreams); + for (i = 0; i < numInStreams; i++) + InStreamUsed[i] = false; + + OutStreamUsed.ClearAndSetSize(numOutStreams); + for (i = 0; i < numOutStreams; i++) + OutStreamUsed[i] = false; + + for (i = 0; i < numBindPairs; i++) + { + CNum index = ReadNum(); + if (index >= numInStreams || InStreamUsed[index]) + ThrowUnsupported(); + InStreamUsed[index] = true; + index = ReadNum(); + if (index >= numOutStreams || OutStreamUsed[index]) + ThrowUnsupported(); + OutStreamUsed[index] = true; + } - WaitAttribute(NID::kCodersUnpackSize); + numPackStreams = numInStreams - numBindPairs; - CNum i; - for (i = 0; i < numFolders; i++) - { - CFolder &folder = folders[i]; - CNum numOutStreams = folder.GetNumOutStreams(); - folder.UnpackSizes.Reserve(numOutStreams); - for (CNum j = 0; j < numOutStreams; j++) - folder.UnpackSizes.Add(ReadNumber()); + if (numPackStreams != 1) + for (i = 0; i < numPackStreams; i++) + inByte->ReadNum(); // PackStreams + + for (i = 0; i < numOutStreams; i++) + if (!OutStreamUsed[i]) + { + indexOfMainStream = i; + break; + } + if (i == numOutStreams) + ThrowUnsupported(); + } + folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams; + numCodersOutStreams += numOutStreams; + folders.FoStartPackStreamIndex[fo] = packStreamIndex; + packStreamIndex += numPackStreams; + folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream; + } + size_t dataSize = _inByteBack->GetPtr() - startBufPtr; + folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams; + folders.FoStartPackStreamIndex[fo] = packStreamIndex; + folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr; + folders.CodersData.CopyFrom(startBufPtr, dataSize); } + WaitId(NID::kCodersUnpackSize); + folders.CoderUnpackSizes.Alloc(numCodersOutStreams); + for (CNum i = 0; i < numCodersOutStreams; i++) + folders.CoderUnpackSizes[i] = ReadNumber(); + for (;;) { UInt64 type = ReadID(); @@ -567,15 +835,7 @@ void CInArchive::ReadUnpackInfo( return; if (type == NID::kCRC) { - CBoolVector crcsDefined; - CRecordVector crcs; - ReadHashDigests(numFolders, crcsDefined, crcs); - for (i = 0; i < numFolders; i++) - { - CFolder &folder = folders[i]; - folder.UnpackCRCDefined = crcsDefined[i]; - folder.UnpackCRC = crcs[i]; - } + ReadHashDigests(numFolders, folders.FolderCRCs); continue; } SkipData(); @@ -583,170 +843,217 @@ void CInArchive::ReadUnpackInfo( } void CInArchive::ReadSubStreamsInfo( - const CObjectVector &folders, - CRecordVector &numUnpackStreamsInFolders, + CFolders &folders, CRecordVector &unpackSizes, - CBoolVector &digestsDefined, - CRecordVector &digests) + CUInt32DefVector &digests) { - numUnpackStreamsInFolders.Clear(); - numUnpackStreamsInFolders.Reserve(folders.Size()); + folders.NumUnpackStreamsVector.Alloc(folders.NumFolders); + CNum i; + for (i = 0; i < folders.NumFolders; i++) + folders.NumUnpackStreamsVector[i] = 1; + UInt64 type; + for (;;) { type = ReadID(); if (type == NID::kNumUnpackStream) { - for (int i = 0; i < folders.Size(); i++) - numUnpackStreamsInFolders.Add(ReadNum()); + for (i = 0; i < folders.NumFolders; i++) + folders.NumUnpackStreamsVector[i] = ReadNum(); continue; } - if (type == NID::kCRC || type == NID::kSize) - break; - if (type == NID::kEnd) + if (type == NID::kCRC || type == NID::kSize || type == NID::kEnd) break; SkipData(); } - if (numUnpackStreamsInFolders.IsEmpty()) - for (int i = 0; i < folders.Size(); i++) - numUnpackStreamsInFolders.Add(1); - - int i; - for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) + if (type == NID::kSize) { - // v3.13 incorrectly worked with empty folders - // v4.07: we check that folder is empty - CNum numSubstreams = numUnpackStreamsInFolders[i]; - if (numSubstreams == 0) - continue; - UInt64 sum = 0; - for (CNum j = 1; j < numSubstreams; j++) - if (type == NID::kSize) + for (i = 0; i < folders.NumFolders; i++) + { + // v3.13 incorrectly worked with empty folders + // v4.07: we check that folder is empty + CNum numSubstreams = folders.NumUnpackStreamsVector[i]; + if (numSubstreams == 0) + continue; + UInt64 sum = 0; + for (CNum j = 1; j < numSubstreams; j++) { UInt64 size = ReadNumber(); unpackSizes.Add(size); sum += size; + if (sum < size) + ThrowIncorrect(); } - unpackSizes.Add(folders[i].GetUnpackSize() - sum); - } - if (type == NID::kSize) + UInt64 folderUnpackSize = folders.GetFolderUnpackSize(i); + if (folderUnpackSize < sum) + ThrowIncorrect(); + unpackSizes.Add(folderUnpackSize - sum); + } type = ReadID(); + } + else + { + for (i = 0; i < folders.NumFolders; i++) + { + /* v9.26 - v9.29 incorrectly worked: + if (folders.NumUnpackStreamsVector[i] == 0), it threw error */ + CNum val = folders.NumUnpackStreamsVector[i]; + if (val > 1) + ThrowIncorrect(); + if (val == 1) + unpackSizes.Add(folders.GetFolderUnpackSize(i)); + } + } - int numDigests = 0; - int numDigestsTotal = 0; - for (i = 0; i < folders.Size(); i++) + unsigned numDigests = 0; + for (i = 0; i < folders.NumFolders; i++) { - CNum numSubstreams = numUnpackStreamsInFolders[i]; - if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) + CNum numSubstreams = folders.NumUnpackStreamsVector[i]; + if (numSubstreams != 1 || !folders.FolderCRCs.ValidAndDefined(i)) numDigests += numSubstreams; - numDigestsTotal += numSubstreams; } for (;;) { + if (type == NID::kEnd) + break; if (type == NID::kCRC) { - CBoolVector digestsDefined2; - CRecordVector digests2; - ReadHashDigests(numDigests, digestsDefined2, digests2); - int digestIndex = 0; - for (i = 0; i < folders.Size(); i++) + // CUInt32DefVector digests2; + // ReadHashDigests(numDigests, digests2); + CBoolVector digests2; + ReadBoolVector2(numDigests, digests2); + + digests.ClearAndSetSize(unpackSizes.Size()); + + unsigned k = 0; + unsigned k2 = 0; + + for (i = 0; i < folders.NumFolders; i++) { - CNum numSubstreams = numUnpackStreamsInFolders[i]; - const CFolder &folder = folders[i]; - if (numSubstreams == 1 && folder.UnpackCRCDefined) + CNum numSubstreams = folders.NumUnpackStreamsVector[i]; + if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i)) { - digestsDefined.Add(true); - digests.Add(folder.UnpackCRC); + digests.Defs[k] = true; + digests.Vals[k] = folders.FolderCRCs.Vals[i]; + k++; + } + else for (CNum j = 0; j < numSubstreams; j++) + { + bool defined = digests2[k2++]; + digests.Defs[k] = defined; + UInt32 crc = 0; + if (defined) + crc = ReadUInt32(); + digests.Vals[k] = crc; + k++; } - else - for (CNum j = 0; j < numSubstreams; j++, digestIndex++) - { - digestsDefined.Add(digestsDefined2[digestIndex]); - digests.Add(digests2[digestIndex]); - } } + // if (k != unpackSizes.Size()) throw 1234567; } - else if (type == NID::kEnd) + else + SkipData(); + + type = ReadID(); + } + + if (digests.Defs.Size() != unpackSizes.Size()) + { + digests.ClearAndSetSize(unpackSizes.Size()); + unsigned k = 0; + for (i = 0; i < folders.NumFolders; i++) { - if (digestsDefined.IsEmpty()) + CNum numSubstreams = folders.NumUnpackStreamsVector[i]; + if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i)) { - BoolVector_Fill_False(digestsDefined, numDigestsTotal); - digests.Clear(); - for (int i = 0; i < numDigestsTotal; i++) - digests.Add(0); + digests.Defs[k] = true; + digests.Vals[k] = folders.FolderCRCs.Vals[i]; + k++; + } + else for (CNum j = 0; j < numSubstreams; j++) + { + digests.Defs[k] = false; + digests.Vals[k] = 0; + k++; } - return; } - else - SkipData(); - type = ReadID(); } } void CInArchive::ReadStreamsInfo( const CObjectVector *dataVector, UInt64 &dataOffset, - CRecordVector &packSizes, - CBoolVector &packCRCsDefined, - CRecordVector &packCRCs, - CObjectVector &folders, - CRecordVector &numUnpackStreamsInFolders, + CFolders &folders, CRecordVector &unpackSizes, - CBoolVector &digestsDefined, - CRecordVector &digests) + CUInt32DefVector &digests) { - for (;;) + UInt64 type = ReadID(); + + if (type == NID::kPackInfo) { - UInt64 type = ReadID(); - if (type > ((UInt32)1 << 30)) - ThrowIncorrect(); - switch((UInt32)type) + dataOffset = ReadNumber(); + ReadPackInfo(folders); + type = ReadID(); + } + + if (type == NID::kUnpackInfo) + { + ReadUnpackInfo(dataVector, folders); + type = ReadID(); + } + + if (folders.NumFolders != 0 && !folders.PackPositions) + { + // if there are folders, we need PackPositions also + folders.PackPositions.Alloc(1); + folders.PackPositions[0] = 0; + } + + if (type == NID::kSubStreamsInfo) + { + ReadSubStreamsInfo(folders, unpackSizes, digests); + type = ReadID(); + } + else + { + folders.NumUnpackStreamsVector.Alloc(folders.NumFolders); + /* If digests.Defs.Size() == 0, it means that there are no crcs. + So we don't need to fill digests with values. */ + // digests.Vals.ClearAndSetSize(folders.NumFolders); + // BoolVector_Fill_False(digests.Defs, folders.NumFolders); + for (CNum i = 0; i < folders.NumFolders; i++) { - case NID::kEnd: - return; - case NID::kPackInfo: - { - ReadPackInfo(dataOffset, packSizes, packCRCsDefined, packCRCs); - break; - } - case NID::kUnpackInfo: - { - ReadUnpackInfo(dataVector, folders); - break; - } - case NID::kSubStreamsInfo: - { - ReadSubStreamsInfo(folders, numUnpackStreamsInFolders, - unpackSizes, digestsDefined, digests); - break; - } - default: - ThrowIncorrect(); + folders.NumUnpackStreamsVector[i] = 1; + unpackSizes.Add(folders.GetFolderUnpackSize(i)); + // digests.Vals[i] = 0; } } + + if (type != NID::kEnd) + ThrowIncorrect(); } -void CInArchive::ReadBoolVector(int numItems, CBoolVector &v) +void CInArchive::ReadBoolVector(unsigned numItems, CBoolVector &v) { - v.Clear(); - v.Reserve(numItems); + v.ClearAndSetSize(numItems); Byte b = 0; Byte mask = 0; - for (int i = 0; i < numItems; i++) + bool *p = &v[0]; + for (unsigned i = 0; i < numItems; i++) { if (mask == 0) { b = ReadByte(); mask = 0x80; } - v.Add((b & mask) != 0); + p[i] = ((b & mask) != 0); mask >>= 1; } } -void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v) +void CInArchive::ReadBoolVector2(unsigned numItems, CBoolVector &v) { Byte allAreDefined = ReadByte(); if (allAreDefined == 0) @@ -754,27 +1061,30 @@ void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v) ReadBoolVector(numItems, v); return; } - v.Clear(); - v.Reserve(numItems); - for (int i = 0; i < numItems; i++) - v.Add(true); + v.ClearAndSetSize(numItems); + bool *p = &v[0]; + for (unsigned i = 0; i < numItems; i++) + p[i] = true; } void CInArchive::ReadUInt64DefVector(const CObjectVector &dataVector, - CUInt64DefVector &v, int numFiles) + CUInt64DefVector &v, unsigned numItems) { - ReadBoolVector2(numFiles, v.Defined); + ReadBoolVector2(numItems, v.Defs); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); - v.Values.Reserve(numFiles); - for (int i = 0; i < numFiles; i++) + v.Vals.ClearAndSetSize(numItems); + UInt64 *p = &v.Vals[0]; + const bool *defs = &v.Defs[0]; + + for (unsigned i = 0; i < numItems; i++) { UInt64 t = 0; - if (v.Defined[i]) + if (defs[i]) t = ReadUInt64(); - v.Values.Add(t); + p[i] = t; } } @@ -782,35 +1092,19 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector &dataVector - #ifndef _NO_CRYPTO - , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS_DECL ) { - CRecordVector packSizes; - CBoolVector packCRCsDefined; - CRecordVector packCRCs; - CObjectVector folders; - - CRecordVector numUnpackStreamsInFolders; + CFolders folders; CRecordVector unpackSizes; - CBoolVector digestsDefined; - CRecordVector digests; - + CUInt32DefVector digests; + ReadStreamsInfo(NULL, dataOffset, - packSizes, - packCRCsDefined, - packCRCs, folders, - numUnpackStreamsInFolders, unpackSizes, - digestsDefined, digests); - - // db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; - - CNum packIndex = 0; + CDecoder decoder( #ifdef _ST_MODE false @@ -818,134 +1112,107 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( true #endif ); - UInt64 dataStartPos = baseOffset + dataOffset; - for (int i = 0; i < folders.Size(); i++) + + for (CNum i = 0; i < folders.NumFolders; i++) { - const CFolder &folder = folders[i]; - dataVector.Add(CByteBuffer()); - CByteBuffer &data = dataVector.Back(); - UInt64 unpackSize64 = folder.GetUnpackSize(); + CByteBuffer &data = dataVector.AddNew(); + UInt64 unpackSize64 = folders.GetFolderUnpackSize(i); size_t unpackSize = (size_t)unpackSize64; if (unpackSize != unpackSize64) ThrowUnsupported(); - data.SetCapacity(unpackSize); - + data.Alloc(unpackSize); + CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream; CMyComPtr outStream = outStreamSpec; outStreamSpec->Init(data, unpackSize); - + HRESULT result = decoder.Decode( EXTERNAL_CODECS_LOC_VARS - _stream, dataStartPos, - &packSizes[packIndex], folder, outStream, NULL - #ifndef _NO_CRYPTO - , getTextPassword, passwordIsDefined - #endif + _stream, baseOffset + dataOffset, + folders, i, + outStream, NULL + _7Z_DECODER_CRYPRO_VARS #if !defined(_7ZIP_ST) && !defined(_SFX) , false, 1 #endif ); RINOK(result); - - if (folder.UnpackCRCDefined) - if (CrcCalc(data, unpackSize) != folder.UnpackCRC) + + if (folders.FolderCRCs.ValidAndDefined(i)) + if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i]) ThrowIncorrect(); - for (int j = 0; j < folder.PackStreams.Size(); j++) - { - UInt64 packSize = packSizes[packIndex++]; - dataStartPos += packSize; - HeadersSize += packSize; - } } + HeadersSize += folders.PackPositions[folders.NumPackStreams]; return S_OK; } HRESULT CInArchive::ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS - CArchiveDatabaseEx &db - #ifndef _NO_CRYPTO - , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined - #endif + CDbEx &db + _7Z_DECODER_CRYPRO_VARS_DECL ) { UInt64 type = ReadID(); if (type == NID::kArchiveProperties) { - ReadArchiveProperties(db.ArchiveInfo); + ReadArchiveProperties(db.ArcInfo); type = ReadID(); } - + CObjectVector dataVector; - + if (type == NID::kAdditionalStreamsInfo) { HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS - db.ArchiveInfo.StartPositionAfterHeader, - db.ArchiveInfo.DataStartPosition2, + db.ArcInfo.StartPositionAfterHeader, + db.ArcInfo.DataStartPosition2, dataVector - #ifndef _NO_CRYPTO - , getTextPassword, passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS ); RINOK(result); - db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; + db.ArcInfo.DataStartPosition2 += db.ArcInfo.StartPositionAfterHeader; type = ReadID(); } CRecordVector unpackSizes; - CBoolVector digestsDefined; - CRecordVector digests; - + CUInt32DefVector digests; + if (type == NID::kMainStreamsInfo) { ReadStreamsInfo(&dataVector, - db.ArchiveInfo.DataStartPosition, - db.PackSizes, - db.PackCRCsDefined, - db.PackCRCs, - db.Folders, - db.NumUnpackStreamsVector, + db.ArcInfo.DataStartPosition, + (CFolders &)db, unpackSizes, - digestsDefined, digests); - db.ArchiveInfo.DataStartPosition += db.ArchiveInfo.StartPositionAfterHeader; + db.ArcInfo.DataStartPosition += db.ArcInfo.StartPositionAfterHeader; type = ReadID(); } - else - { - for (int i = 0; i < db.Folders.Size(); i++) - { - db.NumUnpackStreamsVector.Add(1); - CFolder &folder = db.Folders[i]; - unpackSizes.Add(folder.GetUnpackSize()); - digestsDefined.Add(folder.UnpackCRCDefined); - digests.Add(folder.UnpackCRC); - } - } db.Files.Clear(); - if (type == NID::kEnd) - return S_OK; - if (type != NID::kFilesInfo) - ThrowIncorrect(); - + if (type == NID::kFilesInfo) + { + CNum numFiles = ReadNum(); + db.Files.ClearAndSetSize(numFiles); + CNum i; + /* db.Files.Reserve(numFiles); CNum i; for (i = 0; i < numFiles; i++) db.Files.Add(CFileItem()); + */ - db.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize); - if (!db.PackSizes.IsEmpty()) - db.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo); - if (numFiles > 0 && !digests.IsEmpty()) - db.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC); + db.ArcInfo.FileInfoPopIDs.Add(NID::kSize); + // if (!db.PackSizes.IsEmpty()) + db.ArcInfo.FileInfoPopIDs.Add(NID::kPackInfo); + if (numFiles > 0 && !digests.Defs.IsEmpty()) + db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC); CBoolVector emptyStreamVector; - BoolVector_Fill_False(emptyStreamVector, (int)numFiles); + BoolVector_Fill_False(emptyStreamVector, (unsigned)numFiles); CBoolVector emptyFileVector; CBoolVector antiFileVector; CNum numEmptyStreams = 0; @@ -956,7 +1223,10 @@ HRESULT CInArchive::ReadHeader( if (type == NID::kEnd) break; UInt64 size = ReadNumber(); - size_t ppp = _inByteBack->_pos; + if (size > _inByteBack->GetRem()) + ThrowIncorrect(); + CStreamSwitch switchProp; + switchProp.Set(this, _inByteBack->GetPtr(), (size_t)size, true); bool addPropIdToList = true; bool isKnownType = true; if (type > ((UInt32)1 << 30)) @@ -967,11 +1237,29 @@ HRESULT CInArchive::ReadHeader( { CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); - for (int i = 0; i < db.Files.Size(); i++) - _inByteBack->ReadString(db.Files[i].Name); + size_t rem = _inByteBack->GetRem(); + db.NamesBuf.Alloc(rem); + ReadBytes(db.NamesBuf, rem); + db.NameOffsets.Alloc(db.Files.Size() + 1); + size_t pos = 0; + unsigned i; + for (i = 0; i < db.Files.Size(); i++) + { + size_t curRem = (rem - pos) / 2; + const UInt16 *buf = (const UInt16 *)(db.NamesBuf + pos); + size_t j; + for (j = 0; j < curRem && buf[j] != 0; j++); + if (j == curRem) + ThrowEndOfData(); + db.NameOffsets[i] = pos / 2; + pos += j * 2 + 2; + } + db.NameOffsets[i] = pos / 2; + if (pos != rem) + ThereIsHeaderError = true; break; } - case NID::kWinAttributes: + case NID::kWinAttrib: { CBoolVector boolVector; ReadBoolVector2(db.Files.Size(), boolVector); @@ -986,9 +1274,40 @@ HRESULT CInArchive::ReadHeader( } break; } + /* + case NID::kIsAux: + { + ReadBoolVector(db.Files.Size(), db.IsAux); + break; + } + case NID::kParent: + { + db.IsTree = true; + // CBoolVector boolVector; + // ReadBoolVector2(db.Files.Size(), boolVector); + // CStreamSwitch streamSwitch; + // streamSwitch.Set(this, &dataVector); + CBoolVector boolVector; + ReadBoolVector2(db.Files.Size(), boolVector); + + db.ThereAreAltStreams = false; + for (i = 0; i < numFiles; i++) + { + CFileItem &file = db.Files[i]; + // file.Parent = -1; + // if (boolVector[i]) + file.Parent = (int)ReadUInt32(); + file.IsAltStream = !boolVector[i]; + if (file.IsAltStream) + db.ThereAreAltStreams = true; + } + break; + } + */ case NID::kEmptyStream: { ReadBoolVector(numFiles, emptyStreamVector); + numEmptyStreams = 0; for (i = 0; i < (CNum)emptyStreamVector.Size(); i++) if (emptyStreamVector[i]) numEmptyStreams++; @@ -1000,34 +1319,83 @@ HRESULT CInArchive::ReadHeader( } case NID::kEmptyFile: ReadBoolVector(numEmptyStreams, emptyFileVector); break; case NID::kAnti: ReadBoolVector(numEmptyStreams, antiFileVector); break; - case NID::kStartPos: ReadUInt64DefVector(dataVector, db.StartPos, (int)numFiles); break; - case NID::kCTime: ReadUInt64DefVector(dataVector, db.CTime, (int)numFiles); break; - case NID::kATime: ReadUInt64DefVector(dataVector, db.ATime, (int)numFiles); break; - case NID::kMTime: ReadUInt64DefVector(dataVector, db.MTime, (int)numFiles); break; + case NID::kStartPos: ReadUInt64DefVector(dataVector, db.StartPos, (unsigned)numFiles); break; + case NID::kCTime: ReadUInt64DefVector(dataVector, db.CTime, (unsigned)numFiles); break; + case NID::kATime: ReadUInt64DefVector(dataVector, db.ATime, (unsigned)numFiles); break; + case NID::kMTime: ReadUInt64DefVector(dataVector, db.MTime, (unsigned)numFiles); break; case NID::kDummy: { for (UInt64 j = 0; j < size; j++) if (ReadByte() != 0) - ThrowIncorrect(); + ThereIsHeaderError = true; addPropIdToList = false; break; } + /* + case NID::kNtSecure: + { + try + { + { + CStreamSwitch streamSwitch; + streamSwitch.Set(this, &dataVector); + UInt32 numDescriptors = ReadUInt32(); + size_t offset = 0; + db.SecureOffsets.Clear(); + for (i = 0; i < numDescriptors; i++) + { + UInt32 size = ReadUInt32(); + db.SecureOffsets.Add(offset); + offset += size; + } + // ThrowIncorrect();; + db.SecureOffsets.Add(offset); + db.SecureBuf.SetCapacity(offset); + for (i = 0; i < numDescriptors; i++) + { + offset = db.SecureOffsets[i]; + ReadBytes(db.SecureBuf + offset, db.SecureOffsets[i + 1] - offset); + } + db.SecureIDs.Clear(); + for (unsigned i = 0; i < db.Files.Size(); i++) + { + db.SecureIDs.Add(ReadNum()); + // db.SecureIDs.Add(ReadUInt32()); + } + // ReadUInt32(); + if (_inByteBack->GetRem() != 0) + ThrowIncorrect();; + } + } + catch(CInArchiveException &) + { + ThereIsHeaderError = true; + addPropIdToList = isKnownType = false; + db.ClearSecure(); + } + break; + } + */ default: addPropIdToList = isKnownType = false; } if (isKnownType) { - if(addPropIdToList) - db.ArchiveInfo.FileInfoPopIDs.Add(type); + if (addPropIdToList) + db.ArcInfo.FileInfoPopIDs.Add(type); } else - SkipData(size); - bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 || - db.ArchiveInfo.Version.Minor > 2); - if (checkRecordsSize && _inByteBack->_pos - ppp != size) + { + db.UnsupportedFeatureWarning = true; + _inByteBack->SkipRem(); + } + // SkipData worked incorrectly in some versions before v4.59 (7zVer <= 00.02) + if (_inByteBack->GetRem() != 0) ThrowIncorrect(); } + type = ReadID(); // Read (NID::kEnd) end of headers + CNum emptyFileIndex = 0; CNum sizeIndex = 0; @@ -1035,19 +1403,21 @@ HRESULT CInArchive::ReadHeader( for (i = 0; i < numEmptyStreams; i++) if (antiFileVector[i]) numAntiItems++; - + for (i = 0; i < numFiles; i++) { CFileItem &file = db.Files[i]; bool isAnti; file.HasStream = !emptyStreamVector[i]; + file.Crc = 0; if (file.HasStream) { file.IsDir = false; isAnti = false; file.Size = unpackSizes[sizeIndex]; - file.Crc = digests[sizeIndex]; - file.CrcDefined = digestsDefined[sizeIndex]; + file.CrcDefined = digests.ValidAndDefined(sizeIndex); + if (file.CrcDefined) + file.Crc = digests.Vals[sizeIndex]; sizeIndex++; } else @@ -1061,162 +1431,187 @@ HRESULT CInArchive::ReadHeader( if (numAntiItems != 0) db.IsAnti.Add(isAnti); } + } + db.FillLinks(); + /* + if (type != NID::kEnd) + ThrowIncorrect(); + if (_inByteBack->GetRem() != 0) + ThrowIncorrect(); + */ return S_OK; } - -void CArchiveDatabaseEx::FillFolderStartPackStream() +void CDbEx::FillLinks() { - FolderStartPackStreamIndex.Clear(); - FolderStartPackStreamIndex.Reserve(Folders.Size()); - CNum startPos = 0; - for (int i = 0; i < Folders.Size(); i++) - { - FolderStartPackStreamIndex.Add(startPos); - startPos += (CNum)Folders[i].PackStreams.Size(); - } -} + FolderStartFileIndex.ClearAndSetSize(NumFolders); -void CArchiveDatabaseEx::FillStartPos() -{ - PackStreamStartPositions.Clear(); - PackStreamStartPositions.Reserve(PackSizes.Size()); - UInt64 startPos = 0; - for (int i = 0; i < PackSizes.Size(); i++) - { - PackStreamStartPositions.Add(startPos); - startPos += PackSizes[i]; - } -} + FileIndexToFolderIndexMap.ClearAndSetSize(Files.Size()); -void CArchiveDatabaseEx::FillFolderStartFileIndex() -{ - FolderStartFileIndex.Clear(); - FolderStartFileIndex.Reserve(Folders.Size()); - FileIndexToFolderIndexMap.Clear(); - FileIndexToFolderIndexMap.Reserve(Files.Size()); - - int folderIndex = 0; + CNum folderIndex = 0; CNum indexInFolder = 0; - for (int i = 0; i < Files.Size(); i++) + unsigned i; + for (i = 0; i < Files.Size(); i++) { - const CFileItem &file = Files[i]; - bool emptyStream = !file.HasStream; - if (emptyStream && indexInFolder == 0) - { - FileIndexToFolderIndexMap.Add(kNumNoIndex); - continue; - } + bool emptyStream = !Files[i].HasStream; if (indexInFolder == 0) { + if (emptyStream) + { + FileIndexToFolderIndexMap[i] = kNumNoIndex; + continue; + } // v3.13 incorrectly worked with empty folders - // v4.07: Loop for skipping empty folders + // v4.07: we skip empty folders for (;;) { - if (folderIndex >= Folders.Size()) + if (folderIndex >= NumFolders) ThrowIncorrect(); - FolderStartFileIndex.Add(i); // check it + FolderStartFileIndex[folderIndex] = i; if (NumUnpackStreamsVector[folderIndex] != 0) break; folderIndex++; } } - FileIndexToFolderIndexMap.Add(folderIndex); + FileIndexToFolderIndexMap[i] = folderIndex; if (emptyStream) continue; - indexInFolder++; - if (indexInFolder >= NumUnpackStreamsVector[folderIndex]) + if (++indexInFolder >= NumUnpackStreamsVector[folderIndex]) { folderIndex++; indexInFolder = 0; } } + + if (indexInFolder != 0) + folderIndex++; + /* + if (indexInFolder != 0) + ThrowIncorrect(); + */ + for (;;) + { + if (folderIndex >= NumFolders) + return; + FolderStartFileIndex[folderIndex] = i; + /* + if (NumUnpackStreamsVector[folderIndex] != 0) + ThrowIncorrect();; + */ + folderIndex++; + } } HRESULT CInArchive::ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS - CArchiveDatabaseEx &db - #ifndef _NO_CRYPTO - , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined - #endif + CDbEx &db + _7Z_DECODER_CRYPRO_VARS_DECL ) { db.Clear(); - db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; + db.ArcInfo.StartPosition = _arhiveBeginStreamPosition; - db.ArchiveInfo.Version.Major = _header[6]; - db.ArchiveInfo.Version.Minor = _header[7]; + db.ArcInfo.Version.Major = _header[6]; + db.ArcInfo.Version.Minor = _header[7]; - if (db.ArchiveInfo.Version.Major != kMajorVersion) - ThrowUnsupportedVersion(); + if (db.ArcInfo.Version.Major != kMajorVersion) + { + // db.UnsupportedVersion = true; + return S_FALSE; + } - UInt32 crcFromArchive = Get32(_header + 8); - UInt64 nextHeaderOffset = Get64(_header + 0xC); - UInt64 nextHeaderSize = Get64(_header + 0x14); - UInt32 nextHeaderCRC = Get32(_header + 0x1C); - UInt32 crc = CrcCalc(_header + 0xC, 20); + UInt64 nextHeaderOffset = Get64(_header + 12); + UInt64 nextHeaderSize = Get64(_header + 20); + UInt32 nextHeaderCRC = Get32(_header + 28); #ifdef FORMAT_7Z_RECOVERY - if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0) + UInt32 crcFromArc = Get32(_header + 8); + if (crcFromArc == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0) { - UInt64 cur, cur2; + UInt64 cur, fileSize; RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur)); - const int kCheckSize = 500; + const unsigned kCheckSize = 512; Byte buf[kCheckSize]; - RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2)); - int checkSize = kCheckSize; - if (cur2 - cur < kCheckSize) - checkSize = (int)(cur2 - cur); - RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2)); - + RINOK(_stream->Seek(0, STREAM_SEEK_END, &fileSize)); + UInt64 rem = fileSize - cur; + unsigned checkSize = kCheckSize; + if (rem < kCheckSize) + checkSize = (unsigned)(rem); + if (checkSize < 3) + return S_FALSE; + RINOK(_stream->Seek(fileSize - checkSize, STREAM_SEEK_SET, NULL)); RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize)); - int i; - for (i = (int)checkSize - 2; i >= 0; i--) - if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04) - break; - if (i < 0) + if (buf[checkSize - 1] != 0) return S_FALSE; + + unsigned i; + for (i = checkSize - 2;; i--) + { + if (buf[i] == NID::kEncodedHeader && buf[i + 1] == NID::kPackInfo || + buf[i] == NID::kHeader && buf[i + 1] == NID::kMainStreamsInfo) + break; + if (i == 0) + return S_FALSE; + } nextHeaderSize = checkSize - i; - nextHeaderOffset = cur2 - cur + i; + nextHeaderOffset = rem - nextHeaderSize; nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL)); + db.StartHeaderWasRecovered = true; } else #endif { - if (crc != crcFromArchive) - ThrowIncorrect(); + // Crc was tested already at signature check + // if (CrcCalc(_header + 12, 20) != crcFromArchive) ThrowIncorrect(); } - db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; + db.ArcInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; + db.PhySize = kHeaderSize; + db.IsArc = false; + if ((Int64)nextHeaderOffset < 0 || + nextHeaderSize > ((UInt64)1 << 62)) + return S_FALSE; if (nextHeaderSize == 0) + { + if (nextHeaderOffset != 0) + return S_FALSE; + db.IsArc = true; return S_OK; + } - if (nextHeaderSize > (UInt64)0xFFFFFFFF) - return S_FALSE; + if (!db.StartHeaderWasRecovered) + db.IsArc = true; - if ((Int64)nextHeaderOffset < 0) + HeadersSize += kHeaderSize + nextHeaderSize; + db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize; + if (_fileEndPosition - db.ArcInfo.StartPositionAfterHeader < nextHeaderOffset + nextHeaderSize) + { + db.UnexpectedEnd = true; return S_FALSE; - + } RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL)); - CByteBuffer buffer2; - buffer2.SetCapacity((size_t)nextHeaderSize); + size_t nextHeaderSize_t = (size_t)nextHeaderSize; + if (nextHeaderSize_t != nextHeaderSize) + return E_OUTOFMEMORY; + CByteBuffer buffer2(nextHeaderSize_t); - RINOK(ReadStream_FALSE(_stream, buffer2, (size_t)nextHeaderSize)); - HeadersSize += kHeaderSize + nextHeaderSize; - db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize; + RINOK(ReadStream_FALSE(_stream, buffer2, nextHeaderSize_t)); - if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC) + if (CrcCalc(buffer2, nextHeaderSize_t) != nextHeaderCRC) ThrowIncorrect(); - + + if (!db.StartHeaderWasRecovered) + db.PhySizeWasConfirmed = true; + CStreamSwitch streamSwitch; streamSwitch.Set(this, buffer2); - + CObjectVector dataVector; - + UInt64 type = ReadID(); if (type != NID::kHeader) { @@ -1224,12 +1619,10 @@ HRESULT CInArchive::ReadDatabase2( ThrowIncorrect(); HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS - db.ArchiveInfo.StartPositionAfterHeader, - db.ArchiveInfo.DataStartPosition2, + db.ArcInfo.StartPositionAfterHeader, + db.ArcInfo.DataStartPosition2, dataVector - #ifndef _NO_CRYPTO - , getTextPassword, passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS ); RINOK(result); if (dataVector.Size() == 0) @@ -1242,35 +1635,45 @@ HRESULT CInArchive::ReadDatabase2( ThrowIncorrect(); } + db.IsArc = true; + db.HeadersSize = HeadersSize; return ReadHeader( EXTERNAL_CODECS_LOC_VARS db - #ifndef _NO_CRYPTO - , getTextPassword, passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS ); } HRESULT CInArchive::ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS - CArchiveDatabaseEx &db - #ifndef _NO_CRYPTO - , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined - #endif + CDbEx &db + _7Z_DECODER_CRYPRO_VARS_DECL ) { try { - return ReadDatabase2( + HRESULT res = ReadDatabase2( EXTERNAL_CODECS_LOC_VARS db - #ifndef _NO_CRYPTO - , getTextPassword, passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS ); + if (ThereIsHeaderError) + db.ThereIsHeaderError = true; + if (res == E_NOTIMPL) + ThrowUnsupported(); + return res; + } + catch(CUnsupportedFeatureException &) + { + db.UnsupportedFeatureError = true; + return S_FALSE; + } + catch(CInArchiveException &) + { + db.ThereIsHeaderError = true; + return S_FALSE; } - catch(CInArchiveException &) { return S_FALSE; } } }} diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.h b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.h index 971f27b2a..98f61c81e 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.h @@ -5,6 +5,8 @@ #include "../../../Common/MyCom.h" +#include "../../../Windows/PropVariant.h" + #include "../../IPassword.h" #include "../../IStream.h" @@ -12,10 +14,151 @@ #include "../../Common/InBuffer.h" #include "7zItem.h" - + namespace NArchive { namespace N7z { - + +/* + We don't need to init isEncrypted and passwordIsDefined + We must upgrade them only */ + +#ifdef _NO_CRYPTO +#define _7Z_DECODER_CRYPRO_VARS_DECL +#define _7Z_DECODER_CRYPRO_VARS +#else +#define _7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined +#define _7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined +#endif + +struct CParsedMethods +{ + Byte Lzma2Prop; + UInt32 LzmaDic; + CRecordVector IDs; + + CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {} +}; + +struct CFolders +{ + CNum NumPackStreams; + CNum NumFolders; + + CObjArray PackPositions; // NumPackStreams + 1 + // CUInt32DefVector PackCRCs; // we don't use PackCRCs now + + CUInt32DefVector FolderCRCs; // NumFolders + CObjArray NumUnpackStreamsVector; // NumFolders + + CObjArray CoderUnpackSizes; // including unpack sizes of bind coders + CObjArray FoToCoderUnpackSizes; // NumFolders + 1 + CObjArray FoStartPackStreamIndex; // NumFolders + 1 + CObjArray FoToMainUnpackSizeIndex; // NumFolders + + CObjArray FoCodersDataOffset; // NumFolders + 1 + CByteBuffer CodersData; + + CParsedMethods ParsedMethods; + + void ParseFolderInfo(unsigned folderIndex, CFolder &folder) const; + + unsigned GetNumFolderUnpackSizes(unsigned folderIndex) const + { + return FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex]; + } + + UInt64 GetFolderUnpackSize(unsigned folderIndex) const + { + return CoderUnpackSizes[FoToCoderUnpackSizes[folderIndex] + FoToMainUnpackSizeIndex[folderIndex]]; + } + + UInt64 GetStreamPackSize(unsigned index) const + { + return PackPositions[index + 1] - PackPositions[index]; + } + + void Clear() + { + NumPackStreams = 0; + PackPositions.Free(); + // PackCRCs.Clear(); + + NumFolders = 0; + FolderCRCs.Clear(); + NumUnpackStreamsVector.Free(); + CoderUnpackSizes.Free(); + FoToCoderUnpackSizes.Free(); + FoStartPackStreamIndex.Free(); + FoToMainUnpackSizeIndex.Free(); + FoCodersDataOffset.Free(); + CodersData.Free(); + } +}; + +struct CDatabase: public CFolders +{ + CRecordVector Files; + + CUInt64DefVector CTime; + CUInt64DefVector ATime; + CUInt64DefVector MTime; + CUInt64DefVector StartPos; + CRecordVector IsAnti; + /* + CRecordVector IsAux; + CByteBuffer SecureBuf; + CRecordVector SecureIDs; + */ + + CByteBuffer NamesBuf; + CObjArray NameOffsets; // numFiles + 1, offsets of utf-16 symbols + + /* + void ClearSecure() + { + SecureBuf.Free(); + SecureIDs.Clear(); + } + */ + + void Clear() + { + CFolders::Clear(); + // ClearSecure(); + + NamesBuf.Free(); + NameOffsets.Free(); + + Files.Clear(); + CTime.Clear(); + ATime.Clear(); + MTime.Clear(); + StartPos.Clear(); + IsAnti.Clear(); + // IsAux.Clear(); + } + + bool IsSolid() const + { + for (CNum i = 0; i < NumFolders; i++) + if (NumUnpackStreamsVector[i] > 1) + return true; + return false; + } + bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); } + // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); } + + const void * GetName(unsigned index) const + { + if (!NameOffsets || !NamesBuf) + return NULL; + return (const void *)((const Byte *)NamesBuf + NameOffsets[index] * 2); + }; + + void GetPath(unsigned index, UString &path) const; + HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw(); +}; + struct CInArchiveInfo { CArchiveVersion Version; @@ -24,29 +167,73 @@ struct CInArchiveInfo UInt64 DataStartPosition; UInt64 DataStartPosition2; CRecordVector FileInfoPopIDs; + void Clear() { + StartPosition = 0; + StartPositionAfterHeader = 0; + DataStartPosition = 0; + DataStartPosition2 = 0; FileInfoPopIDs.Clear(); } }; -struct CArchiveDatabaseEx: public CArchiveDatabase +struct CDbEx: public CDatabase { - CInArchiveInfo ArchiveInfo; - CRecordVector PackStreamStartPositions; - CRecordVector FolderStartPackStreamIndex; + CInArchiveInfo ArcInfo; CRecordVector FolderStartFileIndex; CRecordVector FileIndexToFolderIndexMap; UInt64 HeadersSize; UInt64 PhySize; + /* + CRecordVector SecureOffsets; + bool IsTree; + bool ThereAreAltStreams; + */ + + bool IsArc; + bool PhySizeWasConfirmed; + + bool ThereIsHeaderError; + bool UnexpectedEnd; + // bool UnsupportedVersion; + + bool StartHeaderWasRecovered; + bool UnsupportedFeatureWarning; + bool UnsupportedFeatureError; + + /* + void ClearSecureEx() + { + ClearSecure(); + SecureOffsets.Clear(); + } + */ + void Clear() { - CArchiveDatabase::Clear(); - ArchiveInfo.Clear(); - PackStreamStartPositions.Clear(); - FolderStartPackStreamIndex.Clear(); + IsArc = false; + PhySizeWasConfirmed = false; + + ThereIsHeaderError = false; + UnexpectedEnd = false; + // UnsupportedVersion = false; + + StartHeaderWasRecovered = false; + UnsupportedFeatureError = false; + UnsupportedFeatureWarning = false; + + /* + IsTree = false; + ThereAreAltStreams = false; + */ + + CDatabase::Clear(); + + // SecureOffsets.Clear(); + ArcInfo.Clear(); FolderStartFileIndex.Clear(); FileIndexToFolderIndexMap.Clear(); @@ -54,36 +241,25 @@ struct CArchiveDatabaseEx: public CArchiveDatabase PhySize = 0; } - void FillFolderStartPackStream(); - void FillStartPos(); - void FillFolderStartFileIndex(); + void FillLinks(); - void Fill() - { - FillFolderStartPackStream(); - FillStartPos(); - FillFolderStartFileIndex(); - } - - UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const + UInt64 GetFolderStreamPos(unsigned folderIndex, unsigned indexInFolder) const { - return ArchiveInfo.DataStartPosition + - PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] + indexInFolder]; + return ArcInfo.DataStartPosition + + PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder]; } - - UInt64 GetFolderFullPackSize(int folderIndex) const + + UInt64 GetFolderFullPackSize(unsigned folderIndex) const { - CNum packStreamIndex = FolderStartPackStreamIndex[folderIndex]; - const CFolder &folder = Folders[folderIndex]; - UInt64 size = 0; - for (int i = 0; i < folder.PackStreams.Size(); i++) - size += PackSizes[packStreamIndex + i]; - return size; + return + PackPositions[FoStartPackStreamIndex[folderIndex + 1]] - + PackPositions[FoStartPackStreamIndex[folderIndex]]; } - - UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const + + UInt64 GetFolderPackStreamSize(unsigned folderIndex, unsigned streamIndex) const { - return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; + unsigned i = FoStartPackStreamIndex[folderIndex] + streamIndex; + return PackPositions[i + 1] - PackPositions[i]; } UInt64 GetFilePackSize(CNum fileIndex) const @@ -96,12 +272,17 @@ struct CArchiveDatabaseEx: public CArchiveDatabase } }; -class CInByte2 +const unsigned kNumBufLevelsMax = 4; + +struct CInByte2 { const Byte *_buffer; - size_t _size; public: + size_t _size; size_t _pos; + + size_t GetRem() const { return _size - _pos; } + const Byte *GetPtr() const { return _buffer + _pos; } void Init(const Byte *buffer, size_t size) { _buffer = buffer; @@ -110,13 +291,17 @@ public: } Byte ReadByte(); void ReadBytes(Byte *data, size_t size); + void SkipDataNoCheck(UInt64 size) { _pos += (size_t)size; } void SkipData(UInt64 size); + void SkipData(); + void SkipRem() { _pos = _size; } UInt64 ReadNumber(); CNum ReadNum(); UInt32 ReadUInt32(); UInt64 ReadUInt64(); - void ReadString(UString &s); + + void ParseFolder(CFolder &folder); }; class CStreamSwitch; @@ -129,32 +314,35 @@ class CInArchive CMyComPtr _stream; - CObjectVector _inByteVector; + unsigned _numInByteBufs; + CInByte2 _inByteVector[kNumBufLevelsMax]; + CInByte2 *_inByteBack; - + bool ThereIsHeaderError; + UInt64 _arhiveBeginStreamPosition; + UInt64 _fileEndPosition; Byte _header[kHeaderSize]; UInt64 HeadersSize; - void AddByteStream(const Byte *buffer, size_t size) - { - _inByteVector.Add(CInByte2()); - _inByteBack = &_inByteVector.Back(); - _inByteBack->Init(buffer, size); - } - - void DeleteByteStream() + void AddByteStream(const Byte *buffer, size_t size); + + void DeleteByteStream(bool needUpdatePos) { - _inByteVector.DeleteBack(); - if (!_inByteVector.IsEmpty()) - _inByteBack = &_inByteVector.Back(); + _numInByteBufs--; + if (_numInByteBufs > 0) + { + _inByteBack = &_inByteVector[_numInByteBufs - 1]; + if (needUpdatePos) + _inByteBack->_pos += _inByteVector[_numInByteBufs]._pos; + } } private: HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); - + void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); } Byte ReadByte() { return _inByteBack->ReadByte(); } UInt64 ReadNumber() { return _inByteBack->ReadNumber(); } @@ -164,82 +352,61 @@ private: UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); } void SkipData(UInt64 size) { _inByteBack->SkipData(size); } void SkipData() { _inByteBack->SkipData(); } - void WaitAttribute(UInt64 attribute); + void WaitId(UInt64 id); void ReadArchiveProperties(CInArchiveInfo &archiveInfo); - void GetNextFolderItem(CFolder &itemInfo); - void ReadHashDigests(int numItems, - CBoolVector &digestsDefined, CRecordVector &digests); - - void ReadPackInfo( - UInt64 &dataOffset, - CRecordVector &packSizes, - CBoolVector &packCRCsDefined, - CRecordVector &packCRCs); - + void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs); + + void ReadPackInfo(CFolders &f); + void ReadUnpackInfo( const CObjectVector *dataVector, - CObjectVector &folders); - + CFolders &folders); + void ReadSubStreamsInfo( - const CObjectVector &folders, - CRecordVector &numUnpackStreamsInFolders, + CFolders &folders, CRecordVector &unpackSizes, - CBoolVector &digestsDefined, - CRecordVector &digests); + CUInt32DefVector &digests); void ReadStreamsInfo( const CObjectVector *dataVector, UInt64 &dataOffset, - CRecordVector &packSizes, - CBoolVector &packCRCsDefined, - CRecordVector &packCRCs, - CObjectVector &folders, - CRecordVector &numUnpackStreamsInFolders, + CFolders &folders, CRecordVector &unpackSizes, - CBoolVector &digestsDefined, - CRecordVector &digests); - + CUInt32DefVector &digests); - void ReadBoolVector(int numItems, CBoolVector &v); - void ReadBoolVector2(int numItems, CBoolVector &v); + void ReadBoolVector(unsigned numItems, CBoolVector &v); + void ReadBoolVector2(unsigned numItems, CBoolVector &v); void ReadUInt64DefVector(const CObjectVector &dataVector, - CUInt64DefVector &v, int numFiles); + CUInt64DefVector &v, unsigned numItems); HRESULT ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector &dataVector - #ifndef _NO_CRYPTO - , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS_DECL ); HRESULT ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS - CArchiveDatabaseEx &db - #ifndef _NO_CRYPTO - ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined - #endif + CDbEx &db + _7Z_DECODER_CRYPRO_VARS_DECL ); HRESULT ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS - CArchiveDatabaseEx &db - #ifndef _NO_CRYPTO - ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined - #endif + CDbEx &db + _7Z_DECODER_CRYPRO_VARS_DECL ); public: + CInArchive(): _numInByteBufs(0) { } HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive void Close(); HRESULT ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS - CArchiveDatabaseEx &db - #ifndef _NO_CRYPTO - ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined - #endif + CDbEx &db + _7Z_DECODER_CRYPRO_VARS_DECL ); }; - + }} - + #endif diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zItem.h b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zItem.h index 34f10775c..c112f83fd 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zItem.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zItem.h @@ -3,7 +3,7 @@ #ifndef __7Z_ITEM_H #define __7Z_ITEM_H -#include "../../../Common/Buffer.h" +#include "../../../Common/MyBuffer.h" #include "../../../Common/MyString.h" #include "../../Common/MethodId.h" @@ -25,6 +25,7 @@ struct CCoderInfo CByteBuffer Props; CNum NumInStreams; CNum NumOutStreams; + bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } }; @@ -36,55 +37,48 @@ struct CBindPair struct CFolder { - CObjectVector Coders; - CRecordVector BindPairs; - CRecordVector PackStreams; - CRecordVector UnpackSizes; - UInt32 UnpackCRC; - bool UnpackCRCDefined; - - CFolder(): UnpackCRCDefined(false) {} - - UInt64 GetUnpackSize() const // test it - { - if (UnpackSizes.IsEmpty()) - return 0; - for (int i = UnpackSizes.Size() - 1; i >= 0; i--) - if (FindBindPairForOutStream(i) < 0) - return UnpackSizes[i]; - throw 1; - } + CObjArray2 Coders; + CObjArray2 BindPairs; + CObjArray2 PackStreams; CNum GetNumOutStreams() const { CNum result = 0; - for (int i = 0; i < Coders.Size(); i++) + FOR_VECTOR(i, Coders) result += Coders[i].NumOutStreams; return result; } int FindBindPairForInStream(CNum inStreamIndex) const { - for(int i = 0; i < BindPairs.Size(); i++) + FOR_VECTOR(i, BindPairs) if (BindPairs[i].InIndex == inStreamIndex) return i; return -1; } int FindBindPairForOutStream(CNum outStreamIndex) const { - for(int i = 0; i < BindPairs.Size(); i++) + FOR_VECTOR(i, BindPairs) if (BindPairs[i].OutIndex == outStreamIndex) return i; return -1; } int FindPackStreamArrayIndex(CNum inStreamIndex) const { - for(int i = 0; i < PackStreams.Size(); i++) + FOR_VECTOR(i, PackStreams) if (PackStreams[i] == inStreamIndex) return i; return -1; } + int GetIndexOfMainOutStream() const + { + for (int i = (int)GetNumOutStreams() - 1; i >= 0; i--) + if (FindBindPairForOutStream(i) < 0) + return i; + throw 1; + } + bool IsEncrypted() const { for (int i = Coders.Size() - 1; i >= 0; i--) @@ -93,50 +87,66 @@ struct CFolder return false; } - bool CheckStructure() const; + bool CheckStructure(unsigned numUnpackSizes) const; +}; + +struct CUInt32DefVector +{ + CBoolVector Defs; + CRecordVector Vals; + + void ClearAndSetSize(unsigned newSize) + { + Defs.ClearAndSetSize(newSize); + Vals.ClearAndSetSize(newSize); + } + + void Clear() + { + Defs.Clear(); + Vals.Clear(); + } + + void ReserveDown() + { + Defs.ReserveDown(); + Vals.ReserveDown(); + } + + bool ValidAndDefined(unsigned i) const { return i < Defs.Size() && Defs[i]; } }; struct CUInt64DefVector { - CRecordVector Values; - CRecordVector Defined; - + CBoolVector Defs; + CRecordVector Vals; + void Clear() { - Values.Clear(); - Defined.Clear(); + Defs.Clear(); + Vals.Clear(); } - + void ReserveDown() { - Values.ReserveDown(); - Values.ReserveDown(); + Defs.ReserveDown(); + Vals.ReserveDown(); } - bool GetItem(int index, UInt64 &value) const + bool GetItem(unsigned index, UInt64 &value) const { - if (index < Defined.Size() && Defined[index]) + if (index < Defs.Size() && Defs[index]) { - value = Values[index]; + value = Vals[index]; return true; } value = 0; return false; } - - void SetItem(int index, bool defined, UInt64 value) - { - while (index >= Defined.Size()) - Defined.Add(false); - Defined[index] = defined; - if (!defined) - return; - while (index >= Values.Size()) - Values.Add(0); - Values[index] = value; - } - bool CheckSize(int size) const { return Defined.Size() == size || Defined.Size() == 0; } + void SetItem(unsigned index, bool defined, UInt64 value); + + bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; } }; struct CFileItem @@ -144,8 +154,10 @@ struct CFileItem UInt64 Size; UInt32 Attrib; UInt32 Crc; - UString Name; - + /* + int Parent; + bool IsAltStream; + */ bool HasStream; // Test it !!! it means that there is // stream in some folder. It can be empty stream bool IsDir; @@ -153,6 +165,10 @@ struct CFileItem bool AttribDefined; CFileItem(): + /* + Parent(-1), + IsAltStream(false), + */ HasStream(true), IsDir(false), CrcDefined(false), @@ -165,104 +181,6 @@ struct CFileItem } }; -struct CFileItem2 -{ - UInt64 CTime; - UInt64 ATime; - UInt64 MTime; - UInt64 StartPos; - bool CTimeDefined; - bool ATimeDefined; - bool MTimeDefined; - bool StartPosDefined; - bool IsAnti; -}; - -struct CArchiveDatabase -{ - CRecordVector PackSizes; - CRecordVector PackCRCsDefined; - CRecordVector PackCRCs; - CObjectVector Folders; - CRecordVector NumUnpackStreamsVector; - CObjectVector Files; - - CUInt64DefVector CTime; - CUInt64DefVector ATime; - CUInt64DefVector MTime; - CUInt64DefVector StartPos; - CRecordVector IsAnti; - - void Clear() - { - PackSizes.Clear(); - PackCRCsDefined.Clear(); - PackCRCs.Clear(); - Folders.Clear(); - NumUnpackStreamsVector.Clear(); - Files.Clear(); - CTime.Clear(); - ATime.Clear(); - MTime.Clear(); - StartPos.Clear(); - IsAnti.Clear(); - } - - void ReserveDown() - { - PackSizes.ReserveDown(); - PackCRCsDefined.ReserveDown(); - PackCRCs.ReserveDown(); - Folders.ReserveDown(); - NumUnpackStreamsVector.ReserveDown(); - Files.ReserveDown(); - CTime.ReserveDown(); - ATime.ReserveDown(); - MTime.ReserveDown(); - StartPos.ReserveDown(); - IsAnti.ReserveDown(); - } - - bool IsEmpty() const - { - return (PackSizes.IsEmpty() && - PackCRCsDefined.IsEmpty() && - PackCRCs.IsEmpty() && - Folders.IsEmpty() && - NumUnpackStreamsVector.IsEmpty() && - Files.IsEmpty()); - } - - bool CheckNumFiles() const - { - int size = Files.Size(); - return ( - CTime.CheckSize(size) && - ATime.CheckSize(size) && - MTime.CheckSize(size) && - StartPos.CheckSize(size) && - (size == IsAnti.Size() || IsAnti.Size() == 0)); - } - - bool IsSolid() const - { - for (int i = 0; i < NumUnpackStreamsVector.Size(); i++) - if (NumUnpackStreamsVector[i] > 1) - return true; - return false; - } - bool IsItemAnti(int index) const { return (index < IsAnti.Size() && IsAnti[index]); } - void SetItemAnti(int index, bool isAnti) - { - while (index >= IsAnti.Size()) - IsAnti.Add(false); - IsAnti[index] = isAnti; - } - - void GetFile(int index, CFileItem &file, CFileItem2 &file2) const; - void AddFile(const CFileItem &file, const CFileItem2 &file2); -}; - }} #endif diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.cpp index 0c8aa7e8c..e20858ea7 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.cpp @@ -4,41 +4,19 @@ #include "../../../../C/7zCrc.h" -#include "../../../Common/AutoPtr.h" - #include "../../Common/StreamObjects.h" #include "7zOut.h" -static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size) -{ - while (size > 0) - { - UInt32 curSize = (UInt32)MyMin(size, (size_t)0xFFFFFFFF); - UInt32 processedSize; - RINOK(stream->Write(data, curSize, &processedSize)); - if (processedSize == 0) - return E_FAIL; - data = (const void *)((const Byte *)data + processedSize); - size -= processedSize; - } - return S_OK; -} - namespace NArchive { namespace N7z { -HRESULT COutArchive::WriteDirect(const void *data, UInt32 size) -{ - return ::WriteBytes(SeqStream, data, size); -} - HRESULT COutArchive::WriteSignature() { Byte buf[8]; memcpy(buf, kSignature, kSignatureSize); buf[kSignatureSize] = kMajorVersion; - buf[kSignatureSize + 1] = 3; + buf[kSignatureSize + 1] = 4; return WriteDirect(buf, 8); } @@ -145,7 +123,9 @@ HRESULT COutArchive::SkipPrefixArchiveHeader() if (_endMarker) return S_OK; #endif - return Stream->Seek(24, STREAM_SEEK_CUR, NULL); + Byte buf[24]; + memset(buf, 0, 24); + return WriteDirect(buf, 24); } UInt64 COutArchive::GetPos() const @@ -271,19 +251,19 @@ UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props) void COutArchive::WriteFolder(const CFolder &folder) { WriteNumber(folder.Coders.Size()); - int i; + unsigned i; for (i = 0; i < folder.Coders.Size(); i++) { const CCoderInfo &coder = folder.Coders[i]; { - size_t propsSize = coder.Props.GetCapacity(); - + size_t propsSize = coder.Props.Size(); + UInt64 id = coder.MethodID; int idSize; for (idSize = 1; idSize < sizeof(id); idSize++) if ((id >> (8 * idSize)) == 0) break; - BYTE longID[15]; + Byte longID[15]; for (int t = idSize - 1; t >= 0 ; t--, id >>= 8) longID[t] = (Byte)(id & 0xFF); Byte b; @@ -321,7 +301,7 @@ void COutArchive::WriteBoolVector(const CBoolVector &boolVector) { Byte b = 0; Byte mask = 0x80; - for (int i = 0; i < boolVector.Size(); i++) + FOR_VECTOR (i, boolVector) { if (boolVector[i]) b |= mask; @@ -337,37 +317,42 @@ void COutArchive::WriteBoolVector(const CBoolVector &boolVector) WriteByte(b); } +static inline unsigned Bv_GetSizeInBytes(const CBoolVector &v) { return ((unsigned)v.Size() + 7) / 8; } -void COutArchive::WriteHashDigests( - const CRecordVector &digestsDefined, - const CRecordVector &digests) +void COutArchive::WritePropBoolVector(Byte id, const CBoolVector &boolVector) { - int numDefined = 0; - int i; - for (i = 0; i < digestsDefined.Size(); i++) - if (digestsDefined[i]) + WriteByte(id); + WriteNumber(Bv_GetSizeInBytes(boolVector)); + WriteBoolVector(boolVector); +} + +void COutArchive::WriteHashDigests(const CUInt32DefVector &digests) +{ + unsigned numDefined = 0; + unsigned i; + for (i = 0; i < digests.Defs.Size(); i++) + if (digests.Defs[i]) numDefined++; if (numDefined == 0) return; WriteByte(NID::kCRC); - if (numDefined == digestsDefined.Size()) + if (numDefined == digests.Defs.Size()) WriteByte(1); else { WriteByte(0); - WriteBoolVector(digestsDefined); + WriteBoolVector(digests.Defs); } - for (i = 0; i < digests.Size(); i++) - if (digestsDefined[i]) - WriteUInt32(digests[i]); + for (i = 0; i < digests.Defs.Size(); i++) + if (digests.Defs[i]) + WriteUInt32(digests.Vals[i]); } void COutArchive::WritePackInfo( UInt64 dataOffset, const CRecordVector &packSizes, - const CRecordVector &packCRCsDefined, - const CRecordVector &packCRCs) + const CUInt32DefVector &packCRCs) { if (packSizes.IsEmpty()) return; @@ -375,15 +360,15 @@ void COutArchive::WritePackInfo( WriteNumber(dataOffset); WriteNumber(packSizes.Size()); WriteByte(NID::kSize); - for (int i = 0; i < packSizes.Size(); i++) + FOR_VECTOR (i, packSizes) WriteNumber(packSizes[i]); - WriteHashDigests(packCRCsDefined, packCRCs); - + WriteHashDigests(packCRCs); + WriteByte(NID::kEnd); } -void COutArchive::WriteUnpackInfo(const CObjectVector &folders) +void COutArchive::WriteUnpackInfo(const CObjectVector &folders, const COutFolders &outFolders) { if (folders.IsEmpty()) return; @@ -394,44 +379,29 @@ void COutArchive::WriteUnpackInfo(const CObjectVector &folders) WriteNumber(folders.Size()); { WriteByte(0); - for (int i = 0; i < folders.Size(); i++) + FOR_VECTOR (i, folders) WriteFolder(folders[i]); } - + WriteByte(NID::kCodersUnpackSize); - int i; - for (i = 0; i < folders.Size(); i++) - { - const CFolder &folder = folders[i]; - for (int j = 0; j < folder.UnpackSizes.Size(); j++) - WriteNumber(folder.UnpackSizes[j]); - } + FOR_VECTOR (i, outFolders.CoderUnpackSizes) + WriteNumber(outFolders.CoderUnpackSizes[i]); - CRecordVector unpackCRCsDefined; - CRecordVector unpackCRCs; - for (i = 0; i < folders.Size(); i++) - { - const CFolder &folder = folders[i]; - unpackCRCsDefined.Add(folder.UnpackCRCDefined); - unpackCRCs.Add(folder.UnpackCRC); - } - WriteHashDigests(unpackCRCsDefined, unpackCRCs); + WriteHashDigests(outFolders.FolderUnpackCRCs); WriteByte(NID::kEnd); } -void COutArchive::WriteSubStreamsInfo( - const CObjectVector &folders, - const CRecordVector &numUnpackStreamsInFolders, +void COutArchive::WriteSubStreamsInfo(const CObjectVector &folders, + const COutFolders &outFolders, const CRecordVector &unpackSizes, - const CRecordVector &digestsDefined, - const CRecordVector &digests) + const CUInt32DefVector &digests) { + const CRecordVector &numUnpackStreamsInFolders = outFolders.NumUnpackStreamsVector; WriteByte(NID::kSubStreamsInfo); - int i; + unsigned i; for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) - { if (numUnpackStreamsInFolders[i] != 1) { WriteByte(NID::kNumUnpackStream); @@ -439,54 +409,50 @@ void COutArchive::WriteSubStreamsInfo( WriteNumber(numUnpackStreamsInFolders[i]); break; } - } - - bool needFlag = true; - CNum index = 0; for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) - for (CNum j = 0; j < numUnpackStreamsInFolders[i]; j++) + if (numUnpackStreamsInFolders[i] > 1) { - if (j + 1 != numUnpackStreamsInFolders[i]) + WriteByte(NID::kSize); + CNum index = 0; + for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) { - if (needFlag) - WriteByte(NID::kSize); - needFlag = false; - WriteNumber(unpackSizes[index]); + CNum num = numUnpackStreamsInFolders[i]; + for (CNum j = 0; j < num; j++) + { + if (j + 1 != num) + WriteNumber(unpackSizes[index]); + index++; + } } - index++; + break; } - CRecordVector digestsDefined2; - CRecordVector digests2; + CUInt32DefVector digests2; - int digestIndex = 0; + unsigned digestIndex = 0; for (i = 0; i < folders.Size(); i++) { - int numSubStreams = (int)numUnpackStreamsInFolders[i]; - if (numSubStreams == 1 && folders[i].UnpackCRCDefined) + unsigned numSubStreams = (unsigned)numUnpackStreamsInFolders[i]; + if (numSubStreams == 1 && outFolders.FolderUnpackCRCs.ValidAndDefined(i)) digestIndex++; else - for (int j = 0; j < numSubStreams; j++, digestIndex++) + for (unsigned j = 0; j < numSubStreams; j++, digestIndex++) { - digestsDefined2.Add(digestsDefined[digestIndex]); - digests2.Add(digests[digestIndex]); + digests2.Defs.Add(digests.Defs[digestIndex]); + digests2.Vals.Add(digests.Vals[digestIndex]); } } - WriteHashDigests(digestsDefined2, digests2); + WriteHashDigests(digests2); WriteByte(NID::kEnd); } -void COutArchive::SkipAlign(unsigned /* pos */, unsigned /* alignSize */) -{ - return; -} - -/* -7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field. +// 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field. void COutArchive::SkipAlign(unsigned pos, unsigned alignSize) { + if (!_useAlign) + return; pos += (unsigned)GetPos(); pos &= (alignSize - 1); if (pos == 0) @@ -500,11 +466,8 @@ void COutArchive::SkipAlign(unsigned pos, unsigned alignSize) for (unsigned i = 0; i < skip; i++) WriteByte(0); } -*/ -static inline unsigned Bv_GetSizeInBytes(const CBoolVector &v) { return ((unsigned)v.Size() + 7) / 8; } - -void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize) +void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSize) { const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v); const UInt64 dataSize = (UInt64)numDefined * itemSize + bvSize + 2; @@ -524,49 +487,54 @@ void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, B void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type) { - int numDefined = 0; + unsigned numDefined = 0; - int i; - for (i = 0; i < v.Defined.Size(); i++) - if (v.Defined[i]) + unsigned i; + for (i = 0; i < v.Defs.Size(); i++) + if (v.Defs[i]) numDefined++; if (numDefined == 0) return; - WriteAlignedBoolHeader(v.Defined, numDefined, type, 8); - - for (i = 0; i < v.Defined.Size(); i++) - if (v.Defined[i]) - WriteUInt64(v.Values[i]); + WriteAlignedBoolHeader(v.Defs, numDefined, type, 8); + + for (i = 0; i < v.Defs.Size(); i++) + if (v.Defs[i]) + WriteUInt64(v.Vals[i]); } HRESULT COutArchive::EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, - CRecordVector &packSizes, CObjectVector &folders) + CRecordVector &packSizes, CObjectVector &folders, COutFolders &outFolders) { CBufInStream *streamSpec = new CBufInStream; CMyComPtr stream = streamSpec; - streamSpec->Init(data, data.GetCapacity()); - CFolder folderItem; - folderItem.UnpackCRCDefined = true; - folderItem.UnpackCRC = CrcCalc(data, data.GetCapacity()); - UInt64 dataSize64 = data.GetCapacity(); + streamSpec->Init(data, data.Size()); + outFolders.FolderUnpackCRCs.Defs.Add(true); + outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size())); + // outFolders.NumUnpackStreamsVector.Add(1); + UInt64 dataSize64 = data.Size(); + UInt64 unpackSize; RINOK(encoder.Encode( EXTERNAL_CODECS_LOC_VARS - stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL)) - folders.Add(folderItem); + stream, NULL, &dataSize64, folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL)) return S_OK; } void COutArchive::WriteHeader( - const CArchiveDatabase &db, - const CHeaderOptions &headerOptions, + const CArchiveDatabaseOut &db, + // const CHeaderOptions &headerOptions, UInt64 &headerOffset) { - int i; - + /* + bool thereIsSecure = (db.SecureBuf.Size() != 0); + */ + _useAlign = true; + + unsigned i; + UInt64 packedSize = 0; for (i = 0; i < db.PackSizes.Size(); i++) packedSize += db.PackSizes[i]; @@ -580,31 +548,22 @@ void COutArchive::WriteHeader( if (db.Folders.Size() > 0) { WriteByte(NID::kMainStreamsInfo); - WritePackInfo(0, db.PackSizes, - db.PackCRCsDefined, - db.PackCRCs); - - WriteUnpackInfo(db.Folders); + WritePackInfo(0, db.PackSizes, db.PackCRCs); + WriteUnpackInfo(db.Folders, (const COutFolders &)db); CRecordVector unpackSizes; - CRecordVector digestsDefined; - CRecordVector digests; + CUInt32DefVector digests; for (i = 0; i < db.Files.Size(); i++) { const CFileItem &file = db.Files[i]; if (!file.HasStream) continue; unpackSizes.Add(file.Size); - digestsDefined.Add(file.CrcDefined); - digests.Add(file.Crc); + digests.Defs.Add(file.CrcDefined); + digests.Vals.Add(file.Crc); } - WriteSubStreamsInfo( - db.Folders, - db.NumUnpackStreamsVector, - unpackSizes, - digestsDefined, - digests); + WriteSubStreamsInfo(db.Folders, (const COutFolders &)db, unpackSizes, digests); WriteByte(NID::kEnd); } @@ -618,85 +577,75 @@ void COutArchive::WriteHeader( WriteNumber(db.Files.Size()); { - /* ---------- Empty Streams ---------- */ - CBoolVector emptyStreamVector; - emptyStreamVector.Reserve(db.Files.Size()); - int numEmptyStreams = 0; - for (i = 0; i < db.Files.Size(); i++) - if (db.Files[i].HasStream) - emptyStreamVector.Add(false); - else - { - emptyStreamVector.Add(true); - numEmptyStreams++; - } - if (numEmptyStreams > 0) - { - WriteByte(NID::kEmptyStream); - WriteNumber(Bv_GetSizeInBytes(emptyStreamVector)); - WriteBoolVector(emptyStreamVector); - - CBoolVector emptyFileVector, antiVector; - emptyFileVector.Reserve(numEmptyStreams); - antiVector.Reserve(numEmptyStreams); - CNum numEmptyFiles = 0, numAntiItems = 0; + /* ---------- Empty Streams ---------- */ + CBoolVector emptyStreamVector; + emptyStreamVector.ClearAndSetSize(db.Files.Size()); + unsigned numEmptyStreams = 0; for (i = 0; i < db.Files.Size(); i++) + if (db.Files[i].HasStream) + emptyStreamVector[i] = false; + else + { + emptyStreamVector[i] = true; + numEmptyStreams++; + } + if (numEmptyStreams != 0) { - const CFileItem &file = db.Files[i]; - if (!file.HasStream) + WritePropBoolVector(NID::kEmptyStream, emptyStreamVector); + + CBoolVector emptyFileVector, antiVector; + emptyFileVector.ClearAndSetSize(numEmptyStreams); + antiVector.ClearAndSetSize(numEmptyStreams); + bool thereAreEmptyFiles = false, thereAreAntiItems = false; + unsigned cur = 0; + for (i = 0; i < db.Files.Size(); i++) { - emptyFileVector.Add(!file.IsDir); + const CFileItem &file = db.Files[i]; + if (file.HasStream) + continue; + emptyFileVector[cur] = !file.IsDir; if (!file.IsDir) - numEmptyFiles++; + thereAreEmptyFiles = true; bool isAnti = db.IsItemAnti(i); - antiVector.Add(isAnti); + antiVector[cur] = isAnti; if (isAnti) - numAntiItems++; + thereAreAntiItems = true; + cur++; } - } - if (numEmptyFiles > 0) - { - WriteByte(NID::kEmptyFile); - WriteNumber(Bv_GetSizeInBytes(emptyFileVector)); - WriteBoolVector(emptyFileVector); - } - - if (numAntiItems > 0) - { - WriteByte(NID::kAnti); - WriteNumber(Bv_GetSizeInBytes(antiVector)); - WriteBoolVector(antiVector); + if (thereAreEmptyFiles) + WritePropBoolVector(NID::kEmptyFile, emptyFileVector); + if (thereAreAntiItems) + WritePropBoolVector(NID::kAnti, antiVector); } } - } { /* ---------- Names ---------- */ - - int numDefined = 0; + + unsigned numDefined = 0; size_t namesDataSize = 0; - for (int i = 0; i < db.Files.Size(); i++) + FOR_VECTOR (i, db.Files) { - const UString &name = db.Files[i].Name; + const UString &name = db.Names[i]; if (!name.IsEmpty()) numDefined++; - namesDataSize += (name.Length() + 1) * 2; + namesDataSize += (name.Len() + 1) * 2; } - + if (numDefined > 0) { namesDataSize++; - SkipAlign(2 + GetBigNumberSize(namesDataSize), 2); + SkipAlign(2 + GetBigNumberSize(namesDataSize), 16); WriteByte(NID::kName); WriteNumber(namesDataSize); WriteByte(0); - for (int i = 0; i < db.Files.Size(); i++) + FOR_VECTOR (i, db.Files) { - const UString &name = db.Files[i].Name; - for (int t = 0; t <= name.Length(); t++) + const UString &name = db.Names[i]; + for (unsigned t = 0; t <= name.Len(); t++) { wchar_t c = name[t]; WriteByte((Byte)c); @@ -706,26 +655,26 @@ void COutArchive::WriteHeader( } } - if (headerOptions.WriteCTime) WriteUInt64DefVector(db.CTime, NID::kCTime); - if (headerOptions.WriteATime) WriteUInt64DefVector(db.ATime, NID::kATime); - if (headerOptions.WriteMTime) WriteUInt64DefVector(db.MTime, NID::kMTime); + /* if (headerOptions.WriteCTime) */ WriteUInt64DefVector(db.CTime, NID::kCTime); + /* if (headerOptions.WriteATime) */ WriteUInt64DefVector(db.ATime, NID::kATime); + /* if (headerOptions.WriteMTime) */ WriteUInt64DefVector(db.MTime, NID::kMTime); WriteUInt64DefVector(db.StartPos, NID::kStartPos); - + { /* ---------- Write Attrib ---------- */ CBoolVector boolVector; - boolVector.Reserve(db.Files.Size()); - int numDefined = 0; + boolVector.ClearAndSetSize(db.Files.Size()); + unsigned numDefined = 0; for (i = 0; i < db.Files.Size(); i++) { bool defined = db.Files[i].AttribDefined; - boolVector.Add(defined); + boolVector[i] = defined; if (defined) numDefined++; } - if (numDefined > 0) + if (numDefined != 0) { - WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttributes, 4); + WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttrib, 4); for (i = 0; i < db.Files.Size(); i++) { const CFileItem &file = db.Files[i]; @@ -735,13 +684,95 @@ void COutArchive::WriteHeader( } } + /* + { + // ---------- Write IsAux ---------- + unsigned numAux = 0; + const CBoolVector &isAux = db.IsAux; + for (i = 0; i < isAux.Size(); i++) + if (isAux[i]) + numAux++; + if (numAux > 0) + { + const unsigned bvSize = Bv_GetSizeInBytes(isAux); + WriteByte(NID::kIsAux); + WriteNumber(bvSize); + WriteBoolVector(isAux); + } + } + + { + // ---------- Write Parent ---------- + CBoolVector boolVector; + boolVector.Reserve(db.Files.Size()); + unsigned numIsDir = 0; + unsigned numParentLinks = 0; + for (i = 0; i < db.Files.Size(); i++) + { + const CFileItem &file = db.Files[i]; + bool defined = !file.IsAltStream; + boolVector.Add(defined); + if (defined) + numIsDir++; + if (file.Parent >= 0) + numParentLinks++; + } + if (numParentLinks > 0) + { + // WriteAlignedBoolHeader(boolVector, numDefined, NID::kParent, 4); + const unsigned bvSize = (numIsDir == boolVector.Size()) ? 0 : Bv_GetSizeInBytes(boolVector); + const UInt64 dataSize = (UInt64)db.Files.Size() * 4 + bvSize + 1; + SkipAlign(2 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), 4); + + WriteByte(NID::kParent); + WriteNumber(dataSize); + if (numIsDir == boolVector.Size()) + WriteByte(1); + else + { + WriteByte(0); + WriteBoolVector(boolVector); + } + for (i = 0; i < db.Files.Size(); i++) + { + const CFileItem &file = db.Files[i]; + // if (file.Parent >= 0) + WriteUInt32(file.Parent); + } + } + } + + if (thereIsSecure) + { + UInt64 secureDataSize = 1 + 4 + + db.SecureBuf.Size() + + db.SecureSizes.Size() * 4; + // secureDataSize += db.SecureIDs.Size() * 4; + for (i = 0; i < db.SecureIDs.Size(); i++) + secureDataSize += GetBigNumberSize(db.SecureIDs[i]); + SkipAlign(2 + GetBigNumberSize(secureDataSize), 4); + WriteByte(NID::kNtSecure); + WriteNumber(secureDataSize); + WriteByte(0); + WriteUInt32(db.SecureSizes.Size()); + for (i = 0; i < db.SecureSizes.Size(); i++) + WriteUInt32(db.SecureSizes[i]); + WriteBytes(db.SecureBuf, db.SecureBuf.Size()); + for (i = 0; i < db.SecureIDs.Size(); i++) + { + WriteNumber(db.SecureIDs[i]); + // WriteUInt32(db.SecureIDs[i]); + } + } + */ + WriteByte(NID::kEnd); // for files WriteByte(NID::kEnd); // for headers } HRESULT COutArchive::WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS - const CArchiveDatabase &db, + const CArchiveDatabaseOut &db, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions) { @@ -773,18 +804,17 @@ HRESULT COutArchive::WriteDatabase( _countMode = encodeHeaders; _writeToStream = true; _countSize = 0; - WriteHeader(db, headerOptions, headerOffset); + WriteHeader(db, /* headerOptions, */ headerOffset); if (encodeHeaders) { - CByteBuffer buf; - buf.SetCapacity(_countSize); + CByteBuffer buf(_countSize); _outByte2.Init((Byte *)buf, _countSize); - + _countMode = false; _writeToStream = false; - WriteHeader(db, headerOptions, headerOffset); - + WriteHeader(db, /* headerOptions, */ headerOffset); + if (_countSize != _outByte2.GetPos()) return E_FAIL; @@ -794,22 +824,23 @@ HRESULT COutArchive::WriteDatabase( CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions); CRecordVector packSizes; CObjectVector folders; + COutFolders outFolders; + RINOK(EncodeStream( EXTERNAL_CODECS_LOC_VARS encoder, buf, - packSizes, folders)); + packSizes, folders, outFolders)); _writeToStream = true; - + if (folders.Size() == 0) throw 1; WriteID(NID::kEncodedHeader); - WritePackInfo(headerOffset, packSizes, - CRecordVector(), CRecordVector()); - WriteUnpackInfo(folders); + WritePackInfo(headerOffset, packSizes, CUInt32DefVector()); + WriteUnpackInfo(folders, outFolders); WriteByte(NID::kEnd); - for (int i = 0; i < packSizes.Size(); i++) + FOR_VECTOR (i, packSizes) headerOffset += packSizes[i]; } RINOK(_outByte.Flush()); @@ -842,24 +873,28 @@ HRESULT COutArchive::WriteDatabase( } } -void CArchiveDatabase::GetFile(int index, CFileItem &file, CFileItem2 &file2) const +void CUInt64DefVector::SetItem(unsigned index, bool defined, UInt64 value) { - file = Files[index]; - file2.CTimeDefined = CTime.GetItem(index, file2.CTime); - file2.ATimeDefined = ATime.GetItem(index, file2.ATime); - file2.MTimeDefined = MTime.GetItem(index, file2.MTime); - file2.StartPosDefined = StartPos.GetItem(index, file2.StartPos); - file2.IsAnti = IsItemAnti(index); + while (index >= Defs.Size()) + Defs.Add(false); + Defs[index] = defined; + if (!defined) + return; + while (index >= Vals.Size()) + Vals.Add(0); + Vals[index] = value; } -void CArchiveDatabase::AddFile(const CFileItem &file, const CFileItem2 &file2) +void CArchiveDatabaseOut::AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name) { - int index = Files.Size(); + unsigned index = Files.Size(); CTime.SetItem(index, file2.CTimeDefined, file2.CTime); ATime.SetItem(index, file2.ATimeDefined, file2.ATime); MTime.SetItem(index, file2.MTimeDefined, file2.MTime); StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos); - SetItemAnti(index, file2.IsAnti); + SetItem_Anti(index, file2.IsAnti); + // SetItem_Aux(index, file2.IsAux); + Names.Add(name); Files.Add(file); } diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.h b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.h index 7b1b528e6..391ca9d02 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.h @@ -9,6 +9,7 @@ #include "7zItem.h" #include "../../Common/OutBuffer.h" +#include "../../Common/StreamUtils.h" namespace NArchive { namespace N7z { @@ -45,27 +46,191 @@ public: struct CHeaderOptions { bool CompressMainHeader; + /* bool WriteCTime; bool WriteATime; bool WriteMTime; + */ CHeaderOptions(): - CompressMainHeader(true), - WriteCTime(false), - WriteATime(false), - WriteMTime(true) + CompressMainHeader(true) + /* + , WriteCTime(false) + , WriteATime(false) + , WriteMTime(true) + */ {} }; + +struct CFileItem2 +{ + UInt64 CTime; + UInt64 ATime; + UInt64 MTime; + UInt64 StartPos; + bool CTimeDefined; + bool ATimeDefined; + bool MTimeDefined; + bool StartPosDefined; + bool IsAnti; + // bool IsAux; + + void Init() + { + CTimeDefined = false; + ATimeDefined = false; + MTimeDefined = false; + StartPosDefined = false; + IsAnti = false; + // IsAux = false; + } +}; + +struct COutFolders +{ + CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only. + + CRecordVector NumUnpackStreamsVector; + CRecordVector CoderUnpackSizes; // including unpack sizes of bind coders + + void OutFoldersClear() + { + FolderUnpackCRCs.Clear(); + NumUnpackStreamsVector.Clear(); + CoderUnpackSizes.Clear(); + } + + void OutFoldersReserveDown() + { + FolderUnpackCRCs.ReserveDown(); + NumUnpackStreamsVector.ReserveDown(); + CoderUnpackSizes.ReserveDown(); + } +}; + +struct CArchiveDatabaseOut: public COutFolders +{ + CRecordVector PackSizes; + CUInt32DefVector PackCRCs; + CObjectVector Folders; + + CRecordVector Files; + UStringVector Names; + CUInt64DefVector CTime; + CUInt64DefVector ATime; + CUInt64DefVector MTime; + CUInt64DefVector StartPos; + CRecordVector IsAnti; + + /* + CRecordVector IsAux; + + CByteBuffer SecureBuf; + CRecordVector SecureSizes; + CRecordVector SecureIDs; + + void ClearSecure() + { + SecureBuf.Free(); + SecureSizes.Clear(); + SecureIDs.Clear(); + } + */ + + void Clear() + { + OutFoldersClear(); + + PackSizes.Clear(); + PackCRCs.Clear(); + Folders.Clear(); + + Files.Clear(); + Names.Clear(); + CTime.Clear(); + ATime.Clear(); + MTime.Clear(); + StartPos.Clear(); + IsAnti.Clear(); + + /* + IsAux.Clear(); + ClearSecure(); + */ + } + + void ReserveDown() + { + OutFoldersReserveDown(); + + PackSizes.ReserveDown(); + PackCRCs.ReserveDown(); + Folders.ReserveDown(); + + Files.ReserveDown(); + Names.ReserveDown(); + CTime.ReserveDown(); + ATime.ReserveDown(); + MTime.ReserveDown(); + StartPos.ReserveDown(); + IsAnti.ReserveDown(); + + /* + IsAux.ReserveDown(); + */ + } + + bool IsEmpty() const + { + return ( + PackSizes.IsEmpty() && + NumUnpackStreamsVector.IsEmpty() && + Folders.IsEmpty() && + Files.IsEmpty()); + } + + bool CheckNumFiles() const + { + unsigned size = Files.Size(); + return ( + CTime.CheckSize(size) && + ATime.CheckSize(size) && + MTime.CheckSize(size) && + StartPos.CheckSize(size) && + (size == IsAnti.Size() || IsAnti.Size() == 0)); + } + + bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); } + // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); } + + void SetItem_Anti(unsigned index, bool isAnti) + { + while (index >= IsAnti.Size()) + IsAnti.Add(false); + IsAnti[index] = isAnti; + } + /* + void SetItem_Aux(unsigned index, bool isAux) + { + while (index >= IsAux.Size()) + IsAux.Add(false); + IsAux[index] = isAux; + } + */ + + void AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name); +}; + class COutArchive { UInt64 _prefixHeaderPos; - HRESULT WriteDirect(const void *data, UInt32 size); - + HRESULT WriteDirect(const void *data, UInt32 size) { return WriteStream(SeqStream, data, size); } + UInt64 GetPos() const; void WriteBytes(const void *data, size_t size); - void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.GetCapacity()); } + void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.Size()); } void WriteByte(Byte b); void WriteUInt32(UInt32 value); void WriteUInt64(UInt64 value); @@ -75,38 +240,38 @@ class COutArchive void WriteFolder(const CFolder &folder); HRESULT WriteFileHeader(const CFileItem &itemInfo); void WriteBoolVector(const CBoolVector &boolVector); - void WriteHashDigests( - const CRecordVector &digestsDefined, - const CRecordVector &hashDigests); + void WritePropBoolVector(Byte id, const CBoolVector &boolVector); + + void WriteHashDigests(const CUInt32DefVector &digests); void WritePackInfo( UInt64 dataOffset, const CRecordVector &packSizes, - const CRecordVector &packCRCsDefined, - const CRecordVector &packCRCs); + const CUInt32DefVector &packCRCs); - void WriteUnpackInfo(const CObjectVector &folders); + void WriteUnpackInfo( + const CObjectVector &folders, + const COutFolders &outFolders); void WriteSubStreamsInfo( const CObjectVector &folders, - const CRecordVector &numUnpackStreamsInFolders, + const COutFolders &outFolders, const CRecordVector &unpackSizes, - const CRecordVector &digestsDefined, - const CRecordVector &hashDigests); + const CUInt32DefVector &digests); void SkipAlign(unsigned pos, unsigned alignSize); - void WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize); + void WriteAlignedBoolHeader(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSize); void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type); HRESULT EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, - CRecordVector &packSizes, CObjectVector &folders); + CRecordVector &packSizes, CObjectVector &folders, COutFolders &outFolders); void WriteHeader( - const CArchiveDatabase &db, - const CHeaderOptions &headerOptions, + const CArchiveDatabaseOut &db, + // const CHeaderOptions &headerOptions, UInt64 &headerOffset); - + bool _countMode; bool _writeToStream; size_t _countSize; @@ -118,6 +283,8 @@ class COutArchive bool _endMarker; #endif + bool _useAlign; + HRESULT WriteSignature(); #ifdef _7Z_VOL HRESULT WriteFinishSignature(); @@ -136,7 +303,7 @@ public: HRESULT SkipPrefixArchiveHeader(); HRESULT WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS - const CArchiveDatabase &db, + const CArchiveDatabaseOut &db, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions); diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zProperties.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zProperties.cpp index fd4af49c7..a29f8abe9 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zProperties.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zProperties.cpp @@ -17,12 +17,12 @@ struct CPropMap STATPROPSTG StatPROPSTG; }; -CPropMap kPropMap[] = +static const CPropMap kPropMap[] = { { NID::kName, { NULL, kpidPath, VT_BSTR } }, { NID::kSize, { NULL, kpidSize, VT_UI8 } }, { NID::kPackInfo, { NULL, kpidPackSize, VT_UI8 } }, - + #ifdef _MULTI_PACK { 100, { L"Pack0", kpidPackedSize0, VT_UI8 } }, { 101, { L"Pack1", kpidPackedSize1, VT_UI8 } }, @@ -34,11 +34,12 @@ CPropMap kPropMap[] = { NID::kCTime, { NULL, kpidCTime, VT_FILETIME } }, { NID::kMTime, { NULL, kpidMTime, VT_FILETIME } }, { NID::kATime, { NULL, kpidATime, VT_FILETIME } }, - { NID::kWinAttributes, { NULL, kpidAttrib, VT_UI4 } }, + { NID::kWinAttrib, { NULL, kpidAttrib, VT_UI4 } }, { NID::kStartPos, { NULL, kpidPosition, VT_UI4 } }, { NID::kCRC, { NULL, kpidCRC, VT_UI4 } }, - + +// { NID::kIsAux, { NULL, kpidIsAux, VT_BOOL } }, { NID::kAnti, { NULL, kpidIsAnti, VT_BOOL } } #ifndef _SFX @@ -49,11 +50,9 @@ CPropMap kPropMap[] = #endif }; -static const int kPropMapSize = sizeof(kPropMap) / sizeof(kPropMap[0]); - static int FindPropInMap(UInt64 filePropID) { - for (int i = 0; i < kPropMapSize; i++) + for (int i = 0; i < ARRAY_SIZE(kPropMap); i++) if (kPropMap[i].FilePropID == filePropID) return i; return -1; @@ -62,7 +61,7 @@ static int FindPropInMap(UInt64 filePropID) static void CopyOneItem(CRecordVector &src, CRecordVector &dest, UInt32 item) { - for (int i = 0; i < src.Size(); i++) + FOR_VECTOR (i, src) if (src[i] == item) { dest.Add(item); @@ -73,7 +72,7 @@ static void CopyOneItem(CRecordVector &src, static void RemoveOneItem(CRecordVector &src, UInt32 item) { - for (int i = 0; i < src.Size(); i++) + FOR_VECTOR (i, src) if (src[i] == item) { src.Delete(i); @@ -83,7 +82,7 @@ static void RemoveOneItem(CRecordVector &src, UInt32 item) static void InsertToHead(CRecordVector &dest, UInt32 item) { - for (int i = 0; i < dest.Size(); i++) + FOR_VECTOR (i, dest) if (dest[i] == item) { dest.Delete(i); @@ -92,34 +91,41 @@ static void InsertToHead(CRecordVector &dest, UInt32 item) dest.Insert(0, item); } +#define COPY_ONE_ITEM(id) CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::id); + void CHandler::FillPopIDs() { _fileInfoPopIDs.Clear(); #ifdef _7Z_VOL - if(_volumes.Size() < 1) + if (_volumes.Size() < 1) return; const CVolume &volume = _volumes.Front(); const CArchiveDatabaseEx &_db = volume.Database; #endif - CRecordVector fileInfoPopIDs = _db.ArchiveInfo.FileInfoPopIDs; + CRecordVector fileInfoPopIDs = _db.ArcInfo.FileInfoPopIDs; RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream); RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile); + /* + RemoveOneItem(fileInfoPopIDs, NID::kParent); + RemoveOneItem(fileInfoPopIDs, NID::kNtSecure); + */ + + COPY_ONE_ITEM(kName); + COPY_ONE_ITEM(kAnti); + COPY_ONE_ITEM(kSize); + COPY_ONE_ITEM(kPackInfo); + COPY_ONE_ITEM(kCTime); + COPY_ONE_ITEM(kMTime); + COPY_ONE_ITEM(kATime); + COPY_ONE_ITEM(kWinAttrib); + COPY_ONE_ITEM(kCRC); + COPY_ONE_ITEM(kComment); - CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kName); - CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kAnti); - CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kSize); - CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kPackInfo); - CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCTime); - CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kMTime); - CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kATime); - CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kWinAttributes); - CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCRC); - CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kComment); _fileInfoPopIDs += fileInfoPopIDs; - + #ifndef _SFX _fileInfoPopIDs.Add(97); _fileInfoPopIDs.Add(98); @@ -141,9 +147,9 @@ void CHandler::FillPopIDs() #endif } -STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) +STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) { - *numProperties = _fileInfoPopIDs.Size(); + *numProps = _fileInfoPopIDs.Size(); return S_OK; } diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zRegister.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zRegister.cpp index 6e9bf6b99..37ea29d30 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zRegister.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zRegister.cpp @@ -5,14 +5,21 @@ #include "../../Common/RegisterArc.h" #include "7zHandler.h" -static IInArchive *CreateArc() { return new NArchive::N7z::CHandler; } -#ifndef EXTRACT_ONLY -static IOutArchive *CreateArcOut() { return new NArchive::N7z::CHandler; } -#else -#define CreateArcOut 0 -#endif + +namespace NArchive { +namespace N7z { + +IMP_CreateArcIn +IMP_CreateArcOut static CArcInfo g_ArcInfo = - { L"7z", L"7z", 0, 7, {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}, 6, false, CreateArc, CreateArcOut }; + { "7z", "7z", 0, 7, + 6, {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C}, + 0, + NArcInfoFlags::kFindSignature, + REF_CreateArc_Pair }; + +REGISTER_ARC_DEC_SIG(7z) +// REGISTER_ARC(7z) -REGISTER_ARC(7z) +}} diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zSpecStream.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zSpecStream.cpp index 06969636d..8e45d9875 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zSpecStream.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zSpecStream.cpp @@ -9,16 +9,14 @@ STDMETHODIMP CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32 UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; - if (processedSize != 0) + if (processedSize) *processedSize = realProcessedSize; return result; } -STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize( - UInt64 subStream, UInt64 *value) +STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize(UInt64 subStream, UInt64 *value) { - if (_getSubStreamSize == NULL) + if (!_getSubStreamSize) return E_NOTIMPL; - return _getSubStreamSize->GetSubStreamSize(subStream, value); + return _getSubStreamSize->GetSubStreamSize(subStream, value); } - diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.cpp index f07efc178..c745e32f0 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.cpp @@ -4,10 +4,11 @@ #include "../../../../C/CpuArch.h" -#include "../../Common/LimitedStreams.h" -#include "../../Common/ProgressUtils.h" +#include "../../../Common/Wildcard.h" #include "../../Common/CreateCoder.h" +#include "../../Common/LimitedStreams.h" +#include "../../Common/ProgressUtils.h" #include "../../Compress/CopyCoder.h" @@ -28,15 +29,6 @@ namespace NArchive { namespace N7z { -static const UInt64 k_LZMA = 0x030101; -static const UInt64 k_BCJ = 0x03030103; -static const UInt64 k_BCJ2 = 0x0303011B; - -static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2"; -static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20; -static const UInt32 kAlgorithmForBCJ2_LZMA = 1; -static const UInt32 kNumFastBytesForBCJ2_LZMA = 64; - #ifdef MY_CPU_X86_OR_AMD64 #define USE_86_FILTER #endif @@ -71,19 +63,20 @@ int CUpdateItem::GetExtensionPos() const int slashPos = GetReverseSlashPos(Name); int dotPos = Name.ReverseFind(L'.'); if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) - return Name.Length(); + return Name.Len(); return dotPos + 1; } UString CUpdateItem::GetExtension() const { - return Name.Mid(GetExtensionPos()); + return Name.Ptr(GetExtensionPos()); } #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } #define RINOZ_COMP(a, b) RINOZ(MyCompare(a, b)) +/* static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2) { size_t c1 = a1.GetCapacity(); @@ -123,11 +116,12 @@ static int CompareFolders(const CFolder &f1, const CFolder &f2) RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i])); return 0; } +*/ /* static int CompareFiles(const CFileItem &f1, const CFileItem &f2) { - return MyStringCompareNoCase(f1.Name, f2.Name); + return CompareFileNames(f1.Name, f2.Name); } */ @@ -138,15 +132,19 @@ struct CFolderRepack CNum NumCopyFiles; }; -static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void *param) +static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void * /* param */) { RINOZ_COMP(p1->Group, p2->Group); int i1 = p1->FolderIndex; int i2 = p2->FolderIndex; - const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)param; + /* + // In that version we don't want to parse folders here, so we don't compare folders + // probably it must be improved in future + const CDbEx &db = *(const CDbEx *)param; RINOZ(CompareFolders( db.Folders[i1], db.Folders[i2])); + */ return MyCompare(i1, i2); /* RINOZ_COMP( @@ -160,25 +158,31 @@ static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2 */ } -//////////////////////////////////////////////////////////// +/* + we sort empty files and dirs in such order: + - Dir.NonAnti (name sorted) + - File.NonAnti (name sorted) + - File.Anti (name sorted) + - Dir.Anti (reverse name sorted) +*/ static int CompareEmptyItems(const int *p1, const int *p2, void *param) { const CObjectVector &updateItems = *(const CObjectVector *)param; const CUpdateItem &u1 = updateItems[*p1]; const CUpdateItem &u2 = updateItems[*p2]; + // NonAnti < Anti + if (u1.IsAnti != u2.IsAnti) + return (u1.IsAnti ? 1 : -1); if (u1.IsDir != u2.IsDir) - return (u1.IsDir) ? 1 : -1; - if (u1.IsDir) { - if (u1.IsAnti != u2.IsAnti) + // Dir.NonAnti < File < Dir.Anti + if (u1.IsDir) return (u1.IsAnti ? 1 : -1); - int n = MyStringCompareNoCase(u1.Name, u2.Name); - return -n; + return (u2.IsAnti ? -1 : 1); } - if (u1.IsAnti != u2.IsAnti) - return (u1.IsAnti ? 1 : -1); - return MyStringCompareNoCase(u1.Name, u2.Name); + int n = CompareFileNames(u1.Name, u2.Name); + return (u1.IsDir && u1.IsAnti) ? -n : n; } static const char *g_Exts = @@ -211,7 +215,7 @@ static const char *g_Exts = " exe dll ocx vbx sfx sys tlb awx com obj lib out o so " " pdb pch idb ncb opt"; -int GetExtIndex(const char *ext) +static int GetExtIndex(const char *ext) { int extIndex = 1; const char *p = g_Exts; @@ -250,7 +254,9 @@ struct CRefItem UInt32 Index; UInt32 ExtensionPos; UInt32 NamePos; - int ExtensionIndex; + unsigned ExtensionIndex; + + CRefItem() {}; CRefItem(UInt32 index, const CUpdateItem &ui, bool sortByType): UpdateItem(&ui), Index(index), @@ -261,64 +267,134 @@ struct CRefItem if (sortByType) { int slashPos = GetReverseSlashPos(ui.Name); - NamePos = ((slashPos >= 0) ? (slashPos + 1) : 0); + NamePos = slashPos + 1; int dotPos = ui.Name.ReverseFind(L'.'); - if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) - ExtensionPos = ui.Name.Length(); + if (dotPos < 0 || dotPos < slashPos) + ExtensionPos = ui.Name.Len(); else { ExtensionPos = dotPos + 1; - UString us = ui.Name.Mid(ExtensionPos); - if (!us.IsEmpty()) + if (ExtensionPos != ui.Name.Len()) { - us.MakeLower(); - int i; AString s; - for (i = 0; i < us.Length(); i++) + for (unsigned pos = ExtensionPos;; pos++) { - wchar_t c = us[i]; + wchar_t c = ui.Name[pos]; if (c >= 0x80) break; - s += (char)c; + if (c == 0) + { + ExtensionIndex = GetExtIndex(s); + break; + } + s += (char)MyCharLower_Ascii((char)c); } - if (i == us.Length()) - ExtensionIndex = GetExtIndex(s); - else - ExtensionIndex = 0; } } } } }; +struct CSortParam +{ + // const CObjectVector *TreeFolders; + bool SortByType; +}; + +/* + we sort files in such order: + - Dir.NonAnti (name sorted) + - alt streams + - Dirs + - Dir.Anti (reverse name sorted) +*/ + + static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param) { const CRefItem &a1 = *p1; const CRefItem &a2 = *p2; const CUpdateItem &u1 = *a1.UpdateItem; const CUpdateItem &u2 = *a2.UpdateItem; - int n; + + /* + if (u1.IsAltStream != u2.IsAltStream) + return u1.IsAltStream ? 1 : -1; + */ + + // Actually there are no dirs that time. They were stored in other steps + // So that code is unused? if (u1.IsDir != u2.IsDir) - return (u1.IsDir) ? 1 : -1; + return u1.IsDir ? 1 : -1; if (u1.IsDir) { if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); - n = MyStringCompareNoCase(u1.Name, u2.Name); + int n = CompareFileNames(u1.Name, u2.Name); return -n; } - bool sortByType = *(bool *)param; + + // bool sortByType = *(bool *)param; + const CSortParam *sortParam = (const CSortParam *)param; + bool sortByType = sortParam->SortByType; if (sortByType) { RINOZ_COMP(a1.ExtensionIndex, a2.ExtensionIndex); - RINOZ(MyStringCompareNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.ExtensionPos)); - RINOZ(MyStringCompareNoCase(u1.Name + a1.NamePos, u2.Name + a2.NamePos)); + RINOZ(CompareFileNames(u1.Name.Ptr(a1.ExtensionPos), u2.Name.Ptr(a2.ExtensionPos))); + RINOZ(CompareFileNames(u1.Name.Ptr(a1.NamePos), u2.Name.Ptr(a2.NamePos))); if (!u1.MTimeDefined && u2.MTimeDefined) return 1; if (u1.MTimeDefined && !u2.MTimeDefined) return -1; if (u1.MTimeDefined && u2.MTimeDefined) RINOZ_COMP(u1.MTime, u2.MTime); RINOZ_COMP(u1.Size, u2.Size); } - return MyStringCompareNoCase(u1.Name, u2.Name); + /* + int par1 = a1.UpdateItem->ParentFolderIndex; + int par2 = a2.UpdateItem->ParentFolderIndex; + const CTreeFolder &tf1 = (*sortParam->TreeFolders)[par1]; + const CTreeFolder &tf2 = (*sortParam->TreeFolders)[par2]; + + int b1 = tf1.SortIndex, e1 = tf1.SortIndexEnd; + int b2 = tf2.SortIndex, e2 = tf2.SortIndexEnd; + if (b1 < b2) + { + if (e1 <= b2) + return -1; + // p2 in p1 + int par = par2; + for (;;) + { + const CTreeFolder &tf = (*sortParam->TreeFolders)[par]; + par = tf.Parent; + if (par == par1) + { + RINOZ(CompareFileNames(u1.Name, tf.Name)); + break; + } + } + } + else if (b2 < b1) + { + if (e2 <= b1) + return 1; + // p1 in p2 + int par = par1; + for (;;) + { + const CTreeFolder &tf = (*sortParam->TreeFolders)[par]; + par = tf.Parent; + if (par == par2) + { + RINOZ(CompareFileNames(tf.Name, u2.Name)); + break; + } + } + } + */ + // RINOZ_COMP(a1.UpdateItem->ParentSortIndex, a2.UpdateItem->ParentSortIndex); + RINOK(CompareFileNames(u1.Name, u2.Name)); + RINOZ_COMP(a1.UpdateItem->IndexInClient, a2.UpdateItem->IndexInClient); + RINOZ_COMP(a1.UpdateItem->IndexInArchive, a2.UpdateItem->IndexInArchive); + return 0; } struct CSolidGroup @@ -327,19 +403,19 @@ struct CSolidGroup }; #ifdef _WIN32 -static wchar_t *g_ExeExts[] = +static const wchar_t *g_ExeExts[] = { - L"dll", - L"exe", - L"ocx", - L"sfx", - L"sys" + L"dll" + , L"exe" + , L"ocx" + , L"sfx" + , L"sys" }; -static bool IsExeExt(const UString &ext) +static bool IsExeExt(const wchar_t *ext) { - for (int i = 0; i < sizeof(g_ExeExts) / sizeof(g_ExeExts[0]); i++) - if (ext.CompareNoCase(g_ExeExts[i]) == 0) + for (int i = 0; i < ARRAY_SIZE(g_ExeExts); i++) + if (MyStringCompareNoCase(ext, g_ExeExts[i]) == 0) return true; return false; } @@ -361,7 +437,7 @@ static bool IsExeFile(const CUpdateItem &ui) { for(UInt32 i = 0; i < processedSize ; i++) { - if (buffer[i] == 0) + if (buffer[i] == 0) { return true; // this file is not a text (ascii, utf8, ...) ! } @@ -369,112 +445,97 @@ static bool IsExeFile(const CUpdateItem &ui) } } } - } + } return false; } #endif -#ifdef USE_86_FILTER -static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult) +static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &m) +{ + m.Id = methodID; + m.NumInStreams = numInStreams; + m.NumOutStreams = 1; +} + +static void AddBcj2Methods(CCompressionMethodMode &mode) { - methodResult.Id = methodID; - methodResult.NumInStreams = numInStreams; - methodResult.NumOutStreams = 1; + CMethodFull m; + GetMethodFull(k_LZMA, 1, m); + + m.AddProp32(NCoderPropID::kDictionarySize, 1 << 20); + m.AddProp32(NCoderPropID::kNumFastBytes, 128); + m.AddProp32(NCoderPropID::kNumThreads, 1); + m.AddProp32(NCoderPropID::kLitPosBits, 2); + m.AddProp32(NCoderPropID::kLitContextBits, 0); + // m.AddPropString(NCoderPropID::kMatchFinder, L"BT2"); + + mode.Methods.Add(m); + mode.Methods.Add(m); + + CBind bind; + bind.OutCoder = 0; + bind.InStream = 0; + bind.InCoder = 1; bind.OutStream = 0; mode.Binds.Add(bind); + bind.InCoder = 2; bind.OutStream = 1; mode.Binds.Add(bind); + bind.InCoder = 3; bind.OutStream = 2; mode.Binds.Add(bind); } -static void MakeExeMethod(const CCompressionMethodMode &method, - bool bcj2Filter, CCompressionMethodMode &exeMethod) +static void MakeExeMethod(CCompressionMethodMode &mode, + bool useFilters, bool addFilter, bool bcj2Filter) { - exeMethod = method; + if (!mode.Binds.IsEmpty() || !useFilters || mode.Methods.Size() > 2) + return; + if (mode.Methods.Size() == 2) + { + if (mode.Methods[0].Id == k_BCJ2) + AddBcj2Methods(mode); + return; + } + if (!addFilter) + return; + bcj2Filter = bcj2Filter; + #ifdef USE_86_FILTER if (bcj2Filter) { - CMethodFull methodFull; - GetMethodFull(k_BCJ2, 4, methodFull); - exeMethod.Methods.Insert(0, methodFull); - GetMethodFull(k_LZMA, 1, methodFull); - { - CProp prop; - prop.Id = NCoderPropID::kAlgorithm; - prop.Value = kAlgorithmForBCJ2_LZMA; - methodFull.Props.Add(prop); - } - { - CProp prop; - prop.Id = NCoderPropID::kMatchFinder; - prop.Value = kMatchFinderForBCJ2_LZMA; - methodFull.Props.Add(prop); - } - { - CProp prop; - prop.Id = NCoderPropID::kDictionarySize; - prop.Value = kDictionaryForBCJ2_LZMA; - methodFull.Props.Add(prop); - } - { - CProp prop; - prop.Id = NCoderPropID::kNumFastBytes; - prop.Value = kNumFastBytesForBCJ2_LZMA; - methodFull.Props.Add(prop); - } - { - CProp prop; - prop.Id = NCoderPropID::kNumThreads; - prop.Value = (UInt32)1; - methodFull.Props.Add(prop); - } - - exeMethod.Methods.Add(methodFull); - exeMethod.Methods.Add(methodFull); - CBind bind; - - bind.OutCoder = 0; - bind.InStream = 0; - - bind.InCoder = 1; - bind.OutStream = 0; - exeMethod.Binds.Add(bind); - - bind.InCoder = 2; - bind.OutStream = 1; - exeMethod.Binds.Add(bind); - - bind.InCoder = 3; - bind.OutStream = 2; - exeMethod.Binds.Add(bind); + CMethodFull m; + GetMethodFull(k_BCJ2, 4, m); + mode.Methods.Insert(0, m); + AddBcj2Methods(mode); } else { - CMethodFull methodFull; - GetMethodFull(k_BCJ, 1, methodFull); - exeMethod.Methods.Insert(0, methodFull); + CMethodFull m; + GetMethodFull(k_BCJ, 1, m); + mode.Methods.Insert(0, m); CBind bind; bind.OutCoder = 0; bind.InStream = 0; bind.InCoder = 1; bind.OutStream = 0; - exeMethod.Binds.Add(bind); + mode.Binds.Add(bind); } + #endif } -#endif static void FromUpdateItemToFileItem(const CUpdateItem &ui, CFileItem &file, CFileItem2 &file2) { - file.Name = NItemName::MakeLegalName(ui.Name); if (ui.AttribDefined) file.SetAttrib(ui.Attrib); - + file2.CTime = ui.CTime; file2.CTimeDefined = ui.CTimeDefined; file2.ATime = ui.ATime; file2.ATimeDefined = ui.ATimeDefined; file2.MTime = ui.MTime; file2.MTimeDefined = ui.MTimeDefined; file2.IsAnti = ui.IsAnti; + // file2.IsAux = false; file2.StartPosDefined = false; file.Size = ui.Size; file.IsDir = ui.IsDir; file.HasStream = ui.HasStream(); + // file.IsAltStream = ui.IsAltStream; } class CFolderOutStream2: @@ -483,11 +544,11 @@ class CFolderOutStream2: { COutStreamWithCRC *_crcStreamSpec; CMyComPtr _crcStream; - const CArchiveDatabaseEx *_db; + const CDbEx *_db; const CBoolVector *_extractStatuses; CMyComPtr _outStream; UInt32 _startIndex; - int _currentIndex; + unsigned _currentIndex; bool _fileIsOpen; UInt64 _rem; @@ -497,14 +558,14 @@ class CFolderOutStream2: HRESULT ProcessEmptyFiles(); public: MY_UNKNOWN_IMP - + CFolderOutStream2() { _crcStreamSpec = new COutStreamWithCRC; _crcStream = _crcStreamSpec; } - HRESULT Init(const CArchiveDatabaseEx *db, UInt32 startIndex, + HRESULT Init(const CDbEx *db, UInt32 startIndex, const CBoolVector *extractStatuses, ISequentialOutStream *outStream); void ReleaseOutStream(); HRESULT CheckFinishedState() const { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; } @@ -512,7 +573,7 @@ public: STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; -HRESULT CFolderOutStream2::Init(const CArchiveDatabaseEx *db, UInt32 startIndex, +HRESULT CFolderOutStream2::Init(const CDbEx *db, UInt32 startIndex, const CBoolVector *extractStatuses, ISequentialOutStream *outStream) { _db = db; @@ -611,13 +672,13 @@ public: CMyComPtr Fos; UInt64 StartPos; - const UInt64 *PackSizes; - const CFolder *Folder; + const CFolders *Folders; + int FolderIndex; #ifndef _NO_CRYPTO - CMyComPtr GetTextPassword; + CMyComPtr getTextPassword; #endif - DECL_EXTERNAL_CODECS_VARS + DECL_EXTERNAL_CODECS_LOC_VARS2; CDecoder Decoder; #ifndef _7ZIP_ST @@ -636,6 +697,7 @@ public: Fos = FosSpec; Result = E_FAIL; } + ~CThreadDecoder() { CVirtThread::WaitThreadFinish(); } virtual void Execute(); }; @@ -644,21 +706,20 @@ void CThreadDecoder::Execute() try { #ifndef _NO_CRYPTO - bool passwordIsDefined; + bool isEncrypted = false; + bool passwordIsDefined = false; #endif + Result = Decoder.Decode( - EXTERNAL_CODECS_VARS + EXTERNAL_CODECS_LOC_VARS InStream, StartPos, - PackSizes, - *Folder, + *Folders, FolderIndex, Fos, NULL - #ifndef _NO_CRYPTO - , GetTextPassword, passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS #ifndef _7ZIP_ST - , MtMode, NumThreads + , MtMode, NumThreads #endif ); } @@ -673,7 +734,7 @@ void CThreadDecoder::Execute() bool static Is86FilteredFolder(const CFolder &f) { - for (int i = 0; i < f.Coders.Size(); i++) + FOR_VECTOR(i, f.Coders) { CMethodId m = f.Coders[i].MethodID; if (m == k_BCJ || m == k_BCJ2) @@ -704,20 +765,31 @@ STDMETHODIMP CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password) static const int kNumGroupsMax = 4; -#ifdef USE_86_FILTER static bool Is86Group(int group) { return (group & 1) != 0; } -#endif static bool IsEncryptedGroup(int group) { return (group & 2) != 0; } static int GetGroupIndex(bool encrypted, int bcjFiltered) { return (encrypted ? 2 : 0) + (bcjFiltered ? 1 : 0); } +static void GetFile(const CDatabase &inDb, int index, CFileItem &file, CFileItem2 &file2) +{ + file = inDb.Files[index]; + file2.CTimeDefined = inDb.CTime.GetItem(index, file2.CTime); + file2.ATimeDefined = inDb.ATime.GetItem(index, file2.ATime); + file2.MTimeDefined = inDb.MTime.GetItem(index, file2.MTime); + file2.StartPosDefined = inDb.StartPos.GetItem(index, file2.StartPos); + file2.IsAnti = inDb.IsItemAnti(index); + // file2.IsAux = inDb.IsItemAux(index); +} + HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, - const CArchiveDatabaseEx *db, + const CDbEx *db, const CObjectVector &updateItems, + // const CObjectVector &treeFolders, + // const CUniqBlocks &secureBlocks, COutArchive &archive, - CArchiveDatabase &newDatabase, + CArchiveDatabaseOut &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options @@ -729,6 +801,9 @@ HRESULT Update( UInt64 numSolidFiles = options.NumSolidFiles; if (numSolidFiles == 0) numSolidFiles = 1; + + // size_t totalSecureDataSize = (size_t)secureBlocks.GetTotalSizeInBytes(); + /* CMyComPtr outStream; RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream)); @@ -736,23 +811,23 @@ HRESULT Update( return E_NOTIMPL; */ - UInt64 startBlockSize = db != 0 ? db->ArchiveInfo.StartPosition: 0; + UInt64 startBlockSize = db != 0 ? db->ArcInfo.StartPosition: 0; if (startBlockSize > 0 && !options.RemoveSfxBlock) { RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL)); } - CRecordVector fileIndexToUpdateIndexMap; + CIntArr fileIndexToUpdateIndexMap; CRecordVector folderRefs; UInt64 complexity = 0; UInt64 inSizeForReduce2 = 0; bool needEncryptedRepack = false; if (db != 0) { - fileIndexToUpdateIndexMap.Reserve(db->Files.Size()); - int i; + fileIndexToUpdateIndexMap.Alloc(db->Files.Size()); + unsigned i; for (i = 0; i < db->Files.Size(); i++) - fileIndexToUpdateIndexMap.Add(-1); + fileIndexToUpdateIndexMap[i] = -1; for (i = 0; i < updateItems.Size(); i++) { @@ -761,7 +836,7 @@ HRESULT Update( fileIndexToUpdateIndexMap[index] = i; } - for (i = 0; i < db->Folders.Size(); i++) + for (i = 0; i < (int)db->NumFolders; i++) { CNum indexInFolder = 0; CNum numCopyItems = 0; @@ -788,7 +863,8 @@ HRESULT Update( CFolderRepack rep; rep.FolderIndex = i; rep.NumCopyFiles = numCopyItems; - const CFolder &f = db->Folders[i]; + CFolder f; + db->ParseFolderInfo(i, f); bool isEncrypted = f.IsEncrypted(); rep.Group = GetGroupIndex(isEncrypted, Is86FilteredFolder(f)); folderRefs.Add(rep); @@ -807,7 +883,7 @@ HRESULT Update( } UInt64 inSizeForReduce = 0; - int i; + unsigned i; for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; @@ -824,32 +900,30 @@ HRESULT Update( if (inSizeForReduce2 > inSizeForReduce) inSizeForReduce = inSizeForReduce2; - const UInt32 kMinReduceSize = (1 << 16); - if (inSizeForReduce < kMinReduceSize) - inSizeForReduce = kMinReduceSize; - RINOK(updateCallback->SetTotal(complexity)); CLocalProgress *lps = new CLocalProgress; CMyComPtr progress = lps; lps->Init(updateCallback, true); + CStreamBinder sb; + RINOK(sb.CreateEvents()); + CThreadDecoder threadDecoder; if (!folderRefs.IsEmpty()) { #ifdef EXTERNAL_CODECS - threadDecoder._codecsInfo = codecsInfo; - threadDecoder._externalCodecs = *externalCodecs; + threadDecoder.__externalCodecs = __externalCodecs; #endif RINOK(threadDecoder.Create()); } CObjectVector groups; for (i = 0; i < kNumGroupsMax; i++) - groups.Add(CSolidGroup()); + groups.AddNew(); { - // ---------- Split files to 2 groups ---------- + // ---------- Split files to groups ---------- bool useFilters = options.UseFilters; const CCompressionMethodMode &method = *options.Method; @@ -866,7 +940,7 @@ HRESULT Update( #ifdef _WIN32 int dotPos = ui.Name.ReverseFind(L'.'); if (dotPos >= 0) - filteredGroup = IsExeExt(ui.Name.Mid(dotPos + 1)); + filteredGroup = IsExeExt(ui.Name.Ptr(dotPos + 1)); #else filteredGroup = IsExeFile(ui); #endif @@ -881,7 +955,7 @@ HRESULT Update( if (needEncryptedRepack) { getPasswordSpec = new CCryptoGetTextPassword; - threadDecoder.GetTextPassword = getPasswordSpec; + threadDecoder.getTextPassword = getPasswordSpec; if (options.Method->PasswordIsDefined) getPasswordSpec->Password = options.Method->Password; @@ -891,31 +965,119 @@ HRESULT Update( return E_NOTIMPL; CMyComBSTR password; RINOK(getDecoderPassword->CryptoGetTextPassword(&password)); - getPasswordSpec->Password = password; + if ((BSTR)password) + getPasswordSpec->Password = password; } } #endif + // ---------- Compress ---------- RINOK(archive.Create(seqOutStream, false)); RINOK(archive.SkipPrefixArchiveHeader()); - int folderRefIndex = 0; + /* + CIntVector treeFolderToArcIndex; + treeFolderToArcIndex.Reserve(treeFolders.Size()); + for (i = 0; i < treeFolders.Size(); i++) + treeFolderToArcIndex.Add(-1); + // ---------- Write Tree (only AUX dirs) ---------- + for (i = 1; i < treeFolders.Size(); i++) + { + const CTreeFolder &treeFolder = treeFolders[i]; + CFileItem file; + CFileItem2 file2; + file2.Init(); + int secureID = 0; + if (treeFolder.UpdateItemIndex < 0) + { + // we can store virtual dir item wuthout attrib, but we want all items have attrib. + file.SetAttrib(FILE_ATTRIBUTE_DIRECTORY); + file2.IsAux = true; + } + else + { + const CUpdateItem &ui = updateItems[treeFolder.UpdateItemIndex]; + // if item is not dir, then it's parent for alt streams. + // we will write such items later + if (!ui.IsDir) + continue; + secureID = ui.SecureIndex; + if (ui.NewProps) + FromUpdateItemToFileItem(ui, file, file2); + else + GetFile(*db, ui.IndexInArchive, file, file2); + } + file.Size = 0; + file.HasStream = false; + file.IsDir = true; + file.Parent = treeFolder.Parent; + + treeFolderToArcIndex[i] = newDatabase.Files.Size(); + newDatabase.AddFile(file, file2, treeFolder.Name); + + if (totalSecureDataSize != 0) + newDatabase.SecureIDs.Add(secureID); + } + */ + + { + /* ---------- Write non-AUX dirs and Empty files ---------- */ + CRecordVector emptyRefs; + for (i = 0; i < updateItems.Size(); i++) + { + const CUpdateItem &ui = updateItems[i]; + if (ui.NewData) + { + if (ui.HasStream()) + continue; + } + else if (ui.IndexInArchive != -1 && db->Files[ui.IndexInArchive].HasStream) + continue; + /* + if (ui.TreeFolderIndex >= 0) + continue; + */ + emptyRefs.Add(i); + } + emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems); + for (i = 0; i < emptyRefs.Size(); i++) + { + const CUpdateItem &ui = updateItems[emptyRefs[i]]; + CFileItem file; + CFileItem2 file2; + UString name; + if (ui.NewProps) + { + FromUpdateItemToFileItem(ui, file, file2); + name = ui.Name; + } + else + { + GetFile(*db, ui.IndexInArchive, file, file2); + db->GetPath(ui.IndexInArchive, name); + } + + /* + if (totalSecureDataSize != 0) + newDatabase.SecureIDs.Add(ui.SecureIndex); + file.Parent = ui.ParentFolderIndex; + */ + newDatabase.AddFile(file, file2, name); + } + } + + unsigned folderRefIndex = 0; lps->ProgressOffset = 0; for (int groupIndex = 0; groupIndex < kNumGroupsMax; groupIndex++) { const CSolidGroup &group = groups[groupIndex]; - CCompressionMethodMode method; - #ifdef USE_86_FILTER - if (Is86Group(groupIndex)) - MakeExeMethod(*options.Method, options.MaxFilter, method); - else - #endif - method = *options.Method; + CCompressionMethodMode method = *options.Method; + MakeExeMethod(method, options.UseFilters, Is86Group(groupIndex), options.MaxFilter); if (IsEncryptedGroup(groupIndex)) { @@ -942,36 +1104,36 @@ HRESULT Update( if (rep.Group != groupIndex) break; int folderIndex = rep.FolderIndex; - + if (rep.NumCopyFiles == db->NumUnpackStreamsVector[folderIndex]) { UInt64 packSize = db->GetFolderFullPackSize(folderIndex); RINOK(WriteRange(inStream, archive.SeqStream, db->GetFolderStreamPos(folderIndex, 0), packSize, progress)); lps->ProgressOffset += packSize; - - const CFolder &folder = db->Folders[folderIndex]; - CNum startIndex = db->FolderStartPackStreamIndex[folderIndex]; - for (int j = 0; j < folder.PackStreams.Size(); j++) + + CFolder &folder = newDatabase.Folders.AddNew(); + db->ParseFolderInfo(folderIndex, folder); + CNum startIndex = db->FoStartPackStreamIndex[folderIndex]; + for (unsigned j = 0; j < folder.PackStreams.Size(); j++) { - newDatabase.PackSizes.Add(db->PackSizes[startIndex + j]); + newDatabase.PackSizes.Add(db->GetStreamPackSize(startIndex + j)); // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]); // newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]); } - newDatabase.Folders.Add(folder); + + UInt32 indexStart = db->FoToCoderUnpackSizes[folderIndex]; + UInt32 indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1]; + for (; indexStart < indexEnd; indexStart++) + newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes[indexStart]); } else { - CStreamBinder sb; - RINOK(sb.CreateEvents()); - CMyComPtr sbOutStream; - CMyComPtr sbInStream; - sb.CreateStreams(&sbInStream, &sbOutStream); CBoolVector extractStatuses; - + CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; CNum indexInFolder = 0; - + for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) { bool needExtract = false; @@ -985,44 +1147,52 @@ HRESULT Update( extractStatuses.Add(needExtract); } - RINOK(threadDecoder.FosSpec->Init(db, db->FolderStartFileIndex[folderIndex], &extractStatuses, sbOutStream)); - sbOutStream.Release(); - - threadDecoder.InStream = inStream; - threadDecoder.Folder = &db->Folders[folderIndex]; - threadDecoder.StartPos = db->GetFolderStreamPos(folderIndex, 0); - threadDecoder.PackSizes = &db->PackSizes[db->FolderStartPackStreamIndex[folderIndex]]; - - threadDecoder.Start(); - - int startPackIndex = newDatabase.PackSizes.Size(); - CFolder newFolder; - RINOK(encoder.Encode( - EXTERNAL_CODECS_LOC_VARS - sbInStream, NULL, &inSizeForReduce, newFolder, - archive.SeqStream, newDatabase.PackSizes, progress)); - - threadDecoder.WaitFinish(); + unsigned startPackIndex = newDatabase.PackSizes.Size(); + UInt64 curUnpackSize; + { + CMyComPtr sbInStream; + { + CMyComPtr sbOutStream; + sb.CreateStreams(&sbInStream, &sbOutStream); + sb.ReInit(); + RINOK(threadDecoder.FosSpec->Init(db, db->FolderStartFileIndex[folderIndex], &extractStatuses, sbOutStream)); + } + + threadDecoder.InStream = inStream; + threadDecoder.Folders = (const CFolders *)db; + threadDecoder.FolderIndex = folderIndex; + threadDecoder.StartPos = db->ArcInfo.DataStartPosition; // db->GetFolderStreamPos(folderIndex, 0); + + threadDecoder.Start(); + + RINOK(encoder.Encode( + EXTERNAL_CODECS_LOC_VARS + sbInStream, NULL, &inSizeForReduce, + newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curUnpackSize, + archive.SeqStream, newDatabase.PackSizes, progress)); + + threadDecoder.WaitExecuteFinish(); + } RINOK(threadDecoder.Result); for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) lps->OutSize += newDatabase.PackSizes[startPackIndex]; - lps->InSize += newFolder.GetUnpackSize(); - - newDatabase.Folders.Add(newFolder); + lps->InSize += curUnpackSize; } - + newDatabase.NumUnpackStreamsVector.Add(rep.NumCopyFiles); - + CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; - + CNum indexInFolder = 0; for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) { CFileItem file; CFileItem2 file2; - db->GetFile(fi, file, file2); + GetFile(*db, fi, file, file2); + UString name; + db->GetPath(fi, name); if (file.HasStream) { indexInFolder++; @@ -1041,30 +1211,40 @@ HRESULT Update( uf.CrcDefined = file.CrcDefined; uf.HasStream = file.HasStream; file = uf; + name = ui.Name; } - newDatabase.AddFile(file, file2); + /* + file.Parent = ui.ParentFolderIndex; + if (ui.TreeFolderIndex >= 0) + treeFolderToArcIndex[ui.TreeFolderIndex] = newDatabase.Files.Size(); + if (totalSecureDataSize != 0) + newDatabase.SecureIDs.Add(ui.SecureIndex); + */ + newDatabase.AddFile(file, file2, name); } } } } - int numFiles = group.Indices.Size(); + unsigned numFiles = group.Indices.Size(); if (numFiles == 0) continue; CRecordVector refItems; - refItems.Reserve(numFiles); + refItems.ClearAndSetSize(numFiles); bool sortByType = (numSolidFiles > 1); for (i = 0; i < numFiles; i++) - refItems.Add(CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType)); - refItems.Sort(CompareUpdateItems, (void *)&sortByType); - - CRecordVector indices; - indices.Reserve(numFiles); + refItems[i] = CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType); + CSortParam sortParam; + // sortParam.TreeFolders = &treeFolders; + sortParam.SortByType = sortByType; + refItems.Sort(CompareUpdateItems, (void *)&sortParam); + + CObjArray indices(numFiles); for (i = 0; i < numFiles; i++) { UInt32 index = refItems[i].Index; - indices.Add(index); + indices[i] = index; /* const CUpdateItem &ui = updateItems[index]; CFileItem file; @@ -1077,7 +1257,7 @@ HRESULT Update( newDatabase.Files.Add(file); */ } - + for (i = 0; i < numFiles;) { UInt64 totalSize = 0; @@ -1096,7 +1276,7 @@ HRESULT Update( if (numSubFiles == 0) prevExtension = ext; else - if (ext.CompareNoCase(prevExtension) != 0) + if (!ext.IsEqualToNoCase(prevExtension)) break; } } @@ -1106,38 +1286,43 @@ HRESULT Update( CFolderInStream *inStreamSpec = new CFolderInStream; CMyComPtr solidInStream(inStreamSpec); inStreamSpec->Init(updateCallback, &indices[i], numSubFiles); - - CFolder folderItem; - int startPackIndex = newDatabase.PackSizes.Size(); + unsigned startPackIndex = newDatabase.PackSizes.Size(); + UInt64 curFolderUnpackSize; RINOK(encoder.Encode( EXTERNAL_CODECS_LOC_VARS - solidInStream, NULL, &inSizeForReduce, folderItem, + solidInStream, NULL, &inSizeForReduce, + newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curFolderUnpackSize, archive.SeqStream, newDatabase.PackSizes, progress)); for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) lps->OutSize += newDatabase.PackSizes[startPackIndex]; - lps->InSize += folderItem.GetUnpackSize(); + lps->InSize += curFolderUnpackSize; // for () // newDatabase.PackCRCsDefined.Add(false); // newDatabase.PackCRCs.Add(0); - - newDatabase.Folders.Add(folderItem); - + CNum numUnpackStreams = 0; for (int subIndex = 0; subIndex < numSubFiles; subIndex++) { const CUpdateItem &ui = updateItems[indices[i + subIndex]]; CFileItem file; CFileItem2 file2; + UString name; if (ui.NewProps) + { FromUpdateItemToFileItem(ui, file, file2); + name = ui.Name; + } else - db->GetFile(ui.IndexInArchive, file, file2); + { + GetFile(*db, ui.IndexInArchive, file, file2); + db->GetPath(ui.IndexInArchive, name); + } if (file2.IsAnti || file.IsDir) return E_FAIL; - + /* CFileItem &file = newDatabase.Files[ startFileIndexInDatabase + i + subIndex]; @@ -1161,7 +1346,14 @@ HRESULT Update( file.CrcDefined = false; file.HasStream = false; } - newDatabase.AddFile(file, file2); + /* + file.Parent = ui.ParentFolderIndex; + if (ui.TreeFolderIndex >= 0) + treeFolderToArcIndex[ui.TreeFolderIndex] = newDatabase.Files.Size(); + if (totalSecureDataSize != 0) + newDatabase.SecureIDs.Add(ui.SecureIndex); + */ + newDatabase.AddFile(file, file2, name); } // numUnpackStreams = 0 is very bad case for locked files // v3.13 doesn't understand it. @@ -1173,42 +1365,36 @@ HRESULT Update( if (folderRefIndex != folderRefs.Size()) return E_FAIL; + RINOK(lps->SetCur()); + /* folderRefs.ClearAndFree(); fileIndexToUpdateIndexMap.ClearAndFree(); groups.ClearAndFree(); */ + /* + for (i = 0; i < newDatabase.Files.Size(); i++) { - // ---------- Write Folders & Empty Files ---------- - - CRecordVector emptyRefs; - for (i = 0; i < updateItems.Size(); i++) - { - const CUpdateItem &ui = updateItems[i]; - if (ui.NewData) - { - if (ui.HasStream()) - continue; - } - else if (ui.IndexInArchive != -1 && db->Files[ui.IndexInArchive].HasStream) - continue; - emptyRefs.Add(i); - } - emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems); - for (i = 0; i < emptyRefs.Size(); i++) + CFileItem &file = newDatabase.Files[i]; + file.Parent = treeFolderToArcIndex[file.Parent]; + } + + if (totalSecureDataSize != 0) + { + newDatabase.SecureBuf.SetCapacity(totalSecureDataSize); + size_t pos = 0; + newDatabase.SecureSizes.Reserve(secureBlocks.Sorted.Size()); + for (i = 0; i < secureBlocks.Sorted.Size(); i++) { - const CUpdateItem &ui = updateItems[emptyRefs[i]]; - CFileItem file; - CFileItem2 file2; - if (ui.NewProps) - FromUpdateItemToFileItem(ui, file, file2); - else - db->GetFile(ui.IndexInArchive, file, file2); - newDatabase.AddFile(file, file2); + const CByteBuffer &buf = secureBlocks.Bufs[secureBlocks.Sorted[i]]; + size_t size = buf.GetCapacity(); + memcpy(newDatabase.SecureBuf + pos, buf, size); + newDatabase.SecureSizes.Add((UInt32)size); + pos += size; } } - + */ newDatabase.ReserveDown(); return S_OK; } diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.h b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.h index 31e362246..aee2d5ed3 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.h @@ -3,29 +3,54 @@ #ifndef __7Z_UPDATE_H #define __7Z_UPDATE_H +#include "../IArchive.h" + +// #include "../../Common/UniqBlocks.h" + #include "7zCompressionMode.h" #include "7zIn.h" #include "7zOut.h" -#include "../IArchive.h" - namespace NArchive { namespace N7z { +/* +struct CTreeFolder +{ + UString Name; + int Parent; + CIntVector SubFolders; + int UpdateItemIndex; + int SortIndex; + int SortIndexEnd; + + CTreeFolder(): UpdateItemIndex(-1) {} +}; +*/ + struct CUpdateItem { int IndexInArchive; int IndexInClient; - + UInt64 CTime; UInt64 ATime; UInt64 MTime; UInt64 Size; UString Name; + /* + bool IsAltStream; + int ParentFolderIndex; + int TreeFolderIndex; + */ + + // that code is not used in 9.26 + // int ParentSortIndex; + // int ParentSortIndexEnd; UInt32 Attrib; - + bool NewData; bool NewProps; @@ -37,15 +62,20 @@ struct CUpdateItem bool ATimeDefined; bool MTimeDefined; + // int SecureIndex; // 0 means (no_security) + bool HasStream() const { return !IsDir && !IsAnti && Size != 0; } CUpdateItem(): + // ParentSortIndex(-1), + // IsAltStream(false), IsAnti(false), IsDir(false), AttribDefined(false), CTimeDefined(false), ATimeDefined(false), MTimeDefined(false) + // SecureIndex(0) {} void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); }; @@ -72,10 +102,12 @@ struct CUpdateOptions HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, - const CArchiveDatabaseEx *db, + const CDbEx *db, const CObjectVector &updateItems, + // const CObjectVector &treeFolders, // treeFolders[0] is root + // const CUniqBlocks &secureBlocks, COutArchive &archive, - CArchiveDatabase &newDatabase, + CArchiveDatabaseOut &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Archive.pri b/src/libs/7zip/unix/CPP/7zip/Archive/Archive.pri new file mode 100644 index 000000000..fe77cb0d4 --- /dev/null +++ b/src/libs/7zip/unix/CPP/7zip/Archive/Archive.pri @@ -0,0 +1,5 @@ +HEADERS += $$7ZIP_BASE/CPP/7zip/Archive/IArchive.h + +SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/LzmaHandler.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/SplitHandler.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/XzHandler.cpp diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/ArchiveExports.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/ArchiveExports.cpp deleted file mode 100644 index c7908b591..000000000 --- a/src/libs/7zip/unix/CPP/7zip/Archive/ArchiveExports.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// ArchiveExports.cpp - -#include "StdAfx.h" - -#include "../../Common/ComTry.h" - -#include "../../Windows/PropVariant.h" - -#include "../Common/RegisterArc.h" - -static const unsigned int kNumArcsMax = 48; -static unsigned int g_NumArcs = 0; -static unsigned int g_DefaultArcIndex = 0; -static const CArcInfo *g_Arcs[kNumArcsMax]; -void RegisterArc(const CArcInfo *arcInfo) -{ - if (g_NumArcs < kNumArcsMax) - { - const wchar_t *p = arcInfo->Name; - if (p[0] == '7' && p[1] == 'z' && p[2] == 0) - g_DefaultArcIndex = g_NumArcs; - g_Arcs[g_NumArcs++] = arcInfo; - } -} - -DEFINE_GUID(CLSID_CArchiveHandler, -0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); - -#define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5]) - -static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value) -{ - if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) - value->vt = VT_BSTR; - return S_OK; -} - -static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) -{ - return SetPropString((const char *)&guid, sizeof(GUID), value); -} - -int FindFormatCalssId(const GUID *clsID) -{ - GUID cls = *clsID; - CLS_ARC_ID_ITEM(cls) = 0; - if (cls != CLSID_CArchiveHandler) - return -1; - Byte id = CLS_ARC_ID_ITEM(*clsID); - for (unsigned i = 0; i < g_NumArcs; i++) - if (g_Arcs[i]->ClassId == id) - return (int)i; - return -1; -} - -STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject) -{ - COM_TRY_BEGIN - { - int needIn = (*iid == IID_IInArchive); - int needOut = (*iid == IID_IOutArchive); - if (!needIn && !needOut) - return E_NOINTERFACE; - int formatIndex = FindFormatCalssId(clsid); - if (formatIndex < 0) - return CLASS_E_CLASSNOTAVAILABLE; - - const CArcInfo &arc = *g_Arcs[formatIndex]; - if (needIn) - { - *outObject = arc.CreateInArchive(); - ((IInArchive *)*outObject)->AddRef(); - } - else - { - if (!arc.CreateOutArchive) - return CLASS_E_CLASSNOTAVAILABLE; - *outObject = arc.CreateOutArchive(); - ((IOutArchive *)*outObject)->AddRef(); - } - } - COM_TRY_END - return S_OK; -} - -STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value) -{ - COM_TRY_BEGIN - if (formatIndex >= g_NumArcs) - return E_INVALIDARG; - const CArcInfo &arc = *g_Arcs[formatIndex]; - NWindows::NCOM::CPropVariant prop; - switch(propID) - { - case NArchive::kName: - prop = arc.Name; - break; - case NArchive::kClassID: - { - GUID clsId = CLSID_CArchiveHandler; - CLS_ARC_ID_ITEM(clsId) = arc.ClassId; - return SetPropGUID(clsId, value); - } - case NArchive::kExtension: - if (arc.Ext != 0) - prop = arc.Ext; - break; - case NArchive::kAddExtension: - if (arc.AddExt != 0) - prop = arc.AddExt; - break; - case NArchive::kUpdate: - prop = (bool)(arc.CreateOutArchive != 0); - break; - case NArchive::kKeepName: - prop = arc.KeepName; - break; - case NArchive::kStartSignature: - return SetPropString((const char *)arc.Signature, arc.SignatureSize, value); - } - prop.Detach(value); - return S_OK; - COM_TRY_END -} - -STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value) -{ - return GetHandlerProperty2(g_DefaultArcIndex, propID, value); -} - -STDAPI GetNumberOfFormats(UINT32 *numFormats) -{ - *numFormats = g_NumArcs; - return S_OK; -} diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2.cpp index 0b06a489f..e562fec58 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2.cpp @@ -11,16 +11,23 @@ CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo): { srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams); - UInt32 j; + UInt32 j; + _srcInToDestOutMap.ClearAndSetSize(NumSrcInStreams); + DestOutToSrcInMap.ClearAndSetSize(NumSrcInStreams); + for (j = 0; j < NumSrcInStreams; j++) { - _srcInToDestOutMap.Add(0); - DestOutToSrcInMap.Add(0); + _srcInToDestOutMap[j] = 0; + DestOutToSrcInMap[j] = 0; } + + _srcOutToDestInMap.ClearAndSetSize(_numSrcOutStreams); + _destInToSrcOutMap.ClearAndSetSize(_numSrcOutStreams); + for (j = 0; j < _numSrcOutStreams; j++) { - _srcOutToDestInMap.Add(0); - _destInToSrcOutMap.Add(0); + _srcOutToDestInMap[j] = 0; + _destInToSrcOutMap[j] = 0; } UInt32 destInOffset = 0; @@ -34,7 +41,7 @@ CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo): srcInOffset -= srcCoderInfo.NumInStreams; srcOutOffset -= srcCoderInfo.NumOutStreams; - + UInt32 j; for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++) { @@ -53,66 +60,57 @@ CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo): void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo) { - destBindInfo.Coders.Clear(); - destBindInfo.BindPairs.Clear(); - destBindInfo.InStreams.Clear(); - destBindInfo.OutStreams.Clear(); + destBindInfo.Coders.ClearAndReserve(_srcBindInfo.Coders.Size()); + destBindInfo.BindPairs.ClearAndReserve(_srcBindInfo.BindPairs.Size()); + destBindInfo.InStreams.ClearAndReserve(_srcBindInfo.OutStreams.Size()); + destBindInfo.OutStreams.ClearAndReserve(_srcBindInfo.InStreams.Size()); - int i; - for (i = _srcBindInfo.Coders.Size() - 1; i >= 0; i--) + unsigned i; + for (i = _srcBindInfo.Coders.Size(); i != 0;) { + i--; const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i]; CCoderStreamsInfo destCoderInfo; destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams; destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams; - destBindInfo.Coders.Add(destCoderInfo); + destBindInfo.Coders.AddInReserved(destCoderInfo); } - for (i = _srcBindInfo.BindPairs.Size() - 1; i >= 0; i--) + for (i = _srcBindInfo.BindPairs.Size(); i != 0;) { + i--; const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i]; CBindPair destBindPair; destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex]; destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex]; - destBindInfo.BindPairs.Add(destBindPair); + destBindInfo.BindPairs.AddInReserved(destBindPair); } for (i = 0; i < _srcBindInfo.InStreams.Size(); i++) - destBindInfo.OutStreams.Add(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]); + destBindInfo.OutStreams.AddInReserved(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]); for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++) - destBindInfo.InStreams.Add(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]); -} - -CCoderInfo2::CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams): - NumInStreams(numInStreams), - NumOutStreams(numOutStreams) -{ - InSizes.Reserve(NumInStreams); - InSizePointers.Reserve(NumInStreams); - OutSizes.Reserve(NumOutStreams); - OutSizePointers.Reserve(NumOutStreams); + destBindInfo.InStreams.AddInReserved(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]); } -static void SetSizes(const UInt64 **srcSizes, CRecordVector &sizes, +void SetSizes(const UInt64 **srcSizes, CRecordVector &sizes, CRecordVector &sizePointers, UInt32 numItems) { - sizes.Clear(); - sizePointers.Clear(); - for(UInt32 i = 0; i < numItems; i++) + sizes.ClearAndSetSize(numItems); + sizePointers.ClearAndSetSize(numItems); + for (UInt32 i = 0; i < numItems; i++) { - if (srcSizes == 0 || srcSizes[i] == NULL) + if (!srcSizes || !srcSizes[i]) { - sizes.Add(0); - sizePointers.Add(NULL); + sizes[i] = 0; + sizePointers[i] = NULL; } else { - sizes.Add(*srcSizes[i]); - sizePointers.Add(&sizes.Back()); + sizes[i] = *(srcSizes[i]); + sizePointers[i] = &sizes[i]; } } } -void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes, - const UInt64 **outSizes) +void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) { SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2.h b/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2.h index a03722d61..50e7077ae 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2.h @@ -3,9 +3,9 @@ #ifndef __CODER_MIXER2_H #define __CODER_MIXER2_H -#include "../../../Common/MyVector.h" -#include "../../../Common/Types.h" #include "../../../Common/MyCom.h" +#include "../../../Common/MyVector.h" + #include "../../ICoder.h" namespace NCoderMixer { @@ -52,7 +52,7 @@ struct CBindInfo { numInStreams = 0; numOutStreams = 0; - for (int i = 0; i < Coders.Size(); i++) + FOR_VECTOR (i, Coders) { const CCoderStreamsInfo &coderStreamsInfo = Coders[i]; numInStreams += coderStreamsInfo.NumInStreams; @@ -62,14 +62,14 @@ struct CBindInfo int FindBinderForInStream(UInt32 inStream) const { - for (int i = 0; i < BindPairs.Size(); i++) + FOR_VECTOR (i, BindPairs) if (BindPairs[i].InIndex == inStream) return i; return -1; } int FindBinderForOutStream(UInt32 outStream) const { - for (int i = 0; i < BindPairs.Size(); i++) + FOR_VECTOR (i, BindPairs) if (BindPairs[i].OutIndex == outStream) return i; return -1; @@ -139,6 +139,9 @@ public: void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo); }; +void SetSizes(const UInt64 **srcSizes, CRecordVector &sizes, + CRecordVector &sizePointers, UInt32 numItems); + struct CCoderInfo2 { CMyComPtr Coder; @@ -151,7 +154,9 @@ struct CCoderInfo2 CRecordVector InSizePointers; CRecordVector OutSizePointers; - CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams); + CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams): + NumInStreams(numInStreams), + NumOutStreams(numOutStreams) {} void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); HRESULT QueryInterface(REFGUID iid, void** pp) const @@ -170,5 +175,5 @@ public: }; } -#endif +#endif diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2MT.cpp index d76450bd1..36b252600 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2MT.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2MT.cpp @@ -9,30 +9,28 @@ namespace NCoderMixer { CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams): CCoderInfo2(numInStreams, numOutStreams) { - InStreams.Reserve(NumInStreams); - InStreamPointers.Reserve(NumInStreams); - OutStreams.Reserve(NumOutStreams); - OutStreamPointers.Reserve(NumOutStreams); + InStreams.ClearAndReserve(NumInStreams); + OutStreams.ClearAndReserve(NumOutStreams); } void CCoder2::Execute() { Code(NULL); } void CCoder2::Code(ICompressProgressInfo *progress) { - InStreamPointers.Clear(); - OutStreamPointers.Clear(); + InStreamPointers.ClearAndReserve(NumInStreams); + OutStreamPointers.ClearAndReserve(NumOutStreams); UInt32 i; for (i = 0; i < NumInStreams; i++) { - if (InSizePointers[i] != NULL) + if (InSizePointers[i]) InSizePointers[i] = &InSizes[i]; - InStreamPointers.Add((ISequentialInStream *)InStreams[i]); + InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]); } for (i = 0; i < NumOutStreams; i++) { - if (OutSizePointers[i] != NULL) + if (OutSizePointers[i]) OutSizePointers[i] = &OutSizes[i]; - OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]); + OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]); } if (Coder) Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0], @@ -41,7 +39,7 @@ void CCoder2::Code(ICompressProgressInfo *progress) Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams, &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress); { - int i; + unsigned i; for (i = 0; i < InStreams.Size(); i++) InStreams[i].Release(); for (i = 0; i < OutStreams.Size(); i++) @@ -49,32 +47,13 @@ void CCoder2::Code(ICompressProgressInfo *progress) } } -static void SetSizes(const UInt64 **srcSizes, CRecordVector &sizes, - CRecordVector &sizePointers, UInt32 numItems) -{ - sizes.Clear(); - sizePointers.Clear(); - for (UInt32 i = 0; i < numItems; i++) - { - if (srcSizes == 0 || srcSizes[i] == NULL) - { - sizes.Add(0); - sizePointers.Add(NULL); - } - else - { - sizes.Add(*srcSizes[i]); - sizePointers.Add(&sizes.Back()); - } - } -} - - +/* void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) { SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); } +*/ ////////////////////////////////////// // CCoderMixer2MT @@ -83,10 +62,9 @@ HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo) { _bindInfo = bindInfo; _streamBinders.Clear(); - for (int i = 0; i < _bindInfo.BindPairs.Size(); i++) + FOR_VECTOR (i, _bindInfo.BindPairs) { - _streamBinders.Add(CStreamBinder()); - RINOK(_streamBinders.Back().CreateEvents()); + RINOK(_streamBinders.AddNew().CreateEvents()); } return S_OK; } @@ -113,7 +91,7 @@ void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder) void CCoderMixer2MT::ReInit() { - for (int i = 0; i < _streamBinders.Size(); i++) + FOR_VECTOR (i, _streamBinders) _streamBinders[i].ReInit(); } @@ -124,7 +102,7 @@ HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStre if (_coders.Size() != _bindInfo.Coders.Size()) throw 0; */ - int i; + unsigned i; for (i = 0; i < _coders.Size(); i++) { CCoder2 &coderInfo = _coders[i]; @@ -167,7 +145,7 @@ HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStre _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex); _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i]; } - + for (i = 0; i < _bindInfo.OutStreams.Size(); i++) { UInt32 outCoderIndex, outCoderStreamIndex; @@ -179,7 +157,7 @@ HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStre HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code) { - for (int i = 0; i < _coders.Size(); i++) + FOR_VECTOR (i, _coders) if (_coders[i].Result == code) return code; return S_OK; @@ -199,7 +177,7 @@ STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams, Init(inStreams, outStreams); - int i; + unsigned i; for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) { @@ -214,7 +192,7 @@ STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams, for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) - _coders[i].WaitFinish(); + _coders[i].WaitExecuteFinish(); RINOK(ReturnIfError(E_ABORT)); RINOK(ReturnIfError(E_OUTOFMEMORY)); diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2MT.h b/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2MT.h index d1c7f4d07..2190cf867 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2MT.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2MT.h @@ -12,14 +12,17 @@ namespace NCoderMixer { struct CCoder2: public CCoderInfo2, public CVirtThread { + CRecordVector InStreamPointers; + CRecordVector OutStreamPointers; + +public: HRESULT Result; CObjectVector< CMyComPtr > InStreams; CObjectVector< CMyComPtr > OutStreams; - CRecordVector InStreamPointers; - CRecordVector OutStreamPointers; CCoder2(UInt32 numInStreams, UInt32 numOutStreams); - void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); + ~CCoder2() { CVirtThread::WaitThreadFinish(); } + // void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); virtual void Execute(); void Code(ICompressProgressInfo *progress); }; @@ -30,7 +33,7 @@ struct CCoder2: public CCoderInfo2, public CVirtThread for each coder AddCoder[2]() SetProgressIndex(UInt32 coderIndex); - + for each file { ReInit() @@ -47,7 +50,7 @@ class CCoderMixer2MT: { CBindInfo _bindInfo; CObjectVector _streamBinders; - int _progressCoderIndex; + unsigned _progressCoderIndex; void AddCoderCommon(); HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams); @@ -67,7 +70,7 @@ public: HRESULT SetBindInfo(const CBindInfo &bindInfo); void AddCoder(ICompressCoder *coder); void AddCoder2(ICompressCoder2 *coder); - void SetProgressCoderIndex(int coderIndex) { _progressCoderIndex = coderIndex; } + void SetProgressCoderIndex(unsigned coderIndex) { _progressCoderIndex = coderIndex; } void ReInit(); void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/Common.pri b/src/libs/7zip/unix/CPP/7zip/Archive/Common/Common.pri new file mode 100644 index 000000000..5443ba297 --- /dev/null +++ b/src/libs/7zip/unix/CPP/7zip/Archive/Common/Common.pri @@ -0,0 +1,18 @@ +HEADERS += $$7ZIP_BASE/CPP/7zip/Archive/Common/CoderMixer2.h \ + $$7ZIP_BASE/CPP/7zip/Archive/Common/CoderMixer2MT.h \ + $$7ZIP_BASE/CPP/7zip/Archive/Common/DummyOutStream.h \ + $$7ZIP_BASE/CPP/7zip/Archive/Common/HandlerOut.h \ + $$7ZIP_BASE/CPP/7zip/Archive/Common/InStreamWithCRC.h \ + $$7ZIP_BASE/CPP/7zip/Archive/Common/ItemNameUtils.h \ + $$7ZIP_BASE/CPP/7zip/Archive/Common/MultiStream.h \ + $$7ZIP_BASE/CPP/7zip/Archive/Common/OutStreamWithCRC.h \ + $$7ZIP_BASE/CPP/7zip/Archive/Common/ParseProperties.h + +SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/Common/CoderMixer2.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/Common/CoderMixer2MT.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/Common/DummyOutStream.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/Common/HandlerOut.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/Common/InStreamWithCRC.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/Common/ItemNameUtils.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/Common/MultiStream.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/CrossThreadProgress.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/Common/CrossThreadProgress.cpp deleted file mode 100644 index a974b54c7..000000000 --- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/CrossThreadProgress.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// CrossThreadProgress.cpp - -#include "StdAfx.h" - -#include "CrossThreadProgress.h" - -STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) -{ - InSize = inSize; - OutSize = outSize; - ProgressEvent.Set(); - WaitEvent.Lock(); - return Result; -} - diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/CrossThreadProgress.h b/src/libs/7zip/unix/CPP/7zip/Archive/Common/CrossThreadProgress.h deleted file mode 100644 index 7e0b10538..000000000 --- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/CrossThreadProgress.h +++ /dev/null @@ -1,37 +0,0 @@ -// CrossThreadProgress.h - -#ifndef __CROSSTHREADPROGRESS_H -#define __CROSSTHREADPROGRESS_H - -#include "../../ICoder.h" -#include "../../../Windows/Synchronization.h" -#include "../../../Common/MyCom.h" - -class CCrossThreadProgress: - public ICompressProgressInfo, - public CMyUnknownImp -{ -public: - const UInt64 *InSize; - const UInt64 *OutSize; - HRESULT Result; - NWindows::NSynchronization::CAutoResetEvent ProgressEvent; - NWindows::NSynchronization::CAutoResetEvent WaitEvent; - - HRes Create() - { - RINOK(ProgressEvent.CreateIfNotCreated()); - return WaitEvent.CreateIfNotCreated(); - } - void Init() - { - ProgressEvent.Reset(); - WaitEvent.Reset(); - } - - MY_UNKNOWN_IMP - - STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); -}; - -#endif diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/DummyOutStream.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/Common/DummyOutStream.cpp index 54bcfec11..7c4f54879 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/DummyOutStream.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/Common/DummyOutStream.cpp @@ -4,19 +4,14 @@ #include "DummyOutStream.h" -STDMETHODIMP CDummyOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +STDMETHODIMP CDummyOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { - UInt32 realProcessedSize; - HRESULT result; - if(!_stream) - { - realProcessedSize = size; - result = S_OK; - } - else - result = _stream->Write(data, size, &realProcessedSize); + UInt32 realProcessedSize = size; + HRESULT res = S_OK; + if (_stream) + res = _stream->Write(data, size, &realProcessedSize); _size += realProcessedSize; - if(processedSize != NULL) + if (processedSize) *processedSize = realProcessedSize; - return result; + return res; } diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/DummyOutStream.h b/src/libs/7zip/unix/CPP/7zip/Archive/Common/DummyOutStream.h index 13d5b62ca..b5a51fc07 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/DummyOutStream.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/Common/DummyOutStream.h @@ -1,10 +1,11 @@ // DummyOutStream.h -#ifndef __DUMMYOUTSTREAM_H -#define __DUMMYOUTSTREAM_H +#ifndef __DUMMY_OUT_STREAM_H +#define __DUMMY_OUT_STREAM_H + +#include "../../../Common/MyCom.h" #include "../../IStream.h" -#include "Common/MyCom.h" class CDummyOutStream: public ISequentialOutStream, diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/HandlerOut.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/Common/HandlerOut.cpp index 70ad47aad..7b875fbd0 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/HandlerOut.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/Common/HandlerOut.cpp @@ -2,16 +2,10 @@ #include "StdAfx.h" -#include "../../../Common/StringToInt.h" - -#include "../../../Windows/PropVariant.h" - #ifndef _7ZIP_ST #include "../../../Windows/System.h" #endif -#include "../../ICoder.h" - #include "../Common/ParseProperties.h" #include "HandlerOut.h" @@ -20,602 +14,126 @@ using namespace NWindows; namespace NArchive { -static const wchar_t *kCopyMethod = L"Copy"; -static const wchar_t *kLZMAMethodName = L"LZMA"; -static const wchar_t *kLZMA2MethodName = L"LZMA2"; -static const wchar_t *kBZip2MethodName = L"BZip2"; -static const wchar_t *kPpmdMethodName = L"PPMd"; -static const wchar_t *kDeflateMethodName = L"Deflate"; -static const wchar_t *kDeflate64MethodName = L"Deflate64"; - -static const wchar_t *kLzmaMatchFinderX1 = L"HC4"; -static const wchar_t *kLzmaMatchFinderX5 = L"BT4"; - -static const UInt32 kLzmaAlgoX1 = 0; -static const UInt32 kLzmaAlgoX5 = 1; - -static const UInt32 kLzmaDicSizeX1 = 1 << 16; -static const UInt32 kLzmaDicSizeX3 = 1 << 20; -static const UInt32 kLzmaDicSizeX5 = 1 << 24; -static const UInt32 kLzmaDicSizeX7 = 1 << 25; -static const UInt32 kLzmaDicSizeX9 = 1 << 26; - -static const UInt32 kLzmaFastBytesX1 = 32; -static const UInt32 kLzmaFastBytesX7 = 64; - -static const UInt32 kPpmdMemSizeX1 = (1 << 22); -static const UInt32 kPpmdMemSizeX5 = (1 << 24); -static const UInt32 kPpmdMemSizeX7 = (1 << 26); -static const UInt32 kPpmdMemSizeX9 = (192 << 20); - -static const UInt32 kPpmdOrderX1 = 4; -static const UInt32 kPpmdOrderX5 = 6; -static const UInt32 kPpmdOrderX7 = 16; -static const UInt32 kPpmdOrderX9 = 32; - -static const UInt32 kDeflateAlgoX1 = 0; -static const UInt32 kDeflateAlgoX5 = 1; - -static const UInt32 kDeflateFastBytesX1 = 32; -static const UInt32 kDeflateFastBytesX7 = 64; -static const UInt32 kDeflateFastBytesX9 = 128; - -static const UInt32 kDeflatePassesX1 = 1; -static const UInt32 kDeflatePassesX7 = 3; -static const UInt32 kDeflatePassesX9 = 10; - -static const UInt32 kBZip2NumPassesX1 = 1; -static const UInt32 kBZip2NumPassesX7 = 2; -static const UInt32 kBZip2NumPassesX9 = 7; - -static const UInt32 kBZip2DicSizeX1 = 100000; -static const UInt32 kBZip2DicSizeX3 = 500000; -static const UInt32 kBZip2DicSizeX5 = 900000; - -static const wchar_t *kDefaultMethodName = kLZMAMethodName; - -static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; -static const UInt32 kDictionaryForHeaders = 1 << 20; -static const UInt32 kNumFastBytesForHeaders = 273; -static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5; - -static bool AreEqual(const UString &methodName, const wchar_t *s) - { return (methodName.CompareNoCase(s) == 0); } - -bool COneMethodInfo::IsLzma() const -{ - return - AreEqual(MethodName, kLZMAMethodName) || - AreEqual(MethodName, kLZMA2MethodName); -} - -static inline bool IsBZip2Method(const UString &methodName) - { return AreEqual(methodName, kBZip2MethodName); } - -static inline bool IsPpmdMethod(const UString &methodName) - { return AreEqual(methodName, kPpmdMethodName); } - -static inline bool IsDeflateMethod(const UString &methodName) -{ - return - AreEqual(methodName, kDeflateMethodName) || - AreEqual(methodName, kDeflate64MethodName); -} - -struct CNameToPropID -{ - PROPID PropID; - VARTYPE VarType; - const wchar_t *Name; -}; - -static CNameToPropID g_NameToPropID[] = -{ - { NCoderPropID::kBlockSize, VT_UI4, L"C" }, - { NCoderPropID::kDictionarySize, VT_UI4, L"D" }, - { NCoderPropID::kUsedMemorySize, VT_UI4, L"MEM" }, - - { NCoderPropID::kOrder, VT_UI4, L"O" }, - { NCoderPropID::kPosStateBits, VT_UI4, L"PB" }, - { NCoderPropID::kLitContextBits, VT_UI4, L"LC" }, - { NCoderPropID::kLitPosBits, VT_UI4, L"LP" }, - { NCoderPropID::kEndMarker, VT_BOOL, L"eos" }, - - { NCoderPropID::kNumPasses, VT_UI4, L"Pass" }, - { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" }, - { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" }, - { NCoderPropID::kAlgorithm, VT_UI4, L"a" }, - { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" }, - { NCoderPropID::kNumThreads, VT_UI4, L"mt" }, - { NCoderPropID::kDefaultProp, VT_UI4, L"" } -}; - -static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp) -{ - if (varType == srcProp.vt) - { - destProp = srcProp; - return true; - } - if (varType == VT_UI1) - { - if (srcProp.vt == VT_UI4) - { - UInt32 value = srcProp.ulVal; - if (value > 0xFF) - return false; - destProp = (Byte)value; - return true; - } - } - else if (varType == VT_BOOL) - { - bool res; - if (SetBoolProperty(res, srcProp) != S_OK) - return false; - destProp = res; - return true; - } - return false; -} - -static int FindPropIdExact(const UString &name) +static void SetMethodProp32(COneMethodInfo &m, PROPID propID, UInt32 value) { - for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++) - if (name.CompareNoCase(g_NameToPropID[i].Name) == 0) - return i; - return -1; + if (m.FindProp(propID) < 0) + m.AddProp32(propID, value); } -static int FindPropIdStart(const UString &name) -{ - for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++) - { - UString t = g_NameToPropID[i].Name; - if (t.CompareNoCase(name.Left(t.Length())) == 0) - return i; - } - return -1; -} - -static void SetMethodProp(COneMethodInfo &m, PROPID propID, const NCOM::CPropVariant &value) -{ - for (int j = 0; j < m.Props.Size(); j++) - if (m.Props[j].Id == propID) - return; - CProp prop; - prop.Id = propID; - prop.Value = value; - m.Props.Add(prop); -} - -void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo +void CMultiMethodProps::SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo #ifndef _7ZIP_ST , UInt32 numThreads #endif ) { UInt32 level = _level; - if (oneMethodInfo.MethodName.IsEmpty()) - oneMethodInfo.MethodName = kDefaultMethodName; - - if (oneMethodInfo.IsLzma()) - { - UInt32 dicSize = - (level >= 9 ? kLzmaDicSizeX9 : - (level >= 7 ? kLzmaDicSizeX7 : - (level >= 5 ? kLzmaDicSizeX5 : - (level >= 3 ? kLzmaDicSizeX3 : - kLzmaDicSizeX1)))); - - UInt32 algo = - (level >= 5 ? kLzmaAlgoX5 : - kLzmaAlgoX1); - - UInt32 fastBytes = - (level >= 7 ? kLzmaFastBytesX7 : - kLzmaFastBytesX1); - - const wchar_t *matchFinder = - (level >= 5 ? kLzmaMatchFinderX5 : - kLzmaMatchFinderX1); - - SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); - SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); - SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); - SetMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder); - #ifndef _7ZIP_ST - SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); - #endif - } - else if (IsDeflateMethod(oneMethodInfo.MethodName)) - { - UInt32 fastBytes = - (level >= 9 ? kDeflateFastBytesX9 : - (level >= 7 ? kDeflateFastBytesX7 : - kDeflateFastBytesX1)); - - UInt32 numPasses = - (level >= 9 ? kDeflatePassesX9 : - (level >= 7 ? kDeflatePassesX7 : - kDeflatePassesX1)); - - UInt32 algo = - (level >= 5 ? kDeflateAlgoX5 : - kDeflateAlgoX1); - - SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); - SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); - SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); - } - else if (IsBZip2Method(oneMethodInfo.MethodName)) - { - UInt32 numPasses = - (level >= 9 ? kBZip2NumPassesX9 : - (level >= 7 ? kBZip2NumPassesX7 : - kBZip2NumPassesX1)); - - UInt32 dicSize = - (level >= 5 ? kBZip2DicSizeX5 : - (level >= 3 ? kBZip2DicSizeX3 : - kBZip2DicSizeX1)); - - SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); - SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); - #ifndef _7ZIP_ST - SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); - #endif - } - else if (IsPpmdMethod(oneMethodInfo.MethodName)) - { - UInt32 useMemSize = - (level >= 9 ? kPpmdMemSizeX9 : - (level >= 7 ? kPpmdMemSizeX7 : - (level >= 5 ? kPpmdMemSizeX5 : - kPpmdMemSizeX1))); - - UInt32 order = - (level >= 9 ? kPpmdOrderX9 : - (level >= 7 ? kPpmdOrderX7 : - (level >= 5 ? kPpmdOrderX5 : - kPpmdOrderX1))); - - SetMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize); - SetMethodProp(oneMethodInfo, NCoderPropID::kOrder, order); - } -} - -static void SplitParams(const UString &srcString, UStringVector &subStrings) -{ - subStrings.Clear(); - UString name; - int len = srcString.Length(); - if (len == 0) - return; - for (int i = 0; i < len; i++) - { - wchar_t c = srcString[i]; - if (c == L':') - { - subStrings.Add(name); - name.Empty(); - } - else - name += c; - } - subStrings.Add(name); -} - -static void SplitParam(const UString ¶m, UString &name, UString &value) -{ - int eqPos = param.Find(L'='); - if (eqPos >= 0) - { - name = param.Left(eqPos); - value = param.Mid(eqPos + 1); - return; - } - for(int i = 0; i < param.Length(); i++) - { - wchar_t c = param[i]; - if (c >= L'0' && c <= L'9') - { - name = param.Left(i); - value = param.Mid(i); - return; - } - } - name = param; -} - -HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value) -{ - CProp prop; - int index = FindPropIdExact(name); - if (index < 0) - return E_INVALIDARG; - const CNameToPropID &nameToPropID = g_NameToPropID[index]; - prop.Id = nameToPropID.PropID; - - if (prop.Id == NCoderPropID::kBlockSize || - prop.Id == NCoderPropID::kDictionarySize || - prop.Id == NCoderPropID::kUsedMemorySize) - { - UInt32 dicSize; - RINOK(ParsePropDictionaryValue(value, dicSize)); - prop.Value = dicSize; - } - else - { - NCOM::CPropVariant propValue; - - if (nameToPropID.VarType == VT_BSTR) - propValue = value; - else if (nameToPropID.VarType == VT_BOOL) - { - bool res; - if (!StringToBool(value, res)) - return E_INVALIDARG; - propValue = res; - } - else - { - UInt32 number; - if (ParseStringToUInt32(value, number) == value.Length()) - propValue = number; - else - propValue = value; - } - - if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value)) - return E_INVALIDARG; - } - oneMethodInfo.Props.Add(prop); - return S_OK; -} - -HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString) -{ - UStringVector params; - SplitParams(srcString, params); - if (params.Size() > 0) - oneMethodInfo.MethodName = params[0]; - for (int i = 1; i < params.Size(); i++) - { - const UString ¶m = params[i]; - UString name, value; - SplitParam(param, name, value); - RINOK(SetParam(oneMethodInfo, name, value)); - } - return S_OK; -} - -HRESULT COutHandler::SetSolidSettings(const UString &s) -{ - UString s2 = s; - s2.MakeUpper(); - for (int i = 0; i < s2.Length();) - { - const wchar_t *start = ((const wchar_t *)s2) + i; - const wchar_t *end; - UInt64 v = ConvertStringToUInt64(start, &end); - if (start == end) - { - if (s2[i++] != 'E') - return E_INVALIDARG; - _solidExtension = true; - continue; - } - i += (int)(end - start); - if (i == s2.Length()) - return E_INVALIDARG; - wchar_t c = s2[i++]; - switch(c) - { - case 'F': - if (v < 1) - v = 1; - _numSolidFiles = v; - break; - case 'B': - _numSolidBytes = v; - _numSolidBytesDefined = true; - break; - case 'K': - _numSolidBytes = (v << 10); - _numSolidBytesDefined = true; - break; - case 'M': - _numSolidBytes = (v << 20); - _numSolidBytesDefined = true; - break; - case 'G': - _numSolidBytes = (v << 30); - _numSolidBytesDefined = true; - break; - default: - return E_INVALIDARG; - } - } - return S_OK; -} - -HRESULT COutHandler::SetSolidSettings(const PROPVARIANT &value) -{ - bool isSolid; - switch(value.vt) - { - case VT_EMPTY: - isSolid = true; - break; - case VT_BOOL: - isSolid = (value.boolVal != VARIANT_FALSE); - break; - case VT_BSTR: - if (StringToBool(value.bstrVal, isSolid)) - break; - return SetSolidSettings(value.bstrVal); - default: - return E_INVALIDARG; - } - if (isSolid) - InitSolid(); - else - _numSolidFiles = 1; - return S_OK; -} - -void COutHandler::Init() -{ - _removeSfxBlock = false; - _compressHeaders = true; - _encryptHeadersSpecified = false; - _encryptHeaders = false; - - WriteCTime = false; - WriteATime = false; - WriteMTime = true; - + if (level != (UInt32)(Int32)-1) + SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level); #ifndef _7ZIP_ST - _numThreads = NSystem::GetNumberOfProcessors(); + SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif - - _level = 5; - _autoFilter = true; - _volumeMode = false; - _crcSize = 4; - InitSolid(); } -void COutHandler::BeforeSetProperty() +void CMultiMethodProps::Init() { - Init(); #ifndef _7ZIP_ST - numProcessors = NSystem::GetNumberOfProcessors(); + _numProcessors = _numThreads = NSystem::GetNumberOfProcessors(); #endif - mainDicSize = 0xFFFFFFFF; - mainDicMethodIndex = 0xFFFFFFFF; - minNumber = 0; + _level = (UInt32)(Int32)-1; + _autoFilter = true; _crcSize = 4; + _filterMethod.Clear(); + _methods.Clear(); } -HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) +HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) { UString name = nameSpec; - name.MakeUpper(); + name.MakeLower_Ascii(); if (name.IsEmpty()) return E_INVALIDARG; - - if (name[0] == 'X') + + if (name[0] == 'x') { name.Delete(0); _level = 9; - return ParsePropValue(name, value, _level); + return ParsePropToUInt32(name, value, _level); } - - if (name[0] == L'S') - { - name.Delete(0); - if (name.IsEmpty()) - return SetSolidSettings(value); - if (value.vt != VT_EMPTY) - return E_INVALIDARG; - return SetSolidSettings(name); - } - - if (name == L"CRC") + + if (name == L"crc") { - _crcSize = 4; name.Delete(0, 3); - return ParsePropValue(name, value, _crcSize); + _crcSize = 4; + return ParsePropToUInt32(name, value, _crcSize); } - + UInt32 number; int index = ParseStringToUInt32(name, number); - UString realName = name.Mid(index); + UString realName = name.Ptr(index); if (index == 0) { - if(name.Left(2).CompareNoCase(L"MT") == 0) + if (name.IsPrefixedBy(L"mt")) { #ifndef _7ZIP_ST - RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); + RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads)); #endif return S_OK; } - if (name.CompareNoCase(L"RSFX") == 0) return SetBoolProperty(_removeSfxBlock, value); - if (name.CompareNoCase(L"F") == 0) return SetBoolProperty(_autoFilter, value); - if (name.CompareNoCase(L"HC") == 0) return SetBoolProperty(_compressHeaders, value); - if (name.CompareNoCase(L"HCF") == 0) + if (name.IsEqualTo("f")) { - bool compressHeadersFull = true; - RINOK(SetBoolProperty(compressHeadersFull, value)); - if (!compressHeadersFull) + HRESULT res = PROPVARIANT_to_bool(value, _autoFilter); + if (res == S_OK) + return res; + if (value.vt != VT_BSTR) return E_INVALIDARG; - return S_OK; - } - if (name.CompareNoCase(L"HE") == 0) - { - RINOK(SetBoolProperty(_encryptHeaders, value)); - _encryptHeadersSpecified = true; - return S_OK; + return _filterMethod.ParseMethodFromPROPVARIANT(L"", value); } - if (name.CompareNoCase(L"TC") == 0) return SetBoolProperty(WriteCTime, value); - if (name.CompareNoCase(L"TA") == 0) return SetBoolProperty(WriteATime, value); - if (name.CompareNoCase(L"TM") == 0) return SetBoolProperty(WriteMTime, value); - if (name.CompareNoCase(L"V") == 0) return SetBoolProperty(_volumeMode, value); number = 0; } - if (number > 10000) + if (number > 64) return E_FAIL; - if (number < minNumber) - return E_INVALIDARG; - number -= minNumber; - for(int j = _methods.Size(); j <= (int)number; j++) - { - COneMethodInfo oneMethodInfo; - _methods.Add(oneMethodInfo); - } - - COneMethodInfo &oneMethodInfo = _methods[number]; - - if (realName.Length() == 0) - { - if (value.vt != VT_BSTR) - return E_INVALIDARG; - - RINOK(SetParams(oneMethodInfo, value.bstrVal)); - } - else + for (int j = _methods.Size(); j <= (int)number; j++) + _methods.Add(COneMethodInfo()); + return _methods[number].ParseMethodFromPROPVARIANT(realName, value); +} + +void CSingleMethodProps::Init() +{ + Clear(); + #ifndef _7ZIP_ST + _numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors(); + AddNumThreadsProp(_numThreads); + #endif + _level = (UInt32)(Int32)-1; +} + +HRESULT CSingleMethodProps::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) +{ + Init(); + for (UInt32 i = 0; i < numProps; i++) { - int index = FindPropIdStart(realName); - if (index < 0) + UString name = names[i]; + name.MakeLower_Ascii(); + if (name.IsEmpty()) return E_INVALIDARG; - const CNameToPropID &nameToPropID = g_NameToPropID[index]; - CProp prop; - prop.Id = nameToPropID.PropID; - - if (prop.Id == NCoderPropID::kBlockSize || - prop.Id == NCoderPropID::kDictionarySize || - prop.Id == NCoderPropID::kUsedMemorySize) + const PROPVARIANT &value = values[i]; + if (name[0] == L'x') { - UInt32 dicSize; - RINOK(ParsePropDictionaryValue(realName.Mid(MyStringLen(nameToPropID.Name)), value, dicSize)); - prop.Value = dicSize; - if (number <= mainDicMethodIndex) - mainDicSize = dicSize; + UInt32 a = 9; + RINOK(ParsePropToUInt32(name.Ptr(1), value, a)); + _level = a; + AddLevelProp(a); } - else + else if (name.IsPrefixedBy(L"mt")) { - int index = FindPropIdExact(realName); - if (index < 0) - return E_INVALIDARG; - const CNameToPropID &nameToPropID = g_NameToPropID[index]; - prop.Id = nameToPropID.PropID; - if (!ConvertProperty(value, nameToPropID.VarType, prop.Value)) - return E_INVALIDARG; + #ifndef _7ZIP_ST + RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads)); + AddNumThreadsProp(_numThreads); + #endif } - oneMethodInfo.Props.Add(prop); + else + return ParseMethodFromPROPVARIANT(names[i], value); } return S_OK; } diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/HandlerOut.h b/src/libs/7zip/unix/CPP/7zip/Archive/Common/HandlerOut.h index 72ea40321..eba2a19e1 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/HandlerOut.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/Common/HandlerOut.h @@ -3,83 +3,61 @@ #ifndef __HANDLER_OUT_H #define __HANDLER_OUT_H -#include "../../../Common/MyString.h" #include "../../Common/MethodProps.h" namespace NArchive { -struct COneMethodInfo -{ - CObjectVector Props; - UString MethodName; - - bool IsLzma() const; -}; - -class COutHandler +class CMultiMethodProps { + UInt32 _level; public: - HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); - - HRESULT SetSolidSettings(const UString &s); - HRESULT SetSolidSettings(const PROPVARIANT &value); - #ifndef _7ZIP_ST UInt32 _numThreads; + UInt32 _numProcessors; #endif UInt32 _crcSize; - CObjectVector _methods; - bool _removeSfxBlock; - - UInt64 _numSolidFiles; - UInt64 _numSolidBytes; - bool _numSolidBytesDefined; - bool _solidExtension; - - bool _compressHeaders; - bool _encryptHeadersSpecified; - bool _encryptHeaders; - - bool WriteCTime; - bool WriteATime; - bool WriteMTime; - + COneMethodInfo _filterMethod; bool _autoFilter; - UInt32 _level; - - bool _volumeMode; - HRESULT SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value); - HRESULT SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString); - - void SetCompressionMethod2(COneMethodInfo &oneMethodInfo + void SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo #ifndef _7ZIP_ST , UInt32 numThreads #endif ); - void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } - void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } - void InitSolid() + unsigned GetNumEmptyMethods() const { - InitSolidFiles(); - InitSolidSize(); - _solidExtension = false; - _numSolidBytesDefined = false; + unsigned i; + for (i = 0; i < _methods.Size(); i++) + if (!_methods[i].IsEmpty()) + break; + return i; } + int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; } + void Init(); - COutHandler() { Init(); } + CMultiMethodProps() { Init(); } + HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); +}; + +class CSingleMethodProps: public COneMethodInfo +{ + UInt32 _level; - void BeforeSetProperty(); +public: + #ifndef _7ZIP_ST + UInt32 _numThreads; + UInt32 _numProcessors; + #endif - UInt32 minNumber; - UInt32 numProcessors; - UInt32 mainDicSize; - UInt32 mainDicMethodIndex; + void Init(); + CSingleMethodProps() { Init(); } + int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; } + HRESULT SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); }; } diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/InStreamWithCRC.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/Common/InStreamWithCRC.cpp index 569a56f3b..a2d688328 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/InStreamWithCRC.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/Common/InStreamWithCRC.cpp @@ -6,29 +6,33 @@ STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) { - UInt32 realProcessedSize; - HRESULT result = _stream->Read(data, size, &realProcessedSize); - _size += realProcessedSize; - if (size > 0 && realProcessedSize == 0) + UInt32 realProcessed = 0; + HRESULT result = S_OK; + if (_stream) + result = _stream->Read(data, size, &realProcessed); + _size += realProcessed; + if (size != 0 && realProcessed == 0) _wasFinished = true; - _crc = CrcUpdate(_crc, data, realProcessedSize); - if(processedSize != NULL) - *processedSize = realProcessedSize; + _crc = CrcUpdate(_crc, data, realProcessed); + if (processedSize) + *processedSize = realProcessed; return result; } STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) { - UInt32 realProcessedSize; - HRESULT result = _stream->Read(data, size, &realProcessedSize); + UInt32 realProcessed = 0; + HRESULT result = S_OK; + if (_stream) + result = _stream->Read(data, size, &realProcessed); + _size += realProcessed; /* - if (size > 0 && realProcessedSize == 0) + if (size != 0 && realProcessed == 0) _wasFinished = true; */ - _size += realProcessedSize; - _crc = CrcUpdate(_crc, data, realProcessedSize); - if(processedSize != NULL) - *processedSize = realProcessedSize; + _crc = CrcUpdate(_crc, data, realProcessed); + if (processedSize) + *processedSize = realProcessed; return result; } diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/Common/ItemNameUtils.cpp index a5e0dc0be..7cd3037be 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/ItemNameUtils.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/Common/ItemNameUtils.cpp @@ -2,8 +2,6 @@ #include "StdAfx.h" -#include "../../../../C/Types.h" - #include "ItemNameUtils.h" namespace NArchive { @@ -12,6 +10,21 @@ namespace NItemName { static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR; static const wchar_t kDirDelimiter = L'/'; +void ReplaceToOsPathSeparator(wchar_t *s) +{ + #ifdef _WIN32 + for (;;) + { + wchar_t c = *s; + if (c == 0) + break; + if (c == kDirDelimiter) + *s = kOSDirDelimiter; + s++; + } + #endif +} + UString MakeLegalName(const UString &name) { UString zipName = name; @@ -31,20 +44,34 @@ UString GetOSName2(const UString &name) if (name.IsEmpty()) return UString(); UString newName = GetOSName(name); - if (newName[newName.Length() - 1] == kOSDirDelimiter) - newName.Delete(newName.Length() - 1); + if (newName.Back() == kOSDirDelimiter) + newName.DeleteBack(); return newName; } -bool HasTailSlash(const AString &name, UINT codePage) +void ConvertToOSName2(UString &name) +{ + if (!name.IsEmpty()) + { + name.Replace(kDirDelimiter, kOSDirDelimiter); + if (name.Back() == kOSDirDelimiter) + name.DeleteBack(); + } +} + +bool HasTailSlash(const AString &name, UINT + #if defined(_WIN32) && !defined(UNDER_CE) + codePage + #endif + ) { if (name.IsEmpty()) return false; LPCSTR prev = #if defined(_WIN32) && !defined(UNDER_CE) - CharPrevExA((WORD)codePage, name, &name[name.Length()], 0); + CharPrevExA((WORD)codePage, name, &name[name.Len()], 0); #else - (LPCSTR)(name) + (name.Length() - 1); + (LPCSTR)(name) + (name.Len() - 1); #endif return (*prev == '/'); } diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/ItemNameUtils.h b/src/libs/7zip/unix/CPP/7zip/Archive/Common/ItemNameUtils.h index 5eafacb12..d0dc76a41 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/ItemNameUtils.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/Common/ItemNameUtils.h @@ -1,16 +1,19 @@ // Archive/Common/ItemNameUtils.h -#ifndef __ARCHIVE_ITEMNAMEUTILS_H -#define __ARCHIVE_ITEMNAMEUTILS_H +#ifndef __ARCHIVE_ITEM_NAME_UTILS_H +#define __ARCHIVE_ITEM_NAME_UTILS_H #include "../../../Common/MyString.h" namespace NArchive { namespace NItemName { + void ReplaceToOsPathSeparator(wchar_t *s); + UString MakeLegalName(const UString &name); UString GetOSName(const UString &name); UString GetOSName2(const UString &name); + void ConvertToOSName2(UString &name); bool HasTailSlash(const AString &name, UINT codePage); #ifdef _WIN32 diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/MultiStream.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/Common/MultiStream.cpp index 04d11cafb..17f749058 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/MultiStream.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/Common/MultiStream.cpp @@ -11,10 +11,10 @@ STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize) if (size == 0) return S_OK; if (_pos >= _totalLength) - return (_pos == _totalLength) ? S_OK : E_FAIL; + return S_OK; { - int left = 0, mid = _streamIndex, right = Streams.Size(); + unsigned left = 0, mid = _streamIndex, right = Streams.Size(); for (;;) { CSubStreamInfo &m = Streams[mid]; @@ -31,7 +31,7 @@ STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize) } _streamIndex = mid; } - + CSubStreamInfo &s = Streams[_streamIndex]; UInt64 localPos = _pos - s.GlobalOffset; if (localPos != s.LocalPos) @@ -48,18 +48,21 @@ STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize) *processedSize = size; return result; } - + STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - switch(seekOrigin) + switch (seekOrigin) { - case STREAM_SEEK_SET: _pos = offset; break; - case STREAM_SEEK_CUR: _pos = _pos + offset; break; - case STREAM_SEEK_END: _pos = _totalLength + offset; break; + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _pos; break; + case STREAM_SEEK_END: offset += _totalLength; break; default: return STG_E_INVALIDFUNCTION; } - if (newPosition != 0) - *newPosition = _pos; + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _pos = offset; + if (newPosition) + *newPosition = offset; return S_OK; } @@ -69,7 +72,7 @@ class COutVolumeStream: public ISequentialOutStream, public CMyUnknownImp { - int _volIndex; + unsigned _volIndex; UInt64 _volSize; UInt64 _curPos; CMyComPtr _volumeStream; @@ -88,12 +91,12 @@ public: _file.Name = name; _file.IsStartPosDefined = true; _file.StartPos = 0; - + VolumeCallback = volumeCallback; _volIndex = 0; _volSize = 0; } - + HRESULT Flush(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; @@ -116,9 +119,9 @@ HRESULT COutVolumeStream::Flush() /* STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { - if(processedSize != NULL) + if (processedSize != NULL) *processedSize = 0; - while(size > 0) + while (size > 0) { if (_streamIndex >= Streams.Size()) { @@ -154,7 +157,7 @@ STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *proce _absPos += realProcessed; if (_absPos > _length) _length = _absPos; - if(processedSize != NULL) + if (processedSize != NULL) *processedSize += realProcessed; if (subStream.Pos == subStream.Size) { @@ -169,22 +172,20 @@ STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *proce STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - if(seekOrigin >= 3) - return STG_E_INVALIDFUNCTION; - switch(seekOrigin) + switch (seekOrigin) { - case STREAM_SEEK_SET: - _absPos = offset; - break; - case STREAM_SEEK_CUR: - _absPos += offset; - break; - case STREAM_SEEK_END: - _absPos = _length + offset; - break; + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _absPos; break; + case STREAM_SEEK_END: offset += _length; break; + default: return STG_E_INVALIDFUNCTION; } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _absPos = offset; _offsetPos = _absPos; _streamIndex = 0; + if (newPosition) + *newPosition = offset; return S_OK; } */ diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/MultiStream.h b/src/libs/7zip/unix/CPP/7zip/Archive/Common/MultiStream.h index 3fceb7cce..93aff33bf 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/MultiStream.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/Common/MultiStream.h @@ -14,21 +14,26 @@ class CMultiStream: { UInt64 _pos; UInt64 _totalLength; - int _streamIndex; + unsigned _streamIndex; + public: + struct CSubStreamInfo { CMyComPtr Stream; UInt64 Size; UInt64 GlobalOffset; UInt64 LocalPos; + + CSubStreamInfo(): Size(0), GlobalOffset(0), LocalPos(0) {} }; + CObjectVector Streams; - + HRESULT Init() { UInt64 total = 0; - for (int i = 0; i < Streams.Size(); i++) + FOR_VECTOR (i, Streams) { CSubStreamInfo &s = Streams[i]; s.GlobalOffset = total; @@ -52,7 +57,7 @@ class COutMultiStream: public IOutStream, public CMyUnknownImp { - int _streamIndex; // required stream + unsigned _streamIndex; // required stream UInt64 _offsetPos; // offset from start of _streamIndex index UInt64 _absPos; UInt64 _length; diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/OutStreamWithCRC.h b/src/libs/7zip/unix/CPP/7zip/Archive/Common/OutStreamWithCRC.h index 115b442aa..09b899bbd 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/OutStreamWithCRC.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/Common/OutStreamWithCRC.h @@ -28,6 +28,7 @@ public: _calculate = calculate; _crc = CRC_INIT_VAL; } + void EnableCalc(bool calculate) { _calculate = calculate; } void InitCRC() { _crc = CRC_INIT_VAL; } UInt64 GetSize() const { return _size; } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/ParseProperties.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/Common/ParseProperties.cpp deleted file mode 100644 index 5cd849e29..000000000 --- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/ParseProperties.cpp +++ /dev/null @@ -1,177 +0,0 @@ -// ParseProperties.cpp - -#include "StdAfx.h" - -#include "ParseProperties.h" - -#include "Common/StringToInt.h" -#include "Common/MyCom.h" - -HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) -{ - if (prop.vt == VT_UI4) - { - if (!name.IsEmpty()) - return E_INVALIDARG; - resValue = prop.ulVal; - } - else if (prop.vt == VT_EMPTY) - { - if(!name.IsEmpty()) - { - const wchar_t *start = name; - const wchar_t *end; - UInt64 v = ConvertStringToUInt64(start, &end); - if (end - start != name.Length()) - return E_INVALIDARG; - resValue = (UInt32)v; - } - } - else - return E_INVALIDARG; - return S_OK; -} - -static const int kLogarithmicSizeLimit = 32; -static const wchar_t kByteSymbol = L'B'; -static const wchar_t kKiloByteSymbol = L'K'; -static const wchar_t kMegaByteSymbol = L'M'; - -HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize) -{ - UString srcString = srcStringSpec; - srcString.MakeUpper(); - - const wchar_t *start = srcString; - const wchar_t *end; - UInt64 number = ConvertStringToUInt64(start, &end); - int numDigits = (int)(end - start); - if (numDigits == 0 || srcString.Length() > numDigits + 1) - return E_INVALIDARG; - if (srcString.Length() == numDigits) - { - if (number >= kLogarithmicSizeLimit) - return E_INVALIDARG; - dicSize = (UInt32)1 << (int)number; - return S_OK; - } - switch (srcString[numDigits]) - { - case kByteSymbol: - if (number >= ((UInt64)1 << kLogarithmicSizeLimit)) - return E_INVALIDARG; - dicSize = (UInt32)number; - break; - case kKiloByteSymbol: - if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10))) - return E_INVALIDARG; - dicSize = (UInt32)(number << 10); - break; - case kMegaByteSymbol: - if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20))) - return E_INVALIDARG; - dicSize = (UInt32)(number << 20); - break; - default: - return E_INVALIDARG; - } - return S_OK; -} - -HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) -{ - if (name.IsEmpty()) - { - if (prop.vt == VT_UI4) - { - UInt32 logDicSize = prop.ulVal; - if (logDicSize >= 32) - return E_INVALIDARG; - resValue = (UInt32)1 << logDicSize; - return S_OK; - } - if (prop.vt == VT_BSTR) - return ParsePropDictionaryValue(prop.bstrVal, resValue); - return E_INVALIDARG; - } - return ParsePropDictionaryValue(name, resValue); -} - -bool StringToBool(const UString &s, bool &res) -{ - if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0 || s.Compare(L"+") == 0) - { - res = true; - return true; - } - if (s.CompareNoCase(L"OFF") == 0 || s.Compare(L"-") == 0) - { - res = false; - return true; - } - return false; -} - -HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value) -{ - switch(value.vt) - { - case VT_EMPTY: - dest = true; - return S_OK; - case VT_BOOL: - dest = (value.boolVal != VARIANT_FALSE); - return S_OK; - /* - case VT_UI4: - dest = (value.ulVal != 0); - break; - */ - case VT_BSTR: - return StringToBool(value.bstrVal, dest) ? S_OK : E_INVALIDARG; - } - return E_INVALIDARG; -} - -int ParseStringToUInt32(const UString &srcString, UInt32 &number) -{ - const wchar_t *start = srcString; - const wchar_t *end; - UInt64 number64 = ConvertStringToUInt64(start, &end); - if (number64 > 0xFFFFFFFF) - { - number = 0; - return 0; - } - number = (UInt32)number64; - return (int)(end - start); -} - -HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads) -{ - if (name.IsEmpty()) - { - switch(prop.vt) - { - case VT_UI4: - numThreads = prop.ulVal; - break; - default: - { - bool val; - RINOK(SetBoolProperty(val, prop)); - numThreads = (val ? defaultNumThreads : 1); - break; - } - } - } - else - { - UInt32 number; - int index = ParseStringToUInt32(name, number); - if (index != name.Length()) - return E_INVALIDARG; - numThreads = number; - } - return S_OK; -} diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/ParseProperties.h b/src/libs/7zip/unix/CPP/7zip/Archive/Common/ParseProperties.h index 6f80f6344..1038a8c02 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/ParseProperties.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/Common/ParseProperties.h @@ -1,18 +1,6 @@ // ParseProperties.h -#ifndef __PARSEPROPERTIES_H -#define __PARSEPROPERTIES_H - -#include "Common/MyString.h" -#include "Common/Types.h" - -HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); -HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize); -HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); - -bool StringToBool(const UString &s, bool &res); -HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value); -int ParseStringToUInt32(const UString &srcString, UInt32 &number); -HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads); +#ifndef __PARSE_PROPERTIES_H +#define __PARSE_PROPERTIES_H #endif diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/DllExports2.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/DllExports2.cpp deleted file mode 100644 index 1febea714..000000000 --- a/src/libs/7zip/unix/CPP/7zip/Archive/DllExports2.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// DLLExports.cpp - -#include "StdAfx.h" - -#include "../../Common/MyInitGuid.h" - -#if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) -#include "../../../C/Alloc.h" -#endif - -#include "../../Common/ComTry.h" - -#include "../../Windows/NtCheck.h" -#include "../../Windows/PropVariant.h" - -#include "../ICoder.h" -#include "../IPassword.h" - -#include "IArchive.h" - -HINSTANCE g_hInstance; - -#define NT_CHECK_FAIL_ACTION return FALSE; - -#ifdef _WIN32 -extern "C" -BOOL WINAPI DllMain( - #ifdef UNDER_CE - HANDLE - #else - HINSTANCE - #endif - hInstance, DWORD dwReason, LPVOID /*lpReserved*/) -{ - if (dwReason == DLL_PROCESS_ATTACH) - { - g_hInstance = (HINSTANCE)hInstance; - NT_CHECK; - } - return TRUE; -} -#endif - -DEFINE_GUID(CLSID_CArchiveHandler, -0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); - -static const UInt16 kDecodeId = 0x2790; - -DEFINE_GUID(CLSID_CCodec, -0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - -STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); -STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject); - -STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) -{ - // COM_TRY_BEGIN - *outObject = 0; - if (*iid == IID_ICompressCoder || *iid == IID_ICompressCoder2 || *iid == IID_ICompressFilter) - { - return CreateCoder(clsid, iid, outObject); - } - else - { - return CreateArchiver(clsid, iid, outObject); - } - // COM_TRY_END -} - -STDAPI SetLargePageMode() -{ - #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) - SetLargePageSize(); - #endif - return S_OK; -} diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/IArchive.h b/src/libs/7zip/unix/CPP/7zip/Archive/IArchive.h index 853202767..038e05ed2 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/IArchive.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/IArchive.h @@ -20,20 +20,43 @@ namespace NFileTimeType }; } +namespace NArcInfoFlags +{ + const UInt32 kKeepName = 1 << 0; // keep name of file in archive name + const UInt32 kAltStreams = 1 << 1; // the handler supports alt streams + const UInt32 kNtSecure = 1 << 2; // the handler supports NT security + const UInt32 kFindSignature = 1 << 3; // the handler can find start of archive + const UInt32 kMultiSignature = 1 << 4; // there are several signatures + const UInt32 kUseGlobalOffset = 1 << 5; // the seek position of stream must be set as global offset + const UInt32 kStartOpen = 1 << 6; // call handler for each start position + const UInt32 kPureStartOpen = 1 << 7; // call handler only for start of file + const UInt32 kBackwardOpen = 1 << 8; // archive can be open backward + const UInt32 kPreArc = 1 << 9; // such archive can be stored before real archive (like SFX stub) + const UInt32 kSymLinks = 1 << 10; // the handler supports symbolic links + const UInt32 kHardLinks = 1 << 11; // the handler supports hard links +} + namespace NArchive { - enum + namespace NHandlerPropID { - kName = 0, - kClassID, - kExtension, - kAddExtension, - kUpdate, - kKeepName, - kStartSignature, - kFinishSignature, - kAssociate - }; + enum + { + kName = 0, // VT_BSTR + kClassID, // binary GUID in VT_BSTR + kExtension, // VT_BSTR + kAddExtension, // VT_BSTR + kUpdate, // VT_BOOL + kKeepName, // VT_BOOL + kSignature, // binary in VT_BSTR + kMultiSignature, // binary in VT_BSTR + kSignatureOffset, // VT_UI4 + kAltStreams, // VT_BOOL + kNtSecure, // VT_BOOL + kFlags // VT_UI4 + // kVersion // VT_UI4 ((VER_MAJOR << 8) | VER_MINOR) + }; + } namespace NExtract { @@ -46,25 +69,32 @@ namespace NArchive kSkip }; } + namespace NOperationResult { enum { kOK = 0, - kUnSupportedMethod, + kUnsupportedMethod, kDataError, - kCRCError + kCRCError, + kUnavailable, + kUnexpectedEnd, + kDataAfterEnd, + kIsNotArc, + kHeadersError }; } } + namespace NUpdate { namespace NOperationResult { enum { - kOK = 0, - kError + kOK = 0 + , // kError }; } } @@ -79,10 +109,16 @@ ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10) INTERFACE_IArchiveOpenCallback(PURE); }; +/* +IArchiveExtractCallback::GetStream + Result: + (*inStream == NULL) - for directories + (*inStream == NULL) - if link (hard link or symbolic link) was created +*/ #define INTERFACE_IArchiveExtractCallback(x) \ INTERFACE_IProgress(x) \ - STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) x; \ + STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) x; \ STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \ STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \ @@ -115,41 +151,184 @@ ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50) /* +IInArchive::Open + stream + if (kUseGlobalOffset), stream current position can be non 0. + if (!kUseGlobalOffset), stream current position is 0. + if (maxCheckStartPosition == NULL), the handler can try to search archive start in stream + if (*maxCheckStartPosition == 0), the handler must check only current position as archive start + IInArchive::Extract: indices must be sorted - numItems = 0xFFFFFFFF means "all files" + numItems = (UInt32)(Int32)-1 = 0xFFFFFFFF means "all files" testMode != 0 means "test files without writing to outStream" + +IInArchive::GetArchiveProperty: + kpidOffset - start offset of archive. + VT_EMPTY : means offset = 0. + VT_UI4, VT_UI8, VT_I8 : result offset; negative values is allowed + kpidPhySize - size of archive. VT_EMPTY means unknown size. + kpidPhySize is allowed to be larger than file size. In that case it must show + supposed size. + + kpidIsDeleted: + kpidIsAltStream: + kpidIsAux: + kpidINode: + must return VARIANT_TRUE (VT_BOOL), if archive can support that property in GetProperty. + + +Notes: + Don't call IInArchive functions for same IInArchive object from different threads simultaneously. + Some IInArchive handlers will work incorrectly in that case. */ +/* MSVC allows the code where there is throw() in declaration of function, + but there is no throw() in definition of function. */ + +#ifdef _MSC_VER + #define MY_NO_THROW_DECL_ONLY throw() +#else + #define MY_NO_THROW_DECL_ONLY +#endif + #define INTERFACE_IInArchive(x) \ - STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \ - STDMETHOD(Close)() x; \ - STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \ - STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \ - STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) x; \ - STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) x; \ - STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \ - STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \ - STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) x; \ - STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; + STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback) MY_NO_THROW_DECL_ONLY x; \ + STDMETHOD(Close)() MY_NO_THROW_DECL_ONLY x; \ + STDMETHOD(GetNumberOfItems)(UInt32 *numItems) MY_NO_THROW_DECL_ONLY x; \ + STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) MY_NO_THROW_DECL_ONLY x; \ + STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) MY_NO_THROW_DECL_ONLY x; \ + STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) MY_NO_THROW_DECL_ONLY x; \ + STDMETHOD(GetNumberOfProperties)(UInt32 *numProps) MY_NO_THROW_DECL_ONLY x; \ + STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) MY_NO_THROW_DECL_ONLY x; \ + STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProps) MY_NO_THROW_DECL_ONLY x; \ + STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) MY_NO_THROW_DECL_ONLY x; ARCHIVE_INTERFACE(IInArchive, 0x60) { INTERFACE_IInArchive(PURE) }; +namespace NParentType +{ + enum + { + kDir = 0, + kAltStream + }; +}; + +namespace NPropDataType +{ + const UInt32 kMask_ZeroEnd = 1 << 4; + // const UInt32 kMask_BigEndian = 1 << 5; + const UInt32 kMask_Utf = 1 << 6; + // const UInt32 kMask_Utf8 = kMask_Utf | 0; + const UInt32 kMask_Utf16 = kMask_Utf | 1; + // const UInt32 kMask_Utf32 = kMask_Utf | 2; + + const UInt32 kNotDefined = 0; + const UInt32 kRaw = 1; + const UInt32 kUtf16z = kMask_Utf16 | kMask_ZeroEnd; +}; + +// UTF string (pointer to wchar_t) with zero end and little-endian. +#define PROP_DATA_TYPE_wchar_t_PTR_Z_LE ((NPropDataType::kMask_Utf | NPropDataType::kMask_ZeroEnd) + (sizeof(wchar_t) >> 1)) + +/* +GetRawProp: + Result: + S_OK - even if property is not set +*/ + +#define INTERFACE_IArchiveGetRawProps(x) \ + STDMETHOD(GetParent)(UInt32 index, UInt32 *parent, UInt32 *parentType) x; \ + STDMETHOD(GetRawProp)(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) x; \ + STDMETHOD(GetNumRawProps)(UInt32 *numProps) x; \ + STDMETHOD(GetRawPropInfo)(UInt32 index, BSTR *name, PROPID *propID) x; + +ARCHIVE_INTERFACE(IArchiveGetRawProps, 0x70) +{ + INTERFACE_IArchiveGetRawProps(PURE) +}; + +#define INTERFACE_IArchiveGetRootProps(x) \ + STDMETHOD(GetRootProp)(PROPID propID, PROPVARIANT *value) x; \ + STDMETHOD(GetRootRawProp)(PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) x; \ + +ARCHIVE_INTERFACE(IArchiveGetRootProps, 0x71) +{ + INTERFACE_IArchiveGetRootProps(PURE) +}; + ARCHIVE_INTERFACE(IArchiveOpenSeq, 0x61) { STDMETHOD(OpenSeq)(ISequentialInStream *stream) PURE; }; +/* + OpenForSize + Result: + S_FALSE - is not archive + ? - DATA error +*/ + +/* +const UInt32 kOpenFlags_RealPhySize = 1 << 0; +const UInt32 kOpenFlags_NoSeek = 1 << 1; +// const UInt32 kOpenFlags_BeforeExtract = 1 << 2; +*/ + +/* +Flags: + 0 - opens archive with IInStream, if IInStream interface is supported + - if phySize is not available, it doesn't try to make full parse to get phySize + kOpenFlags_NoSeek - ArcOpen2 function doesn't use IInStream interface, even if it's available + kOpenFlags_RealPhySize - the handler will try to get PhySize, even if it requires full decompression for file + + if handler is not allowed to use IInStream and the flag kOpenFlags_RealPhySize is not specified, + the handler can return S_OK, but it doesn't check even Signature. + So next Extract can be called for that sequential stream. +*/ + +/* +ARCHIVE_INTERFACE(IArchiveOpen2, 0x62) +{ + STDMETHOD(ArcOpen2)(ISequentialInStream *stream, UInt32 flags, IArchiveOpenCallback *openCallback) PURE; +}; +*/ + +// ---------- UPDATE ---------- + +/* +GetUpdateItemInfo outs: +*newData *newProps + 0 0 - Copy data and properties from archive + 0 1 - Copy data from archive, request new properties + 1 0 - that combination is unused now + 1 1 - Request new data and new properties. It can be used even for folders + + indexInArchive = -1 if there is no item in archive, or if it doesn't matter. + + +GetStream out: + Result: + S_OK: + (*inStream == NULL) - only for directories + - the bug was fixed in 9.33: (*Stream == NULL) was in case of anti-file + (*inStream != NULL) - for any file, even for empty file or anti-file + S_FALSE - skip that file (don't add item to archive) - (client code can't open stream of that file by some reason) + (*inStream == NULL) + +The order of calling for hard links: + - GetStream() + - GetProperty(kpidHardLink) + +*/ + #define INTERFACE_IArchiveUpdateCallback(x) \ INTERFACE_IProgress(x); \ - STDMETHOD(GetUpdateItemInfo)(UInt32 index, \ - Int32 *newData, /*1 - new data, 0 - old data */ \ - Int32 *newProperties, /* 1 - new properties, 0 - old properties */ \ - UInt32 *indexInArchive /* -1 if there is no in archive, or if doesn't matter */ \ - ) x; \ + STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProps, UInt32 *indexInArchive) x; \ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) x; \ STDMETHOD(SetOperationResult)(Int32 operationResult) x; \ @@ -169,6 +348,27 @@ ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82) INTERFACE_IArchiveUpdateCallback2(PURE); }; +/* +UpdateItems() +------------- + + outStream: output stream. (the handler) MUST support the case when + Seek position in outStream is not ZERO. + but the caller calls with empty outStream and seek position is ZERO?? + + archives with stub: + + If archive is open and the handler and (Offset > 0), then the handler + knows about stub size. + UpdateItems(): + 1) the handler MUST copy that stub to outStream + 2) the caller MUST NOT copy the stub to outStream, if + "rsfx" property is set with SetProperties + + the handler must support the case where + ISequentialOutStream *outStream +*/ + #define INTERFACE_IOutArchive(x) \ STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \ @@ -182,47 +382,61 @@ ARCHIVE_INTERFACE(IOutArchive, 0xA0) ARCHIVE_INTERFACE(ISetProperties, 0x03) { - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE; + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) PURE; +}; + +ARCHIVE_INTERFACE(IArchiveKeepModeForNextOpen, 0x04) +{ + STDMETHOD(KeepModeForNextOpen)() PURE; +}; + +/* Exe handler: the handler for executable format (PE, ELF, Mach-O). + SFX archive: executable stub + some tail data. + before 9.31: exe handler didn't parse SFX archives as executable format. + for 9.31+: exe handler parses SFX archives as executable format, only if AllowTail(1) was called */ + +ARCHIVE_INTERFACE(IArchiveAllowTail, 0x05) +{ + STDMETHOD(AllowTail)(Int32 allowTail) PURE; }; #define IMP_IInArchive_GetProp(k) \ (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ - { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ - const STATPROPSTG &srcItem = k[index]; \ - *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \ + { if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \ + *propID = k[index]; *varType = k7z_PROPID_To_VARTYPE[(unsigned)*propID]; *name = 0; return S_OK; } \ #define IMP_IInArchive_GetProp_WITH_NAME(k) \ (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ - { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ + { if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \ const STATPROPSTG &srcItem = k[index]; \ *propID = srcItem.propid; *varType = srcItem.vt; \ if (srcItem.lpwstrName == 0) *name = 0; else *name = ::SysAllocString(srcItem.lpwstrName); return S_OK; } \ #define IMP_IInArchive_Props \ - STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ - { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ + STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) \ + { *numProps = ARRAY_SIZE(kProps); return S_OK; } \ STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps) #define IMP_IInArchive_Props_WITH_NAME \ - STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ - { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ + STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) \ + { *numProps = ARRAY_SIZE(kProps); return S_OK; } \ STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps) #define IMP_IInArchive_ArcProps \ - STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ - { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ + STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProps) \ + { *numProps = ARRAY_SIZE(kArcProps); return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps) #define IMP_IInArchive_ArcProps_WITH_NAME \ - STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ - { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ + STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProps) \ + { *numProps = ARRAY_SIZE(kArcProps); return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kArcProps) #define IMP_IInArchive_ArcProps_NO_Table \ - STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ - { *numProperties = 0; return S_OK; } \ + STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProps) \ + { *numProps = 0; return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \ { return E_NOTIMPL; } \ @@ -231,4 +445,21 @@ ARCHIVE_INTERFACE(ISetProperties, 0x03) STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \ { value->vt = VT_EMPTY; return S_OK; } + + +#define k_IsArc_Res_NO 0 +#define k_IsArc_Res_YES 1 +#define k_IsArc_Res_NEED_MORE 2 +// #define k_IsArc_Res_YES_LOW_PROB 3 + +#define API_FUNC_IsArc EXTERN_C UInt32 WINAPI +#define API_FUNC_static_IsArc extern "C" { static UInt32 WINAPI + +extern "C" +{ + typedef UInt32 (*Func_IsArc)(const Byte *p, size_t size); + typedef IOutArchive * (*Func_CreateOutArchive)(); + typedef IInArchive * (*Func_CreateInArchive)(); +} + #endif diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/LzmaHandler.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/LzmaHandler.cpp index a83e6a1ad..279cdefb7 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/LzmaHandler.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/LzmaHandler.cpp @@ -4,10 +4,10 @@ #include "../../../C/CpuArch.h" -#include "Common/ComTry.h" -#include "Common/IntToString.h" +#include "../../Common/ComTry.h" +#include "../../Common/IntToString.h" -#include "Windows/PropVariant.h" +#include "../../Windows/PropVariant.h" #include "../Common/CreateCoder.h" #include "../Common/ProgressUtils.h" @@ -26,17 +26,24 @@ namespace NLzma { static bool CheckDicSize(const Byte *p) { UInt32 dicSize = GetUi32(p); - for (int i = 1; i <= 30; i++) + if (dicSize == 1) + return true; + for (unsigned i = 0; i <= 30; i++) if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i)) return true; return (dicSize == 0xFFFFFFFF); } -STATPROPSTG kProps[] = +static const Byte kProps[] = { - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, - { NULL, kpidMethod, VT_BSTR} + kpidSize, + kpidPackSize, + kpidMethod +}; + +static const Byte kArcProps[] = +{ + kpidNumStreams }; struct CHeader @@ -62,16 +69,17 @@ bool CHeader::Parse(const Byte *buf, bool isThereFilter) return LzmaProps[0] < 5 * 5 * 9 && FilterID < 2 && - (!HasSize() || Size < ((UInt64)1 << 56)) && - CheckDicSize(LzmaProps + 1); + (!HasSize() || Size < ((UInt64)1 << 56)) + && CheckDicSize(LzmaProps + 1); } class CDecoder { - NCompress::NLzma::CDecoder *_lzmaDecoderSpec; CMyComPtr _lzmaDecoder; CMyComPtr _bcjStream; public: + NCompress::NLzma::CDecoder *_lzmaDecoderSpec; + ~CDecoder(); HRESULT Create(DECL_EXTERNAL_CODECS_LOC_VARS bool filtered, ISequentialInStream *inStream); @@ -86,8 +94,8 @@ public: { return _lzmaDecoderSpec->ReadFromInputStream(data, size, processedSize); } }; -static const UInt64 k_BCJ = 0x03030103; - +static const UInt32 k_BCJ = 0x03030103; + HRESULT CDecoder::Create( DECL_EXTERNAL_CODECS_LOC_VARS bool filteredMode, ISequentialInStream *inStream) @@ -95,6 +103,7 @@ HRESULT CDecoder::Create( if (!_lzmaDecoder) { _lzmaDecoderSpec = new NCompress::NLzma::CDecoder; + _lzmaDecoderSpec->FinishStream = true; _lzmaDecoder = _lzmaDecoderSpec; } @@ -166,6 +175,10 @@ HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream, } RINOK(res); + if (header.HasSize()) + if (_lzmaDecoderSpec->GetOutputProcessedSize() != header.Size) + return S_FALSE; + return S_OK; } @@ -178,12 +191,25 @@ class CHandler: { CHeader _header; bool _lzma86; - UInt64 _startPosition; - UInt64 _packSize; - bool _packSizeDefined; CMyComPtr _stream; CMyComPtr _seqStream; + bool _isArc; + bool _needSeekToStart; + bool _dataAfterEnd; + bool _needMoreInput; + + bool _packSize_Defined; + bool _unpackSize_Defined; + bool _numStreams_Defined; + + bool _unsupported; + bool _dataError; + + UInt64 _packSize; + UInt64 _unpackSize; + UInt64 _numStreams; + DECL_EXTERNAL_CODECS_VARS DECL_ISetCompressCodecsInfo @@ -204,14 +230,26 @@ public: }; IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO_Table +IMP_IInArchive_ArcProps STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { NCOM::CPropVariant prop; - switch(propID) + switch (propID) { - case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; + case kpidPhySize: if (_packSize_Defined) prop = _packSize; break; + case kpidNumStreams: if (_numStreams_Defined) prop = _numStreams; break; + case kpidUnpackSize: if (_unpackSize_Defined) prop = _unpackSize; break; + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;; + if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd; + if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; + if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod; + if (_dataError) v |= kpv_ErrorFlags_DataError; + prop = v; + } } prop.Detach(value); return S_OK; @@ -226,50 +264,37 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) static void DictSizeToString(UInt32 value, char *s) { for (int i = 0; i <= 31; i++) - if ((UInt32(1) << i) == value) + if (((UInt32)1 << i) == value) { ::ConvertUInt32ToString(i, s); return; } char c = 'b'; - if ((value & ((1 << 20) - 1)) == 0) - { - value >>= 20; - c = 'm'; - } - else if ((value & ((1 << 10) - 1)) == 0) - { - value >>= 10; - c = 'k'; - } + if ((value & ((1 << 20) - 1)) == 0) { value >>= 20; c = 'm'; } + else if ((value & ((1 << 10) - 1)) == 0) { value >>= 10; c = 'k'; } ::ConvertUInt32ToString(value, s); - int p = MyStringLen(s); - s[p++] = c; - s[p++] = '\0'; -} - -static void MyStrCat(char *d, const char *s) -{ - MyStringCopy(d + MyStringLen(d), s); + s += MyStringLen(s); + *s++ = c; + *s = 0; } -STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) { NCOM::CPropVariant prop; - switch(propID) + switch (propID) { case kpidSize: if (_stream && _header.HasSize()) prop = _header.Size; break; - case kpidPackSize: if (_packSizeDefined) prop = _packSize; break; + case kpidPackSize: if (_packSize_Defined) prop = _packSize; break; case kpidMethod: if (_stream) { - char s[64]; - s[0] = '\0'; + char sz[64]; + char *s = sz; if (_header.FilterID != 0) - MyStrCat(s, "BCJ "); - MyStrCat(s, "LZMA:"); - DictSizeToString(_header.GetDicSize(), s + MyStringLen(s)); - prop = s; + s = MyStpCpy(s, "BCJ "); + s = MyStpCpy(s, "LZMA:"); + DictSizeToString(_header.GetDicSize(), s); + prop = sz; } break; } @@ -277,46 +302,126 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIA return S_OK; } +API_FUNC_static_IsArc IsArc_Lzma(const Byte *p, size_t size) +{ + const UInt32 kHeaderSize = 1 + 4 + 8; + if (size < kHeaderSize) + return k_IsArc_Res_NEED_MORE; + if (p[0] >= 5 * 5 * 9) + return k_IsArc_Res_NO; + UInt64 unpackSize = GetUi64(p + 1 + 4); + if (unpackSize != (UInt64)(Int64)-1) + { + if (size >= ((UInt64)1 << 56)) + return k_IsArc_Res_NO; + } + if (unpackSize != 0) + { + if (size < kHeaderSize + 2) + return k_IsArc_Res_NEED_MORE; + if (p[kHeaderSize] != 0) + return k_IsArc_Res_NO; + if (unpackSize != (UInt64)(Int64)-1) + { + if ((p[kHeaderSize + 1] & 0x80) != 0) + return k_IsArc_Res_NO; + } + } + if (!CheckDicSize(p + 1)) + // return k_IsArc_Res_YES_LOW_PROB; + return k_IsArc_Res_NO; + return k_IsArc_Res_YES; +} +} + +API_FUNC_static_IsArc IsArc_Lzma86(const Byte *p, size_t size) +{ + if (size < 1) + return k_IsArc_Res_NEED_MORE; + Byte filterID = p[0]; + if (filterID != 0 && filterID != 1) + return k_IsArc_Res_NO; + return IsArc_Lzma(p + 1, size - 1); +} +} + STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *) { - RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &_startPosition)); - - const UInt32 kBufSize = 1 + 5 + 8 + 1; + Close(); + + const UInt32 kBufSize = 1 + 5 + 8 + 2; Byte buf[kBufSize]; - + RINOK(ReadStream_FALSE(inStream, buf, kBufSize)); - + if (!_header.Parse(buf, _lzma86)) return S_FALSE; const Byte *start = buf + GetHeaderSize(); - if (start[0] != 0) + if (start[0] != 0 /* || (start[1] & 0x80) != 0 */ ) // empty stream with EOS is not 0x80 + return S_FALSE; + + RINOK(inStream->Seek(0, STREAM_SEEK_END, &_packSize)); + if (_packSize >= 24 && _header.Size == 0 && _header.FilterID == 0 && _header.LzmaProps[0] == 0) return S_FALSE; - - UInt64 endPos; - RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); - _packSize = endPos - _startPosition; - _packSizeDefined = true; - + _isArc = true; _stream = inStream; _seqStream = inStream; + _needSeekToStart = true; return S_OK; } STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) { Close(); + _isArc = true; _seqStream = stream; return S_OK; } STDMETHODIMP CHandler::Close() { - _packSizeDefined = false; + _isArc = false; + _packSize_Defined = false; + _unpackSize_Defined = false; + _numStreams_Defined = false; + + _dataAfterEnd = false; + _needMoreInput = false; + _unsupported = false; + _dataError = false; + + _packSize = 0; + + _needSeekToStart = false; + _stream.Release(); _seqStream.Release(); return S_OK; } +class CCompressProgressInfoImp: + public ICompressProgressInfo, + public CMyUnknownImp +{ + CMyComPtr Callback; +public: + UInt64 Offset; + + MY_UNKNOWN_IMP1(ICompressProgressInfo) + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); + void Init(IArchiveOpenCallback *callback) { Callback = callback; } +}; + +STDMETHODIMP CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */) +{ + if (Callback) + { + UInt64 files = 0; + UInt64 value = Offset + *inSize; + return Callback->SetCompleted(&files, &value); + } + return S_OK; +} STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) @@ -324,13 +429,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_BEGIN if (numItems == 0) return S_OK; - if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0)) + if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) return E_INVALIDARG; - if (_stream) + if (_packSize_Defined) extractCallback->SetTotal(_packSize); - - + + CMyComPtr realOutStream; Int32 askMode = testMode ? NExtract::NAskMode::kTest : @@ -338,7 +443,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); if (!testMode && !realOutStream) return S_OK; - + extractCallback->PrepareOperation(askMode); CDummyOutStream *outStreamSpec = new CDummyOutStream; @@ -351,78 +456,147 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CMyComPtr progress = lps; lps->Init(extractCallback, true); - if (_stream) + if (_needSeekToStart) { - RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); + if (!_stream) + return E_FAIL; + RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); } + else + _needSeekToStart = true; CDecoder decoder; HRESULT result = decoder.Create( EXTERNAL_CODECS_VARS _lzma86, _seqStream); RINOK(result); - - Int32 opRes = NExtract::NOperationResult::kOK; + bool firstItem = true; + UInt64 packSize = 0; + UInt64 unpackSize = 0; + UInt64 numStreams = 0; + + bool dataAfterEnd = false; + for (;;) { - lps->OutSize = outStreamSpec->GetSize(); - lps->InSize = _packSize = decoder.GetInputProcessedSize(); - _packSizeDefined = true; + lps->InSize = packSize; + lps->OutSize = unpackSize; RINOK(lps->SetCur()); - CHeader st; - const UInt32 kBufSize = 1 + 5 + 8; Byte buf[kBufSize]; const UInt32 headerSize = GetHeaderSize(); UInt32 processed; RINOK(decoder.ReadInput(buf, headerSize, &processed)); if (processed != headerSize) + { + if (processed != 0) + dataAfterEnd = true; break; - + } + + CHeader st; if (!st.Parse(buf, _lzma86)) + { + dataAfterEnd = true; break; + } + numStreams++; firstItem = false; result = decoder.Code(st, outStream, progress); + + packSize = decoder.GetInputProcessedSize(); + unpackSize = outStreamSpec->GetSize(); + if (result == E_NOTIMPL) { - opRes = NExtract::NOperationResult::kUnSupportedMethod; + _unsupported = true; + result = S_FALSE; break; } if (result == S_FALSE) - { - opRes = NExtract::NOperationResult::kDataError; break; - } RINOK(result); } + if (firstItem) - return E_FAIL; + { + _isArc = false; + result = S_FALSE; + } + else if (result == S_OK || result == S_FALSE) + { + if (dataAfterEnd) + _dataAfterEnd = true; + else if (decoder._lzmaDecoderSpec->NeedMoreInput) + _needMoreInput = true; + + _packSize = packSize; + _unpackSize = unpackSize; + _numStreams = numStreams; + + _packSize_Defined = true; + _unpackSize_Defined = true; + _numStreams_Defined = true; + } + + Int32 opResult = NExtract::NOperationResult::kOK; + + if (!_isArc) + opResult = NExtract::NOperationResult::kIsNotArc; + else if (_needMoreInput) + opResult = NExtract::NOperationResult::kUnexpectedEnd; + else if (_unsupported) + opResult = NExtract::NOperationResult::kUnsupportedMethod; + else if (_dataAfterEnd) + opResult = NExtract::NOperationResult::kDataAfterEnd; + else if (result == S_FALSE) + opResult = NExtract::NOperationResult::kDataError; + else if (result == S_OK) + opResult = NExtract::NOperationResult::kOK; + else + return result; + outStream.Release(); - return extractCallback->SetOperationResult(opRes); + return extractCallback->SetOperationResult(opResult); COM_TRY_END } IMPL_ISetCompressCodecsInfo -static IInArchive *CreateArc() { return new CHandler(false); } -static IInArchive *CreateArc86() { return new CHandler(true); } - namespace NLzmaAr { - + +IMP_CreateArcIn_2(CHandler(false)) + static CArcInfo g_ArcInfo = - { L"lzma", L"lzma", 0, 0xA, { 0 }, 0, true, CreateArc, NULL }; + { "lzma", "lzma", 0, 0xA, + 0, { 0 }, + // 2, { 0x5D, 0x00 }, + 0, + NArcInfoFlags::kStartOpen | + NArcInfoFlags::kKeepName, + CreateArc, NULL, + IsArc_Lzma }; + REGISTER_ARC(Lzma) } namespace NLzma86Ar { +IMP_CreateArcIn_2(CHandler(true)) + static CArcInfo g_ArcInfo = - { L"lzma86", L"lzma86", 0, 0xB, { 0 }, 0, true, CreateArc86, NULL }; + { "lzma86", "lzma86", 0, 0xB, + 0, { 0 }, + 0, + NArcInfoFlags::kKeepName, + CreateArc, NULL, + IsArc_Lzma86 }; + REGISTER_ARC(Lzma86) } diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/SplitHandler.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/SplitHandler.cpp index 5d84de4ed..db9f49aa0 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/SplitHandler.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/SplitHandler.cpp @@ -2,10 +2,10 @@ #include "StdAfx.h" -#include "Common/ComTry.h" -#include "Common/MyString.h" +#include "../../Common/ComTry.h" +#include "../../Common/MyString.h" -#include "Windows/PropVariant.h" +#include "../../Windows/PropVariant.h" #include "../Common/ProgressUtils.h" #include "../Common/RegisterArc.h" @@ -19,15 +19,16 @@ using namespace NWindows; namespace NArchive { namespace NSplit { -STATPROPSTG kProps[] = +static const Byte kProps[] = { - { NULL, kpidPath, VT_BSTR}, - { NULL, kpidSize, VT_UI8} + kpidPath, + kpidSize }; -STATPROPSTG kArcProps[] = +static const Byte kArcProps[] = { - { NULL, kpidNumVolumes, VT_UI4} + kpidNumVolumes, + kpidTotalPhySize }; class CHandler: @@ -35,10 +36,12 @@ class CHandler: public IInArchiveGetStream, public CMyUnknownImp { - UString _subName; CObjectVector > _streams; CRecordVector _sizes; + UString _subName; UInt64 _totalSize; + + HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); public: MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) @@ -51,9 +54,11 @@ IMP_IInArchive_ArcProps STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { NCOM::CPropVariant prop; - switch(propID) + switch (propID) { case kpidMainSubfile: prop = (UInt32)0; break; + case kpidPhySize: if (!_sizes.IsEmpty()) prop = _sizes[0]; break; + case kpidTotalPhySize: prop = _totalSize; break; case kpidNumVolumes: prop = (UInt32)_streams.Size(); break; } prop.Detach(value); @@ -65,27 +70,25 @@ struct CSeqName UString _unchangedPart; UString _changedPart; bool _splitStyle; - + UString GetNextName() { UString newName; if (_splitStyle) { int i; - int numLetters = _changedPart.Length(); + int numLetters = _changedPart.Len(); for (i = numLetters - 1; i >= 0; i--) { wchar_t c = _changedPart[i]; if (c == 'z') { - c = 'a'; - newName = c + newName; + newName.InsertAtFront('a'); continue; } else if (c == 'Z') { - c = 'A'; - newName = c + newName; + newName.InsertAtFront('A'); continue; } c++; @@ -99,33 +102,32 @@ struct CSeqName newName += newChar; break; } - newName = c + newName; + newName.InsertAtFront(c); i--; for (; i >= 0; i--) - newName = _changedPart[i] + newName; + newName.InsertAtFront(_changedPart[i]); break; } } else { int i; - int numLetters = _changedPart.Length(); + int numLetters = _changedPart.Len(); for (i = numLetters - 1; i >= 0; i--) { wchar_t c = _changedPart[i]; - if (c == L'9') + if (c == '9') { - c = L'0'; - newName = c + newName; + newName.InsertAtFront('0'); if (i == 0) - newName = UString(L'1') + newName; + newName.InsertAtFront('1'); continue; } c++; - newName = c + newName; + newName.InsertAtFront(c); i--; for (; i >= 0; i--) - newName = _changedPart[i] + newName; + newName.InsertAtFront(_changedPart[i]); break; } } @@ -134,142 +136,139 @@ struct CSeqName } }; -STDMETHODIMP CHandler::Open(IInStream *stream, - const UInt64 * /* maxCheckStartPosition */, - IArchiveOpenCallback *openArchiveCallback) +HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) { - COM_TRY_BEGIN Close(); - if (openArchiveCallback == 0) + if (!callback) + return S_FALSE; + + CMyComPtr volumeCallback; + callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&volumeCallback); + if (!volumeCallback) return S_FALSE; - // try + + UString name; { - CMyComPtr openVolumeCallback; - CMyComPtr openArchiveCallbackWrap = openArchiveCallback; - if (openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, - &openVolumeCallback) != S_OK) + NCOM::CPropVariant prop; + RINOK(volumeCallback->GetProperty(kpidName, &prop)); + if (prop.vt != VT_BSTR) return S_FALSE; - - UString name; - { - NCOM::CPropVariant prop; - RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); - if (prop.vt != VT_BSTR) - return S_FALSE; - name = prop.bstrVal; - } - - int dotPos = name.ReverseFind('.'); - UString prefix, ext; - if (dotPos >= 0) - { - prefix = name.Left(dotPos + 1); - ext = name.Mid(dotPos + 1); - } - else - ext = name; - UString extBig = ext; - extBig.MakeUpper(); + name = prop.bstrVal; + } + + int dotPos = name.ReverseFind('.'); + const UString prefix = name.Left(dotPos + 1); + const UString ext = name.Ptr(dotPos + 1); + UString ext2 = ext; + ext2.MakeLower_Ascii(); - CSeqName seqName; + CSeqName seqName; - int numLetters = 2; - bool splitStyle = false; - if (extBig.Right(2) == L"AA") + unsigned numLetters = 2; + bool splitStyle = false; + + if (ext2.Len() >= 2 && StringsAreEqual_Ascii(ext2.RightPtr(2), "aa")) + { + splitStyle = true; + while (numLetters < ext2.Len()) { - splitStyle = true; - while (numLetters < extBig.Length()) - { - if (extBig[extBig.Length() - numLetters - 1] != 'A') - break; - numLetters++; - } + if (ext2[ext2.Len() - numLetters - 1] != 'a') + break; + numLetters++; } - else if (ext.Right(2) == L"01") + } + else if (ext.Len() >= 2 && StringsAreEqual_Ascii(ext2.RightPtr(2), "01")) + { + while (numLetters < ext2.Len()) { - while (numLetters < extBig.Length()) - { - if (extBig[extBig.Length() - numLetters - 1] != '0') - break; - numLetters++; - } - if (numLetters != ext.Length()) - return S_FALSE; + if (ext2[ext2.Len() - numLetters - 1] != '0') + break; + numLetters++; } - else + if (numLetters != ext.Len()) return S_FALSE; + } + else + return S_FALSE; - _streams.Add(stream); + seqName._unchangedPart = prefix + ext.Left(ext2.Len() - numLetters); + seqName._changedPart = ext.RightPtr(numLetters); + seqName._splitStyle = splitStyle; - seqName._unchangedPart = prefix + ext.Left(extBig.Length() - numLetters); - seqName._changedPart = ext.Right(numLetters); - seqName._splitStyle = splitStyle; + if (prefix.Len() < 1) + _subName = L"file"; + else + _subName.SetFrom(prefix, prefix.Len() - 1); - if (prefix.Length() < 1) - _subName = L"file"; - else - _subName = prefix.Left(prefix.Length() - 1); + UInt64 size; + { + NCOM::CPropVariant prop; + RINOK(volumeCallback->GetProperty(kpidSize, &prop)); + if (prop.vt != VT_UI8) + return E_INVALIDARG; + size = prop.uhVal.QuadPart; + } + + _totalSize += size; + _sizes.Add(size); + _streams.Add(stream); - _totalSize = 0; - UInt64 size; + { + UInt64 numFiles = _streams.Size(); + RINOK(callback->SetCompleted(&numFiles, NULL)); + } + + for (;;) + { + const UString fullName = seqName.GetNextName(); + CMyComPtr nextStream; + HRESULT result = volumeCallback->GetStream(fullName, &nextStream); + if (result == S_FALSE) + break; + if (result != S_OK) + return result; + if (!stream) + break; { NCOM::CPropVariant prop; - RINOK(openVolumeCallback->GetProperty(kpidSize, &prop)); + RINOK(volumeCallback->GetProperty(kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; size = prop.uhVal.QuadPart; } _totalSize += size; _sizes.Add(size); - - if (openArchiveCallback != NULL) + _streams.Add(nextStream); { UInt64 numFiles = _streams.Size(); - RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); - } - - for (;;) - { - UString fullName = seqName.GetNextName(); - CMyComPtr nextStream; - HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream); - if (result == S_FALSE) - break; - if (result != S_OK) - return result; - if (!stream) - break; - { - NCOM::CPropVariant prop; - RINOK(openVolumeCallback->GetProperty(kpidSize, &prop)); - if (prop.vt != VT_UI8) - return E_INVALIDARG; - size = prop.uhVal.QuadPart; - } - _totalSize += size; - _sizes.Add(size); - _streams.Add(nextStream); - if (openArchiveCallback != NULL) - { - UInt64 numFiles = _streams.Size(); - RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); - } + RINOK(callback->SetCompleted(&numFiles, NULL)); } } - /* - catch(...) + + if (_streams.Size() == 1) { - return S_FALSE; + if (splitStyle) + return S_FALSE; } - */ return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + HRESULT res = Open2(stream, callback); + if (res != S_OK) + Close(); + return res; COM_TRY_END } STDMETHODIMP CHandler::Close() { - _sizes.Clear(); + _totalSize = 0; + _subName.Empty(); _streams.Clear(); + _sizes.Clear(); return S_OK; } @@ -281,8 +280,8 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) { - NWindows::NCOM::CPropVariant prop; - switch(propID) + NCOM::CPropVariant prop; + switch (propID) { case kpidPath: prop = _subName; break; case kpidSize: @@ -300,7 +299,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_BEGIN if (numItems == 0) return S_OK; - if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0)) + if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) return E_INVALIDARG; UInt64 currentTotalSize = 0; @@ -313,7 +312,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (!testMode && !outStream) return S_OK; RINOK(extractCallback->PrepareOperation(askMode)); - + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr copyCoder = copyCoderSpec; @@ -321,7 +320,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CMyComPtr progress = lps; lps->Init(extractCallback, false); - for (int i = 0; i < _streams.Size(); i++) + FOR_VECTOR (i, _streams) { lps->InSize = lps->OutSize = currentTotalSize; RINOK(lps->SetCur()); @@ -343,7 +342,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) *stream = 0; CMultiStream *streamSpec = new CMultiStream; CMyComPtr streamTemp = streamSpec; - for (int i = 0; i < _streams.Size(); i++) + FOR_VECTOR (i, _streams) { CMultiStream::CSubStreamInfo subStreamInfo; subStreamInfo.Stream = _streams[i]; @@ -356,10 +355,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) COM_TRY_END } -static IInArchive *CreateArc() { return new CHandler; } +IMP_CreateArcIn static CArcInfo g_ArcInfo = -{ L"Split", L"001", 0, 0xEA, { 0 }, 0, false, CreateArc, 0 }; + { "Split", "001", 0, 0xEA, + 0, { 0 }, + 0, + 0, + CreateArc }; REGISTER_ARC(Split) diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/XzHandler.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/XzHandler.cpp index 64b7a5863..789f41a72 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/XzHandler.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/XzHandler.cpp @@ -7,6 +7,7 @@ #include "../../../C/XzEnc.h" #include "../../Common/ComTry.h" +#include "../../Common/Defs.h" #include "../../Common/IntToString.h" #include "../ICoder.h" @@ -40,37 +41,120 @@ namespace NXz { struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit; +static const wchar_t *k_LZMA2_Name = L"LZMA2"; + +struct CStatInfo +{ + UInt64 InSize; + UInt64 OutSize; + UInt64 PhySize; + + UInt64 NumStreams; + UInt64 NumBlocks; + + bool UnpackSize_Defined; + + bool NumStreams_Defined; + bool NumBlocks_Defined; + + bool IsArc; + bool UnexpectedEnd; + bool DataAfterEnd; + bool Unsupported; + bool HeadersError; + bool DataError; + bool CrcError; + + CStatInfo() { Clear(); } + + void Clear() + { + InSize = 0; + OutSize = 0; + PhySize = 0; + + NumStreams = 0; + NumBlocks = 0; + + UnpackSize_Defined = false; + + NumStreams_Defined = false; + NumBlocks_Defined = false; + + UnexpectedEnd = false; + DataAfterEnd = false; + Unsupported = false; + HeadersError = false; + DataError = false; + CrcError = false; + IsArc = false; + } + +}; + +struct IDecodeState: public CStatInfo +{ + SRes DecodeRes; + + IDecodeState(): DecodeRes(SZ_OK) {} + virtual HRESULT Progress() = 0; + + HRESULT Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream); +}; + +struct CVirtProgress_To_LocalProgress: public IDecodeState +{ + CLocalProgress *lps; + CMyComPtr progress; + + HRESULT Progress(); +}; + +HRESULT CVirtProgress_To_LocalProgress::Progress() +{ + lps->InSize = InSize; + lps->OutSize = OutSize; + return lps->SetCur(); +} + + class CHandler: public IInArchive, public IArchiveOpenSeq, #ifndef EXTRACT_ONLY public IOutArchive, public ISetProperties, - public COutHandler, + public CMultiMethodProps, #endif public CMyUnknownImp { - Int64 _startPosition; - UInt64 _packSize; - UInt64 _unpackSize; - UInt64 _numBlocks; - AString _methodsString; - bool _useSeq; - UInt64 _unpackSizeDefined; - UInt64 _packSizeDefined; - + CStatInfo _stat; + + bool _isArc; + bool _needSeekToStart; + bool _phySize_Defined; + CMyComPtr _stream; CMyComPtr _seqStream; - UInt32 _crcSize; + UInt32 _filterId; + AString _methodsString; void Init() { - _crcSize = 4; - COutHandler::Init(); + _filterId = 0; + CMultiMethodProps::Init(); } - HRESULT Open2(IInStream *inStream, IArchiveOpenCallback *callback); + HRESULT Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback); + + HRESULT Decode2(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, IDecodeState &progress) + { + RINOK(progress.Decode(seqInStream, outStream)); + _stat = progress; + _phySize_Defined = true; + return S_OK; + } public: MY_QUERYINTERFACE_BEGIN2(IInArchive) @@ -87,7 +171,7 @@ public: #ifndef EXTRACT_ONLY INTERFACE_IOutArchive(;) - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps); + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); #endif CHandler(); @@ -98,60 +182,60 @@ CHandler::CHandler() Init(); } -STATPROPSTG kProps[] = +static const Byte kProps[] = { - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, - { NULL, kpidMethod, VT_BSTR} + kpidSize, + kpidPackSize, + kpidMethod }; -STATPROPSTG kArcProps[] = +static const Byte kArcProps[] = { - { NULL, kpidMethod, VT_BSTR}, - { NULL, kpidNumBlocks, VT_UI4} + kpidMethod, + kpidNumStreams, + kpidNumBlocks }; IMP_IInArchive_Props IMP_IInArchive_ArcProps -static char GetHex(Byte value) +static inline char GetHex(unsigned value) { return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); } -static inline void AddHexToString(AString &res, Byte value) +static inline void AddHexToString(AString &s, Byte value) { - res += GetHex((Byte)(value >> 4)); - res += GetHex((Byte)(value & 0xF)); + s += GetHex(value >> 4); + s += GetHex(value & 0xF); } -static AString ConvertUInt32ToString(UInt32 value) +static void AddUInt32ToString(AString &s, UInt32 value) { - char temp[32]; - ::ConvertUInt32ToString(value, temp); - return temp; + char temp[16]; + ConvertUInt32ToString(value, temp); + s += temp; } -static AString Lzma2PropToString(int prop) +static void Lzma2PropToString(AString &s, unsigned prop) { + char c = 0; + UInt32 size; if ((prop & 1) == 0) - return ConvertUInt32ToString(prop / 2 + 12); - AString res; - char c; - - UInt32 size = (2 | ((prop) & 1)) << ((prop) / 2 + 1); - - if (prop > 17) - { - res = ConvertUInt32ToString(size >> 10); - c = 'm'; - } + size = prop / 2 + 12; else { - res = ConvertUInt32ToString(size); c = 'k'; + size = (UInt32)(2 | (prop & 1)) << (prop / 2 + 1); + if (prop > 17) + { + size >>= 10; + c = 'm'; + } } - return res + c; + AddUInt32ToString(s, size); + if (c != 0) + s += c; } struct CMethodNamePair @@ -160,11 +244,11 @@ struct CMethodNamePair const char *Name; }; -static CMethodNamePair g_NamePairs[] = +static const CMethodNamePair g_NamePairs[] = { { XZ_ID_Subblock, "SB" }, { XZ_ID_Delta, "Delta" }, - { XZ_ID_X86, "x86" }, + { XZ_ID_X86, "BCJ" }, { XZ_ID_PPC, "PPC" }, { XZ_ID_IA64, "IA64" }, { XZ_ID_ARM, "ARM" }, @@ -175,25 +259,29 @@ static CMethodNamePair g_NamePairs[] = static AString GetMethodString(const CXzFilter &f) { - AString s; - - for (int i = 0; i < sizeof(g_NamePairs) / sizeof(g_NamePairs[i]); i++) + const char *p = NULL; + for (unsigned i = 0; i < ARRAY_SIZE(g_NamePairs); i++) if (g_NamePairs[i].Id == f.id) - s = g_NamePairs[i].Name; - if (s.IsEmpty()) + { + p = g_NamePairs[i].Name; + break; + } + char temp[32]; + if (!p) { - char temp[32]; ::ConvertUInt64ToString(f.id, temp); - s = temp; + p = temp; } + AString s = p; + if (f.propsSize > 0) { s += ':'; if (f.id == XZ_ID_LZMA2 && f.propsSize == 1) - s += Lzma2PropToString(f.props[0]); + Lzma2PropToString(s, f.props[0]); else if (f.id == XZ_ID_Delta && f.propsSize == 1) - s += ConvertUInt32ToString((UInt32)f.props[0] + 1); + AddUInt32ToString(s, (UInt32)f.props[0] + 1); else { s += '['; @@ -214,22 +302,22 @@ static void AddString(AString &dest, const AString &src) static const char *kChecks[] = { - "NoCheck", - "CRC32", - NULL, - NULL, - "CRC64", - NULL, - NULL, - NULL, - NULL, - NULL, - "SHA256", - NULL, - NULL, - NULL, - NULL, - NULL + "NoCheck" + , "CRC32" + , NULL + , NULL + , "CRC64" + , NULL + , NULL + , NULL + , NULL + , NULL + , "SHA256" + , NULL + , NULL + , NULL + , NULL + , NULL }; static AString GetCheckString(const CXzs &xzs) @@ -246,7 +334,10 @@ static AString GetCheckString(const CXzs &xzs) if (kChecks[i]) s2 = kChecks[i]; else - s2 = "Check-" + ConvertUInt32ToString((UInt32)i); + { + s2 = "Check-"; + AddUInt32ToString(s2, (UInt32)i); + } AddString(s, s2); } return s; @@ -255,12 +346,26 @@ static AString GetCheckString(const CXzs &xzs) STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - switch(propID) + NCOM::CPropVariant prop; + switch (propID) { - case kpidNumBlocks: if (!_useSeq) prop = _numBlocks; break; - case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; + case kpidPhySize: if (_phySize_Defined) prop = _stat.PhySize; break; + case kpidNumStreams: if (_stat.NumStreams_Defined) prop = _stat.NumStreams; break; + case kpidNumBlocks: if (_stat.NumBlocks_Defined) prop = _stat.NumBlocks; break; + case kpidUnpackSize: if (_stat.UnpackSize_Defined) prop = _stat.OutSize; break; case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break; + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;; + if (_stat.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd; + if (_stat.DataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; + if (_stat.HeadersError) v |= kpv_ErrorFlags_HeadersError; + if (_stat.Unsupported) v |= kpv_ErrorFlags_UnsupportedMethod; + if (_stat.DataError) v |= kpv_ErrorFlags_DataError; + if (_stat.CrcError) v |= kpv_ErrorFlags_CrcError; + prop = v; + } } prop.Detach(value); return S_OK; @@ -273,14 +378,14 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } -STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value) +STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - switch(propID) + NCOM::CPropVariant prop; + switch (propID) { - case kpidSize: if (_unpackSizeDefined) prop = _unpackSize; break; - case kpidPackSize: if (_packSizeDefined) prop = _packSize; break; + case kpidSize: if (_stat.UnpackSize_Defined) prop = _stat.OutSize; break; + case kpidPackSize: if (_phySize_Defined) prop = _stat.PhySize; break; case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break; } prop.Detach(value); @@ -318,82 +423,124 @@ struct CXzsCPP ~CXzsCPP() { Xzs_Free(&p, &g_Alloc); } }; -HRESULT CHandler::Open2(IInStream *inStream, IArchiveOpenCallback *callback) + +struct CVirtProgress_To_OpenProgress: public IDecodeState { - CSeekInStreamWrap inStreamImp(inStream); + IArchiveOpenCallback *Callback; + UInt64 Offset; - CLookToRead lookStream; - LookToRead_CreateVTable(&lookStream, True); - lookStream.realStream = &inStreamImp.p; - LookToRead_Init(&lookStream); + HRESULT Progress(); +}; - COpenCallbackWrap openWrap(callback); - RINOK(inStream->Seek(0, STREAM_SEEK_END, &_packSize)); - RINOK(callback->SetTotal(NULL, &_packSize)); +HRESULT CVirtProgress_To_OpenProgress::Progress() +{ + if (Callback) + { + UInt64 files = 0; + UInt64 value = Offset + InSize; + return Callback->SetCompleted(&files, &value); + } + return S_OK; +} - CXzsCPP xzs; - SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.s, &_startPosition, &openWrap.p, &g_Alloc); - if (res == SZ_ERROR_NO_ARCHIVE && xzs.p.num > 0) - res = SZ_OK; - if (res == SZ_OK) +static HRESULT SRes_to_Open_HRESULT(SRes res) +{ + switch (res) { - _packSize -= _startPosition; - _unpackSize = Xzs_GetUnpackSize(&xzs.p); - _unpackSizeDefined = _packSizeDefined = true; - _numBlocks = (UInt64)Xzs_GetNumBlocks(&xzs.p); + case SZ_OK: return S_OK; + case SZ_ERROR_MEM: return E_OUTOFMEMORY; + case SZ_ERROR_PROGRESS: return E_ABORT; + /* + case SZ_ERROR_UNSUPPORTED: + case SZ_ERROR_CRC: + case SZ_ERROR_DATA: + case SZ_ERROR_ARCHIVE: + case SZ_ERROR_NO_ARCHIVE: + return S_FALSE; + */ + } + return S_FALSE; +} + +HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback) +{ + _needSeekToStart = true; - RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); + { CXzStreamFlags st; CSeqInStreamWrap inStreamWrap(inStream); - SRes res2 = Xz_ReadHeader(&st, &inStreamWrap.p); + SRes res = Xz_ReadHeader(&st, &inStreamWrap.p); + if (res != SZ_OK) + return SRes_to_Open_HRESULT(res); - if (res2 == SZ_OK) { CXzBlock block; Bool isIndex; UInt32 headerSizeRes; - res2 = XzBlock_ReadHeader(&block, &inStreamWrap.p, &isIndex, &headerSizeRes); + SRes res2 = XzBlock_ReadHeader(&block, &inStreamWrap.p, &isIndex, &headerSizeRes); if (res2 == SZ_OK && !isIndex) { - int numFilters = XzBlock_GetNumFilters(&block); - for (int i = 0; i < numFilters; i++) + unsigned numFilters = XzBlock_GetNumFilters(&block); + for (unsigned i = 0; i < numFilters; i++) AddString(_methodsString, GetMethodString(block.filters[i])); } } - AddString(_methodsString, GetCheckString(xzs.p)); } - if (res != SZ_OK || _startPosition != 0) + RINOK(inStream->Seek(0, STREAM_SEEK_END, &_stat.PhySize)); + RINOK(callback->SetTotal(NULL, &_stat.PhySize)); + + CSeekInStreamWrap inStreamImp(inStream); + + CLookToRead lookStream; + LookToRead_CreateVTable(&lookStream, True); + lookStream.realStream = &inStreamImp.p; + LookToRead_Init(&lookStream); + + COpenCallbackWrap openWrap(callback); + + CXzsCPP xzs; + Int64 startPosition; + SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.s, &startPosition, &openWrap.p, &g_Alloc); + if (res == SZ_ERROR_PROGRESS) + return (openWrap.Res == S_OK) ? E_FAIL : openWrap.Res; + /* + if (res == SZ_ERROR_NO_ARCHIVE && xzs.p.num > 0) + res = SZ_OK; + */ + if (res == SZ_OK && startPosition == 0) { - RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); - CXzStreamFlags st; - CSeqInStreamWrap inStreamWrap(inStream); - SRes res2 = Xz_ReadHeader(&st, &inStreamWrap.p); - if (res2 == SZ_OK) - { - res = res2; - _startPosition = 0; - _useSeq = True; - _unpackSizeDefined = _packSizeDefined = false; - } + _phySize_Defined = true; + + _stat.OutSize = Xzs_GetUnpackSize(&xzs.p); + _stat.UnpackSize_Defined = true; + + _stat.NumStreams = xzs.p.num; + _stat.NumStreams_Defined = true; + + _stat.NumBlocks = Xzs_GetNumBlocks(&xzs.p); + _stat.NumBlocks_Defined = true; + + AddString(_methodsString, GetCheckString(xzs.p)); } - if (res == SZ_ERROR_NO_ARCHIVE) - return S_FALSE; - RINOK(SResToHRESULT(res)); + else + { + res = SZ_OK; + } + RINOK(SRes_to_Open_HRESULT(res)); _stream = inStream; _seqStream = inStream; + _isArc = true; return S_OK; } STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback) { COM_TRY_BEGIN - try { Close(); - return Open2(inStream, callback); + return Open2(inStream, /* 0, */ callback); } - catch(...) { return S_FALSE; } COM_TRY_END } @@ -401,15 +548,21 @@ STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) { Close(); _seqStream = stream; + _isArc = true; + _needSeekToStart = false; return S_OK; } STDMETHODIMP CHandler::Close() { - _numBlocks = 0; - _useSeq = true; - _unpackSizeDefined = _packSizeDefined = false; - _methodsString.Empty(); + _stat.Clear(); + + _isArc = false; + _needSeekToStart = false; + + _phySize_Defined = false; + + _methodsString.Empty(); _stream.Release(); _seqStream.Release(); return S_OK; @@ -439,7 +592,11 @@ struct CXzUnpackerCPP Byte *InBuf; Byte *OutBuf; CXzUnpacker p; - CXzUnpackerCPP(): InBuf(0), OutBuf(0) {} + + CXzUnpackerCPP(): InBuf(0), OutBuf(0) + { + XzUnpacker_Construct(&p, &g_Alloc); + } ~CXzUnpackerCPP() { XzUnpacker_Free(&p); @@ -448,133 +605,195 @@ struct CXzUnpackerCPP } }; -STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, - Int32 testMode, IArchiveExtractCallback *extractCallback) +HRESULT IDecodeState::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream) { - COM_TRY_BEGIN - if (numItems == 0) - return S_OK; - if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0)) - return E_INVALIDARG; - - extractCallback->SetTotal(_packSize); - UInt64 currentTotalPacked = 0; - RINOK(extractCallback->SetCompleted(¤tTotalPacked)); - CMyComPtr realOutStream; - Int32 askMode = testMode ? - NExtract::NAskMode::kTest : - NExtract::NAskMode::kExtract; - - RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); - - if (!testMode && !realOutStream) - return S_OK; - - extractCallback->PrepareOperation(askMode); + const size_t kInBufSize = 1 << 15; + const size_t kOutBufSize = 1 << 21; - if (_stream) - { - RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); - } - - CLocalProgress *lps = new CLocalProgress; - CMyComPtr progress = lps; - lps->Init(extractCallback, true); + DecodeRes = SZ_OK; - CCompressProgressWrap progressWrap(progress); - - SRes res; - - const UInt32 kInBufSize = 1 << 15; - const UInt32 kOutBufSize = 1 << 21; + CXzUnpackerCPP xzu; + XzUnpacker_Init(&xzu.p); + xzu.InBuf = (Byte *)MyAlloc(kInBufSize); + xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize); + if (!xzu.InBuf || !xzu.OutBuf) + return E_OUTOFMEMORY; - UInt32 inPos = 0; UInt32 inSize = 0; - UInt32 outPos = 0; - CXzUnpackerCPP xzu; - res = XzUnpacker_Create(&xzu.p, &g_Alloc); - if (res == SZ_OK) - { - xzu.InBuf = (Byte *)MyAlloc(kInBufSize); - xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize); - if (xzu.InBuf == 0 || xzu.OutBuf == 0) - res = SZ_ERROR_MEM; - } - if (res == SZ_OK) + SizeT inPos = 0; + SizeT outPos = 0; + for (;;) { if (inPos == inSize) { inPos = inSize = 0; - RINOK(_seqStream->Read(xzu.InBuf, kInBufSize, &inSize)); + RINOK(seqInStream->Read(xzu.InBuf, kInBufSize, &inSize)); } SizeT inLen = inSize - inPos; SizeT outLen = kOutBufSize - outPos; ECoderStatus status; - res = XzUnpacker_Code(&xzu.p, + + SRes res = XzUnpacker_Code(&xzu.p, xzu.OutBuf + outPos, &outLen, xzu.InBuf + inPos, &inLen, (inSize == 0 ? CODER_FINISH_END : CODER_FINISH_ANY), &status); - // printf("\n_inPos = %6d inLen = %5d, outLen = %5d", inPos, inLen, outLen); + inPos += inLen; + outPos += outLen; - inPos += (UInt32)inLen; - outPos += (UInt32)outLen; - lps->InSize += inLen; - lps->OutSize += outLen; + InSize += inLen; + OutSize += outLen; - bool finished = (((inLen == 0) && (outLen == 0)) || res != SZ_OK); + DecodeRes = res; - if (outPos == kOutBufSize || finished) + bool finished = ((inLen == 0 && outLen == 0) || res != SZ_OK); + + if (outStream) { - if (realOutStream && outPos > 0) + if (outPos == kOutBufSize || finished) { - RINOK(WriteStream(realOutStream, xzu.OutBuf, outPos)); + if (outPos != 0) + { + RINOK(WriteStream(outStream, xzu.OutBuf, outPos)); + outPos = 0; + } } - outPos = 0; } + else + outPos = 0; + + RINOK(Progress()); + if (finished) { - _packSize = lps->InSize; - _unpackSize = lps->OutSize; - _packSizeDefined = _unpackSizeDefined = true; + PhySize = InSize; + NumStreams = xzu.p.numStartedStreams; + if (NumStreams > 0) + IsArc = true; + NumBlocks = xzu.p.numTotalBlocks; + + UnpackSize_Defined = true; + NumStreams_Defined = true; + NumBlocks_Defined = true; + + UInt64 extraSize = XzUnpacker_GetExtraSize(&xzu.p); + if (res == SZ_OK) { if (status == CODER_STATUS_NEEDS_MORE_INPUT) { - if (XzUnpacker_IsStreamWasFinished(&xzu.p)) - _packSize -= xzu.p.padSize; - else + extraSize = 0; + if (!XzUnpacker_IsStreamWasFinished(&xzu.p)) + { + // finished at padding bytes, but padding is not aligned for 4 + UnexpectedEnd = true; res = SZ_ERROR_DATA; + } } - else + else // status == CODER_STATUS_NOT_FINISHED res = SZ_ERROR_DATA; } + else if (res == SZ_ERROR_NO_ARCHIVE) + { + if (InSize == extraSize) + IsArc = false; + else + { + if (extraSize != 0 || inPos != inSize) + { + DataAfterEnd = true; + res = SZ_OK; + } + } + } + + DecodeRes = res; + PhySize -= extraSize; + + switch (res) + { + case SZ_OK: break; + case SZ_ERROR_NO_ARCHIVE: IsArc = false; break; + case SZ_ERROR_ARCHIVE: HeadersError = true; break; + case SZ_ERROR_UNSUPPORTED: Unsupported = true; break; + case SZ_ERROR_CRC: CrcError = true; break; + case SZ_ERROR_DATA: DataError = true; break; + default: DataError = true; break; + } + break; } - RINOK(lps->SetCur()); } - Int32 opRes; - switch(res) + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + if (numItems == 0) + return S_OK; + if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) + return E_INVALIDARG; + + extractCallback->SetTotal(_stat.PhySize); + UInt64 currentTotalPacked = 0; + RINOK(extractCallback->SetCompleted(¤tTotalPacked)); + CMyComPtr realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + + RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); + + if (!testMode && !realOutStream) + return S_OK; + + extractCallback->PrepareOperation(askMode); + + CVirtProgress_To_LocalProgress vp; + vp.lps = new CLocalProgress; + vp.progress = vp.lps; + vp.lps->Init(extractCallback, true); + + + if (_needSeekToStart) { - case SZ_OK: - opRes = NExtract::NOperationResult::kOK; break; - case SZ_ERROR_UNSUPPORTED: - opRes = NExtract::NOperationResult::kUnSupportedMethod; break; - case SZ_ERROR_CRC: - opRes = NExtract::NOperationResult::kCRCError; break; - case SZ_ERROR_DATA: - case SZ_ERROR_ARCHIVE: - case SZ_ERROR_NO_ARCHIVE: - opRes = NExtract::NOperationResult::kDataError; break; - default: - return SResToHRESULT(res); + if (!_stream) + return E_FAIL; + RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); } + else + _needSeekToStart = true; + + RINOK(Decode2(_seqStream, realOutStream, vp)); + + Int32 opRes; + + if (!vp.IsArc) + opRes = NExtract::NOperationResult::kIsNotArc; + else if (vp.UnexpectedEnd) + opRes = NExtract::NOperationResult::kUnexpectedEnd; + else if (vp.DataAfterEnd) + opRes = NExtract::NOperationResult::kDataAfterEnd; + else if (vp.CrcError) + opRes = NExtract::NOperationResult::kCRCError; + else if (vp.Unsupported) + opRes = NExtract::NOperationResult::kUnsupportedMethod; + else if (vp.HeadersError) + opRes = NExtract::NOperationResult::kDataError; + else if (vp.DataError) + opRes = NExtract::NOperationResult::kDataError; + else if (vp.DecodeRes != SZ_OK) + opRes = NExtract::NOperationResult::kDataError; + else + opRes = NExtract::NOperationResult::kOK; + realOutStream.Release(); - RINOK(extractCallback->SetOperationResult(opRes)); - return S_OK; + return extractCallback->SetOperationResult(opRes); COM_TRY_END } @@ -590,13 +809,13 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt IArchiveUpdateCallback *updateCallback) { CSeqOutStreamWrap seqOutStream(outStream); - + if (numItems == 0) { SRes res = Xz_EncodeEmpty(&seqOutStream.p); return SResToHRESULT(res); } - + if (numItems != 1) return E_INVALIDARG; @@ -619,8 +838,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (IntToBool(newData)) { + UInt64 size; { - UInt64 size; NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(0, kpidSize, &prop)); if (prop.vt != VT_UI8) @@ -632,24 +851,28 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt CLzma2EncProps lzma2Props; Lzma2EncProps_Init(&lzma2Props); - lzma2Props.lzmaProps.level = _level; + lzma2Props.lzmaProps.level = GetLevel(); CMyComPtr fileInStream; RINOK(updateCallback->GetStream(0, &fileInStream)); CSeqInStreamWrap seqInStream(fileInStream); - for (int i = 0; i < _methods.Size(); i++) + { + NCOM::CPropVariant prop = (UInt64)size; + RINOK(NCompress::NLzma2::SetLzma2Prop(NCoderPropID::kReduceSize, prop, lzma2Props)); + } + + FOR_VECTOR (i, _methods) { COneMethodInfo &m = _methods[i]; - SetCompressionMethod2(m + SetGlobalLevelAndThreads(m #ifndef _7ZIP_ST , _numThreads #endif ); - if (m.IsLzma()) { - for (int j = 0; j < m.Props.Size(); j++) + FOR_VECTOR (j, m.Props) { const CProp &prop = m.Props[j]; RINOK(NCompress::NLzma2::SetLzma2Prop(prop.Id, prop.Value, lzma2Props)); @@ -666,7 +889,40 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt lps->Init(updateCallback, true); CCompressProgressWrap progressWrap(progress); - SRes res = Xz_Encode(&seqOutStream.p, &seqInStream.p, &lzma2Props, False, &progressWrap.p); + CXzProps xzProps; + CXzFilterProps filter; + XzProps_Init(&xzProps); + XzFilterProps_Init(&filter); + xzProps.lzma2Props = &lzma2Props; + xzProps.filterProps = (_filterId != 0 ? &filter : NULL); + switch (_crcSize) + { + case 0: xzProps.checkId = XZ_CHECK_NO; break; + case 4: xzProps.checkId = XZ_CHECK_CRC32; break; + case 8: xzProps.checkId = XZ_CHECK_CRC64; break; + case 32: xzProps.checkId = XZ_CHECK_SHA256; break; + default: return E_INVALIDARG; + } + filter.id = _filterId; + if (_filterId == XZ_ID_Delta) + { + bool deltaDefined = false; + FOR_VECTOR (j, _filterMethod.Props) + { + const CProp &prop = _filterMethod.Props[j]; + if (prop.Id == NCoderPropID::kDefaultProp && prop.Value.vt == VT_UI4) + { + UInt32 delta = (UInt32)prop.Value.ulVal; + if (delta < 1 || delta > 256) + return E_INVALIDARG; + filter.delta = delta; + deltaDefined = true; + } + } + if (!deltaDefined) + return E_INVALIDARG; + } + SRes res = Xz_Encode(&seqOutStream.p, &seqInStream.p, &xzProps, &progressWrap.p); if (res == SZ_OK) return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); return SResToHRESULT(res); @@ -674,33 +930,61 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (indexInArchive != 0) return E_INVALIDARG; if (_stream) - RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); - return NCompress::CopyStream(_stream, outStream, 0); + RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); + return NCompress::CopyStream(_stream, outStream, NULL); } -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) { COM_TRY_BEGIN - BeforeSetProperty(); - for (int i = 0; i < numProps; i++) + Init(); + for (UInt32 i = 0; i < numProps; i++) { RINOK(SetProperty(names[i], values[i])); } + + if (!_filterMethod.MethodName.IsEmpty()) + { + unsigned k; + for (k = 0; k < ARRAY_SIZE(g_NamePairs); k++) + { + const CMethodNamePair &pair = g_NamePairs[k]; + if (StringsAreEqualNoCase_Ascii(_filterMethod.MethodName, pair.Name)) + { + _filterId = pair.Id; + break; + } + } + if (k == ARRAY_SIZE(g_NamePairs)) + return E_INVALIDARG; + } + + _methods.DeleteFrontal(GetNumEmptyMethods()); + if (_methods.Size() > 1) + return E_INVALIDARG; + if (_methods.Size() == 1) + { + UString &methodName = _methods[0].MethodName; + if (methodName.IsEmpty()) + methodName = k_LZMA2_Name; + else if (!methodName.IsEqualToNoCase(k_LZMA2_Name)) + return E_INVALIDARG; + } return S_OK; COM_TRY_END } #endif -static IInArchive *CreateArc() { return new NArchive::NXz::CHandler; } -#ifndef EXTRACT_ONLY -static IOutArchive *CreateArcOut() { return new NArchive::NXz::CHandler; } -#else -#define CreateArcOut 0 -#endif +IMP_CreateArcIn +IMP_CreateArcOut static CArcInfo g_ArcInfo = - { L"xz", L"xz txz", L"* .tar", 0xC, {0xFD, '7' , 'z', 'X', 'Z', '\0'}, 6, true, CreateArc, CreateArcOut }; + { "xz", "xz txz", "* .tar", 0xC, + 6, { 0xFD, '7' , 'z', 'X', 'Z', 0 }, + 0, + NArcInfoFlags::kKeepName, + REF_CreateArc_Pair }; REGISTER_ARC(xz) diff --git a/src/libs/7zip/unix/CPP/7zip/Common/CWrappers.cpp b/src/libs/7zip/unix/CPP/7zip/Common/CWrappers.cpp index 358f0b503..a15794e2a 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/CWrappers.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Common/CWrappers.cpp @@ -12,14 +12,14 @@ #define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x) -static SRes CompressProgress(void *pp, UInt64 inSize, UInt64 outSize) +static SRes CompressProgress(void *pp, UInt64 inSize, UInt64 outSize) throw() { CCompressProgressWrap *p = (CCompressProgressWrap *)pp; p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize)); return (SRes)p->Res; } -CCompressProgressWrap::CCompressProgressWrap(ICompressProgressInfo *progress) +CCompressProgressWrap::CCompressProgressWrap(ICompressProgressInfo *progress) throw() { p.Progress = CompressProgress; Progress = progress; @@ -30,29 +30,31 @@ static const UInt32 kStreamStepSize = (UInt32)1 << 31; SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) { - switch(res) + switch (res) { case S_OK: return SZ_OK; case E_OUTOFMEMORY: return SZ_ERROR_MEM; case E_INVALIDARG: return SZ_ERROR_PARAM; case E_ABORT: return SZ_ERROR_PROGRESS; case S_FALSE: return SZ_ERROR_DATA; + case E_NOTIMPL: return SZ_ERROR_UNSUPPORTED; } return defaultRes; } -static SRes MyRead(void *object, void *data, size_t *size) +static SRes MyRead(void *object, void *data, size_t *size) throw() { CSeqInStreamWrap *p = (CSeqInStreamWrap *)object; UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize); p->Res = (p->Stream->Read(data, curSize, &curSize)); *size = curSize; + p->Processed += curSize; if (p->Res == S_OK) return SZ_OK; return HRESULT_To_SRes(p->Res, SZ_ERROR_READ); } -static size_t MyWrite(void *object, const void *data, size_t size) +static size_t MyWrite(void *object, const void *data, size_t size) throw() { CSeqOutStreamWrap *p = (CSeqOutStreamWrap *)object; if (p->Stream) @@ -67,13 +69,14 @@ static size_t MyWrite(void *object, const void *data, size_t size) return size; } -CSeqInStreamWrap::CSeqInStreamWrap(ISequentialInStream *stream) +CSeqInStreamWrap::CSeqInStreamWrap(ISequentialInStream *stream) throw() { p.Read = MyRead; Stream = stream; + Processed = 0; } -CSeqOutStreamWrap::CSeqOutStreamWrap(ISequentialOutStream *stream) +CSeqOutStreamWrap::CSeqOutStreamWrap(ISequentialOutStream *stream) throw() { p.Write = MyWrite; Stream = stream; @@ -81,7 +84,7 @@ CSeqOutStreamWrap::CSeqOutStreamWrap(ISequentialOutStream *stream) Processed = 0; } -HRESULT SResToHRESULT(SRes res) +HRESULT SResToHRESULT(SRes res) throw() { switch(res) { @@ -90,11 +93,12 @@ HRESULT SResToHRESULT(SRes res) case SZ_ERROR_PARAM: return E_INVALIDARG; case SZ_ERROR_PROGRESS: return E_ABORT; case SZ_ERROR_DATA: return S_FALSE; + case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; } return E_FAIL; } -static SRes InStreamWrap_Read(void *pp, void *data, size_t *size) +static SRes InStreamWrap_Read(void *pp, void *data, size_t *size) throw() { CSeekInStreamWrap *p = (CSeekInStreamWrap *)pp; UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize); @@ -103,7 +107,7 @@ static SRes InStreamWrap_Read(void *pp, void *data, size_t *size) return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ; } -static SRes InStreamWrap_Seek(void *pp, Int64 *offset, ESzSeek origin) +static SRes InStreamWrap_Seek(void *pp, Int64 *offset, ESzSeek origin) throw() { CSeekInStreamWrap *p = (CSeekInStreamWrap *)pp; UInt32 moveMethod; @@ -120,7 +124,7 @@ static SRes InStreamWrap_Seek(void *pp, Int64 *offset, ESzSeek origin) return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ; } -CSeekInStreamWrap::CSeekInStreamWrap(IInStream *stream) +CSeekInStreamWrap::CSeekInStreamWrap(IInStream *stream) throw() { Stream = stream; p.Read = InStreamWrap_Read; @@ -131,13 +135,13 @@ CSeekInStreamWrap::CSeekInStreamWrap(IInStream *stream) /* ---------- CByteInBufWrap ---------- */ -void CByteInBufWrap::Free() +void CByteInBufWrap::Free() throw() { ::MidFree(Buf); Buf = 0; } -bool CByteInBufWrap::Alloc(UInt32 size) +bool CByteInBufWrap::Alloc(UInt32 size) throw() { if (Buf == 0 || size != Size) { @@ -148,7 +152,7 @@ bool CByteInBufWrap::Alloc(UInt32 size) return (Buf != 0); } -Byte CByteInBufWrap::ReadByteFromNewBlock() +Byte CByteInBufWrap::ReadByteFromNewBlock() throw() { if (Res == S_OK) { @@ -164,7 +168,7 @@ Byte CByteInBufWrap::ReadByteFromNewBlock() return 0; } -static Byte Wrap_ReadByte(void *pp) +static Byte Wrap_ReadByte(void *pp) throw() { CByteInBufWrap *p = (CByteInBufWrap *)pp; if (p->Cur != p->Lim) @@ -180,13 +184,13 @@ CByteInBufWrap::CByteInBufWrap(): Buf(0) /* ---------- CByteOutBufWrap ---------- */ -void CByteOutBufWrap::Free() +void CByteOutBufWrap::Free() throw() { ::MidFree(Buf); Buf = 0; } -bool CByteOutBufWrap::Alloc(size_t size) +bool CByteOutBufWrap::Alloc(size_t size) throw() { if (Buf == 0 || size != Size) { @@ -197,7 +201,7 @@ bool CByteOutBufWrap::Alloc(size_t size) return (Buf != 0); } -HRESULT CByteOutBufWrap::Flush() +HRESULT CByteOutBufWrap::Flush() throw() { if (Res == S_OK) { @@ -210,7 +214,7 @@ HRESULT CByteOutBufWrap::Flush() return Res; } -static void Wrap_WriteByte(void *pp, Byte b) +static void Wrap_WriteByte(void *pp, Byte b) throw() { CByteOutBufWrap *p = (CByteOutBufWrap *)pp; Byte *dest = p->Cur; @@ -220,7 +224,7 @@ static void Wrap_WriteByte(void *pp, Byte b) p->Flush(); } -CByteOutBufWrap::CByteOutBufWrap(): Buf(0) +CByteOutBufWrap::CByteOutBufWrap() throw(): Buf(0) { p.Write = Wrap_WriteByte; } diff --git a/src/libs/7zip/unix/CPP/7zip/Common/CWrappers.h b/src/libs/7zip/unix/CPP/7zip/Common/CWrappers.h index 80a8a1b61..4fe7dea3e 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/CWrappers.h +++ b/src/libs/7zip/unix/CPP/7zip/Common/CWrappers.h @@ -11,7 +11,8 @@ struct CCompressProgressWrap ICompressProgress p; ICompressProgressInfo *Progress; HRESULT Res; - CCompressProgressWrap(ICompressProgressInfo *progress); + + CCompressProgressWrap(ICompressProgressInfo *progress) throw(); }; struct CSeqInStreamWrap @@ -19,7 +20,9 @@ struct CSeqInStreamWrap ISeqInStream p; ISequentialInStream *Stream; HRESULT Res; - CSeqInStreamWrap(ISequentialInStream *stream); + UInt64 Processed; + + CSeqInStreamWrap(ISequentialInStream *stream) throw(); }; struct CSeekInStreamWrap @@ -27,7 +30,8 @@ struct CSeekInStreamWrap ISeekInStream p; IInStream *Stream; HRESULT Res; - CSeekInStreamWrap(IInStream *stream); + + CSeekInStreamWrap(IInStream *stream) throw(); }; struct CSeqOutStreamWrap @@ -36,10 +40,11 @@ struct CSeqOutStreamWrap ISequentialOutStream *Stream; HRESULT Res; UInt64 Processed; - CSeqOutStreamWrap(ISequentialOutStream *stream); + + CSeqOutStreamWrap(ISequentialOutStream *stream) throw(); }; -HRESULT SResToHRESULT(SRes res); +HRESULT SResToHRESULT(SRes res) throw(); struct CByteInBufWrap { @@ -52,11 +57,11 @@ struct CByteInBufWrap UInt64 Processed; bool Extra; HRESULT Res; - + CByteInBufWrap(); - ~CByteInBufWrap() { Free(); } - void Free(); - bool Alloc(UInt32 size); + ~CByteInBufWrap() { Free(); } + void Free() throw(); + bool Alloc(UInt32 size) throw(); void Init() { Lim = Cur = Buf; @@ -65,7 +70,7 @@ struct CByteInBufWrap Res = S_OK; } UInt64 GetProcessed() const { return Processed + (Cur - Buf); } - Byte ReadByteFromNewBlock(); + Byte ReadByteFromNewBlock() throw(); Byte ReadByte() { if (Cur != Lim) @@ -84,11 +89,11 @@ struct CByteOutBufWrap ISequentialOutStream *Stream; UInt64 Processed; HRESULT Res; - - CByteOutBufWrap(); - ~CByteOutBufWrap() { Free(); } - void Free(); - bool Alloc(size_t size); + + CByteOutBufWrap() throw(); + ~CByteOutBufWrap() { Free(); } + void Free() throw(); + bool Alloc(size_t size) throw(); void Init() { Cur = Buf; @@ -97,7 +102,7 @@ struct CByteOutBufWrap Res = S_OK; } UInt64 GetProcessed() const { return Processed + (Cur - Buf); } - HRESULT Flush(); + HRESULT Flush() throw(); void WriteByte(Byte b) { *Cur++ = b; diff --git a/src/libs/7zip/unix/CPP/7zip/Common/Common.pri b/src/libs/7zip/unix/CPP/7zip/Common/Common.pri new file mode 100644 index 000000000..a23ad30b1 --- /dev/null +++ b/src/libs/7zip/unix/CPP/7zip/Common/Common.pri @@ -0,0 +1,39 @@ +HEADERS += $$7ZIP_BASE/CPP/7zip/Common/CWrappers.h \ + $$7ZIP_BASE/CPP/7zip/Common/CreateCoder.h \ + $$7ZIP_BASE/CPP/7zip/Common/FilePathAutoRename.h \ + $$7ZIP_BASE/CPP/7zip/Common/FileStreams.h \ + $$7ZIP_BASE/CPP/7zip/Common/FilterCoder.h \ + $$7ZIP_BASE/CPP/7zip/Common/InBuffer.h \ + $$7ZIP_BASE/CPP/7zip/Common/InOutTempBuffer.h \ + $$7ZIP_BASE/CPP/7zip/Common/LimitedStreams.h \ + $$7ZIP_BASE/CPP/7zip/Common/LockedStream.h \ + $$7ZIP_BASE/CPP/7zip/Common/MethodId.h \ + $$7ZIP_BASE/CPP/7zip/Common/MethodProps.h \ + $$7ZIP_BASE/CPP/7zip/Common/OutBuffer.h \ + $$7ZIP_BASE/CPP/7zip/Common/ProgressUtils.h \ + $$7ZIP_BASE/CPP/7zip/Common/RegisterArc.h \ + $$7ZIP_BASE/CPP/7zip/Common/RegisterCodec.h \ + $$7ZIP_BASE/CPP/7zip/Common/StreamBinder.h \ + $$7ZIP_BASE/CPP/7zip/Common/StreamObjects.h \ + $$7ZIP_BASE/CPP/7zip/Common/StreamUtils.h \ + $$7ZIP_BASE/CPP/7zip/Common/UniqBlocks.h \ + $$7ZIP_BASE/CPP/7zip/Common/VirtThread.h + +SOURCES += $$7ZIP_BASE/CPP/7zip/Common/CWrappers.cpp \ + $$7ZIP_BASE/CPP/7zip/Common/CreateCoder.cpp \ + $$7ZIP_BASE/CPP/7zip/Common/FilePathAutoRename.cpp \ + $$7ZIP_BASE/CPP/7zip/Common/FileStreams.cpp \ + $$7ZIP_BASE/CPP/7zip/Common/FilterCoder.cpp \ + $$7ZIP_BASE/CPP/7zip/Common/InBuffer.cpp \ + $$7ZIP_BASE/CPP/7zip/Common/InOutTempBuffer.cpp \ + $$7ZIP_BASE/CPP/7zip/Common/LimitedStreams.cpp \ + $$7ZIP_BASE/CPP/7zip/Common/LockedStream.cpp \ + $$7ZIP_BASE/CPP/7zip/Common/MethodProps.cpp \ + $$7ZIP_BASE/CPP/7zip/Common/OutBuffer.cpp \ + $$7ZIP_BASE/CPP/7zip/Common/ProgressUtils.cpp \ + $$7ZIP_BASE/CPP/7zip/Common/PropId.cpp \ + $$7ZIP_BASE/CPP/7zip/Common/StreamBinder.cpp \ + $$7ZIP_BASE/CPP/7zip/Common/StreamObjects.cpp \ + $$7ZIP_BASE/CPP/7zip/Common/StreamUtils.cpp \ + $$7ZIP_BASE/CPP/7zip/Common/UniqBlocks.cpp \ + $$7ZIP_BASE/CPP/7zip/Common/VirtThread.cpp diff --git a/src/libs/7zip/unix/CPP/7zip/Common/CreateCoder.cpp b/src/libs/7zip/unix/CPP/7zip/Common/CreateCoder.cpp index cc82a0db5..01ccbe12a 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/CreateCoder.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Common/CreateCoder.cpp @@ -13,12 +13,21 @@ static const unsigned int kNumCodecsMax = 64; unsigned int g_NumCodecs = 0; const CCodecInfo *g_Codecs[kNumCodecsMax]; -void RegisterCodec(const CCodecInfo *codecInfo) +void RegisterCodec(const CCodecInfo *codecInfo) throw() { if (g_NumCodecs < kNumCodecsMax) g_Codecs[g_NumCodecs++] = codecInfo; } +static const unsigned int kNumHashersMax = 16; +unsigned int g_NumHashers = 0; +const CHasherInfo *g_Hashers[kNumHashersMax]; +void RegisterHasher(const CHasherInfo *hashInfo) throw() +{ + if (g_NumHashers < kNumHashersMax) + g_Hashers[g_NumHashers++] = hashInfo; +} + #ifdef EXTERNAL_CODECS static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res) { @@ -46,56 +55,74 @@ static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, return S_OK; } -HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector &externalCodecs) +HRESULT CExternalCodecs::LoadCodecs() { - UInt32 num; - RINOK(codecsInfo->GetNumberOfMethods(&num)); - for (UInt32 i = 0; i < num; i++) + if (GetCodecs) { - CCodecInfoEx info; - NWindows::NCOM::CPropVariant prop; - RINOK(codecsInfo->GetProperty(i, NMethodPropID::kID, &prop)); - // if (prop.vt != VT_BSTR) - // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal); - // memmove(info.Id.ID, prop.bstrVal, info.Id.IDSize); - if (prop.vt != VT_UI8) + UInt32 num; + RINOK(GetCodecs->GetNumberOfMethods(&num)); + for (UInt32 i = 0; i < num; i++) { - continue; // old Interface - // return E_INVALIDARG; + CCodecInfoEx info; + NWindows::NCOM::CPropVariant prop; + RINOK(GetCodecs->GetProperty(i, NMethodPropID::kID, &prop)); + // if (prop.vt != VT_BSTR) + // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal); + // memcpy(info.Id.ID, prop.bstrVal, info.Id.IDSize); + if (prop.vt != VT_UI8) + continue; // old Interface + info.Id = prop.uhVal.QuadPart; + prop.Clear(); + + RINOK(GetCodecs->GetProperty(i, NMethodPropID::kName, &prop)); + if (prop.vt == VT_BSTR) + info.Name = prop.bstrVal; + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + + RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kInStreams, info.NumInStreams)); + RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kOutStreams, info.NumOutStreams)); + RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned)); + RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned)); + + Codecs.Add(info); + } + } + if (GetHashers) + { + UInt32 num = GetHashers->GetNumHashers(); + for (UInt32 i = 0; i < num; i++) + { + CHasherInfoEx info; + NWindows::NCOM::CPropVariant prop; + RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kID, &prop)); + if (prop.vt != VT_UI8) + continue; + info.Id = prop.uhVal.QuadPart; + prop.Clear(); + + RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kName, &prop)); + if (prop.vt == VT_BSTR) + info.Name = prop.bstrVal; + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + + Hashers.Add(info); } - info.Id = prop.uhVal.QuadPart; - prop.Clear(); - - RINOK(codecsInfo->GetProperty(i, NMethodPropID::kName, &prop)); - if (prop.vt == VT_BSTR) - info.Name = prop.bstrVal; - else if (prop.vt != VT_EMPTY) - return E_INVALIDARG;; - - RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kInStreams, info.NumInStreams)); - RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kOutStreams, info.NumOutStreams)); - RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned)); - RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned)); - - externalCodecs.Add(info); } return S_OK; } #endif -bool FindMethod( - #ifdef EXTERNAL_CODECS - ICompressCodecsInfo * /* codecsInfo */, const CObjectVector *externalCodecs, - #endif - const UString &name, - CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams) +bool FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS + const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams) { UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; - if (name.CompareNoCase(codec.Name) == 0) + if (name.IsEqualToNoCase(codec.Name)) { methodId = codec.Id; numInStreams = codec.NumInStreams; @@ -104,11 +131,11 @@ bool FindMethod( } } #ifdef EXTERNAL_CODECS - if (externalCodecs) - for (i = 0; i < (UInt32)externalCodecs->Size(); i++) + if (__externalCodecs) + for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++) { - const CCodecInfoEx &codec = (*externalCodecs)[i]; - if (codec.Name.CompareNoCase(name) == 0) + const CCodecInfoEx &codec = __externalCodecs->Codecs[i]; + if (codec.Name.IsEqualToNoCase(name)) { methodId = codec.Id; numInStreams = codec.NumInStreams; @@ -120,11 +147,8 @@ bool FindMethod( return false; } -bool FindMethod( - #ifdef EXTERNAL_CODECS - ICompressCodecsInfo * /* codecsInfo */, const CObjectVector *externalCodecs, - #endif - CMethodId methodId, UString &name) +bool FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, UString &name) { UInt32 i; for (i = 0; i < g_NumCodecs; i++) @@ -137,10 +161,10 @@ bool FindMethod( } } #ifdef EXTERNAL_CODECS - if (externalCodecs) - for (i = 0; i < (UInt32)externalCodecs->Size(); i++) + if (__externalCodecs) + for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++) { - const CCodecInfoEx &codec = (*externalCodecs)[i]; + const CCodecInfoEx &codec = __externalCodecs->Codecs[i]; if (methodId == codec.Id) { name = codec.Name; @@ -151,6 +175,49 @@ bool FindMethod( return false; } +bool FindHashMethod(DECL_EXTERNAL_CODECS_LOC_VARS + const UString &name, + CMethodId &methodId) +{ + UInt32 i; + for (i = 0; i < g_NumHashers; i++) + { + const CHasherInfo &codec = *g_Hashers[i]; + if (name.IsEqualToNoCase(codec.Name)) + { + methodId = codec.Id; + return true; + } + } + #ifdef EXTERNAL_CODECS + if (__externalCodecs) + for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++) + { + const CHasherInfoEx &codec = __externalCodecs->Hashers[i]; + if (codec.Name.IsEqualToNoCase(name)) + { + methodId = codec.Id; + return true; + } + } + #endif + return false; +} + +void GetHashMethods(DECL_EXTERNAL_CODECS_LOC_VARS + CRecordVector &methods) +{ + methods.ClearAndSetSize(g_NumHashers); + UInt32 i; + for (i = 0; i < g_NumHashers; i++) + methods[i] = (*g_Hashers[i]).Id; + #ifdef EXTERNAL_CODECS + if (__externalCodecs) + for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++) + methods.Add(__externalCodecs->Hashers[i].Id); + #endif +} + HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, @@ -159,7 +226,6 @@ HRESULT CreateCoder( CMyComPtr &coder2, bool encode, bool onlyCoder) { - bool created = false; UInt32 i; for (i = 0; i < g_NumCodecs; i++) { @@ -174,7 +240,6 @@ HRESULT CreateCoder( if (codec.IsFilter) filter = (ICompressFilter *)p; else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; else coder2 = (ICompressCoder2 *)p; - created = (p != 0); break; } } @@ -185,17 +250,16 @@ HRESULT CreateCoder( if (codec.IsFilter) filter = (ICompressFilter *)p; else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; else coder2 = (ICompressCoder2 *)p; - created = (p != 0); break; } } } #ifdef EXTERNAL_CODECS - if (!created && externalCodecs) - for (i = 0; i < (UInt32)externalCodecs->Size(); i++) + if (!filter && !coder && !coder2 && __externalCodecs) + for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++) { - const CCodecInfoEx &codec = (*externalCodecs)[i]; + const CCodecInfoEx &codec = __externalCodecs->Codecs[i]; if (codec.Id == methodId) { if (encode) @@ -204,17 +268,17 @@ HRESULT CreateCoder( { if (codec.IsSimpleCodec()) { - HRESULT result = codecsInfo->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder); + HRESULT result = __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder); if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) return result; if (!coder) { - RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter)); + RINOK(__externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter)); } } else { - RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2)); + RINOK(__externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2)); } break; } @@ -224,17 +288,17 @@ HRESULT CreateCoder( { if (codec.IsSimpleCodec()) { - HRESULT result = codecsInfo->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder); + HRESULT result = __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder); if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) return result; if (!coder) { - RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter)); + RINOK(__externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter)); } } else { - RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2)); + RINOK(__externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2)); } break; } @@ -291,3 +355,37 @@ HRESULT CreateFilter( methodId, filter, coder, coder2, encode, false); } + +HRESULT CreateHasher( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + UString &name, + CMyComPtr &hasher) +{ + UInt32 i; + for (i = 0; i < g_NumHashers; i++) + { + const CHasherInfo &codec = *g_Hashers[i]; + if (codec.Id == methodId) + { + hasher = (IHasher *)codec.CreateHasher(); + name = codec.Name; + break; + } + } + + #ifdef EXTERNAL_CODECS + if (!hasher && __externalCodecs) + for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++) + { + const CHasherInfoEx &codec = __externalCodecs->Hashers[i]; + if (codec.Id == methodId) + { + name = codec.Name; + return __externalCodecs->GetHashers->CreateHasher(i, &hasher); + } + } + #endif + + return S_OK; +} diff --git a/src/libs/7zip/unix/CPP/7zip/Common/CreateCoder.h b/src/libs/7zip/unix/CPP/7zip/Common/CreateCoder.h index bf0e96a38..fe1f6ccfe 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/CreateCoder.h +++ b/src/libs/7zip/unix/CPP/7zip/Common/CreateCoder.h @@ -19,27 +19,43 @@ struct CCodecInfoEx UInt32 NumOutStreams; bool EncoderIsAssigned; bool DecoderIsAssigned; + bool IsSimpleCodec() const { return NumOutStreams == 1 && NumInStreams == 1; } CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {} }; -HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector &externalCodecs); +struct CHasherInfoEx +{ + UString Name; + CMethodId Id; +}; #define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo, #define QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_ENTRY(ISetCompressCodecsInfo) #define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo); #define IMPL_ISetCompressCodecsInfo2(x) \ STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \ - COM_TRY_BEGIN _codecsInfo = compressCodecsInfo; return LoadExternalCodecs(_codecsInfo, _externalCodecs); COM_TRY_END } + COM_TRY_BEGIN __externalCodecs.GetCodecs = compressCodecsInfo; return __externalCodecs.LoadCodecs(); COM_TRY_END } #define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler) -#define EXTERNAL_CODECS_VARS2 _codecsInfo, &_externalCodecs +struct CExternalCodecs +{ + CMyComPtr GetCodecs; + CMyComPtr GetHashers; + + CObjectVector Codecs; + CObjectVector Hashers; + + HRESULT LoadCodecs(); +}; + +#define EXTERNAL_CODECS_VARS2 &__externalCodecs -#define DECL_EXTERNAL_CODECS_VARS CMyComPtr _codecsInfo; CObjectVector _externalCodecs; +#define DECL_EXTERNAL_CODECS_VARS CExternalCodecs __externalCodecs; #define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2, -#define DECL_EXTERNAL_CODECS_LOC_VARS2 ICompressCodecsInfo *codecsInfo, const CObjectVector *externalCodecs -#define EXTERNAL_CODECS_LOC_VARS2 codecsInfo, externalCodecs +#define DECL_EXTERNAL_CODECS_LOC_VARS2 const CExternalCodecs *__externalCodecs +#define EXTERNAL_CODECS_LOC_VARS2 __externalCodecs #define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2, #define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2, @@ -68,6 +84,13 @@ bool FindMethod( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, UString &name); +bool FindHashMethod( + DECL_EXTERNAL_CODECS_LOC_VARS + const UString &name, CMethodId &methodId); + +void GetHashMethods( + DECL_EXTERNAL_CODECS_LOC_VARS + CRecordVector &methods); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS @@ -95,4 +118,10 @@ HRESULT CreateFilter( CMyComPtr &filter, bool encode); +HRESULT CreateHasher( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + UString &name, + CMyComPtr &hacher); + #endif diff --git a/src/libs/7zip/unix/CPP/7zip/Common/FilePathAutoRename.cpp b/src/libs/7zip/unix/CPP/7zip/Common/FilePathAutoRename.cpp index 7d6e36f14..958360fac 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/FilePathAutoRename.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Common/FilePathAutoRename.cpp @@ -2,19 +2,19 @@ #include "StdAfx.h" -#include "Common/Defs.h" -#include "Common/IntToString.h" +#include "../../Common/Defs.h" +#include "../../Common/IntToString.h" -#include "Windows/FileFind.h" +#include "../../Windows/FileFind.h" #include "FilePathAutoRename.h" using namespace NWindows; -static bool MakeAutoName(const UString &name, - const UString &extension, unsigned value, UString &path) +static bool MakeAutoName(const FString &name, + const FString &extension, unsigned value, FString &path) { - wchar_t number[16]; + FChar number[16]; ConvertUInt32ToString(value, number); path = name; path += number; @@ -22,22 +22,22 @@ static bool MakeAutoName(const UString &name, return NFile::NFind::DoesFileOrDirExist(path); } -bool AutoRenamePath(UString &fullProcessedPath) +bool AutoRenamePath(FString &fullProcessedPath) { - UString path; - int dotPos = fullProcessedPath.ReverseFind(L'.'); + FString path; + int dotPos = fullProcessedPath.ReverseFind(FTEXT('.')); - int slashPos = fullProcessedPath.ReverseFind(L'/'); + int slashPos = fullProcessedPath.ReverseFind(FTEXT('/')); #ifdef _WIN32 - int slash1Pos = fullProcessedPath.ReverseFind(L'\\'); + int slash1Pos = fullProcessedPath.ReverseFind(FTEXT('\\')); slashPos = MyMax(slashPos, slash1Pos); #endif - UString name, extension; + FString name, extension; if (dotPos > slashPos && dotPos > 0) { - name = fullProcessedPath.Left(dotPos); - extension = fullProcessedPath.Mid(dotPos); + name.SetFrom(fullProcessedPath, dotPos); + extension = fullProcessedPath.Ptr(dotPos); } else name = fullProcessedPath; diff --git a/src/libs/7zip/unix/CPP/7zip/Common/FilePathAutoRename.h b/src/libs/7zip/unix/CPP/7zip/Common/FilePathAutoRename.h index 3ef87f482..7b576591c 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/FilePathAutoRename.h +++ b/src/libs/7zip/unix/CPP/7zip/Common/FilePathAutoRename.h @@ -1,10 +1,10 @@ -// Util/FilePathAutoRename.h +// FilePathAutoRename.h -#ifndef __FILEPATHAUTORENAME_H -#define __FILEPATHAUTORENAME_H +#ifndef __FILE_PATH_AUTO_RENAME_H +#define __FILE_PATH_AUTO_RENAME_H -#include "Common/MyString.h" +#include "../../Common/MyString.h" -bool AutoRenamePath(UString &fullProcessedPath); +bool AutoRenamePath(FString &fullProcessedPath); #endif diff --git a/src/libs/7zip/unix/CPP/7zip/Common/FileStreams.cpp b/src/libs/7zip/unix/CPP/7zip/Common/FileStreams.cpp index 76ab5ee29..ee1cc54e2 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/FileStreams.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Common/FileStreams.cpp @@ -8,6 +8,11 @@ #include #endif +#ifdef SUPPORT_DEVICE_FILE +#include "../../../C/Alloc.h" +#include "../../Common/Defs.h" +#endif + #include "FileStreams.h" static inline HRESULT ConvertBoolToHRESULT(bool result) @@ -24,86 +29,175 @@ static inline HRESULT ConvertBoolToHRESULT(bool result) #endif } -bool CInFileStream::Open(LPCTSTR fileName) -{ -#ifdef ENV_UNIX - return File.Open(fileName,_ignoreSymbolicLink); -#else - return File.Open(fileName); -#endif -} +#ifdef SUPPORT_DEVICE_FILE -#ifdef USE_WIN_FILE -#ifndef _UNICODE -bool CInFileStream::Open(LPCWSTR fileName) +static const UInt32 kClusterSize = 1 << 18; +CInFileStream::CInFileStream(): + VirtPos(0), + PhyPos(0), + Buf(0), + BufSize(0), + SupportHardLinks(false) { -#ifdef ENV_UNIX - return File.Open(fileName,_ignoreSymbolicLink); -#else - return File.Open(fileName); -#endif } -#endif -#endif -bool CInFileStream::OpenShared(LPCTSTR fileName, bool shareForWrite) -{ -#ifdef ENV_UNIX - return File.Open(fileName,_ignoreSymbolicLink); -#else - return File.OpenShared(fileName, shareForWrite); #endif -} -#ifdef USE_WIN_FILE -#ifndef _UNICODE -bool CInFileStream::OpenShared(LPCWSTR fileName, bool shareForWrite) +CInFileStream::~CInFileStream() { - return File.OpenShared(fileName, shareForWrite); + #ifdef SUPPORT_DEVICE_FILE + MidFree(Buf); + #endif } -#endif -#endif STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef USE_WIN_FILE - + + #ifdef SUPPORT_DEVICE_FILE + if (processedSize) + *processedSize = 0; + if (size == 0) + return S_OK; + if (File.IsDeviceFile) + { + if (File.SizeDefined) + { + if (VirtPos >= File.Size) + return VirtPos == File.Size ? S_OK : E_FAIL; + UInt64 rem = File.Size - VirtPos; + if (size > rem) + size = (UInt32)rem; + } + for (;;) + { + const UInt32 mask = kClusterSize - 1; + const UInt64 mask2 = ~(UInt64)mask; + UInt64 alignedPos = VirtPos & mask2; + if (BufSize > 0 && BufStartPos == alignedPos) + { + UInt32 pos = (UInt32)VirtPos & mask; + if (pos >= BufSize) + return S_OK; + UInt32 rem = MyMin(BufSize - pos, size); + memcpy(data, Buf + pos, rem); + VirtPos += rem; + if (processedSize) + *processedSize += rem; + return S_OK; + } + + bool useBuf = false; + if ((VirtPos & mask) != 0 || ((ptrdiff_t)data & mask) != 0 ) + useBuf = true; + else + { + UInt64 end = VirtPos + size; + if ((end & mask) != 0) + { + end &= mask2; + if (end <= VirtPos) + useBuf = true; + else + size = (UInt32)(end - VirtPos); + } + } + if (!useBuf) + break; + if (alignedPos != PhyPos) + { + UInt64 realNewPosition; + bool result = File.Seek(alignedPos, FILE_BEGIN, realNewPosition); + if (!result) + return ConvertBoolToHRESULT(result); + PhyPos = realNewPosition; + } + + BufStartPos = alignedPos; + UInt32 readSize = kClusterSize; + if (File.SizeDefined) + readSize = (UInt32)MyMin(File.Size - PhyPos, (UInt64)kClusterSize); + + if (!Buf) + { + Buf = (Byte *)MidAlloc(kClusterSize); + if (!Buf) + return E_OUTOFMEMORY; + } + bool result = File.Read1(Buf, readSize, BufSize); + if (!result) + return ConvertBoolToHRESULT(result); + + if (BufSize == 0) + return S_OK; + PhyPos += BufSize; + } + + if (VirtPos != PhyPos) + { + UInt64 realNewPosition; + bool result = File.Seek(VirtPos, FILE_BEGIN, realNewPosition); + if (!result) + return ConvertBoolToHRESULT(result); + PhyPos = VirtPos = realNewPosition; + } + } + #endif + UInt32 realProcessedSize; bool result = File.ReadPart(data, size, realProcessedSize); - if(processedSize != NULL) + if (processedSize) *processedSize = realProcessedSize; + #ifdef SUPPORT_DEVICE_FILE + VirtPos += realProcessedSize; + PhyPos += realProcessedSize; + #endif return ConvertBoolToHRESULT(result); - + #else - - if(processedSize != NULL) + + if (processedSize) *processedSize = 0; ssize_t res = File.Read(data, (size_t)size); if (res == -1) return E_FAIL; - if(processedSize != NULL) + if (processedSize) *processedSize = (UInt32)res; return S_OK; #endif } -#ifndef _WIN32_WCE +#ifdef UNDER_CE +STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + size_t s2 = fread(data, 1, size, stdin); + int error = ferror(stdin); + if (processedSize) + *processedSize = s2; + if (s2 <= size && error == 0) + return S_OK; + return E_FAIL; +} +#else STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 - UInt32 realProcessedSize; - BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), - data, size, (DWORD *)&realProcessedSize, NULL); - if(processedSize != NULL) + + DWORD realProcessedSize; + UInt32 sizeTemp = (1 << 20); + if (sizeTemp > size) + sizeTemp = size; + BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, sizeTemp, &realProcessedSize, NULL); + if (processedSize) *processedSize = realProcessedSize; if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE) return S_OK; return ConvertBoolToHRESULT(res != FALSE); - + #else - if(processedSize != NULL) + if (processedSize) *processedSize = 0; ssize_t res; do @@ -113,38 +207,61 @@ STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSi while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; - if(processedSize != NULL) + if (processedSize) *processedSize = (UInt32)res; return S_OK; - + #endif } - + #endif -STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, - UInt64 *newPosition) +STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - if(seekOrigin >= 3) + if (seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef USE_WIN_FILE + #ifdef SUPPORT_DEVICE_FILE + if (File.IsDeviceFile && (File.SizeDefined || seekOrigin != STREAM_SEEK_END)) + { + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += VirtPos; break; + case STREAM_SEEK_END: offset += File.Size; break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + VirtPos = offset; + if (newPosition) + *newPosition = offset; + return S_OK; + } + #endif + UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); - if(newPosition != NULL) + + #ifdef SUPPORT_DEVICE_FILE + PhyPos = VirtPos = realNewPosition; + #endif + + if (newPosition) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); - + #else - - off_t res = File.Seek(offset, seekOrigin); + + off_t res = File.Seek((off_t)offset, seekOrigin); if (res == -1) return E_FAIL; - if(newPosition != NULL) + if (newPosition) *newPosition = (UInt64)res; return S_OK; - + #endif } @@ -153,6 +270,43 @@ STDMETHODIMP CInFileStream::GetSize(UInt64 *size) return ConvertBoolToHRESULT(File.GetLength(*size)); } +#if 0 // FIXME #ifdef USE_WIN_FILE + +STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib) +{ + BY_HANDLE_FILE_INFORMATION info; + if (File.GetFileInformation(&info)) + { + if (size) *size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; + if (cTime) *cTime = info.ftCreationTime; + if (aTime) *aTime = info.ftLastAccessTime; + if (mTime) *mTime = info.ftLastWriteTime; + if (attrib) *attrib = info.dwFileAttributes; + return S_OK; + } + return GetLastError(); +} + +STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) +{ + BY_HANDLE_FILE_INFORMATION info; + if (File.GetFileInformation(&info)) + { + props->Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; + props->VolID = info.dwVolumeSerialNumber; + props->FileID_Low = (((UInt64)info.nFileIndexHigh) << 32) + info.nFileIndexLow; + props->FileID_High = 0; + props->NumLinks = SupportHardLinks ? info.nNumberOfLinks : 1; + props->Attrib = info.dwFileAttributes; + props->CTime = info.ftCreationTime; + props->ATime = info.ftLastAccessTime; + props->MTime = info.ftLastWriteTime; + return S_OK; + } + return GetLastError(); +} + +#endif ////////////////////////// // COutFileStream @@ -169,46 +323,46 @@ STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *proces UInt32 realProcessedSize; bool result = File.WritePart(data, size, realProcessedSize); ProcessedSize += realProcessedSize; - if(processedSize != NULL) + if (processedSize) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); - + #else - - if(processedSize != NULL) + + if (processedSize) *processedSize = 0; ssize_t res = File.Write(data, (size_t)size); if (res == -1) return E_FAIL; - if(processedSize != NULL) + if (processedSize) *processedSize = (UInt32)res; ProcessedSize += res; return S_OK; - + #endif } - + STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - if(seekOrigin >= 3) + if (seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef USE_WIN_FILE UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); - if(newPosition != NULL) + if (newPosition) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); - + #else - - off_t res = File.Seek(offset, seekOrigin); + + off_t res = File.Seek((off_t)offset, seekOrigin); if (res == -1) return E_FAIL; - if(newPosition != NULL) + if (newPosition) *newPosition = (UInt64)res; return S_OK; - + #endif } @@ -216,7 +370,7 @@ STDMETHODIMP COutFileStream::SetSize(UInt64 newSize) { #ifdef USE_WIN_FILE UInt64 currentPos; - if(!File.Seek(0, FILE_CURRENT, currentPos)) + if (!File.Seek(0, FILE_CURRENT, currentPos)) return E_FAIL; bool result = File.SetLength(newSize); UInt64 currentPos2; @@ -227,10 +381,18 @@ STDMETHODIMP COutFileStream::SetSize(UInt64 newSize) #endif } -#ifndef _WIN32_WCE +#ifdef UNDER_CE +STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + size_t s2 = fwrite(data, 1, size, stdout); + if (processedSize) + *processedSize = s2; + return (s2 == size) ? S_OK : E_FAIL; +} +#else STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { - if(processedSize != NULL) + if (processedSize) *processedSize = 0; #ifdef _WIN32 @@ -247,13 +409,13 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro data, sizeTemp, (DWORD *)&realProcessedSize, NULL); size -= realProcessedSize; data = (const void *)((const Byte *)data + realProcessedSize); - if(processedSize != NULL) + if (processedSize) *processedSize += realProcessedSize; } return ConvertBoolToHRESULT(res != FALSE); #else - + ssize_t res; do { @@ -262,12 +424,12 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; - if(processedSize != NULL) + if (processedSize) *processedSize = (UInt32)res; return S_OK; - + return S_OK; #endif } - + #endif diff --git a/src/libs/7zip/unix/CPP/7zip/Common/FileStreams.h b/src/libs/7zip/unix/CPP/7zip/Common/FileStreams.h index f70905b56..a80cbad4d 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/FileStreams.h +++ b/src/libs/7zip/unix/CPP/7zip/Common/FileStreams.h @@ -1,12 +1,14 @@ // FileStreams.h -#ifndef __FILESTREAMS_H -#define __FILESTREAMS_H +#ifndef __FILE_STREAMS_H +#define __FILE_STREAMS_H #if defined(_WIN32) || defined(ENV_UNIX) #define USE_WIN_FILE #endif +#include "../../Common/MyString.h" + #ifdef USE_WIN_FILE #include "../../Windows/FileIO.h" #else @@ -14,43 +16,67 @@ #endif #include "../../Common/MyCom.h" + #include "../IStream.h" class CInFileStream: public IInStream, public IStreamGetSize, + #if 0 // #ifdef USE_WIN_FILE + public IStreamGetProps, + public IStreamGetProps2, + #endif public CMyUnknownImp { bool _ignoreSymbolicLink; public: #ifdef USE_WIN_FILE NWindows::NFile::NIO::CInFile File; + + #ifdef SUPPORT_DEVICE_FILE + UInt64 VirtPos; + UInt64 PhyPos; + UInt64 BufStartPos; + Byte *Buf; + UInt32 BufSize; + #endif + #else NC::NFile::NIO::CInFile File; #endif + + bool SupportHardLinks; + CInFileStream(bool b=false) { _ignoreSymbolicLink = b; } - virtual ~CInFileStream() {} + virtual ~CInFileStream(); - bool Open(LPCTSTR fileName); - #ifdef USE_WIN_FILE - #ifndef _UNICODE - bool Open(LPCWSTR fileName); - #endif - #endif + bool Open(CFSTR fileName) + { + return File.Open(fileName,_ignoreSymbolicLink); + } - bool OpenShared(LPCTSTR fileName, bool shareForWrite); - #ifdef USE_WIN_FILE - #ifndef _UNICODE - bool OpenShared(LPCWSTR fileName, bool shareForWrite); - #endif - #endif + bool OpenShared(CFSTR fileName , bool /* shareForWrite */ ) + { + return File.Open(fileName,_ignoreSymbolicLink); + } - MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) + MY_QUERYINTERFACE_BEGIN2(IInStream) + MY_QUERYINTERFACE_ENTRY(IStreamGetSize) + #if 0 // #ifdef USE_WIN_FILE + MY_QUERYINTERFACE_ENTRY(IStreamGetProps) + MY_QUERYINTERFACE_ENTRY(IStreamGetProps2) + #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(GetSize)(UInt64 *size); + #if 0 // #ifdef USE_WIN_FILE + STDMETHOD(GetProps)(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib); + STDMETHOD(GetProps2)(CStreamFileProps *props); + #endif }; class CStdInFileStream: @@ -68,40 +94,26 @@ class COutFileStream: public IOutStream, public CMyUnknownImp { +public: #ifdef USE_WIN_FILE NWindows::NFile::NIO::COutFile File; #else NC::NFile::NIO::COutFile File; #endif -public: virtual ~COutFileStream() {} - bool Create(LPCTSTR fileName, bool createAlways) + bool Create(CFSTR fileName, bool createAlways) { ProcessedSize = 0; return File.Create(fileName, createAlways); } - bool Open(LPCTSTR fileName, DWORD creationDisposition) + bool Open(CFSTR fileName, DWORD creationDisposition) { ProcessedSize = 0; return File.Open(fileName, creationDisposition); } - #ifdef USE_WIN_FILE - #ifndef _UNICODE - bool Create(LPCWSTR fileName, bool createAlways) - { - ProcessedSize = 0; - return File.Create(fileName, createAlways); - } - bool Open(LPCWSTR fileName, DWORD creationDisposition) - { - ProcessedSize = 0; - return File.Open(fileName, creationDisposition); - } - #endif - #endif HRESULT Close(); - + UInt64 ProcessedSize; #ifdef USE_WIN_FILE diff --git a/src/libs/7zip/unix/CPP/7zip/Common/FilterCoder.cpp b/src/libs/7zip/unix/CPP/7zip/Common/FilterCoder.cpp index 696735278..3a2023b35 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/FilterCoder.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Common/FilterCoder.cpp @@ -48,10 +48,10 @@ STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStr while (!_outSizeIsDefined || _nowPos64 < _outSize) { size_t processedSize = kBufferSize - bufferPos; - + // Change it: It can be optimized using ReadPart RINOK(ReadStream(inStream, _buffer + bufferPos, &processedSize)); - + UInt32 endPos = bufferPos + (UInt32)processedSize; bufferPos = Filter->Filter(_buffer, endPos); @@ -153,10 +153,16 @@ STDMETHODIMP CFilterCoder::Flush() } -STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream) +void CFilterCoder::SetInStream_NoSubFilterInit(ISequentialInStream *inStream) { _convertedPosBegin = _convertedPosEnd = _bufferPos = 0; _inStream = inStream; + Init2(); +} + +STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream) +{ + SetInStream_NoSubFilterInit(inStream); return Init(); } @@ -210,10 +216,22 @@ STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize) } #ifndef _NO_CRYPTO + STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size) { return _setPassword->CryptoSetPassword(data, size); } + +STDMETHODIMP CFilterCoder::SetKey(const Byte *data, UInt32 size) +{ + return _cryptoProperties->SetKey(data, size); +} + +STDMETHODIMP CFilterCoder::SetInitVector(const Byte *data, UInt32 size) +{ + return _cryptoProperties->SetInitVector(data, size); +} + #endif #ifndef EXTRACT_ONLY diff --git a/src/libs/7zip/unix/CPP/7zip/Common/FilterCoder.h b/src/libs/7zip/unix/CPP/7zip/Common/FilterCoder.h index 8132a6dd7..2b8f142f5 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/FilterCoder.h +++ b/src/libs/7zip/unix/CPP/7zip/Common/FilterCoder.h @@ -7,9 +7,9 @@ #include "../ICoder.h" #include "../IPassword.h" -#define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) if (iid == IID_ ## i) \ -{ if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \ -*outObject = (void *)(i *)this; AddRef(); return S_OK; } +#define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) else if (iid == IID_ ## i) \ + { if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \ + *outObject = (void *)(i *)this; } class CFilterCoder: public ICompressCoder, @@ -21,6 +21,7 @@ class CFilterCoder: #ifndef _NO_CRYPTO public ICryptoSetPassword, + public ICryptoProperties, #endif #ifndef EXTRACT_ONLY public ICompressSetCoderProperties, @@ -42,14 +43,20 @@ protected: UInt64 _outSize; UInt64 _nowPos64; - HRESULT Init() + void Init2() { _nowPos64 = 0; _outSizeIsDefined = false; + } + + HRESULT Init() + { + Init2(); return Filter->Init(); } CMyComPtr _setPassword; + CMyComPtr _cryptoProperties; #ifndef EXTRACT_ONLY CMyComPtr _SetCoderProperties; CMyComPtr _writeCoderProperties; @@ -74,6 +81,7 @@ public: #ifndef _NO_CRYPTO MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword) + MY_QUERYINTERFACE_ENTRY_AG(ICryptoProperties, Filter, _cryptoProperties) #endif #ifndef EXTRACT_ONLY @@ -98,6 +106,9 @@ public: #ifndef _NO_CRYPTO STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); + + STDMETHOD(SetKey)(const Byte *data, UInt32 size); + STDMETHOD(SetInitVector)(const Byte *data, UInt32 size); #endif #ifndef EXTRACT_ONLY STDMETHOD(SetCoderProperties)(const PROPID *propIDs, @@ -107,6 +118,9 @@ public: STDMETHOD(ResetInitVector)(); #endif STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + + void SetInStream_NoSubFilterInit(ISequentialInStream *inStream); + }; class CInStreamReleaser diff --git a/src/libs/7zip/unix/CPP/7zip/Common/InBuffer.cpp b/src/libs/7zip/unix/CPP/7zip/Common/InBuffer.cpp index ad4f8825e..133d95b38 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/InBuffer.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Common/InBuffer.cpp @@ -6,50 +6,49 @@ #include "InBuffer.h" -CInBuffer::CInBuffer(): - _buffer(0), - _bufferLimit(0), - _bufferBase(0), +CInBufferBase::CInBufferBase() throw(): + _buf(0), + _bufLim(0), + _bufBase(0), _stream(0), - _bufferSize(0) + _processedSize(0), + _bufSize(0), + _wasFinished(false), + NumExtraBytes(0) {} -bool CInBuffer::Create(UInt32 bufferSize) +bool CInBuffer::Create(size_t bufSize) throw() { - const UInt32 kMinBlockSize = 1; - if (bufferSize < kMinBlockSize) - bufferSize = kMinBlockSize; - if (_bufferBase != 0 && _bufferSize == bufferSize) + const unsigned kMinBlockSize = 1; + if (bufSize < kMinBlockSize) + bufSize = kMinBlockSize; + if (_bufBase != 0 && _bufSize == bufSize) return true; Free(); - _bufferSize = bufferSize; - _bufferBase = (Byte *)::MidAlloc(bufferSize); - return (_bufferBase != 0); + _bufSize = bufSize; + _bufBase = (Byte *)::MidAlloc(bufSize); + return (_bufBase != 0); } -void CInBuffer::Free() +void CInBuffer::Free() throw() { - ::MidFree(_bufferBase); - _bufferBase = 0; + ::MidFree(_bufBase); + _bufBase = 0; } -void CInBuffer::SetStream(ISequentialInStream *stream) -{ - _stream = stream; -} - -void CInBuffer::Init() +void CInBufferBase::Init() throw() { _processedSize = 0; - _buffer = _bufferBase; - _bufferLimit = _buffer; + _buf = _bufBase; + _bufLim = _buf; _wasFinished = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif + NumExtraBytes = 0; } -bool CInBuffer::ReadBlock() +bool CInBufferBase::ReadBlock() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) @@ -57,27 +56,80 @@ bool CInBuffer::ReadBlock() #endif if (_wasFinished) return false; - _processedSize += (_buffer - _bufferBase); - UInt32 numProcessedBytes; - HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes); + _processedSize += (_buf - _bufBase); + _buf = _bufBase; + _bufLim = _bufBase; + UInt32 processed; + // FIX_ME: we can improve it to support (_bufSize >= (1 << 32)) + HRESULT result = _stream->Read(_bufBase, (UInt32)_bufSize, &processed); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw CInBufferException(result); #endif - _buffer = _bufferBase; - _bufferLimit = _buffer + numProcessedBytes; - _wasFinished = (numProcessedBytes == 0); - return (!_wasFinished); + _bufLim = _buf + processed; + _wasFinished = (processed == 0); + return !_wasFinished; } -Byte CInBuffer::ReadBlock2() +bool CInBufferBase::ReadByte_FromNewBlock(Byte &b) { if (!ReadBlock()) { - _processedSize++; + NumExtraBytes++; + b = 0xFF; + return false; + } + b = *_buf++; + return true; +} + +Byte CInBufferBase::ReadByte_FromNewBlock() +{ + if (!ReadBlock()) + { + NumExtraBytes++; return 0xFF; } - return *_buffer++; + return *_buf++; +} + +size_t CInBufferBase::ReadBytes(Byte *buf, size_t size) +{ + if ((size_t)(_bufLim - _buf) >= size) + { + const Byte *src = _buf; + for (size_t i = 0; i < size; i++) + buf[i] = src[i]; + _buf += size; + return size; + } + for (size_t i = 0; i < size; i++) + { + if (_buf >= _bufLim) + if (!ReadBlock()) + return i; + buf[i] = *_buf++; + } + return size; +} + +size_t CInBufferBase::Skip(size_t size) +{ + size_t processed = 0; + for (;;) + { + size_t rem = (_bufLim - _buf); + if (rem >= size) + { + _buf += size; + return processed + size; + } + _buf += rem; + processed += rem; + size -= rem; + if (!ReadBlock()) + return processed; + } } diff --git a/src/libs/7zip/unix/CPP/7zip/Common/InBuffer.h b/src/libs/7zip/unix/CPP/7zip/Common/InBuffer.h index 75625bfd9..dd3c66808 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/InBuffer.h +++ b/src/libs/7zip/unix/CPP/7zip/Common/InBuffer.h @@ -1,11 +1,10 @@ // InBuffer.h -#ifndef __INBUFFER_H -#define __INBUFFER_H +#ifndef __IN_BUFFER_H +#define __IN_BUFFER_H -#include "../IStream.h" -#include "../../Common/MyCom.h" #include "../../Common/MyException.h" +#include "../IStream.h" #ifndef _NO_EXCEPTIONS struct CInBufferException: public CSystemException @@ -14,68 +13,78 @@ struct CInBufferException: public CSystemException }; #endif -class CInBuffer +class CInBufferBase { - Byte *_buffer; - Byte *_bufferLimit; - Byte *_bufferBase; - CMyComPtr _stream; +protected: + Byte *_buf; + Byte *_bufLim; + Byte *_bufBase; + + ISequentialInStream *_stream; UInt64 _processedSize; - UInt32 _bufferSize; + size_t _bufSize; // actually it's number of Bytes for next read. The buf can be larger + // only up to 32-bits values now are supported! bool _wasFinished; bool ReadBlock(); - Byte ReadBlock2(); + bool ReadByte_FromNewBlock(Byte &b); + Byte ReadByte_FromNewBlock(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif + UInt32 NumExtraBytes; - CInBuffer(); - ~CInBuffer() { Free(); } + CInBufferBase() throw(); + + UInt64 GetStreamSize() const { return _processedSize + (_buf - _bufBase); } + UInt64 GetProcessedSize() const { return _processedSize + NumExtraBytes + (_buf - _bufBase); } + bool WasFinished() const { return _wasFinished; } + + void SetStream(ISequentialInStream *stream) { _stream = stream; } + + void SetBuf(Byte *buf, size_t bufSize, size_t end, size_t pos) + { + _bufBase = buf; + _bufSize = bufSize; + _processedSize = 0; + _buf = buf + pos; + _bufLim = buf + end; + _wasFinished = false; + #ifdef _NO_EXCEPTIONS + ErrorCode = S_OK; + #endif + NumExtraBytes = 0; + } - bool Create(UInt32 bufferSize); - void Free(); - - void SetStream(ISequentialInStream *stream); - void Init(); - void ReleaseStream() { _stream.Release(); } + void Init() throw(); bool ReadByte(Byte &b) { - if (_buffer >= _bufferLimit) - if (!ReadBlock()) - return false; - b = *_buffer++; + if (_buf >= _bufLim) + return ReadByte_FromNewBlock(b); + b = *_buf++; return true; } + Byte ReadByte() { - if (_buffer >= _bufferLimit) - return ReadBlock2(); - return *_buffer++; - } - UInt32 ReadBytes(Byte *buf, UInt32 size) - { - if ((UInt32)(_bufferLimit - _buffer) >= size) - { - for (UInt32 i = 0; i < size; i++) - buf[i] = _buffer[i]; - _buffer += size; - return size; - } - for (UInt32 i = 0; i < size; i++) - { - if (_buffer >= _bufferLimit) - if (!ReadBlock()) - return i; - buf[i] = *_buffer++; - } - return size; + if (_buf >= _bufLim) + return ReadByte_FromNewBlock(); + return *_buf++; } - UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); } - bool WasFinished() const { return _wasFinished; } + + size_t ReadBytes(Byte *buf, size_t size); + size_t Skip(size_t size); +}; + +class CInBuffer: public CInBufferBase +{ +public: + ~CInBuffer() { Free(); } + bool Create(size_t bufSize) throw(); // only up to 32-bits values now are supported! + void Free() throw(); }; #endif diff --git a/src/libs/7zip/unix/CPP/7zip/Common/InOutTempBuffer.cpp b/src/libs/7zip/unix/CPP/7zip/Common/InOutTempBuffer.cpp index dfe8b3d32..be65ba32f 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/InOutTempBuffer.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Common/InOutTempBuffer.cpp @@ -4,16 +4,18 @@ #include "../../../C/7zCrc.h" +#include "../../Common/Defs.h" + #include "InOutTempBuffer.h" #include "StreamUtils.h" using namespace NWindows; using namespace NFile; -using namespace NDirectory; +using namespace NDir; static const UInt32 kTempBufSize = (1 << 20); -static LPCTSTR kTempFilePrefixString = TEXT("7zt"); +static CFSTR kTempFilePrefixString = FTEXT("7zt"); CInOutTempBuffer::CInOutTempBuffer(): _buf(NULL) { } @@ -42,12 +44,7 @@ bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size) return true; if (!_tempFileCreated) { - CSysString tempDirPath; - if (!MyGetTempPath(tempDirPath)) - return false; - if (_tempFile.Create(tempDirPath, kTempFilePrefixString, _tempFileName) == 0) - return false; - if (!_outFile.Create(_tempFileName, true)) + if (!_tempFile.CreateRandomInTempFolder(kTempFilePrefixString, &_outFile)) return false; _tempFileCreated = true; } @@ -91,7 +88,7 @@ HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) if (_tempFileCreated) { NIO::CInFile inFile; - if (!inFile.Open(_tempFileName)) + if (!inFile.Open(_tempFile.GetPath())) return E_FAIL; while (size < _size) { diff --git a/src/libs/7zip/unix/CPP/7zip/Common/InOutTempBuffer.h b/src/libs/7zip/unix/CPP/7zip/Common/InOutTempBuffer.h index 073f95acf..256d72420 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/InOutTempBuffer.h +++ b/src/libs/7zip/unix/CPP/7zip/Common/InOutTempBuffer.h @@ -5,17 +5,15 @@ #include "../../Common/MyCom.h" #include "../../Windows/FileDir.h" -#include "../../Windows/FileIO.h" #include "../IStream.h" class CInOutTempBuffer { - NWindows::NFile::NDirectory::CTempFile _tempFile; + NWindows::NFile::NDir::CTempFile _tempFile; NWindows::NFile::NIO::COutFile _outFile; Byte *_buf; UInt32 _bufPos; - CSysString _tempFileName; bool _tempFileCreated; UInt64 _size; UInt32 _crc; diff --git a/src/libs/7zip/unix/CPP/7zip/Common/LimitedStreams.cpp b/src/libs/7zip/unix/CPP/7zip/Common/LimitedStreams.cpp index 1837e3201..5f20dcda4 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/LimitedStreams.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Common/LimitedStreams.cpp @@ -17,17 +17,21 @@ STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *p if (realProcessedSize == 0) _wasFinished = true; } - if (processedSize != NULL) + if (processedSize) *processedSize = realProcessedSize; return result; } STDMETHODIMP CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { - if (processedSize != NULL) + if (processedSize) *processedSize = 0; if (_virtPos >= _size) - return (_virtPos == _size) ? S_OK: E_FAIL; + { + // 9.31: Fixed. Windows doesn't return error in ReadFile and IStream->Read in that case. + return S_OK; + // return (_virtPos == _size) ? S_OK: E_FAIL; // ERROR_HANDLE_EOF + } UInt64 rem = _size - _virtPos; if (rem < size) size = (UInt32)rem; @@ -38,7 +42,7 @@ STDMETHODIMP CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSi RINOK(SeekToPhys()); } HRESULT res = _stream->Read(data, size, &size); - if (processedSize != NULL) + if (processedSize) *processedSize = size; _physPos += size; _virtPos += size; @@ -47,24 +51,39 @@ STDMETHODIMP CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSi STDMETHODIMP CLimitedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - switch(seekOrigin) + switch (seekOrigin) { - case STREAM_SEEK_SET: _virtPos = offset; break; - case STREAM_SEEK_CUR: _virtPos += offset; break; - case STREAM_SEEK_END: _virtPos = _size + offset; break; + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += _size; break; default: return STG_E_INVALIDFUNCTION; } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = offset; if (newPosition) *newPosition = _virtPos; return S_OK; } +HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream) +{ + *resStream = 0; + CLimitedInStream *streamSpec = new CLimitedInStream; + CMyComPtr streamTemp = streamSpec; + streamSpec->SetStream(inStream); + RINOK(streamSpec->InitAndSeek(pos, size)); + streamSpec->SeekToStart(); + *resStream = streamTemp.Detach(); + return S_OK; +} + STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { - if (processedSize != NULL) + if (processedSize) *processedSize = 0; if (_virtPos >= Size) - return (_virtPos == Size) ? S_OK: E_FAIL; + return S_OK; if (_curRem == 0) { @@ -88,49 +107,98 @@ STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSi if (size > _curRem) size = _curRem; HRESULT res = Stream->Read(data, size, &size); - if (processedSize != NULL) + if (processedSize) *processedSize = size; _physPos += size; _virtPos += size; _curRem -= size; return res; } - + STDMETHODIMP CClusterInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - UInt64 newVirtPos = offset; - switch(seekOrigin) + switch (seekOrigin) { case STREAM_SEEK_SET: break; - case STREAM_SEEK_CUR: newVirtPos += _virtPos; break; - case STREAM_SEEK_END: newVirtPos += Size; break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += Size; break; default: return STG_E_INVALIDFUNCTION; } - if (_virtPos != newVirtPos) + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + if (_virtPos != (UInt64)offset) _curRem = 0; - _virtPos = newVirtPos; + _virtPos = offset; if (newPosition) - *newPosition = newVirtPos; + *newPosition = offset; return S_OK; } -HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream) +STDMETHODIMP CExtentsStream::Read(void *data, UInt32 size, UInt32 *processedSize) { - *resStream = 0; - CLimitedInStream *streamSpec = new CLimitedInStream; - CMyComPtr streamTemp = streamSpec; - streamSpec->SetStream(inStream); - RINOK(streamSpec->InitAndSeek(pos, size)); - streamSpec->SeekToStart(); - *resStream = streamTemp.Detach(); + if (processedSize) + *processedSize = 0; + if (_virtPos >= Extents.Back().Virt) + return S_OK; + if (size == 0) + return S_OK; + + unsigned left = 0, right = Extents.Size() - 1; + for (;;) + { + unsigned mid = (left + right) / 2; + if (mid == left) + break; + if (_virtPos < Extents[mid].Virt) + right = mid; + else + left = mid; + } + + const CSeekExtent &extent = Extents[left]; + UInt64 phyPos = extent.Phy + (_virtPos - extent.Virt); + if (_needStartSeek || _phyPos != phyPos) + { + _needStartSeek = false; + _phyPos = phyPos; + RINOK(SeekToPhys()); + } + + UInt64 rem = Extents[left + 1].Virt - _virtPos; + if (size > rem) + size = (UInt32)rem; + + HRESULT res = Stream->Read(data, size, &size); + _phyPos += size; + _virtPos += size; + if (processedSize) + *processedSize = size; + return res; +} + +STDMETHODIMP CExtentsStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += Extents.Back().Virt; break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = offset; + if (newPosition) + *newPosition = _virtPos; return S_OK; } + STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { HRESULT result = S_OK; - if (processedSize != NULL) + if (processedSize) *processedSize = 0; if (size > _size) { @@ -139,7 +207,7 @@ STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, U _overflow = true; if (!_overflowIsAllowed) return E_FAIL; - if (processedSize != NULL) + if (processedSize) *processedSize = size; return S_OK; } @@ -148,7 +216,134 @@ STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, U if (_stream) result = _stream->Write(data, size, &size); _size -= size; - if (processedSize != NULL) + if (processedSize) *processedSize = size; return result; } + + +STDMETHODIMP CTailInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 cur; + HRESULT res = Stream->Read(data, size, &cur); + if (processedSize) + *processedSize = cur; + _virtPos += cur; + return res; +} + +STDMETHODIMP CTailInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: + { + UInt64 pos = 0; + RINOK(Stream->Seek(offset, STREAM_SEEK_END, &pos)); + if (pos < Offset) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = pos - Offset; + if (newPosition) + *newPosition = _virtPos; + return S_OK; + } + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = offset; + if (newPosition) + *newPosition = _virtPos; + return Stream->Seek(Offset + _virtPos, STREAM_SEEK_SET, NULL); +} + +STDMETHODIMP CLimitedCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (_virtPos >= _size) + { + // 9.31: Fixed. Windows doesn't return error in ReadFile and IStream->Read in that case. + return S_OK; + // return (_virtPos == _size) ? S_OK: E_FAIL; // ERROR_HANDLE_EOF + } + UInt64 rem = _size - _virtPos; + if (rem < size) + size = (UInt32)rem; + + UInt64 newPos = _startOffset + _virtPos; + UInt64 offsetInCache = newPos - _cachePhyPos; + HRESULT res = S_OK; + if (newPos >= _cachePhyPos && + offsetInCache <= _cacheSize && + size <= _cacheSize - (size_t)offsetInCache) + memcpy(data, _cache + (size_t)offsetInCache, size); + else + { + if (newPos != _physPos) + { + _physPos = newPos; + RINOK(SeekToPhys()); + } + res = _stream->Read(data, size, &size); + _physPos += size; + } + if (processedSize) + *processedSize = size; + _virtPos += size; + return res; +} + +STDMETHODIMP CLimitedCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += _size; break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = offset; + if (newPosition) + *newPosition = _virtPos; + return S_OK; +} + +STDMETHODIMP CTailOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 cur; + HRESULT res = Stream->Write(data, size, &cur); + if (processedSize) + *processedSize = cur; + _virtPos += cur; + if (_virtSize < _virtPos) + _virtSize = _virtPos; + return res; +} + +STDMETHODIMP CTailOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += _virtSize; break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = offset; + if (newPosition) + *newPosition = _virtPos; + return Stream->Seek(Offset + _virtPos, STREAM_SEEK_SET, NULL); +} + +STDMETHODIMP CTailOutStream::SetSize(UInt64 newSize) +{ + _virtSize = newSize; + return Stream->SetSize(Offset + newSize); +} diff --git a/src/libs/7zip/unix/CPP/7zip/Common/LimitedStreams.h b/src/libs/7zip/unix/CPP/7zip/Common/LimitedStreams.h index 2cbe18e48..b14616f3b 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/LimitedStreams.h +++ b/src/libs/7zip/unix/CPP/7zip/Common/LimitedStreams.h @@ -3,6 +3,7 @@ #ifndef __LIMITED_STREAMS_H #define __LIMITED_STREAMS_H +#include "../../Common/MyBuffer.h" #include "../../Common/MyCom.h" #include "../../Common/MyVector.h" #include "../IStream.h" @@ -24,8 +25,8 @@ public: _pos = 0; _wasFinished = false; } - - MY_UNKNOWN_IMP + + MY_UNKNOWN_IMP1(ISequentialInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); UInt64 GetSize() const { return _pos; } @@ -53,8 +54,8 @@ public: _size = size; return SeekToPhys(); } - - MY_UNKNOWN_IMP1(IInStream) + + MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); @@ -62,6 +63,8 @@ public: HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); } }; +HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream); + class CClusterInStream: public IInStream, public CMyUnknownImp @@ -73,7 +76,7 @@ public: CMyComPtr Stream; UInt64 StartOffset; UInt64 Size; - int BlockSizeLog; + unsigned BlockSizeLog; CRecordVector Vector; HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); } @@ -91,13 +94,44 @@ public: return S_OK; } - MY_UNKNOWN_IMP1(IInStream) + MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; -HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream); +struct CSeekExtent +{ + UInt64 Phy; + UInt64 Virt; +}; + +class CExtentsStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _phyPos; + UInt64 _virtPos; + bool _needStartSeek; + + HRESULT SeekToPhys() { return Stream->Seek(_phyPos, STREAM_SEEK_SET, NULL); } + +public: + CMyComPtr Stream; + CRecordVector Extents; + + MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + void ReleaseStream() { Stream.Release(); } + + void Init() + { + _virtPos = 0; + _phyPos = 0; + _needStartSeek = true; + } +}; class CLimitedSequentialOutStream: public ISequentialOutStream, @@ -108,7 +142,7 @@ class CLimitedSequentialOutStream: bool _overflow; bool _overflowIsAllowed; public: - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(ISequentialOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } @@ -122,4 +156,96 @@ public: UInt64 GetRem() const { return _size; } }; + +class CTailInStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _virtPos; +public: + CMyComPtr Stream; + UInt64 Offset; + + void Init() + { + _virtPos = 0; + } + + MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + + HRESULT SeekToStart() { return Stream->Seek(Offset, STREAM_SEEK_SET, NULL); } +}; + +class CLimitedCachedInStream: + public IInStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + UInt64 _virtPos; + UInt64 _physPos; + UInt64 _size; + UInt64 _startOffset; + + const Byte *_cache; + size_t _cacheSize; + size_t _cachePhyPos; + + + HRESULT SeekToPhys() { return _stream->Seek(_physPos, STREAM_SEEK_SET, NULL); } +public: + CByteBuffer Buffer; + + void SetStream(IInStream *stream) { _stream = stream; } + void SetCache(size_t cacheSize, size_t cachePos) + { + _cache = Buffer; + _cacheSize = cacheSize; + _cachePhyPos = cachePos; + } + + HRESULT InitAndSeek(UInt64 startOffset, UInt64 size) + { + _startOffset = startOffset; + _physPos = startOffset; + _virtPos = 0; + _size = size; + return SeekToPhys(); + } + + MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + + HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); } +}; + +class CTailOutStream: + public IOutStream, + public CMyUnknownImp +{ + UInt64 _virtPos; + UInt64 _virtSize; +public: + CMyComPtr Stream; + UInt64 Offset; + + virtual ~CTailOutStream() {} + + MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStream) + + void Init() + { + _virtPos = 0; + _virtSize = 0; + } + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + STDMETHOD(SetSize)(UInt64 newSize); +}; + #endif diff --git a/src/libs/7zip/unix/CPP/7zip/Common/MethodId.cpp b/src/libs/7zip/unix/CPP/7zip/Common/MethodId.cpp deleted file mode 100644 index b797b6857..000000000 --- a/src/libs/7zip/unix/CPP/7zip/Common/MethodId.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// MethodId.cpp - -#include "StdAfx.h" - -#include "MethodId.h" -#include "../../Common/MyString.h" - -static inline wchar_t GetHex(Byte value) -{ - return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10))); -} - -UString ConvertMethodIdToString(UInt64 id) -{ - wchar_t s[32]; - int len = 32; - s[--len] = 0; - do - { - s[--len] = GetHex((Byte)id & 0xF); - id >>= 4; - s[--len] = GetHex((Byte)id & 0xF); - id >>= 4; - } - while (id != 0); - return s + len; -} diff --git a/src/libs/7zip/unix/CPP/7zip/Common/MethodId.h b/src/libs/7zip/unix/CPP/7zip/Common/MethodId.h index 54ebc9f7d..28b615fcd 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/MethodId.h +++ b/src/libs/7zip/unix/CPP/7zip/Common/MethodId.h @@ -3,7 +3,7 @@ #ifndef __7Z_METHOD_ID_H #define __7Z_METHOD_ID_H -#include "../../Common/Types.h" +#include "../../Common/MyTypes.h" typedef UInt64 CMethodId; diff --git a/src/libs/7zip/unix/CPP/7zip/Common/MethodProps.cpp b/src/libs/7zip/unix/CPP/7zip/Common/MethodProps.cpp index 5836d0f84..ff61995b7 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/MethodProps.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Common/MethodProps.cpp @@ -2,98 +2,440 @@ #include "StdAfx.h" -#include "../../Common/MyCom.h" - -#include "../ICoder.h" +#include "../../Common/StringToInt.h" #include "MethodProps.h" -static const UInt64 k_LZMA = 0x030101; -static const UInt64 k_LZMA2 = 0x21; +using namespace NWindows; + +bool StringToBool(const UString &s, bool &res) +{ + if (s.IsEmpty() || s == L"+" || StringsAreEqualNoCase_Ascii(s, "ON")) + { + res = true; + return true; + } + if (s == L"-" || StringsAreEqualNoCase_Ascii(s, "OFF")) + { + res = false; + return true; + } + return false; +} + +HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest) +{ + switch (prop.vt) + { + case VT_EMPTY: dest = true; return S_OK; + case VT_BOOL: dest = (prop.boolVal != VARIANT_FALSE); return S_OK; + case VT_BSTR: return StringToBool(prop.bstrVal, dest) ? S_OK : E_INVALIDARG; + } + return E_INVALIDARG; +} + +unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number) +{ + const wchar_t *start = srcString; + const wchar_t *end; + number = ConvertStringToUInt32(start, &end); + return (unsigned)(end - start); +} + +HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) +{ + // =VT_UI4 + // =VT_EMPTY + // {stringUInt32}=VT_EMPTY -HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder) + if (prop.vt == VT_UI4) + { + if (!name.IsEmpty()) + return E_INVALIDARG; + resValue = prop.ulVal; + return S_OK; + } + if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + if (name.IsEmpty()) + return S_OK; + UInt32 v; + if (ParseStringToUInt32(name, v) != name.Len()) + return E_INVALIDARG; + resValue = v; + return S_OK; +} + +HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads) { - bool tryReduce = false; - UInt32 reducedDictionarySize = 1 << 10; - if (inSizeForReduce != 0 && (method.Id == k_LZMA || method.Id == k_LZMA2)) + if (name.IsEmpty()) { - for (;;) + switch (prop.vt) { - const UInt32 step = (reducedDictionarySize >> 1); - if (reducedDictionarySize >= *inSizeForReduce) - { - tryReduce = true; + case VT_UI4: + numThreads = prop.ulVal; break; - } - reducedDictionarySize += step; - if (reducedDictionarySize >= *inSizeForReduce) + default: { - tryReduce = true; + bool val; + RINOK(PROPVARIANT_to_bool(prop, val)); + numThreads = (val ? defaultNumThreads : 1); break; } - if (reducedDictionarySize >= ((UInt32)3 << 30)) - break; - reducedDictionarySize += step; } + return S_OK; + } + if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + return ParsePropToUInt32(name, prop, numThreads); +} + +static HRESULT StringToDictSize(const UString &s, UInt32 &dicSize) +{ + const wchar_t *end; + UInt32 number = ConvertStringToUInt32(s, &end); + unsigned numDigits = (unsigned)(end - s); + if (numDigits == 0 || s.Len() > numDigits + 1) + return E_INVALIDARG; + const unsigned kLogDictSizeLimit = 32; + if (s.Len() == numDigits) + { + if (number >= kLogDictSizeLimit) + return E_INVALIDARG; + dicSize = (UInt32)1 << (unsigned)number; + return S_OK; + } + unsigned numBits; + switch (MyCharLower_Ascii(s[numDigits])) + { + case 'b': dicSize = number; return S_OK; + case 'k': numBits = 10; break; + case 'm': numBits = 20; break; + case 'g': numBits = 30; break; + default: return E_INVALIDARG; + } + if (number >= ((UInt32)1 << (kLogDictSizeLimit - numBits))) + return E_INVALIDARG; + dicSize = number << numBits; + return S_OK; +} + +static HRESULT PROPVARIANT_to_DictSize(const PROPVARIANT &prop, UInt32 &resValue) +{ + if (prop.vt == VT_UI4) + { + UInt32 v = prop.ulVal; + if (v >= 32) + return E_INVALIDARG; + resValue = (UInt32)1 << v; + return S_OK; + } + if (prop.vt == VT_BSTR) + return StringToDictSize(prop.bstrVal, resValue); + return E_INVALIDARG; +} + +void CProps::AddProp32(PROPID propid, UInt32 level) +{ + CProp prop; + prop.IsOptional = true; + prop.Id = propid; + prop.Value = (UInt32)level; + Props.Add(prop); +} + +class CCoderProps +{ + PROPID *_propIDs; + NCOM::CPropVariant *_props; + unsigned _numProps; + unsigned _numPropsMax; +public: + CCoderProps(unsigned numPropsMax) + { + _numPropsMax = numPropsMax; + _numProps = 0; + _propIDs = new PROPID[numPropsMax]; + _props = new NCOM::CPropVariant[numPropsMax]; + } + ~CCoderProps() + { + delete []_propIDs; + delete []_props; + } + void AddProp(const CProp &prop); + HRESULT SetProps(ICompressSetCoderProperties *setCoderProperties) + { + return setCoderProperties->SetCoderProperties(_propIDs, _props, _numProps); + } +}; + +void CCoderProps::AddProp(const CProp &prop) +{ + if (_numProps >= _numPropsMax) + throw 1; + _propIDs[_numProps] = prop.Id; + _props[_numProps] = prop.Value; + _numProps++; +} + +HRESULT CProps::SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const +{ + CCoderProps coderProps(Props.Size() + (dataSizeReduce ? 1 : 0)); + FOR_VECTOR (i, Props) + coderProps.AddProp(Props[i]); + if (dataSizeReduce) + { + CProp prop; + prop.Id = NCoderPropID::kReduceSize; + prop.Value = *dataSizeReduce; + coderProps.AddProp(prop); + } + return coderProps.SetProps(scp); +} + + +int CMethodProps::FindProp(PROPID id) const +{ + for (int i = Props.Size() - 1; i >= 0; i--) + if (Props[i].Id == id) + return i; + return -1; +} + +int CMethodProps::GetLevel() const +{ + int i = FindProp(NCoderPropID::kLevel); + if (i < 0) + return 5; + if (Props[i].Value.vt != VT_UI4) + return 9; + UInt32 level = Props[i].Value.ulVal; + return level > 9 ? 9 : (int)level; +} + +struct CNameToPropID +{ + VARTYPE VarType; + const char *Name; +}; + +static const CNameToPropID g_NameToPropID[] = +{ + { VT_UI4, "" }, + { VT_UI4, "d" }, + { VT_UI4, "mem" }, + { VT_UI4, "o" }, + { VT_UI4, "c" }, + { VT_UI4, "pb" }, + { VT_UI4, "lc" }, + { VT_UI4, "lp" }, + { VT_UI4, "fb" }, + { VT_BSTR, "mf" }, + { VT_UI4, "mc" }, + { VT_UI4, "pass" }, + { VT_UI4, "a" }, + { VT_UI4, "mt" }, + { VT_BOOL, "eos" }, + { VT_UI4, "x" }, + { VT_UI4, "reduceSize" } +}; + +static int FindPropIdExact(const UString &name) +{ + for (unsigned i = 0; i < ARRAY_SIZE(g_NameToPropID); i++) + if (StringsAreEqualNoCase_Ascii(name, g_NameToPropID[i].Name)) + return i; + return -1; +} + +static bool ConvertProperty(const PROPVARIANT &srcProp, VARTYPE varType, NCOM::CPropVariant &destProp) +{ + if (varType == srcProp.vt) + { + destProp = srcProp; + return true; + } + if (varType == VT_BOOL) + { + bool res; + if (PROPVARIANT_to_bool(srcProp, res) != S_OK) + return false; + destProp = res; + return true; + } + if (srcProp.vt == VT_EMPTY) + { + destProp = srcProp; + return true; + } + return false; +} + +static void SplitParams(const UString &srcString, UStringVector &subStrings) +{ + subStrings.Clear(); + UString s; + int len = srcString.Len(); + if (len == 0) + return; + for (int i = 0; i < len; i++) + { + wchar_t c = srcString[i]; + if (c == L':') + { + subStrings.Add(s); + s.Empty(); + } + else + s += c; + } + subStrings.Add(s); +} + +static void SplitParam(const UString ¶m, UString &name, UString &value) +{ + int eqPos = param.Find(L'='); + if (eqPos >= 0) + { + name.SetFrom(param, eqPos); + value = param.Ptr(eqPos + 1); + return; } + unsigned i; + for (i = 0; i < param.Len(); i++) + { + wchar_t c = param[i]; + if (c >= L'0' && c <= L'9') + break; + } + name.SetFrom(param, i); + value = param.Ptr(i); +} + +static bool IsLogSizeProp(PROPID propid) +{ + switch (propid) + { + case NCoderPropID::kDictionarySize: + case NCoderPropID::kUsedMemorySize: + case NCoderPropID::kBlockSize: + case NCoderPropID::kReduceSize: + return true; + } + return false; +} +HRESULT CMethodProps::SetParam(const UString &name, const UString &value) +{ + int index = FindPropIdExact(name); + if (index < 0) + return E_INVALIDARG; + const CNameToPropID &nameToPropID = g_NameToPropID[index]; + CProp prop; + prop.Id = index; + + if (IsLogSizeProp(prop.Id)) { - int numProps = method.Props.Size(); - CMyComPtr setCoderProperties; - coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); - if (setCoderProperties == NULL) + UInt32 dicSize; + RINOK(StringToDictSize(value, dicSize)); + prop.Value = dicSize; + } + else + { + NCOM::CPropVariant propValue; + if (nameToPropID.VarType == VT_BSTR) + propValue = value; + else if (nameToPropID.VarType == VT_BOOL) { - if (numProps != 0) + bool res; + if (!StringToBool(value, res)) return E_INVALIDARG; + propValue = res; } - else + else if (!value.IsEmpty()) { - CRecordVector propIDs; - NWindows::NCOM::CPropVariant *values = new NWindows::NCOM::CPropVariant[numProps]; - HRESULT res = S_OK; - try - { - for (int i = 0; i < numProps; i++) - { - const CProp &prop = method.Props[i]; - propIDs.Add(prop.Id); - NWindows::NCOM::CPropVariant &value = values[i]; - value = prop.Value; - // if (tryReduce && prop.Id == NCoderPropID::kDictionarySize && value.vt == VT_UI4 && reducedDictionarySize < value.ulVal) - if (tryReduce) - if (prop.Id == NCoderPropID::kDictionarySize) - if (value.vt == VT_UI4) - if (reducedDictionarySize < value.ulVal) - value.ulVal = reducedDictionarySize; - } - CMyComPtr setCoderProperties; - coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); - res = setCoderProperties->SetCoderProperties(&propIDs.Front(), values, numProps); - } - catch(...) - { - delete []values; - throw; - } - delete []values; - RINOK(res); + UInt32 number; + if (ParseStringToUInt32(value, number) == value.Len()) + propValue = number; + else + propValue = value; } + if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value)) + return E_INVALIDARG; + } + Props.Add(prop); + return S_OK; +} + +HRESULT CMethodProps::ParseParamsFromString(const UString &srcString) +{ + UStringVector params; + SplitParams(srcString, params); + FOR_VECTOR (i, params) + { + const UString ¶m = params[i]; + UString name, value; + SplitParam(param, name, value); + RINOK(SetParam(name, value)); + } + return S_OK; +} + +HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value) +{ + if (realName.Len() == 0) + { + // [empty]=method + return E_INVALIDARG; } - - /* - CMyComPtr writeCoderProperties; - coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); - if (writeCoderProperties != NULL) - { - CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; - CMyComPtr outStream(outStreamSpec); - outStreamSpec->Init(); - RINOK(writeCoderProperties->WriteCoderProperties(outStream)); - size_t size = outStreamSpec->GetSize(); - filterProps.SetCapacity(size); - memmove(filterProps, outStreamSpec->GetBuffer(), size); - } - */ + if (value.vt == VT_EMPTY) + { + // {realName}=[empty] + UString name, value; + SplitParam(realName, name, value); + return SetParam(name, value); + } + + // {realName}=value + int index = FindPropIdExact(realName); + if (index < 0) + return E_INVALIDARG; + const CNameToPropID &nameToPropID = g_NameToPropID[index]; + CProp prop; + prop.Id = index; + + if (IsLogSizeProp(prop.Id)) + { + UInt32 dicSize; + RINOK(PROPVARIANT_to_DictSize(value, dicSize)); + prop.Value = dicSize; + } + else + { + if (!ConvertProperty(value, nameToPropID.VarType, prop.Value)) + return E_INVALIDARG; + } + Props.Add(prop); return S_OK; } +HRESULT COneMethodInfo::ParseMethodFromString(const UString &s) +{ + int splitPos = s.Find(':'); + MethodName = s; + if (splitPos < 0) + return S_OK; + MethodName.DeleteFrom(splitPos); + return ParseParamsFromString(s.Ptr(splitPos + 1)); +} + +HRESULT COneMethodInfo::ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value) +{ + if (!realName.IsEmpty() && !StringsAreEqualNoCase_Ascii(realName, "m")) + return ParseParamsFromPROPVARIANT(realName, value); + // -m{N}=method + if (value.vt != VT_BSTR) + return E_INVALIDARG; + return ParseMethodFromString(value.bstrVal); +} diff --git a/src/libs/7zip/unix/CPP/7zip/Common/MethodProps.h b/src/libs/7zip/unix/CPP/7zip/Common/MethodProps.h index 8127e21ee..39e2ee937 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/MethodProps.h +++ b/src/libs/7zip/unix/CPP/7zip/Common/MethodProps.h @@ -3,39 +3,183 @@ #ifndef __7Z_METHOD_PROPS_H #define __7Z_METHOD_PROPS_H -#include "../../Common/MyVector.h" +#include "../../Common/MyString.h" #include "../../Windows/PropVariant.h" -#include "MethodId.h" +#include "../ICoder.h" + +bool StringToBool(const UString &s, bool &res); +HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest); +unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number); +HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); + +HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads); struct CProp { PROPID Id; + bool IsOptional; NWindows::NCOM::CPropVariant Value; + CProp(): IsOptional(false) {} }; -struct CMethod +struct CProps { - CMethodId Id; CObjectVector Props; + + void Clear() { Props.Clear(); } + + bool AreThereNonOptionalProps() const + { + FOR_VECTOR (i, Props) + if (!Props[i].IsOptional) + return true; + return false; + } + + void AddProp32(PROPID propid, UInt32 level); + + void AddPropString(PROPID propid, const wchar_t *s) + { + CProp prop; + prop.IsOptional = true; + prop.Id = propid; + prop.Value = s; + Props.Add(prop); + } + + HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const; }; -struct CMethodsMode +class CMethodProps: public CProps { - CObjectVector Methods; - #ifndef _7ZIP_ST - UInt32 NumThreads; - #endif - - CMethodsMode() - #ifndef _7ZIP_ST - : NumThreads(1) - #endif - {} - bool IsEmpty() const { return Methods.IsEmpty() ; } + HRESULT SetParam(const UString &name, const UString &value); +public: + int GetLevel() const; + int Get_NumThreads() const + { + int i = FindProp(NCoderPropID::kNumThreads); + if (i >= 0) + if (Props[i].Value.vt == VT_UI4) + return (int)Props[i].Value.ulVal; + return -1; + } + + bool Get_DicSize(UInt32 &res) const + { + res = 0; + int i = FindProp(NCoderPropID::kDictionarySize); + if (i >= 0) + if (Props[i].Value.vt == VT_UI4) + { + res = Props[i].Value.ulVal; + return true; + } + return false; + } + + int FindProp(PROPID id) const; + + UInt32 Get_Lzma_Algo() const + { + int i = FindProp(NCoderPropID::kAlgorithm); + if (i >= 0) + if (Props[i].Value.vt == VT_UI4) + return Props[i].Value.ulVal; + return GetLevel() >= 5 ? 1 : 0; + } + + UInt32 Get_Lzma_DicSize() const + { + int i = FindProp(NCoderPropID::kDictionarySize); + if (i >= 0) + if (Props[i].Value.vt == VT_UI4) + return Props[i].Value.ulVal; + int level = GetLevel(); + return level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)); + } + + UInt32 Get_Lzma_NumThreads(bool &fixedNumber) const + { + fixedNumber = false; + int numThreads = Get_NumThreads(); + if (numThreads >= 0) + { + fixedNumber = true; + return numThreads < 2 ? 1 : 2; + } + return Get_Lzma_Algo() == 0 ? 1 : 2; + } + + UInt32 Get_BZip2_NumThreads(bool &fixedNumber) const + { + fixedNumber = false; + int numThreads = Get_NumThreads(); + if (numThreads >= 0) + { + fixedNumber = true; + if (numThreads < 1) return 1; + if (numThreads > 64) return 64; + return numThreads; + } + return 1; + } + + UInt32 Get_BZip2_BlockSize() const + { + int i = FindProp(NCoderPropID::kDictionarySize); + if (i >= 0) + if (Props[i].Value.vt == VT_UI4) + { + UInt32 blockSize = Props[i].Value.ulVal; + const UInt32 kDicSizeMin = 100000; + const UInt32 kDicSizeMax = 900000; + if (blockSize < kDicSizeMin) blockSize = kDicSizeMin; + if (blockSize > kDicSizeMax) blockSize = kDicSizeMax; + return blockSize; + } + int level = GetLevel(); + return 100000 * (level >= 5 ? 9 : (level >= 1 ? level * 2 - 1: 1)); + } + + UInt32 Get_Ppmd_MemSize() const + { + int i = FindProp(NCoderPropID::kUsedMemorySize); + if (i >= 0) + if (Props[i].Value.vt == VT_UI4) + return Props[i].Value.ulVal; + int level = GetLevel(); + return level >= 9 ? (192 << 20) : ((UInt32)1 << (level + 19)); + } + + void AddLevelProp(UInt32 level) + { + AddProp32(NCoderPropID::kLevel, level); + } + + void AddNumThreadsProp(UInt32 numThreads) + { + AddProp32(NCoderPropID::kNumThreads, numThreads); + } + + HRESULT ParseParamsFromString(const UString &srcString); + HRESULT ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value); }; -HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder); +class COneMethodInfo: public CMethodProps +{ +public: + UString MethodName; + + void Clear() + { + CMethodProps::Clear(); + MethodName.Empty(); + } + bool IsEmpty() const { return MethodName.IsEmpty() && Props.IsEmpty(); } + HRESULT ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value); + HRESULT ParseMethodFromString(const UString &s); +}; #endif diff --git a/src/libs/7zip/unix/CPP/7zip/Common/OffsetStream.cpp b/src/libs/7zip/unix/CPP/7zip/Common/OffsetStream.cpp deleted file mode 100644 index c5e4e6da4..000000000 --- a/src/libs/7zip/unix/CPP/7zip/Common/OffsetStream.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// OffsetStream.cpp - -#include "StdAfx.h" - -#include "Common/Defs.h" -#include "OffsetStream.h" - -HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset) -{ - _offset = offset; - _stream = stream; - return _stream->Seek(offset, STREAM_SEEK_SET, NULL); -} - -STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) -{ - return _stream->Write(data, size, processedSize); -} - -STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, - UInt64 *newPosition) -{ - UInt64 absoluteNewPosition; - if (seekOrigin == STREAM_SEEK_SET) - offset += _offset; - HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition); - if (newPosition != NULL) - *newPosition = absoluteNewPosition - _offset; - return result; -} - -STDMETHODIMP COffsetOutStream::SetSize(UInt64 newSize) -{ - return _stream->SetSize(_offset + newSize); -} diff --git a/src/libs/7zip/unix/CPP/7zip/Common/OffsetStream.h b/src/libs/7zip/unix/CPP/7zip/Common/OffsetStream.h deleted file mode 100644 index de9d06dd0..000000000 --- a/src/libs/7zip/unix/CPP/7zip/Common/OffsetStream.h +++ /dev/null @@ -1,25 +0,0 @@ -// OffsetStream.h - -#ifndef __OFFSETSTREAM_H -#define __OFFSETSTREAM_H - -#include "Common/MyCom.h" -#include "../IStream.h" - -class COffsetOutStream: - public IOutStream, - public CMyUnknownImp -{ - UInt64 _offset; - CMyComPtr _stream; -public: - HRESULT Init(IOutStream *stream, UInt64 offset); - - MY_UNKNOWN_IMP - - STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); - STDMETHOD(SetSize)(UInt64 newSize); -}; - -#endif diff --git a/src/libs/7zip/unix/CPP/7zip/Common/OutBuffer.cpp b/src/libs/7zip/unix/CPP/7zip/Common/OutBuffer.cpp index 2e5debd83..4ba34a053 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/OutBuffer.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Common/OutBuffer.cpp @@ -6,34 +6,29 @@ #include "OutBuffer.h" -bool COutBuffer::Create(UInt32 bufferSize) +bool COutBuffer::Create(UInt32 bufSize) throw() { const UInt32 kMinBlockSize = 1; - if (bufferSize < kMinBlockSize) - bufferSize = kMinBlockSize; - if (_buffer != 0 && _bufferSize == bufferSize) + if (bufSize < kMinBlockSize) + bufSize = kMinBlockSize; + if (_buf != 0 && _bufSize == bufSize) return true; Free(); - _bufferSize = bufferSize; - _buffer = (Byte *)::MidAlloc(bufferSize); - return (_buffer != 0); + _bufSize = bufSize; + _buf = (Byte *)::MidAlloc(bufSize); + return (_buf != 0); } -void COutBuffer::Free() +void COutBuffer::Free() throw() { - ::MidFree(_buffer); - _buffer = 0; + ::MidFree(_buf); + _buf = 0; } -void COutBuffer::SetStream(ISequentialOutStream *stream) -{ - _stream = stream; -} - -void COutBuffer::Init() +void COutBuffer::Init() throw() { _streamPos = 0; - _limitPos = _bufferSize; + _limitPos = _bufSize; _pos = 0; _processedSize = 0; _overDict = false; @@ -42,27 +37,27 @@ void COutBuffer::Init() #endif } -UInt64 COutBuffer::GetProcessedSize() const +UInt64 COutBuffer::GetProcessedSize() const throw() { UInt64 res = _processedSize + _pos - _streamPos; if (_streamPos > _pos) - res += _bufferSize; + res += _bufSize; return res; } -HRESULT COutBuffer::FlushPart() +HRESULT COutBuffer::FlushPart() throw() { - // _streamPos < _bufferSize - UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos); + // _streamPos < _bufSize + UInt32 size = (_streamPos >= _pos) ? (_bufSize - _streamPos) : (_pos - _streamPos); HRESULT result = S_OK; #ifdef _NO_EXCEPTIONS result = ErrorCode; #endif - if (_buffer2 != 0) + if (_buf2 != 0) { - memmove(_buffer2, _buffer + _streamPos, size); - _buffer2 += size; + memcpy(_buf2, _buf + _streamPos, size); + _buf2 += size; } if (_stream != 0 @@ -72,30 +67,30 @@ HRESULT COutBuffer::FlushPart() ) { UInt32 processedSize = 0; - result = _stream->Write(_buffer + _streamPos, size, &processedSize); + result = _stream->Write(_buf + _streamPos, size, &processedSize); size = processedSize; } _streamPos += size; - if (_streamPos == _bufferSize) + if (_streamPos == _bufSize) _streamPos = 0; - if (_pos == _bufferSize) + if (_pos == _bufSize) { _overDict = true; _pos = 0; } - _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize; + _limitPos = (_streamPos > _pos) ? _streamPos : _bufSize; _processedSize += size; return result; } -HRESULT COutBuffer::Flush() +HRESULT COutBuffer::Flush() throw() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return ErrorCode; #endif - while(_streamPos != _pos) + while (_streamPos != _pos) { HRESULT result = FlushPart(); if (result != S_OK) diff --git a/src/libs/7zip/unix/CPP/7zip/Common/OutBuffer.h b/src/libs/7zip/unix/CPP/7zip/Common/OutBuffer.h index 62e77caae..0baad3636 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/OutBuffer.h +++ b/src/libs/7zip/unix/CPP/7zip/Common/OutBuffer.h @@ -1,7 +1,7 @@ // OutBuffer.h -#ifndef __OUTBUFFER_H -#define __OUTBUFFER_H +#ifndef __OUT_BUFFER_H +#define __OUT_BUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" @@ -17,39 +17,38 @@ struct COutBufferException: public CSystemException class COutBuffer { protected: - Byte *_buffer; + Byte *_buf; UInt32 _pos; UInt32 _limitPos; UInt32 _streamPos; - UInt32 _bufferSize; - CMyComPtr _stream; + UInt32 _bufSize; + ISequentialOutStream *_stream; UInt64 _processedSize; - Byte *_buffer2; + Byte *_buf2; bool _overDict; - HRESULT FlushPart(); + HRESULT FlushPart() throw(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif - COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {} + COutBuffer(): _buf(0), _pos(0), _stream(0), _buf2(0) {} ~COutBuffer() { Free(); } - - bool Create(UInt32 bufferSize); - void Free(); - void SetMemStream(Byte *buffer) { _buffer2 = buffer; } - void SetStream(ISequentialOutStream *stream); - void Init(); - HRESULT Flush(); + bool Create(UInt32 bufSize) throw(); + void Free() throw(); + + void SetMemStream(Byte *buf) { _buf2 = buf; } + void SetStream(ISequentialOutStream *stream) { _stream = stream; } + void Init() throw(); + HRESULT Flush() throw(); void FlushWithCheck(); - void ReleaseStream() { _stream.Release(); } void WriteByte(Byte b) { - _buffer[_pos++] = b; - if(_pos == _limitPos) + _buf[_pos++] = b; + if (_pos == _limitPos) FlushWithCheck(); } void WriteBytes(const void *data, size_t size) @@ -58,7 +57,7 @@ public: WriteByte(((const Byte *)data)[i]); } - UInt64 GetProcessedSize() const; + UInt64 GetProcessedSize() const throw(); }; #endif diff --git a/src/libs/7zip/unix/CPP/7zip/Common/ProgressUtils.cpp b/src/libs/7zip/unix/CPP/7zip/Common/ProgressUtils.cpp index f24ff6b6f..bac45c1c2 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/ProgressUtils.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Common/ProgressUtils.cpp @@ -1,4 +1,4 @@ -// ProgressUtils.h +// ProgressUtils.cpp #include "StdAfx.h" diff --git a/src/libs/7zip/unix/CPP/7zip/Common/PropId.cpp b/src/libs/7zip/unix/CPP/7zip/Common/PropId.cpp new file mode 100644 index 000000000..10daef715 --- /dev/null +++ b/src/libs/7zip/unix/CPP/7zip/Common/PropId.cpp @@ -0,0 +1,99 @@ +// PropId.cpp + +#include "StdAfx.h" + +#include "../PropID.h" + +// VARTYPE +Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] = +{ + VT_EMPTY, + VT_UI4, + VT_UI4, + VT_BSTR, + VT_BSTR, + VT_BSTR, + VT_BOOL, + VT_UI8, + VT_UI8, + VT_UI4, + VT_FILETIME, + VT_FILETIME, + VT_FILETIME, + VT_BOOL, + VT_BOOL, + VT_BOOL, + VT_BOOL, + VT_BOOL, + VT_UI4, + VT_UI4, + VT_BSTR, + VT_BOOL, + VT_BSTR, + VT_BSTR, + VT_BSTR, + VT_BSTR, + VT_BSTR, + VT_UI8, + VT_BSTR, + VT_UI8, + VT_BSTR, + VT_UI8, + VT_UI8, + VT_BSTR, // or VT_UI8 kpidUnpackVer + VT_UI4, // or VT_UI8 kpidVolume + VT_BOOL, + VT_UI8, + VT_UI8, + VT_UI8, + VT_UI8, + VT_UI4, + VT_BOOL, + VT_BOOL, + VT_BSTR, + VT_UI8, + VT_UI8, + VT_UI4, // kpidChecksum + VT_BSTR, + VT_UI8, + VT_BSTR, // or VT_UI8 kpidId + VT_BSTR, + VT_BSTR, + VT_UI4, + VT_UI4, + VT_BSTR, + VT_BSTR, + VT_UI8, + VT_UI8, + VT_UI4, + VT_BSTR, + VT_BSTR, + VT_BSTR, + VT_BSTR, // kpidNtSecure + VT_BOOL, + VT_BOOL, + VT_BOOL, + VT_BOOL, + VT_BSTR, // SHA-1 + VT_BSTR, // SHA-256 + VT_BSTR, + VT_UI8, + VT_UI4, + VT_UI4, + VT_BSTR, + VT_UI8, + VT_UI8, + VT_UI8, + VT_UI8, + VT_UI8, + VT_UI8, + VT_UI8, + VT_BSTR, + VT_BSTR, + VT_BSTR, + VT_BOOL, + VT_BOOL, + VT_BOOL, + VT_UI8, + VT_UI8 +}; diff --git a/src/libs/7zip/unix/CPP/7zip/Common/RegisterArc.h b/src/libs/7zip/unix/CPP/7zip/Common/RegisterArc.h index 305aac1fd..82bd09673 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/RegisterArc.h +++ b/src/libs/7zip/unix/CPP/7zip/Common/RegisterArc.h @@ -5,28 +5,69 @@ #include "../Archive/IArchive.h" -typedef IInArchive * (*CreateInArchiveP)(); -typedef IOutArchive * (*CreateOutArchiveP)(); +#include struct CArcInfo { - const wchar_t *Name; - const wchar_t *Ext; - const wchar_t *AddExt; + const char *Name; + const char *Ext; + const char *AddExt; + Byte ClassId; - Byte Signature[28]; // FIXME Byte Signature[16]; adding 22 bytes to insure kSignature[0x1A]!= 0 and kSignature[0x1B] != 0 - int SignatureSize; - bool KeepName; - CreateInArchiveP CreateInArchive; - CreateOutArchiveP CreateOutArchive; + + Byte SignatureSize; + Byte Signature[20]; + UInt16 SignatureOffset; + + UInt16 Flags; + + Func_CreateInArchive CreateInArchive; + Func_CreateOutArchive CreateOutArchive; + Func_IsArc IsArc; + + bool IsMultiSignature() const { return (Flags & NArcInfoFlags::kMultiSignature) != 0; } + + std::once_flag once; }; -void RegisterArc(const CArcInfo *arcInfo); +void RegisterArc(const CArcInfo *arcInfo) throw(); #define REGISTER_ARC_NAME(x) CRegister ## x -#define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) { \ - REGISTER_ARC_NAME(x)() { RegisterArc(&g_ArcInfo); }}; \ +#define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) \ + { \ + REGISTER_ARC_NAME(x)() \ + { \ + std::call_once(g_ArcInfo.once, [] { RegisterArc(&g_ArcInfo); }); \ + } \ + }; \ static REGISTER_ARC_NAME(x) g_RegisterArc; \ void registerArc##x() { static REGISTER_ARC_NAME(x) g_RegisterArc; } + +#define REGISTER_ARC_DEC_SIG(x) struct REGISTER_ARC_NAME(x) \ + { \ + REGISTER_ARC_NAME(x)() { \ + std::call_once(g_ArcInfo.once, [] { \ + g_ArcInfo.Signature[0]--; \ + RegisterArc(&g_ArcInfo); \ + }); \ + } \ + }; \ + static REGISTER_ARC_NAME(x) g_RegisterArc; \ + void registerArcDec##x() { static REGISTER_ARC_NAME(x) g_RegisterArc; } + + +#define IMP_CreateArcIn_2(c) \ + static IInArchive *CreateArc() { return new c; } + +#define IMP_CreateArcIn IMP_CreateArcIn_2(CHandler) + +#ifdef EXTRACT_ONLY + #define IMP_CreateArcOut + #define REF_CreateArc_Pair CreateArc, NULL +#else + #define IMP_CreateArcOut static IOutArchive *CreateArcOut() { return new CHandler; } + #define REF_CreateArc_Pair CreateArc, CreateArcOut +#endif + #endif diff --git a/src/libs/7zip/unix/CPP/7zip/Common/RegisterCodec.h b/src/libs/7zip/unix/CPP/7zip/Common/RegisterCodec.h index d53c4344a..0c6662a6c 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/RegisterCodec.h +++ b/src/libs/7zip/unix/CPP/7zip/Common/RegisterCodec.h @@ -1,9 +1,12 @@ // RegisterCodec.h -#ifndef __REGISTERCODEC_H -#define __REGISTERCODEC_H +#ifndef __REGISTER_CODEC_H +#define __REGISTER_CODEC_H #include "../Common/MethodId.h" +#include "../ICoder.h" + +#include typedef void * (*CreateCodecP)(); struct CCodecInfo @@ -14,21 +17,50 @@ struct CCodecInfo const wchar_t *Name; UInt32 NumInStreams; bool IsFilter; + std::once_flag once; }; -void RegisterCodec(const CCodecInfo *codecInfo); +void RegisterCodec(const CCodecInfo *codecInfo) throw(); #define REGISTER_CODEC_NAME(x) CRegisterCodec ## x -#define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \ - REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \ +#define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) \ + { \ + REGISTER_CODEC_NAME(x)() \ + { \ + std::call_once(g_CodecInfo.once, [] { RegisterCodec(&g_CodecInfo); }); \ + } \ + }; \ static REGISTER_CODEC_NAME(x) g_RegisterCodec; \ void registerCodec##x() { static REGISTER_CODEC_NAME(x) g_RegisterCodecs; } #define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x -#define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \ - REGISTER_CODECS_NAME(x)() { for (int i = 0; i < sizeof(g_CodecsInfo) / sizeof(g_CodecsInfo[0]); i++) \ - RegisterCodec(&g_CodecsInfo[i]); }}; \ +#define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) \ + { \ + REGISTER_CODECS_NAME(x)() \ + { \ + for (unsigned i = 0; i < ARRAY_SIZE(g_CodecsInfo); i++) \ + std::call_once(g_CodecsInfo[i].once, [&i] { RegisterCodec(&g_CodecsInfo[i]); }); \ + } \ + }; \ static REGISTER_CODECS_NAME(x) g_RegisterCodecs; \ void registerCodec##x() { static REGISTER_CODECS_NAME(x) g_RegisterCodecs; } + + +struct CHasherInfo +{ + IHasher * (*CreateHasher)(); + CMethodId Id; + const wchar_t *Name; + UInt32 DigestSize; +}; + +void RegisterHasher(const CHasherInfo *hasher) throw(); + +#define REGISTER_HASHER_NAME(x) CRegisterHasher ## x + +#define REGISTER_HASHER(x) struct REGISTER_HASHER_NAME(x) { \ + REGISTER_HASHER_NAME(x)() { RegisterHasher(&g_HasherInfo); }}; \ + static REGISTER_HASHER_NAME(x) g_RegisterHasher; + #endif diff --git a/src/libs/7zip/unix/CPP/7zip/Common/StreamBinder.cpp b/src/libs/7zip/unix/CPP/7zip/Common/StreamBinder.cpp index 9dfa3fb75..43feef1ba 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/StreamBinder.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Common/StreamBinder.cpp @@ -2,151 +2,128 @@ #include "StdAfx.h" -#include "StreamBinder.h" -#include "../../Common/Defs.h" #include "../../Common/MyCom.h" -using namespace NWindows; -using namespace NSynchronization; +#include "StreamBinder.h" -class CSequentialInStreamForBinder: +class CBinderInStream: public ISequentialInStream, public CMyUnknownImp { + CStreamBinder *_binder; public: MY_UNKNOWN_IMP - STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); -private: - CStreamBinder *m_StreamBinder; -public: - ~CSequentialInStreamForBinder() { m_StreamBinder->CloseRead(); } - void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } + ~CBinderInStream() { _binder->CloseRead(); } + CBinderInStream(CStreamBinder *binder): _binder(binder) {} }; -STDMETHODIMP CSequentialInStreamForBinder::Read(void *data, UInt32 size, UInt32 *processedSize) - { return m_StreamBinder->Read(data, size, processedSize); } +STDMETHODIMP CBinderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) + { return _binder->Read(data, size, processedSize); } -class CSequentialOutStreamForBinder: +class CBinderOutStream: public ISequentialOutStream, public CMyUnknownImp { + CStreamBinder *_binder; public: MY_UNKNOWN_IMP - STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - -private: - CStreamBinder *m_StreamBinder; -public: - ~CSequentialOutStreamForBinder() { m_StreamBinder->CloseWrite(); } - void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } + ~CBinderOutStream() { _binder->CloseWrite(); } + CBinderOutStream(CStreamBinder *binder): _binder(binder) {} }; -STDMETHODIMP CSequentialOutStreamForBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) - { return m_StreamBinder->Write(data, size, processedSize); } +STDMETHODIMP CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) + { return _binder->Write(data, size, processedSize); } -////////////////////////// -// CStreamBinder -// (_thereAreBytesToReadEvent && _bufferSize == 0) means that stream is finished. -HRes CStreamBinder::CreateEvents() +WRes CStreamBinder::CreateEvents() { - _synchroFor_allBytesAreWritenEvent_and_readStreamIsClosedEvent = new NWindows::NSynchronization::CSynchro(); - _synchroFor_allBytesAreWritenEvent_and_readStreamIsClosedEvent->Create(); - RINOK(_allBytesAreWritenEvent.Create(_synchroFor_allBytesAreWritenEvent_and_readStreamIsClosedEvent,true)); - RINOK(_thereAreBytesToReadEvent.Create()); - return _readStreamIsClosedEvent.Create(_synchroFor_allBytesAreWritenEvent_and_readStreamIsClosedEvent); + _synchroFor_canWrite_Event_and_readingWasClosed_Event = new NWindows::NSynchronization::CSynchro(); + _synchroFor_canWrite_Event_and_readingWasClosed_Event->Create(); + RINOK(_canWrite_Event.Create(_synchroFor_canWrite_Event_and_readingWasClosed_Event,true)); + // RINOK(_canWrite_Event.Create(true)); + RINOK(_canRead_Event.Create()); + return _readingWasClosed_Event.Create(_synchroFor_canWrite_Event_and_readingWasClosed_Event); } void CStreamBinder::ReInit() { - _thereAreBytesToReadEvent.Reset(); - _readStreamIsClosedEvent.Reset(); + _waitWrite = true; + _canRead_Event.Reset(); + _readingWasClosed_Event.Reset(); ProcessedSize = 0; } - -void CStreamBinder::CreateStreams(ISequentialInStream **inStream, - ISequentialOutStream **outStream) +void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream) { - CSequentialInStreamForBinder *inStreamSpec = new - CSequentialInStreamForBinder; + _waitWrite = true; + _bufSize = 0; + _buf = NULL; + ProcessedSize = 0; + + CBinderInStream *inStreamSpec = new CBinderInStream(this); CMyComPtr inStreamLoc(inStreamSpec); - inStreamSpec->SetBinder(this); *inStream = inStreamLoc.Detach(); - CSequentialOutStreamForBinder *outStreamSpec = new - CSequentialOutStreamForBinder; + CBinderOutStream *outStreamSpec = new CBinderOutStream(this); CMyComPtr outStreamLoc(outStreamSpec); - outStreamSpec->SetBinder(this); *outStream = outStreamLoc.Detach(); - - _buffer = NULL; - _bufferSize= 0; - ProcessedSize = 0; } +// (_canRead_Event && _bufSize == 0) means that stream is finished. + HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { - UInt32 sizeToRead = size; - if (size > 0) + if (processedSize) + *processedSize = 0; + if (size != 0) { - RINOK(_thereAreBytesToReadEvent.Lock()); - sizeToRead = MyMin(_bufferSize, size); - if (_bufferSize > 0) + if (_waitWrite) { - memcpy(data, _buffer, sizeToRead); - _buffer = ((const Byte *)_buffer) + sizeToRead; - _bufferSize -= sizeToRead; - if (_bufferSize == 0) + RINOK(_canRead_Event.Lock()); + _waitWrite = false; + } + if (size > _bufSize) + size = _bufSize; + if (size != 0) + { + memcpy(data, _buf, size); + _buf = ((const Byte *)_buf) + size; + ProcessedSize += size; + if (processedSize) + *processedSize = size; + _bufSize -= size; + if (_bufSize == 0) { - _thereAreBytesToReadEvent.Reset(); - _allBytesAreWritenEvent.Set(); + _waitWrite = true; + _canRead_Event.Reset(); + _canWrite_Event.Set(); } } } - if (processedSize != NULL) - *processedSize = sizeToRead; - ProcessedSize += sizeToRead; return S_OK; } -void CStreamBinder::CloseRead() -{ - _readStreamIsClosedEvent.Set(); -} - HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { - if (size > 0) + if (processedSize) + *processedSize = 0; + if (size != 0) { - _buffer = data; - _bufferSize = size; - _allBytesAreWritenEvent.Reset(); - _thereAreBytesToReadEvent.Set(); - - HANDLE events[2]; - events[0] = _allBytesAreWritenEvent; - events[1] = _readStreamIsClosedEvent; + _buf = data; + _bufSize = size; + _canWrite_Event.Reset(); + _canRead_Event.Set(); + + HANDLE events[2] = { _canWrite_Event, _readingWasClosed_Event }; DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE); if (waitResult != WAIT_OBJECT_0 + 0) - { - // ReadingWasClosed = true; return S_FALSE; - } - // if(!_allBytesAreWritenEvent.Lock()) - // return E_FAIL; + if (processedSize) + *processedSize = size; } - if (processedSize != NULL) - *processedSize = size; return S_OK; } - -void CStreamBinder::CloseWrite() -{ - // _bufferSize must be = 0 - _thereAreBytesToReadEvent.Set(); -} diff --git a/src/libs/7zip/unix/CPP/7zip/Common/StreamBinder.h b/src/libs/7zip/unix/CPP/7zip/Common/StreamBinder.h index 47743dee2..aba6b8e17 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/StreamBinder.h +++ b/src/libs/7zip/unix/CPP/7zip/Common/StreamBinder.h @@ -1,38 +1,35 @@ // StreamBinder.h -#ifndef __STREAMBINDER_H -#define __STREAMBINDER_H +#ifndef __STREAM_BINDER_H +#define __STREAM_BINDER_H -#include "../IStream.h" #include "../../Windows/Synchronization.h" +#include "../IStream.h" + class CStreamBinder { - NWindows::NSynchronization::CManualResetEventWFMO _allBytesAreWritenEvent; - NWindows::NSynchronization::CManualResetEvent _thereAreBytesToReadEvent; - NWindows::NSynchronization::CManualResetEventWFMO _readStreamIsClosedEvent; - NWindows::NSynchronization::CSynchro * _synchroFor_allBytesAreWritenEvent_and_readStreamIsClosedEvent; - UInt32 _bufferSize; - const void *_buffer; + NWindows::NSynchronization::CManualResetEventWFMO _canWrite_Event; + NWindows::NSynchronization::CManualResetEvent _canRead_Event; + NWindows::NSynchronization::CManualResetEventWFMO _readingWasClosed_Event; + NWindows::NSynchronization::CSynchro * _synchroFor_canWrite_Event_and_readingWasClosed_Event; + bool _waitWrite; + UInt32 _bufSize; + const void *_buf; public: - // bool ReadingWasClosed; UInt64 ProcessedSize; - CStreamBinder() { _synchroFor_allBytesAreWritenEvent_and_readStreamIsClosedEvent = 0; } - ~CStreamBinder() { - if (_synchroFor_allBytesAreWritenEvent_and_readStreamIsClosedEvent) - delete _synchroFor_allBytesAreWritenEvent_and_readStreamIsClosedEvent; - _synchroFor_allBytesAreWritenEvent_and_readStreamIsClosedEvent = 0; - } - HRes CreateEvents(); - void CreateStreams(ISequentialInStream **inStream, - ISequentialOutStream **outStream); + WRes CreateEvents(); + void CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream); + void ReInit(); HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); - void CloseRead(); - HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize); - void CloseWrite(); - void ReInit(); + void CloseRead() { _readingWasClosed_Event.Set(); } + void CloseWrite() + { + // _bufSize must be = 0 + _canRead_Event.Set(); + } }; #endif diff --git a/src/libs/7zip/unix/CPP/7zip/Common/StreamObjects.cpp b/src/libs/7zip/unix/CPP/7zip/Common/StreamObjects.cpp index 24253a9ed..7721c3a7e 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/StreamObjects.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Common/StreamObjects.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include + #include "../../../C/Alloc.h" #include "StreamObjects.h" @@ -12,8 +14,8 @@ STDMETHODIMP CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize) *processedSize = 0; if (size == 0) return S_OK; - if (_pos > _size) - return E_FAIL; + if (_pos >= _size) + return S_OK; size_t rem = _size - (size_t)_pos; if (rem > size) rem = (size_t)size; @@ -26,26 +28,51 @@ STDMETHODIMP CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize) STDMETHODIMP CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - switch(seekOrigin) + switch (seekOrigin) { - case STREAM_SEEK_SET: _pos = offset; break; - case STREAM_SEEK_CUR: _pos += offset; break; - case STREAM_SEEK_END: _pos = _size + offset; break; + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _pos; break; + case STREAM_SEEK_END: offset += _size; break; default: return STG_E_INVALIDFUNCTION; } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _pos = offset; if (newPosition) - *newPosition = _pos; + *newPosition = offset; return S_OK; } -void CByteDynBuffer::Free() +/* +void Create_BufInStream_WithReference(const void *data, size_t size, ISequentialInStream **stream) +{ + CBufInStream *inStreamSpec = new CBufInStream; + CMyComPtr streamTemp = inStreamSpec; + inStreamSpec->Init((const Byte *)data, size); + *stream = streamTemp.Detach(); +} +*/ + +void Create_BufInStream_WithNewBuf(const void *data, size_t size, ISequentialInStream **stream) +{ + CReferenceBuf *referenceBuf = new CReferenceBuf; + CMyComPtr ref = referenceBuf; + referenceBuf->Buf.CopyFrom((const Byte *)data, size); + + CBufInStream *inStreamSpec = new CBufInStream; + CMyComPtr streamTemp = inStreamSpec; + inStreamSpec->Init(referenceBuf); + *stream = streamTemp.Detach(); +} + +void CByteDynBuffer::Free() throw() { free(_buf); _buf = 0; _capacity = 0; } -bool CByteDynBuffer::EnsureCapacity(size_t cap) +bool CByteDynBuffer::EnsureCapacity(size_t cap) throw() { if (cap <= _capacity) return true; @@ -77,8 +104,7 @@ Byte *CDynBufSeqOutStream::GetBufPtrForWriting(size_t addSize) void CDynBufSeqOutStream::CopyToBuffer(CByteBuffer &dest) const { - dest.SetCapacity(_size); - memcpy((Byte *)dest, (const Byte *)_buffer, _size); + dest.CopyFrom((const Byte *)_buffer, _size); } STDMETHODIMP CDynBufSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) @@ -121,7 +147,7 @@ STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, static const UInt64 kEmptyTag = (UInt64)(Int64)-1; -void CCachedInStream::Free() +void CCachedInStream::Free() throw() { MyFree(_tags); _tags = 0; @@ -129,7 +155,7 @@ void CCachedInStream::Free() _data = 0; } -bool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog) +bool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw() { unsigned sizeLog = blockSizeLog + numBlocksLog; if (sizeLog >= sizeof(size_t) * 8) @@ -155,7 +181,7 @@ bool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog) return true; } -void CCachedInStream::Init(UInt64 size) +void CCachedInStream::Init(UInt64 size) throw() { _size = size; _pos = 0; @@ -170,8 +196,8 @@ STDMETHODIMP CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSiz *processedSize = 0; if (size == 0) return S_OK; - if (_pos > _size) - return E_FAIL; + if (_pos >= _size) + return S_OK; { UInt64 rem = _size - _pos; @@ -205,17 +231,20 @@ STDMETHODIMP CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSiz return S_OK; } - + STDMETHODIMP CCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - switch(seekOrigin) + 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; + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _pos; break; + case STREAM_SEEK_END: offset += _size; break; default: return STG_E_INVALIDFUNCTION; } - if (newPosition != 0) - *newPosition = _pos; + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _pos = offset; + if (newPosition) + *newPosition = offset; return S_OK; } diff --git a/src/libs/7zip/unix/CPP/7zip/Common/StreamObjects.h b/src/libs/7zip/unix/CPP/7zip/Common/StreamObjects.h index 5c8b5e51b..d0c86b566 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/StreamObjects.h +++ b/src/libs/7zip/unix/CPP/7zip/Common/StreamObjects.h @@ -3,8 +3,10 @@ #ifndef __STREAM_OBJECTS_H #define __STREAM_OBJECTS_H -#include "../../Common/Buffer.h" +#include "../../Common/MyBuffer.h" #include "../../Common/MyCom.h" +#include "../../Common/MyVector.h" + #include "../IStream.h" struct CReferenceBuf: @@ -31,13 +33,16 @@ public: _pos = 0; _ref = ref; } - void Init(CReferenceBuf *ref) { Init(ref->Buf, ref->Buf.GetCapacity(), ref); } + void Init(CReferenceBuf *ref) { Init(ref->Buf, ref->Buf.Size(), ref); } - MY_UNKNOWN_IMP1(IInStream) + MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; +// void Create_BufInStream_WithReference(const void *data, size_t size, ISequentialInStream **stream); +void Create_BufInStream_WithNewBuf(const void *data, size_t size, ISequentialInStream **stream); + class CByteDynBuffer { size_t _capacity; @@ -46,11 +51,11 @@ public: 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*() { return _buf; }; + void Free() throw(); + size_t GetCapacity() const { return _capacity; } + operator Byte*() const { return _buf; }; operator const Byte*() const { return _buf; }; - bool EnsureCapacity(size_t capacity); + bool EnsureCapacity(size_t capacity) throw(); }; class CDynBufSeqOutStream: @@ -68,7 +73,7 @@ public: Byte *GetBufPtrForWriting(size_t addSize); void UpdateSize(size_t addSize) { _size += addSize; } - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(ISequentialOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; @@ -88,7 +93,7 @@ public: } size_t GetPos() const { return _pos; } - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(ISequentialOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; @@ -103,7 +108,7 @@ public: void Init() { _size = 0; } UInt64 GetSize() const { return _size; } - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(ISequentialOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; @@ -123,9 +128,9 @@ protected: public: 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); + void Free() throw(); + bool Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw(); + void Init(UInt64 size) throw(); MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); diff --git a/src/libs/7zip/unix/CPP/7zip/Common/StreamUtils.cpp b/src/libs/7zip/unix/CPP/7zip/Common/StreamUtils.cpp index 049e4aa17..1402f4205 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/StreamUtils.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Common/StreamUtils.cpp @@ -6,7 +6,7 @@ static const UInt32 kBlockSize = ((UInt32)1 << 31); -HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *processedSize) +HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *processedSize) throw() { size_t size = *processedSize; *processedSize = 0; @@ -25,21 +25,21 @@ HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *processedSiz return S_OK; } -HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) +HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) throw() { size_t processedSize = size; RINOK(ReadStream(stream, data, &processedSize)); return (size == processedSize) ? S_OK : S_FALSE; } -HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) +HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) throw() { size_t processedSize = size; RINOK(ReadStream(stream, data, &processedSize)); return (size == processedSize) ? S_OK : E_FAIL; } -HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) +HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) throw() { while (size != 0) { diff --git a/src/libs/7zip/unix/CPP/7zip/Common/StreamUtils.h b/src/libs/7zip/unix/CPP/7zip/Common/StreamUtils.h index f1cfd1848..ae914c004 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/StreamUtils.h +++ b/src/libs/7zip/unix/CPP/7zip/Common/StreamUtils.h @@ -1,13 +1,13 @@ // StreamUtils.h -#ifndef __STREAMUTILS_H -#define __STREAMUTILS_H +#ifndef __STREAM_UTILS_H +#define __STREAM_UTILS_H #include "../IStream.h" -HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *size); -HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size); -HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size); -HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size); +HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *size) throw(); +HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) throw(); +HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) throw(); +HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) throw(); #endif diff --git a/src/libs/7zip/unix/CPP/7zip/Common/UniqBlocks.cpp b/src/libs/7zip/unix/CPP/7zip/Common/UniqBlocks.cpp new file mode 100644 index 000000000..7fcc88f5e --- /dev/null +++ b/src/libs/7zip/unix/CPP/7zip/Common/UniqBlocks.cpp @@ -0,0 +1,56 @@ +// UniqBlocks.cpp + +#include "StdAfx.h" + +#include "UniqBlocks.h" + +int CUniqBlocks::AddUniq(const Byte *data, size_t size) +{ + unsigned left = 0, right = Sorted.Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + int index = Sorted[mid]; + const CByteBuffer &buf = Bufs[index]; + size_t sizeMid = buf.Size(); + if (size < sizeMid) + right = mid; + else if (size > sizeMid) + left = mid + 1; + else + { + int cmp = memcmp(data, buf, size); + if (cmp == 0) + return index; + if (cmp < 0) + right = mid; + else + left = mid + 1; + } + } + int index = Bufs.Size(); + Sorted.Insert(left, index); + CByteBuffer &buf = Bufs.AddNew(); + buf.CopyFrom(data, size); + return index; +} + +UInt64 CUniqBlocks::GetTotalSizeInBytes() const +{ + UInt64 size = 0; + FOR_VECTOR (i, Bufs) + size += Bufs[i].Size(); + return size; +} + +void CUniqBlocks::GetReverseMap() +{ + unsigned num = Sorted.Size(); + BufIndexToSortedIndex.ClearAndSetSize(num); + int *p = &BufIndexToSortedIndex[0]; + unsigned i; + for (i = 0; i < num; i++) + p[i] = 0; + for (i = 0; i < num; i++) + p[Sorted[i]] = i; +} diff --git a/src/libs/7zip/unix/CPP/7zip/Common/UniqBlocks.h b/src/libs/7zip/unix/CPP/7zip/Common/UniqBlocks.h new file mode 100644 index 000000000..9c08b09f4 --- /dev/null +++ b/src/libs/7zip/unix/CPP/7zip/Common/UniqBlocks.h @@ -0,0 +1,30 @@ +// UniqBlocks.h + +#ifndef __UNIQ_BLOCKS_H +#define __UNIQ_BLOCKS_H + +#include "../../Common/MyTypes.h" +#include "../../Common/MyBuffer.h" +#include "../../Common/MyVector.h" + +struct CUniqBlocks +{ + CObjectVector Bufs; + CIntVector Sorted; + CIntVector BufIndexToSortedIndex; + + int AddUniq(const Byte *data, size_t size); + UInt64 GetTotalSizeInBytes() const; + void GetReverseMap(); + + bool IsOnlyEmpty() const + { + if (Bufs.Size() == 0) + return true; + if (Bufs.Size() > 1) + return false; + return Bufs[0].Size() == 0; + } +}; + +#endif diff --git a/src/libs/7zip/unix/CPP/7zip/Common/VirtThread.cpp b/src/libs/7zip/unix/CPP/7zip/Common/VirtThread.cpp index cf39bd023..77e3c1acf 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/VirtThread.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Common/VirtThread.cpp @@ -10,7 +10,7 @@ static THREAD_FUNC_DECL CoderThread(void *p) { CVirtThread *t = (CVirtThread *)p; t->StartEvent.Lock(); - if (t->ExitEvent) + if (t->Exit) return 0; t->Execute(); t->FinishedEvent.Set(); @@ -23,7 +23,7 @@ WRes CVirtThread::Create() RINOK(FinishedEvent.CreateIfNotCreated()); StartEvent.Reset(); FinishedEvent.Reset(); - ExitEvent = false; + Exit = false; if (Thread.IsCreated()) return S_OK; return Thread.Create(CoderThread, this); @@ -31,16 +31,18 @@ WRes CVirtThread::Create() void CVirtThread::Start() { - ExitEvent = false; + Exit = false; StartEvent.Set(); } -CVirtThread::~CVirtThread() +void CVirtThread::WaitThreadFinish() { - ExitEvent = true; + Exit = true; if (StartEvent.IsCreated()) StartEvent.Set(); if (Thread.IsCreated()) + { Thread.Wait(); + Thread.Close(); + } } - diff --git a/src/libs/7zip/unix/CPP/7zip/Common/VirtThread.h b/src/libs/7zip/unix/CPP/7zip/Common/VirtThread.h index f14a1f223..ebee158ca 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/VirtThread.h +++ b/src/libs/7zip/unix/CPP/7zip/Common/VirtThread.h @@ -1,7 +1,7 @@ // VirtThread.h -#ifndef __VIRTTHREAD_H -#define __VIRTTHREAD_H +#ifndef __VIRT_THREAD_H +#define __VIRT_THREAD_H #include "../../Windows/Synchronization.h" #include "../../Windows/Thread.h" @@ -11,13 +11,14 @@ struct CVirtThread NWindows::NSynchronization::CAutoResetEvent StartEvent; NWindows::NSynchronization::CAutoResetEvent FinishedEvent; NWindows::CThread Thread; - bool ExitEvent; + bool Exit; - ~CVirtThread(); + ~CVirtThread() { WaitThreadFinish(); } + void WaitThreadFinish(); // call it in destructor of child class ! WRes Create(); void Start(); - void WaitFinish() { FinishedEvent.Lock(); } virtual void Execute() = 0; + void WaitExecuteFinish() { FinishedEvent.Lock(); } }; #endif diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/Bcj2Coder.cpp b/src/libs/7zip/unix/CPP/7zip/Compress/Bcj2Coder.cpp index 684da5abf..9da6b9c28 100644 --- a/src/libs/7zip/unix/CPP/7zip/Compress/Bcj2Coder.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Compress/Bcj2Coder.cpp @@ -15,35 +15,22 @@ inline unsigned GetIndex(Byte b0, Byte b1) { return ((b1 == 0xE8) ? b0 : ((b1 == #ifndef EXTRACT_ONLY -static const int kBufferSize = 1 << 17; +static const unsigned kBufSize = 1 << 17; -static bool inline Test86MSByte(Byte b) -{ - return (b == 0 || b == 0xFF); -} +#define NUM_BITS 2 +#define SIGN_BIT (1 << NUM_BITS) +#define MASK_HIGH (0x100 - (1 << (NUM_BITS + 1))) -bool CEncoder::Create() +static const UInt32 kDefaultLimit = (1 << (24 + NUM_BITS)); + +static bool inline Test86MSByte(Byte b) { - if (!_mainStream.Create(1 << 18)) - return false; - if (!_callStream.Create(1 << 18)) - return false; - if (!_jumpStream.Create(1 << 18)) - return false; - if (!_rangeEncoder.Create(1 << 20)) - return false; - if (_buffer == 0) - { - _buffer = (Byte *)MidAlloc(kBufferSize); - if (_buffer == 0) - return false; - } - return true; + return (((b) + SIGN_BIT) & MASK_HIGH) == 0; } CEncoder::~CEncoder() { - ::MidFree(_buffer); + ::MidFree(_buf); } HRESULT CEncoder::Flush() @@ -51,12 +38,10 @@ HRESULT CEncoder::Flush() RINOK(_mainStream.Flush()); RINOK(_callStream.Flush()); RINOK(_jumpStream.Flush()); - _rangeEncoder.FlushData(); - return _rangeEncoder.FlushStream(); + _rc.FlushData(); + return _rc.FlushStream(); } -const UInt32 kDefaultLimit = (1 << 24); - HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) @@ -64,32 +49,34 @@ HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSiz if (numInStreams != 1 || numOutStreams != 4) return E_INVALIDARG; - if (!Create()) - return E_OUTOFMEMORY; + if (!_mainStream.Create(1 << 18)) return E_OUTOFMEMORY; + if (!_callStream.Create(1 << 18)) return E_OUTOFMEMORY; + if (!_jumpStream.Create(1 << 18)) return E_OUTOFMEMORY; + if (!_rc.Create(1 << 20)) return E_OUTOFMEMORY; + if (_buf == 0) + { + _buf = (Byte *)MidAlloc(kBufSize); + if (_buf == 0) + return E_OUTOFMEMORY; + } bool sizeIsDefined = false; UInt64 inSize = 0; - if (inSizes != NULL) - if (inSizes[0] != NULL) + if (inSizes) + if (inSizes[0]) { inSize = *inSizes[0]; if (inSize <= kDefaultLimit) sizeIsDefined = true; } - CCoderReleaser releaser(this); - ISequentialInStream *inStream = inStreams[0]; - _mainStream.SetStream(outStreams[0]); - _mainStream.Init(); - _callStream.SetStream(outStreams[1]); - _callStream.Init(); - _jumpStream.SetStream(outStreams[2]); - _jumpStream.Init(); - _rangeEncoder.SetStream(outStreams[3]); - _rangeEncoder.Init(); - for (int i = 0; i < 256 + 2; i++) + _mainStream.SetStream(outStreams[0]); _mainStream.Init(); + _callStream.SetStream(outStreams[1]); _callStream.Init(); + _jumpStream.SetStream(outStreams[2]); _jumpStream.Init(); + _rc.SetStream(outStreams[3]); _rc.Init(); + for (unsigned i = 0; i < 256 + 2; i++) _statusEncoder[i].Init(); CMyComPtr getSubStreamSize; @@ -99,12 +86,12 @@ HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSiz UInt32 nowPos = 0; UInt64 nowPos64 = 0; - UInt32 bufferPos = 0; + UInt32 bufPos = 0; Byte prevByte = 0; UInt64 subStreamIndex = 0; - UInt64 subStreamStartPos = 0; + UInt64 subStreamStartPos = 0; UInt64 subStreamEndPos = 0; for (;;) @@ -112,23 +99,23 @@ HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSiz UInt32 processedSize = 0; for (;;) { - UInt32 size = kBufferSize - (bufferPos + processedSize); + UInt32 size = kBufSize - (bufPos + processedSize); UInt32 processedSizeLoc; if (size == 0) break; - RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc)); + RINOK(inStream->Read(_buf + bufPos + processedSize, size, &processedSizeLoc)); if (processedSizeLoc == 0) break; processedSize += processedSizeLoc; } - UInt32 endPos = bufferPos + processedSize; - + UInt32 endPos = bufPos + processedSize; + if (endPos < 5) { // change it - for (bufferPos = 0; bufferPos < endPos; bufferPos++) + for (bufPos = 0; bufPos < endPos; bufPos++) { - Byte b = _buffer[bufferPos]; + Byte b = _buf[bufPos]; _mainStream.WriteByte(b); UInt32 index; if (b == 0xE8) @@ -142,37 +129,37 @@ HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSiz prevByte = b; continue; } - _statusEncoder[index].Encode(&_rangeEncoder, 0); + _statusEncoder[index].Encode(&_rc, 0); prevByte = b; } return Flush(); } - bufferPos = 0; + bufPos = 0; UInt32 limit = endPos - 5; - while(bufferPos <= limit) + while (bufPos <= limit) { - Byte b = _buffer[bufferPos]; + Byte b = _buf[bufPos]; _mainStream.WriteByte(b); if (!IsJ(prevByte, b)) { - bufferPos++; + bufPos++; prevByte = b; continue; } - Byte nextByte = _buffer[bufferPos + 4]; + Byte nextByte = _buf[bufPos + 4]; UInt32 src = (UInt32(nextByte) << 24) | - (UInt32(_buffer[bufferPos + 3]) << 16) | - (UInt32(_buffer[bufferPos + 2]) << 8) | - (_buffer[bufferPos + 1]); - UInt32 dest = (nowPos + bufferPos + 5) + src; + (UInt32(_buf[bufPos + 3]) << 16) | + (UInt32(_buf[bufPos + 2]) << 8) | + (_buf[bufPos + 1]); + UInt32 dest = (nowPos + bufPos + 5) + src; // if (Test86MSByte(nextByte)) bool convert; - if (getSubStreamSize != NULL) + if (getSubStreamSize) { - UInt64 currentPos = (nowPos64 + bufferPos); + UInt64 currentPos = (nowPos64 + bufPos); while (subStreamEndPos < currentPos) { UInt64 subStreamSize; @@ -214,8 +201,8 @@ HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSiz unsigned index = GetIndex(prevByte, b); if (convert) { - _statusEncoder[index].Encode(&_rangeEncoder, 1); - bufferPos += 5; + _statusEncoder[index].Encode(&_rc, 1); + bufPos += 5; COutBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; for (int i = 24; i >= 0; i -= 8) s.WriteByte((Byte)(dest >> i)); @@ -223,30 +210,30 @@ HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSiz } else { - _statusEncoder[index].Encode(&_rangeEncoder, 0); - bufferPos++; + _statusEncoder[index].Encode(&_rc, 0); + bufPos++; prevByte = b; } } - nowPos += bufferPos; - nowPos64 += bufferPos; + nowPos += bufPos; + nowPos64 += bufPos; - if (progress != NULL) + if (progress) { /* const UInt64 compressedSize = _mainStream.GetProcessedSize() + _callStream.GetProcessedSize() + _jumpStream.GetProcessedSize() + - _rangeEncoder.GetProcessedSize(); + _rc.GetProcessedSize(); */ RINOK(progress->SetRatioInfo(&nowPos64, NULL)); } - + UInt32 i = 0; - while(bufferPos < endPos) - _buffer[i++] = _buffer[bufferPos++]; - bufferPos = i; + while (bufPos < endPos) + _buf[i++] = _buf[bufPos++]; + bufPos = i; } } @@ -284,46 +271,39 @@ HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams, const UInt64 ** /* i if (numInStreams != 4 || numOutStreams != 1) return E_INVALIDARG; - if (!_mainInStream.Create(_inBufSizes[0])) - return E_OUTOFMEMORY; - if (!_callStream.Create(_inBufSizes[1])) - return E_OUTOFMEMORY; - if (!_jumpStream.Create(_inBufSizes[2])) - return E_OUTOFMEMORY; - if (!_rangeDecoder.Create(_inBufSizes[3])) - return E_OUTOFMEMORY; - if (!_outStream.Create(_outBufSize)) - return E_OUTOFMEMORY; - - CCoderReleaser releaser(this); + if (!_mainStream.Create(_inBufSizes[0])) return E_OUTOFMEMORY; + if (!_callStream.Create(_inBufSizes[1])) return E_OUTOFMEMORY; + if (!_jumpStream.Create(_inBufSizes[2])) return E_OUTOFMEMORY; + if (!_rc.Create(_inBufSizes[3])) return E_OUTOFMEMORY; + if (!_outStream.Create(_outBufSize)) return E_OUTOFMEMORY; - _mainInStream.SetStream(inStreams[0]); + _mainStream.SetStream(inStreams[0]); _callStream.SetStream(inStreams[1]); _jumpStream.SetStream(inStreams[2]); - _rangeDecoder.SetStream(inStreams[3]); + _rc.SetStream(inStreams[3]); _outStream.SetStream(outStreams[0]); - _mainInStream.Init(); + _mainStream.Init(); _callStream.Init(); _jumpStream.Init(); - _rangeDecoder.Init(); + _rc.Init(); _outStream.Init(); - for (int i = 0; i < 256 + 2; i++) + for (unsigned i = 0; i < 256 + 2; i++) _statusDecoder[i].Init(); Byte prevByte = 0; UInt32 processedBytes = 0; for (;;) { - if (processedBytes >= (1 << 20) && progress != NULL) + if (processedBytes >= (1 << 20) && progress) { /* const UInt64 compressedSize = - _mainInStream.GetProcessedSize() + + _mainStream.GetProcessedSize() + _callStream.GetProcessedSize() + _jumpStream.GetProcessedSize() + - _rangeDecoder.GetProcessedSize(); + _rc.GetProcessedSize(); */ const UInt64 nowPos64 = _outStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(NULL, &nowPos64)); @@ -334,8 +314,8 @@ HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams, const UInt64 ** /* i const UInt32 kBurstSize = (1 << 18); for (i = 0; i < kBurstSize; i++) { - if (!_mainInStream.ReadByte(b)) - return Flush(); + if (!_mainStream.ReadByte(b)) + return _outStream.Flush(); _outStream.WriteByte(b); if (IsJ(prevByte, b)) break; @@ -345,14 +325,14 @@ HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams, const UInt64 ** /* i if (i == kBurstSize) continue; unsigned index = GetIndex(prevByte, b); - if (_statusDecoder[index].Decode(&_rangeDecoder) == 1) + if (_statusDecoder[index].Decode(&_rc) == 1) { UInt32 src = 0; CInBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; - for (int i = 0; i < 4; i++) + for (unsigned i = 0; i < 4; i++) { Byte b0; - if(!s.ReadByte(b0)) + if (!s.ReadByte(b0)) return S_FALSE; src <<= 8; src |= ((UInt32)b0); diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/Bcj2Coder.h b/src/libs/7zip/unix/CPP/7zip/Compress/Bcj2Coder.h index 79a713f17..e7bd37951 100644 --- a/src/libs/7zip/unix/CPP/7zip/Compress/Bcj2Coder.h +++ b/src/libs/7zip/unix/CPP/7zip/Compress/Bcj2Coder.h @@ -12,7 +12,7 @@ namespace NCompress { namespace NBcj2 { -const int kNumMoveBits = 5; +const unsigned kNumMoveBits = 5; #ifndef EXTRACT_ONLY @@ -20,32 +20,15 @@ class CEncoder: public ICompressCoder2, public CMyUnknownImp { - Byte *_buffer; - bool Create(); + Byte *_buf; COutBuffer _mainStream; COutBuffer _callStream; COutBuffer _jumpStream; - NCompress::NRangeCoder::CEncoder _rangeEncoder; - NCompress::NRangeCoder::CBitEncoder _statusEncoder[256 + 2]; + NRangeCoder::CEncoder _rc; + NRangeCoder::CBitEncoder _statusEncoder[256 + 2]; HRESULT Flush(); -public: - void ReleaseStreams() - { - _mainStream.ReleaseStream(); - _callStream.ReleaseStream(); - _jumpStream.ReleaseStream(); - _rangeEncoder.ReleaseStream(); - } - - class CCoderReleaser - { - CEncoder *_coder; - public: - CCoderReleaser(CEncoder *coder): _coder(coder) {} - ~CCoderReleaser() { _coder->ReleaseStreams(); } - }; public: MY_UNKNOWN_IMP @@ -56,7 +39,8 @@ public: STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); - CEncoder(): _buffer(0) {}; + + CEncoder(): _buf(0) {}; ~CEncoder(); }; @@ -67,37 +51,19 @@ class CDecoder: public ICompressSetBufSize, public CMyUnknownImp { - CInBuffer _mainInStream; + CInBuffer _mainStream; CInBuffer _callStream; CInBuffer _jumpStream; - NCompress::NRangeCoder::CDecoder _rangeDecoder; - NCompress::NRangeCoder::CBitDecoder _statusDecoder[256 + 2]; + NRangeCoder::CDecoder _rc; + NRangeCoder::CBitDecoder _statusDecoder[256 + 2]; COutBuffer _outStream; UInt32 _inBufSizes[4]; UInt32 _outBufSize; -public: - void ReleaseStreams() - { - _mainInStream.ReleaseStream(); - _callStream.ReleaseStream(); - _jumpStream.ReleaseStream(); - _rangeDecoder.ReleaseStream(); - _outStream.ReleaseStream(); - } - - HRESULT Flush() { return _outStream.Flush(); } - class CCoderReleaser - { - CDecoder *_coder; - public: - CCoderReleaser(CDecoder *coder): _coder(coder) {} - ~CCoderReleaser() { _coder->ReleaseStreams(); } - }; - public: MY_UNKNOWN_IMP1(ICompressSetBufSize); + HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); @@ -107,6 +73,7 @@ public: STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size); STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size); + CDecoder(); }; diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/BranchMisc.cpp b/src/libs/7zip/unix/CPP/7zip/Compress/BranchMisc.cpp index 423b723ab..239f25138 100644 --- a/src/libs/7zip/unix/CPP/7zip/Compress/BranchMisc.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Compress/BranchMisc.cpp @@ -6,32 +6,16 @@ #include "BranchMisc.h" -UInt32 CBC_ARM_Encoder::SubFilter(Byte *data, UInt32 size) - { return (UInt32)::ARM_Convert(data, size, _bufferPos, 1); } - -UInt32 CBC_ARM_Decoder::SubFilter(Byte *data, UInt32 size) - { return (UInt32)::ARM_Convert(data, size, _bufferPos, 0); } - -UInt32 CBC_ARMT_Encoder::SubFilter(Byte *data, UInt32 size) - { return (UInt32)::ARMT_Convert(data, size, _bufferPos, 1); } - -UInt32 CBC_ARMT_Decoder::SubFilter(Byte *data, UInt32 size) - { return (UInt32)::ARMT_Convert(data, size, _bufferPos, 0); } - -UInt32 CBC_PPC_Encoder::SubFilter(Byte *data, UInt32 size) - { return (UInt32)::PPC_Convert(data, size, _bufferPos, 1); } - -UInt32 CBC_PPC_Decoder::SubFilter(Byte *data, UInt32 size) - { return (UInt32)::PPC_Convert(data, size, _bufferPos, 0); } - -UInt32 CBC_SPARC_Encoder::SubFilter(Byte *data, UInt32 size) - { return (UInt32)::SPARC_Convert(data, size, _bufferPos, 1); } - -UInt32 CBC_SPARC_Decoder::SubFilter(Byte *data, UInt32 size) - { return (UInt32)::SPARC_Convert(data, size, _bufferPos, 0); } - -UInt32 CBC_IA64_Encoder::SubFilter(Byte *data, UInt32 size) - { return (UInt32)::IA64_Convert(data, size, _bufferPos, 1); } - -UInt32 CBC_IA64_Decoder::SubFilter(Byte *data, UInt32 size) - { return (UInt32)::IA64_Convert(data, size, _bufferPos, 0); } +#define SUB_FILTER_IMP2(name, coderStr, coderNum) \ + UInt32 CBC_ ## name ## coderStr::SubFilter(Byte *data, UInt32 size) \ + { return (UInt32)::name ## Convert(data, size, _bufferPos, coderNum); } + +#define SUB_FILTER_IMP(name) \ + SUB_FILTER_IMP2(name, Encoder, 1) \ + SUB_FILTER_IMP2(name, Decoder, 0) \ + +SUB_FILTER_IMP(ARM_) +SUB_FILTER_IMP(ARMT_) +SUB_FILTER_IMP(PPC_) +SUB_FILTER_IMP(SPARC_) +SUB_FILTER_IMP(IA64_) diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/CodecExports.cpp b/src/libs/7zip/unix/CPP/7zip/Compress/CodecExports.cpp deleted file mode 100644 index 4ff1c0fcb..000000000 --- a/src/libs/7zip/unix/CPP/7zip/Compress/CodecExports.cpp +++ /dev/null @@ -1,160 +0,0 @@ -// CodecExports.cpp - -#include "StdAfx.h" - -#include "../../Common/ComTry.h" - -#include "../../Windows/PropVariant.h" - -#include "../ICoder.h" - -#include "../Common/RegisterCodec.h" - -extern unsigned int g_NumCodecs; -extern const CCodecInfo *g_Codecs[]; - -static const UInt16 kDecodeId = 0x2790; - -DEFINE_GUID(CLSID_CCodec, -0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - -static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value) -{ - if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) - value->vt = VT_BSTR; - return S_OK; -} - -static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) -{ - return SetPropString((const char *)&guid, sizeof(GUID), value); -} - -static HRESULT SetClassID(CMethodId id, bool encode, PROPVARIANT *value) -{ - GUID clsId = CLSID_CCodec; - for (int i = 0; i < sizeof(id); i++, id >>= 8) - clsId.Data4[i] = (Byte)(id & 0xFF); - if (encode) - clsId.Data3++; - return SetPropGUID(clsId, value); -} - -static HRESULT FindCodecClassId(const GUID *clsID, UInt32 isCoder2, bool isFilter, bool &encode, int &index) -{ - index = -1; - if (clsID->Data1 != CLSID_CCodec.Data1 || - clsID->Data2 != CLSID_CCodec.Data2 || - (clsID->Data3 & ~1) != kDecodeId) - return S_OK; - encode = (clsID->Data3 != kDecodeId); - UInt64 id = 0; - for (int j = 0; j < 8; j++) - id |= ((UInt64)clsID->Data4[j]) << (8 * j); - for (unsigned i = 0; i < g_NumCodecs; i++) - { - const CCodecInfo &codec = *g_Codecs[i]; - if (id != codec.Id || encode && !codec.CreateEncoder || !encode && !codec.CreateDecoder) - continue; - if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter || - codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2) - return E_NOINTERFACE; - index = i; - return S_OK; - } - return S_OK; -} - -STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject) -{ - COM_TRY_BEGIN - *outObject = 0; - bool isCoder = (*iid == IID_ICompressCoder) != 0; - bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; - bool isFilter = (*iid == IID_ICompressFilter) != 0; - const CCodecInfo &codec = *g_Codecs[index]; - if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter || - codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2) - return E_NOINTERFACE; - if (encode) - { - if (!codec.CreateEncoder) - return CLASS_E_CLASSNOTAVAILABLE; - *outObject = codec.CreateEncoder(); - } - else - { - if (!codec.CreateDecoder) - return CLASS_E_CLASSNOTAVAILABLE; - *outObject = codec.CreateDecoder(); - } - if (isCoder) - ((ICompressCoder *)*outObject)->AddRef(); - else if (isCoder2) - ((ICompressCoder2 *)*outObject)->AddRef(); - else - ((ICompressFilter *)*outObject)->AddRef(); - return S_OK; - COM_TRY_END -} - -STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject) -{ - *outObject = 0; - bool isCoder = (*iid == IID_ICompressCoder) != 0; - bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; - bool isFilter = (*iid == IID_ICompressFilter) != 0; - if (!isCoder && !isCoder2 && !isFilter) - return E_NOINTERFACE; - bool encode; - int codecIndex; - HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex); - if (res != S_OK) - return res; - if (codecIndex < 0) - return CLASS_E_CLASSNOTAVAILABLE; - return CreateCoder2(encode, codecIndex, iid, outObject); -} - -STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value) -{ - ::VariantClear((VARIANTARG *)value); - const CCodecInfo &codec = *g_Codecs[codecIndex]; - switch(propID) - { - case NMethodPropID::kID: - { - value->uhVal.QuadPart = (UInt64)codec.Id; - value->vt = VT_UI8; - break; - } - case NMethodPropID::kName: - if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0) - value->vt = VT_BSTR; - break; - case NMethodPropID::kDecoder: - if (codec.CreateDecoder) - return SetClassID(codec.Id, false, value); - break; - case NMethodPropID::kEncoder: - if (codec.CreateEncoder) - return SetClassID(codec.Id, true, value); - break; - case NMethodPropID::kInStreams: - { - if (codec.NumInStreams != 1) - { - value->vt = VT_UI4; - value->ulVal = (ULONG)codec.NumInStreams; - } - break; - } - } - return S_OK; -} - -STDAPI GetNumberOfMethods(UINT32 *numCodecs) -{ - *numCodecs = g_NumCodecs; - return S_OK; -} diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/Compress.pri b/src/libs/7zip/unix/CPP/7zip/Compress/Compress.pri new file mode 100644 index 000000000..c9a7a5045 --- /dev/null +++ b/src/libs/7zip/unix/CPP/7zip/Compress/Compress.pri @@ -0,0 +1,29 @@ +HEADERS += $$7ZIP_BASE/CPP/7zip/Compress/Bcj2Coder.h \ + $$7ZIP_BASE/CPP/7zip/Compress/BcjCoder.h \ + $$7ZIP_BASE/CPP/7zip/Compress/BranchCoder.h \ + $$7ZIP_BASE/CPP/7zip/Compress/BranchMisc.h \ + $$7ZIP_BASE/CPP/7zip/Compress/CopyCoder.h \ + $$7ZIP_BASE/CPP/7zip/Compress/Lzma2Decoder.h \ + $$7ZIP_BASE/CPP/7zip/Compress/Lzma2Encoder.h \ + $$7ZIP_BASE/CPP/7zip/Compress/LzmaDecoder.h \ + $$7ZIP_BASE/CPP/7zip/Compress/LzmaEncoder.h \ + $$7ZIP_BASE/CPP/7zip/Compress/RangeCoder.h \ + $$7ZIP_BASE/CPP/7zip/Compress/RangeCoderBit.h + +SOURCES += $$7ZIP_BASE/CPP/7zip/Compress/Bcj2Coder.cpp \ + $$7ZIP_BASE/CPP/7zip/Compress/Bcj2Register.cpp \ + $$7ZIP_BASE/CPP/7zip/Compress/BcjCoder.cpp \ + $$7ZIP_BASE/CPP/7zip/Compress/BcjRegister.cpp \ + $$7ZIP_BASE/CPP/7zip/Compress/BranchCoder.cpp \ + $$7ZIP_BASE/CPP/7zip/Compress/BranchMisc.cpp \ + $$7ZIP_BASE/CPP/7zip/Compress/BranchRegister.cpp \ + $$7ZIP_BASE/CPP/7zip/Compress/ByteSwap.cpp \ + $$7ZIP_BASE/CPP/7zip/Compress/CopyCoder.cpp \ + $$7ZIP_BASE/CPP/7zip/Compress/CopyRegister.cpp \ + $$7ZIP_BASE/CPP/7zip/Compress/DeltaFilter.cpp \ + $$7ZIP_BASE/CPP/7zip/Compress/Lzma2Decoder.cpp \ + $$7ZIP_BASE/CPP/7zip/Compress/Lzma2Encoder.cpp \ + $$7ZIP_BASE/CPP/7zip/Compress/Lzma2Register.cpp \ + $$7ZIP_BASE/CPP/7zip/Compress/LzmaDecoder.cpp \ + $$7ZIP_BASE/CPP/7zip/Compress/LzmaEncoder.cpp \ + $$7ZIP_BASE/CPP/7zip/Compress/LzmaRegister.cpp diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/CopyCoder.cpp b/src/libs/7zip/unix/CPP/7zip/Compress/CopyCoder.cpp index f71692a77..f0863202a 100644 --- a/src/libs/7zip/unix/CPP/7zip/Compress/CopyCoder.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Compress/CopyCoder.cpp @@ -22,10 +22,10 @@ STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { - if (_buffer == 0) + if (!_buffer) { _buffer = (Byte *)::MidAlloc(kBufferSize); - if (_buffer == 0) + if (!_buffer) return E_OUTOFMEMORY; } @@ -33,9 +33,8 @@ STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, for (;;) { UInt32 size = kBufferSize; - if (outSize != 0) - if (size > *outSize - TotalSize) - size = (UInt32)(*outSize - TotalSize); + if (outSize && size > *outSize - TotalSize) + size = (UInt32)(*outSize - TotalSize); RINOK(inStream->Read(_buffer, size, &size)); if (size == 0) break; @@ -44,7 +43,7 @@ STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, RINOK(WriteStream(outStream, _buffer, size)); } TotalSize += size; - if (progress != NULL) + if (progress) { RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize)); } @@ -60,8 +59,16 @@ STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value) HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress) { - CMyComPtr copyCoder = new NCompress::CCopyCoder; + CMyComPtr copyCoder = new CCopyCoder; return copyCoder->Code(inStream, outStream, NULL, NULL, progress); } +HRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress) +{ + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; + CMyComPtr copyCoder = copyCoderSpec; + RINOK(copyCoder->Code(inStream, outStream, NULL, &size, progress)); + return copyCoderSpec->TotalSize == size ? S_OK : E_FAIL; +} + } diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/CopyCoder.h b/src/libs/7zip/unix/CPP/7zip/Compress/CopyCoder.h index c5445ccf8..5e0bb6436 100644 --- a/src/libs/7zip/unix/CPP/7zip/Compress/CopyCoder.h +++ b/src/libs/7zip/unix/CPP/7zip/Compress/CopyCoder.h @@ -28,6 +28,7 @@ public: }; HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress); +HRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress); } diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/DeltaFilter.cpp b/src/libs/7zip/unix/CPP/7zip/Compress/DeltaFilter.cpp index 2e421acf4..d8378a60e 100644 --- a/src/libs/7zip/unix/CPP/7zip/Compress/DeltaFilter.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Compress/DeltaFilter.cpp @@ -62,9 +62,22 @@ STDMETHODIMP CDeltaEncoder::SetCoderProperties(const PROPID *propIDs, const PROP for (UInt32 i = 0; i < numProps; i++) { const PROPVARIANT &prop = props[i]; - if (propIDs[i] != NCoderPropID::kDefaultProp || prop.vt != VT_UI4 || prop.ulVal < 1 || prop.ulVal > 256) + PROPID propID = propIDs[i]; + if (propID >= NCoderPropID::kReduceSize) + continue; + if (prop.vt != VT_UI4) return E_INVALIDARG; - delta = prop.ulVal; + switch (propID) + { + case NCoderPropID::kDefaultProp: + delta = (UInt32)prop.ulVal; + if (delta < 1 || delta > 256) + return E_INVALIDARG; + break; + case NCoderPropID::kNumThreads: break; + case NCoderPropID::kLevel: break; + default: return E_INVALIDARG; + } } _delta = delta; return S_OK; diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Decoder.cpp b/src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Decoder.cpp index 322015e29..b20ae5f5e 100644 --- a/src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Decoder.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Decoder.cpp @@ -66,7 +66,7 @@ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) _outSize = *outSize; Lzma2Dec_Init(&_state); - + _inPos = _inSize = 0; _inSizeProcessed = _outSizeProcessed = 0; return S_OK; @@ -93,7 +93,7 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, const UInt32 kStepSize = ((UInt32)1 << 22); if (curSize > kStepSize) curSize = (SizeT)kStepSize; - + ELzmaFinishMode finishMode = LZMA_FINISH_ANY; if (_outSizeDefined) { diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Encoder.cpp b/src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Encoder.cpp index 5e4c71bea..f867881c0 100644 --- a/src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Encoder.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Encoder.cpp @@ -90,5 +90,5 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream return progressWrap.Res; return SResToHRESULT(res); } - + }} diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Encoder.h b/src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Encoder.h index f0fb74d33..6a2318076 100644 --- a/src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Encoder.h +++ b/src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Encoder.h @@ -21,7 +21,7 @@ class CEncoder: CLzma2EncHandle _encoder; public: MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties) - + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/LzmaDecoder.cpp b/src/libs/7zip/unix/CPP/7zip/Compress/LzmaDecoder.cpp index b7c260bd9..d378ba668 100644 --- a/src/libs/7zip/unix/CPP/7zip/Compress/LzmaDecoder.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Compress/LzmaDecoder.cpp @@ -27,7 +27,8 @@ namespace NLzma { CDecoder::CDecoder(): _inBuf(0), _propsWereSet(false), _outSizeDefined(false), _inBufSize(1 << 20), _outBufSize(1 << 22), - FinishStream(false) + FinishStream(false), + NeedMoreInput(false) { _inSizeProcessed = 0; _inPos = _inSize = 0; @@ -81,6 +82,7 @@ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { _inSizeProcessed = 0; _inPos = _inSize = 0; + NeedMoreInput = false; SetOutStreamSizeResume(outSize); return S_OK; } @@ -103,7 +105,7 @@ HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream * SizeT dicPos = _state.dicPos; SizeT curSize = next - dicPos; - + ELzmaFinishMode finishMode = LZMA_FINISH_ANY; if (_outSizeDefined) { @@ -144,9 +146,21 @@ HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream * return S_FALSE; RINOK(res2); if (stopDecoding) + { + if (status == LZMA_STATUS_NEEDS_MORE_INPUT) + NeedMoreInput = true; + if (FinishStream && + status != LZMA_STATUS_FINISHED_WITH_MARK && + status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) + return S_FALSE; return S_OK; + } if (finished) + { + if (status == LZMA_STATUS_NEEDS_MORE_INPUT) + NeedMoreInput = true; return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE); + } } if (progress) { diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/LzmaDecoder.h b/src/libs/7zip/unix/CPP/7zip/Compress/LzmaDecoder.h index d28a4634b..140c48b9c 100644 --- a/src/libs/7zip/unix/CPP/7zip/Compress/LzmaDecoder.h +++ b/src/libs/7zip/unix/CPP/7zip/Compress/LzmaDecoder.h @@ -62,7 +62,7 @@ public: STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size); #ifndef NO_READ_FROM_CODER - + STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); @@ -73,10 +73,14 @@ public: #endif - bool FinishStream; + bool FinishStream; // set it before decoding, if you need to decode full LZMA stream + + bool NeedMoreInput; // it's set by decoder, if it needs more input data to decode stream CDecoder(); virtual ~CDecoder(); + + UInt64 GetOutputProcessedSize() const { return _outSizeProcessed; } }; }} diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/LzmaEncoder.cpp b/src/libs/7zip/unix/CPP/7zip/Compress/LzmaEncoder.cpp index 9bdedaeb6..484d04523 100644 --- a/src/libs/7zip/unix/CPP/7zip/Compress/LzmaEncoder.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Compress/LzmaEncoder.cpp @@ -73,6 +73,8 @@ static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes) return 1; } +#define SET_PROP_32(_id_, _dest_) case NCoderPropID::_id_: ep._dest_ = v; break; + HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep) { if (propID == NCoderPropID::kMatchFinder) @@ -81,18 +83,29 @@ HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep) return E_INVALIDARG; return ParseMatchFinder(prop.bstrVal, &ep.btMode, &ep.numHashBytes) ? S_OK : E_INVALIDARG; } + if (propID > NCoderPropID::kReduceSize) + return S_OK; + if (propID == NCoderPropID::kReduceSize) + { + if (prop.vt == VT_UI8) + ep.reduceSize = prop.uhVal.QuadPart; + return S_OK; + } if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 v = prop.ulVal; switch (propID) { - case NCoderPropID::kNumFastBytes: ep.fb = v; break; - case NCoderPropID::kMatchFinderCycles: ep.mc = v; break; - case NCoderPropID::kAlgorithm: ep.algo = v; break; - case NCoderPropID::kDictionarySize: ep.dictSize = v; break; - case NCoderPropID::kPosStateBits: ep.pb = v; break; - case NCoderPropID::kLitPosBits: ep.lp = v; break; - case NCoderPropID::kLitContextBits: ep.lc = v; break; + case NCoderPropID::kDefaultProp: if (v > 31) return E_INVALIDARG; ep.dictSize = (UInt32)1 << (unsigned)v; break; + SET_PROP_32(kLevel, level) + SET_PROP_32(kNumFastBytes, fb) + SET_PROP_32(kMatchFinderCycles, mc) + SET_PROP_32(kAlgorithm, algo) + SET_PROP_32(kDictionarySize, dictSize) + SET_PROP_32(kPosStateBits, pb) + SET_PROP_32(kLitPosBits, lp) + SET_PROP_32(kLitContextBits, lc) + SET_PROP_32(kNumThreads, numThreads) default: return E_INVALIDARG; } return S_OK; @@ -111,9 +124,7 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, switch (propID) { case NCoderPropID::kEndMarker: - if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal == VARIANT_TRUE); break; - case NCoderPropID::kNumThreads: - if (prop.vt != VT_UI4) return E_INVALIDARG; props.numThreads = prop.ulVal; break; + if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal != VARIANT_FALSE); break; default: RINOK(SetLzmaProp(propID, prop, props)); } @@ -137,6 +148,7 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream CCompressProgressWrap progressWrap(progress); SRes res = LzmaEnc_Encode(_encoder, &outWrap.p, &inWrap.p, progress ? &progressWrap.p : NULL, &g_Alloc, &g_BigAlloc); + _inputProcessed = inWrap.Processed; if (res == SZ_ERROR_READ && inWrap.Res != S_OK) return inWrap.Res; if (res == SZ_ERROR_WRITE && outWrap.Res != S_OK) @@ -145,5 +157,5 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream return progressWrap.Res; return SResToHRESULT(res); } - + }} diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/LzmaEncoder.h b/src/libs/7zip/unix/CPP/7zip/Compress/LzmaEncoder.h index 904c0002c..7e15a132d 100644 --- a/src/libs/7zip/unix/CPP/7zip/Compress/LzmaEncoder.h +++ b/src/libs/7zip/unix/CPP/7zip/Compress/LzmaEncoder.h @@ -19,9 +19,10 @@ class CEncoder: public CMyUnknownImp { CLzmaEncHandle _encoder; + UInt64 _inputProcessed; public: MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties) - + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); @@ -29,6 +30,7 @@ public: CEncoder(); virtual ~CEncoder(); + UInt64 GetInputProcessedSize() const { return _inputProcessed; } }; }} diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/RangeCoder.h b/src/libs/7zip/unix/CPP/7zip/Compress/RangeCoder.h index 1eb2a6d47..1555bd705 100644 --- a/src/libs/7zip/unix/CPP/7zip/Compress/RangeCoder.h +++ b/src/libs/7zip/unix/CPP/7zip/Compress/RangeCoder.h @@ -1,5 +1,5 @@ // Compress/RangeCoder.h -// 2009-05-30 : Igor Pavlov : Public domain +// 2013-01-10 : Igor Pavlov : Public domain #ifndef __COMPRESS_RANGE_CODER_H #define __COMPRESS_RANGE_CODER_H @@ -10,7 +10,7 @@ namespace NCompress { namespace NRangeCoder { -const int kNumTopBits = 24; +const unsigned kNumTopBits = 24; const UInt32 kTopValue = (1 << kNumTopBits); class CEncoder @@ -21,7 +21,7 @@ public: UInt64 Low; UInt32 Range; COutBuffer Stream; - bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } + bool Create(UInt32 bufSize) { return Stream.Create(bufSize); } void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); } void Init() @@ -36,14 +36,12 @@ public: void FlushData() { // Low += 1; - for(int i = 0; i < 5; i++) + for (int i = 0; i < 5; i++) ShiftLow(); } HRESULT FlushStream() { return Stream.Flush(); } - void ReleaseStream() { Stream.ReleaseStream(); } - void Encode(UInt32 start, UInt32 size, UInt32 total) { Low += start * (Range /= total); @@ -57,7 +55,7 @@ public: void ShiftLow() { - if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0) + if ((UInt32)Low < (UInt32)0xFF000000 || (unsigned)(Low >> 32) != 0) { Byte temp = _cache; do @@ -65,13 +63,13 @@ public: Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32))); temp = 0xFF; } - while(--_cacheSize != 0); + while (--_cacheSize != 0); _cache = (Byte)((UInt32)Low >> 24); } _cacheSize++; Low = (UInt32)Low << 8; } - + void EncodeDirectBits(UInt32 value, int numBits) { for (numBits--; numBits >= 0; numBits--) @@ -103,7 +101,7 @@ public: } } - UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; } + UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; } }; class CDecoder @@ -112,7 +110,7 @@ public: CInBuffer Stream; UInt32 Range; UInt32 Code; - bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } + bool Create(UInt32 bufSize) { return Stream.Create(bufSize); } void Normalize() { @@ -122,22 +120,20 @@ public: Range <<= 8; } } - + void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Code = 0; Range = 0xFFFFFFFF; - for(int i = 0; i < 5; i++) + for (int i = 0; i < 5; i++) Code = (Code << 8) | Stream.ReadByte(); } - void ReleaseStream() { Stream.ReleaseStream(); } - UInt32 GetThreshold(UInt32 total) { - return (Code) / ( Range /= total); + return (Code) / (Range /= total); } void Decode(UInt32 start, UInt32 size) @@ -197,7 +193,7 @@ public: return symbol; } - UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); } + UInt64 GetProcessedSize() { return Stream.GetProcessedSize(); } }; }} diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/RangeCoderBit.h b/src/libs/7zip/unix/CPP/7zip/Compress/RangeCoderBit.h index b5a1830d6..0eddd5586 100644 --- a/src/libs/7zip/unix/CPP/7zip/Compress/RangeCoderBit.h +++ b/src/libs/7zip/unix/CPP/7zip/Compress/RangeCoderBit.h @@ -1,5 +1,5 @@ // Compress/RangeCoderBit.h -// 2009-05-30 : Igor Pavlov : Public domain +// 2013-01-10 : Igor Pavlov : Public domain #ifndef __COMPRESS_RANGE_CODER_BIT_H #define __COMPRESS_RANGE_CODER_BIT_H @@ -9,17 +9,17 @@ namespace NCompress { namespace NRangeCoder { -const int kNumBitModelTotalBits = 11; +const unsigned kNumBitModelTotalBits = 11; const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); -const int kNumMoveReducingBits = 4; +const unsigned kNumMoveReducingBits = 4; -const int kNumBitPriceShiftBits = 4; +const unsigned kNumBitPriceShiftBits = 4; const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits; extern UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; -template +template class CBitModel { public: @@ -39,7 +39,7 @@ public: void Init() { Prob = kBitModelTotal / 2; } }; -template +template class CBitEncoder: public CBitModel { public: @@ -69,14 +69,14 @@ public: } UInt32 GetPrice(UInt32 symbol) const { - return ProbPrices[(this->Prob ^ ((-(int)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; + return ProbPrices[(this->Prob ^ ((-(int)(Int32)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } UInt32 GetPrice0() const { return ProbPrices[this->Prob >> kNumMoveReducingBits]; } UInt32 GetPrice1() const { return ProbPrices[(this->Prob ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } }; -template +template class CBitDecoder: public CBitModel { public: diff --git a/src/libs/7zip/unix/CPP/7zip/Guid.txt b/src/libs/7zip/unix/CPP/7zip/Guid.txt index 59a743b96..c1e7446be 100644 --- a/src/libs/7zip/unix/CPP/7zip/Guid.txt +++ b/src/libs/7zip/unix/CPP/7zip/Guid.txt @@ -6,14 +6,17 @@ 01 IFolderArchive.h - 05 IArchiveFolder + // 05 IArchiveFolder // old // 06 IInFolderArchive // old 07 IFileExtractCallback.h::IFolderArchiveExtractCallback - 0A IOutFolderArchive + // 0A IOutFolderArchive 0B IFolderArchiveUpdateCallback 0C Agent.h::IArchiveFolderInternal - 0D + 0D IArchiveFolder 0E IInFolderArchive + 0F IOutFolderArchive + 20 IFileExtractCallback.h::IGetProp + 30 IFileExtractCallback.h::IFolderExtractToStreamCallback 03 IStream.h @@ -23,6 +26,8 @@ 04 IOutStream 06 IStreamGetSize 07 IOutStreamFlush + 08 IStreamGetProps + 09 IStreamGetProps2 04 ICoder.h @@ -50,6 +55,8 @@ 8C ICryptoResetInitVector 90 ICryptoSetPassword A0 ICryptoSetCRC + C0 IHasher + C1 IHashers 05 IPassword.h @@ -61,6 +68,8 @@ 06 IArchive.h 03 ISetProperties + 04 IArchiveKeepModeForNextOpen + 05 IArchiveAllowTail 10 IArchiveOpenCallback 20 IArchiveExtractCallback @@ -69,6 +78,8 @@ 50 IArchiveOpenSetSubArchiveName 60 IInArchive 61 IArchiveOpenSeq + 70 IArchiveGetRawProps + 71 IArchiveGetRootProps 80 IArchiveUpdateCallback 82 IArchiveUpdateCallback2 @@ -84,18 +95,23 @@ 03 IFolderGetPath 04 IFolderWasChanged 05 // IFolderReload - 06 IFolderOperations + 06 // IFolderOperations old 07 IFolderGetSystemIconIndex 08 IFolderGetItemFullSize 09 IFolderClone 0A IFolderSetFlatMode 0B IFolderOperationsExtractCallback - 0C // - 0D // + 0C // + 0D // 0E IFolderProperties - 0F + 0F 10 IFolderArcProps 11 IGetFolderArcProps + 12 // IFolderOperations + 13 IFolderOperations + 14 IFolderCalcItemFullSize + 15 IFolderCompare + 16 IFolderGetItemName 09 IFolder.h :: FOLDER_MANAGER_INTERFACE @@ -128,6 +144,11 @@ Handler GUIDs: 0C xz 0D ppmd + CD IHex + CE Hxs + CF TE + D0 UEFIc + D1 UEFIs D2 SquashFS D3 CramFS D4 APM @@ -150,7 +171,7 @@ Handler GUIDs: E5 Compound E6 Wim E7 Iso - E8 Bkf + E8 E9 Chm EA Split EB Rpm @@ -168,3 +189,4 @@ Handler GUIDs: {23170F69-40C1-2790-id} Codec Decoders {23170F69-40C1-2791-id} Codec Encoders +{23170F69-40C1-2792-id} Hashers diff --git a/src/libs/7zip/unix/CPP/7zip/ICoder.h b/src/libs/7zip/unix/CPP/7zip/ICoder.h index a518de463..74ee0e453 100644 --- a/src/libs/7zip/unix/CPP/7zip/ICoder.h +++ b/src/libs/7zip/unix/CPP/7zip/ICoder.h @@ -44,7 +44,9 @@ namespace NCoderPropID kNumPasses, kAlgorithm, kNumThreads, - kEndMarker + kEndMarker, + kLevel, + kReduceSize // estimated size of data that will be compressed. Encoder can use this value to reduce dictionary size. }; } @@ -179,8 +181,31 @@ namespace NMethodPropID kOutStreams, kDescription, kDecoderIsAssigned, - kEncoderIsAssigned + kEncoderIsAssigned, + kDigestSize }; } +CODER_INTERFACE(IHasher, 0xC0) +{ + STDMETHOD_(void, Init)() PURE; + STDMETHOD_(void, Update)(const void *data, UInt32 size) PURE; + STDMETHOD_(void, Final)(Byte *digest) PURE; + STDMETHOD_(UInt32, GetDigestSize)() PURE; +}; + +CODER_INTERFACE(IHashers, 0xC1) +{ + STDMETHOD_(UInt32, GetNumHashers)() PURE; + STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE; + STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher) PURE; +}; + +extern "C" +{ + typedef HRESULT (WINAPI *Func_GetNumberOfMethods)(UInt32 *numMethods); + typedef HRESULT (WINAPI *Func_GetMethodProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); + typedef HRESULT (WINAPI *Func_GetHashers)(IHashers **hashers); +} + #endif diff --git a/src/libs/7zip/unix/CPP/7zip/IPassword.h b/src/libs/7zip/unix/CPP/7zip/IPassword.h index 3ca7b090e..7ea45537e 100644 --- a/src/libs/7zip/unix/CPP/7zip/IPassword.h +++ b/src/libs/7zip/unix/CPP/7zip/IPassword.h @@ -3,8 +3,8 @@ #ifndef __IPASSWORD_H #define __IPASSWORD_H +#include "../Common/MyTypes.h" #include "../Common/MyUnknown.h" -#include "../Common/Types.h" #include "IDecl.h" @@ -21,4 +21,3 @@ PASSWORD_INTERFACE(ICryptoGetTextPassword2, 0x11) }; #endif - diff --git a/src/libs/7zip/unix/CPP/7zip/IProgress.h b/src/libs/7zip/unix/CPP/7zip/IProgress.h index d6093f173..a270e693b 100644 --- a/src/libs/7zip/unix/CPP/7zip/IProgress.h +++ b/src/libs/7zip/unix/CPP/7zip/IProgress.h @@ -3,8 +3,8 @@ #ifndef __IPROGRESS_H #define __IPROGRESS_H +#include "../Common/MyTypes.h" #include "../Common/MyUnknown.h" -#include "../Common/Types.h" #include "IDecl.h" diff --git a/src/libs/7zip/unix/CPP/7zip/IStream.h b/src/libs/7zip/unix/CPP/7zip/IStream.h index 165e8baad..48643e7b3 100644 --- a/src/libs/7zip/unix/CPP/7zip/IStream.h +++ b/src/libs/7zip/unix/CPP/7zip/IStream.h @@ -3,8 +3,8 @@ #ifndef __ISTREAM_H #define __ISTREAM_H +#include "../Common/MyTypes.h" #include "../Common/MyUnknown.h" -#include "../Common/Types.h" #include "IDecl.h" @@ -14,26 +14,71 @@ STREAM_INTERFACE(ISequentialInStream, 0x01) { STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE; + /* - Out: if size != 0, return_value = S_OK and (*processedSize == 0), - then there are no more bytes in stream. - if (size > 0) && there are bytes in stream, - this function must read at least 1 byte. - This function is allowed to read less than number of remaining bytes in stream. - You must call Read function in loop, if you need exact amount of data + The requirement for caller: (processedSize != NULL). + The callee can allow (processedSize == NULL) for compatibility reasons. + + if (size == 0), this function returns S_OK and (*processedSize) is set to 0. + + if (size != 0) + { + Partial read is allowed: (*processedSize <= avail_size && *processedSize <= size), + where (avail_size) is the size of remaining bytes in stream. + If (avail_size != 0), this function must read at least 1 byte: (*processedSize > 0). + You must call Read() in loop, if you need to read exact amount of data. + } + + If seek pointer before Read() call was changed to position past the end of stream: + if (seek_pointer >= stream_size), this function returns S_OK and (*processedSize) is set to 0. + + ERROR CASES: + If the function returns error code, then (*processedSize) is size of + data written to (data) buffer (it can be data before error or data with errors). + The recommended way for callee to work with reading errors: + 1) write part of data before error to (data) buffer and return S_OK. + 2) return error code for further calls of Read(). */ }; STREAM_INTERFACE(ISequentialOutStream, 0x02) { STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE; + /* - if (size > 0) this function must write at least 1 byte. - This function is allowed to write less than "size". - You must call Write function in loop, if you need to write exact amount of data + The requirement for caller: (processedSize != NULL). + The callee can allow (processedSize == NULL) for compatibility reasons. + + if (size != 0) + { + Partial write is allowed: (*processedSize <= size), + but this function must write at least 1 byte: (*processedSize > 0). + You must call Write() in loop, if you need to write exact amount of data. + } + + ERROR CASES: + If the function returns error code, then (*processedSize) is size of + data written from (data) buffer. */ }; +#ifdef __HRESULT_FROM_WIN32 +#define HRESULT_WIN32_ERROR_NEGATIVE_SEEK __HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK) +#else +#define HRESULT_WIN32_ERROR_NEGATIVE_SEEK HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK) +#endif + +/* Seek() Function + If you seek before the beginning of the stream, Seek() function returns error code: + Recommended error code is __HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK). + or STG_E_INVALIDFUNCTION + + It is allowed to seek past the end of the stream. + + + if Seek() returns error, then the value of *newPosition is undefined. +*/ + STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; @@ -55,4 +100,28 @@ STREAM_INTERFACE(IOutStreamFlush, 0x07) STDMETHOD(Flush)() PURE; }; + +STREAM_INTERFACE(IStreamGetProps, 0x08) +{ + STDMETHOD(GetProps)(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib) PURE; +}; + +struct CStreamFileProps +{ + UInt64 Size; + UInt64 VolID; + UInt64 FileID_Low; + UInt64 FileID_High; + UInt32 NumLinks; + UInt32 Attrib; + FILETIME CTime; + FILETIME ATime; + FILETIME MTime; +}; + +STREAM_INTERFACE(IStreamGetProps2, 0x09) +{ + STDMETHOD(GetProps2)(CStreamFileProps *props) PURE; +}; + #endif diff --git a/src/libs/7zip/unix/CPP/7zip/MyVersion.h b/src/libs/7zip/unix/CPP/7zip/MyVersion.h deleted file mode 100644 index 3acfb833f..000000000 --- a/src/libs/7zip/unix/CPP/7zip/MyVersion.h +++ /dev/null @@ -1,11 +0,0 @@ -#define MY_VER_MAJOR 9 -#define MY_VER_MINOR 20 -#define MY_VER_BUILD 0 -#define MY_VERSION "9.20" -#define MY_7ZIP_VERSION "7-Zip 9.20" -#define MY_DATE "2010-11-18" -#define MY_COPYRIGHT "Copyright (c) 1999-2010 Igor Pavlov" -#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE - -#define P7ZIP_VERSION "9.20" - diff --git a/src/libs/7zip/unix/CPP/7zip/PropID.h b/src/libs/7zip/unix/CPP/7zip/PropID.h index 8f8885263..82a7462bb 100644 --- a/src/libs/7zip/unix/CPP/7zip/PropID.h +++ b/src/libs/7zip/unix/CPP/7zip/PropID.h @@ -1,13 +1,15 @@ // PropID.h -#ifndef __7ZIP_PROPID_H -#define __7ZIP_PROPID_H +#ifndef __7ZIP_PROP_ID_H +#define __7ZIP_PROP_ID_H + +#include "../Common/MyTypes.h" enum { kpidNoProperty = 0, - kpidMainSubfile = 1, - kpidHandlerItemIndex = 2, + kpidMainSubfile, + kpidHandlerItemIndex, kpidPath, kpidName, kpidExtension, @@ -59,18 +61,64 @@ enum kpidCreatorApp, kpidSectorSize, kpidPosixAttrib, - kpidLink, + kpidSymLink, kpidError, - - kpidTotalSize = 0x1100, + kpidTotalSize, kpidFreeSpace, kpidClusterSize, kpidVolumeName, - - kpidLocalName = 0x1200, + kpidLocalName, kpidProvider, + kpidNtSecure, + kpidIsAltStream, + kpidIsAux, + kpidIsDeleted, + kpidIsTree, + kpidSha1, + kpidSha256, + kpidErrorType, + kpidNumErrors, + kpidErrorFlags, + kpidWarningFlags, + kpidWarning, + kpidNumStreams, + kpidNumAltStreams, + kpidAltStreamsSize, + kpidVirtualSize, + kpidUnpackSize, + kpidTotalPhySize, + kpidVolumeIndex, + kpidSubType, + kpidShortComment, + kpidCodePage, + kpidIsNotArcType, + kpidPhySizeCantBeDetected, + kpidZerosTailIsAllowed, + kpidTailSize, + kpidEmbeddedStubSize, + kpidNtReparse, + kpidHardLink, + kpidINode, + kpidStreamId, + + kpid_NUM_DEFINED, kpidUserDefined = 0x10000 }; +extern Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED]; // VARTYPE + +const UInt32 kpv_ErrorFlags_IsNotArc = 1 << 0; +const UInt32 kpv_ErrorFlags_HeadersError = 1 << 1; +const UInt32 kpv_ErrorFlags_EncryptedHeadersError = 1 << 2; +const UInt32 kpv_ErrorFlags_UnavailableStart = 1 << 3; +const UInt32 kpv_ErrorFlags_UnconfirmedStart = 1 << 4; +const UInt32 kpv_ErrorFlags_UnexpectedEnd = 1 << 5; +const UInt32 kpv_ErrorFlags_DataAfterEnd = 1 << 6; +const UInt32 kpv_ErrorFlags_UnsupportedMethod = 1 << 7; +const UInt32 kpv_ErrorFlags_UnsupportedFeature = 1 << 8; +const UInt32 kpv_ErrorFlags_DataError = 1 << 9; +const UInt32 kpv_ErrorFlags_CrcError = 1 << 10; +// const UInt32 kpv_ErrorFlags_Unsupported = 1 << 11; + #endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.cpp index d954129f3..48587264f 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.cpp +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.cpp @@ -1,6 +1,8 @@ // ArchiveCommandLine.cpp #include "StdAfx.h" +#undef printf +#undef sprintf #ifdef _WIN32 #ifndef UNDER_CE @@ -9,15 +11,15 @@ #endif #include -#include "Common/ListFileUtils.h" -#include "Common/StringConvert.h" -#include "Common/StringToInt.h" +#include "../../../Common/ListFileUtils.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/StringToInt.h" -#include "Windows/FileDir.h" -#include "Windows/FileName.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileName.h" #ifdef _WIN32 -#include "Windows/FileMapping.h" -#include "Windows/Synchronization.h" +#include "../../../Windows/FileMapping.h" +#include "../../../Windows/Synchronization.h" #else #include "myPrivate.h" #endif @@ -50,6 +52,32 @@ using namespace NCommandLineParser; using namespace NWindows; using namespace NFile; +static bool StringToUInt32(const wchar_t *s, UInt32 &v) +{ + if (*s == 0) + return false; + const wchar_t *end; + v = ConvertStringToUInt32(s, &end); + return *end == 0; +} + +static void AddNewLine(UString &s) +{ + s += L'\n'; +} + +CArcCmdLineException::CArcCmdLineException(const char *a, const wchar_t *u) +{ + (*this) += MultiByteToUnicodeString(a); + if (u) + { + AddNewLine(*this); + (*this) += u; + } +} + +int g_CodePage = -1; + namespace NKey { enum Enum { @@ -81,22 +109,55 @@ enum Enum kEmail, kShowDialog, kLargePages, - kUseLStat, + // kListfileCharSet, + // kConsoleCharSet, kTechMode, +#ifdef _WIN32 + kShareForWrite, +#endif + kUseLStat, kCaseSensitive, - kCalcCrc + kHash, + kArcNameMode, + + kDisableWildcardParsing, + kElimDup, + kFullPathMode, + + kHardLinks, + kSymLinks, + kNtSecurity, + kAltStreams, + kReplaceColonForAltStream, + kWriteToAltStreamIfColon, + + kDeleteAfterCompressing, + kSetArcMTime, + kExcludedArcType }; } -static const wchar_t kRecursedIDChar = 'R'; -static const wchar_t *kRecursedPostCharSet = L"0-"; +static const wchar_t kRecursedIDChar = 'r'; +static const char *kRecursedPostCharSet = "0-"; + +static const char *k_ArcNameMode_PostCharSet = "sea"; + +static inline const EArcNameMode ParseArcNameMode(int postCharIndex) +{ + switch (postCharIndex) + { + case 1: return k_ArcNameMode_Exact; + case 2: return k_ArcNameMode_Add; + default: return k_ArcNameMode_Smart; + } +} namespace NRecursedPostCharIndex { enum EEnum { - kWildCardRecursionOnly = 0, + kWildcardRecursionOnly = 0, kNoRecursion = 1 }; } @@ -108,133 +169,128 @@ static const char kFileListID = '@'; static const char kSomeCludePostStringMinSize = 2; // at least <@|!>ame must be static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!>ame must be -static const wchar_t *kOverwritePostCharSet = L"asut"; +static const char *kOverwritePostCharSet = "asut"; NExtract::NOverwriteMode::EEnum k_OverwriteModes[] = { - NExtract::NOverwriteMode::kWithoutPrompt, - NExtract::NOverwriteMode::kSkipExisting, - NExtract::NOverwriteMode::kAutoRename, - NExtract::NOverwriteMode::kAutoRenameExisting + NExtract::NOverwriteMode::kOverwrite, + NExtract::NOverwriteMode::kSkip, + NExtract::NOverwriteMode::kRename, + NExtract::NOverwriteMode::kRenameExisting }; static const CSwitchForm kSwitchForms[] = - { - { L"?", NSwitchType::kSimple, false }, - { L"H", NSwitchType::kSimple, false }, - { L"-HELP", NSwitchType::kSimple, false }, - { L"BA", NSwitchType::kSimple, false }, - { L"BD", NSwitchType::kSimple, false }, - { L"T", NSwitchType::kUnLimitedPostString, false, 1 }, - { L"Y", NSwitchType::kSimple, false }, - #ifndef _NO_CRYPTO - { L"P", NSwitchType::kUnLimitedPostString, false, 0 }, - #endif - { L"M", NSwitchType::kUnLimitedPostString, true, 1 }, - { L"O", NSwitchType::kUnLimitedPostString, false, 1 }, - { L"W", NSwitchType::kUnLimitedPostString, false, 0 }, - { L"I", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, - { L"X", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, - { L"AI", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, - { L"AX", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, - { L"AN", NSwitchType::kSimple, false }, - { L"U", NSwitchType::kUnLimitedPostString, true, 1}, - { L"V", NSwitchType::kUnLimitedPostString, true, 1}, - { L"R", NSwitchType::kPostChar, false, 0, 0, kRecursedPostCharSet }, - { L"SFX", NSwitchType::kUnLimitedPostString, false, 0 }, - { L"SI", NSwitchType::kUnLimitedPostString, false, 0 }, - { L"SO", NSwitchType::kSimple, false, 0 }, - { L"AO", NSwitchType::kPostChar, false, 1, 1, kOverwritePostCharSet}, - { L"SEML", NSwitchType::kUnLimitedPostString, false, 0}, - { L"AD", NSwitchType::kSimple, false }, - { L"SLP", NSwitchType::kUnLimitedPostString, false, 0}, - { L"L", NSwitchType::kSimple, false }, - { L"SLT", NSwitchType::kSimple, false }, - { L"SSC", NSwitchType::kPostChar, false, 0, 0, L"-" }, - { L"SCRC", NSwitchType::kSimple, false } - }; - -static const CCommandForm g_CommandForms[] = -{ - { L"A", false }, - { L"U", false }, - { L"D", false }, - { L"T", false }, - { L"E", false }, - { L"X", false }, - { L"L", false }, - { L"B", false }, - { L"I", false } +{ + { "?" }, + { "h" }, + { "-help" }, + { "ba" }, + { "bd" }, + { "t", NSwitchType::kString, false, 1 }, + { "y" }, + #ifndef _NO_CRYPTO + { "p", NSwitchType::kString }, + #endif + { "m", NSwitchType::kString, true, 1 }, + { "o", NSwitchType::kString, false, 1 }, + { "w", NSwitchType::kString }, + { "i", NSwitchType::kString, true, kSomeCludePostStringMinSize}, + { "x", NSwitchType::kString, true, kSomeCludePostStringMinSize}, + { "ai", NSwitchType::kString, true, kSomeCludePostStringMinSize}, + { "ax", NSwitchType::kString, true, kSomeCludePostStringMinSize}, + { "an" }, + { "u", NSwitchType::kString, true, 1}, + { "v", NSwitchType::kString, true, 1}, + { "r", NSwitchType::kChar, false, 0, kRecursedPostCharSet }, + { "sfx", NSwitchType::kString }, + { "si", NSwitchType::kString }, + { "so" }, + { "ao", NSwitchType::kChar, false, 1, kOverwritePostCharSet}, + { "seml", NSwitchType::kString, false, 0}, + { "ad" }, + { "slp", NSwitchType::kMinus }, + // { "scs", NSwitchType::kString }, + // { "scc", NSwitchType::kString }, + { "slt" }, + // { "ssw" }, + { "l" }, + { "ssc", NSwitchType::kMinus }, + { "scrc", NSwitchType::kString, true, 0 }, + { "sa", NSwitchType::kChar, false, 1, k_ArcNameMode_PostCharSet }, + + { "spd" }, + { "spe", NSwitchType::kMinus }, + { "spf", NSwitchType::kString, false, 0 }, + + { "snh", NSwitchType::kMinus }, + { "snl", NSwitchType::kMinus }, + { "sni" }, + { "sns", NSwitchType::kMinus }, + + { "snr" }, + { "snc" }, + + { "sdel" }, + { "stl" }, + { "stx", NSwitchType::kString, true, 1 } }; -static const int kNumCommandForms = sizeof(g_CommandForms) / sizeof(g_CommandForms[0]); - static const wchar_t *kUniversalWildcard = L"*"; static const int kMinNonSwitchWords = 1; static const int kCommandIndex = 0; -// --------------------------- -// exception messages - -static const char *kUserErrorMessage = "Incorrect command line"; +// static const char *kUserErrorMessage = "Incorrect command line"; static const char *kCannotFindListFile = "Cannot find listfile"; static const char *kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch."; -static const char *kIncorrectWildCardInListFile = "Incorrect wildcard in listfile"; -static const char *kIncorrectWildCardInCommandLine = "Incorrect wildcard in command line"; +static const char *kIncorrectWildcardInListFile = "Incorrect wildcard in listfile"; +static const char *kIncorrectWildcardInCommandLine = "Incorrect wildcard in command line"; static const char *kTerminalOutError = "I won't write compressed data to a terminal"; static const char *kSameTerminalError = "I won't write data and program's messages to same terminal"; static const char *kEmptyFilePath = "Empty file path"; +static const char *kCannotFindArchive = "Cannot find archive"; -static void ThrowException(const char *errorMessage) +bool CArcCommand::IsFromExtractGroup() const { - throw CArchiveCommandLineException(errorMessage); -} - -static void ThrowUserErrorException() -{ - ThrowException(kUserErrorMessage); -} - -// --------------------------- - -bool CArchiveCommand::IsFromExtractGroup() const -{ - switch(CommandType) + switch (CommandType) { case NCommandType::kTest: case NCommandType::kExtract: - case NCommandType::kFullExtract: + case NCommandType::kExtractFull: return true; - default: - return false; } + return false; } -NExtract::NPathMode::EEnum CArchiveCommand::GetPathMode() const +NExtract::NPathMode::EEnum CArcCommand::GetPathMode() const { - switch(CommandType) + switch (CommandType) { case NCommandType::kTest: - case NCommandType::kFullExtract: - return NExtract::NPathMode::kFullPathnames; - default: - return NExtract::NPathMode::kNoPathnames; + case NCommandType::kExtractFull: + return NExtract::NPathMode::kFullPaths; } + return NExtract::NPathMode::kNoPaths; } -bool CArchiveCommand::IsFromUpdateGroup() const +bool CArcCommand::IsFromUpdateGroup() const { - return (CommandType == NCommandType::kAdd || - CommandType == NCommandType::kUpdate || - CommandType == NCommandType::kDelete); + switch (CommandType) + { + case NCommandType::kAdd: + case NCommandType::kUpdate: + case NCommandType::kDelete: + case NCommandType::kRename: + return true; + } + return false; } static NRecursedType::EEnum GetRecursedTypeFromIndex(int index) { switch (index) { - case NRecursedPostCharIndex::kWildCardRecursionOnly: - return NRecursedType::kWildCardOnlyRecursed; + case NRecursedPostCharIndex::kWildcardRecursionOnly: + return NRecursedType::kWildcardOnlyRecursed; case NRecursedPostCharIndex::kNoRecursion: return NRecursedType::kNonRecursed; default: @@ -242,170 +298,281 @@ static NRecursedType::EEnum GetRecursedTypeFromIndex(int index) } } -static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command) +static const char *g_Commands = "audtexlbih"; + +static bool ParseArchiveCommand(const UString &commandString, CArcCommand &command) { - UString commandStringUpper = commandString; - commandStringUpper.MakeUpper(); - UString postString; - int commandIndex = ParseCommand(kNumCommandForms, g_CommandForms, commandStringUpper, - postString) ; - if (commandIndex < 0) - return false; - command.CommandType = (NCommandType::EEnum)commandIndex; - return true; + UString s = commandString; + s.MakeLower_Ascii(); + if (s.Len() == 1) + { + if (s[0] > 0x7F) + return false; + int index = FindCharPosInString(g_Commands, (char)s[0]); + if (index < 0) + return false; + command.CommandType = (NCommandType::EEnum)index; + return true; + } + if (s.Len() == 2 && s[0] == 'r' && s[1] == 'n') + { + command.CommandType = (NCommandType::kRename); + return true; + } + return false; } // ------------------------------------------------------------------ // filenames functions -static void AddNameToCensor(NWildcard::CCensor &wildcardCensor, - const UString &name, bool include, NRecursedType::EEnum type) +static void AddNameToCensor(NWildcard::CCensor &censor, + const UString &name, bool include, NRecursedType::EEnum type, bool wildcardMatching) { bool recursed = false; switch (type) { - case NRecursedType::kWildCardOnlyRecursed: - recursed = DoesNameContainWildCard(name); + case NRecursedType::kWildcardOnlyRecursed: + recursed = DoesNameContainWildcard(name); break; case NRecursedType::kRecursed: recursed = true; break; } - wildcardCensor.AddItem(include, name, recursed); + censor.AddPreItem(include, name, recursed, wildcardMatching); } -static void AddToCensorFromListFile(NWildcard::CCensor &wildcardCensor, - LPCWSTR fileName, bool include, NRecursedType::EEnum type, UINT codePage) +static void AddRenamePair(CObjectVector *renamePairs, + const UString &oldName, const UString &newName, NRecursedType::EEnum type, + bool wildcardMatching) +{ + CRenamePair &pair = renamePairs->AddNew(); + pair.OldName = oldName; + pair.NewName = newName; + pair.RecursedType = type; + pair.WildcardParsing = wildcardMatching; + + if (!pair.Prepare()) + { + UString val; + val += pair.OldName; + AddNewLine(val); + val += pair.NewName; + AddNewLine(val); + if (type == NRecursedType::kRecursed) + val += L"-r"; + else if (type == NRecursedType::kRecursed) + val += L"-r0"; + throw CArcCmdLineException("Unsupported rename command:", val); + } +} + +static void AddToCensorFromListFile( + CObjectVector *renamePairs, + NWildcard::CCensor &censor, + LPCWSTR fileName, bool include, NRecursedType::EEnum type, bool wildcardMatching, Int32 codePage) { UStringVector names; - if (!NFind::DoesFileExist(fileName)) - throw kCannotFindListFile; - if (!ReadNamesFromListFile(fileName, names, codePage)) - throw kIncorrectListFile; - for (int i = 0; i < names.Size(); i++) - AddNameToCensor(wildcardCensor, names[i], include, type); + if (!NFind::DoesFileExist(us2fs(fileName))) + throw CArcCmdLineException(kCannotFindListFile, fileName); + if (!ReadNamesFromListFile(us2fs(fileName), names, codePage)) + throw CArcCmdLineException(kIncorrectListFile, fileName); + if (renamePairs) + { + if ((names.Size() & 1) != 0) + throw CArcCmdLineException(kIncorrectListFile, fileName); + for (unsigned i = 0; i < names.Size(); i += 2) + { + // change type !!!! + AddRenamePair(renamePairs, names[i], names[i + 1], type, wildcardMatching); + } + } + else + FOR_VECTOR (i, names) + AddNameToCensor(censor, names[i], include, type, wildcardMatching); } static void AddToCensorFromNonSwitchesStrings( - int startIndex, - NWildcard::CCensor &wildcardCensor, + CObjectVector *renamePairs, + unsigned startIndex, + NWildcard::CCensor &censor, const UStringVector &nonSwitchStrings, NRecursedType::EEnum type, - bool thereAreSwitchIncludes, UINT codePage) + bool wildcardMatching, + bool thereAreSwitchIncludes, Int32 codePage) { - if (nonSwitchStrings.Size() == startIndex && (!thereAreSwitchIncludes)) - AddNameToCensor(wildcardCensor, kUniversalWildcard, true, type); - for (int i = startIndex; i < nonSwitchStrings.Size(); i++) + if ((renamePairs || nonSwitchStrings.Size() == startIndex) && !thereAreSwitchIncludes) + AddNameToCensor(censor, kUniversalWildcard, true, type, + true // wildcardMatching + ); + + int oldIndex = -1; + + for (unsigned i = startIndex; i < nonSwitchStrings.Size(); i++) { const UString &s = nonSwitchStrings[i]; if (s.IsEmpty()) - throw kEmptyFilePath; + throw CArcCmdLineException(kEmptyFilePath); if (s[0] == kFileListID) - AddToCensorFromListFile(wildcardCensor, s.Mid(1), true, type, codePage); - else - AddNameToCensor(wildcardCensor, s, true, type); - } -} - -#ifdef _WIN32 -static void ParseMapWithPaths(NWildcard::CCensor &wildcardCensor, - const UString &switchParam, bool include, - NRecursedType::EEnum commonRecursedType) -{ - int splitPos = switchParam.Find(L':'); - if (splitPos < 0) - ThrowUserErrorException(); - UString mappingName = switchParam.Left(splitPos); - - UString switchParam2 = switchParam.Mid(splitPos + 1); - splitPos = switchParam2.Find(L':'); - if (splitPos < 0) - ThrowUserErrorException(); - - UString mappingSize = switchParam2.Left(splitPos); - UString eventName = switchParam2.Mid(splitPos + 1); - - UInt64 dataSize64 = ConvertStringToUInt64(mappingSize, NULL); - UInt32 dataSize = (UInt32)dataSize64; - { - CFileMapping fileMapping; - if (fileMapping.Open(FILE_MAP_READ, GetSystemString(mappingName)) != 0) - ThrowException("Can not open mapping"); - LPVOID data = fileMapping.Map(FILE_MAP_READ, 0, dataSize); - if (data == NULL) - ThrowException("MapViewOfFile error"); - try + AddToCensorFromListFile(renamePairs, censor, s.Ptr(1), true, type, wildcardMatching, codePage); + else if (renamePairs) { - const wchar_t *curData = (const wchar_t *)data; - if (*curData != 0) - ThrowException("Incorrect mapping data"); - UInt32 numChars = dataSize / sizeof(wchar_t); - UString name; - for (UInt32 i = 1; i < numChars; i++) + if (oldIndex == -1) + oldIndex = startIndex; + else { - wchar_t c = curData[i]; - if (c == L'\0') - { - AddNameToCensor(wildcardCensor, name, include, commonRecursedType); - name.Empty(); - } - else - name += c; + // NRecursedType::EEnum type is used for global wildcard (-i! switches) + AddRenamePair(renamePairs, nonSwitchStrings[oldIndex], s, NRecursedType::kNonRecursed, wildcardMatching); + // AddRenamePair(renamePairs, nonSwitchStrings[oldIndex], s, type); + oldIndex = -1; } - if (!name.IsEmpty()) - ThrowException("data error"); } - catch(...) - { - UnmapViewOfFile(data); - throw; - } - UnmapViewOfFile(data); + else + AddNameToCensor(censor, s, true, type, wildcardMatching); } - + + if (oldIndex != -1) + { + throw CArcCmdLineException("There is no second file name for rename pair:", nonSwitchStrings[oldIndex]); + } +} + +#ifdef _WIN32 + +struct CEventSetEnd +{ + UString Name; + + CEventSetEnd(const wchar_t *name): Name(name) {} + ~CEventSetEnd() { NSynchronization::CManualResetEvent event; - if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(eventName)) == S_OK) + if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(Name)) == 0) event.Set(); } +}; + +const char *k_IncorrectMapCommand = "Incorrect Map command"; + +static const char *ParseMapWithPaths( + NWildcard::CCensor &censor, + const UString &s2, bool include, + NRecursedType::EEnum commonRecursedType, + bool wildcardMatching) +{ + UString s = s2; + int pos = s.Find(L':'); + if (pos < 0) + return k_IncorrectMapCommand; + int pos2 = s.Find(L':', pos + 1); + if (pos2 < 0) + return k_IncorrectMapCommand; + + CEventSetEnd eventSetEnd((const wchar_t *)s + (pos2 + 1)); + s.DeleteFrom(pos2); + UInt32 size; + if (!StringToUInt32(s.Ptr(pos + 1), size) + || size < sizeof(wchar_t) + || size > ((UInt32)1 << 31) + || size % sizeof(wchar_t) != 0) + return "Unsupported Map data size"; + + s.DeleteFrom(pos); + CFileMapping map; + if (map.Open(FILE_MAP_READ, GetSystemString(s)) != 0) + return "Can not open mapping"; + LPVOID data = map.Map(FILE_MAP_READ, 0, size); + if (!data) + return "MapViewOfFile error"; + CFileUnmapper unmapper(data); + + UString name; + const wchar_t *p = (const wchar_t *)data; + if (*p != 0) // data format marker + return "Unsupported Map data"; + UInt32 numChars = size / sizeof(wchar_t); + for (UInt32 i = 1; i < numChars; i++) + { + wchar_t c = p[i]; + if (c == 0) + { + // MessageBoxW(0, name, L"7-Zip", 0); + AddNameToCensor(censor, name, include, commonRecursedType, wildcardMatching); + name.Empty(); + } + else + name += c; + } + if (!name.IsEmpty()) + return "Map data error"; + + return NULL; } + #endif -static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor, +static void AddSwitchWildcardsToCensor( + NWildcard::CCensor &censor, const UStringVector &strings, bool include, - NRecursedType::EEnum commonRecursedType, UINT codePage) + NRecursedType::EEnum commonRecursedType, + bool wildcardMatching, + Int32 codePage) { - for (int i = 0; i < strings.Size(); i++) + const char *errorMessage = NULL; + unsigned i; + for (i = 0; i < strings.Size(); i++) { const UString &name = strings[i]; NRecursedType::EEnum recursedType; - int pos = 0; - if (name.Length() < kSomeCludePostStringMinSize) - ThrowUserErrorException(); - if (::MyCharUpper(name[pos]) == kRecursedIDChar) + unsigned pos = 0; + + if (name.Len() < kSomeCludePostStringMinSize) + { + errorMessage = "Too short switch"; + break; + } + + if (::MyCharLower_Ascii(name[pos]) == kRecursedIDChar) { pos++; - int index = UString(kRecursedPostCharSet).Find(name[pos]); + wchar_t c = name[pos]; + int index = -1; + if (c <= 0x7F) + index = FindCharPosInString(kRecursedPostCharSet, (char)c); recursedType = GetRecursedTypeFromIndex(index); if (index >= 0) pos++; } else recursedType = commonRecursedType; - if (name.Length() < pos + kSomeCludeAfterRecursedPostStringMinSize) - ThrowUserErrorException(); - UString tail = name.Mid(pos + 1); + + if (name.Len() < pos + kSomeCludeAfterRecursedPostStringMinSize) + { + errorMessage = "Too short switch"; + break; + } + + UString tail = name.Ptr(pos + 1); + if (name[pos] == kImmediateNameID) - AddNameToCensor(wildcardCensor, tail, include, recursedType); + AddNameToCensor(censor, tail, include, recursedType, wildcardMatching); else if (name[pos] == kFileListID) - AddToCensorFromListFile(wildcardCensor, tail, include, recursedType, codePage); + AddToCensorFromListFile(NULL, censor, tail, include, recursedType, wildcardMatching, codePage); #ifdef _WIN32 else if (name[pos] == kMapNameID) - ParseMapWithPaths(wildcardCensor, tail, include, recursedType); + { + errorMessage = ParseMapWithPaths(censor, tail, include, recursedType, wildcardMatching); + if (errorMessage) + break; + } #endif else - ThrowUserErrorException(); + { + errorMessage = "Incorrect wildcarc type marker"; + break; + } } + if (i != strings.Size()) + throw CArcCmdLineException(errorMessage, strings[i]); } #ifdef _WIN32 @@ -414,20 +581,25 @@ static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor, static void ConvertToLongName(const UString &prefix, UString &name) { - if (name.IsEmpty() || DoesNameContainWildCard(name)) + if (name.IsEmpty() || DoesNameContainWildcard(name)) return; - NFind::CFileInfoW fi; - if (fi.Find(prefix + name)) - name = fi.Name; + NFind::CFileInfo fi; + const FString path = us2fs(prefix + name); + if (NFile::NName::IsDevicePath(path)) + return; + if (fi.Find(path)) + name = fs2us(fi.Name); } static void ConvertToLongNames(const UString &prefix, CObjectVector &items) { - for (int i = 0; i < items.Size(); i++) + FOR_VECTOR (i, items) { NWildcard::CItem &item = items[i]; if (item.Recursive || item.PathParts.Size() != 1) continue; + if (prefix.IsEmpty() && item.IsDriveItem()) + continue; ConvertToLongName(prefix, item.PathParts.Front()); } } @@ -436,17 +608,22 @@ static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &no { ConvertToLongNames(prefix, node.IncludeItems); ConvertToLongNames(prefix, node.ExcludeItems); - int i; + unsigned i; for (i = 0; i < node.SubNodes.Size(); i++) - ConvertToLongName(prefix, node.SubNodes[i].Name); + { + UString &name = node.SubNodes[i].Name; + if (prefix.IsEmpty() && NWildcard::IsDriveColonName(name)) + continue; + ConvertToLongName(prefix, name); + } // mix folders with same name for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode1 = node.SubNodes[i]; - for (int j = i + 1; j < node.SubNodes.Size();) + for (unsigned j = i + 1; j < node.SubNodes.Size();) { const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j]; - if (nextNode1.Name.CompareNoCase(nextNode2.Name) == 0) + if (nextNode1.Name.IsEqualToNoCase(nextNode2.Name)) { nextNode1.IncludeItems += nextNode2.IncludeItems; nextNode1.ExcludeItems += nextNode2.ExcludeItems; @@ -459,13 +636,13 @@ static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &no for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode = node.SubNodes[i]; - ConvertToLongNames(prefix + nextNode.Name + wchar_t(NFile::NName::kDirDelimiter), nextNode); + ConvertToLongNames(prefix + nextNode.Name + WCHAR_PATH_SEPARATOR, nextNode); } } -static void ConvertToLongNames(NWildcard::CCensor &censor) +void ConvertToLongNames(NWildcard::CCensor &censor) { - for (int i = 0; i < censor.Pairs.Size(); i++) + FOR_VECTOR (i, censor.Pairs) { NWildcard::CPair &pair = censor.Pairs[i]; ConvertToLongNames(pair.Prefix, pair.Head); @@ -474,9 +651,10 @@ static void ConvertToLongNames(NWildcard::CCensor &censor) #endif +/* static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i) { - switch(i) + switch (i) { case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairAction::kIgnore; case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction::kCopy; @@ -485,35 +663,36 @@ static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i) } throw 98111603; } +*/ -const UString kUpdatePairStateIDSet = L"PQRXYZW"; -const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1}; +static const wchar_t *kUpdatePairStateIDSet = L"pqrxyzw"; +static const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1}; -const UString kUpdatePairActionIDSet = L"0123"; //Ignore, Copy, Compress, Create Anti - -const wchar_t *kUpdateIgnoreItselfPostStringID = L"-"; -const wchar_t kUpdateNewArchivePostCharID = '!'; +static const unsigned kNumUpdatePairActions = 4; +static const char *kUpdateIgnoreItselfPostStringID = "-"; +static const wchar_t kUpdateNewArchivePostCharID = '!'; static bool ParseUpdateCommandString2(const UString &command, NUpdateArchive::CActionSet &actionSet, UString &postString) { - for (int i = 0; i < command.Length();) + for (unsigned i = 0; i < command.Len();) { - wchar_t c = MyCharUpper(command[i]); - int statePos = kUpdatePairStateIDSet.Find(c); + wchar_t c = MyCharLower_Ascii(command[i]); + int statePos = FindCharPosInString(kUpdatePairStateIDSet, c); if (statePos < 0) { - postString = command.Mid(i); + postString = command.Ptr(i); return true; } i++; - if (i >= command.Length()) + if (i >= command.Len()) return false; - int actionPos = kUpdatePairActionIDSet.Find(::MyCharUpper(command[i])); - if (actionPos < 0) + c = command[i]; + if (c < '0' || c >= '0' + kNumUpdatePairActions) return false; - actionSet.StateActions[statePos] = GetUpdatePairActionType(actionPos); + int actionPos = c - '0'; + actionSet.StateActions[statePos] = (NUpdateArchive::NPairAction::EEnum)(actionPos); if (kUpdatePairStateNotSupportedActions[statePos] == actionPos) return false; i++; @@ -526,10 +705,12 @@ static void ParseUpdateCommandString(CUpdateOptions &options, const UStringVector &updatePostStrings, const NUpdateArchive::CActionSet &defaultActionSet) { - for (int i = 0; i < updatePostStrings.Size(); i++) + const char *errorMessage = "incorrect update switch command"; + unsigned i; + for (i = 0; i < updatePostStrings.Size(); i++) { const UString &updateString = updatePostStrings[i]; - if (updateString.CompareNoCase(kUpdateIgnoreItselfPostStringID) == 0) + if (updateString.IsEqualTo(kUpdateIgnoreItselfPostStringID)) { if (options.UpdateArchiveItself) { @@ -543,7 +724,7 @@ static void ParseUpdateCommandString(CUpdateOptions &options, UString postString; if (!ParseUpdateCommandString2(updateString, actionSet, postString)) - ThrowUserErrorException(); + break; if (postString.IsEmpty()) { if (options.UpdateArchiveItself) @@ -551,64 +732,23 @@ static void ParseUpdateCommandString(CUpdateOptions &options, } else { - if (MyCharUpper(postString[0]) != kUpdateNewArchivePostCharID) - ThrowUserErrorException(); + if (postString[0] != kUpdateNewArchivePostCharID) + break; CUpdateArchiveCommand uc; - UString archivePath = postString.Mid(1); + UString archivePath = postString.Ptr(1); if (archivePath.IsEmpty()) - ThrowUserErrorException(); + break; uc.UserArchivePath = archivePath; uc.ActionSet = actionSet; options.Commands.Add(uc); } } } + if (i != updatePostStrings.Size()) + throw CArcCmdLineException(errorMessage, updatePostStrings[i]); } -static const char kByteSymbol = 'B'; -static const char kKiloSymbol = 'K'; -static const char kMegaSymbol = 'M'; -static const char kGigaSymbol = 'G'; - -static bool ParseComplexSize(const UString &src, UInt64 &result) -{ - UString s = src; - s.MakeUpper(); - - const wchar_t *start = s; - const wchar_t *end; - UInt64 number = ConvertStringToUInt64(start, &end); - int numDigits = (int)(end - start); - if (numDigits == 0 || s.Length() > numDigits + 1) - return false; - if (s.Length() == numDigits) - { - result = number; - return true; - } - int numBits; - switch (s[numDigits]) - { - case kByteSymbol: - result = number; - return true; - case kKiloSymbol: - numBits = 10; - break; - case kMegaSymbol: - numBits = 20; - break; - case kGigaSymbol: - numBits = 30; - break; - default: - return false; - } - if (number >= ((UInt64)1 << (64 - numBits))) - return false; - result = number << numBits; - return true; -} +bool ParseComplexSize(const wchar_t *s, UInt64 &result); static void SetAddCommandOptions( NCommandType::EEnum commandType, @@ -616,20 +756,20 @@ static void SetAddCommandOptions( CUpdateOptions &options) { NUpdateArchive::CActionSet defaultActionSet; - switch(commandType) + switch (commandType) { case NCommandType::kAdd: - defaultActionSet = NUpdateArchive::kAddActionSet; + defaultActionSet = NUpdateArchive::k_ActionSet_Add; break; case NCommandType::kDelete: - defaultActionSet = NUpdateArchive::kDeleteActionSet; + defaultActionSet = NUpdateArchive::k_ActionSet_Delete; break; default: - defaultActionSet = NUpdateArchive::kUpdateActionSet; + defaultActionSet = NUpdateArchive::k_ActionSet_Update; } - + options.UpdateArchiveItself = true; - + options.Commands.Clear(); CUpdateArchiveCommand updateMainCommand; updateMainCommand.ActionSet = defaultActionSet; @@ -641,22 +781,22 @@ static void SetAddCommandOptions( { const UString &postString = parser[NKey::kWorkingDir].PostStrings[0]; if (postString.IsEmpty()) - NDirectory::MyGetTempPath(options.WorkingDir); + NDir::MyGetTempPath(options.WorkingDir); else - options.WorkingDir = postString; + options.WorkingDir = us2fs(postString); } options.SfxMode = parser[NKey::kSfx].ThereIs; if (options.SfxMode) - options.SfxModule = parser[NKey::kSfx].PostStrings[0]; + options.SfxModule = us2fs(parser[NKey::kSfx].PostStrings[0]); if (parser[NKey::kVolume].ThereIs) { const UStringVector &sv = parser[NKey::kVolume].PostStrings; - for (int i = 0; i < sv.Size(); i++) + FOR_VECTOR (i, sv) { UInt64 size; - if (!ParseComplexSize(sv[i], size)) - ThrowException("Incorrect volume size"); + if (!ParseComplexSize(sv[i], size) || size == 0) + throw CArcCmdLineException("Incorrect volume size:", sv[i]); options.VolumesSizes.Add(size); } } @@ -666,38 +806,28 @@ static void SetMethodOptions(const CParser &parser, CObjectVector &pr { if (parser[NKey::kProperty].ThereIs) { - // options.MethodMode.Properties.Clear(); - for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) + FOR_VECTOR (i, parser[NKey::kProperty].PostStrings) { - CProperty property; - const UString &postString = parser[NKey::kProperty].PostStrings[i]; - int index = postString.Find(L'='); - if (index < 0) - property.Name = postString; - else + CProperty prop; + prop.Name = parser[NKey::kProperty].PostStrings[i]; + int index = prop.Name.Find(L'='); + if (index >= 0) { - property.Name = postString.Left(index); - property.Value = postString.Mid(index + 1); + prop.Value = prop.Name.Ptr(index + 1); + prop.Name.DeleteFrom(index); } - properties.Add(property); + properties.Add(prop); } } } -CArchiveCommandLineParser::CArchiveCommandLineParser(): - parser(sizeof(kSwitchForms) / sizeof(kSwitchForms[0])) {} +CArcCmdLineParser::CArcCmdLineParser(): parser(ARRAY_SIZE(kSwitchForms)) {} -void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings, - CArchiveCommandLineOptions &options) +void CArcCmdLineParser::Parse1(const UStringVector &commandStrings, + CArcCmdLineOptions &options) { - try - { - parser.ParseStrings(kSwitchForms, commandStrings); - } - catch(...) - { - ThrowUserErrorException(); - } + if (!parser.ParseStrings(kSwitchForms, commandStrings)) + throw CArcCmdLineException(parser.ErrorMessage, parser.ErrorLine); options.IsInTerminal = MY_IS_TERMINAL(stdin); options.IsStdOutTerminal = MY_IS_TERMINAL(stdout); @@ -707,44 +837,160 @@ void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings, options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs; options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs; + if (parser[NKey::kCaseSensitive].ThereIs) + { + g_CaseSensitive = !parser[NKey::kCaseSensitive].WithMinus; + options.CaseSensitiveChange = true; + options.CaseSensitive = g_CaseSensitive; + } + #ifdef _7ZIP_LARGE_PAGES options.LargePages = false; if (parser[NKey::kLargePages].ThereIs) { - const UString &postString = parser[NKey::kLargePages].PostStrings.Front(); - if (postString.IsEmpty()) - options.LargePages = true; + options.LargePages = !parser[NKey::kLargePages].WithMinus; } #endif } -static bool ConvertStringToUInt32(const wchar_t *s, UInt32 &v) +struct CCodePagePair { - const wchar_t *end; - UInt64 number = ConvertStringToUInt64(s, &end); - if (*end != 0) - return false; - if (number > (UInt32)0xFFFFFFFF) - return false; - v = (UInt32)number; - return true; + const char *Name; + Int32 CodePage; +}; + +static const unsigned kNumByteOnlyCodePages = 3; + +static CCodePagePair g_CodePagePairs[] = +{ + { "utf-8", CP_UTF8 }, + { "win", CP_ACP }, + { "dos", CP_OEMCP }, + { "utf-16le", MY__CP_UTF16 }, + { "utf-16be", MY__CP_UTF16BE } +}; + +static Int32 FindCharset(const NCommandLineParser::CParser &parser, int keyIndex, + bool byteOnlyCodePages, Int32 defaultVal) +{ + if (!parser[keyIndex].ThereIs) + return defaultVal; + + UString name = parser[keyIndex].PostStrings.Back(); + UInt32 v; + if (StringToUInt32(name, v)) + if (v < ((UInt32)1 << 16)) + return (Int32)v; + name.MakeLower_Ascii(); + unsigned num = byteOnlyCodePages ? kNumByteOnlyCodePages : ARRAY_SIZE(g_CodePagePairs); + for (unsigned i = 0;; i++) + { + if (i == num) // to disable warnings from different compilers + throw CArcCmdLineException("Unsupported charset:", name); + const CCodePagePair &pair = g_CodePagePairs[i]; + if (name.IsEqualTo(pair.Name)) + return pair.CodePage; + } } -void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) +void EnumerateDirItemsAndSort( + bool storeAltStreams, + NWildcard::CCensor &censor, + NWildcard::ECensorPathMode censorPathMode, + const UString &addPathPrefix, + UStringVector &sortedPaths, + UStringVector &sortedFullPaths) +{ + UStringVector paths; + { + CDirItems dirItems; + { + dirItems.ScanAltStreams = storeAltStreams; + HRESULT res = EnumerateItems(censor, censorPathMode, addPathPrefix, dirItems, NULL); + if (res != S_OK || dirItems.ErrorPaths.Size() > 0) + { + UString errorPath; + if (dirItems.ErrorPaths.Size() > 0) + errorPath = fs2us(dirItems.ErrorPaths[0]); + throw CArcCmdLineException(kCannotFindArchive, + dirItems.ErrorPaths.Size() > 0 ? (const wchar_t *)errorPath : NULL); + } + } + FOR_VECTOR (i, dirItems.Items) + { + const CDirItem &dirItem = dirItems.Items[i]; + if (!dirItem.IsDir()) + paths.Add(dirItems.GetPhyPath(i)); + } + } + + if (paths.Size() == 0) + throw CArcCmdLineException(kCannotFindArchive); + + UStringVector fullPaths; + + unsigned i; + for (i = 0; i < paths.Size(); i++) + { + FString fullPath; + NFile::NDir::MyGetFullPathName(us2fs(paths[i]), fullPath); + fullPaths.Add(fs2us(fullPath)); + } + CUIntVector indices; + SortFileNames(fullPaths, indices); + sortedPaths.ClearAndReserve(indices.Size()); + sortedFullPaths.ClearAndReserve(indices.Size()); + for (i = 0; i < indices.Size(); i++) + { + unsigned index = indices[i]; + sortedPaths.AddInReserved(paths[index]); + sortedFullPaths.AddInReserved(fullPaths[index]); + if (i > 0 && CompareFileNames(sortedFullPaths[i], sortedFullPaths[i - 1]) == 0) + throw CArcCmdLineException("Duplicate archive path:", sortedFullPaths[i]); + } +} + +static void SetBoolPair(NCommandLineParser::CParser &parser, unsigned switchID, CBoolPair &bp) +{ + bp.Def = parser[switchID].ThereIs; + if (bp.Def) + bp.Val = !parser[switchID].WithMinus; +} + +void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) { const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int numNonSwitchStrings = nonSwitchStrings.Size(); if (numNonSwitchStrings < kMinNonSwitchWords) - ThrowUserErrorException(); + throw CArcCmdLineException("The command must be spcified"); if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command)) - ThrowUserErrorException(); + throw CArcCmdLineException("Unsupported command:", nonSwitchStrings[kCommandIndex]); options.TechMode = parser[NKey::kTechMode].ThereIs; - options.CalcCrc = parser[NKey::kCalcCrc].ThereIs; + if (parser[NKey::kHash].ThereIs) + options.HashMethods = parser[NKey::kHash].PostStrings; - if (parser[NKey::kCaseSensitive].ThereIs) - g_CaseSensitive = (parser[NKey::kCaseSensitive].PostCharIndex < 0); + if (parser[NKey::kElimDup].ThereIs) + { + options.ExtractOptions.ElimDup.Def = true; + options.ExtractOptions.ElimDup.Val = !parser[NKey::kElimDup].WithMinus; + } + + NWildcard::ECensorPathMode censorPathMode = NWildcard::k_RelatPath; + bool fullPathMode = parser[NKey::kFullPathMode].ThereIs; + if (fullPathMode) + { + censorPathMode = NWildcard::k_AbsPath; + const UString &s = parser[NKey::kFullPathMode].PostStrings[0]; + if (!s.IsEmpty()) + { + if (s == L"2") + censorPathMode = NWildcard::k_FullPath; + else + throw CArcCmdLineException("Unsupported -spf:", s); + } + } NRecursedType::EEnum recursedType; if (parser[NKey::kRecursed].ThereIs) @@ -752,48 +998,57 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) else recursedType = NRecursedType::kNonRecursed; - UINT codePage = CP_ACP; + bool wildcardMatching = true; + if (parser[NKey::kDisableWildcardParsing].ThereIs) + wildcardMatching = false; + + Int32 codePage = CP_ACP; bool thereAreSwitchIncludes = false; + if (parser[NKey::kInclude].ThereIs) { thereAreSwitchIncludes = true; - AddSwitchWildCardsToCensor(options.WildcardCensor, - parser[NKey::kInclude].PostStrings, true, recursedType, codePage); + AddSwitchWildcardsToCensor(options.Censor, + parser[NKey::kInclude].PostStrings, true, recursedType, wildcardMatching, codePage); } + if (parser[NKey::kExclude].ThereIs) - AddSwitchWildCardsToCensor(options.WildcardCensor, - parser[NKey::kExclude].PostStrings, false, recursedType, codePage); - + AddSwitchWildcardsToCensor(options.Censor, + parser[NKey::kExclude].PostStrings, false, recursedType, wildcardMatching, codePage); + int curCommandIndex = kCommandIndex + 1; bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs && options.Command.CommandType != NCommandType::kBenchmark && - options.Command.CommandType != NCommandType::kInfo; + options.Command.CommandType != NCommandType::kInfo && + options.Command.CommandType != NCommandType::kHash; bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); bool isExtractOrList = isExtractGroupCommand || options.Command.CommandType == NCommandType::kList; + bool isRename = options.Command.CommandType == NCommandType::kRename; - if (isExtractOrList && options.StdInMode) + if ((isExtractOrList || isRename) && options.StdInMode) thereIsArchiveName = false; + if (parser[NKey::kArcNameMode].ThereIs) + options.UpdateOptions.ArcNameMode = ParseArcNameMode(parser[NKey::kArcNameMode].PostCharIndex); + if (thereIsArchiveName) { if (curCommandIndex >= numNonSwitchStrings) - ThrowUserErrorException(); + throw CArcCmdLineException("Cannot find archive name"); options.ArchiveName = nonSwitchStrings[curCommandIndex++]; if (options.ArchiveName.IsEmpty()) - ThrowUserErrorException(); + throw CArcCmdLineException("Archive name cannot by empty"); } - AddToCensorFromNonSwitchesStrings( - curCommandIndex, options.WildcardCensor, - nonSwitchStrings, recursedType, thereAreSwitchIncludes, codePage); + AddToCensorFromNonSwitchesStrings(isRename ? &options.UpdateOptions.RenamePairs : NULL, + curCommandIndex, options.Censor, + nonSwitchStrings, recursedType, wildcardMatching, + thereAreSwitchIncludes, codePage); options.YesToAll = parser[NKey::kYes].ThereIs; -#ifdef ENV_HAVE_LSTAT - global_use_lstat = !parser[NKey::kUseLStat].ThereIs; -#endif #ifndef _NO_CRYPTO options.PasswordEnabled = parser[NKey::kPassword].ThereIs; @@ -806,35 +1061,73 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) if (parser[NKey::kArchiveType].ThereIs) options.ArcType = parser[NKey::kArchiveType].PostStrings[0]; + options.ExcludedArcTypes = parser[NKey::kExcludedArcType].PostStrings; + + SetMethodOptions(parser, options.Properties); + + options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs; + + if (options.EnablePercents) + { + if ((options.StdOutMode && !options.IsStdErrTerminal) || + (!options.StdOutMode && !options.IsStdOutTerminal)) + options.EnablePercents = false; + } + + if (parser[NKey::kNtSecurity].ThereIs) options.NtSecurity.SetTrueTrue(); + + SetBoolPair(parser, NKey::kAltStreams, options.AltStreams); + SetBoolPair(parser, NKey::kHardLinks, options.HardLinks); + SetBoolPair(parser, NKey::kSymLinks, options.SymLinks); + if (isExtractOrList) { - if (!options.WildcardCensor.AllAreRelative()) - ThrowException("Cannot use absolute pathnames for this command"); + CExtractOptionsBase &eo = options.ExtractOptions; + + { + CExtractNtOptions &nt = eo.NtOptions; + nt.NtSecurity = options.NtSecurity; - NWildcard::CCensor archiveWildcardCensor; + nt.AltStreams = options.AltStreams; + if (!options.AltStreams.Def) + nt.AltStreams.Val = true; + + nt.HardLinks = options.HardLinks; + if (!options.HardLinks.Def) + nt.HardLinks.Val = true; + + nt.SymLinks = options.SymLinks; + if (!options.SymLinks.Def) + nt.SymLinks.Val = true; + + nt.ReplaceColonForAltStream = parser[NKey::kReplaceColonForAltStream].ThereIs; + nt.WriteToAltStreamIfColon = parser[NKey::kWriteToAltStreamIfColon].ThereIs; + } + + options.Censor.AddPathsToCensor(NWildcard::k_AbsPath); + options.Censor.ExtendExclude(); + + // are there paths that look as non-relative (!Prefix.IsEmpty()) + if (!options.Censor.AllAreRelative()) + throw CArcCmdLineException("Cannot use absolute pathnames for this command"); + + NWildcard::CCensor arcCensor; if (parser[NKey::kArInclude].ThereIs) - AddSwitchWildCardsToCensor(archiveWildcardCensor, - parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, codePage); + AddSwitchWildcardsToCensor(arcCensor, parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, wildcardMatching, codePage); if (parser[NKey::kArExclude].ThereIs) - AddSwitchWildCardsToCensor(archiveWildcardCensor, - parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, codePage); - - bool directlyAddArchiveName = false; - if (thereIsArchiveName) { - if ((options.ArchiveName.Find(kUniversalWildcard) == -1) && (options.ArchiveName.Find(L"?") == -1)) { - // no wildcard => no need to scan - directlyAddArchiveName = true; - } else { - AddNameToCensor(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed); - } - } + AddSwitchWildcardsToCensor(arcCensor, parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, wildcardMatching, codePage); + + if (thereIsArchiveName) + AddNameToCensor(arcCensor, options.ArchiveName, true, NRecursedType::kNonRecursed, wildcardMatching); + + arcCensor.AddPathsToCensor(NWildcard::k_RelatPath); #ifdef _WIN32 - ConvertToLongNames(archiveWildcardCensor); + ConvertToLongNames(arcCensor); #endif - archiveWildcardCensor.ExtendExclude(); + arcCensor.ExtendExclude(); if (options.StdInMode) { @@ -844,95 +1137,78 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) } else { - - UStringVector archivePaths; - - { - CDirItems dirItems; - { - UStringVector errorPaths; - CRecordVector errorCodes; - HRESULT res = EnumerateItems(archiveWildcardCensor, dirItems, NULL, errorPaths, errorCodes); - if (res != S_OK || errorPaths.Size() > 0) - throw "cannot find archive"; - } - for (int i = 0; i < dirItems.Items.Size(); i++) - { - const CDirItem &dirItem = dirItems.Items[i]; - if (!dirItem.IsDir()) - archivePaths.Add(dirItems.GetPhyPath(i)); - } + EnumerateDirItemsAndSort( + false, // scanAltStreams + arcCensor, + NWildcard::k_RelatPath, + UString(), // addPathPrefix + options.ArchivePathsSorted, + options.ArchivePathsFullSorted); } - // Because the pathname of archive can be a symbolic link - // do not use "AddCommandLineWildCardToCensr(archiveWildcardCensor, options.ArchiveName" - if (directlyAddArchiveName) - archivePaths.Add(options.ArchiveName); - - if (archivePaths.Size() == 0) - throw "there is no such archive"; - - UStringVector archivePathsFull; - - int i; - for (i = 0; i < archivePaths.Size(); i++) - { - UString fullPath; - NFile::NDirectory::MyGetFullPathName(archivePaths[i], fullPath); - archivePathsFull.Add(fullPath); - } - CIntVector indices; - SortFileNames(archivePathsFull, indices); - options.ArchivePathsSorted.Reserve(indices.Size()); - options.ArchivePathsFullSorted.Reserve(indices.Size()); - for (i = 0; i < indices.Size(); i++) - { - options.ArchivePathsSorted.Add(archivePaths[indices[i]]); - options.ArchivePathsFullSorted.Add(archivePathsFull[indices[i]]); - } - - } - if (isExtractGroupCommand) { - SetMethodOptions(parser, options.ExtractProperties); if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal) - throw kSameTerminalError; + throw CArcCmdLineException(kSameTerminalError); if (parser[NKey::kOutputDir].ThereIs) { - options.OutputDir = parser[NKey::kOutputDir].PostStrings[0]; - NFile::NName::NormalizeDirPathPrefix(options.OutputDir); + eo.OutputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]); + NFile::NName::NormalizeDirPathPrefix(eo.OutputDir); } - options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore; + eo.OverwriteMode = NExtract::NOverwriteMode::kAsk; if (parser[NKey::kOverwrite].ThereIs) - options.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex]; + { + eo.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex]; + eo.OverwriteMode_Force = true; + } else if (options.YesToAll) - options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; + { + eo.OverwriteMode = NExtract::NOverwriteMode::kOverwrite; + eo.OverwriteMode_Force = true; + } + } + + eo.PathMode = options.Command.GetPathMode(); + if (censorPathMode == NWildcard::k_AbsPath) + { + eo.PathMode = NExtract::NPathMode::kAbsPaths; + eo.PathMode_Force = true; + } + else if (censorPathMode == NWildcard::k_FullPath) + { + eo.PathMode = NExtract::NPathMode::kFullPaths; + eo.PathMode_Force = true; } } else if (options.Command.IsFromUpdateGroup()) { + if (parser[NKey::kArInclude].ThereIs) + throw CArcCmdLineException("-ai switch is not supported for this command"); + CUpdateOptions &updateOptions = options.UpdateOptions; SetAddCommandOptions(options.Command.CommandType, parser, updateOptions); - - SetMethodOptions(parser, updateOptions.MethodMode.Properties); - options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs; + updateOptions.MethodMode.Properties = options.Properties; - if (options.EnablePercents) - { - if ((options.StdOutMode && !options.IsStdErrTerminal) || - (!options.StdOutMode && !options.IsStdOutTerminal)) - options.EnablePercents = false; - } +#ifdef _WIN32 + if (parser[NKey::kShareForWrite].ThereIs) + updateOptions.OpenShareForWrite = true; +#endif + + updateOptions.PathMode = censorPathMode; + + updateOptions.AltStreams = options.AltStreams; + updateOptions.NtSecurity = options.NtSecurity; + updateOptions.HardLinks = options.HardLinks; + updateOptions.SymLinks = options.SymLinks; updateOptions.EMailMode = parser[NKey::kEmail].ThereIs; if (updateOptions.EMailMode) { updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front(); - if (updateOptions.EMailAddress.Length() > 0) + if (updateOptions.EMailAddress.Len() > 0) if (updateOptions.EMailAddress[0] == L'.') { updateOptions.EMailRemoveAfter = true; @@ -943,68 +1219,48 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) updateOptions.StdOutMode = options.StdOutMode; updateOptions.StdInMode = options.StdInMode; + updateOptions.DeleteAfterCompressing = parser[NKey::kDeleteAfterCompressing].ThereIs; + updateOptions.SetArcMTime = parser[NKey::kSetArcMTime].ThereIs; + if (updateOptions.StdOutMode && updateOptions.EMailMode) - throw "stdout mode and email mode cannot be combined"; + throw CArcCmdLineException("stdout mode and email mode cannot be combined"); if (updateOptions.StdOutMode && options.IsStdOutTerminal) - throw kTerminalOutError; + throw CArcCmdLineException(kTerminalOutError); if (updateOptions.StdInMode) updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front(); - #ifdef _WIN32 - ConvertToLongNames(options.WildcardCensor); - #endif + if (options.Command.CommandType == NCommandType::kRename) + if (updateOptions.Commands.Size() != 1) + throw CArcCmdLineException("Only one archive can be created with rename command"); } else if (options.Command.CommandType == NCommandType::kBenchmark) { - options.NumThreads = (UInt32)-1; - options.DictionarySize = (UInt32)-1; options.NumIterations = 1; if (curCommandIndex < numNonSwitchStrings) { - if (!ConvertStringToUInt32(nonSwitchStrings[curCommandIndex++], options.NumIterations)) - ThrowUserErrorException(); - } - for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) - { - UString postString = parser[NKey::kProperty].PostStrings[i]; - postString.MakeUpper(); - if (postString.Length() < 2) - ThrowUserErrorException(); - if (postString[0] == 'D') - { - int pos = 1; - if (postString[pos] == '=') - pos++; - UInt32 logSize; - if (!ConvertStringToUInt32((const wchar_t *)postString + pos, logSize)) - ThrowUserErrorException(); - if (logSize > 31) - ThrowUserErrorException(); - options.DictionarySize = 1 << logSize; - } - else if (postString[0] == 'M' && postString[1] == 'T' ) - { - int pos = 2; - if (postString[pos] == '=') - pos++; - if (postString[pos] != 0) - if (!ConvertStringToUInt32((const wchar_t *)postString + pos, options.NumThreads)) - ThrowUserErrorException(); - } - else if (postString[0] == 'M' && postString[1] == '=' ) - { - int pos = 2; - if (postString[pos] != 0) - options.Method = postString.Mid(2); - } - else - ThrowUserErrorException(); + if (!StringToUInt32(nonSwitchStrings[curCommandIndex], options.NumIterations)) + throw CArcCmdLineException("Incorrect Number of benmchmark iterations", nonSwitchStrings[curCommandIndex]); + curCommandIndex++; } } + else if (options.Command.CommandType == NCommandType::kHash) + { + options.Censor.AddPathsToCensor(censorPathMode); + options.Censor.ExtendExclude(); + + CHashOptions &hashOptions = options.HashOptions; + hashOptions.PathMode = censorPathMode; + hashOptions.Methods = options.HashMethods; +#ifdef _WIN32 + if (parser[NKey::kShareForWrite].ThereIs) + hashOptions.OpenShareForWrite = true; +#endif + hashOptions.StdInMode = options.StdInMode; + hashOptions.AltStreamsMode = options.AltStreams.Val; + } else if (options.Command.CommandType == NCommandType::kInfo) { } else - ThrowUserErrorException(); - options.WildcardCensor.ExtendExclude(); + throw 815676711; // FIXME 9815676711; } diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.h index bc7a99b0d..255e12c3c 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.h +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.h @@ -3,15 +3,16 @@ #ifndef __ARCHIVE_COMMAND_LINE_H #define __ARCHIVE_COMMAND_LINE_H -#include "Common/CommandLineParser.h" -#include "Common/Wildcard.h" +#include "../../../Common/CommandLineParser.h" +#include "../../../Common/Wildcard.h" #include "Extract.h" +#include "HashCalc.h" #include "Update.h" -struct CArchiveCommandLineException: public AString +struct CArcCmdLineException: public UString { - CArchiveCommandLineException(const char *errorMessage): AString(errorMessage) {} + CArcCmdLineException(const char *a, const wchar_t *u = NULL); }; namespace NCommandType { enum EEnum @@ -21,35 +22,33 @@ namespace NCommandType { enum EEnum kDelete, kTest, kExtract, - kFullExtract, + kExtractFull, kList, kBenchmark, - kInfo + kInfo, + kHash, + kRename };} -namespace NRecursedType { enum EEnum -{ - kRecursed, - kWildCardOnlyRecursed, - kNonRecursed -};} - -struct CArchiveCommand +struct CArcCommand { NCommandType::EEnum CommandType; + bool IsFromExtractGroup() const; bool IsFromUpdateGroup() const; - bool IsTestMode() const { return CommandType == NCommandType::kTest; } + bool IsTestCommand() const { return CommandType == NCommandType::kTest; } NExtract::NPathMode::EEnum GetPathMode() const; }; -struct CArchiveCommandLineOptions +struct CArcCmdLineOptions { bool HelpMode; #ifdef _7ZIP_LARGE_PAGES bool LargePages; #endif + bool CaseSensitiveChange; + bool CaseSensitive; bool IsInTerminal; bool IsStdOutTerminal; @@ -60,10 +59,9 @@ struct CArchiveCommandLineOptions bool YesToAll; bool ShowDialog; - // NWildcard::CCensor ArchiveWildcardCensor; - NWildcard::CCensor WildcardCensor; + NWildcard::CCensor Censor; - CArchiveCommand Command; + CArcCommand Command; UString ArchiveName; #ifndef _NO_CRYPTO @@ -72,39 +70,52 @@ struct CArchiveCommandLineOptions #endif bool TechMode; - // Extract - bool CalcCrc; + + UStringVector HashMethods; + bool AppendName; - UString OutputDir; - NExtract::NOverwriteMode::EEnum OverwriteMode; UStringVector ArchivePathsSorted; UStringVector ArchivePathsFullSorted; - CObjectVector ExtractProperties; + CObjectVector Properties; + + CExtractOptionsBase ExtractOptions; + + CBoolPair NtSecurity; + CBoolPair AltStreams; + CBoolPair HardLinks; + CBoolPair SymLinks; CUpdateOptions UpdateOptions; + CHashOptions HashOptions; UString ArcType; + UStringVector ExcludedArcTypes; bool EnablePercents; // Benchmark UInt32 NumIterations; - UInt32 NumThreads; - UInt32 DictionarySize; - UString Method; - - CArchiveCommandLineOptions(): StdInMode(false), StdOutMode(false) {}; + CArcCmdLineOptions(): + StdInMode(false), + StdOutMode(false), + CaseSensitiveChange(false), + CaseSensitive(false) + {}; }; -class CArchiveCommandLineParser +class CArcCmdLineParser { NCommandLineParser::CParser parser; public: - CArchiveCommandLineParser(); - void Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options); - void Parse2(CArchiveCommandLineOptions &options); + CArcCmdLineParser(); + void Parse1(const UStringVector &commandStrings, CArcCmdLineOptions &options); + void Parse2(CArcCmdLineOptions &options); }; -void EnumerateDirItemsAndSort(NWildcard::CCensor &wildcardCensor, +void EnumerateDirItemsAndSort( + bool storeAltStreams, + NWildcard::CCensor &censor, + NWildcard::ECensorPathMode pathMode, + const UString &addPathPrefix, UStringVector &sortedPaths, UStringVector &sortedFullPaths); diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp index 4c0cc90b5..250f66797 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp @@ -2,40 +2,200 @@ #include "StdAfx.h" -#include "Common/ComTry.h" -#include "Common/Wildcard.h" +#undef sprintf +#undef printf -#include "Windows/FileDir.h" -#include "Windows/FileFind.h" -#include "Windows/PropVariant.h" -#include "Windows/PropVariantConversions.h" +#include "../../../Common/ComTry.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/PropVariantConv.h" + +#if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX) +#define _USE_SECURITY_CODE +#include "../../../Windows/SecurityUtils.h" +#endif #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" +#include "../Common/PropIDUtils.h" #include "ArchiveExtractCallback.h" using namespace NWindows; +using namespace NFile; +using namespace NDir; + +static const char *kCantAutoRename = "Can not create file with auto name"; +static const char *kCantRenameFile = "Can not rename existing file"; +static const char *kCantDeleteOutputFile = "Can not delete output file"; +static const char *kCantDeleteOutputDir = "Can not delete output folder"; + + +#ifndef _SFX + +STDMETHODIMP COutStreamWithHash::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + HRESULT result = S_OK; + if (_stream) + result = _stream->Write(data, size, &size); + if (_calculate) + _hash->Update(data, size); + _size += size; + if (processedSize) + *processedSize = size; + return result; +} + +#endif + +#ifdef _USE_SECURITY_CODE +bool InitLocalPrivileges() +{ + NSecurity::CAccessToken token; + if (!token.OpenProcessToken(GetCurrentProcess(), + TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES)) + return false; -static const wchar_t *kCantAutoRename = L"ERROR: Can not create file with auto name"; -static const wchar_t *kCantRenameFile = L"ERROR: Can not rename existing file "; -static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; + TOKEN_PRIVILEGES tp; + + tp.PrivilegeCount = 1; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if (!::LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tp.Privileges[0].Luid)) + return false; + if (!token.AdjustPrivileges(&tp)) + return false; + return (GetLastError() == ERROR_SUCCESS); +} +#endif + +#ifdef SUPPORT_LINKS + +int CHardLinkNode::Compare(const CHardLinkNode &a) const +{ + if (StreamId < a.StreamId) return -1; + if (StreamId > a.StreamId) return 1; + return MyCompare(INode, a.INode); +} + +HRESULT Archive_Get_HardLinkNode(IInArchive *archive, UInt32 index, CHardLinkNode &h, bool &defined) +{ + h.INode = 0; + h.StreamId = (UInt64)(Int64)-1; + defined = false; + { + NCOM::CPropVariant prop; + RINOK(archive->GetProperty(index, kpidINode, &prop)); + if (!ConvertPropVariantToUInt64(prop, h.INode)) + return S_OK; + } + { + NCOM::CPropVariant prop; + RINOK(archive->GetProperty(index, kpidStreamId, &prop)); + ConvertPropVariantToUInt64(prop, h.StreamId); + } + defined = true; + return S_OK; +} + + +HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector *realIndices) +{ + _hardLinks.Clear(); + + if (!_arc->Ask_INode) + return S_OK; + + IInArchive *archive = _arc->Archive; + CRecordVector &hardIDs = _hardLinks.IDs; + + { + UInt32 numItems; + if (realIndices) + numItems = realIndices->Size(); + else + { + RINOK(archive->GetNumberOfItems(&numItems)); + } + + for (UInt32 i = 0; i < numItems; i++) + { + CHardLinkNode h; + bool defined; + RINOK(Archive_Get_HardLinkNode(archive, realIndices ? (*realIndices)[i] : i, h, defined)); + if (defined) + hardIDs.Add(h); + } + } + + hardIDs.Sort2(); + + { + // wee keep only items that have 2 or more items + unsigned k = 0; + unsigned numSame = 1; + for (unsigned i = 1; i < hardIDs.Size(); i++) + { + if (hardIDs[i].Compare(hardIDs[i - 1]) != 0) + numSame = 1; + else if (++numSame == 2) + { + if (i - 1 != k) + hardIDs[k] = hardIDs[i - 1]; + k++; + } + } + hardIDs.DeleteFrom(k); + } + + _hardLinks.PrepareLinks(); + return S_OK; +} + +#endif + +CArchiveExtractCallback::CArchiveExtractCallback(): + WriteCTime(true), + WriteATime(true), + WriteMTime(true), + _multiArchives(false) +{ + LocalProgressSpec = new CLocalProgress(); + _localProgress = LocalProgressSpec; + + #ifdef _USE_SECURITY_CODE + _saclEnabled = InitLocalPrivileges(); + #endif +} void CArchiveExtractCallback::Init( + const CExtractNtOptions &ntOptions, const NWildcard::CCensorNode *wildcardCensor, const CArc *arc, IFolderArchiveExtractCallback *extractCallback2, - bool stdOutMode, bool testMode, bool crcMode, - const UString &directoryPath, + bool stdOutMode, bool testMode, + const FString &directoryPath, const UStringVector &removePathParts, UInt64 packSize) { + _extractedFolderPaths.Clear(); + _extractedFolderIndices.Clear(); + + #ifdef SUPPORT_LINKS + _hardLinks.Clear(); + #endif + + _ntOptions = ntOptions; _wildcardCensor = wildcardCensor; _stdOutMode = stdOutMode; _testMode = testMode; - _crcMode = crcMode; _unpTotal = 1; _packTotal = packSize; @@ -43,14 +203,31 @@ void CArchiveExtractCallback::Init( _compressProgress.Release(); _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress); + #ifndef _SFX + + _extractCallback2.QueryInterface(IID_IFolderExtractToStreamCallback, &ExtractToStreamCallback); + if (ExtractToStreamCallback) + { + Int32 useStreams = 0; + if (ExtractToStreamCallback->UseExtractToStream(&useStreams) != S_OK) + useStreams = 0; + if (useStreams == 0) + ExtractToStreamCallback.Release(); + } + + #endif + LocalProgressSpec->Init(extractCallback2, true); LocalProgressSpec->SendProgress = false; - _removePathParts = removePathParts; + _baseParentFolder = (UInt32)(Int32)-1; + _use_baseParentFolder_mode = false; + _arc = arc; _directoryPath = directoryPath; - NFile::NName::NormalizeDirPathPrefix(_directoryPath); + NName::NormalizeDirPathPrefix(_directoryPath); + NDir::MyGetFullPathName(directoryPath, _directoryPathFull); } STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size) @@ -107,15 +284,48 @@ STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const U COM_TRY_END } -void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath) +#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z') + +static inline bool IsDriveName(const UString &s) { - fullPath = _directoryPath; - for (int i = 0; i < dirPathParts.Size(); i++) + return s.Len() == 2 && s[1] == ':' && IS_LETTER_CHAR(s[0]); +} + +void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath) +{ + bool isAbsPath = false; + + if (!dirPathParts.IsEmpty()) + { + const UString &s = dirPathParts[0]; + if (s.IsEmpty()) + isAbsPath = true; + #ifdef _WIN32 + else + { + if (dirPathParts.Size() > 1 && IsDriveName(s)) + isAbsPath = true; + } + #endif + } + + if (_pathMode == NExtract::NPathMode::kAbsPaths && isAbsPath) + fullPath.Empty(); + else + fullPath = _directoryPath; + + FOR_VECTOR (i, dirPathParts) { if (i > 0) - fullPath += wchar_t(NFile::NName::kDirDelimiter); - fullPath += dirPathParts[i]; - NFile::NDirectory::MyCreateDirectory(fullPath); + fullPath += FCHAR_PATH_SEPARATOR; + const UString &s = dirPathParts[i]; + fullPath += us2fs(s); + #ifdef _WIN32 + if (_pathMode == NExtract::NPathMode::kAbsPaths) + if (i == 0 && IsDriveName(s)) + continue; + #endif + CreateDir(fullPath); } } @@ -136,23 +346,100 @@ HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &fil HRESULT CArchiveExtractCallback::GetUnpackSize() { - NCOM::CPropVariant prop; - RINOK(_arc->Archive->GetProperty(_index, kpidSize, &prop)); - _curSizeDefined = (prop.vt != VT_EMPTY); - if (_curSizeDefined) - _curSize = ConvertPropVariantToUInt64(prop); - return S_OK; + return _arc->GetItemSize(_index, _curSize, _curSizeDefined); } +HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FString &path) +{ + return _extractCallback2->MessageError( + UString(L"ERROR: ") + + GetUnicodeString(message) + L": " + fs2us(path)); +} + +HRESULT CArchiveExtractCallback::SendMessageError2(const char *message, const FString &path1, const FString &path2) +{ + return _extractCallback2->MessageError( + UString(L"ERROR: ") + + GetUnicodeString(message) + UString(L": ") + fs2us(path1) + UString(L" : ") + fs2us(path2)); +} + +#ifndef _SFX + +STDMETHODIMP CGetProp::GetProp(PROPID propID, PROPVARIANT *value) +{ + if (propID == kpidName) + { + COM_TRY_BEGIN + NCOM::CPropVariant prop = Name.Ptr(); + prop.Detach(value); + return S_OK; + COM_TRY_END + } + return Arc->Archive->GetProperty(IndexInArc, propID, value); +} + +#endif + + +#ifdef SUPPORT_LINKS + +static UString GetDirPrefixOf(const UString &src) +{ + UString s = src; + if (!s.IsEmpty()) + { + if (s.Back() == WCHAR_PATH_SEPARATOR) + s.DeleteBack(); + int pos = s.ReverseFind(WCHAR_PATH_SEPARATOR); + s.DeleteFrom(pos + 1); + } + return s; +} + +static bool IsSafePath(const UString &path) +{ + UStringVector parts; + SplitPathToParts(path, parts); + int level = 0; + FOR_VECTOR(i, parts) + { + const UString &s = parts[i]; + if (s.IsEmpty()) + continue; + if (s == L".") + continue; + if (s == L"..") + { + if (level <= 0) + return false; + level--; + } + else + level++; + } + return level > 0; +} + +#endif + + STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { COM_TRY_BEGIN - _crcStream.Release(); + *outStream = 0; + + #ifndef _SFX + if (_hashStream) + _hashStreamSpec->ReleaseStream(); + _hashStreamWasUsed = false; + #endif + _outFileStream.Release(); _encrypted = false; _isSplit = false; + _isAltStream = false; _curSize = 0; _curSizeDefined = false; _index = index; @@ -161,7 +448,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre IInArchive *archive = _arc->Archive; RINOK(_arc->GetItemPath(index, fullPath)); - RINOK(IsArchiveItemFolder(archive, index, _fi.IsDir)); + RINOK(Archive_IsItem_Folder(archive, index, _fi.IsDir)); _filePath = fullPath; @@ -176,26 +463,220 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre _isSplit = true; } } - - RINOK(GetArchiveItemBoolProp(archive, index, kpidEncrypted, _encrypted)); + + #ifdef SUPPORT_LINKS + + bool isHardLink = false; + bool isJunction = false; + bool isRelative = false; + + UString linkPath; + // RINOK(Archive_GetItemBoolProp(archive, index, kpidIsHardLink, isHardLink)); + // if (isHardLink) + { + NCOM::CPropVariant prop; + RINOK(archive->GetProperty(index, kpidHardLink, &prop)); + if (prop.vt == VT_BSTR) + { + isHardLink = true; + linkPath = prop.bstrVal; + isRelative = false; // TAR: hard links are from root folder of archive + } + else if (prop.vt == VT_EMPTY) + { + // linkPath.Empty(); + } + else + return E_FAIL; + } + { + NCOM::CPropVariant prop; + RINOK(archive->GetProperty(index, kpidSymLink, &prop)); + if (prop.vt == VT_BSTR) + { + isHardLink = false; + linkPath = prop.bstrVal; + isRelative = true; // TAR: symbolic links are relative + } + else if (prop.vt == VT_EMPTY) + { + // linkPath.Empty(); + } + else + return E_FAIL; + } + + bool isOkReparse = false; + + if (linkPath.IsEmpty() && _arc->GetRawProps) + { + const void *data; + UInt32 dataSize; + UInt32 propType; + _arc->GetRawProps->GetRawProp(_index, kpidNtReparse, &data, &dataSize, &propType); + if (dataSize != 0) + { + if (propType != NPropDataType::kRaw) + return E_FAIL; + UString s; + CReparseAttr reparse; + isOkReparse = reparse.Parse((const Byte *)data, dataSize); + if (isOkReparse) + { + isHardLink = false; + linkPath = reparse.GetPath(); + isJunction = reparse.IsMountPoint(); + isRelative = reparse.IsRelative(); + #ifndef _WIN32 + linkPath.Replace(WCHAR_PATH_SEPARATOR, '/', ); + #endif + } + } + } + + if (!linkPath.IsEmpty()) + { + #ifdef _WIN32 + linkPath.Replace('/', WCHAR_PATH_SEPARATOR); + #endif + + for (;;) + // while (NName::IsAbsolutePath(linkPath)) + { + unsigned n = NName::GetRootPrefixSize(linkPath); + if (n == 0) + break; + isRelative = false; + linkPath.DeleteFrontal(n); + } + } + + if (!linkPath.IsEmpty() && !isRelative && _removePathParts.Size() != 0) + { + UStringVector pathParts; + SplitPathToParts(linkPath, pathParts); + bool badPrefix = false; + FOR_VECTOR (i, _removePathParts) + { + if (CompareFileNames(_removePathParts[i], pathParts[i]) != 0) + { + badPrefix = true; + break; + } + } + if (!badPrefix) + pathParts.DeleteFrontal(_removePathParts.Size()); + linkPath = MakePathNameFromParts(pathParts); + } + + #endif + + RINOK(Archive_GetItemBoolProp(archive, index, kpidEncrypted, _encrypted)); RINOK(GetUnpackSize()); + RINOK(Archive_IsItem_AltStream(archive, index, _isAltStream)); + + if (!_ntOptions.AltStreams.Val && _isAltStream) + return S_OK; + if (_wildcardCensor) { - if (!_wildcardCensor->CheckPath(fullPath, !_fi.IsDir)) + if (!_wildcardCensor->CheckPath(_isAltStream, fullPath, !_fi.IsDir)) return S_OK; } - if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) + + UStringVector pathParts; + + if (_use_baseParentFolder_mode) + { + int baseParent = _baseParentFolder; + if (_pathMode == NExtract::NPathMode::kFullPaths || + _pathMode == NExtract::NPathMode::kAbsPaths) + baseParent = -1; + RINOK(_arc->GetItemPathToParent(index, baseParent, pathParts)); + if (_pathMode == NExtract::NPathMode::kNoPaths && !pathParts.IsEmpty()) + pathParts.DeleteFrontal(pathParts.Size() - 1); + } + else + { + SplitPathToParts(fullPath, pathParts); + + if (pathParts.IsEmpty()) + return E_FAIL; + unsigned numRemovePathParts = 0; + + switch (_pathMode) + { + case NExtract::NPathMode::kCurPaths: + { + bool badPrefix = false; + if (pathParts.Size() <= _removePathParts.Size()) + badPrefix = true; + else + { + FOR_VECTOR (i, _removePathParts) + { + if (!_removePathParts[i].IsEqualToNoCase(pathParts[i])) + { + badPrefix = true; + break; + } + } + } + if (badPrefix) + { + if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) + return E_FAIL; + } + else + numRemovePathParts = _removePathParts.Size(); + break; + } + case NExtract::NPathMode::kNoPaths: + { + numRemovePathParts = pathParts.Size() - 1; + break; + } + /* + case NExtract::NPathMode::kFullPaths: + case NExtract::NPathMode::kAbsPaths: + break; + */ + } + + pathParts.DeleteFrontal(numRemovePathParts); + } + + #ifndef _SFX + + if (ExtractToStreamCallback) { - if (_stdOutMode) + if (!GetProp) { - CMyComPtr outStreamLoc = new CStdOutFileStream; - *outStream = outStreamLoc.Detach(); - return S_OK; + GetProp_Spec = new CGetProp; + GetProp = GetProp_Spec; } + GetProp_Spec->Arc = _arc; + GetProp_Spec->IndexInArc = index; + GetProp_Spec->Name = MakePathNameFromParts(pathParts); + + return ExtractToStreamCallback->GetStream7(GetProp_Spec->Name, _fi.IsDir, outStream, askExtractMode, GetProp); + } + + #endif + CMyComPtr outStreamLoc; + +if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) +{ + if (_stdOutMode) + { + outStreamLoc = new CStdOutFileStream; + } + else + { { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidAttrib, &prop)); @@ -217,35 +698,15 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre bool isAnti = false; RINOK(_arc->IsItemAnti(index, isAnti)); - UStringVector pathParts; - SplitPathToParts(fullPath, pathParts); - - if (pathParts.IsEmpty()) - return E_FAIL; - int numRemovePathParts = 0; - switch(_pathMode) - { - case NExtract::NPathMode::kFullPathnames: - break; - case NExtract::NPathMode::kCurrentPathnames: - { - numRemovePathParts = _removePathParts.Size(); - if (pathParts.Size() <= numRemovePathParts) - return E_FAIL; - for (int i = 0; i < numRemovePathParts; i++) - if (_removePathParts[i].CompareNoCase(pathParts[i]) != 0) - return E_FAIL; - break; - } - case NExtract::NPathMode::kNoPathnames: - { - numRemovePathParts = pathParts.Size() - 1; - break; - } - } - pathParts.Delete(0, numRemovePathParts); - MakeCorrectPath(pathParts); + bool replace = _isAltStream ? + _ntOptions.ReplaceColonForAltStream : + !_ntOptions.WriteToAltStreamIfColon; + + if (_pathMode != NExtract::NPathMode::kAbsPaths) + MakeCorrectPath(_directoryPath.IsEmpty(), pathParts, replace); + Correct_IfEmptyLastPart(pathParts); UString processedPath = MakePathNameFromParts(pathParts); + if (!isAnti) { if (!_fi.IsDir) @@ -253,142 +714,273 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre if (!pathParts.IsEmpty()) pathParts.DeleteBack(); } - + if (!pathParts.IsEmpty()) { - UString fullPathNew; + FString fullPathNew; CreateComplexDirectory(pathParts, fullPathNew); if (_fi.IsDir) - NFile::NDirectory::SetDirTime(fullPathNew, + { + _extractedFolderPaths.Add(fullPathNew); + _extractedFolderIndices.Add(index); + SetDirTime(fullPathNew, (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL, (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL, (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL)); + } } } - UString fullProcessedPath = _directoryPath + processedPath; + FString fullProcessedPath = us2fs(processedPath); + if (_pathMode != NExtract::NPathMode::kAbsPaths || + !NName::IsAbsolutePath(processedPath)) + fullProcessedPath = _directoryPath + fullProcessedPath; if (_fi.IsDir) { _diskFilePath = fullProcessedPath; if (isAnti) - NFile::NDirectory::MyRemoveDirectory(_diskFilePath); - return S_OK; + RemoveDir(_diskFilePath); + #ifdef SUPPORT_LINKS + if (linkPath.IsEmpty()) + #endif + return S_OK; } - - if (!_isSplit) + else if (!_isSplit) { - NFile::NFind::CFileInfoW fileInfo; + NFind::CFileInfo fileInfo; if (fileInfo.Find(fullProcessedPath)) { - switch(_overwriteMode) + switch (_overwriteMode) { - case NExtract::NOverwriteMode::kSkipExisting: + case NExtract::NOverwriteMode::kSkip: return S_OK; - case NExtract::NOverwriteMode::kAskBefore: + case NExtract::NOverwriteMode::kAsk: { + int slashPos = fullProcessedPath.ReverseFind(FTEXT('/')); + #ifdef _WIN32 + int slash1Pos = fullProcessedPath.ReverseFind(FTEXT('\\')); + slashPos = MyMax(slashPos, slash1Pos); + #endif + FString realFullProcessedPath = fullProcessedPath.Left(slashPos + 1) + fileInfo.Name; + Int32 overwiteResult; RINOK(_extractCallback2->AskOverwrite( - fullProcessedPath, &fileInfo.MTime, &fileInfo.Size, fullPath, + fs2us(realFullProcessedPath), &fileInfo.MTime, &fileInfo.Size, fullPath, _fi.MTimeDefined ? &_fi.MTime : NULL, _curSizeDefined ? &_curSize : NULL, &overwiteResult)) - switch(overwiteResult) + switch (overwiteResult) { - case NOverwriteAnswer::kCancel: - return E_ABORT; - case NOverwriteAnswer::kNo: - return S_OK; - case NOverwriteAnswer::kNoToAll: - _overwriteMode = NExtract::NOverwriteMode::kSkipExisting; - return S_OK; - case NOverwriteAnswer::kYesToAll: - _overwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; - break; - case NOverwriteAnswer::kYes: - break; - case NOverwriteAnswer::kAutoRename: - _overwriteMode = NExtract::NOverwriteMode::kAutoRename; - break; + case NOverwriteAnswer::kCancel: return E_ABORT; + case NOverwriteAnswer::kNo: return S_OK; + case NOverwriteAnswer::kNoToAll: _overwriteMode = NExtract::NOverwriteMode::kSkip; return S_OK; + case NOverwriteAnswer::kYes: break; + case NOverwriteAnswer::kYesToAll: _overwriteMode = NExtract::NOverwriteMode::kOverwrite; break; + case NOverwriteAnswer::kAutoRename: _overwriteMode = NExtract::NOverwriteMode::kRename; break; default: return E_FAIL; } } } - if (_overwriteMode == NExtract::NOverwriteMode::kAutoRename) + if (_overwriteMode == NExtract::NOverwriteMode::kRename) { if (!AutoRenamePath(fullProcessedPath)) { - UString message = UString(kCantAutoRename) + fullProcessedPath; - RINOK(_extractCallback2->MessageError(message)); + RINOK(SendMessageError(kCantAutoRename, fullProcessedPath)); return E_FAIL; } } - else if (_overwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting) + else if (_overwriteMode == NExtract::NOverwriteMode::kRenameExisting) { - UString existPath = fullProcessedPath; + FString existPath = fullProcessedPath; if (!AutoRenamePath(existPath)) { - UString message = kCantAutoRename + fullProcessedPath; - RINOK(_extractCallback2->MessageError(message)); + RINOK(SendMessageError(kCantAutoRename, fullProcessedPath)); return E_FAIL; } - if (!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath)) + // MyMoveFile can raname folders. So it's OK to use it folders too + if (!MyMoveFile(fullProcessedPath, existPath)) { - UString message = UString(kCantRenameFile) + fullProcessedPath; - RINOK(_extractCallback2->MessageError(message)); + RINOK(SendMessageError(kCantRenameFile, fullProcessedPath)); return E_FAIL; } } else - if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) + { + if (fileInfo.IsDir()) { - UString message = UString(kCantDeleteOutputFile) + fullProcessedPath; - RINOK(_extractCallback2->MessageError(message)); + // do we need to delete all files in folder? + if (!RemoveDir(fullProcessedPath)) + { + RINOK(SendMessageError(kCantDeleteOutputDir, fullProcessedPath)); + return S_OK; + } + } + else if (!DeleteFileAlways(fullProcessedPath)) + { + RINOK(SendMessageError(kCantDeleteOutputFile, fullProcessedPath)); return S_OK; // return E_FAIL; } + } } } + _diskFilePath = fullProcessedPath; + + if (!isAnti) { - _outFileStreamSpec = new COutFileStream; - CMyComPtr outStreamLoc(_outFileStreamSpec); - if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS)) + #ifdef SUPPORT_LINKS + + if (!linkPath.IsEmpty()) { - // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) + #ifndef UNDER_CE + + UString relatPath; + if (isRelative) + relatPath = GetDirPrefixOf(_filePath); + relatPath += linkPath; + + if (!IsSafePath(relatPath)) { - UString message = L"can not open output file " + fullProcessedPath; - RINOK(_extractCallback2->MessageError(message)); - return S_OK; + RINOK(SendMessageError("Dangerous link path was ignored", us2fs(relatPath))); } + else + { + FString existPath; + if (isHardLink || !isRelative) + { + if (!NName::GetFullPath(_directoryPathFull, us2fs(relatPath), existPath)) + { + RINOK(SendMessageError("Incorrect path", us2fs(relatPath))); + } + } + else + { + existPath = us2fs(linkPath); + } + + if (!existPath.IsEmpty()) + { + if (isHardLink) + { + if (!MyCreateHardLink(fullProcessedPath, existPath)) + { + RINOK(SendMessageError2("Can not create hard link", fullProcessedPath, existPath)); + // return S_OK; + } + } + else if (_ntOptions.SymLinks.Val) + { + // bool isSymLink = true; // = false for junction + if (_fi.IsDir && !isRelative) + { + // if it's before Vista we use Junction Point + // isJunction = true; + // convertToAbs = true; + } + + CByteBuffer data; + if (FillLinkData(data, fs2us(existPath), !isJunction)) + { + CReparseAttr attr; + if (!attr.Parse(data, data.Size())) + { + return E_FAIL; // "Internal conversion error"; + } + + if (!NFile::NIO::SetReparseData(fullProcessedPath, _fi.IsDir, data, (DWORD)data.Size())) + { + RINOK(SendMessageError("Can not set reparse data", fullProcessedPath)); + } + } + } + } + } + + #endif } - if (_isSplit) + else + #endif // SUPPORT_LINKS { - RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL)); + bool needWriteFile = true; + + #ifdef SUPPORT_LINKS + if (!_hardLinks.IDs.IsEmpty()) + { + CHardLinkNode h; + bool defined; + RINOK(Archive_Get_HardLinkNode(archive, index, h, defined)); + if (defined) + { + { + int linkIndex = _hardLinks.IDs.FindInSorted2(h); + if (linkIndex >= 0) + { + FString &hl = _hardLinks.Links[linkIndex]; + if (hl.IsEmpty()) + hl = fullProcessedPath; + else + { + if (!MyCreateHardLink(fullProcessedPath, hl)) + { + RINOK(SendMessageError2("Can not create hard link", fullProcessedPath, hl)); + return S_OK; + } + needWriteFile = false; + } + } + } + } + } + #endif + + if (needWriteFile) + { + _outFileStreamSpec = new COutFileStream; + CMyComPtr outStreamLoc(_outFileStreamSpec); + if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS)) + { + // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) + { + RINOK(SendMessageError("Can not open output file ", fullProcessedPath)); + return S_OK; + } + } + if (_isSplit) + { + RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL)); + } + _outFileStream = outStreamLoc; + } } - _outFileStream = outStreamLoc; - *outStream = outStreamLoc.Detach(); } - _diskFilePath = fullProcessedPath; - } - else - { - *outStream = NULL; + + outStreamLoc = _outFileStream; } - if (_crcMode) +} + + #ifndef _SFX + + if (_hashStream) { - _crcStreamSpec = new COutStreamWithCRC; - _crcStream = _crcStreamSpec; - CMyComPtr crcStream = _crcStreamSpec; - _crcStreamSpec->SetStream(*outStream); - if (*outStream) - (*outStream)->Release(); - *outStream = crcStream.Detach(); - _crcStreamSpec->Init(true); + if (askExtractMode == NArchive::NExtract::NAskMode::kExtract || + askExtractMode == NArchive::NExtract::NAskMode::kTest) + { + _hashStreamSpec->SetStream(outStreamLoc); + outStreamLoc = _hashStream; + _hashStreamSpec->Init(true); + _hashStreamWasUsed = true; + } } + + #endif + + if (outStreamLoc) + *outStream = outStreamLoc.Detach(); return S_OK; COM_TRY_END } @@ -396,6 +988,12 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) { COM_TRY_BEGIN + + #ifndef _SFX + if (ExtractToStreamCallback) + return ExtractToStreamCallback->PrepareOperation7(askExtractMode); + #endif + _extractMode = false; switch (askExtractMode) { @@ -414,24 +1012,25 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) { COM_TRY_BEGIN - switch(operationResult) - { - case NArchive::NExtract::NOperationResult::kOK: - case NArchive::NExtract::NOperationResult::kUnSupportedMethod: - case NArchive::NExtract::NOperationResult::kCRCError: - case NArchive::NExtract::NOperationResult::kDataError: - break; - default: - _outFileStream.Release(); - return E_FAIL; - } - if (_crcStream) + + #ifndef _SFX + if (ExtractToStreamCallback) + return ExtractToStreamCallback->SetOperationResult7(operationResult, _encrypted); + #endif + + #ifndef _SFX + + if (_hashStreamWasUsed) { - CrcSum += _crcStreamSpec->GetCRC(); - _curSize = _crcStreamSpec->GetSize(); + _hashStreamSpec->_hash->Final(_fi.IsDir, _isAltStream, _filePath); + _curSize = _hashStreamSpec->GetSize(); _curSizeDefined = true; - _crcStream.Release(); + _hashStreamSpec->ReleaseStream(); + _hashStreamWasUsed = false; } + + #endif + if (_outFileStream) { _outFileStreamSpec->SetTime( @@ -443,17 +1042,48 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) RINOK(_outFileStreamSpec->Close()); _outFileStream.Release(); } + + #ifdef _USE_SECURITY_CODE + if (_ntOptions.NtSecurity.Val && _arc->GetRawProps) + { + const void *data; + UInt32 dataSize; + UInt32 propType; + _arc->GetRawProps->GetRawProp(_index, kpidNtSecure, &data, &dataSize, &propType); + if (dataSize != 0) + { + if (propType != NPropDataType::kRaw) + return E_FAIL; + if (CheckNtSecure((const Byte *)data, dataSize)) + { + SECURITY_INFORMATION securInfo = DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION; + if (_saclEnabled) + securInfo |= SACL_SECURITY_INFORMATION; + ::SetFileSecurityW(fs2us(_diskFilePath), securInfo, (PSECURITY_DESCRIPTOR)(void *)data); + } + } + } + #endif + if (!_curSizeDefined) GetUnpackSize(); if (_curSizeDefined) - UnpackSize += _curSize; + { + if (_isAltStream) + AltStreams_UnpackSize += _curSize; + else + UnpackSize += _curSize; + } + if (_fi.IsDir) NumFolders++; + else if (_isAltStream) + NumAltStreams++; else NumFiles++; if (_extractMode && _fi.AttribDefined) - NFile::NDirectory::MySetFileAttributes(_diskFilePath, _fi.Attrib); + SetFileAttrib(_diskFilePath, _fi.Attrib); RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted)); return S_OK; COM_TRY_END @@ -486,3 +1116,76 @@ STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) COM_TRY_END } + +struct CExtrRefSortPair +{ + int Len; + int Index; + + int Compare(const CExtrRefSortPair &a) const; +}; + +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } + +int CExtrRefSortPair::Compare(const CExtrRefSortPair &a) const +{ + RINOZ(-MyCompare(Len, a.Len)); + return MyCompare(Index, a.Index); +} + +static int GetNumSlashes(const FChar *s) +{ + for (int numSlashes = 0;;) + { + FChar c = *s++; + if (c == 0) + return numSlashes; + if ( + #ifdef _WIN32 + c == FTEXT('\\') || + #endif + c == FTEXT('/')) + numSlashes++; + } +} + +HRESULT CArchiveExtractCallback::SetDirsTimes() +{ + CRecordVector pairs; + pairs.ClearAndSetSize(_extractedFolderPaths.Size()); + unsigned i; + + for (i = 0; i < _extractedFolderPaths.Size(); i++) + { + CExtrRefSortPair &pair = pairs[i]; + pair.Index = i; + pair.Len = GetNumSlashes(_extractedFolderPaths[i]); + } + + pairs.Sort2(); + + for (i = 0; i < pairs.Size(); i++) + { + int pairIndex = pairs[i].Index; + int index = _extractedFolderIndices[pairIndex]; + + FILETIME CTime; + FILETIME ATime; + FILETIME MTime; + + bool CTimeDefined; + bool ATimeDefined; + bool MTimeDefined; + + RINOK(GetTime(index, kpidCTime, CTime, CTimeDefined)); + RINOK(GetTime(index, kpidATime, ATime, ATimeDefined)); + RINOK(GetTime(index, kpidMTime, MTime, MTimeDefined)); + + // printf("\n%S", _extractedFolderPaths[pairIndex]); + SetDirTime(_extractedFolderPaths[pairIndex], + (WriteCTime && CTimeDefined) ? &CTime : NULL, + (WriteATime && ATimeDefined) ? &ATime : NULL, + (WriteMTime && MTimeDefined) ? &MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL)); + } + return S_OK; +} diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.h index 367e4b07d..374297651 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.h +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.h @@ -3,8 +3,8 @@ #ifndef __ARCHIVE_EXTRACT_CALLBACK_H #define __ARCHIVE_EXTRACT_CALLBACK_H -#include "Common/MyCom.h" -#include "Common/Wildcard.h" +#include "../../../Common/MyCom.h" +#include "../../../Common/Wildcard.h" #include "../../IPassword.h" @@ -13,12 +13,117 @@ #include "../../Archive/IArchive.h" -#include "../../Archive/Common/OutStreamWithCRC.h" - #include "ExtractMode.h" #include "IFileExtractCallback.h" #include "OpenArchive.h" +#include "HashCalc.h" + +#ifndef _SFX + +class COutStreamWithHash: + public ISequentialOutStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + UInt64 _size; + bool _calculate; +public: + IHashCalc *_hash; + + MY_UNKNOWN_IMP + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + void SetStream(ISequentialOutStream *stream) { _stream = stream; } + void ReleaseStream() { _stream.Release(); } + void Init(bool calculate = true) + { + InitCRC(); + _size = 0; + _calculate = calculate; + } + void EnableCalc(bool calculate) { _calculate = calculate; } + void InitCRC() { _hash->InitForNewFile(); } + UInt64 GetSize() const { return _size; } +}; + +#endif + +struct CExtractNtOptions +{ + CBoolPair NtSecurity; + CBoolPair SymLinks; + CBoolPair HardLinks; + CBoolPair AltStreams; + bool ReplaceColonForAltStream; + bool WriteToAltStreamIfColon; + + CExtractNtOptions(): + ReplaceColonForAltStream(false), + WriteToAltStreamIfColon(false) + { + SymLinks.Val = true; + HardLinks.Val = true; + AltStreams.Val = true; + } +}; + +#ifndef _SFX + +class CGetProp: + public IGetProp, + public CMyUnknownImp +{ +public: + const CArc *Arc; + UInt32 IndexInArc; + UString Name; // relative path + + MY_UNKNOWN_IMP1(IGetProp) + INTERFACE_IGetProp(;) +}; + +#endif + +#ifndef _SFX +#ifndef UNDER_CE + +// FIXME #define SUPPORT_LINKS + +#endif +#endif + + +#ifdef SUPPORT_LINKS + +struct CHardLinkNode +{ + UInt64 StreamId; + UInt64 INode; + + int Compare(const CHardLinkNode &a) const; +}; + +class CHardLinks +{ +public: + CRecordVector IDs; + CObjectVector Links; + + void Clear() + { + IDs.Clear(); + Links.Clear(); + } + + void PrepareLinks() + { + while (Links.Size() < IDs.Size()) + Links.AddNew(); + } +}; + +#endif + class CArchiveExtractCallback: public IArchiveExtractCallback, // public IArchiveVolumeExtractCallback, @@ -27,18 +132,30 @@ class CArchiveExtractCallback: public CMyUnknownImp { const CArc *_arc; + CExtractNtOptions _ntOptions; + const NWildcard::CCensorNode *_wildcardCensor; CMyComPtr _extractCallback2; CMyComPtr _compressProgress; CMyComPtr _cryptoGetTextPassword; - UString _directoryPath; + FString _directoryPath; + FString _directoryPathFull; NExtract::NPathMode::EEnum _pathMode; NExtract::NOverwriteMode::EEnum _overwriteMode; - UString _diskFilePath; + #ifndef _SFX + + CMyComPtr ExtractToStreamCallback; + CGetProp *GetProp_Spec; + CMyComPtr GetProp; + + #endif + + FString _diskFilePath; UString _filePath; UInt64 _position; bool _isSplit; + bool _isAltStream; bool _extractMode; @@ -54,7 +171,7 @@ class CArchiveExtractCallback: FILETIME ATime; FILETIME MTime; UInt32 Attrib; - + bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; @@ -69,33 +186,50 @@ class CArchiveExtractCallback: COutFileStream *_outFileStreamSpec; CMyComPtr _outFileStream; - COutStreamWithCRC *_crcStreamSpec; - CMyComPtr _crcStream; + #ifndef _SFX + + COutStreamWithHash *_hashStreamSpec; + CMyComPtr _hashStream; + bool _hashStreamWasUsed; + + #endif UStringVector _removePathParts; + bool _use_baseParentFolder_mode; + UInt32 _baseParentFolder; bool _stdOutMode; bool _testMode; - bool _crcMode; bool _multiArchives; CMyComPtr _localProgress; UInt64 _packTotal; UInt64 _unpTotal; - void CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath); + FStringVector _extractedFolderPaths; + CRecordVector _extractedFolderIndices; + + #if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX) + bool _saclEnabled; + #endif + + void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath); HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined); HRESULT GetUnpackSize(); + HRESULT SendMessageError(const char *message, const FString &path); + HRESULT SendMessageError2(const char *message, const FString &path1, const FString &path2); + public: CLocalProgress *LocalProgressSpec; UInt64 NumFolders; UInt64 NumFiles; + UInt64 NumAltStreams; UInt64 UnpackSize; - UInt32 CrcSum; - + UInt64 AltStreams_UnpackSize; + MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo) // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback) @@ -108,15 +242,7 @@ public: STDMETHOD(CryptoGetTextPassword)(BSTR *password); - CArchiveExtractCallback(): - WriteCTime(true), - WriteATime(true), - WriteMTime(true), - _multiArchives(false) - { - LocalProgressSpec = new CLocalProgress(); - _localProgress = LocalProgressSpec; - } + CArchiveExtractCallback(); void InitForMulti(bool multiArchives, NExtract::NPathMode::EEnum pathMode, @@ -125,19 +251,49 @@ public: _multiArchives = multiArchives; _pathMode = pathMode; _overwriteMode = overwriteMode; - NumFolders = NumFiles = UnpackSize = 0; - CrcSum = 0; + NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0; + } + + #ifndef _SFX + + void SetHashMethods(IHashCalc *hash) + { + if (!hash) + return; + _hashStreamSpec = new COutStreamWithHash; + _hashStream = _hashStreamSpec; + _hashStreamSpec->_hash = hash; } + #endif + void Init( + const CExtractNtOptions &ntOptions, const NWildcard::CCensorNode *wildcardCensor, const CArc *arc, IFolderArchiveExtractCallback *extractCallback2, - bool stdOutMode, bool testMode, bool crcMode, - const UString &directoryPath, + bool stdOutMode, bool testMode, + const FString &directoryPath, const UStringVector &removePathParts, UInt64 packSize); + #ifdef SUPPORT_LINKS +private: + CHardLinks _hardLinks; +public: + // call PrepareHardLinks() after Init() + HRESULT PrepareHardLinks(const CRecordVector *realIndices); // NULL means all items + #endif + + // call it after Init() + + void SetBaseParentFolderIndex(UInt32 indexInArc) + { + _use_baseParentFolder_mode = true; + _baseParentFolder = indexInArc; + } + + HRESULT SetDirsTimes(); }; #endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveName.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveName.cpp deleted file mode 100644 index c3684def8..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveName.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// ArchiveName.cpp - -#include "StdAfx.h" - -#include "Windows/FileDir.h" -#include "Windows/FileFind.h" - -#include "ExtractingFilePath.h" - -using namespace NWindows; - -static UString CreateArchiveName2(const UString &srcName, bool fromPrev, bool keepName) -{ - UString resultName = L"Archive"; - if (fromPrev) - { - UString dirPrefix; - if (NFile::NDirectory::GetOnlyDirPrefix(srcName, dirPrefix)) - { - if (dirPrefix.Length() > 0) - if (dirPrefix[dirPrefix.Length() - 1] == WCHAR_PATH_SEPARATOR) - { - dirPrefix.Delete(dirPrefix.Length() - 1); - NFile::NFind::CFileInfoW fileInfo; - if (fileInfo.Find(dirPrefix)) - resultName = fileInfo.Name; - } - } - } - else - { - NFile::NFind::CFileInfoW fileInfo; - if (!fileInfo.Find(srcName)) - // return resultName; - return srcName; - resultName = fileInfo.Name; - if (!fileInfo.IsDir() && !keepName) - { - int dotPos = resultName.ReverseFind('.'); - if (dotPos > 0) - { - UString archiveName2 = resultName.Left(dotPos); - if (archiveName2.ReverseFind('.') < 0) - resultName = archiveName2; - } - } - } - return resultName; -} - -UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) -{ - return GetCorrectFsPath(CreateArchiveName2(srcName, fromPrev, keepName)); -} diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveName.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveName.h deleted file mode 100644 index 9513fb2ba..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveName.h +++ /dev/null @@ -1,10 +0,0 @@ -// ArchiveName.h - -#ifndef __ARCHIVENAME_H -#define __ARCHIVENAME_H - -#include "Common/MyString.h" - -UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName); - -#endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp index e7e617131..9eab39d31 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp @@ -2,10 +2,10 @@ #include "StdAfx.h" -#include "Common/StringConvert.h" -#include "Common/ComTry.h" +#include "../../../Common/ComTry.h" -#include "Windows/PropVariant.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/PropVariant.h" #include "../../Common/FileStreams.h" @@ -34,7 +34,7 @@ STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *b return Callback->Open_SetCompleted(files, bytes); COM_TRY_END } - + STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN @@ -60,55 +60,48 @@ STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value) COM_TRY_END } -int COpenCallbackImp::FindName(const UString &name) -{ - for (int i = 0; i < FileNames.Size(); i++) - if (name.CompareNoCase(FileNames[i]) == 0) - return i; - return -1; -} - struct CInFileStreamVol: public CInFileStream { - UString Name; + int FileNameIndex; COpenCallbackImp *OpenCallbackImp; CMyComPtr OpenCallbackRef; + CInFileStreamVol(bool ignoreLink = false) : CInFileStream(ignoreLink) { } ~CInFileStreamVol() { if (OpenCallbackRef) - { - int index = OpenCallbackImp->FindName(Name); - if (index >= 0) - OpenCallbackImp->FileNames.Delete(index); - } + OpenCallbackImp->FileNames_WasUsed[FileNameIndex] = false; } }; STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream) { COM_TRY_BEGIN + *inStream = NULL; if (_subArchiveMode) return S_FALSE; if (Callback) { RINOK(Callback->Open_CheckBreak()); } - *inStream = NULL; - UString fullPath = _folderPrefix + name; - if (!_fileInfo.Find(fullPath)) + FString fullPath; + if (!NFile::NName::GetFullPath(_folderPrefix, us2fs(name), fullPath)) + return S_FALSE; + if (!_fileInfo.Find(fullPath,true)) return S_FALSE; if (_fileInfo.IsDir()) return S_FALSE; - CInFileStreamVol *inFile = new CInFileStreamVol; + CInFileStreamVol *inFile = new CInFileStreamVol(true); CMyComPtr inStreamTemp = inFile; if (!inFile->Open(fullPath)) return ::GetLastError(); - *inStream = inStreamTemp.Detach(); - inFile->Name = name; + + FileSizes.Add(_fileInfo.Size); + FileNames.Add(name); + inFile->FileNameIndex = FileNames_WasUsed.Add(true); inFile->OpenCallbackImp = this; inFile->OpenCallbackRef = this; - FileNames.Add(name); - TotalSize += _fileInfo.Size; + // TotalSize += _fileInfo.Size; + *inStream = inStreamTemp.Detach(); return S_OK; COM_TRY_END } @@ -130,4 +123,3 @@ STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password) COM_TRY_END } #endif - diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.h index c6651e8f9..b72892c2f 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.h +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.h @@ -3,10 +3,9 @@ #ifndef __ARCHIVE_OPEN_CALLBACK_H #define __ARCHIVE_OPEN_CALLBACK_H -#include "Common/MyCom.h" -#include "Common/MyString.h" +#include "../../../Common/MyCom.h" -#include "Windows/FileFind.h" +#include "../../../Windows/FileFind.h" #ifndef _NO_CRYPTO #include "../../IPassword.h" @@ -21,10 +20,10 @@ #define INTERFACE_IOpenCallbackUI_Crypto(x) \ virtual HRESULT Open_CryptoGetTextPassword(BSTR *password) x; \ - virtual HRESULT Open_GetPasswordIfAny(UString &password) x; \ + virtual HRESULT Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) x; \ virtual bool Open_WasPasswordAsked() x; \ virtual void Open_ClearPasswordWasAskedFlag() x; \ - + #endif #define INTERFACE_IOpenCallbackUI(x) \ @@ -72,32 +71,41 @@ public: { _subArchiveMode = true; _subArchiveName = name; - TotalSize = 0; - return S_OK; + // TotalSize = 0; + return S_OK; } private: - UString _folderPrefix; - NWindows::NFile::NFind::CFileInfoW _fileInfo; + FString _folderPrefix; + NWindows::NFile::NFind::CFileInfo _fileInfo; bool _subArchiveMode; UString _subArchiveName; + public: UStringVector FileNames; + CBoolVector FileNames_WasUsed; + CRecordVector FileSizes; + IOpenCallbackUI *Callback; CMyComPtr ReOpenCallback; - UInt64 TotalSize; + // UInt64 TotalSize; COpenCallbackImp(): Callback(NULL) {} - void Init(const UString &folderPrefix, const UString &fileName) + void Init(const FString &folderPrefix, const FString &fileName) { _folderPrefix = folderPrefix; - if (!_fileInfo.Find(_folderPrefix + fileName)) - throw 1; + if (!_fileInfo.Find(_folderPrefix + fileName,true)) + throw 20121118; FileNames.Clear(); + FileNames_WasUsed.Clear(); + FileSizes.Clear(); _subArchiveMode = false; - TotalSize = 0; + // TotalSize = 0; + } + bool SetSecondFileInfo(CFSTR newName) + { + return _fileInfo.Find(newName) && !_fileInfo.IsDir(); } - int FindName(const UString &name); }; #endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Bench.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/Bench.cpp deleted file mode 100644 index 282f405f1..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/Bench.cpp +++ /dev/null @@ -1,1028 +0,0 @@ -// Bench.cpp - -#include "StdAfx.h" - -#include "Bench.h" - -#ifndef _WIN32 -#define USE_POSIX_TIME -#define USE_POSIX_TIME2 -#endif - -#ifdef USE_POSIX_TIME -#include -#ifdef USE_POSIX_TIME2 -#include -#endif -#endif - -#ifdef _WIN32 -#define USE_ALLOCA -#endif - -#ifdef USE_ALLOCA -#ifdef _WIN32 -#include -#else -#include -#endif -#endif - -#include "../../../../C/7zCrc.h" -#include "../../../../C/Alloc.h" - -#ifndef _7ZIP_ST -#include "../../../Windows/Synchronization.h" -#include "../../../Windows/Thread.h" -#endif - -#include "../../../Windows/PropVariant.h" - -static const UInt32 kUncompressMinBlockSize = -#ifdef UNDER_CE -1 << 24; -#else -1 << 26; -#endif - -static const UInt32 kCrcBlockSize = -#ifdef UNDER_CE -1 << 25; -#else -1 << 30; -#endif - -static const UInt32 kAdditionalSize = (1 << 16); -static const UInt32 kCompressedAdditionalSize = (1 << 10); -static const UInt32 kMaxLzmaPropSize = 5; - -class CBaseRandomGenerator -{ - UInt32 A1; - UInt32 A2; -public: - CBaseRandomGenerator() { Init(); } - void Init() { A1 = 362436069; A2 = 521288629;} - UInt32 GetRnd() - { - return - ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) + - ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) ); - } -}; - -class CBenchBuffer -{ -public: - size_t BufferSize; - Byte *Buffer; - CBenchBuffer(): Buffer(0) {} - virtual ~CBenchBuffer() { Free(); } - void Free() - { - ::MidFree(Buffer); - Buffer = 0; - } - bool Alloc(size_t bufferSize) - { - if (Buffer != 0 && BufferSize == bufferSize) - return true; - Free(); - Buffer = (Byte *)::MidAlloc(bufferSize); - BufferSize = bufferSize; - return (Buffer != 0); - } -}; - -class CBenchRandomGenerator: public CBenchBuffer -{ - CBaseRandomGenerator *RG; -public: - void Set(CBaseRandomGenerator *rg) { RG = rg; } - UInt32 GetVal(UInt32 &res, int numBits) - { - UInt32 val = res & (((UInt32)1 << numBits) - 1); - res >>= numBits; - return val; - } - UInt32 GetLen(UInt32 &res) - { - UInt32 len = GetVal(res, 2); - return GetVal(res, 1 + len); - } - void Generate() - { - UInt32 pos = 0; - UInt32 rep0 = 1; - while (pos < BufferSize) - { - UInt32 res = RG->GetRnd(); - res >>= 1; - if (GetVal(res, 1) == 0 || pos < 1024) - Buffer[pos++] = (Byte)(res & 0xFF); - else - { - UInt32 len; - len = 1 + GetLen(res); - if (GetVal(res, 3) != 0) - { - len += GetLen(res); - do - { - UInt32 ppp = GetVal(res, 5) + 6; - res = RG->GetRnd(); - if (ppp > 30) - continue; - rep0 = /* (1 << ppp) +*/ GetVal(res, ppp); - res = RG->GetRnd(); - } - while (rep0 >= pos); - rep0++; - } - - for (UInt32 i = 0; i < len && pos < BufferSize; i++, pos++) - Buffer[pos] = Buffer[pos - rep0]; - } - } - } -}; - - -class CBenchmarkInStream: - public ISequentialInStream, - public CMyUnknownImp -{ - const Byte *Data; - size_t Pos; - size_t Size; -public: - MY_UNKNOWN_IMP - void Init(const Byte *data, size_t size) - { - Data = data; - Size = size; - Pos = 0; - } - STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); -}; - -STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize) -{ - size_t remain = Size - Pos; - UInt32 kMaxBlockSize = (1 << 20); - if (size > kMaxBlockSize) - size = kMaxBlockSize; - if (size > remain) - size = (UInt32)remain; - for (UInt32 i = 0; i < size; i++) - ((Byte *)data)[i] = Data[Pos + i]; - Pos += size; - if(processedSize != NULL) - *processedSize = size; - return S_OK; -} - -class CBenchmarkOutStream: - public ISequentialOutStream, - public CBenchBuffer, - public CMyUnknownImp -{ - // bool _overflow; -public: - UInt32 Pos; - // CBenchmarkOutStream(): _overflow(false) {} - void Init() - { - // _overflow = false; - Pos = 0; - } - MY_UNKNOWN_IMP - STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); -}; - -STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) -{ - size_t curSize = BufferSize - Pos; - if (curSize > size) - curSize = size; - memcpy(Buffer + Pos, data, curSize); - Pos += (UInt32)curSize; - if(processedSize != NULL) - *processedSize = (UInt32)curSize; - if (curSize != size) - { - // _overflow = true; - return E_FAIL; - } - return S_OK; -} - -class CCrcOutStream: - public ISequentialOutStream, - public CMyUnknownImp -{ -public: - UInt32 Crc; - MY_UNKNOWN_IMP - void Init() { Crc = CRC_INIT_VAL; } - STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); -}; - -STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) -{ - Crc = CrcUpdate(Crc, data, size); - if (processedSize != NULL) - *processedSize = size; - return S_OK; -} - -static UInt64 GetTimeCount() -{ - #ifdef USE_POSIX_TIME - #ifdef USE_POSIX_TIME2 - timeval v; - if (gettimeofday(&v, 0) == 0) - return (UInt64)(v.tv_sec) * 1000000 + v.tv_usec; - return (UInt64)time(NULL) * 1000000; - #else - return time(NULL); - #endif - #else - /* - LARGE_INTEGER value; - if (::QueryPerformanceCounter(&value)) - return value.QuadPart; - */ - return GetTickCount(); - #endif -} - -static UInt64 GetFreq() -{ - #ifdef USE_POSIX_TIME - #ifdef USE_POSIX_TIME2 - return 1000000; - #else - return 1; - #endif - #else - /* - LARGE_INTEGER value; - if (::QueryPerformanceFrequency(&value)) - return value.QuadPart; - */ - return 1000; - #endif -} - -#ifndef USE_POSIX_TIME -static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } -#endif - -static UInt64 GetUserTime() -{ - #ifdef USE_POSIX_TIME - return clock(); - #else - FILETIME creationTime, exitTime, kernelTime, userTime; - if ( - #ifdef UNDER_CE - ::GetThreadTimes(::GetCurrentThread() - #else - ::GetProcessTimes(::GetCurrentProcess() - #endif - , &creationTime, &exitTime, &kernelTime, &userTime) != 0) - return GetTime64(userTime) + GetTime64(kernelTime); - return (UInt64)GetTickCount() * 10000; - #endif -} - -static UInt64 GetUserFreq() -{ - #ifdef USE_POSIX_TIME - return CLOCKS_PER_SEC; - #else - return 10000000; - #endif -} - -class CBenchProgressStatus -{ - #ifndef _7ZIP_ST - NWindows::NSynchronization::CCriticalSection CS; - #endif -public: - HRESULT Res; - bool EncodeMode; - void SetResult(HRESULT res) - { - #ifndef _7ZIP_ST - NWindows::NSynchronization::CCriticalSectionLock lock(CS); - #endif - Res = res; - } - HRESULT GetResult() - { - #ifndef _7ZIP_ST - NWindows::NSynchronization::CCriticalSectionLock lock(CS); - #endif - return Res; - } -}; - -class CBenchProgressInfo: - public ICompressProgressInfo, - public CMyUnknownImp -{ -public: - CBenchProgressStatus *Status; - CBenchInfo BenchInfo; - HRESULT Res; - IBenchCallback *callback; - CBenchProgressInfo(): callback(0) {} - MY_UNKNOWN_IMP - STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); -}; - -static void SetStartTime(CBenchInfo &bi) -{ - bi.GlobalFreq = GetFreq(); - bi.UserFreq = GetUserFreq(); - bi.GlobalTime = ::GetTimeCount(); - bi.UserTime = ::GetUserTime(); -} - -static void SetFinishTime(const CBenchInfo &biStart, CBenchInfo &dest) -{ - dest.GlobalFreq = GetFreq(); - dest.UserFreq = GetUserFreq(); - dest.GlobalTime = ::GetTimeCount() - biStart.GlobalTime; - dest.UserTime = ::GetUserTime() - biStart.UserTime; -} - -STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) -{ - HRESULT res = Status->GetResult(); - if (res != S_OK) - return res; - if (!callback) - return res; - CBenchInfo info = BenchInfo; - SetFinishTime(BenchInfo, info); - if (Status->EncodeMode) - { - info.UnpackSize = *inSize; - info.PackSize = *outSize; - res = callback->SetEncodeResult(info, false); - } - else - { - info.PackSize = BenchInfo.PackSize + *inSize; - info.UnpackSize = BenchInfo.UnpackSize + *outSize; - res = callback->SetDecodeResult(info, false); - } - if (res != S_OK) - Status->SetResult(res); - return res; -} - -static const int kSubBits = 8; - -static UInt32 GetLogSize(UInt32 size) -{ - for (int i = kSubBits; i < 32; i++) - for (UInt32 j = 0; j < (1 << kSubBits); j++) - if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) - return (i << kSubBits) + j; - return (32 << kSubBits); -} - -static void NormalizeVals(UInt64 &v1, UInt64 &v2) -{ - while (v1 > 1000000) - { - v1 >>= 1; - v2 >>= 1; - } -} - -UInt64 GetUsage(const CBenchInfo &info) -{ - UInt64 userTime = info.UserTime; - UInt64 userFreq = info.UserFreq; - UInt64 globalTime = info.GlobalTime; - UInt64 globalFreq = info.GlobalFreq; - NormalizeVals(userTime, userFreq); - NormalizeVals(globalFreq, globalTime); - if (userFreq == 0) - userFreq = 1; - if (globalTime == 0) - globalTime = 1; - return userTime * globalFreq * 1000000 / userFreq / globalTime; -} - -UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating) -{ - UInt64 userTime = info.UserTime; - UInt64 userFreq = info.UserFreq; - UInt64 globalTime = info.GlobalTime; - UInt64 globalFreq = info.GlobalFreq; - NormalizeVals(userFreq, userTime); - NormalizeVals(globalTime, globalFreq); - if (globalFreq == 0) - globalFreq = 1; - if (userTime == 0) - userTime = 1; - return userFreq * globalTime / globalFreq * rating / userTime; -} - -static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) -{ - UInt64 elTime = elapsedTime; - NormalizeVals(freq, elTime); - if (elTime == 0) - elTime = 1; - return value * freq / elTime; -} - -UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size) -{ - UInt64 t = GetLogSize(dictionarySize) - (kBenchMinDicLogSize << kSubBits); - UInt64 numCommandsForOne = 870 + ((t * t * 5) >> (2 * kSubBits)); - UInt64 numCommands = (UInt64)(size) * numCommandsForOne; - return MyMultDiv64(numCommands, elapsedTime, freq); -} - -UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations) -{ - UInt64 numCommands = (inSize * 200 + outSize * 4) * numIterations; - return MyMultDiv64(numCommands, elapsedTime, freq); -} - -struct CEncoderInfo; - -struct CEncoderInfo -{ - #ifndef _7ZIP_ST - NWindows::CThread thread[2]; - #endif - CMyComPtr encoder; - CBenchProgressInfo *progressInfoSpec[2]; - CMyComPtr progressInfo[2]; - UInt32 NumIterations; - #ifdef USE_ALLOCA - size_t AllocaSize; - #endif - - struct CDecoderInfo - { - CEncoderInfo *Encoder; - UInt32 DecoderIndex; - #ifdef USE_ALLOCA - size_t AllocaSize; - #endif - bool CallbackMode; - }; - CDecoderInfo decodersInfo[2]; - - CMyComPtr decoders[2]; - HRESULT Results[2]; - CBenchmarkOutStream *outStreamSpec; - CMyComPtr outStream; - IBenchCallback *callback; - UInt32 crc; - UInt32 kBufferSize; - UInt32 compressedSize; - CBenchRandomGenerator rg; - CBenchmarkOutStream *propStreamSpec; - CMyComPtr propStream; - HRESULT Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rg); - HRESULT Encode(); - HRESULT Decode(UInt32 decoderIndex); - - CEncoderInfo(): outStreamSpec(0), callback(0), propStreamSpec(0) {} - - #ifndef _7ZIP_ST - static THREAD_FUNC_DECL EncodeThreadFunction(void *param) - { - CEncoderInfo *encoder = (CEncoderInfo *)param; - #ifdef USE_ALLOCA - alloca(encoder->AllocaSize); - #endif - HRESULT res = encoder->Encode(); - encoder->Results[0] = res; - if (res != S_OK) - encoder->progressInfoSpec[0]->Status->SetResult(res); - - return 0; - } - static THREAD_FUNC_DECL DecodeThreadFunction(void *param) - { - CDecoderInfo *decoder = (CDecoderInfo *)param; - #ifdef USE_ALLOCA - alloca(decoder->AllocaSize); - #endif - CEncoderInfo *encoder = decoder->Encoder; - encoder->Results[decoder->DecoderIndex] = encoder->Decode(decoder->DecoderIndex); - return 0; - } - - HRESULT CreateEncoderThread() - { - return thread[0].Create(EncodeThreadFunction, this); - } - - HRESULT CreateDecoderThread(int index, bool callbackMode - #ifdef USE_ALLOCA - , size_t allocaSize - #endif - ) - { - CDecoderInfo &decoder = decodersInfo[index]; - decoder.DecoderIndex = index; - decoder.Encoder = this; - #ifdef USE_ALLOCA - decoder.AllocaSize = allocaSize; - #endif - decoder.CallbackMode = callbackMode; - return thread[index].Create(DecodeThreadFunction, &decoder); - } - #endif -}; - -HRESULT CEncoderInfo::Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rgLoc) -{ - rg.Set(rgLoc); - kBufferSize = dictionarySize + kAdditionalSize; - UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; - if (!rg.Alloc(kBufferSize)) - return E_OUTOFMEMORY; - rg.Generate(); - crc = CrcCalc(rg.Buffer, rg.BufferSize); - - outStreamSpec = new CBenchmarkOutStream; - if (!outStreamSpec->Alloc(kCompressedBufferSize)) - return E_OUTOFMEMORY; - - outStream = outStreamSpec; - - propStreamSpec = 0; - if (!propStream) - { - propStreamSpec = new CBenchmarkOutStream; - propStream = propStreamSpec; - } - if (!propStreamSpec->Alloc(kMaxLzmaPropSize)) - return E_OUTOFMEMORY; - propStreamSpec->Init(); - - PROPID propIDs[] = - { - NCoderPropID::kDictionarySize, - NCoderPropID::kNumThreads - }; - const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); - PROPVARIANT props[kNumProps]; - props[0].vt = VT_UI4; - props[0].ulVal = dictionarySize; - - props[1].vt = VT_UI4; - props[1].ulVal = numThreads; - - { - CMyComPtr setCoderProperties; - RINOK(encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties)); - if (!setCoderProperties) - return E_FAIL; - RINOK(setCoderProperties->SetCoderProperties(propIDs, props, kNumProps)); - - CMyComPtr writeCoderProperties; - encoder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProperties); - if (writeCoderProperties) - { - RINOK(writeCoderProperties->WriteCoderProperties(propStream)); - } - } - return S_OK; -} - -HRESULT CEncoderInfo::Encode() -{ - CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; - CMyComPtr inStream = inStreamSpec; - inStreamSpec->Init(rg.Buffer, rg.BufferSize); - outStreamSpec->Init(); - - RINOK(encoder->Code(inStream, outStream, 0, 0, progressInfo[0])); - compressedSize = outStreamSpec->Pos; - encoder.Release(); - return S_OK; -} - -HRESULT CEncoderInfo::Decode(UInt32 decoderIndex) -{ - CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; - CMyComPtr inStream = inStreamSpec; - CMyComPtr &decoder = decoders[decoderIndex]; - - CMyComPtr compressSetDecoderProperties; - decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &compressSetDecoderProperties); - if (!compressSetDecoderProperties) - return E_FAIL; - - CCrcOutStream *crcOutStreamSpec = new CCrcOutStream; - CMyComPtr crcOutStream = crcOutStreamSpec; - - CBenchProgressInfo *pi = progressInfoSpec[decoderIndex]; - pi->BenchInfo.UnpackSize = 0; - pi->BenchInfo.PackSize = 0; - - for (UInt32 j = 0; j < NumIterations; j++) - { - inStreamSpec->Init(outStreamSpec->Buffer, compressedSize); - crcOutStreamSpec->Init(); - - RINOK(compressSetDecoderProperties->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos)); - UInt64 outSize = kBufferSize; - RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex])); - if (CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc) - return S_FALSE; - pi->BenchInfo.UnpackSize += kBufferSize; - pi->BenchInfo.PackSize += compressedSize; - } - decoder.Release(); - return S_OK; -} - -static const UInt32 kNumThreadsMax = (1 << 16); - -struct CBenchEncoders -{ - CEncoderInfo *encoders; - CBenchEncoders(UInt32 num): encoders(0) { encoders = new CEncoderInfo[num]; } - ~CBenchEncoders() { delete []encoders; } -}; - -HRESULT LzmaBench( - DECL_EXTERNAL_CODECS_LOC_VARS - UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback) -{ - UInt32 numEncoderThreads = - #ifndef _7ZIP_ST - (numThreads > 1 ? numThreads / 2 : 1); - #else - 1; - #endif - UInt32 numSubDecoderThreads = - #ifndef _7ZIP_ST - (numThreads > 1 ? 2 : 1); - #else - 1; - #endif - if (dictionarySize < (1 << kBenchMinDicLogSize) || numThreads < 1 || numEncoderThreads > kNumThreadsMax) - { - return E_INVALIDARG; - } - - CBenchEncoders encodersSpec(numEncoderThreads); - CEncoderInfo *encoders = encodersSpec.encoders; - - - UInt32 i; - for (i = 0; i < numEncoderThreads; i++) - { - CEncoderInfo &encoder = encoders[i]; - encoder.callback = (i == 0) ? callback : 0; - - const UInt32 kLzmaId = 0x030101; - RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS kLzmaId, encoder.encoder, true)); - if (!encoder.encoder) - return E_NOTIMPL; - for (UInt32 j = 0; j < numSubDecoderThreads; j++) - { - RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS kLzmaId, encoder.decoders[j], false)); - if (!encoder.decoders[j]) - return E_NOTIMPL; - } - } - - CBaseRandomGenerator rg; - rg.Init(); - for (i = 0; i < numEncoderThreads; i++) - { - RINOK(encoders[i].Init(dictionarySize, numThreads, &rg)); - } - - CBenchProgressStatus status; - status.Res = S_OK; - status.EncodeMode = true; - - for (i = 0; i < numEncoderThreads; i++) - { - CEncoderInfo &encoder = encoders[i]; - for (int j = 0; j < 2; j++) - { - encoder.progressInfo[j] = encoder.progressInfoSpec[j] = new CBenchProgressInfo; - encoder.progressInfoSpec[j]->Status = &status; - } - if (i == 0) - { - encoder.progressInfoSpec[0]->callback = callback; - encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numEncoderThreads; - SetStartTime(encoder.progressInfoSpec[0]->BenchInfo); - } - - #ifndef _7ZIP_ST - if (numEncoderThreads > 1) - { - #ifdef USE_ALLOCA - encoder.AllocaSize = (i * 16 * 21) & 0x7FF; - #endif - RINOK(encoder.CreateEncoderThread()) - } - else - #endif - { - RINOK(encoder.Encode()); - } - } - #ifndef _7ZIP_ST - if (numEncoderThreads > 1) - for (i = 0; i < numEncoderThreads; i++) - encoders[i].thread[0].Wait(); - #endif - - RINOK(status.Res); - - CBenchInfo info; - - SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info); - info.UnpackSize = 0; - info.PackSize = 0; - info.NumIterations = 1; // progressInfoSpec->NumIterations; - for (i = 0; i < numEncoderThreads; i++) - { - CEncoderInfo &encoder = encoders[i]; - info.UnpackSize += encoder.kBufferSize; - info.PackSize += encoder.compressedSize; - } - RINOK(callback->SetEncodeResult(info, true)); - - - status.Res = S_OK; - status.EncodeMode = false; - - UInt32 numDecoderThreads = numEncoderThreads * numSubDecoderThreads; - for (i = 0; i < numEncoderThreads; i++) - { - CEncoderInfo &encoder = encoders[i]; - encoder.NumIterations = 2 + kUncompressMinBlockSize / encoder.kBufferSize; - - if (i == 0) - { - encoder.progressInfoSpec[0]->callback = callback; - encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numDecoderThreads; - SetStartTime(encoder.progressInfoSpec[0]->BenchInfo); - } - - #ifndef _7ZIP_ST - if (numDecoderThreads > 1) - { - for (UInt32 j = 0; j < numSubDecoderThreads; j++) - { - HRESULT res = encoder.CreateDecoderThread(j, (i == 0 && j == 0) - #ifdef USE_ALLOCA - , ((i * numSubDecoderThreads + j) * 16 * 21) & 0x7FF - #endif - ); - RINOK(res); - } - } - else - #endif - { - RINOK(encoder.Decode(0)); - } - } - #ifndef _7ZIP_ST - HRESULT res = S_OK; - if (numDecoderThreads > 1) - for (i = 0; i < numEncoderThreads; i++) - for (UInt32 j = 0; j < numSubDecoderThreads; j++) - { - CEncoderInfo &encoder = encoders[i]; - encoder.thread[j].Wait(); - if (encoder.Results[j] != S_OK) - res = encoder.Results[j]; - } - RINOK(res); - #endif - RINOK(status.Res); - SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info); - #ifndef _7ZIP_ST - #ifdef UNDER_CE - if (numDecoderThreads > 1) - for (i = 0; i < numEncoderThreads; i++) - for (UInt32 j = 0; j < numSubDecoderThreads; j++) - { - FILETIME creationTime, exitTime, kernelTime, userTime; - if (::GetThreadTimes(encoders[i].thread[j], &creationTime, &exitTime, &kernelTime, &userTime) != 0) - info.UserTime += GetTime64(userTime) + GetTime64(kernelTime); - } - #endif - #endif - info.UnpackSize = 0; - info.PackSize = 0; - info.NumIterations = numSubDecoderThreads * encoders[0].NumIterations; - for (i = 0; i < numEncoderThreads; i++) - { - CEncoderInfo &encoder = encoders[i]; - info.UnpackSize += encoder.kBufferSize; - info.PackSize += encoder.compressedSize; - } - RINOK(callback->SetDecodeResult(info, false)); - RINOK(callback->SetDecodeResult(info, true)); - return S_OK; -} - - -inline UInt64 GetLZMAUsage(bool multiThread, UInt32 dictionary) -{ - UInt32 hs = dictionary - 1; - hs |= (hs >> 1); - hs |= (hs >> 2); - hs |= (hs >> 4); - hs |= (hs >> 8); - hs >>= 1; - hs |= 0xFFFF; - if (hs > (1 << 24)) - hs >>= 1; - hs++; - return ((hs + (1 << 16)) + (UInt64)dictionary * 2) * 4 + (UInt64)dictionary * 3 / 2 + - (1 << 20) + (multiThread ? (6 << 20) : 0); -} - -UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary) -{ - const UInt32 kBufferSize = dictionary; - const UInt32 kCompressedBufferSize = (kBufferSize / 2); - UInt32 numSubThreads = (numThreads > 1) ? 2 : 1; - UInt32 numBigThreads = numThreads / numSubThreads; - return (kBufferSize + kCompressedBufferSize + - GetLZMAUsage((numThreads > 1), dictionary) + (2 << 20)) * numBigThreads; -} - -static bool CrcBig(const void *data, UInt32 size, UInt32 numCycles, UInt32 crcBase) -{ - for (UInt32 i = 0; i < numCycles; i++) - if (CrcCalc(data, size) != crcBase) - return false; - return true; -} - -#ifndef _7ZIP_ST -struct CCrcInfo -{ - NWindows::CThread Thread; - const Byte *Data; - UInt32 Size; - UInt32 NumCycles; - UInt32 Crc; - bool Res; - void Wait() - { - Thread.Wait(); - Thread.Close(); - } -}; - -static THREAD_FUNC_DECL CrcThreadFunction(void *param) -{ - CCrcInfo *p = (CCrcInfo *)param; - p->Res = CrcBig(p->Data, p->Size, p->NumCycles, p->Crc); - return 0; -} - -struct CCrcThreads -{ - UInt32 NumThreads; - CCrcInfo *Items; - CCrcThreads(): Items(0), NumThreads(0) {} - void WaitAll() - { - for (UInt32 i = 0; i < NumThreads; i++) - Items[i].Wait(); - NumThreads = 0; - } - ~CCrcThreads() - { - WaitAll(); - delete []Items; - } -}; -#endif - -static UInt32 CrcCalc1(const Byte *buf, UInt32 size) -{ - UInt32 crc = CRC_INIT_VAL;; - for (UInt32 i = 0; i < size; i++) - crc = CRC_UPDATE_BYTE(crc, buf[i]); - return CRC_GET_DIGEST(crc); -} - -static void RandGen(Byte *buf, UInt32 size, CBaseRandomGenerator &RG) -{ - for (UInt32 i = 0; i < size; i++) - buf[i] = (Byte)RG.GetRnd(); -} - -static UInt32 RandGenCrc(Byte *buf, UInt32 size, CBaseRandomGenerator &RG) -{ - RandGen(buf, size, RG); - return CrcCalc1(buf, size); -} - -bool CrcInternalTest() -{ - CBenchBuffer buffer; - const UInt32 kBufferSize0 = (1 << 8); - const UInt32 kBufferSize1 = (1 << 10); - const UInt32 kCheckSize = (1 << 5); - if (!buffer.Alloc(kBufferSize0 + kBufferSize1)) - return false; - Byte *buf = buffer.Buffer; - UInt32 i; - for (i = 0; i < kBufferSize0; i++) - buf[i] = (Byte)i; - UInt32 crc1 = CrcCalc1(buf, kBufferSize0); - if (crc1 != 0x29058C73) - return false; - CBaseRandomGenerator RG; - RandGen(buf + kBufferSize0, kBufferSize1, RG); - for (i = 0; i < kBufferSize0 + kBufferSize1 - kCheckSize; i++) - for (UInt32 j = 0; j < kCheckSize; j++) - if (CrcCalc1(buf + i, j) != CrcCalc(buf + i, j)) - return false; - return true; -} - -HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed) -{ - if (numThreads == 0) - numThreads = 1; - - CBenchBuffer buffer; - size_t totalSize = (size_t)bufferSize * numThreads; - if (totalSize / numThreads != bufferSize) - return E_OUTOFMEMORY; - if (!buffer.Alloc(totalSize)) - return E_OUTOFMEMORY; - - Byte *buf = buffer.Buffer; - CBaseRandomGenerator RG; - UInt32 numCycles = (kCrcBlockSize) / ((bufferSize >> 2) + 1) + 1; - - UInt64 timeVal; - #ifndef _7ZIP_ST - CCrcThreads threads; - if (numThreads > 1) - { - threads.Items = new CCrcInfo[numThreads]; - UInt32 i; - for (i = 0; i < numThreads; i++) - { - CCrcInfo &info = threads.Items[i]; - Byte *data = buf + (size_t)bufferSize * i; - info.Data = data; - info.NumCycles = numCycles; - info.Size = bufferSize; - info.Crc = RandGenCrc(data, bufferSize, RG); - } - timeVal = GetTimeCount(); - for (i = 0; i < numThreads; i++) - { - CCrcInfo &info = threads.Items[i]; - RINOK(info.Thread.Create(CrcThreadFunction, &info)); - threads.NumThreads++; - } - threads.WaitAll(); - for (i = 0; i < numThreads; i++) - if (!threads.Items[i].Res) - return S_FALSE; - } - else - #endif - { - UInt32 crc = RandGenCrc(buf, bufferSize, RG); - timeVal = GetTimeCount(); - if (!CrcBig(buf, bufferSize, numCycles, crc)) - return S_FALSE; - } - timeVal = GetTimeCount() - timeVal; - if (timeVal == 0) - timeVal = 1; - - UInt64 size = (UInt64)numCycles * totalSize; - speed = MyMultDiv64(size, timeVal, GetFreq()); - return S_OK; -} diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Bench.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/Bench.h deleted file mode 100644 index a8d02a19b..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/Bench.h +++ /dev/null @@ -1,42 +0,0 @@ -// Bench.h - -#ifndef __7ZIP_BENCH_H -#define __7ZIP_BENCH_H - -#include "../../Common/CreateCoder.h" - -struct CBenchInfo -{ - UInt64 GlobalTime; - UInt64 GlobalFreq; - UInt64 UserTime; - UInt64 UserFreq; - UInt64 UnpackSize; - UInt64 PackSize; - UInt32 NumIterations; - CBenchInfo(): NumIterations(0) {} -}; - -struct IBenchCallback -{ - virtual HRESULT SetEncodeResult(const CBenchInfo &info, bool final) = 0; - virtual HRESULT SetDecodeResult(const CBenchInfo &info, bool final) = 0; -}; - -UInt64 GetUsage(const CBenchInfo &benchOnfo); -UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating); -UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size); -UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations); - -HRESULT LzmaBench( - DECL_EXTERNAL_CODECS_LOC_VARS - UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback); - -const int kBenchMinDicLogSize = 18; - -UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary); - -bool CrcInternalTest(); -HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed); - -#endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Common.pri b/src/libs/7zip/unix/CPP/7zip/UI/Common/Common.pri new file mode 100644 index 000000000..a1d75b674 --- /dev/null +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/Common.pri @@ -0,0 +1,43 @@ +HEADERS += $$7ZIP_BASE/CPP/7zip/UI/Common/ArchiveOpenCallback.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/ArchiveExtractCallback.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/ArchiveCommandLine.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/DefaultName.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/DirItem.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/EnumDirItems.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/Extract.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/ExtractMode.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/ExtractingFilePath.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/HashCalc.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/IFileExtractCallback.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/LoadCodecs.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/OpenArchive.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/Property.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/PropIDUtils.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/SetProperties.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/SortUtils.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/TempFiles.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/Update.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/UpdateAction.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/UpdateCallback.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/UpdatePair.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/UpdateProduce.h + +SOURCES += $$7ZIP_BASE/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp \ + $$7ZIP_BASE/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp \ + $$7ZIP_BASE/CPP/7zip/UI/Common/ArchiveCommandLine.cpp \ + $$7ZIP_BASE/CPP/7zip/UI/Common/DefaultName.cpp \ + $$7ZIP_BASE/CPP/7zip/UI/Common/EnumDirItems.cpp \ + $$7ZIP_BASE/CPP/7zip/UI/Common/Extract.cpp \ + $$7ZIP_BASE/CPP/7zip/UI/Common/ExtractingFilePath.cpp \ + $$7ZIP_BASE/CPP/7zip/UI/Common/HashCalc.cpp \ + $$7ZIP_BASE/CPP/7zip/UI/Common/LoadCodecs.cpp \ + $$7ZIP_BASE/CPP/7zip/UI/Common/OpenArchive.cpp \ + $$7ZIP_BASE/CPP/7zip/UI/Common/PropIDUtils.cpp \ + $$7ZIP_BASE/CPP/7zip/UI/Common/SetProperties.cpp \ + $$7ZIP_BASE/CPP/7zip/UI/Common/SortUtils.cpp \ + $$7ZIP_BASE/CPP/7zip/UI/Common/TempFiles.cpp \ + $$7ZIP_BASE/CPP/7zip/UI/Common/Update.cpp \ + $$7ZIP_BASE/CPP/7zip/UI/Common/UpdateAction.cpp \ + $$7ZIP_BASE/CPP/7zip/UI/Common/UpdateCallback.cpp \ + $$7ZIP_BASE/CPP/7zip/UI/Common/UpdatePair.cpp \ + $$7ZIP_BASE/CPP/7zip/UI/Common/UpdateProduce.cpp diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.cpp index 4335e2731..ce0b327b5 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.cpp +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.cpp @@ -7,13 +7,13 @@ static UString GetDefaultName3(const UString &fileName, const UString &extension, const UString &addSubExtension) { - int extLength = extension.Length(); - int fileNameLength = fileName.Length(); + int extLength = extension.Len(); + int fileNameLength = fileName.Len(); if (fileNameLength > extLength + 1) { int dotPos = fileNameLength - (extLength + 1); if (fileName[dotPos] == '.') - if (extension.CompareNoCase(fileName.Mid(dotPos + 1)) == 0) + if (extension.IsEqualToNoCase(fileName.Ptr(dotPos + 1))) return fileName.Left(dotPos) + addSubExtension; } int dotPos = fileName.ReverseFind(L'.'); diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.h index 9764ff871..df1645602 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.h +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.h @@ -1,9 +1,9 @@ // DefaultName.h -#ifndef __DEFAULTNAME_H -#define __DEFAULTNAME_H +#ifndef __DEFAULT_NAME_H +#define __DEFAULT_NAME_H -#include "Common/MyString.h" +#include "../../../Common/MyString.h" UString GetDefaultName2(const UString &fileName, const UString &extension, const UString &addSubExtension); diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/DirItem.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/DirItem.h index 29cc60d93..82203c03a 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/DirItem.h +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/DirItem.h @@ -3,8 +3,12 @@ #ifndef __DIR_ITEM_H #define __DIR_ITEM_H -#include "Common/MyString.h" -#include "Common/Types.h" +#include "../../../Common/MyString.h" + +#include "../../../Windows/FileFind.h" + +#include "../../Common/UniqBlocks.h" + #include "../../Archive/IArchive.h" struct CDirItem @@ -14,11 +18,23 @@ struct CDirItem FILETIME ATime; FILETIME MTime; UString Name; + + #if defined(_WIN32) && !defined(UNDER_CE) + // UString ShortName; + CByteBuffer ReparseData; + CByteBuffer ReparseData2; // fixed (reduced) absolute links + + bool AreReparseData() const { return ReparseData.Size() != 0 || ReparseData2.Size() != 0; } + #endif + UInt32 Attrib; int PhyParent; int LogParent; - - CDirItem(): PhyParent(-1), LogParent(-1) {} + int SecureIndex; + + bool IsAltStream; + + CDirItem(): PhyParent(-1), LogParent(-1), SecureIndex(-1), IsAltStream(false) {} bool IsDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } }; @@ -29,24 +45,64 @@ class CDirItems CIntVector LogParents; UString GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const; + + void EnumerateDir(int phyParent, int logParent, const FString &phyPrefix); + public: CObjectVector Items; - int GetNumFolders() const { return Prefixes.Size(); } - UString GetPhyPath(int index) const; - UString GetLogPath(int index) const; + bool SymLinks; + + bool ScanAltStreams; + FStringVector ErrorPaths; + CRecordVector ErrorCodes; + UInt64 TotalSize; - int AddPrefix(int phyParent, int logParent, const UString &prefix); - void DeleteLastPrefix(); - void EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix, - UStringVector &errorPaths, CRecordVector &errorCodes); + #ifndef UNDER_CE + void SetLinkInfo(CDirItem &dirItem, const NWindows::NFile::NFind::CFileInfo &fi, + const FString &phyPrefix); + #endif - void EnumerateDirItems2( - const UString &phyPrefix, + void AddError(const FString &path, DWORD errorCode) + { + ErrorCodes.Add(errorCode); + ErrorPaths.Add(path); + } + + void AddError(const FString &path) + { + AddError(path, ::GetLastError()); + } + + #if defined(_WIN32) && !defined(UNDER_CE) + + CUniqBlocks SecureBlocks; + CByteBuffer TempSecureBuf; + bool _saclEnabled; + bool ReadSecure; + + void AddSecurityItem(const FString &path, int &secureIndex); + + #endif + + CDirItems(); + + int GetNumFolders() const { return Prefixes.Size(); } + UString GetPhyPath(unsigned index) const; + UString GetLogPath(unsigned index) const; + + unsigned AddPrefix(int phyParent, int logParent, const UString &prefix); + void DeleteLastPrefix(); + void EnumerateItems2( + const FString &phyPrefix, const UString &logPrefix, - const UStringVector &filePaths, - UStringVector &errorPaths, CRecordVector &errorCodes); + const FStringVector &filePaths, + FStringVector *requestedPaths); + + #if defined(_WIN32) && !defined(UNDER_CE) + void FillFixedReparse(); + #endif void ReserveDown(); }; @@ -57,13 +113,14 @@ struct CArcItem FILETIME MTime; UString Name; bool IsDir; + bool IsAltStream; bool SizeDefined; bool MTimeDefined; bool Censored; UInt32 IndexInServer; int TimeType; - - CArcItem(): IsDir(false), SizeDefined(false), MTimeDefined(false), Censored(false), TimeType(-1) {} + + CArcItem(): IsDir(false), IsAltStream(false), SizeDefined(false), MTimeDefined(false), Censored(false), TimeType(-1) {} }; #endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.cpp index ba03ea35c..b94e6274c 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.cpp +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.cpp @@ -2,14 +2,25 @@ #include "StdAfx.h" +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileIO.h" +#include "../../../Windows/FileName.h" + +#if defined(_WIN32) && !defined(UNDER_CE) +#define _USE_SECURITY_CODE +#include "../../../Windows/SecurityUtils.h" +#endif + #include "EnumDirItems.h" using namespace NWindows; using namespace NFile; using namespace NName; -void AddDirFileInfo(int phyParent, int logParent, - const NFind::CFileInfoW &fi, CObjectVector &dirItems) +void AddDirFileInfo(int phyParent, int logParent, int secureIndex, + const NFind::CFileInfo &fi, CObjectVector &dirItems) { CDirItem di; di.Size = fi.Size; @@ -17,41 +28,46 @@ void AddDirFileInfo(int phyParent, int logParent, di.ATime = fi.ATime; di.MTime = fi.MTime; di.Attrib = fi.Attrib; + // FIXME di.IsAltStream = fi.IsAltStream; di.PhyParent = phyParent; di.LogParent = logParent; - di.Name = fi.Name; + di.SecureIndex = secureIndex; + di.Name = fs2us(fi.Name); + #if defined(_WIN32) && !defined(UNDER_CE) + // di.ShortName = fs2us(fi.ShortName); + #endif dirItems.Add(di); } UString CDirItems::GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const { UString path; - int len = name.Length(); + unsigned len = name.Len(); int i; for (i = index; i >= 0; i = parents[i]) - len += Prefixes[i].Length(); - int totalLen = len; + len += Prefixes[i].Len(); + unsigned totalLen = len; wchar_t *p = path.GetBuffer(len); p[len] = 0; - len -= name.Length(); - memcpy(p + len, (const wchar_t *)name, name.Length() * sizeof(wchar_t)); + len -= name.Len(); + memcpy(p + len, (const wchar_t *)name, name.Len() * sizeof(wchar_t)); for (i = index; i >= 0; i = parents[i]) { const UString &s = Prefixes[i]; - len -= s.Length(); - memcpy(p + len, (const wchar_t *)s, s.Length() * sizeof(wchar_t)); + len -= s.Len(); + memcpy(p + len, (const wchar_t *)s, s.Len() * sizeof(wchar_t)); } path.ReleaseBuffer(totalLen); return path; } -UString CDirItems::GetPhyPath(int index) const +UString CDirItems::GetPhyPath(unsigned index) const { const CDirItem &di = Items[index]; return GetPrefixesPath(PhyParents, di.PhyParent, di.Name); } -UString CDirItems::GetLogPath(int index) const +UString CDirItems::GetLogPath(unsigned index) const { const CDirItem &di = Items[index]; return GetPrefixesPath(LogParents, di.LogParent, di.Name); @@ -65,7 +81,7 @@ void CDirItems::ReserveDown() Items.ReserveDown(); } -int CDirItems::AddPrefix(int phyParent, int logParent, const UString &prefix) +unsigned CDirItems::AddPrefix(int phyParent, int logParent, const UString &prefix) { PhyParents.Add(phyParent); LogParents.Add(logParent); @@ -79,162 +95,440 @@ void CDirItems::DeleteLastPrefix() Prefixes.DeleteBack(); } -void CDirItems::EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix, - UStringVector &errorPaths, CRecordVector &errorCodes) +bool InitLocalPrivileges(); + +CDirItems::CDirItems(): + SymLinks(false), + TotalSize(0) + #ifdef _USE_SECURITY_CODE + , ReadSecure(false) + #endif +{ + #ifdef _USE_SECURITY_CODE + _saclEnabled = InitLocalPrivileges(); + #endif +} + +#ifdef _USE_SECURITY_CODE + +void CDirItems::AddSecurityItem(const FString &path, int &secureIndex) +{ + secureIndex = -1; + + SECURITY_INFORMATION securInfo = + DACL_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | + OWNER_SECURITY_INFORMATION; + if (_saclEnabled) + securInfo |= SACL_SECURITY_INFORMATION; + + DWORD errorCode = 0; + DWORD secureSize; + BOOL res = ::GetFileSecurityW(fs2us(path), securInfo, TempSecureBuf, (DWORD)TempSecureBuf.Size(), &secureSize); + if (res) + { + if (secureSize == 0) + return; + if (secureSize > TempSecureBuf.Size()) + errorCode = ERROR_INVALID_FUNCTION; + } + else + { + errorCode = GetLastError(); + if (errorCode == ERROR_INSUFFICIENT_BUFFER) + { + if (secureSize <= TempSecureBuf.Size()) + errorCode = ERROR_INVALID_FUNCTION; + else + { + TempSecureBuf.Alloc(secureSize); + res = ::GetFileSecurityW(fs2us(path), securInfo, TempSecureBuf, (DWORD)TempSecureBuf.Size(), &secureSize); + if (res) + { + if (secureSize != TempSecureBuf.Size()) + errorCode = ERROR_INVALID_FUNCTION;; + } + else + errorCode = GetLastError(); + } + } + } + if (res) + { + secureIndex = SecureBlocks.AddUniq(TempSecureBuf, secureSize); + return; + } + if (errorCode == 0) + errorCode = ERROR_INVALID_FUNCTION; + AddError(path, errorCode); +} + +#endif + +void CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phyPrefix) { - NFind::CEnumeratorW enumerator(phyPrefix + (wchar_t)kAnyStringWildcard); + NFind::CEnumerator enumerator(phyPrefix + FCHAR_ANY_MASK); for (;;) { - NFind::CFileInfoW fi; + NFind::CFileInfo fi; bool found; if (!enumerator.Next(fi, found)) { - errorCodes.Add(::GetLastError()); - errorPaths.Add(phyPrefix); + AddError(phyPrefix); return; } if (!found) break; - AddDirFileInfo(phyParent, logParent, fi, Items); + + int secureIndex = -1; + #ifdef _USE_SECURITY_CODE + if (ReadSecure) + AddSecurityItem(phyPrefix + fi.Name, secureIndex); + #endif + + AddDirFileInfo(phyParent, logParent, secureIndex, fi, Items); + if (fi.IsDir()) { - const UString name2 = fi.Name + (wchar_t)kDirDelimiter; - int parent = AddPrefix(phyParent, logParent, name2); - EnumerateDirectory(parent, parent, phyPrefix + name2, errorPaths, errorCodes); + const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR; + unsigned parent = AddPrefix(phyParent, logParent, fs2us(name2)); + EnumerateDir(parent, parent, phyPrefix + name2); } } } -void CDirItems::EnumerateDirItems2(const UString &phyPrefix, const UString &logPrefix, - const UStringVector &filePaths, UStringVector &errorPaths, CRecordVector &errorCodes) +void CDirItems::EnumerateItems2( + const FString &phyPrefix, + const UString &logPrefix, + const FStringVector &filePaths, + FStringVector *requestedPaths) { - int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, phyPrefix); + int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, fs2us(phyPrefix)); int logParent = logPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, logPrefix); - for (int i = 0; i < filePaths.Size(); i++) + FOR_VECTOR (i, filePaths) { - const UString &filePath = filePaths[i]; - NFind::CFileInfoW fi; - const UString phyPath = phyPrefix + filePath; + const FString &filePath = filePaths[i]; + NFind::CFileInfo fi; + const FString phyPath = phyPrefix + filePath; if (!fi.Find(phyPath)) { - errorCodes.Add(::GetLastError()); - errorPaths.Add(phyPath); + AddError(phyPath); continue; } - int delimiter = filePath.ReverseFind((wchar_t)kDirDelimiter); - UString phyPrefixCur; + if (requestedPaths) + requestedPaths->Add(phyPath); + + int delimiter = filePath.ReverseFind(FCHAR_PATH_SEPARATOR); + FString phyPrefixCur; int phyParentCur = phyParent; if (delimiter >= 0) { - phyPrefixCur = filePath.Left(delimiter + 1); - phyParentCur = AddPrefix(phyParent, logParent, phyPrefixCur); + phyPrefixCur.SetFrom(filePath, delimiter + 1); + phyParentCur = AddPrefix(phyParent, logParent, fs2us(phyPrefixCur)); } - AddDirFileInfo(phyParentCur, logParent, fi, Items); + + int secureIndex = -1; + #ifdef _USE_SECURITY_CODE + if (ReadSecure) + AddSecurityItem(phyPath, secureIndex); + #endif + + AddDirFileInfo(phyParentCur, logParent, secureIndex, fi, Items); + if (fi.IsDir()) { - const UString name2 = fi.Name + (wchar_t)kDirDelimiter; - int parent = AddPrefix(phyParentCur, logParent, name2); - EnumerateDirectory(parent, parent, phyPrefix + phyPrefixCur + name2, errorPaths, errorCodes); + const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR; + unsigned parent = AddPrefix(phyParentCur, logParent, fs2us(name2)); + EnumerateDir(parent, parent, phyPrefix + phyPrefixCur + name2); } } ReserveDown(); } -static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, - int phyParent, int logParent, const UString &phyPrefix, + + + + + +static HRESULT EnumerateDirItems( + const NWildcard::CCensorNode &curNode, + int phyParent, int logParent, const FString &phyPrefix, const UStringVector &addArchivePrefix, CDirItems &dirItems, bool enterToSubFolders, - IEnumDirItemCallback *callback, - UStringVector &errorPaths, - CRecordVector &errorCodes); + IEnumDirItemCallback *callback); -static HRESULT EnumerateDirItems_Spec(const NWildcard::CCensorNode &curNode, - int phyParent, int logParent, const UString &curFolderName, - const UString &phyPrefix, +static HRESULT EnumerateDirItems_Spec( + const NWildcard::CCensorNode &curNode, + int phyParent, int logParent, const FString &curFolderName, + const FString &phyPrefix, const UStringVector &addArchivePrefix, CDirItems &dirItems, bool enterToSubFolders, - IEnumDirItemCallback *callback, - UStringVector &errorPaths, - CRecordVector &errorCodes) - + IEnumDirItemCallback *callback) { - const UString name2 = curFolderName + (wchar_t)kDirDelimiter; - int parent = dirItems.AddPrefix(phyParent, logParent, name2); - int numItems = dirItems.Items.Size(); - HRESULT res = EnumerateDirItems(curNode, parent, parent, phyPrefix + name2, - addArchivePrefix, dirItems, enterToSubFolders, callback, errorPaths, errorCodes); + const FString name2 = curFolderName + FCHAR_PATH_SEPARATOR; + unsigned parent = dirItems.AddPrefix(phyParent, logParent, fs2us(name2)); + unsigned numItems = dirItems.Items.Size(); + HRESULT res = EnumerateDirItems( + curNode, parent, parent, phyPrefix + name2, + addArchivePrefix, dirItems, enterToSubFolders, callback); if (numItems == dirItems.Items.Size()) dirItems.DeleteLastPrefix(); return res; } +#if 0 // #ifndef UNDER_CE -static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, - int phyParent, int logParent, const UString &phyPrefix, +static void EnumerateAltStreams( + const NFind::CFileInfo &fi, + const NWildcard::CCensorNode &curNode, + int phyParent, int logParent, const FString &phyPrefix, + const UStringVector &addArchivePrefix, // prefix from curNode + CDirItems &dirItems) +{ + const FString fullPath = phyPrefix + fi.Name; + NFind::CStreamEnumerator enumerator(fullPath); + for (;;) + { + NFind::CStreamInfo si; + bool found; + if (!enumerator.Next(si, found)) + { + dirItems.AddError(fullPath + FTEXT(":*"), (DWORD)E_FAIL); + break; + } + if (!found) + break; + if (si.IsMainStream()) + continue; + UStringVector addArchivePrefixNew = addArchivePrefix; + UString reducedName = si.GetReducedName(); + addArchivePrefixNew.Back() += reducedName; + if (curNode.CheckPathToRoot(false, addArchivePrefixNew, true)) + continue; + NFind::CFileInfo fi2 = fi; + fi2.Name += us2fs(reducedName); + fi2.Size = si.Size; + fi2.Attrib &= ~FILE_ATTRIBUTE_DIRECTORY; + fi2.IsAltStream = true; + AddDirFileInfo(phyParent, logParent, -1, fi2, dirItems.Items); + dirItems.TotalSize += fi2.Size; + } +} + +void CDirItems::SetLinkInfo(CDirItem &dirItem, const NFind::CFileInfo &fi, + const FString &phyPrefix) +{ + if (!SymLinks || !fi.HasReparsePoint()) + return; + const FString path = phyPrefix + fi.Name; + CByteBuffer &buf = dirItem.ReparseData; + if (NIO::GetReparseData(path, buf)) + { + CReparseAttr attr; + if (attr.Parse(buf, buf.Size())) + return; + } + AddError(path); + buf.Free(); +} + +#endif + +static HRESULT EnumerateForItem( + NFind::CFileInfo &fi, + const NWildcard::CCensorNode &curNode, + int phyParent, int logParent, const FString &phyPrefix, const UStringVector &addArchivePrefix, // prefix from curNode CDirItems &dirItems, bool enterToSubFolders, - IEnumDirItemCallback *callback, - UStringVector &errorPaths, - CRecordVector &errorCodes) + IEnumDirItemCallback *callback) +{ + const UString name = fs2us(fi.Name); + bool enterToSubFolders2 = enterToSubFolders; + UStringVector addArchivePrefixNew = addArchivePrefix; + addArchivePrefixNew.Add(name); + { + UStringVector addArchivePrefixNewTemp(addArchivePrefixNew); + if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir())) + return S_OK; + } + int dirItemIndex = -1; + + if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir())) + { + int secureIndex = -1; + #ifdef _USE_SECURITY_CODE + if (dirItems.ReadSecure) + dirItems.AddSecurityItem(phyPrefix + fi.Name, secureIndex); + #endif + + dirItemIndex = dirItems.Items.Size(); + AddDirFileInfo(phyParent, logParent, secureIndex, fi, dirItems.Items); + dirItems.TotalSize += fi.Size; + if (fi.IsDir()) + enterToSubFolders2 = true; + } + + #if 0 // #ifndef UNDER_CE + if (dirItems.ScanAltStreams) + { + EnumerateAltStreams(fi, curNode, phyParent, logParent, phyPrefix, + addArchivePrefixNew, dirItems); + } + + if (dirItemIndex >= 0) + { + CDirItem &dirItem = dirItems.Items[dirItemIndex]; + dirItems.SetLinkInfo(dirItem, fi, phyPrefix); + if (dirItem.ReparseData.Size() != 0) + return S_OK; + } + #endif + + if (!fi.IsDir()) + return S_OK; + + const NWildcard::CCensorNode *nextNode = 0; + if (addArchivePrefix.IsEmpty()) + { + int index = curNode.FindSubNode(name); + if (index >= 0) + nextNode = &curNode.SubNodes[index]; + } + if (!enterToSubFolders2 && nextNode == 0) + return S_OK; + + addArchivePrefixNew = addArchivePrefix; + if (nextNode == 0) + { + nextNode = &curNode; + addArchivePrefixNew.Add(name); + } + + return EnumerateDirItems_Spec( + *nextNode, phyParent, logParent, fi.Name, phyPrefix, + addArchivePrefixNew, + dirItems, + enterToSubFolders2, callback); +} + + +static bool CanUseFsDirect(const NWildcard::CCensorNode &curNode) +{ + FOR_VECTOR (i, curNode.IncludeItems) + { + const NWildcard::CItem &item = curNode.IncludeItems[i]; + if (item.Recursive || item.PathParts.Size() != 1) + return false; + const UString &name = item.PathParts.Front(); + if (name.IsEmpty()) + return false; + + /* Windows doesn't support file name with wildcard. + but if another system supports file name with wildcard, + and wildcard mode is disabled, we can ignore wildcard in name */ + /* + if (!item.WildcardParsing) + continue; + */ + if (DoesNameContainWildcard(name)) + return false; + } + return true; +} + + +static HRESULT EnumerateDirItems( + const NWildcard::CCensorNode &curNode, + int phyParent, int logParent, const FString &phyPrefix, + const UStringVector &addArchivePrefix, // prefix from curNode + CDirItems &dirItems, + bool enterToSubFolders, + IEnumDirItemCallback *callback) { if (!enterToSubFolders) if (curNode.NeedCheckSubDirs()) enterToSubFolders = true; if (callback) - RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix)); + RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), dirItems.TotalSize, fs2us(phyPrefix), true)); // try direct_names case at first if (addArchivePrefix.IsEmpty() && !enterToSubFolders) { - // check that all names are direct - int i; - for (i = 0; i < curNode.IncludeItems.Size(); i++) - { - const NWildcard::CItem &item = curNode.IncludeItems[i]; - if (item.Recursive || item.PathParts.Size() != 1) - break; - const UString &name = item.PathParts.Front(); - if (name.IsEmpty() || DoesNameContainWildCard(name)) - break; - } - if (i == curNode.IncludeItems.Size()) + if (CanUseFsDirect(curNode)) { // all names are direct (no wildcards) // so we don't need file_system's dir enumerator CRecordVector needEnterVector; + unsigned i; + for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; const UString &name = item.PathParts.Front(); - const UString fullPath = phyPrefix + name; - NFind::CFileInfoW fi; + const FString fullPath = phyPrefix + us2fs(name); + NFind::CFileInfo fi; + #ifdef _WIN32 + if (phyPrefix.IsEmpty() && item.IsDriveItem()) + { + fi.SetAsDir(); + fi.Name = fullPath; + } + else + #endif if (!fi.Find(fullPath)) { - errorCodes.Add(::GetLastError()); - errorPaths.Add(fullPath); + dirItems.AddError(fullPath); continue; } bool isDir = fi.IsDir(); if (isDir && !item.ForDir || !isDir && !item.ForFile) { - errorCodes.Add((DWORD)E_FAIL); - errorPaths.Add(fullPath); + dirItems.AddError(fullPath, (DWORD)E_FAIL); continue; } { UStringVector pathParts; - pathParts.Add(fi.Name); + pathParts.Add(fs2us(fi.Name)); if (curNode.CheckPathToRoot(false, pathParts, !isDir)) continue; } - AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); + + int secureIndex = -1; + #ifdef _USE_SECURITY_CODE + if (dirItems.ReadSecure) + dirItems.AddSecurityItem(fullPath, secureIndex); + #endif + + AddDirFileInfo(phyParent, logParent, secureIndex, fi, dirItems.Items); + + #if 0 // #ifndef UNDER_CE + { + CDirItem &dirItem = dirItems.Items.Back(); + dirItems.SetLinkInfo(dirItem, fi, phyPrefix); + if (dirItem.ReparseData.Size() != 0) + continue; + } + #endif + + dirItems.TotalSize += fi.Size; + + #if 0 // #ifndef UNDER_CE + if (dirItems.ScanAltStreams) + { + UStringVector pathParts; + pathParts.Add(fs2us(fi.Name)); + EnumerateAltStreams(fi, curNode, phyParent, logParent, phyPrefix, + pathParts, dirItems); + } + #endif + if (!isDir) continue; - + UStringVector addArchivePrefixNew; const NWildcard::CCensorNode *nextNode = 0; int index = curNode.FindSubNode(name); @@ -252,110 +546,212 @@ static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, } RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix, - addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes)); + addArchivePrefixNew, dirItems, true, callback)); } + for (i = 0; i < curNode.SubNodes.Size(); i++) { if (i < needEnterVector.Size()) if (!needEnterVector[i]) continue; const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i]; - const UString fullPath = phyPrefix + nextNode.Name; - NFind::CFileInfoW fi; - if (!fi.Find(fullPath)) + const FString fullPath = phyPrefix + us2fs(nextNode.Name); + NFind::CFileInfo fi; + #ifdef _WIN32 + if (phyPrefix.IsEmpty() && NWildcard::IsDriveColonName(nextNode.Name)) + { + fi.SetAsDir(); + fi.Name = fullPath; + } + else + #endif + if (!fi.Find(fullPath,true)) { if (!nextNode.AreThereIncludeItems()) continue; - errorCodes.Add(::GetLastError()); - errorPaths.Add(fullPath); + dirItems.AddError(fullPath); continue; } if (!fi.IsDir()) { - errorCodes.Add((DWORD)E_FAIL); - errorPaths.Add(fullPath); + dirItems.AddError(fullPath, (DWORD)E_FAIL); continue; } RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix, - UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); + UStringVector(), dirItems, false, callback)); } + return S_OK; } } + #ifdef _WIN32 + #ifndef UNDER_CE - NFind::CEnumeratorW enumerator(phyPrefix + wchar_t(kAnyStringWildcard)); - for (int ttt = 0; ; ttt++) - { - NFind::CFileInfoW fi; - bool found; - if (!enumerator.Next(fi, found)) - { - errorCodes.Add(::GetLastError()); - errorPaths.Add(phyPrefix); - break; - } - if (!found) - break; + // scan drives, if wildcard is "*:\" - if (callback && (ttt & 0xFF) == 0xFF) - RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix)); - const UString &name = fi.Name; - bool enterToSubFolders2 = enterToSubFolders; - UStringVector addArchivePrefixNew = addArchivePrefix; - addArchivePrefixNew.Add(name); + if (phyPrefix.IsEmpty() && curNode.IncludeItems.Size() > 0) + { + unsigned i; + for (i = 0; i < curNode.IncludeItems.Size(); i++) { - UStringVector addArchivePrefixNewTemp(addArchivePrefixNew); - if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir())) + const NWildcard::CItem &item = curNode.IncludeItems[i]; + if (item.PathParts.Size() < 1) + break; + const UString &name = item.PathParts.Front(); + if (name.Len() != 2 || name[1] != ':') + break; + if (item.PathParts.Size() == 1) + if (item.ForFile || !item.ForDir) + break; + if (NWildcard::IsDriveColonName(name)) continue; + if (name[0] != '*' && name[0] != '?') + break; } - if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir())) + if (i == curNode.IncludeItems.Size()) { - AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); - if (fi.IsDir()) - enterToSubFolders2 = true; - } - if (!fi.IsDir()) - continue; + FStringVector driveStrings; + NFind::MyGetLogicalDriveStrings(driveStrings); + for (i = 0; i < driveStrings.Size(); i++) + { + FString driveName = driveStrings[i]; + if (driveName.Len() < 3 || driveName.Back() != '\\') + return E_FAIL; + driveName.DeleteBack(); + NFind::CFileInfo fi; + fi.SetAsDir(); + fi.Name = driveName; - const NWildcard::CCensorNode *nextNode = 0; - if (addArchivePrefix.IsEmpty()) - { - int index = curNode.FindSubNode(name); - if (index >= 0) - nextNode = &curNode.SubNodes[index]; + RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix, + addArchivePrefix, dirItems, enterToSubFolders, callback)); + } + return S_OK; } - if (!enterToSubFolders2 && nextNode == 0) - continue; + } + + #endif + #endif - addArchivePrefixNew = addArchivePrefix; - if (nextNode == 0) + NFind::CEnumerator enumerator(phyPrefix + FCHAR_ANY_MASK); + for (unsigned ttt = 0; ; ttt++) + { + NFind::CFileInfo fi; + bool found; + if (!enumerator.Next(fi, found)) { - nextNode = &curNode; - addArchivePrefixNew.Add(name); + dirItems.AddError(phyPrefix); + break; } + if (!found) + break; - RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, name, phyPrefix, - addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes)); + if (callback && (ttt & 0xFF) == 0xFF) + RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), dirItems.TotalSize, fs2us(phyPrefix), true)); + + RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix, + addArchivePrefix, dirItems, enterToSubFolders, callback)); } return S_OK; } HRESULT EnumerateItems( const NWildcard::CCensor &censor, + const NWildcard::ECensorPathMode pathMode, + const UString &addPathPrefix, CDirItems &dirItems, - IEnumDirItemCallback *callback, - UStringVector &errorPaths, - CRecordVector &errorCodes) + IEnumDirItemCallback *callback) { - for (int i = 0; i < censor.Pairs.Size(); i++) + FOR_VECTOR (i, censor.Pairs) { const NWildcard::CPair &pair = censor.Pairs[i]; int phyParent = pair.Prefix.IsEmpty() ? -1 : dirItems.AddPrefix(-1, -1, pair.Prefix); - RINOK(EnumerateDirItems(pair.Head, phyParent, -1, pair.Prefix, UStringVector(), dirItems, false, - callback, errorPaths, errorCodes)); + int logParent = -1; + + if (pathMode == NWildcard::k_AbsPath) + logParent = phyParent; + else + { + if (!addPathPrefix.IsEmpty()) + logParent = dirItems.AddPrefix(-1, -1, addPathPrefix); + } + + RINOK(EnumerateDirItems(pair.Head, phyParent, logParent, us2fs(pair.Prefix), UStringVector(), + dirItems, + false, // enterToSubFolders + callback)); } dirItems.ReserveDown(); + + #if defined(_WIN32) && !defined(UNDER_CE) + dirItems.FillFixedReparse(); + #endif + return S_OK; } + +#if defined(_WIN32) && !defined(UNDER_CE) + +void CDirItems::FillFixedReparse() +{ + /* imagex/WIM reduces absolute pathes in links (raparse data), + if we archive non root folder. We do same thing here */ + + if (!SymLinks) + return; + + FOR_VECTOR(i, Items) + { + CDirItem &item = Items[i]; + if (item.ReparseData.Size() == 0) + continue; + + CReparseAttr attr; + if (!attr.Parse(item.ReparseData, item.ReparseData.Size())) + continue; + if (attr.IsRelative()) + continue; + + const UString &link = attr.GetPath(); + if (!IsDrivePath(link)) + continue; + // maybe we need to support networks paths also ? + + FString fullPathF; + if (!NDir::MyGetFullPathName(us2fs(GetPhyPath(i)), fullPathF)) + continue; + UString fullPath = fs2us(fullPathF); + const UString logPath = GetLogPath(i); + if (logPath.Len() >= fullPath.Len()) + continue; + if (CompareFileNames(logPath, fullPath.RightPtr(logPath.Len())) != 0) + continue; + + const UString prefix = fullPath.Left(fullPath.Len() - logPath.Len()); + if (prefix.Back() != WCHAR_PATH_SEPARATOR) + continue; + + unsigned rootPrefixSize = GetRootPrefixSize(prefix); + if (rootPrefixSize == 0) + continue; + if (rootPrefixSize == prefix.Len()) + continue; // simple case: paths are from root + + if (link.Len() <= prefix.Len()) + continue; + + if (CompareFileNames(link.Left(prefix.Len()), prefix) != 0) + continue; + + UString newLink = prefix.Left(rootPrefixSize); + newLink += link.Ptr(prefix.Len()); + + CByteBuffer data; + if (!FillLinkData(data, newLink, attr.IsSymLink())) + continue; + item.ReparseData2 = data; + } +} + +#endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.h index d0ce950e3..803a64e7d 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.h +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.h @@ -3,23 +3,25 @@ #ifndef __ENUM_DIR_ITEMS_H #define __ENUM_DIR_ITEMS_H -#include "Common/Wildcard.h" -#include "Windows/FileFind.h" +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/FileFind.h" + #include "DirItem.h" -void AddDirFileInfo(int phyParent, int logParent, - const NWindows::NFile::NFind::CFileInfoW &fi, CObjectVector &dirItems); +void AddDirFileInfo(int phyParent, int logParent, int secureIndex, + const NWindows::NFile::NFind::CFileInfo &fi, CObjectVector &dirItems); struct IEnumDirItemCallback { - virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) = 0; + virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) = 0; }; HRESULT EnumerateItems( const NWildcard::CCensor &censor, + NWildcard::ECensorPathMode pathMode, + const UString &addPathPrefix, CDirItems &dirItems, - IEnumDirItemCallback *callback, - UStringVector &errorPaths, - CRecordVector &errorCodes); + IEnumDirItemCallback *callback); #endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ExitCode.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/ExitCode.h deleted file mode 100644 index b6d7d4dfc..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ExitCode.h +++ /dev/null @@ -1,27 +0,0 @@ -// ExitCode.h - -#ifndef __EXIT_CODE_H -#define __EXIT_CODE_H - -namespace NExitCode { - -enum EEnum { - - kSuccess = 0, // Successful operation - kWarning = 1, // Non fatal error(s) occurred - kFatalError = 2, // A fatal error occurred - // kCRCError = 3, // A CRC error occurred when unpacking - // kLockedArchive = 4, // Attempt to modify an archive previously locked - // kWriteError = 5, // Write to disk error - // kOpenError = 6, // Open file error - kUserError = 7, // Command line option error - kMemoryError = 8, // Not enough memory for operation - // kCreateFileError = 9, // Create file error - - kUserBreak = 255 // User stopped the process - -}; - -} - -#endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.cpp index ca2c8c73d..5f94254ef 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.cpp +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.cpp @@ -2,11 +2,11 @@ #include "StdAfx.h" -#include +#include "../../../Common/StringConvert.h" -#include "Windows/FileDir.h" -#include "Windows/PropVariant.h" -#include "Windows/PropVariantConversions.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/PropVariantConv.h" #include "../Common/ExtractingFilePath.h" @@ -14,135 +14,251 @@ #include "SetProperties.h" using namespace NWindows; +using namespace NFile; +using namespace NDir; static HRESULT DecompressArchive( - const CArc &arc, + CCodecs *codecs, + const CArchiveLink &arcLink, UInt64 packSize, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, + bool calcCrc, IExtractCallbackUI *callback, - CArchiveExtractCallback *extractCallbackSpec, + CArchiveExtractCallback *ecs, UString &errorMessage, UInt64 &stdInProcessed) { + const CArc &arc = arcLink.Arcs.Back(); stdInProcessed = 0; IInArchive *archive = arc.Archive; CRecordVector realIndices; + + UStringVector removePathParts; + + FString outDir = options.OutputDir; + UString replaceName = arc.DefaultName; + + if (arcLink.Arcs.Size() > 1) + { + // Most "pe" archives have same name of archive subfile "[0]" or ".rsrc_1". + // So it extracts different archives to one folder. + // We will use top level archive name + const CArc &arc0 = arcLink.Arcs[0]; + if (StringsAreEqualNoCase_Ascii(codecs->Formats[arc0.FormatIndex].Name, "pe")) + replaceName = arc0.DefaultName; + } + + outDir.Replace(FSTRING_ANY_MASK, us2fs(GetCorrectFsPath(replaceName))); + + bool elimIsPossible = false; + UString elimPrefix; // only pure name without dir delimiter + FString outDirReduced = outDir; + + if (options.ElimDup.Val) + { + UString dirPrefix; + SplitPathToParts_Smart(fs2us(outDir), dirPrefix, elimPrefix); + if (!elimPrefix.IsEmpty()) + { + if (IsCharDirLimiter(elimPrefix.Back())) + elimPrefix.DeleteBack(); + if (!elimPrefix.IsEmpty()) + { + outDirReduced = us2fs(dirPrefix); + elimIsPossible = true; + } + } + } + if (!options.StdInMode) { UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); - + + UString filePath; + for (UInt32 i = 0; i < numItems; i++) { - UString filePath; RINOK(arc.GetItemPath(i, filePath)); + + if (elimIsPossible && options.ElimDup.Val) + { + if (!IsPath1PrefixedByPath2(filePath, elimPrefix)) + elimIsPossible = false; + else + { + wchar_t c = filePath[elimPrefix.Len()]; + if (c != 0 && !IsCharDirLimiter(c)) + elimIsPossible = false; + } + } + bool isFolder; - RINOK(IsArchiveItemFolder(archive, i, isFolder)); - if (!wildcardCensor.CheckPath(filePath, !isFolder)) + RINOK(Archive_IsItem_Folder(archive, i, isFolder)); + bool isAltStream; + RINOK(Archive_IsItem_AltStream(archive, i, isAltStream)); + if (!options.NtOptions.AltStreams.Val && isAltStream) + continue; + if (!wildcardCensor.CheckPath(isAltStream, filePath, !isFolder)) continue; realIndices.Add(i); } + if (realIndices.Size() == 0) { callback->ThereAreNoFiles(); - return S_OK; + return callback->ExtractResult(S_OK); } } - UStringVector removePathParts; + if (elimIsPossible) + outDir = outDirReduced; - UString outDir = options.OutputDir; - outDir.Replace(L"*", GetCorrectFsPath(arc.DefaultName)); #ifdef _WIN32 // GetCorrectFullFsPath doesn't like "..". // outDir.TrimRight(); // outDir = GetCorrectFullFsPath(outDir); #endif - if (!outDir.IsEmpty()) - if (!NFile::NDirectory::CreateComplexDirectory(outDir)) + if (outDir.IsEmpty()) + outDir = FString(FTEXT(".")) + FString(FSTRING_PATH_SEPARATOR); + else + if (!CreateComplexDir(outDir)) { HRESULT res = ::GetLastError(); if (res == S_OK) res = E_FAIL; - errorMessage = ((UString)L"Can not create output directory ") + outDir; + errorMessage = ((UString)L"Can not create output directory ") + fs2us(outDir); return res; } - extractCallbackSpec->Init( + ecs->Init( + options.NtOptions, options.StdInMode ? &wildcardCensor : NULL, &arc, callback, - options.StdOutMode, options.TestMode, options.CalcCrc, + options.StdOutMode, options.TestMode, outDir, removePathParts, packSize); - #if !defined(_7ZIP_ST) && !defined(_SFX) - RINOK(SetProperties(archive, options.Properties)); + + #ifdef SUPPORT_LINKS + + if (!options.StdInMode && + !options.TestMode && + options.NtOptions.HardLinks.Val) + { + RINOK(ecs->PrepareHardLinks(&realIndices)); + } + #endif + HRESULT result; - Int32 testMode = (options.TestMode && !options.CalcCrc) ? 1: 0; + Int32 testMode = (options.TestMode && !calcCrc) ? 1: 0; if (options.StdInMode) { - result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, extractCallbackSpec); + result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, ecs); NCOM::CPropVariant prop; if (archive->GetArchiveProperty(kpidPhySize, &prop) == S_OK) - if (prop.vt == VT_UI8 || prop.vt == VT_UI4) - stdInProcessed = ConvertPropVariantToUInt64(prop); + ConvertPropVariantToUInt64(prop, stdInProcessed); } else - result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, extractCallbackSpec); - + result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, ecs); + if (result == S_OK && !options.StdInMode) + result = ecs->SetDirsTimes(); return callback->ExtractResult(result); } -HRESULT DecompressArchives( - CCodecs *codecs, const CIntVector &formatIndices, +/* v9.31: BUG was fixed: + Sorted list for file paths was sorted with case insensitive compare function. + But FindInSorted function did binary search via case sensitive compare function */ + +int Find_FileName_InSortedVector(const UStringVector &fileName, const UString &name) +{ + unsigned left = 0, right = fileName.Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + const UString &midValue = fileName[mid]; + int compare = CompareFileNames(name, midValue); + if (compare == 0) + return mid; + if (compare < 0) + right = mid; + else + left = mid + 1; + } + return -1; +} + +HRESULT Extract( + CCodecs *codecs, + const CObjectVector &types, + const CIntVector &excludedFormats, UStringVector &arcPaths, UStringVector &arcPathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, + #ifndef _SFX + IHashCalc *hash, + #endif UString &errorMessage, CDecompressStat &stat) { stat.Clear(); - int i; UInt64 totalPackSize = 0; - CRecordVector archiveSizes; + CRecordVector arcSizes; - int numArcs = options.StdInMode ? 1 : arcPaths.Size(); + unsigned numArcs = options.StdInMode ? 1 : arcPaths.Size(); + unsigned i; for (i = 0; i < numArcs; i++) { - NFile::NFind::CFileInfoW fi; + NFind::CFileInfo fi; fi.Size = 0; if (!options.StdInMode) { - const UString &arcPath = arcPaths[i]; - if (!fi.Find(arcPath)) + const FString &arcPath = us2fs(arcPaths[i]); + if (!fi.Find(arcPath,true)) throw "there is no such archive"; if (fi.IsDir()) throw "can't decompress folder"; } - archiveSizes.Add(fi.Size); + arcSizes.Add(fi.Size); totalPackSize += fi.Size; } - CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; - CMyComPtr ec(extractCallbackSpec); + + CBoolArr skipArcs(numArcs); + for (i = 0; i < numArcs; i++) + skipArcs[i] = false; + + CArchiveExtractCallback *ecs = new CArchiveExtractCallback; + CMyComPtr ec(ecs); bool multi = (numArcs > 1); - extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode); + ecs->InitForMulti(multi, options.PathMode, options.OverwriteMode); + #ifndef _SFX + ecs->SetHashMethods(hash); + #endif + if (multi) { RINOK(extractCallback->SetTotal(totalPackSize)); } + + UInt64 totalPackProcessed = 0; + bool thereAreNotOpenArcs = false; + for (i = 0; i < numArcs; i++) { + if (skipArcs[i]) + continue; + const UString &arcPath = arcPaths[i]; - NFile::NFind::CFileInfoW fi; + NFind::CFileInfo fi; if (options.StdInMode) { fi.Size = 0; @@ -150,7 +266,7 @@ HRESULT DecompressArchives( } else { - if (!fi.Find(arcPath) || fi.IsDir()) + if (!fi.Find(us2fs(arcPath),true) || fi.IsDir()) throw "there is no such archive"; } @@ -159,16 +275,17 @@ HRESULT DecompressArchives( #endif RINOK(extractCallback->BeforeOpen(arcPath)); - CArchiveLink archiveLink; + CArchiveLink arcLink; - CIntVector formatIndices2 = formatIndices; + CObjectVector types2 = types; + /* #ifndef _SFX - if (formatIndices.IsEmpty()) + if (types.IsEmpty()) { int pos = arcPath.ReverseFind(L'.'); if (pos >= 0) { - UString s = arcPath.Mid(pos + 1); + UString s = arcPath.Ptr(pos + 1); int index = codecs->FindFormatForExtension(s); if (index >= 0 && s == L"001") { @@ -176,18 +293,31 @@ HRESULT DecompressArchives( pos = s.ReverseFind(L'.'); if (pos >= 0) { - int index2 = codecs->FindFormatForExtension(s.Mid(pos + 1)); - if (index2 >= 0 && s.CompareNoCase(L"rar") != 0) + int index2 = codecs->FindFormatForExtension(s.Ptr(pos + 1)); + if (index2 >= 0) // && s.CompareNoCase(L"rar") != 0 { - formatIndices2.Add(index2); - formatIndices2.Add(index); + types2.Add(index2); + types2.Add(index); } } } } } #endif - HRESULT result = archiveLink.Open2(codecs, formatIndices2, options.StdInMode, NULL, arcPath, openCallback); + */ + + COpenOptions op; + #ifndef _SFX + op.props = &options.Properties; + #endif + op.codecs = codecs; + op.types = &types2; + op.excludedFormats = &excludedFormats; + op.stdInMode = options.StdInMode; + op.stream = NULL; + op.filePath = arcPath; + HRESULT result = arcLink.Open2(op, openCallback); + if (result == E_ABORT) return result; @@ -196,68 +326,148 @@ HRESULT DecompressArchives( crypted = openCallback->Open_WasPasswordAsked(); #endif + if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) + result = S_FALSE; + + // arcLink.Set_ErrorsText(); RINOK(extractCallback->OpenResult(arcPath, result, crypted)); + + + { + FOR_VECTOR (r, arcLink.Arcs) + { + const CArc &arc = arcLink.Arcs[r]; + const CArcErrorInfo &er = arc.ErrorInfo; + if (er.IsThereErrorOrWarning()) + { + RINOK(extractCallback->SetError(r, arc.Path, + er.GetErrorFlags(), er.ErrorMessage, + er.GetWarningFlags(), er.WarningMessage)); + } + } + } + if (result != S_OK) + { + thereAreNotOpenArcs = true; + if (!options.StdInMode) + { + NFind::CFileInfo fi; + if (fi.Find(us2fs(arcPath))) + if (!fi.IsDir()) + totalPackProcessed += fi.Size; + } continue; + } if (!options.StdInMode) - for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { - int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]); - if (index >= 0 && index > i) + // numVolumes += arcLink.VolumePaths.Size(); + // arcLink.VolumesSize; + + // totalPackSize -= DeleteUsedFileNamesFromList(arcLink, i + 1, arcPaths, arcPathsFull, &arcSizes); + // numArcs = arcPaths.Size(); + if (arcLink.VolumePaths.Size() != 0) { - arcPaths.Delete(index); - arcPathsFull.Delete(index); - totalPackSize -= archiveSizes[index]; - archiveSizes.Delete(index); - numArcs = arcPaths.Size(); + Int64 correctionSize = arcLink.VolumesSize; + FOR_VECTOR (v, arcLink.VolumePaths) + { + int index = Find_FileName_InSortedVector(arcPathsFull, arcLink.VolumePaths[v]); + if (index >= 0) + { + if ((unsigned)index > i) + { + skipArcs[index] = true; + correctionSize -= arcSizes[index]; + } + } + } + if (correctionSize != 0) + { + Int64 newPackSize = (Int64)totalPackSize + correctionSize; + if (newPackSize < 0) + newPackSize = 0; + totalPackSize = newPackSize; + RINOK(extractCallback->SetTotal(totalPackSize)); + } } } - if (archiveLink.VolumePaths.Size() != 0) - { - totalPackSize += archiveLink.VolumesSize; - RINOK(extractCallback->SetTotal(totalPackSize)); - } #ifndef _NO_CRYPTO + bool passwordIsDefined; UString password; - RINOK(openCallback->Open_GetPasswordIfAny(password)); - if (!password.IsEmpty()) + RINOK(openCallback->Open_GetPasswordIfAny(passwordIsDefined, password)); + if (passwordIsDefined) { RINOK(extractCallback->SetPassword(password)); } #endif - for (int v = 0; v < archiveLink.Arcs.Size(); v++) + FOR_VECTOR (k, arcLink.Arcs) { - const UString &s = archiveLink.Arcs[v].ErrorMessage; - if (!s.IsEmpty()) + const CArc &arc = arcLink.Arcs[k]; + const CArcErrorInfo &er = arc.ErrorInfo; + + if (er.ErrorFormatIndex >= 0) { + RINOK(extractCallback->OpenTypeWarning(arc.Path, + codecs->GetFormatNamePtr(arc.FormatIndex), + codecs->GetFormatNamePtr(er.ErrorFormatIndex))) + /* + UString s = L"Can not open the file as [" + codecs->Formats[arc.ErrorFormatIndex].Name + L"] archive\n"; + s += L"The file is open as [" + codecs->Formats[arc.FormatIndex].Name + L"] archive"; RINOK(extractCallback->MessageError(s)); + */ + } + { + const UString &s = er.ErrorMessage; + if (!s.IsEmpty()) + { + RINOK(extractCallback->MessageError(s)); + } } } - CArc &arc = archiveLink.Arcs.Back(); + CArc &arc = arcLink.Arcs.Back(); arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice); arc.MTime = fi.MTime; UInt64 packProcessed; - RINOK(DecompressArchive(arc, - fi.Size + archiveLink.VolumesSize, - wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage, packProcessed)); + bool calcCrc = + #ifndef _SFX + (hash != NULL); + #else + false; + #endif + + RINOK(DecompressArchive( + codecs, + arcLink, + fi.Size + arcLink.VolumesSize, + wildcardCensor, + options, + calcCrc, + extractCallback, ecs, errorMessage, packProcessed)); if (!options.StdInMode) - packProcessed = fi.Size + archiveLink.VolumesSize; - extractCallbackSpec->LocalProgressSpec->InSize += packProcessed; - extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize; + packProcessed = fi.Size + arcLink.VolumesSize; + totalPackProcessed += packProcessed; + ecs->LocalProgressSpec->InSize += packProcessed; + ecs->LocalProgressSpec->OutSize = ecs->UnpackSize; if (!errorMessage.IsEmpty()) return E_FAIL; } - stat.NumFolders = extractCallbackSpec->NumFolders; - stat.NumFiles = extractCallbackSpec->NumFiles; - stat.UnpackSize = extractCallbackSpec->UnpackSize; - stat.CrcSum = extractCallbackSpec->CrcSum; + if (multi || thereAreNotOpenArcs) + { + RINOK(extractCallback->SetTotal(totalPackSize)); + RINOK(extractCallback->SetCompleted(&totalPackProcessed)); + } + stat.NumFolders = ecs->NumFolders; + stat.NumFiles = ecs->NumFiles; + stat.NumAltStreams = ecs->NumAltStreams; + stat.UnpackSize = ecs->UnpackSize; + stat.AltStreams_UnpackSize = ecs->AltStreams_UnpackSize; stat.NumArchives = arcPaths.Size(); - stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize; + stat.PackSize = ecs->LocalProgressSpec->InSize; return S_OK; } diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.h index 5a939ed23..052b2f7d3 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.h +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.h @@ -3,7 +3,7 @@ #ifndef __EXTRACT_H #define __EXTRACT_H -#include "Windows/FileFind.h" +#include "../../../Windows/FileFind.h" #include "../../Archive/IArchive.h" @@ -14,21 +14,37 @@ #include "../Common/LoadCodecs.h" -struct CExtractOptions +struct CExtractOptionsBase +{ + CBoolPair ElimDup; + + bool PathMode_Force; + bool OverwriteMode_Force; + NExtract::NPathMode::EEnum PathMode; + NExtract::NOverwriteMode::EEnum OverwriteMode; + + FString OutputDir; + CExtractNtOptions NtOptions; + + CExtractOptionsBase(): + PathMode_Force(false), + OverwriteMode_Force(false), + PathMode(NExtract::NPathMode::kFullPaths), + OverwriteMode(NExtract::NOverwriteMode::kAsk) + {} +}; + +struct CExtractOptions: public CExtractOptionsBase { bool StdInMode; bool StdOutMode; bool YesToAll; bool TestMode; - bool CalcCrc; - NExtract::NPathMode::EEnum PathMode; - NExtract::NOverwriteMode::EEnum OverwriteMode; - UString OutputDir; - + // bool ShowDialog; // bool PasswordEnabled; // UString Password; - #if !defined(_7ZIP_ST) && !defined(_SFX) + #ifndef _SFX CObjectVector Properties; #endif @@ -37,13 +53,10 @@ struct CExtractOptions #endif CExtractOptions(): + TestMode(false), StdInMode(false), StdOutMode(false), - YesToAll(false), - TestMode(false), - CalcCrc(false), - PathMode(NExtract::NPathMode::kFullPathnames), - OverwriteMode(NExtract::NOverwriteMode::kAskBefore) + YesToAll(false) {} }; @@ -51,25 +64,30 @@ struct CDecompressStat { UInt64 NumArchives; UInt64 UnpackSize; + UInt64 AltStreams_UnpackSize; UInt64 PackSize; UInt64 NumFolders; UInt64 NumFiles; - UInt32 CrcSum; + UInt64 NumAltStreams; void Clear() { - NumArchives = UnpackSize = PackSize = NumFolders = NumFiles = 0; - CrcSum = 0; + NumArchives = UnpackSize = AltStreams_UnpackSize = PackSize = NumFolders = NumFiles = NumAltStreams = 0; } }; -HRESULT DecompressArchives( - CCodecs *codecs, const CIntVector &formatIndices, +HRESULT Extract( + CCodecs *codecs, + const CObjectVector &types, + const CIntVector &excludedFormats, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, + #ifndef _SFX + IHashCalc *hash, + #endif UString &errorMessage, CDecompressStat &stat); diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractMode.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractMode.h index b448fb30a..a54376705 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractMode.h +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractMode.h @@ -4,28 +4,30 @@ #define __EXTRACT_MODE_H namespace NExtract { - - namespace NPathMode + +namespace NPathMode +{ + enum EEnum { - enum EEnum - { - kFullPathnames, - kCurrentPathnames, - kNoPathnames - }; - } - - namespace NOverwriteMode + kFullPaths, + kCurPaths, + kNoPaths, + kAbsPaths + }; +} + +namespace NOverwriteMode +{ + enum EEnum { - enum EEnum - { - kAskBefore, - kWithoutPrompt, - kSkipExisting, - kAutoRename, - kAutoRenameExisting - }; - } + kAsk, + kOverwrite, + kSkip, + kRename, + kRenameExisting + }; +} + } #endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.cpp index 8f31708b6..852fd5adb 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.cpp +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.cpp @@ -2,26 +2,44 @@ #include "StdAfx.h" -#include "../../../../C/Types.h" +#include "../../../Common/Wildcard.h" -#include "Common/Wildcard.h" +#include "../../../Windows/FileName.h" #include "ExtractingFilePath.h" -static UString ReplaceIncorrectChars(const UString &s) +static UString ReplaceIncorrectChars(const UString &s, bool repaceColon) { #ifdef _WIN32 UString res; - for (int i = 0; i < s.Length(); i++) + bool beforeColon = true; { - wchar_t c = s[i]; - if (c < 0x20 || c == '*' || c == '?' || c == '<' || c == '>' || c == '|' || c == ':' || c == '"') - c = '_'; - res += c; + for (unsigned i = 0; i < s.Len(); i++) + { + wchar_t c = s[i]; + if (beforeColon) + if (c == '*' || c == '?' || c < 0x20 || c == '<' || c == '>' || c == '|' || c == '"') + c = '_'; + if (c == ':') + { + if (repaceColon) + c = '_'; + else + beforeColon = false; + } + res += c; + } + } + if (beforeColon) + { + for (int i = res.Len() - 1; i >= 0; i--) + { + wchar_t c = res[i]; + if (c != '.' && c != ' ') + break; + res.ReplaceOneCharAtPos(i, '_'); + } } - res.TrimRight(); - while (!res.IsEmpty() && res[res.Length() - 1] == '.') - res.Delete(res.Length() - 1); return res; #else return s; @@ -29,27 +47,28 @@ static UString ReplaceIncorrectChars(const UString &s) } #ifdef _WIN32 + static const wchar_t *g_ReservedNames[] = { L"CON", L"PRN", L"AUX", L"NUL" }; -static bool CheckTail(const UString &name, int len) +static bool CheckTail(const UString &name, unsigned len) { int dotPos = name.Find(L'.'); if (dotPos < 0) - dotPos = name.Length(); + dotPos = name.Len(); UString s = name.Left(dotPos); s.TrimRight(); - return (s.Length() != len); + return s.Len() != len; } static bool CheckNameNum(const UString &name, const wchar_t *reservedName) { - int len = MyStringLen(reservedName); - if (name.Length() <= len) + unsigned len = MyStringLen(reservedName); + if (name.Len() <= len) return true; - if (name.Left(len).CompareNoCase(reservedName) != 0) + if (MyStringCompareNoCase_N(name, reservedName, len) != 0) return true; wchar_t c = name[len]; if (c < L'0' || c > L'9') @@ -59,13 +78,13 @@ static bool CheckNameNum(const UString &name, const wchar_t *reservedName) static bool IsSupportedName(const UString &name) { - for (int i = 0; i < sizeof(g_ReservedNames) / sizeof(g_ReservedNames[0]); i++) + for (unsigned i = 0; i < ARRAY_SIZE(g_ReservedNames); i++) { const wchar_t *reservedName = g_ReservedNames[i]; - int len = MyStringLen(reservedName); - if (name.Length() < len) + unsigned len = MyStringLen(reservedName); + if (name.Len() < len) continue; - if (name.Left(len).CompareNoCase(reservedName) != 0) + if (MyStringCompareNoCase_N(name, reservedName, len) != 0) continue; if (!CheckTail(name, len)) return false; @@ -74,21 +93,34 @@ static bool IsSupportedName(const UString &name) return false; return CheckNameNum(name, L"LPT"); } + #endif -static UString GetCorrectFileName(const UString &path) +static UString GetCorrectFileName(const UString &path, bool repaceColon) { if (path == L".." || path == L".") return UString(); - return ReplaceIncorrectChars(path); + return ReplaceIncorrectChars(path, repaceColon); } -void MakeCorrectPath(UStringVector &pathParts) +void MakeCorrectPath(bool isPathFromRoot, UStringVector &pathParts, bool replaceAltStreamColon) { - for (int i = 0; i < pathParts.Size();) + for (unsigned i = 0; i < pathParts.Size();) { UString &s = pathParts[i]; - s = GetCorrectFileName(s); + #ifdef _WIN32 + bool needReplaceColon = (replaceAltStreamColon || i != pathParts.Size() - 1); + if (i == 0 && isPathFromRoot && NWindows::NFile::NName::IsDrivePath(s)) + { + UString s2 = s[0]; + s2 += L'_'; + s2 += GetCorrectFileName(s.Ptr(2), needReplaceColon); + s = s2; + } + else + s = GetCorrectFileName(s, needReplaceColon); + #endif + if (s.IsEmpty()) pathParts.Delete(i); else @@ -105,7 +137,7 @@ void MakeCorrectPath(UStringVector &pathParts) UString MakePathNameFromParts(const UStringVector &parts) { UString result; - for (int i = 0; i < parts.Size(); i++) + FOR_VECTOR (i, parts) { if (i != 0) result += WCHAR_PATH_SEPARATOR; @@ -114,28 +146,44 @@ UString MakePathNameFromParts(const UStringVector &parts) return result; } +static const wchar_t *k_EmptyReplaceName = L"[]"; + +void Correct_IfEmptyLastPart(UStringVector &parts) +{ + if (parts.IsEmpty()) + parts.Add(k_EmptyReplaceName); + else + { + UString &s = parts.Back(); + if (s.IsEmpty()) + s = k_EmptyReplaceName; + } +} + UString GetCorrectFsPath(const UString &path) { - UString res = GetCorrectFileName(path); + UString res = GetCorrectFileName(path, true); #ifdef _WIN32 if (!IsSupportedName(res)) res = (UString)L"_" + res; #endif + if (res.IsEmpty()) + res = k_EmptyReplaceName; return res; } - + UString GetCorrectFullFsPath(const UString &path) { UStringVector parts; SplitPathToParts(path, parts); - for (int i = 0; i < parts.Size(); i++) + FOR_VECTOR (i, parts) { UString &s = parts[i]; #ifdef _WIN32 - while (!s.IsEmpty() && s[s.Length() - 1] == '.') - s.Delete(s.Length() - 1); + while (!s.IsEmpty() && (s.Back() == '.' || s.Back() == ' ')) + s.DeleteBack(); if (!IsSupportedName(s)) - s = (UString)L"_" + s; + s.InsertAtFront(L'_'); #endif } return MakePathNameFromParts(parts); diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.h index da28bfc23..751248a97 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.h +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.h @@ -3,11 +3,19 @@ #ifndef __EXTRACTING_FILE_PATH_H #define __EXTRACTING_FILE_PATH_H -#include "Common/MyString.h" +#include "../../../Common/MyString.h" UString MakePathNameFromParts(const UStringVector &parts); -void MakeCorrectPath(UStringVector &pathParts); + +/* for WIN32: + if (isRoot == true), and pathParts[0] contains path like "c:name", + it thinks that "c:" is drive prefix (it's not ":name alt stream) and + the function changes part to c_name */ +void MakeCorrectPath(bool isPathFromRoot, UStringVector &pathParts, bool replaceAltStreamColon); + UString GetCorrectFsPath(const UString &path); UString GetCorrectFullFsPath(const UString &path); +void Correct_IfEmptyLastPart(UStringVector &parts); + #endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.cpp new file mode 100644 index 000000000..2d13a2af1 --- /dev/null +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.cpp @@ -0,0 +1,361 @@ +// HashCalc.cpp + +#include "StdAfx.h" + +#include "../../../../C/Alloc.h" + +#include "../../../Common/StringToInt.h" + +#include "../../Common/FileStreams.h" +#include "../../Common/StreamUtils.h" + +#include "EnumDirItems.h" +#include "HashCalc.h" + +using namespace NWindows; + +class CHashMidBuf +{ + void *_data; +public: + CHashMidBuf(): _data(0) {} + operator void *() { return _data; } + bool Alloc(size_t size) + { + if (_data != 0) + return false; + _data = ::MidAlloc(size); + return _data != 0; + } + ~CHashMidBuf() { ::MidFree(_data); } +}; + +struct CEnumDirItemCallback_Hash: public IEnumDirItemCallback +{ + IHashCallbackUI *Callback; + + HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) + { + return Callback->ScanProgress(numFolders, numFiles, totalSize, path, isDir); + } +}; + +static const wchar_t *k_DefaultHashMethod = L"CRC32"; + +HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &hashMethods) +{ + UStringVector names = hashMethods; + if (names.IsEmpty()) + names.Add(k_DefaultHashMethod); + + CRecordVector ids; + CObjectVector methods; + + unsigned i; + for (i = 0; i < names.Size(); i++) + { + COneMethodInfo m; + RINOK(m.ParseMethodFromString(names[i])); + + if (m.MethodName.IsEmpty()) + m.MethodName = k_DefaultHashMethod; + + if (m.MethodName == L"*") + { + CRecordVector tempMethods; + GetHashMethods(EXTERNAL_CODECS_LOC_VARS tempMethods); + methods.Clear(); + ids.Clear(); + FOR_VECTOR (t, tempMethods) + { + int index = ids.AddToUniqueSorted(tempMethods[t]); + if (ids.Size() != methods.Size()) + methods.Insert(index, m); + } + break; + } + else + { + // m.MethodName.RemoveChar(L'-'); + CMethodId id; + if (!FindHashMethod(EXTERNAL_CODECS_LOC_VARS m.MethodName, id)) + return E_NOTIMPL; + int index = ids.AddToUniqueSorted(id); + if (ids.Size() != methods.Size()) + methods.Insert(index, m); + } + } + + for (i = 0; i < ids.Size(); i++) + { + CMyComPtr hasher; + UString name; + RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS ids[i], name, hasher)); + if (!hasher) + throw "Can't create hasher"; + const COneMethodInfo &m = methods[i]; + { + CMyComPtr scp; + hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp); + if (scp) + { + RINOK(m.SetCoderProps(scp, NULL)); + } + } + UInt32 digestSize = hasher->GetDigestSize(); + if (digestSize > k_HashCalc_DigestSize_Max) + return E_NOTIMPL; + CHasherState &h = Hashers.AddNew(); + h.Hasher = hasher; + h.Name = name; + h.DigestSize = digestSize; + for (int i = 0; i < k_HashCalc_NumGroups; i++) + memset(h.Digests[i], 0, digestSize); + } + return S_OK; +} + +void CHashBundle::InitForNewFile() +{ + CurSize = 0; + FOR_VECTOR (i, Hashers) + { + CHasherState &h = Hashers[i]; + h.Hasher->Init(); + memset(h.Digests[k_HashCalc_Index_Current], 0, h.DigestSize); + } +} + +void CHashBundle::Update(const void *data, UInt32 size) +{ + CurSize += size; + FOR_VECTOR (i, Hashers) + Hashers[i].Hasher->Update(data, size); +} + +void CHashBundle::SetSize(UInt64 size) +{ + CurSize = size; +} + +static void AddDigests(Byte *dest, const Byte *src, UInt32 size) +{ + unsigned next = 0; + for (UInt32 i = 0; i < size; i++) + { + next += (unsigned)dest[i] + (unsigned)src[i]; + dest[i] = (Byte)next; + next >>= 8; + } +} + +void CHashBundle::Final(bool isDir, bool isAltStream, const UString &path) +{ + if (isDir) + NumDirs++; + else if (isAltStream) + { + NumAltStreams++; + AltStreamsSize += CurSize; + } + else + { + NumFiles++; + FilesSize += CurSize; + } + + Byte pre[16]; + memset(pre, 0, sizeof(pre)); + if (isDir) + pre[0] = 1; + + FOR_VECTOR (i, Hashers) + { + CHasherState &h = Hashers[i]; + if (!isDir) + { + h.Hasher->Final(h.Digests[0]); + if (!isAltStream) + AddDigests(h.Digests[k_HashCalc_Index_DataSum], h.Digests[0], h.DigestSize); + } + + h.Hasher->Init(); + h.Hasher->Update(pre, sizeof(pre)); + h.Hasher->Update(h.Digests[0], h.DigestSize); + + for (unsigned k = 0; k < path.Len(); k++) + { + wchar_t c = path[k]; + Byte temp[2] = { (Byte)(c & 0xFF), (Byte)((c >> 8) & 0xFF) }; + h.Hasher->Update(temp, 2); + } + + Byte tempDigest[k_HashCalc_DigestSize_Max]; + h.Hasher->Final(tempDigest); + if (!isAltStream) + AddDigests(h.Digests[k_HashCalc_Index_NamesSum], tempDigest, h.DigestSize); + AddDigests(h.Digests[k_HashCalc_Index_StreamsSum], tempDigest, h.DigestSize); + } +} + + +HRESULT HashCalc( + DECL_EXTERNAL_CODECS_LOC_VARS + const NWildcard::CCensor &censor, + const CHashOptions &options, + UString &errorInfo, + IHashCallbackUI *callback) +{ + CDirItems dirItems; + + UInt64 numErrors = 0; + UInt64 totalBytes = 0; + if (options.StdInMode) + { + CDirItem di; + di.Size = (UInt64)(Int64)-1; + di.Attrib = 0; + di.MTime.dwLowDateTime = 0; + di.MTime.dwHighDateTime = 0; + di.CTime = di.ATime = di.MTime; + dirItems.Items.Add(di); + } + else + { + CEnumDirItemCallback_Hash enumCallback; + enumCallback.Callback = callback; + RINOK(callback->StartScanning()); + dirItems.ScanAltStreams = options.AltStreamsMode; + HRESULT res = EnumerateItems(censor, + options.PathMode, + UString(), + dirItems, &enumCallback); + totalBytes = dirItems.TotalSize; + FOR_VECTOR (i, dirItems.ErrorPaths) + { + RINOK(callback->CanNotFindError(fs2us(dirItems.ErrorPaths[i]), dirItems.ErrorCodes[i])); + } + numErrors = dirItems.ErrorPaths.Size(); + if (res != S_OK) + { + if (res != E_ABORT) + errorInfo = L"Scanning error"; + return res; + } + RINOK(callback->FinishScanning()); + } + + unsigned i; + CHashBundle hb; + RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS options.Methods)); + hb.Init(); + hb.NumErrors = numErrors; + + if (options.StdInMode) + { + RINOK(callback->SetNumFiles(1)); + } + else + { + RINOK(callback->SetTotal(totalBytes)); + } + + const UInt32 kBufSize = 1 << 15; + CHashMidBuf buf; + if (!buf.Alloc(kBufSize)) + return E_OUTOFMEMORY; + + UInt64 completeValue = 0; + + RINOK(callback->BeforeFirstFile(hb)); + + for (i = 0; i < dirItems.Items.Size(); i++) + { + CMyComPtr inStream; + UString path; + bool isDir = false; + bool isAltStream = false; + if (options.StdInMode) + { + inStream = new CStdInFileStream; + } + else + { + CInFileStream *inStreamSpec = new CInFileStream; + inStream = inStreamSpec; + const CDirItem &dirItem = dirItems.Items[i]; + isDir = dirItem.IsDir(); + isAltStream = dirItem.IsAltStream; + path = dirItems.GetLogPath(i); + if (!isDir) + { + UString phyPath = dirItems.GetPhyPath(i); + if (!inStreamSpec->OpenShared(us2fs(phyPath), options.OpenShareForWrite)) + { + HRESULT res = callback->OpenFileError(phyPath, ::GetLastError()); + hb.NumErrors++; + if (res != S_FALSE) + return res; + continue; + } + } + } + RINOK(callback->GetStream(path, isDir)); + UInt64 fileSize = 0; + + hb.InitForNewFile(); + if (!isDir) + { + for (UInt32 step = 0;; step++) + { + if ((step & 0xFF) == 0) + RINOK(callback->SetCompleted(&completeValue)); + UInt32 size; + RINOK(inStream->Read(buf, kBufSize, &size)); + if (size == 0) + break; + hb.Update(buf, size); + fileSize += size; + completeValue += size; + } + } + hb.Final(isDir, isAltStream, path); + RINOK(callback->SetOperationResult(fileSize, hb, !isDir)); + RINOK(callback->SetCompleted(&completeValue)); + } + return callback->AfterLastFile(hb); +} + + +static inline char GetHex(Byte value) +{ + return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} + +void AddHashHexToString(char *dest, const Byte *data, UInt32 size) +{ + dest[size * 2] = 0; + if (!data) + { + for (UInt32 i = 0; i < size; i++) + { + dest[0] = ' '; + dest[1] = ' '; + dest += 2; + } + return; + } + int step = 2; + if (size <= 8) + { + step = -2; + dest += size * 2 - 2; + } + for (UInt32 i = 0; i < size; i++) + { + Byte b = data[i]; + dest[0] = GetHex((Byte)((b >> 4) & 0xF)); + dest[1] = GetHex((Byte)(b & 0xF)); + dest += step; + } +} diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.h new file mode 100644 index 000000000..68e2404cc --- /dev/null +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.h @@ -0,0 +1,107 @@ +// HashCalc.h + +#ifndef __HASH_CALC_H +#define __HASH_CALC_H + +#include "../../../Common/Wildcard.h" + +#include "../../Common/CreateCoder.h" +#include "../../Common/MethodProps.h" + +#include "Property.h" + +const unsigned k_HashCalc_DigestSize_Max = 64; + +const unsigned k_HashCalc_NumGroups = 4; + +enum +{ + k_HashCalc_Index_Current, + k_HashCalc_Index_DataSum, + k_HashCalc_Index_NamesSum, + k_HashCalc_Index_StreamsSum +}; + +struct CHasherState +{ + CMyComPtr Hasher; + UString Name; + UInt32 DigestSize; + Byte Digests[k_HashCalc_NumGroups][k_HashCalc_DigestSize_Max]; +}; + +struct IHashCalc +{ + virtual void InitForNewFile() = 0; + virtual void Update(const void *data, UInt32 size) = 0; + virtual void SetSize(UInt64 size) = 0; + virtual void Final(bool isDir, bool isAltStream, const UString &path) = 0; +}; + +struct CHashBundle: public IHashCalc +{ + CObjectVector Hashers; + + UInt64 NumFiles; + UInt64 NumDirs; + UInt64 NumAltStreams; + UInt64 FilesSize; + UInt64 AltStreamsSize; + UInt64 NumErrors; + + UInt64 CurSize; + + HRESULT SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &methods); + + void Init() + { + NumFiles = NumDirs = NumAltStreams = FilesSize = AltStreamsSize = NumErrors = 0; + } + + void InitForNewFile(); + void Update(const void *data, UInt32 size); + void SetSize(UInt64 size); + void Final(bool isDir, bool isAltStream, const UString &path); +}; + +#define INTERFACE_IHashCallbackUI(x) \ + virtual HRESULT StartScanning() x; \ + virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) x; \ + virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \ + virtual HRESULT FinishScanning() x; \ + virtual HRESULT SetNumFiles(UInt64 numFiles) x; \ + virtual HRESULT SetTotal(UInt64 size) x; \ + virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \ + virtual HRESULT CheckBreak() x; \ + virtual HRESULT BeforeFirstFile(const CHashBundle &hb) x; \ + virtual HRESULT GetStream(const wchar_t *name, bool isFolder) x; \ + virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \ + virtual HRESULT SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash) x; \ + virtual HRESULT AfterLastFile(const CHashBundle &hb) x; \ + +struct IHashCallbackUI +{ + INTERFACE_IHashCallbackUI(=0) +}; + +struct CHashOptions +{ + UStringVector Methods; + bool OpenShareForWrite; + bool StdInMode; + bool AltStreamsMode; + NWildcard::ECensorPathMode PathMode; + + CHashOptions(): StdInMode(false), OpenShareForWrite(false), AltStreamsMode(false), PathMode(NWildcard::k_RelatPath) {}; +}; + +HRESULT HashCalc( + DECL_EXTERNAL_CODECS_LOC_VARS + const NWildcard::CCensor &censor, + const CHashOptions &options, + UString &errorInfo, + IHashCallbackUI *callback); + +void AddHashHexToString(char *dest, const Byte *data, UInt32 size); + +#endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/IFileExtractCallback.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/IFileExtractCallback.h index e8dcdce5f..7bb852795 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/IFileExtractCallback.h +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/IFileExtractCallback.h @@ -1,9 +1,10 @@ // IFileExtractCallback.h -#ifndef __IFILEEXTRACTCALLBACK_H -#define __IFILEEXTRACTCALLBACK_H +#ifndef __I_FILE_EXTRACT_CALLBACK_H +#define __I_FILE_EXTRACT_CALLBACK_H + +#include "../../../Common/MyString.h" -#include "Common/MyString.h" #include "../../IDecl.h" namespace NOverwriteAnswer @@ -35,12 +36,37 @@ struct IExtractCallbackUI: IFolderArchiveExtractCallback { virtual HRESULT BeforeOpen(const wchar_t *name) = 0; virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted) = 0; + virtual HRESULT SetError(int level, const wchar_t *name, + UInt32 errorFlags, const wchar_t *errors, + UInt32 warningFlags, const wchar_t *warnings) = 0; virtual HRESULT ThereAreNoFiles() = 0; virtual HRESULT ExtractResult(HRESULT result) = 0; + virtual HRESULT OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType) = 0; #ifndef _NO_CRYPTO virtual HRESULT SetPassword(const UString &password) = 0; #endif }; + +#define INTERFACE_IGetProp(x) \ + STDMETHOD(GetProp)(PROPID propID, PROPVARIANT *value) x; \ + +DECL_INTERFACE_SUB(IGetProp, IUnknown, 0x01, 0x20) +{ + INTERFACE_IGetProp(PURE) +}; + +#define INTERFACE_IFolderExtractToStreamCallback(x) \ + STDMETHOD(UseExtractToStream)(Int32 *res) x; \ + STDMETHOD(GetStream7)(const wchar_t *name, Int32 isDir, ISequentialOutStream **outStream, Int32 askExtractMode, IGetProp *getProp) x; \ + STDMETHOD(PrepareOperation7)(Int32 askExtractMode) x; \ + STDMETHOD(SetOperationResult7)(Int32 resultEOperationResult, bool encrypted) x; \ + +DECL_INTERFACE_SUB(IFolderExtractToStreamCallback, IUnknown, 0x01, 0x30) +{ + INTERFACE_IFolderExtractToStreamCallback(PURE) +}; + + #endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.cpp index 171b7c104..09c79147d 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.cpp +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.cpp @@ -2,18 +2,27 @@ #include "StdAfx.h" -#include "LoadCodecs.h" +#include "../../../../C/7zVersion.h" #include "../../../Common/MyCom.h" +#include "../../../Common/StringToInt.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/PropVariant.h" + +#include "LoadCodecs.h" + +using namespace NWindows; + #ifdef NEW_FOLDER_INTERFACE #include "../../../Common/StringToInt.h" #endif -#include "../../../Windows/PropVariant.h" #include "../../ICoder.h" #include "../../Common/RegisterArc.h" #ifdef EXTERNAL_CODECS + #include "../../../Windows/FileFind.h" #include "../../../Windows/DLL.h" #ifdef NEW_FOLDER_INTERFACE @@ -22,106 +31,169 @@ static const UINT kIconTypesResId = 100; #endif #ifdef _WIN32 -#include "Windows/Registry.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/Registry.h" #else -#include "Common/StringConvert.h" +#include "../../../Common/StringConvert.h" #endif -using namespace NWindows; using namespace NFile; #ifdef _WIN32 extern HINSTANCE g_hInstance; #endif -static CSysString GetLibraryFolderPrefix() -{ - #ifdef _WIN32 - TCHAR fullPath[MAX_PATH + 1]; - ::GetModuleFileName(g_hInstance, fullPath, MAX_PATH); - CSysString path = fullPath; - int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); - return path.Left(pos + 1); - #else - const char *p7zip_home_dir = getenv("P7ZIP_HOME_DIR"); - if (p7zip_home_dir == 0) p7zip_home_dir="./"; -#ifdef _UNICODE - return MultiByteToUnicodeString(p7zip_home_dir); -#else - return p7zip_home_dir; -#endif - #endif -} - -#define kCodecsFolderName TEXT("Codecs") -#define kFormatsFolderName TEXT("Formats") -static const TCHAR *kMainDll = TEXT("7z.dll"); +#define kCodecsFolderName FTEXT("Codecs") +#define kFormatsFolderName FTEXT("Formats") +static CFSTR kMainDll = FTEXT("7z.dll"); #ifdef _WIN32 + static LPCTSTR kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip"); -static LPCTSTR kProgramPathValue = TEXT("Path"); -static bool ReadPathFromRegistry(HKEY baseKey, CSysString &path) +static LPCWSTR kProgramPathValue = L"Path"; +static LPCWSTR kProgramPath2Value = L"Path" + #ifdef _WIN64 + L"64"; + #else + L"32"; + #endif + +static bool ReadPathFromRegistry(HKEY baseKey, LPCWSTR value, FString &path) { NRegistry::CKey key; - if(key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS) - if (key.QueryValue(kProgramPathValue, path) == ERROR_SUCCESS) + if (key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS) + { + UString pathU; + if (key.QueryValue(value, pathU) == ERROR_SUCCESS) { + path = us2fs(pathU); NName::NormalizeDirPathPrefix(path); - return true; + return NFind::DoesFileExist(path + kMainDll); } + } return false; } -#endif +#endif // _WIN32 + +#endif // EXTERNAL_CODECS + -CSysString GetBaseFolderPrefixFromRegistry() +static const unsigned kNumArcsMax = 48; +static unsigned g_NumArcs = 0; +static const CArcInfo *g_Arcs[kNumArcsMax]; + +void RegisterArc(const CArcInfo *arcInfo) throw() { - CSysString moduleFolderPrefix = GetLibraryFolderPrefix(); -#ifdef _UNICODE - NFind::CFileInfoW fi; -#else - NFind::CFileInfo fi; -#endif - if (NFind::FindFile(moduleFolderPrefix + kMainDll, fi)) - if (!fi.IsDir()) - return moduleFolderPrefix; - if (NFind::FindFile(moduleFolderPrefix + kCodecsFolderName, fi)) - if (fi.IsDir()) - return moduleFolderPrefix; - if (NFind::FindFile(moduleFolderPrefix + kFormatsFolderName, fi)) - if (fi.IsDir()) - return moduleFolderPrefix; + if (g_NumArcs < kNumArcsMax) + { + g_Arcs[g_NumArcs] = arcInfo; + g_NumArcs++; + } +} + +static void SplitString(const UString &srcString, UStringVector &destStrings) +{ + destStrings.Clear(); + UString s; + unsigned len = srcString.Len(); + if (len == 0) + return; + for (unsigned i = 0; i < len; i++) + { + wchar_t c = srcString[i]; + if (c == L' ') + { + if (!s.IsEmpty()) + { + destStrings.Add(s); + s.Empty(); + } + } + else + s += c; + } + if (!s.IsEmpty()) + destStrings.Add(s); +} + +int CArcInfoEx::FindExtension(const UString &ext) const +{ + FOR_VECTOR (i, Exts) + if (ext.IsEqualToNoCase(Exts[i].Ext)) + return i; + return -1; +} + +void CArcInfoEx::AddExts(const UString &ext, const UString &addExt) +{ + UStringVector exts, addExts; + SplitString(ext, exts); + SplitString(addExt, addExts); + FOR_VECTOR (i, exts) + { + CArcExtInfo extInfo; + extInfo.Ext = exts[i]; + if (i < addExts.Size()) + { + extInfo.AddExt = addExts[i]; + if (extInfo.AddExt == L"*") + extInfo.AddExt.Empty(); + } + Exts.Add(extInfo); + } +} + +#ifndef _SFX + +static bool ParseSignatures(const Byte *data, unsigned size, CObjectVector &signatures) +{ + signatures.Clear(); + while (size > 0) + { + unsigned len = *data++; + size--; + if (len > size) + return false; + signatures.AddNew().CopyFrom(data, len); + data += len; + size -= len; + } + return true; +} + +#endif // _SFX + +#ifdef EXTERNAL_CODECS + +static FString GetBaseFolderPrefixFromRegistry() +{ + FString moduleFolderPrefix = NDLL::GetModuleDirPrefix(); #ifdef _WIN32 if (!NFind::DoesFileExist(moduleFolderPrefix + kMainDll) && !NFind::DoesDirExist(moduleFolderPrefix + kCodecsFolderName) && !NFind::DoesDirExist(moduleFolderPrefix + kFormatsFolderName)) { - CSysString path; - if (ReadPathFromRegistry(HKEY_CURRENT_USER, path)) - return path; - if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path)) - return path; + FString path; + if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPath2Value, path)) return path; + if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPath2Value, path)) return path; + if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPathValue, path)) return path; + if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPathValue, path)) return path; } #endif return moduleFolderPrefix; } -typedef UInt32 (WINAPI *GetNumberOfMethodsFunc)(UInt32 *numMethods); -typedef UInt32 (WINAPI *GetNumberOfFormatsFunc)(UInt32 *numFormats); -typedef UInt32 (WINAPI *GetHandlerPropertyFunc)(PROPID propID, PROPVARIANT *value); -typedef UInt32 (WINAPI *GetHandlerPropertyFunc2)(UInt32 index, PROPID propID, PROPVARIANT *value); -typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *iid, void **outObject); -typedef UInt32 (WINAPI *SetLargePageModeFunc)(); - - -static HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 index, +static HRESULT GetCoderClass(Func_GetMethodProperty getMethodProperty, UInt32 index, PROPID propId, CLSID &clsId, bool &isAssigned) { - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; isAssigned = false; RINOK(getMethodProperty(index, propId, &prop)); if (prop.vt == VT_BSTR) { + if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID)) + return E_FAIL; isAssigned = true; clsId = *(const GUID *)prop.bstrVal; } @@ -133,34 +205,48 @@ static HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 ind HRESULT CCodecs::LoadCodecs() { CCodecLib &lib = Libs.Back(); - lib.GetMethodProperty = (GetMethodPropertyFunc)lib.Lib.GetProc("GetMethodProperty"); - if (lib.GetMethodProperty == NULL) - return S_OK; - - UInt32 numMethods = 1; - GetNumberOfMethodsFunc getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)lib.Lib.GetProc("GetNumberOfMethods"); - if (getNumberOfMethodsFunc != NULL) + lib.GetMethodProperty = (Func_GetMethodProperty)lib.Lib.GetProc("GetMethodProperty"); + if (lib.GetMethodProperty) { - RINOK(getNumberOfMethodsFunc(&numMethods)); + UInt32 numMethods = 1; + Func_GetNumberOfMethods getNumberOfMethodsFunc = (Func_GetNumberOfMethods)lib.Lib.GetProc("GetNumberOfMethods"); + if (getNumberOfMethodsFunc) + { + RINOK(getNumberOfMethodsFunc(&numMethods)); + } + for (UInt32 i = 0; i < numMethods; i++) + { + CDllCodecInfo info; + info.LibIndex = Libs.Size() - 1; + info.CodecIndex = i; + RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned)); + RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned)); + Codecs.Add(info); + } } - for(UInt32 i = 0; i < numMethods; i++) + Func_GetHashers getHashers = (Func_GetHashers)lib.Lib.GetProc("GetHashers"); + if (getHashers) { - CDllCodecInfo info; - info.LibIndex = Libs.Size() - 1; - info.CodecIndex = i; - - RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned)); - RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned)); - - Codecs.Add(info); + RINOK(getHashers(&lib.Hashers)); + if (lib.Hashers) + { + UInt32 numMethods = lib.Hashers->GetNumHashers(); + for (UInt32 i = 0; i < numMethods; i++) + { + CDllHasherInfo info; + info.LibIndex = Libs.Size() - 1; + info.HasherIndex = i; + Hashers.Add(info); + } + } } return S_OK; } -static HRESULT ReadProp( - GetHandlerPropertyFunc getProp, - GetHandlerPropertyFunc2 getProp2, +static HRESULT GetProp( + Func_GetHandlerProperty getProp, + Func_GetHandlerProperty2 getProp2, UInt32 index, PROPID propID, NCOM::CPropVariant &prop) { if (getProp2) @@ -168,13 +254,14 @@ static HRESULT ReadProp( return getProp(propID, &prop); } -static HRESULT ReadBoolProp( - GetHandlerPropertyFunc getProp, - GetHandlerPropertyFunc2 getProp2, +static HRESULT GetProp_Bool( + Func_GetHandlerProperty getProp, + Func_GetHandlerProperty2 getProp2, UInt32 index, PROPID propID, bool &res) { + res = false; NCOM::CPropVariant prop; - RINOK(ReadProp(getProp, getProp2, index, propID, prop)); + RINOK(GetProp(getProp, getProp2, index, propID, prop)); if (prop.vt == VT_BOOL) res = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt != VT_EMPTY) @@ -182,132 +269,150 @@ static HRESULT ReadBoolProp( return S_OK; } -static HRESULT ReadStringProp( - GetHandlerPropertyFunc getProp, - GetHandlerPropertyFunc2 getProp2, - UInt32 index, PROPID propID, UString &res) +static HRESULT GetProp_UInt32( + Func_GetHandlerProperty getProp, + Func_GetHandlerProperty2 getProp2, + UInt32 index, PROPID propID, UInt32 &res, bool &defined) { + res = 0; + defined = false; NCOM::CPropVariant prop; - RINOK(ReadProp(getProp, getProp2, index, propID, prop)); - if (prop.vt == VT_BSTR) - res = prop.bstrVal; + RINOK(GetProp(getProp, getProp2, index, propID, prop)); + if (prop.vt == VT_UI4) + { + res = prop.ulVal; + defined = true; + } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } -#endif - -static const unsigned int kNumArcsMax = 48; -static unsigned int g_NumArcs = 0; -static const CArcInfo *g_Arcs[kNumArcsMax]; -void RegisterArc(const CArcInfo *arcInfo) +static HRESULT GetProp_String( + Func_GetHandlerProperty getProp, + Func_GetHandlerProperty2 getProp2, + UInt32 index, PROPID propID, UString &res) { - if (g_NumArcs < kNumArcsMax) - g_Arcs[g_NumArcs++] = arcInfo; + res.Empty(); + NCOM::CPropVariant prop; + RINOK(GetProp(getProp, getProp2, index, propID, prop)); + if (prop.vt == VT_BSTR) + res = prop.bstrVal; + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; } -static void SplitString(const UString &srcString, UStringVector &destStrings) +static HRESULT GetProp_RawData( + Func_GetHandlerProperty getProp, + Func_GetHandlerProperty2 getProp2, + UInt32 index, PROPID propID, CByteBuffer &bb) { - destStrings.Clear(); - UString s; - int len = srcString.Length(); - if (len == 0) - return; - for (int i = 0; i < len; i++) + bb.Free(); + NCOM::CPropVariant prop; + RINOK(GetProp(getProp, getProp2, index, propID, prop)); + if (prop.vt == VT_BSTR) { - wchar_t c = srcString[i]; - if (c == L' ') - { - if (!s.IsEmpty()) - { - destStrings.Add(s); - s.Empty(); - } - } - else - s += c; + UINT len = ::SysStringByteLen(prop.bstrVal); + bb.CopyFrom((const Byte *)prop.bstrVal, len); } - if (!s.IsEmpty()) - destStrings.Add(s); + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; } -void CArcInfoEx::AddExts(const wchar_t *ext, const wchar_t *addExt) +static const UInt32 kArcFlagsPars[] = { - UStringVector exts, addExts; - if (ext != 0) - SplitString(ext, exts); - if (addExt != 0) - SplitString(addExt, addExts); - for (int i = 0; i < exts.Size(); i++) - { - CArcExtInfo extInfo; - extInfo.Ext = exts[i]; - if (i < addExts.Size()) - { - extInfo.AddExt = addExts[i]; - if (extInfo.AddExt == L"*") - extInfo.AddExt.Empty(); - } - Exts.Add(extInfo); - } -} - -#ifdef EXTERNAL_CODECS + NArchive::NHandlerPropID::kKeepName, NArcInfoFlags::kKeepName, + NArchive::NHandlerPropID::kAltStreams, NArcInfoFlags::kAltStreams, + NArchive::NHandlerPropID::kNtSecure, NArcInfoFlags::kNtSecure +}; HRESULT CCodecs::LoadFormats() { const NDLL::CLibrary &lib = Libs.Back().Lib; - GetHandlerPropertyFunc getProp = 0; - GetHandlerPropertyFunc2 getProp2 = (GetHandlerPropertyFunc2)lib.GetProc("GetHandlerProperty2"); - if (getProp2 == NULL) - { - getProp = (GetHandlerPropertyFunc)lib.GetProc("GetHandlerProperty"); - if (getProp == NULL) - return S_OK; - } + + Func_GetHandlerProperty getProp = NULL; + Func_GetHandlerProperty2 getProp2 = (Func_GetHandlerProperty2)lib.GetProc("GetHandlerProperty2"); + Func_GetIsArc getIsArc = (Func_GetIsArc)lib.GetProc("GetIsArc"); UInt32 numFormats = 1; - GetNumberOfFormatsFunc getNumberOfFormats = (GetNumberOfFormatsFunc)lib.GetProc("GetNumberOfFormats"); - if (getNumberOfFormats != NULL) + + if (getProp2) { - RINOK(getNumberOfFormats(&numFormats)); + Func_GetNumberOfFormats getNumberOfFormats = (Func_GetNumberOfFormats)lib.GetProc("GetNumberOfFormats"); + if (getNumberOfFormats) + { + RINOK(getNumberOfFormats(&numFormats)); + } + } + else + { + getProp = (Func_GetHandlerProperty)lib.GetProc("GetHandlerProperty"); + if (!getProp) + return S_OK; } - if (getProp2 == NULL) - numFormats = 1; - for(UInt32 i = 0; i < numFormats; i++) + for (UInt32 i = 0; i < numFormats; i++) { CArcInfoEx item; item.LibIndex = Libs.Size() - 1; item.FormatIndex = i; - RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kName, item.Name)); + RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kName, item.Name)); - NCOM::CPropVariant prop; - if (ReadProp(getProp, getProp2, i, NArchive::kClassID, prop) != S_OK) - continue; - if (prop.vt != VT_BSTR) - continue; - item.ClassID = *(const GUID *)prop.bstrVal; - prop.Clear(); + { + NCOM::CPropVariant prop; + if (GetProp(getProp, getProp2, i, NArchive::NHandlerPropID::kClassID, prop) != S_OK) + continue; + if (prop.vt != VT_BSTR) + continue; + if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID)) + return E_FAIL; + item.ClassID = *(const GUID *)prop.bstrVal; + prop.Clear(); + } UString ext, addExt; - RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kExtension, ext)); - RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kAddExtension, addExt)); + RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kExtension, ext)); + RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kAddExtension, addExt)); item.AddExts(ext, addExt); - ReadBoolProp(getProp, getProp2, i, NArchive::kUpdate, item.UpdateEnabled); - if (item.UpdateEnabled) - ReadBoolProp(getProp, getProp2, i, NArchive::kKeepName, item.KeepName); - - if (ReadProp(getProp, getProp2, i, NArchive::kStartSignature, prop) == S_OK) - if (prop.vt == VT_BSTR) + GetProp_Bool(getProp, getProp2, i, NArchive::NHandlerPropID::kUpdate, item.UpdateEnabled); + bool flags_Defined = false; + RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kFlags, item.Flags, flags_Defined)); + item.NewInterface = flags_Defined; + if (!flags_Defined) // && item.UpdateEnabled + { + // support for DLL version before 9.31: + for (unsigned j = 0; j < ARRAY_SIZE(kArcFlagsPars); j += 2) { - UINT len = ::SysStringByteLen(prop.bstrVal); - item.StartSignature.SetCapacity(len); - memmove((Byte *)item.StartSignature, prop.bstrVal, len); + bool val = false; + GetProp_Bool(getProp, getProp2, i, kArcFlagsPars[j], val); + if (val) + item.Flags |= kArcFlagsPars[j + 1]; } + } + + CByteBuffer sig; + RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kSignature, sig)); + if (sig.Size() != 0) + item.Signatures.Add(sig); + else + { + RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kMultiSignature, sig)); + ParseSignatures(sig, (unsigned)sig.Size(), item.Signatures); + } + + bool signatureOffset_Defined; + RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kSignatureOffset, item.SignatureOffset, signatureOffset_Defined)); + + // bool version_Defined; + // RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kVersion, item.Version, version_Defined)); + + if (getIsArc) + getIsArc(i, &item.IsArcFunc); + Formats.Add(item); } return S_OK; @@ -317,25 +422,26 @@ HRESULT CCodecs::LoadFormats() void CCodecIcons::LoadIcons(HMODULE m) { #ifdef _WIN32 - UString iconTypes = MyLoadStringW(m, kIconTypesResId); + UString iconTypes; + MyLoadString(m, kIconTypesResId, iconTypes); UStringVector pairs; SplitString(iconTypes, pairs); - for (int i = 0; i < pairs.Size(); i++) + FOR_VECTOR (i, pairs) { const UString &s = pairs[i]; int pos = s.Find(L':'); CIconPair iconPair; iconPair.IconIndex = -1; if (pos < 0) - pos = s.Length(); + pos = s.Len(); else { - UString num = s.Mid(pos + 1); + UString num = s.Ptr(pos + 1); if (!num.IsEmpty()) { const wchar_t *end; - iconPair.IconIndex = (UInt32)ConvertStringToUInt64(num, &end); - if (*end != L'\0') + iconPair.IconIndex = ConvertStringToUInt32(num, &end); + if (*end != 0) continue; } } @@ -349,10 +455,10 @@ bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const { #ifdef _WIN32 iconIndex = -1; - for (int i = 0; i < IconPairs.Size(); i++) + FOR_VECTOR (i, IconPairs) { const CIconPair &pair = IconPairs[i]; - if (ext.CompareNoCase(pair.Ext) == 0) + if (ext.IsEqualToNoCase(pair.Ext)) { iconIndex = pair.IconIndex; return true; @@ -361,7 +467,8 @@ bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const #endif // #ifdef _WIN32 return false; } -#endif + +#endif // EXTERNAL_CODECS #ifdef _7ZIP_LARGE_PAGES extern "C" @@ -370,7 +477,7 @@ extern "C" } #endif -HRESULT CCodecs::LoadDll(const CSysString &dllPath, bool needCheckDll) +HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll) { #ifdef _WIN32 if (needCheckDll) @@ -382,9 +489,7 @@ HRESULT CCodecs::LoadDll(const CSysString &dllPath, bool needCheckDll) #endif Libs.Add(CCodecLib()); CCodecLib &lib = Libs.Back(); - #ifdef NEW_FOLDER_INTERFACE lib.Path = dllPath; - #endif bool used = false; HRESULT res = S_OK; if (lib.Lib.Load(dllPath)) @@ -396,23 +501,31 @@ HRESULT CCodecs::LoadDll(const CSysString &dllPath, bool needCheckDll) #ifdef _7ZIP_LARGE_PAGES if (g_LargePageSize != 0) { - SetLargePageModeFunc setLargePageMode = (SetLargePageModeFunc)lib.Lib.GetProc("SetLargePageMode"); - if (setLargePageMode != 0) + Func_SetLargePageMode setLargePageMode = (Func_SetLargePageMode)lib.Lib.GetProc("SetLargePageMode"); + if (setLargePageMode) setLargePageMode(); } #endif - lib.CreateObject = (CreateObjectFunc)lib.Lib.GetProc("CreateObject"); - if (lib.CreateObject != 0) + if (CaseSensitiveChange) { - int startSize = Codecs.Size(); + Func_SetCaseSensitive setCaseSensitive = (Func_SetCaseSensitive)lib.Lib.GetProc("SetCaseSensitive"); + if (setCaseSensitive) + setCaseSensitive(CaseSensitive ? 1 : 0); + } + + lib.CreateObject = (Func_CreateObject)lib.Lib.GetProc("CreateObject"); + if (lib.CreateObject) + { + unsigned startSize = Codecs.Size() + Hashers.Size(); res = LoadCodecs(); - used = (Codecs.Size() != startSize); + used = (startSize != Codecs.Size() + Hashers.Size()); if (res == S_OK) { startSize = Formats.Size(); res = LoadFormats(); - used = used || (Formats.Size() != startSize); + if (startSize != Formats.Size()) + used = true; } } } @@ -421,15 +534,10 @@ HRESULT CCodecs::LoadDll(const CSysString &dllPath, bool needCheckDll) return res; } -HRESULT CCodecs::LoadDllsFromFolder(const CSysString &folderPrefix) +HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPrefix) { -#ifdef _UNICODE - NFile::NFind::CEnumeratorW enumerator(folderPrefix + CSysString(TEXT("*"))); - NFile::NFind::CFileInfoW fi; -#else - NFile::NFind::CEnumerator enumerator(folderPrefix + CSysString(TEXT("*"))); + NFile::NFind::CEnumerator enumerator(folderPrefix + FCHAR_ANY_MASK); NFile::NFind::CFileInfo fi; -#endif while (enumerator.Next(fi)) { if (fi.IsDir()) @@ -441,48 +549,65 @@ HRESULT CCodecs::LoadDllsFromFolder(const CSysString &folderPrefix) #endif -#ifndef _SFX -static inline void SetBuffer(CByteBuffer &bb, const Byte *data, int size) -{ - bb.SetCapacity(size); - memmove((Byte *)bb, data, size); -} -#endif - HRESULT CCodecs::Load() { #ifdef NEW_FOLDER_INTERFACE #ifdef _WIN32 - InternalIcons.LoadIcons(g_hInstance); + InternalIcons.LoadIcons(g_hInstance); #endif #endif Formats.Clear(); + #ifdef EXTERNAL_CODECS - Codecs.Clear(); + Codecs.Clear(); + Hashers.Clear(); #endif + for (UInt32 i = 0; i < g_NumArcs; i++) { const CArcInfo &arc = *g_Arcs[i]; CArcInfoEx item; - item.Name = arc.Name; + + item.Name.SetFromAscii(arc.Name); item.CreateInArchive = arc.CreateInArchive; - item.CreateOutArchive = arc.CreateOutArchive; - item.AddExts(arc.Ext, arc.AddExt); - item.UpdateEnabled = (arc.CreateOutArchive != 0); - item.KeepName = arc.KeepName; + item.IsArcFunc = arc.IsArc; + item.Flags = arc.Flags; + + { + UString e, ae; + if (arc.Ext) + e.SetFromAscii(arc.Ext); + if (arc.AddExt) + ae.SetFromAscii(arc.AddExt); + item.AddExts(e, ae); + } #ifndef _SFX - SetBuffer(item.StartSignature, arc.Signature, arc.SignatureSize); + + item.CreateOutArchive = arc.CreateOutArchive; + item.UpdateEnabled = (arc.CreateOutArchive != NULL); + item.SignatureOffset = arc.SignatureOffset; + // item.Version = MY_VER_MIX; + item.NewInterface = true; + + if (arc.IsMultiSignature()) + ParseSignatures(arc.Signature, arc.SignatureSize, item.Signatures); + else + item.Signatures.AddNew().CopyFrom(arc.Signature, arc.SignatureSize); + #endif + Formats.Add(item); } + #ifdef EXTERNAL_CODECS - const CSysString baseFolder = GetBaseFolderPrefixFromRegistry(); - RINOK(LoadDll(baseFolder + kMainDll, false)); - RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName TEXT(STRING_PATH_SEPARATOR))); - RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName TEXT(STRING_PATH_SEPARATOR))); + const FString baseFolder = GetBaseFolderPrefixFromRegistry(); + RINOK(LoadDll(baseFolder + kMainDll, false)); + RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName FSTRING_PATH_SEPARATOR)); + RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName FSTRING_PATH_SEPARATOR)); #endif + return S_OK; } @@ -490,17 +615,22 @@ HRESULT CCodecs::Load() int CCodecs::FindFormatForArchiveName(const UString &arcPath) const { - int slashPos1 = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR); - int slashPos2 = arcPath.ReverseFind(L'.'); + int slashPos = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR); int dotPos = arcPath.ReverseFind(L'.'); - if (dotPos < 0 || dotPos < slashPos1 || dotPos < slashPos2) + if (dotPos < 0 || dotPos < slashPos) + return -1; + const UString ext = arcPath.Ptr(dotPos + 1); + if (ext.IsEmpty()) return -1; - UString ext = arcPath.Mid(dotPos + 1); - for (int i = 0; i < Formats.Size(); i++) + if (ext.IsEqualToNoCase(L"exe")) + return -1; + FOR_VECTOR (i, Formats) { const CArcInfoEx &arc = Formats[i]; + /* if (!arc.UpdateEnabled) continue; + */ if (arc.FindExtension(ext) >= 0) return i; } @@ -511,7 +641,7 @@ int CCodecs::FindFormatForExtension(const UString &ext) const { if (ext.IsEmpty()) return -1; - for (int i = 0; i < Formats.Size(); i++) + FOR_VECTOR (i, Formats) if (Formats[i].FindExtension(ext) >= 0) return i; return -1; @@ -519,8 +649,8 @@ int CCodecs::FindFormatForExtension(const UString &ext) const int CCodecs::FindFormatForArchiveType(const UString &arcType) const { - for (int i = 0; i < Formats.Size(); i++) - if (Formats[i].Name.CompareNoCase(arcType) == 0) + FOR_VECTOR (i, Formats) + if (Formats[i].Name.IsEqualToNoCase(arcType)) return i; return -1; } @@ -528,12 +658,14 @@ int CCodecs::FindFormatForArchiveType(const UString &arcType) const bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const { formatIndices.Clear(); - for (int pos = 0; pos < arcType.Length();) + for (unsigned pos = 0; pos < arcType.Len();) { int pos2 = arcType.Find('.', pos); if (pos2 < 0) - pos2 = arcType.Length(); + pos2 = arcType.Len(); const UString name = arcType.Mid(pos, pos2 - pos); + if (name.IsEmpty()) + return false; int index = FindFormatForArchiveType(name); if (index < 0 && name != L"*") { @@ -546,24 +678,39 @@ bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &forma return true; } -#endif +#endif // _SFX + #ifdef EXTERNAL_CODECS +// #define EXPORT_CODECS + #ifdef EXPORT_CODECS -extern unsigned int g_NumCodecs; + +extern unsigned g_NumCodecs; STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject); STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); -// STDAPI GetNumberOfMethods(UInt32 *numCodecs); -#endif +#define NUM_EXPORT_CODECS g_NumCodecs + +extern unsigned g_NumHashers; +STDAPI CreateHasher(UInt32 index, IHasher **hasher); +STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); +#define NUM_EXPORT_HASHERS g_NumHashers + +#else // EXPORT_CODECS + +#define NUM_EXPORT_CODECS 0 +#define NUM_EXPORT_HASHERS 0 + +#endif // EXPORT_CODECS STDMETHODIMP CCodecs::GetNumberOfMethods(UInt32 *numMethods) { - *numMethods = - #ifdef EXPORT_CODECS - g_NumCodecs + - #endif - Codecs.Size(); + *numMethods = NUM_EXPORT_CODECS + #ifdef EXTERNAL_CODECS + + Codecs.Size() + #endif + ; return S_OK; } @@ -574,27 +721,23 @@ STDMETHODIMP CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *valu return GetMethodProperty(index, propID, value); #endif - const CDllCodecInfo &ci = Codecs[index - #ifdef EXPORT_CODECS - - g_NumCodecs - #endif - ]; + #ifdef EXTERNAL_CODECS + const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; - if (propID == NMethodPropID::kDecoderIsAssigned) - { - NWindows::NCOM::CPropVariant propVariant; - propVariant = ci.DecoderIsAssigned; - propVariant.Detach(value); - return S_OK; - } - if (propID == NMethodPropID::kEncoderIsAssigned) + if (propID == NMethodPropID::kDecoderIsAssigned || + propID == NMethodPropID::kEncoderIsAssigned) { - NWindows::NCOM::CPropVariant propVariant; - propVariant = ci.EncoderIsAssigned; - propVariant.Detach(value); + NCOM::CPropVariant prop; + prop = (propID == NMethodPropID::kDecoderIsAssigned) ? + ci.DecoderIsAssigned : + ci.EncoderIsAssigned; + prop.Detach(value); return S_OK; } return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value); + #else + return E_FAIL; + #endif } STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder) @@ -603,14 +746,14 @@ STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder) if (index < g_NumCodecs) return CreateCoder2(false, index, iid, coder); #endif - const CDllCodecInfo &ci = Codecs[index - #ifdef EXPORT_CODECS - - g_NumCodecs - #endif - ]; + #ifdef EXTERNAL_CODECS + const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; if (ci.DecoderIsAssigned) return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder); return S_OK; + #else + return E_FAIL; + #endif } STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder) @@ -619,35 +762,53 @@ STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder) if (index < g_NumCodecs) return CreateCoder2(true, index, iid, coder); #endif - const CDllCodecInfo &ci = Codecs[index - #ifdef EXPORT_CODECS - - g_NumCodecs - #endif - ]; + #ifdef EXTERNAL_CODECS + const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; if (ci.EncoderIsAssigned) return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder); return S_OK; + #else + return E_FAIL; + #endif } -HRESULT CCodecs::CreateCoder(const UString &name, bool encode, CMyComPtr &coder) const + +STDMETHODIMP_(UInt32) CCodecs::GetNumHashers() { - for (int i = 0; i < Codecs.Size(); i++) - { - const CDllCodecInfo &codec = Codecs[i]; - if (encode && !codec.EncoderIsAssigned || !encode && !codec.DecoderIsAssigned) - continue; - const CCodecLib &lib = Libs[codec.LibIndex]; - UString res; - NWindows::NCOM::CPropVariant prop; - RINOK(lib.GetMethodProperty(codec.CodecIndex, NMethodPropID::kName, &prop)); - if (prop.vt == VT_BSTR) - res = prop.bstrVal; - else if (prop.vt != VT_EMPTY) - continue; - if (name.CompareNoCase(res) == 0) - return lib.CreateObject(encode ? &codec.Encoder : &codec.Decoder, &IID_ICompressCoder, (void **)&coder); - } - return CLASS_E_CLASSNOTAVAILABLE; + return NUM_EXPORT_HASHERS + #ifdef EXTERNAL_CODECS + + Hashers.Size() + #endif + ; +} + +STDMETHODIMP CCodecs::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + #ifdef EXPORT_CODECS + if (index < g_NumHashers) + return ::GetHasherProp(index, propID, value); + #endif + + #ifdef EXTERNAL_CODECS + const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; + return Libs[ci.LibIndex].Hashers->GetHasherProp(ci.HasherIndex, propID, value); + #else + return E_FAIL; + #endif +} + +STDMETHODIMP CCodecs::CreateHasher(UInt32 index, IHasher **hasher) +{ + #ifdef EXPORT_CODECS + if (index < g_NumHashers) + return CreateHasher(index, hasher); + #endif + #ifdef EXTERNAL_CODECS + const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; + return Libs[ci.LibIndex].Hashers->CreateHasher(ci.HasherIndex, hasher); + #else + return E_FAIL; + #endif } int CCodecs::GetCodecLibIndex(UInt32 index) @@ -657,11 +818,21 @@ int CCodecs::GetCodecLibIndex(UInt32 index) return -1; #endif #ifdef EXTERNAL_CODECS - const CDllCodecInfo &ci = Codecs[index - #ifdef EXPORT_CODECS - - g_NumCodecs - #endif - ]; + const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; + return ci.LibIndex; + #else + return -1; + #endif +} + +int CCodecs::GetHasherLibIndex(UInt32 index) +{ + #ifdef EXPORT_CODECS + if (index < g_NumHashers) + return -1; + #endif + #ifdef EXTERNAL_CODECS + const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; return ci.LibIndex; #else return -1; @@ -673,7 +844,7 @@ bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index) #ifdef EXPORT_CODECS if (index < g_NumCodecs) { - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK) if (prop.vt != VT_EMPTY) return true; @@ -681,11 +852,7 @@ bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index) } #endif #ifdef EXTERNAL_CODECS - const CDllCodecInfo &ci = Codecs[index - #ifdef EXPORT_CODECS - - g_NumCodecs - #endif - ]; + const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; return ci.EncoderIsAssigned; #else return false; @@ -694,8 +861,7 @@ bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index) HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id) { - UString s; - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; RINOK(GetProperty(index, NMethodPropID::kID, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; @@ -706,11 +872,39 @@ HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id) UString CCodecs::GetCodecName(UInt32 index) { UString s; - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK) if (prop.vt == VT_BSTR) s = prop.bstrVal; return s; } -#endif +UInt64 CCodecs::GetHasherId(UInt32 index) +{ + NCOM::CPropVariant prop; + RINOK(GetHasherProp(index, NMethodPropID::kID, &prop)); + if (prop.vt != VT_UI8) + return 0; + return prop.uhVal.QuadPart; +} + +UString CCodecs::GetHasherName(UInt32 index) +{ + UString s; + NCOM::CPropVariant prop; + if (GetHasherProp(index, NMethodPropID::kName, &prop) == S_OK) + if (prop.vt == VT_BSTR) + s = prop.bstrVal; + return s; +} + +UInt32 CCodecs::GetHasherDigestSize(UInt32 index) +{ + NCOM::CPropVariant prop; + RINOK(GetHasherProp(index, NMethodPropID::kDigestSize, &prop)); + if (prop.vt != VT_UI4) + return 0; + return prop.ulVal; +} + +#endif // EXTERNAL_CODECS diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.h index a633dd2e1..d254ae659 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.h +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.h @@ -1,12 +1,13 @@ // LoadCodecs.h -#ifndef __LOADCODECS_H -#define __LOADCODECS_H +#ifndef __LOAD_CODECS_H +#define __LOAD_CODECS_H -#include "../../../Common/Types.h" +#include "../../../Common/MyBuffer.h" #include "../../../Common/MyCom.h" #include "../../../Common/MyString.h" -#include "../../../Common/Buffer.h" +#include "../../../Common/ComTry.h" + #include "../../ICoder.h" #ifdef EXTERNAL_CODECS @@ -23,15 +24,19 @@ struct CDllCodecInfo UInt32 CodecIndex; }; -#include "../../Archive/IArchive.h" +struct CDllHasherInfo +{ + int LibIndex; + UInt32 HasherIndex; +}; -typedef IInArchive * (*CreateInArchiveP)(); -typedef IOutArchive * (*CreateOutArchiveP)(); +#include "../../Archive/IArchive.h" struct CArcExtInfo { UString Ext; UString AddExt; + CArcExtInfo() {} CArcExtInfo(const UString &ext): Ext(ext) {} CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {} @@ -40,37 +45,55 @@ struct CArcExtInfo struct CArcInfoEx { - #ifdef EXTERNAL_CODECS - int LibIndex; - UInt32 FormatIndex; - CLSID ClassID; - #endif - bool UpdateEnabled; - CreateInArchiveP CreateInArchive; - CreateOutArchiveP CreateOutArchive; + UInt32 Flags; + + Func_CreateInArchive CreateInArchive; + Func_IsArc IsArcFunc; + UString Name; CObjectVector Exts; + #ifndef _SFX - CByteBuffer StartSignature; - // CByteBuffer FinishSignature; - #ifdef NEW_FOLDER_INTERFACE - UStringVector AssociateExts; + Func_CreateOutArchive CreateOutArchive; + bool UpdateEnabled; + bool NewInterface; + // UInt32 Version; + UInt32 SignatureOffset; + CObjectVector Signatures; + #ifdef NEW_FOLDER_INTERFACE + UStringVector AssociateExts; + #endif #endif + + #ifdef EXTERNAL_CODECS + int LibIndex; + UInt32 FormatIndex; + CLSID ClassID; #endif - bool KeepName; + + bool Flags_KeepName() const { return (Flags & NArcInfoFlags::kKeepName) != 0; } + bool Flags_FindSignature() const { return (Flags & NArcInfoFlags::kFindSignature) != 0; } + + bool Flags_AltStreams() const { return (Flags & NArcInfoFlags::kAltStreams) != 0; } + bool Flags_NtSecure() const { return (Flags & NArcInfoFlags::kNtSecure) != 0; } + bool Flags_SymLinks() const { return (Flags & NArcInfoFlags::kSymLinks) != 0; } + bool Flags_HardLinks() const { return (Flags & NArcInfoFlags::kHardLinks) != 0; } + + bool Flags_UseGlobalOffset() const { return (Flags & NArcInfoFlags::kUseGlobalOffset) != 0; } + bool Flags_StartOpen() const { return (Flags & NArcInfoFlags::kStartOpen) != 0; } + bool Flags_BackwardOpen() const { return (Flags & NArcInfoFlags::kBackwardOpen) != 0; } + bool Flags_PreArc() const { return (Flags & NArcInfoFlags::kPreArc) != 0; } + bool Flags_PureStartOpen() const { return (Flags & NArcInfoFlags::kPureStartOpen) != 0; } + UString GetMainExt() const { if (Exts.IsEmpty()) return UString(); return Exts[0].Ext; } - int FindExtension(const UString &ext) const - { - for (int i = 0; i < Exts.Size(); i++) - if (ext.CompareNoCase(Exts[i].Ext) == 0) - return i; - return -1; - } + int FindExtension(const UString &ext) const; + + /* UString GetAllExtensions() const { UString s; @@ -82,25 +105,31 @@ struct CArcInfoEx } return s; } + */ + + void AddExts(const UString &ext, const UString &addExt); - void AddExts(const wchar_t* ext, const wchar_t* addExt); + bool IsSplit() const { return StringsAreEqualNoCase_Ascii(Name, "Split"); } + // bool IsRar() const { return StringsAreEqualNoCase_Ascii(Name, "Rar"); } CArcInfoEx(): - #ifdef EXTERNAL_CODECS - LibIndex(-1), - #endif - UpdateEnabled(false), - CreateInArchive(0), CreateOutArchive(0), - KeepName(false) - #ifndef _SFX - #endif + Flags(0), + CreateInArchive(NULL), + IsArcFunc(NULL) + #ifndef _SFX + , CreateOutArchive(NULL) + , UpdateEnabled(false) + , NewInterface(false) + // , Version(0) + , SignatureOffset(0) + #endif + #ifdef EXTERNAL_CODECS + , LibIndex(-1) + #endif {} }; #ifdef EXTERNAL_CODECS -typedef UInt32 (WINAPI *GetMethodPropertyFunc)(UInt32 index, PROPID propID, PROPVARIANT *value); -typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *interfaceID, void **outObject); - #ifdef NEW_FOLDER_INTERFACE struct CCodecIcons @@ -117,24 +146,28 @@ struct CCodecIcons #endif struct CCodecLib -#ifdef NEW_FOLDER_INTERFACE -: public CCodecIcons -#endif + #ifdef NEW_FOLDER_INTERFACE + : public CCodecIcons + #endif { NWindows::NDLL::CLibrary Lib; - GetMethodPropertyFunc GetMethodProperty; - CreateObjectFunc CreateObject; + FString Path; + Func_GetMethodProperty GetMethodProperty; + Func_CreateObject CreateObject; + CMyComPtr Hashers; + #ifdef NEW_FOLDER_INTERFACE - CSysString Path; void LoadIcons() { CCodecIcons::LoadIcons((HMODULE)Lib); } #endif - CCodecLib(): GetMethodProperty(0) {} + + CCodecLib(): GetMethodProperty(NULL) {} }; #endif class CCodecs: #ifdef EXTERNAL_CODECS public ICompressCodecsInfo, + public IHashers, #else public IUnknown, #endif @@ -143,7 +176,8 @@ class CCodecs: public: #ifdef EXTERNAL_CODECS CObjectVector Libs; - CObjectVector Codecs; + CRecordVector Codecs; + CRecordVector Hashers; #ifdef NEW_FOLDER_INTERFACE CCodecIcons InternalIcons; @@ -151,8 +185,8 @@ public: HRESULT LoadCodecs(); HRESULT LoadFormats(); - HRESULT LoadDll(const CSysString &path, bool needCheckDll); - HRESULT LoadDllsFromFolder(const CSysString &folderPrefix); + HRESULT LoadDll(const FString &path, bool needCheckDll); + HRESULT LoadDllsFromFolder(const FString &folderPrefix); HRESULT CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const { @@ -162,8 +196,18 @@ public: public: CObjectVector Formats; + bool CaseSensitiveChange; + bool CaseSensitive; + + CCodecs(): CaseSensitiveChange(false), CaseSensitive(false) {} + + const wchar_t *GetFormatNamePtr(int formatIndex) + { + return formatIndex < 0 ? L"#" : (const wchar_t *)Formats[formatIndex].Name; + } + HRESULT Load(); - + #ifndef _SFX int FindFormatForArchiveName(const UString &arcPath) const; int FindFormatForExtension(const UString &ext) const; @@ -171,65 +215,89 @@ public: bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const; #endif - MY_UNKNOWN_IMP - #ifdef EXTERNAL_CODECS + + MY_UNKNOWN_IMP2(ICompressCodecsInfo, IHashers) + STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(CreateDecoder)(UInt32 index, const GUID *interfaceID, void **coder); STDMETHOD(CreateEncoder)(UInt32 index, const GUID *interfaceID, void **coder); - #endif + + STDMETHOD_(UInt32, GetNumHashers)(); + STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value); + STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher); + + #else + + MY_UNKNOWN_IMP + + #endif // EXTERNAL_CODECS + + #ifdef EXTERNAL_CODECS int GetCodecLibIndex(UInt32 index); bool GetCodecEncoderIsAssigned(UInt32 index); HRESULT GetCodecId(UInt32 index, UInt64 &id); UString GetCodecName(UInt32 index); - HRESULT CreateInArchive(int formatIndex, CMyComPtr &archive) const + int GetHasherLibIndex(UInt32 index); + UInt64 GetHasherId(UInt32 index); + UString GetHasherName(UInt32 index); + UInt32 GetHasherDigestSize(UInt32 index); + + #endif + + HRESULT CreateInArchive(unsigned formatIndex, CMyComPtr &archive) const { const CArcInfoEx &ai = Formats[formatIndex]; #ifdef EXTERNAL_CODECS if (ai.LibIndex < 0) #endif { + COM_TRY_BEGIN archive = ai.CreateInArchive(); return S_OK; + COM_TRY_END } #ifdef EXTERNAL_CODECS return CreateArchiveHandler(ai, (void **)&archive, false); #endif } - HRESULT CreateOutArchive(int formatIndex, CMyComPtr &archive) const + + #ifndef _SFX + + HRESULT CreateOutArchive(unsigned formatIndex, CMyComPtr &archive) const { const CArcInfoEx &ai = Formats[formatIndex]; #ifdef EXTERNAL_CODECS if (ai.LibIndex < 0) #endif { + COM_TRY_BEGIN archive = ai.CreateOutArchive(); return S_OK; + COM_TRY_END } #ifdef EXTERNAL_CODECS return CreateArchiveHandler(ai, (void **)&archive, true); #endif } + int FindOutFormatFromName(const UString &name) const { - for (int i = 0; i < Formats.Size(); i++) + FOR_VECTOR (i, Formats) { const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; - if (arc.Name.CompareNoCase(name) == 0) + if (arc.Name.IsEqualToNoCase(name)) return i; } return -1; } - #ifdef EXTERNAL_CODECS - HRESULT CreateCoder(const UString &name, bool encode, CMyComPtr &coder) const; - #endif - + #endif // _SFX }; #endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.cpp index 5e67915bb..7c53bd99f 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.cpp +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.cpp @@ -2,27 +2,487 @@ #include "StdAfx.h" -#include "Common/Wildcard.h" +// #define SHOW_DEBUG_INFO -#include "Windows/FileDir.h" -#include "Windows/PropVariant.h" +#ifdef SHOW_DEBUG_INFO +#include +#endif + +#include "../../../../C/CpuArch.h" + +#include "../../../Common/ComTry.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/StringToInt.h" +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/FileDir.h" #include "../../Common/FileStreams.h" +#include "../../Common/LimitedStreams.h" +#include "../../Common/ProgressUtils.h" #include "../../Common/StreamUtils.h" +#include "../../Compress/CopyCoder.h" + #include "DefaultName.h" #include "OpenArchive.h" +#ifndef _SFX +#include "SetProperties.h" +#endif + +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + +// increase it, if you need to support larger SFX stubs +static const UInt64 kMaxCheckStartPosition = 1 << 22; + +/* +Open: + - formatIndex >= 0 (exact Format) + 1) Open with main type. Archive handler is allowed to use archive start finder. + Warning, if there is tail. + + - formatIndex = -1 (Parser:0) (default) + - same as #1 but doesn't return Parser + + - formatIndex = -2 (#1) + - file has supported extension (like a.7z) + Open with that main type (only starting from start of file). + - open OK: + - if there is no tail - return OK + - if there is tail: + - archive is not "Self Exe" - return OK with Warning, that there is tail + - archive is "Self Exe" + ignore "Self Exe" stub, and tries to open tail + - tail can be open as archive - shows that archive and stub size property. + - tail can't be open as archive - shows Parser ??? + - open FAIL: + Try to open with all other types from offset 0 only. + If some open type is OK and physical archive size is uequal or larger + than file size, then return that archive with warning that can not be open as [extension type]. + If extension was EXE, it will try to open as unknown_extension case + - file has unknown extension (like a.hhh) + It tries to open via parser code. + - if there is full archive or tail archive and unknown block or "Self Exe" + at front, it shows tail archive and stub size property. + - in another cases, if there is some archive inside file, it returns parser/ + - in another cases, it retuens S_FALSE + + + - formatIndex = -3 (#2) + - same as #1, but + - stub (EXE) + archive is open in Parser + + - formatIndex = -4 (#3) + - returns only Parser. skip full file archive. And show other sub-archives + + - formatIndex = -5 (#4) + - returns only Parser. skip full file archive. And show other sub-archives for each byte pos + +*/ + + + + using namespace NWindows; -// Static-SFX (for Linux) can be big. -const UInt64 kMaxCheckStartPosition = 1 << 22; +/* +#ifdef _SFX +#define OPEN_PROPS_PARAM +#else +#define OPEN_PROPS_PARAM , props +#endif +*/ + +/* +CArc::~CArc() +{ + GetRawProps.Release(); + Archive.Release(); + printf("\nCArc::~CArc()\n"); +} +*/ + +#ifndef _SFX + +namespace NArchive { +namespace NParser { + +struct CParseItem +{ + UInt64 Offset; + UInt64 Size; + // UInt64 OkSize; + UString Name; + UString Extension; + FILETIME FileTime; + UString Comment; + UString ArcType; + + bool FileTime_Defined; + bool UnpackSize_Defined; + bool NumSubDirs_Defined; + bool NumSubFiles_Defined; + + bool IsSelfExe; + bool IsNotArcType; + + UInt64 UnpackSize; + UInt64 NumSubDirs; + UInt64 NumSubFiles; + + int FormatIndex; + + bool LenIsUnknown; + + CParseItem(): + LenIsUnknown(false), + FileTime_Defined(false), + UnpackSize_Defined(false), + NumSubFiles_Defined(false), + NumSubDirs_Defined(false), + IsSelfExe(false), + IsNotArcType(false) + // OkSize(0) + {} + + /* + bool IsEqualTo(const CParseItem &item) const + { + return Offset == item.Offset && Size == item.Size; + } + */ + + void NormalizeOffset() + { + if ((Int64)Offset < 0) + { + Size += Offset; + // OkSize += Offset; + Offset = 0; + } + } +}; + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ +public: + CObjectVector _items; + UInt64 _maxEndOffset; + CMyComPtr _stream; + + MY_UNKNOWN_IMP2( + IInArchive, + IInArchiveGetStream) + + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); + + UInt64 GetLastEnd() const + { + if (_items.IsEmpty()) + return 0; + const CParseItem &back = _items.Back(); + return back.Offset + back.Size; + } + + void AddUnknownItem(UInt64 next); + int FindInsertPos(const CParseItem &item); + void AddItem(const CParseItem &item); + // void Init(); + + CHandler() + { + _maxEndOffset = 0; + } +}; + +int CHandler::FindInsertPos(const CParseItem &item) +{ + unsigned left = 0, right = _items.Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + const CParseItem & midItem = _items[mid]; + if (item.Offset < midItem.Offset) + right = mid; + else if (item.Offset > midItem.Offset) + left = mid + 1; + else if (item.Size < midItem.Size) + right = mid; + else if (item.Size > midItem.Size) + left = mid + 1; + else + { + left = mid + 1; + // return -1; + } + } + return left; +} + +void CHandler::AddUnknownItem(UInt64 next) +{ + /* + UInt64 prevEnd = 0; + if (!_items.IsEmpty()) + { + const CParseItem &back = _items.Back(); + prevEnd = back.Offset + back.Size; + } + */ + if (_maxEndOffset < next) + { + CParseItem item2; + item2.Offset = _maxEndOffset; + item2.Size = next - _maxEndOffset; + _maxEndOffset = next; + _items.Add(item2); + } + else if (_maxEndOffset > next && !_items.IsEmpty()) + { + CParseItem &back = _items.Back(); + if (back.LenIsUnknown) + { + back.Size = next - back.Offset; + _maxEndOffset = next; + } + } +} + +void CHandler::AddItem(const CParseItem &item) +{ + AddUnknownItem(item.Offset); + int pos = FindInsertPos(item); + if (pos >= 0) + { + _items.Insert(pos, item); + UInt64 next = item.Offset + item.Size; + if (_maxEndOffset < next) + _maxEndOffset = next; + } +} + +/* +static const STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidType, VT_BSTR}, + { NULL, kpidComment, VT_BSTR}, + { NULL, kpidOffset, VT_UI8}, + { NULL, kpidUnpackSize, VT_UI8}, +// { NULL, kpidNumSubDirs, VT_UI8}, +}; +*/ + +static const Byte kProps[] = +{ + kpidPath, + kpidSize, + kpidMTime, + kpidType, + kpidComment, + kpidOffset, + kpidUnpackSize +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* openArchiveCallback */) +{ + COM_TRY_BEGIN + { + Close(); + _stream = stream; + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _items.Clear(); + _stream.Release(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _items.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NCOM::CPropVariant prop; + + const CParseItem &item = _items[index]; + + switch (propID) + { + case kpidPath: + { + wchar_t sz[32]; + ConvertUInt32ToString(index + 1, sz); + UString s = sz; + if (!item.Name.IsEmpty()) + { + s += L'.'; + s += item.Name; + } + if (!item.Extension.IsEmpty()) + { + s += L'.'; + s += item.Extension; + } + prop = s; break; + } + case kpidSize: + case kpidPackSize: prop = item.Size; break; + case kpidOffset: prop = item.Offset; break; + case kpidUnpackSize: if (item.UnpackSize_Defined) prop = item.UnpackSize; break; + case kpidNumSubFiles: if (item.NumSubFiles_Defined) prop = item.NumSubFiles; break; + case kpidNumSubDirs: if (item.NumSubDirs_Defined) prop = item.NumSubDirs; break; + case kpidMTime: if (item.FileTime_Defined) prop = item.FileTime; break; + case kpidComment: if (!item.Comment.IsEmpty()) prop = item.Comment; break; + case kpidType: if (!item.ArcType.IsEmpty()) prop = item.ArcType; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)(Int32)-1); + if (allFilesMode) + numItems = _items.Size(); + if (_stream && numItems == 0) + return S_OK; + UInt64 totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + totalSize += _items[allFilesMode ? i : indices[i]].Size; + extractCallback->SetTotal(totalSize); + + totalSize = 0; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(streamSpec); + streamSpec->SetStream(_stream); + + CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream; + CMyComPtr outStream(outStreamSpec); -HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + for (i = 0; i < numItems; i++) + { + lps->InSize = totalSize; + lps->OutSize = totalSize; + RINOK(lps->SetCur()); + CMyComPtr realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + const CParseItem &item = _items[index]; + + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + UInt64 unpackSize = item.Size; + totalSize += unpackSize; + bool skipMode = false; + if (!testMode && !realOutStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + + outStreamSpec->SetStream(realOutStream); + realOutStream.Release(); + outStreamSpec->Init(skipMode ? 0 : unpackSize, true); + + Int32 opRes = NExtract::NOperationResult::kOK; + RINOK(_stream->Seek(item.Offset, STREAM_SEEK_SET, NULL)); + streamSpec->Init(unpackSize); + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + + if (outStreamSpec->GetRem() != 0) + opRes = NExtract::NOperationResult::kDataError; + outStreamSpec->ReleaseStream(); + RINOK(extractCallback->SetOperationResult(opRes)); + } + return S_OK; + COM_TRY_END +} + + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + const CParseItem &item = _items[index]; + return CreateLimitedInStream(_stream, item.Offset, item.Size, stream); + COM_TRY_END +} + +}} + +#endif + +HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw() +{ + NCOM::CPropVariant prop; + result = false; + RINOK(arc->GetProperty(index, propID, &prop)); + if (prop.vt == VT_BOOL) + result = VARIANT_BOOLToBool(prop.boolVal); + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; +} + +HRESULT Archive_IsItem_Folder(IInArchive *arc, UInt32 index, bool &result) throw() +{ + return Archive_GetItemBoolProp(arc, index, kpidIsDir, result); +} + +HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw() +{ + return Archive_GetItemBoolProp(arc, index, kpidIsAux, result); +} + +HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw() +{ + return Archive_GetItemBoolProp(arc, index, kpidIsAltStream, result); +} + +HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &result) throw() +{ + return Archive_GetItemBoolProp(arc, index, kpidIsDeleted, result); +} + +static HRESULT Archive_GetArcBoolProp(IInArchive *arc, PROPID propid, bool &result) { NCOM::CPropVariant prop; result = false; - RINOK(archive->GetProperty(index, propID, &prop)); + RINOK(arc->GetArchiveProperty(propid, &prop)); if (prop.vt == VT_BOOL) result = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt != VT_EMPTY) @@ -30,13 +490,179 @@ HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, return S_OK; } -HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) +static HRESULT Archive_GetArcProp_UInt(IInArchive *arc, PROPID propid, UInt64 &result, bool &defined) +{ + defined = false; + NCOM::CPropVariant prop; + RINOK(arc->GetArchiveProperty(propid, &prop)); + switch (prop.vt) + { + case VT_UI4: result = prop.ulVal; defined = true; break; + case VT_I4: result = prop.lVal; defined = true; break; + case VT_UI8: result = (UInt64)prop.uhVal.QuadPart; defined = true; break; + case VT_I8: result = (UInt64)prop.hVal.QuadPart; defined = true; break; + case VT_EMPTY: break; + default: return E_FAIL; + } + return S_OK; +} + +static HRESULT Archive_GetArcProp_Int(IInArchive *arc, PROPID propid, Int64 &result, bool &defined) { - return GetArchiveItemBoolProp(archive, index, kpidIsDir, result); + defined = false; + NCOM::CPropVariant prop; + RINOK(arc->GetArchiveProperty(propid, &prop)); + switch (prop.vt) + { + case VT_UI4: result = prop.ulVal; defined = true; break; + case VT_I4: result = prop.lVal; defined = true; break; + case VT_UI8: result = (Int64)prop.uhVal.QuadPart; defined = true; break; + case VT_I8: result = (Int64)prop.hVal.QuadPart; defined = true; break; + case VT_EMPTY: break; + default: return E_FAIL; + } + return S_OK; +} + +HRESULT CArc::GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const +{ + if (!GetRawProps) + return E_FAIL; + UInt32 curIndex = index; + bool prevWasAltStream = false; + for (;;) + { + UString s; + + #ifdef MY_CPU_LE + const void *p; + UInt32 size; + UInt32 propType; + RINOK(GetRawProps->GetRawProp(curIndex, kpidName, &p, &size, &propType)); + if (p && propType == PROP_DATA_TYPE_wchar_t_PTR_Z_LE) + s = (const wchar_t *)p; + else + #endif + { + NCOM::CPropVariant prop; + RINOK(Archive->GetProperty(curIndex, kpidName, &prop)); + if (prop.vt == VT_BSTR) + s = prop.bstrVal; + else if (prop.vt == VT_EMPTY) + s = L"[Content]"; + else + return E_FAIL; + } + + if (prevWasAltStream) + parts[0] = s + L":" + parts[0]; + else + parts.Insert(0, s); + + UInt32 curParent = (UInt32)(Int32)-1; + UInt32 parentType = 0; + RINOK(GetRawProps->GetParent(curIndex, &curParent, &parentType)); + if (parent == curParent) + return S_OK; + if (curParent == (UInt32)(Int32)-1) + return E_FAIL; + prevWasAltStream = (parentType == NParentType::kAltStream); + curIndex = curParent; + } } HRESULT CArc::GetItemPath(UInt32 index, UString &result) const { + #ifdef MY_CPU_LE + if (GetRawProps) + { + const void *p; + UInt32 size; + UInt32 propType; + if (!IsTree) + { + if (GetRawProps->GetRawProp(index, kpidPath, &p, &size, &propType) == S_OK && + propType == NPropDataType::kUtf16z) + { + unsigned len = size / 2 - 1; + wchar_t *s = result.GetBuffer(len); + for (unsigned i = 0; i < len; i++) + { + wchar_t c = GetUi16(p); + p = (const void *)((const Byte *)p + 2); + #if WCHAR_PATH_SEPARATOR != L'/' + if (c == L'/') + c = WCHAR_PATH_SEPARATOR; + #endif + *s++ = c; + } + result.ReleaseBuffer(len); + if (len != 0) + return S_OK; + } + } + /* + else if (GetRawProps->GetRawProp(index, kpidName, &p, &size, &propType) == S_OK && + p && propType == NPropDataType::kUtf16z) + { + UInt32 totalSize = size; + bool isOK = false; + { + UInt32 index2 = index; + for (;;) + { + UInt32 parent = (UInt32)(Int32)-1; + UInt32 parentType = 0; + if (GetRawProps->GetParent(index2, &parent, &parentType) != S_OK) + break; + if (parent == (UInt32)(Int32)-1) + { + isOK = true; + break; + } + index2 = parent; + UInt32 size2; + const void *p2; + if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK) + break; + totalSize += size2; + } + } + + if (isOK) + { + wchar_t *sz = result.GetBuffer(totalSize / 2); + UInt32 pos = totalSize - size; + memcpy((Byte *)sz + pos, p, size - 2); + UInt32 index2 = index; + for (;;) + { + UInt32 parent = (UInt32)(Int32)-1; + UInt32 parentType = 0; + if (GetRawProps->GetParent(index2, &parent, &parentType) != S_OK) + break; + if (parent == (UInt32)(Int32)-1) + break; + index2 = parent; + UInt32 size2; + const void *p2; + if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK) + break; + pos -= size2; + memcpy((Byte *)sz + pos, p2, size2); + sz[(pos + size2 - 2) / 2] = (parentType == 0) ? WCHAR_PATH_SEPARATOR : L':'; + } + result.ReleaseBuffer((totalSize - 2) / 2); + #ifdef _WIN32 + // result.Replace(L'/', WCHAR_PATH_SEPARATOR); + #endif + return S_OK; + } + } + */ + } + #endif + { NCOM::CPropVariant prop; RINOK(Archive->GetProperty(index, kpidPath, &prop)); @@ -47,6 +673,7 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const else return E_FAIL; } + if (result.IsEmpty()) { result = DefaultName; @@ -63,6 +690,61 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const return S_OK; } +HRESULT CArc::GetItemPath2(UInt32 index, UString &result) const +{ + RINOK(GetItemPath(index, result)); + if (Ask_Deleted) + { + bool isDeleted = false; + RINOK(Archive_IsItem_Deleted(Archive, index, isDeleted)); + if (isDeleted) + result.Insert(0, L"[DELETED]" WSTRING_PATH_SEPARATOR); + } + return S_OK; +} + +#ifndef _SFX + +static HRESULT Archive_GetItem_Size(IInArchive *archive, UInt32 index, UInt64 &size, bool &defined) +{ + NCOM::CPropVariant prop; + defined = false; + size = 0; + RINOK(archive->GetProperty(index, kpidSize, &prop)); + switch (prop.vt) + { + case VT_UI1: size = prop.bVal; break; + case VT_UI2: size = prop.uiVal; break; + case VT_UI4: size = prop.ulVal; break; + case VT_UI8: size = (UInt64)prop.uhVal.QuadPart; break; + case VT_EMPTY: return S_OK; + default: return E_FAIL; + } + defined = true; + return S_OK; +} + +#endif + +HRESULT CArc::GetItemSize(UInt32 index, UInt64 &size, bool &defined) const +{ + NCOM::CPropVariant prop; + defined = false; + size = 0; + RINOK(Archive->GetProperty(index, kpidSize, &prop)); + switch (prop.vt) + { + case VT_UI1: size = prop.bVal; break; + case VT_UI2: size = prop.uiVal; break; + case VT_UI4: size = prop.ulVal; break; + case VT_UI8: size = (UInt64)prop.uhVal.QuadPart; break; + case VT_EMPTY: return S_OK; + default: return E_FAIL; + } + defined = true; + return S_OK; +} + HRESULT CArc::GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const { NCOM::CPropVariant prop; @@ -85,6 +767,7 @@ HRESULT CArc::GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const } #ifndef _SFX + static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size) { for (size_t i = 0; i < size; i++) @@ -92,327 +775,2107 @@ static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size) return false; return true; } -#endif -#ifdef UNDER_CE -static const int kNumHashBytes = 1; -#define HASH_VAL(buf, pos) ((buf)[pos]) -#else -static const int kNumHashBytes = 2; -#define HASH_VAL(buf, pos) ((buf)[pos] | ((UInt32)(buf)[pos + 1] << 8)) -#endif +static void MakeCheckOrder(CCodecs *codecs, + CIntVector &orderIndices, unsigned numTypes, CIntVector &orderIndices2, + const Byte *data, size_t dataSize) +{ + for (unsigned i = 0; i < numTypes; i++) + { + int index = orderIndices[i]; + if (index < 0) + continue; + const CArcInfoEx &ai = codecs->Formats[index]; + if (ai.SignatureOffset != 0) + { + orderIndices2.Add(index); + orderIndices[i] = -1; + continue; + } + + const CObjectVector &sigs = ai.Signatures; + FOR_VECTOR (k, sigs) + { + const CByteBuffer &sig = sigs[k]; + if (sig.Size() == 0 && dataSize == 0 || + sig.Size() != 0 && sig.Size() <= dataSize && + TestSignature(data, sig, sig.Size())) + { + orderIndices2.Add(index); + orderIndices[i] = -1; + break; + } + } + } +} + +#endif + +#ifdef UNDER_CE + static const unsigned kNumHashBytes = 1; + #define HASH_VAL(buf, pos) ((buf)[pos]) +#else + static const unsigned kNumHashBytes = 2; + #define HASH_VAL(buf, pos) ((buf)[pos] | ((UInt32)(buf)[pos + 1] << 8)) +#endif + + +#ifndef _SFX + +static bool IsExeExt(const UString &ext) +{ + return ext.IsEqualToNoCase(L"exe"); +} + +static const char *k_PreArcFormats[] = +{ + "pe" + , "elf" + , "macho" + , "mub" + , "te" +}; + +static bool IsNameFromList(const UString &s, const char *names[], size_t num) +{ + for (unsigned i = 0; i < num; i++) + if (StringsAreEqualNoCase_Ascii(s, names[i])) + return true; + return false; +} + + +static bool IsPreArcFormat(const CArcInfoEx &ai) +{ + if (ai.Flags_PreArc()) + return true; + return IsNameFromList(ai.Name, k_PreArcFormats, ARRAY_SIZE(k_PreArcFormats)); +} + +static const char *k_Formats_with_simple_signuature[] = +{ + "7z" + , "xz" + , "rar" + , "bzip2" + , "gzip" + , "cab" + , "wim" + , "rpm" + , "vhd" + , "xar" +}; + +static bool IsNewStyleSignature(const CArcInfoEx &ai) +{ + // if (ai.Version >= 0x91F) + if (ai.NewInterface) + return true; + return IsNameFromList(ai.Name, k_Formats_with_simple_signuature, ARRAY_SIZE(k_Formats_with_simple_signuature)); +} + +class CArchiveOpenCallback_Offset: + public IArchiveOpenCallback, + #ifndef _NO_CRYPTO + public ICryptoGetTextPassword, + #endif + public CMyUnknownImp +{ +public: + CMyComPtr Callback; + UInt64 Files; + UInt64 Offset; + + #ifndef _NO_CRYPTO + CMyComPtr GetTextPassword; + MY_UNKNOWN_IMP2( + IArchiveOpenCallback, + ICryptoGetTextPassword) + #else + MY_UNKNOWN_IMP1(IArchiveOpenCallback) + #endif + STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes); + STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes); + #ifndef _NO_CRYPTO + STDMETHOD(CryptoGetTextPassword)(BSTR *password); + #endif +}; + +#ifndef _NO_CRYPTO +STDMETHODIMP CArchiveOpenCallback_Offset::CryptoGetTextPassword(BSTR *password) +{ + COM_TRY_BEGIN + if (GetTextPassword) + return GetTextPassword->CryptoGetTextPassword(password); + return E_NOTIMPL; + COM_TRY_END +} +#endif + +STDMETHODIMP CArchiveOpenCallback_Offset::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */) +{ + return S_OK; +} + +STDMETHODIMP CArchiveOpenCallback_Offset::SetCompleted(const UInt64 * /* files */, const UInt64 *bytes) +{ + if (!Callback) + return S_OK; + UInt64 value = Offset; + if (bytes) + value += *bytes; + return Callback->SetCompleted(&Files, &value); +} + +#endif + +UInt32 GetOpenArcErrorFlags(const NCOM::CPropVariant &prop, bool *isDefinedProp) +{ + if (isDefinedProp != NULL) + *isDefinedProp = false; + + switch (prop.vt) + { + case VT_UI8: if (isDefinedProp) *isDefinedProp = true; return (UInt32)prop.uhVal.QuadPart; + case VT_UI4: if (isDefinedProp) *isDefinedProp = true; return prop.ulVal; + case VT_EMPTY: return 0; + default: throw 151199; + } +} + +void CArcErrorInfo::ClearErrors() +{ + // ErrorFormatIndex = -1; // we don't need to clear ErrorFormatIndex here !!! + + ThereIsTail = false; + UnexpecedEnd = false; + IgnoreTail = false; + // NonZerosTail = false; + ErrorFlags_Defined = false; + ErrorFlags = 0; + WarningFlags = 0; + TailSize = 0; + + ErrorMessage.Empty(); + WarningMessage.Empty(); +} + +HRESULT CArc::ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes) +{ + // OkPhySize_Defined = false; + PhySizeDefined = false; + PhySize = 0; + Offset = 0; + AvailPhySize = FileSize - startPos; + + ErrorInfo.ClearErrors(); + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidErrorFlags, &prop)); + ErrorInfo.ErrorFlags = GetOpenArcErrorFlags(prop, &ErrorInfo.ErrorFlags_Defined); + } + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidWarningFlags, &prop)); + ErrorInfo.WarningFlags = GetOpenArcErrorFlags(prop); + } + + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidError, &prop)); + if (prop.vt != VT_EMPTY) + ErrorInfo.ErrorMessage = (prop.vt == VT_BSTR) ? prop.bstrVal : L"Unknown error"; + } + + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidWarning, &prop)); + if (prop.vt != VT_EMPTY) + ErrorInfo.WarningMessage = (prop.vt == VT_BSTR) ? prop.bstrVal : L"Unknown warning"; + } + + if (openRes == S_OK || ErrorInfo.IsArc_After_NonOpen()) + { + RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, PhySize, PhySizeDefined)); + /* + RINOK(Archive_GetArcProp_UInt(archive, kpidOkPhySize, OkPhySize, OkPhySize_Defined)); + if (!OkPhySize_Defined) + { + OkPhySize_Defined = PhySizeDefined; + OkPhySize = PhySize; + } + */ + + bool offsetDefined; + RINOK(Archive_GetArcProp_Int(archive, kpidOffset, Offset, offsetDefined)); + + Int64 globalOffset = startPos + Offset; + AvailPhySize = FileSize - globalOffset; + if (PhySizeDefined) + { + UInt64 endPos = globalOffset + PhySize; + if (endPos < FileSize) + { + AvailPhySize = PhySize; + ErrorInfo.ThereIsTail = true; + ErrorInfo.TailSize = FileSize - endPos; + } + else if (endPos > FileSize) + ErrorInfo.UnexpecedEnd = true; + } + } + + return S_OK; +} + +/* +static PrintNumber(const char *s, int n) +{ + char temp[100]; + sprintf(temp, "%s %d", s, n); + OutputDebugStringA(temp); +} +*/ + +HRESULT CArc::PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr &archive) +{ + // OutputDebugStringW(L"a1"); + // PrintNumber("formatIndex", formatIndex); + + RINOK(op.codecs->CreateInArchive(formatIndex, archive)); + // OutputDebugStringW(L"a2"); + if (!archive) + return S_OK; + + #ifdef EXTERNAL_CODECS + { + CMyComPtr setCompressCodecsInfo; + archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); + if (setCompressCodecsInfo) + { + RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(op.codecs)); + } + } + #endif + + // OutputDebugStringW(ai.Name); + // OutputDebugStringW(L"a3"); + + #ifndef _SFX + const CArcInfoEx &ai = op.codecs->Formats[formatIndex]; + if (ai.Flags_PreArc()) + { + /* we notify parsers that extract executables, that they don't need + to open archive, if there is tail after executable (for SFX cases) */ + CMyComPtr allowTail; + archive.QueryInterface(IID_IArchiveAllowTail, (void **)&allowTail); + if (allowTail) + allowTail->AllowTail(BoolToInt(true)); + } + if (op.props) + { + /* + FOR_VECTOR (y, op.props) + { + const COptionalOpenProperties &optProps = (*op.props)[y]; + if (optProps.FormatName.IsEmpty() || optProps.FormatName.CompareNoCase(ai.Name) == 0) + { + RINOK(SetProperties(archive, optProps.Props)); + break; + } + } + */ + RINOK(SetProperties(archive, *op.props)); + } + #endif + return S_OK; +} + +#ifndef _SFX + +static HRESULT ReadParseItemProps(IInArchive *archive, const CArcInfoEx &ai, NArchive::NParser::CParseItem &pi) +{ + pi.Extension = ai.GetMainExt(); + pi.FileTime_Defined = false; + pi.ArcType = ai.Name; + + RINOK(Archive_GetArcBoolProp(archive, kpidIsNotArcType, pi.IsNotArcType)); + + // RINOK(Archive_GetArcBoolProp(archive, kpidIsSelfExe, pi.IsSelfExe)); + pi.IsSelfExe = ai.Flags_PreArc(); + + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidMTime, &prop)); + if (prop.vt == VT_FILETIME) + { + pi.FileTime_Defined = true; + pi.FileTime = prop.filetime; + } + } + + if (!pi.FileTime_Defined) + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidCTime, &prop)); + if (prop.vt == VT_FILETIME) + { + pi.FileTime_Defined = true; + pi.FileTime = prop.filetime; + } + } + + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidName, &prop)); + if (prop.vt == VT_BSTR) + { + pi.Name = prop.bstrVal; + pi.Extension.Empty(); + } + else + { + RINOK(archive->GetArchiveProperty(kpidExtension, &prop)); + if (prop.vt == VT_BSTR) + pi.Extension = prop.bstrVal; + } + } + + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidShortComment, &prop)); + if (prop.vt == VT_BSTR) + pi.Comment = prop.bstrVal; + } + + + UInt32 numItems; + RINOK(archive->GetNumberOfItems(&numItems)); + + // pi.NumSubFiles = numItems; + // RINOK(Archive_GetArcProp_UInt(archive, kpidUnpackSize, pi.UnpackSize, pi.UnpackSize_Defined)); + // if (!pi.UnpackSize_Defined) + { + pi.NumSubFiles = 0; + pi.NumSubDirs = 0; + pi.UnpackSize = 0; + for (UInt32 i = 0; i < numItems; i++) + { + UInt64 size = 0; + bool defined = false; + Archive_GetItem_Size(archive, i, size, defined); + if (defined) + { + pi.UnpackSize_Defined = true; + pi.UnpackSize += size; + } + + bool isDir = false; + Archive_IsItem_Folder(archive, i, isDir); + if (isDir) + pi.NumSubDirs++; + else + pi.NumSubFiles++; + } + if (pi.NumSubDirs != 0) + pi.NumSubDirs_Defined = true; + pi.NumSubFiles_Defined = true; + } + + return S_OK; +} + +#endif + +HRESULT CArc::CheckZerosTail(const COpenOptions &op, UInt64 offset) +{ + if (!op.stream) + return S_OK; + RINOK(op.stream->Seek(offset, STREAM_SEEK_SET, NULL)); + const UInt32 kBufSize = 1 << 11; + Byte buf[kBufSize]; + + for (;;) + { + UInt32 processed = 0; + RINOK(op.stream->Read(buf, kBufSize, &processed)); + if (processed == 0) + { + // ErrorInfo.NonZerosTail = false; + ErrorInfo.IgnoreTail = true; + return S_OK; + } + for (size_t i = 0; i < processed; i++) + { + if (buf[i] != 0) + { + // ErrorInfo.IgnoreTail = false; + // ErrorInfo.NonZerosTail = true; + return S_OK; + } + } + } +} + +#ifndef _SFX + +class CExtractCallback_To_OpenCallback: + public IArchiveExtractCallback, + public ICompressProgressInfo, + public CMyUnknownImp +{ +public: + CMyComPtr Callback; + UInt64 Files; + UInt64 Offset; + + MY_UNKNOWN_IMP2(IArchiveExtractCallback, ICompressProgressInfo) + INTERFACE_IArchiveExtractCallback(;) + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); + void Init(IArchiveOpenCallback *callback) + { + Callback = callback; + Files = 0; + Offset = 0; + } +}; + +STDMETHODIMP CExtractCallback_To_OpenCallback::SetTotal(UInt64 /* size */) +{ + return S_OK; +} + +STDMETHODIMP CExtractCallback_To_OpenCallback::SetCompleted(const UInt64 * /* completeValue */) +{ + return S_OK; +} + +STDMETHODIMP CExtractCallback_To_OpenCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */) +{ + if (Callback) + { + UInt64 value = Offset; + if (inSize) + value += *inSize; + return Callback->SetCompleted(&Files, &value); + } + return S_OK; +} + +STDMETHODIMP CExtractCallback_To_OpenCallback::GetStream(UInt32 /* index */, ISequentialOutStream **outStream, Int32 /* askExtractMode */) +{ + *outStream = 0; + return S_OK; +} + +STDMETHODIMP CExtractCallback_To_OpenCallback::PrepareOperation(Int32 /* askExtractMode */) +{ + return S_OK; +} + +STDMETHODIMP CExtractCallback_To_OpenCallback::SetOperationResult(Int32 /* operationResult */) +{ + return S_OK; +} + +static HRESULT OpenArchiveSpec(IInArchive *archive, bool needPhySize, + IInStream *stream, const UInt64 *maxCheckStartPosition, + IArchiveOpenCallback *openCallback, + IArchiveExtractCallback *extractCallback) +{ + /* + if (needPhySize) + { + CMyComPtr open2; + archive->QueryInterface(IID_IArchiveOpen2, (void **)&open2); + if (open2) + return open2->ArcOpen2(stream, kOpenFlags_RealPhySize, openCallback); + } + */ + RINOK(archive->Open(stream, maxCheckStartPosition, openCallback)); + if (needPhySize) + { + bool phySize_Defined = false; + UInt64 phySize = 0; + RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, phySize, phySize_Defined)); + if (phySize_Defined) + return S_OK; + + bool phySizeCantBeDetected = false;; + RINOK(Archive_GetArcBoolProp(archive, kpidPhySizeCantBeDetected, phySizeCantBeDetected)); + + if (!phySizeCantBeDetected) + { + RINOK(archive->Extract(0, (UInt32)(Int32)-1, BoolToInt(true), extractCallback)); + } + } + return S_OK; +} + +static int FindFormatForArchiveType(CCodecs *codecs, CIntVector orderIndices, const char *name) +{ + FOR_VECTOR (i, orderIndices) + if (StringsAreEqualNoCase_Ascii(codecs->Formats[orderIndices[i]].Name, name)) + return i; + return -1; +} + +#endif + +HRESULT CArc::OpenStream2(const COpenOptions &op) +{ + // fprintf(stdout, "\nOpen: %S", Path); fflush(stdout); + + Archive.Release(); + GetRawProps.Release(); + GetRootProps.Release(); + + ErrorInfo.ClearErrors(); + ErrorInfo.ErrorFormatIndex = -1; + + IsParseArc = false; + ArcStreamOffset = 0; + + // OutputDebugStringW(L"1"); + // OutputDebugStringW(Path); + + const UString fileName = ExtractFileNameFromPath(Path); + UString extension; + { + int dotPos = fileName.ReverseFind(L'.'); + if (dotPos >= 0) + extension = fileName.Ptr(dotPos + 1); + } + + CIntVector orderIndices; + + bool searchMarkerInHandler = false; + #ifdef _SFX + searchMarkerInHandler = true; + #endif + + CBoolArr isMainFormatArr(op.codecs->Formats.Size()); + { + FOR_VECTOR(i, op.codecs->Formats) + isMainFormatArr[i] = false; + } + + UInt64 maxStartOffset = + op.openType.MaxStartOffset_Defined ? + op.openType.MaxStartOffset : + kMaxCheckStartPosition; + + #ifndef _SFX + bool isUnknownExt = false; + #endif + + bool isForced = false; + unsigned numMainTypes = 0; + int formatIndex = op.openType.FormatIndex; + + if (formatIndex >= 0) + { + isForced = true; + orderIndices.Add(formatIndex); + numMainTypes = 1; + isMainFormatArr[formatIndex] = true; + + searchMarkerInHandler = true; + } + else + { + unsigned numFinded = 0; + #ifndef _SFX + bool isPrearcExt = false; + #endif + + { + FOR_VECTOR (i, op.codecs->Formats) + { + const CArcInfoEx &ai = op.codecs->Formats[i]; + + if (IgnoreSplit || !op.openType.CanReturnArc) + if (ai.IsSplit()) + continue; + if (op.excludedFormats->FindInSorted(i) >= 0) + continue; + + #ifndef _SFX + if (IsPreArcFormat(ai)) + isPrearcExt = true; + #endif + + if (ai.FindExtension(extension) >= 0) + { + // PrintNumber("orderIndices.Insert", i); + orderIndices.Insert(numFinded++, i); + isMainFormatArr[i] = true; + } + else + orderIndices.Add(i); + } + } + + if (!op.stream) + { + if (numFinded != 1) + return E_NOTIMPL; + orderIndices.DeleteFrom(1); + } + // PrintNumber("numFinded", numFinded ); + + /* + if (op.openOnlySpecifiedByExtension) + { + if (numFinded != 0 && !IsExeExt(extension)) + orderIndices.DeleteFrom(numFinded); + } + */ + + #ifndef _SFX + + if (op.stream && orderIndices.Size() >= 2) + { + RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); + CByteBuffer byteBuffer; + CIntVector orderIndices2; + if (numFinded == 0 || IsExeExt(extension)) + { + // signature search was here + } + else if (extension == L"000" || extension == L"001") + { + int i = FindFormatForArchiveType(op.codecs, orderIndices, "rar"); + if (i >= 0) + { + const size_t kBufSize = (1 << 10); + byteBuffer.Alloc(kBufSize); + size_t processedSize = kBufSize; + RINOK(ReadStream(op.stream, byteBuffer, &processedSize)); + if (processedSize >= 16) + { + const Byte *buf = byteBuffer; + const Byte kRarHeader[] = { 0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00 }; + if (TestSignature(buf, kRarHeader, 7) && buf[9] == 0x73 && (buf[10] & 1) != 0) + { + orderIndices2.Add(orderIndices[i]); + orderIndices[i] = -1; + if (i >= (int)numFinded) + numFinded++; + } + } + } + } + else + { + const size_t kBufSize = (1 << 10); + byteBuffer.Alloc(kBufSize); + size_t processedSize = kBufSize; + RINOK(ReadStream(op.stream, byteBuffer, &processedSize)); + if (processedSize == 0) + return S_FALSE; + + /* + check type order: + 1) matched extension, no signuature + 2) matched extension, matched signuature + // 3) no signuature + // 4) matched signuature + */ + + MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, NULL, 0); + MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, byteBuffer, processedSize); + // MakeCheckOrder(op.codecs, orderIndices, orderIndices.Size(), orderIndices2, NULL, 0); + // MakeCheckOrder(op.codecs, orderIndices, orderIndices.Size(), orderIndices2, byteBuffer, processedSize); + } + + FOR_VECTOR (i, orderIndices) + { + int val = orderIndices[i]; + if (val != -1) + orderIndices2.Add(val); + } + orderIndices = orderIndices2; + } + + if (orderIndices.Size() >= 2) + { + int iIso = FindFormatForArchiveType(op.codecs, orderIndices, "iso"); + int iUdf = FindFormatForArchiveType(op.codecs, orderIndices, "udf"); + if (iUdf > iIso && iIso >= 0) + { + int isoIndex = orderIndices[iIso]; + int udfIndex = orderIndices[iUdf]; + orderIndices[iUdf] = isoIndex; + orderIndices[iIso] = udfIndex; + } + } + + numMainTypes = numFinded; + isUnknownExt = (numMainTypes == 0) || isPrearcExt; + + #else // _SFX + + numMainTypes = orderIndices.Size(); + + #endif + } + + UInt64 fileSize = 0; + if (op.stream) + { + RINOK(op.stream->Seek(0, STREAM_SEEK_END, &fileSize)); + RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); + } + FileSize = fileSize; + + + #ifndef _SFX + + CBoolArr skipFrontalFormat(op.codecs->Formats.Size()); + { + FOR_VECTOR(i, op.codecs->Formats) + skipFrontalFormat[i] = false; + } + + #endif + + const COpenType &mode = op.openType; + + + + + + if (mode.CanReturnArc) + { + // ---------- OPEN main type by extenssion ---------- + + unsigned numCheckTypes = orderIndices.Size(); + if (formatIndex >= 0) + numCheckTypes = numMainTypes; + + for (unsigned i = 0; i < numCheckTypes; i++) + { + FormatIndex = orderIndices[i]; + const CArcInfoEx &ai = op.codecs->Formats[FormatIndex]; + // OutputDebugStringW(ai.Name); + + bool exactOnly = false; + if (i >= numMainTypes) + { + if (!ai.Flags_BackwardOpen() + // && !ai.Flags_PureStartOpen() + ) + continue; + exactOnly = true; + } + + // Some handlers do not set total bytes. So we set it here + RINOK(op.callback->SetTotal(NULL, &fileSize)); + if (op.stream) + { + RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); + } + + CMyComPtr archive; + + RINOK(PrepareToOpen(op, FormatIndex, archive)); + if (!archive) + continue; + + HRESULT result; + if (op.stream) + { + UInt64 searchLimit = (!exactOnly && searchMarkerInHandler) ? maxStartOffset: 0; + result = archive->Open(op.stream, &searchLimit, op.callback); + } + else + { + CMyComPtr openSeq; + archive.QueryInterface(IID_IArchiveOpenSeq, (void **)&openSeq); + if (!openSeq) + return E_NOTIMPL; + result = openSeq->OpenSeq(op.seqStream); + } + + RINOK(ReadBasicProps(archive, 0, result)); + + if (result == S_FALSE) + { + bool isArc = ErrorInfo.IsArc_After_NonOpen(); + + #ifndef _SFX + // if it's archive, we allow another open attempt for parser + if (!mode.CanReturnParser || !isArc) + skipFrontalFormat[FormatIndex] = true; + #endif + + if (exactOnly) + continue; + + if (i == 0 && numMainTypes == 1) + { + // we set NonOpenErrorInfo, only if there is only one main format (defined by extension). + ErrorInfo.ErrorFormatIndex = FormatIndex; + NonOpen_ErrorInfo = ErrorInfo; + + if (!mode.CanReturnParser && isArc) + { + // if (formatIndex < 0 && !searchMarkerInHandler) + { + // if bad archive was detected, we don't need additional open attempts + #ifndef _SFX + if (!IsPreArcFormat(ai) /* || !mode.SkipSfxStub */) + #endif + return S_FALSE; + } + } + } + + /* + #ifndef _SFX + if (IsExeExt(extension) || ai.Flags_PreArc()) + { + // openOnlyFullArc = false; + // canReturnTailArc = true; + // limitSignatureSearch = true; + } + #endif + */ + + continue; + } + + RINOK(result); + + #ifndef _SFX + + bool isMainFormat = isMainFormatArr[FormatIndex]; + const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt); + + bool thereIsTail = ErrorInfo.ThereIsTail; + if (thereIsTail && mode.ZerosTailIsAllowed) + { + RINOK(CheckZerosTail(op, Offset + PhySize)); + if (ErrorInfo.IgnoreTail) + thereIsTail = false; + } + + if (Offset > 0) + { + if (exactOnly + || !searchMarkerInHandler + || !specFlags.CanReturn_NonStart() + || (mode.MaxStartOffset_Defined && (UInt64)Offset > mode.MaxStartOffset)) + continue; + } + if (thereIsTail) + { + if (Offset > 0) + { + if (!specFlags.CanReturnMid) + continue; + } + else if (!specFlags.CanReturnFrontal) + continue; + } + + if (Offset > 0 || thereIsTail) + { + if (formatIndex < 0) + { + if (IsPreArcFormat(ai)) + { + // openOnlyFullArc = false; + // canReturnTailArc = true; + /* + if (mode.SkipSfxStub) + limitSignatureSearch = true; + */ + // if (mode.SkipSfxStub) + { + // skipFrontalFormat[FormatIndex] = true; + continue; + } + } + } + } + + #endif + + Archive = archive; + return S_OK; + } + } + + + + #ifndef _SFX + + if (!op.stream) + return S_FALSE; + + if (formatIndex >= 0 && !mode.CanReturnParser) + { + if (mode.MaxStartOffset_Defined) + { + if (mode.MaxStartOffset == 0) + return S_FALSE; + } + else + { + const CArcInfoEx &ai = op.codecs->Formats[formatIndex]; + if (ai.FindExtension(extension) >= 0) + { + const CArcInfoEx &ai = op.codecs->Formats[formatIndex]; + if (ai.Flags_FindSignature() && searchMarkerInHandler) + return S_FALSE; + } + } + } + + NArchive::NParser::CHandler *handlerSpec = new NArchive::NParser::CHandler; + CMyComPtr handler = handlerSpec; + + CExtractCallback_To_OpenCallback *extractCallback_To_OpenCallback_Spec = new CExtractCallback_To_OpenCallback; + CMyComPtr extractCallback_To_OpenCallback = extractCallback_To_OpenCallback_Spec; + extractCallback_To_OpenCallback_Spec->Init(op.callback); + + { + // ---------- Check all possible START archives ---------- + // this code is better for full file archives than Parser's code. + + CByteBuffer byteBuffer; + bool endOfFile = false; + size_t processedSize; + { + size_t bufSize = 1 << 20; // it must be larger than max signature offset or IsArcFunc offset ((1 << 19) + x for UDF) + if (bufSize > fileSize) + { + bufSize = (size_t)fileSize; + endOfFile = true; + } + byteBuffer.Alloc(bufSize); + RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); + processedSize = bufSize; + RINOK(ReadStream(op.stream, byteBuffer, &processedSize)); + if (processedSize == 0) + return S_FALSE; + if (processedSize < bufSize) + endOfFile = true; + } + CUIntVector sortedFormats; + + unsigned i; + + int splitIndex = -1; + + for (i = 0; i < orderIndices.Size(); i++) + { + unsigned form = orderIndices[i]; + if (skipFrontalFormat[form]) + continue; + const CArcInfoEx &ai = op.codecs->Formats[form]; + if (ai.IsSplit()) + { + splitIndex = form; + continue; + } + + if (ai.IsArcFunc) + { + UInt32 isArcRes = ai.IsArcFunc(byteBuffer, processedSize); + if (isArcRes == k_IsArc_Res_NO) + continue; + if (isArcRes == k_IsArc_Res_NEED_MORE && endOfFile) + continue; + // if (isArcRes == k_IsArc_Res_YES_LOW_PROB) continue; + sortedFormats.Insert(0, form); + continue; + } + + bool isNewStyleSignature = IsNewStyleSignature(ai); + bool needCheck = !isNewStyleSignature + || ai.Signatures.IsEmpty() + || ai.Flags_PureStartOpen() + || ai.Flags_StartOpen() + || ai.Flags_BackwardOpen(); + + if (isNewStyleSignature && !ai.Signatures.IsEmpty()) + { + unsigned k; + for (k = 0; k < ai.Signatures.Size(); k++) + { + const CByteBuffer &sig = ai.Signatures[k]; + UInt32 signatureEnd = ai.SignatureOffset + (UInt32)sig.Size(); + if (processedSize < signatureEnd) + { + if (!endOfFile) + needCheck = true; + } + else if (memcmp(sig, byteBuffer + ai.SignatureOffset, sig.Size()) == 0) + break; + } + if (k != ai.Signatures.Size()) + { + sortedFormats.Insert(0, form); + continue; + } + } + if (needCheck) + sortedFormats.Add(form); + } + + if (splitIndex >= 0) + sortedFormats.Insert(0, splitIndex); + + for (i = 0; i < sortedFormats.Size(); i++) + { + FormatIndex = sortedFormats[i]; + const CArcInfoEx &ai = op.codecs->Formats[FormatIndex]; + + RINOK(op.callback->SetTotal(NULL, &fileSize)); + RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); + + CMyComPtr archive; + RINOK(PrepareToOpen(op, FormatIndex, archive)); + if (!archive) + continue; + + PRF(printf("\nSorted Open %S", (const wchar_t *)ai.Name)); + HRESULT result; + { + UInt64 searchLimit = 0; + /* + if (mode.CanReturnArc) + result = archive->Open(op.stream, &searchLimit, op.callback); + else + */ + result = OpenArchiveSpec(archive, !mode.CanReturnArc, op.stream, &searchLimit, op.callback, extractCallback_To_OpenCallback); + } + + if (result == S_FALSE) + { + skipFrontalFormat[FormatIndex] = true; + // FIXME: maybe we must use LenIsUnknown. + // printf(" OpenForSize Error"); + continue; + } + RINOK(result); + + RINOK(ReadBasicProps(archive, 0, result)); + + if (Offset > 0) + { + continue; // good handler doesn't return such Offset > 0 + // but there are some cases like false prefixed PK00 archive, when + // we can support it? + } + + NArchive::NParser::CParseItem pi; + pi.Offset = Offset; + pi.Size = AvailPhySize; + + // bool needScan = false; + + if (!PhySizeDefined) + { + // it's for Z format + pi.LenIsUnknown = true; + // needScan = true; + // phySize = arcRem; + // nextNeedCheckStartOpen = false; + } + + /* + if (OkPhySize_Defined) + pi.OkSize = pi.OkPhySize; + else + pi.OkSize = pi.Size; + */ + + pi.NormalizeOffset(); + // printf(" phySize = %8d", (unsigned)phySize); + + + if (mode.CanReturnArc) + { + bool isMainFormat = isMainFormatArr[FormatIndex]; + const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt); + bool openCur = false; + + if (!ErrorInfo.ThereIsTail) + openCur = true; + else + { + if (mode.ZerosTailIsAllowed) + { + RINOK(CheckZerosTail(op, Offset + PhySize)); + if (ErrorInfo.IgnoreTail) + openCur = true; + } + if (!openCur) + { + openCur = specFlags.CanReturnFrontal; + if (formatIndex < 0) // format is not forced + { + if (IsPreArcFormat(ai)) + { + // if (mode.SkipSfxStub) + { + openCur = false; + } + } + } + } + } + + if (openCur) + { + InStream = op.stream; + Archive = archive; + return S_OK; + } + } + + skipFrontalFormat[FormatIndex] = true; + + + // if (!mode.CanReturnArc) + /* + if (!ErrorInfo.ThereIsTail) + continue; + */ + if (pi.Offset == 0 && !pi.LenIsUnknown && pi.Size >= FileSize) + continue; + + // printf("\nAdd offset = %d", (int)pi.Offset); + RINOK(ReadParseItemProps(archive, ai, pi)); + handlerSpec->AddItem(pi); + } + } + + + + + + // ---------- PARSER ---------- + + CUIntVector arc2sig; // formatIndex to signatureIndex + CUIntVector sig2arc; // signatureIndex to formatIndex; + { + unsigned sum = 0; + FOR_VECTOR (i, op.codecs->Formats) + { + arc2sig.Add(sum); + const CObjectVector &sigs = op.codecs->Formats[i].Signatures; + sum += sigs.Size(); + FOR_VECTOR (k, sigs) + sig2arc.Add(i); + } + } + + { + CArchiveOpenCallback_Offset *openCallback_Offset_Spec = new CArchiveOpenCallback_Offset; + CMyComPtr openCallback_Offset = openCallback_Offset_Spec; + + const size_t kBeforeSize = 1 << 16; + const size_t kAfterSize = 1 << 20; + const size_t kBufSize = 1 << 22; // it must be more than kBeforeSize + kAfterSize + + const UInt32 kNumVals = (UInt32)1 << (kNumHashBytes * 8); + CByteArr hashBuffer(kNumVals); + Byte *hash = hashBuffer; + memset(hash, 0xFF, kNumVals); + Byte prevs[256]; + memset(prevs, 0xFF, sizeof(prevs)); + if (sig2arc.Size() >= 0xFF) + return S_FALSE; + + CUIntVector difficultFormats; + CBoolArr difficultBools(256); + { + for (unsigned i = 0; i < 256; i++) + difficultBools[i] = false; + } + + bool thereAreHandlersForSearch = false; + + // UInt32 maxSignatureEnd = 0; + + FOR_VECTOR (i, orderIndices) + { + int index = orderIndices[i]; + if (index < 0) + continue; + const CArcInfoEx &ai = op.codecs->Formats[index]; + bool isDifficult = false; + // if (ai.Version < 0x91F) // we don't use parser with old DLL (before 9.31) + if (!ai.NewInterface) + isDifficult = true; + else + { + if (ai.Flags_StartOpen()) + isDifficult = true; + FOR_VECTOR (k, ai.Signatures) + { + const CByteBuffer &sig = ai.Signatures[k]; + /* + UInt32 signatureEnd = ai.SignatureOffset + (UInt32)sig.Size(); + if (maxSignatureEnd < signatureEnd) + maxSignatureEnd = signatureEnd; + */ + if (sig.Size() < kNumHashBytes) + { + isDifficult = true; + continue; + } + thereAreHandlersForSearch = true; + UInt32 v = HASH_VAL(sig, 0); + unsigned sigIndex = arc2sig[index] + k; + prevs[sigIndex] = hash[v]; + hash[v] = (Byte)sigIndex; + } + } + if (isDifficult) + { + difficultFormats.Add(index); + difficultBools[index] = true; + } + } + + if (!thereAreHandlersForSearch) + { + // openOnlyFullArc = true; + // canReturnTailArc = true; + } + + RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); + + CLimitedCachedInStream *limitedStreamSpec = new CLimitedCachedInStream; + CMyComPtr limitedStream = limitedStreamSpec; + limitedStreamSpec->SetStream(op.stream); + + openCallback_Offset_Spec->Callback = op.callback; + + #ifndef _NO_CRYPTO + if (op.callback) + { + openCallback_Offset_Spec->Callback.QueryInterface(IID_ICryptoGetTextPassword, &openCallback_Offset_Spec->GetTextPassword); + } + #endif + + RINOK(op.callback->SetTotal(NULL, &fileSize)); + CByteBuffer &byteBuffer = limitedStreamSpec->Buffer; + byteBuffer.Alloc(kBufSize); + + UInt64 callbackPrev = 0; + bool needCheckStartOpen = true; // = true, if we need to test all archives types for current pos. + + bool endOfFile = false; + UInt64 bufPhyPos = 0; + size_t bytesInBuf = 0; + // UInt64 prevPos = 0; + + // ---------- Main Scan Loop ---------- + + UInt64 pos = 0; + + if (!mode.EachPos && handlerSpec->_items.Size() == 1) + { + NArchive::NParser::CParseItem &pi = handlerSpec->_items[0]; + if (!pi.LenIsUnknown && pi.Offset == 0) + pos = pi.Size; + } + + for (;;) + { + // printf("\nPos = %d", (int)pos); + UInt64 posInBuf = pos - bufPhyPos; + + // if (pos > ((UInt64)1 << 35)) break; + + if (!endOfFile) + { + if (bytesInBuf < kBufSize) + { + size_t processedSize = kBufSize - bytesInBuf; + // printf("\nRead ask = %d", (unsigned)processedSize); + UInt64 seekPos = bufPhyPos + bytesInBuf; + RINOK(op.stream->Seek(bufPhyPos + bytesInBuf, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream(op.stream, byteBuffer + bytesInBuf, &processedSize)); + // printf(" processed = %d", (unsigned)processedSize); + if (processedSize == 0) + { + fileSize = seekPos; + endOfFile = true; + } + else + { + bytesInBuf += processedSize; + limitedStreamSpec->SetCache(processedSize, (size_t)bufPhyPos); + } + continue; + } + + if (bytesInBuf < posInBuf) + { + UInt64 skipSize = posInBuf - bytesInBuf; + if (skipSize <= kBeforeSize) + { + size_t keepSize = (size_t)(kBeforeSize - skipSize); + // printf("\nmemmove skip = %d", (int)keepSize); + memmove(byteBuffer, byteBuffer + bytesInBuf - keepSize, keepSize); + bytesInBuf = keepSize; + bufPhyPos = pos - keepSize; + continue; + } + // printf("\nSkip %d", (int)(skipSize - kBeforeSize)); + // RINOK(op.stream->Seek(skipSize - kBeforeSize, STREAM_SEEK_CUR, NULL)); + bytesInBuf = 0; + bufPhyPos = pos - kBeforeSize; + continue; + } + + if (bytesInBuf - posInBuf < kAfterSize) + { + size_t beg = (size_t)posInBuf - kBeforeSize; + // printf("\nmemmove for after beg = %d", (int)beg); + memmove(byteBuffer, byteBuffer + beg, bytesInBuf - beg); + bufPhyPos += beg; + bytesInBuf -= beg; + continue; + } + } + + if (pos >= callbackPrev + (1 << 23)) + { + openCallback_Offset_Spec->Files = handlerSpec->_items.Size(); + openCallback_Offset_Spec->Offset = pos; + RINOK(openCallback_Offset->SetCompleted(NULL, NULL)); + callbackPrev = pos; + } + + { + UInt64 endPos = bufPhyPos + bytesInBuf; + if (fileSize < endPos) + { + FileSize = fileSize; // why ???? + fileSize = endPos; + } + } + + size_t availSize = bytesInBuf - (size_t)posInBuf; + if (availSize < kNumHashBytes) + break; + size_t scanSize = availSize - + ((availSize >= kAfterSize) ? kAfterSize : kNumHashBytes); + + { + /* + UInt64 scanLimit = openOnlyFullArc ? + maxSignatureEnd : + op.openType.ScanSize + maxSignatureEnd; + */ + if (!mode.CanReturnParser) + { + if (pos > maxStartOffset) + break; + UInt64 remScan = maxStartOffset - pos; + if (scanSize > remScan) + scanSize = (size_t)remScan; + } + } + + scanSize++; + + const Byte *buf = byteBuffer + (size_t)posInBuf; + size_t ppp = 0; + + if (!needCheckStartOpen) + { + for (; ppp < scanSize && hash[HASH_VAL(buf, ppp)] == 0xFF; ppp++); + pos += ppp; + if (ppp == scanSize) + continue; + } + + UInt32 v = HASH_VAL(buf, ppp); + bool nextNeedCheckStartOpen = true; + unsigned i = hash[v]; + unsigned indexOfDifficult = 0; + + // ---------- Open Loop for Current Pos ---------- + bool wasOpen = false; + + for (;;) + { + unsigned index; + bool isDifficult; + if (needCheckStartOpen && indexOfDifficult < difficultFormats.Size()) + { + index = difficultFormats[indexOfDifficult++]; + isDifficult = true; + } + else + { + if (i == 0xFF) + break; + index = sig2arc[i]; + unsigned sigIndex = i - arc2sig[index]; + i = prevs[i]; + if (needCheckStartOpen && difficultBools[index]) + continue; + const CArcInfoEx &ai = op.codecs->Formats[index]; + + if (pos < ai.SignatureOffset) + continue; + + /* + if (openOnlyFullArc) + if (pos != ai.SignatureOffset) + continue; + */ + + const CByteBuffer &sig = ai.Signatures[sigIndex]; + + if (ppp + sig.Size() > availSize + || !TestSignature(buf + ppp, sig, sig.Size())) + continue; + // printf("\nSignature OK: %10S %8x %5d", (const wchar_t *)ai.Name, (int)pos, (int)(pos - prevPos)); + // prevPos = pos; + isDifficult = false; + } + + const CArcInfoEx &ai = op.codecs->Formats[index]; + + + if ((isDifficult && pos == 0) || ai.SignatureOffset == pos) + { + // we don't check same archive second time */ + if (skipFrontalFormat[index]) + continue; + } + + UInt64 startArcPos = pos; + if (!isDifficult) + { + if (pos < ai.SignatureOffset) + continue; + startArcPos = pos - ai.SignatureOffset; + /* + // we don't need the check for Z files + if (startArcPos < handlerSpec->GetLastEnd()) + continue; + */ + } + + if (ai.IsArcFunc && startArcPos >= bufPhyPos) + { + size_t offsetInBuf = (size_t)(startArcPos - bufPhyPos); + if (offsetInBuf < bytesInBuf) + { + UInt32 isArcRes = ai.IsArcFunc(byteBuffer + offsetInBuf, bytesInBuf - offsetInBuf); + if (isArcRes == k_IsArc_Res_NO) + continue; + if (isArcRes == k_IsArc_Res_NEED_MORE && endOfFile) + continue; + /* + if (isArcRes == k_IsArc_Res_YES_LOW_PROB) + { + // if (pos != ai.SignatureOffset) + continue; + } + */ + } + // printf("\nIsArc OK: %S", (const wchar_t *)ai.Name); + } + + /* + if (pos == 67109888) + pos = pos; + */ + PRF(printf("\npos = %9I64d : %S", pos, (const wchar_t *)ai.Name)); + + bool isMainFormat = isMainFormatArr[index]; + const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt); + + CMyComPtr archive; + RINOK(PrepareToOpen(op, index, archive)); + if (!archive) + return E_FAIL; + + // OutputDebugStringW(ai.Name); + + UInt64 rem = fileSize - startArcPos; + + UInt64 arcStreamOffset = 0; + + if (ai.Flags_UseGlobalOffset()) + { + limitedStreamSpec->InitAndSeek(0, fileSize); + limitedStream->Seek(startArcPos, STREAM_SEEK_SET, NULL); + } + else + { + limitedStreamSpec->InitAndSeek(startArcPos, rem); + arcStreamOffset = startArcPos; + } + + UInt64 maxCheckStartPosition = 0; + openCallback_Offset_Spec->Files = handlerSpec->_items.Size(); + openCallback_Offset_Spec->Offset = startArcPos; + // HRESULT result = archive->Open(limitedStream, &maxCheckStartPosition, openCallback_Offset); + extractCallback_To_OpenCallback_Spec->Files = 0; + extractCallback_To_OpenCallback_Spec->Offset = startArcPos; + + HRESULT result = OpenArchiveSpec(archive, true, limitedStream, &maxCheckStartPosition, openCallback_Offset, extractCallback_To_OpenCallback); + + RINOK(ReadBasicProps(archive, ai.Flags_UseGlobalOffset() ? 0 : startArcPos, result)); + + bool isOpen = false; + if (result == S_FALSE) + { + if (!mode.CanReturnParser) + { + if (formatIndex < 0 && ErrorInfo.IsArc_After_NonOpen()) + { + ErrorInfo.ErrorFormatIndex = index; + NonOpen_ErrorInfo = ErrorInfo; + // if archive was detected, we don't need additional open attempts + return S_FALSE; + } + continue; + } + if (!ErrorInfo.IsArc_After_NonOpen() || !PhySizeDefined || PhySize == 0) + continue; + } + else + { + isOpen = true; + RINOK(result); + PRF(printf(" OK ")); + } + + // fprintf(stderr, "\n %8X %S", startArcPos, Path); + // printf("\nOpen OK: %S", ai.Name); + + + NArchive::NParser::CParseItem pi; + pi.Offset = startArcPos; + + if (ai.Flags_UseGlobalOffset()) + pi.Offset = Offset; + else if (Offset != 0) + return E_FAIL; + UInt64 arcRem = FileSize - pi.Offset; + UInt64 phySize = arcRem; + bool phySizeDefined = PhySizeDefined; + if (phySizeDefined) + { + if (pi.Offset + PhySize > FileSize) + { + // ErrorInfo.ThereIsTail = true; + PhySize = FileSize - pi.Offset; + } + phySize = PhySize; + } + if (phySize == 0 || (UInt64)phySize > ((UInt64)1 << 63)) + return E_FAIL; + + /* + if (!ai.UseGlobalOffset) + { + if (phySize > arcRem) + { + ThereIsTail = true; + phySize = arcRem; + } + } + */ + + bool needScan = false; + + + if (isOpen && !phySizeDefined) + { + // it's for Z format + pi.LenIsUnknown = true; + needScan = true; + phySize = arcRem; + nextNeedCheckStartOpen = false; + } + + pi.Size = phySize; + /* + if (OkPhySize_Defined) + pi.OkSize = OkPhySize; + */ + pi.NormalizeOffset(); + // printf(" phySize = %8d", (unsigned)phySize); + + /* + if (needSkipFullArc) + if (pi.Offset == 0 && phySizeDefined && pi.Size >= fileSize) + continue; + */ + if (pi.Offset == 0 && !pi.LenIsUnknown && pi.Size >= FileSize) + { + // it's possible for dmg archives + if (!mode.CanReturnArc) + continue; + } + + if (mode.EachPos) + pos++; + else if (needScan) + { + pos++; + /* + if (!OkPhySize_Defined) + pos++; + else + pos = pi.Offset + pi.OkSize; + */ + } + else + pos = pi.Offset + pi.Size; + + + RINOK(ReadParseItemProps(archive, ai, pi)); + + if (pi.Offset < startArcPos && !mode.EachPos /* && phySizeDefined */) + { + /* It's for DMG format. + This code deletes all previous items that are included to current item */ + + while (!handlerSpec->_items.IsEmpty()) + { + { + const NArchive::NParser::CParseItem &back = handlerSpec->_items.Back(); + if (back.Offset < pi.Offset) + break; + if (back.Offset + back.Size > pi.Offset + pi.Size) + break; + } + handlerSpec->_items.DeleteBack(); + } + } + + if (isOpen && mode.CanReturnArc && phySizeDefined) + { + // if (pi.Offset + pi.Size >= fileSize) + bool openCur = false; -HRESULT CArc::OpenStream( - CCodecs *codecs, - int formatIndex, - IInStream *stream, - ISequentialInStream *seqStream, - IArchiveOpenCallback *callback) -{ - Archive.Release(); - ErrorMessage.Empty(); - const UString fileName = ExtractFileNameFromPath(Path); - UString extension; - { - int dotPos = fileName.ReverseFind(L'.'); - if (dotPos >= 0) - extension = fileName.Mid(dotPos + 1); - } - CIntVector orderIndices; - if (formatIndex >= 0) - orderIndices.Add(formatIndex); - else - { + bool thereIsTail = ErrorInfo.ThereIsTail; + if (thereIsTail && mode.ZerosTailIsAllowed) + { + RINOK(CheckZerosTail(op, arcStreamOffset + Offset + PhySize)); + if (ErrorInfo.IgnoreTail) + thereIsTail = false; + } - int i; - int numFinded = 0; - for (i = 0; i < codecs->Formats.Size(); i++) - if (codecs->Formats[i].FindExtension(extension) >= 0) - orderIndices.Insert(numFinded++, i); - else - orderIndices.Add(i); - - if (!stream) - { - if (numFinded != 1) - return E_NOTIMPL; - orderIndices.DeleteFrom(1); - } + if (pi.Offset != 0) + { + if (!pi.IsNotArcType) + if (thereIsTail) + openCur = specFlags.CanReturnMid; + else + openCur = specFlags.CanReturnTail; + } + else + { + if (!thereIsTail) + openCur = true; + else + openCur = specFlags.CanReturnFrontal; - #ifndef _SFX - if (orderIndices.Size() >= 2 && (numFinded == 0 || extension.CompareNoCase(L"exe") == 0)) - { - CIntVector orderIndices2; - CByteBuffer byteBuffer; - const size_t kBufferSize = (1 << 21); - byteBuffer.SetCapacity(kBufferSize); - RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); - size_t processedSize = kBufferSize; - RINOK(ReadStream(stream, byteBuffer, &processedSize)); - if (processedSize == 0) - return S_FALSE; - const Byte *buf = byteBuffer; - CByteBuffer hashBuffer; - const UInt32 kNumVals = 1 << (kNumHashBytes * 8); - hashBuffer.SetCapacity(kNumVals); - Byte *hash = hashBuffer; - memset(hash, 0xFF, kNumVals); - Byte prevs[256]; - if (orderIndices.Size() >= 256) - return S_FALSE; - int i; - for (i = 0; i < orderIndices.Size(); i++) - { - const CArcInfoEx &ai = codecs->Formats[orderIndices[i]]; - const CByteBuffer &sig = ai.StartSignature; - if (sig.GetCapacity() < kNumHashBytes) - continue; - UInt32 v = HASH_VAL(sig, 0); - prevs[i] = hash[v]; - hash[v] = (Byte)i; - } + if (formatIndex >= -2) + openCur = true; + } + if (formatIndex < 0 && pi.IsSelfExe /* && mode.SkipSfxStub */) + openCur = false; - processedSize -= (kNumHashBytes - 1); - for (UInt32 pos = 0; pos < processedSize; pos++) - { - for (; pos < processedSize && hash[HASH_VAL(buf, pos)] == 0xFF; pos++) {} - if (pos == processedSize) - break; - UInt32 v = HASH_VAL(buf, pos); - Byte *ptr = &hash[v]; - int i = *ptr; - do - { - int index = orderIndices[i]; - const CArcInfoEx &ai = codecs->Formats[index]; - const CByteBuffer &sig = ai.StartSignature; - if (sig.GetCapacity() != 0 && pos + sig.GetCapacity() <= processedSize + (kNumHashBytes - 1) && - TestSignature(buf + pos, sig, sig.GetCapacity())) + // We open file as SFX, if there is front archive or first archive is "Self Executable" + if (!openCur && !pi.IsSelfExe && !thereIsTail && + (!pi.IsNotArcType || pi.Offset == 0)) + { + if (handlerSpec->_items.IsEmpty()) + { + if (specFlags.CanReturnTail) + openCur = true; + } + else if (handlerSpec->_items.Size() == 1) + { + if (handlerSpec->_items[0].IsSelfExe) + { + if (mode.SpecUnknownExt.CanReturnTail) + openCur = true; + } + } + } + + if (openCur) + { + InStream = op.stream; + Archive = archive; + FormatIndex = index; + ArcStreamOffset = arcStreamOffset; + return S_OK; + } + } + + /* + if (openOnlyFullArc) { - orderIndices2.Add(index); - orderIndices[i] = 0xFF; - *ptr = prevs[i]; + ErrorInfo.ClearErrors(); + return S_FALSE; } - else - ptr = &prevs[i]; - i = *ptr; + */ + + pi.FormatIndex = index; + + // printf("\nAdd offset = %d", (int)pi.Offset); + handlerSpec->AddItem(pi); + wasOpen = true; + break; } - while (i != 0xFF); + // ---------- End of Open Loop for Current Pos ---------- + + if (!wasOpen) + pos++; + needCheckStartOpen = (nextNeedCheckStartOpen && wasOpen); } - - for (i = 0; i < orderIndices.Size(); i++) + // ---------- End of Main Scan Loop ---------- + + /* + if (handlerSpec->_items.Size() == 1) { - int val = orderIndices[i]; - if (val != 0xFF) - orderIndices2.Add(val); - } - orderIndices = orderIndices2; - } - else if (extension == L"000" || extension == L"001") - { - CByteBuffer byteBuffer; - const size_t kBufferSize = (1 << 10); - byteBuffer.SetCapacity(kBufferSize); - Byte *buffer = byteBuffer; - RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); - size_t processedSize = kBufferSize; - RINOK(ReadStream(stream, buffer, &processedSize)); - if (processedSize >= 16) - { - Byte kRarHeader[] = {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00}; - if (TestSignature(buffer, kRarHeader, 7) && buffer[9] == 0x73 && (buffer[10] & 1) != 0) - { - for (int i = 0; i < orderIndices.Size(); i++) - { - int index = orderIndices[i]; - const CArcInfoEx &ai = codecs->Formats[index]; - if (ai.Name.CompareNoCase(L"rar") != 0) - continue; - orderIndices.Delete(i--); - orderIndices.Insert(0, index); - break; - } + const NArchive::NParser::CParseItem &pi = handlerSpec->_items[0]; + if (pi.Size == fileSize && pi.Offset == 0) + { + Archive = archive; + FormatIndex2 = pi.FormatIndex; + return S_OK; } } - } - if (orderIndices.Size() >= 2) - { - int isoIndex = codecs->FindFormatForArchiveType(L"iso"); - int udfIndex = codecs->FindFormatForArchiveType(L"udf"); - int iIso = -1; - int iUdf = -1; - for (int i = 0; i < orderIndices.Size(); i++) - { - if (orderIndices[i] == isoIndex) iIso = i; - if (orderIndices[i] == udfIndex) iUdf = i; - } - if (iUdf > iIso && iIso >= 0) + */ + + if (mode.CanReturnParser) { - orderIndices[iUdf] = isoIndex; - orderIndices[iIso] = udfIndex; + bool returnParser = (handlerSpec->_items.Size() == 1); // it's possible if fileSize was not correct at start of parsing + handlerSpec->AddUnknownItem(fileSize); + if (handlerSpec->_items.Size() == 0) + return S_FALSE; + if (returnParser || handlerSpec->_items.Size() != 1) + { + // return S_FALSE; + handlerSpec->_stream = op.stream; + Archive = handler; + ErrorInfo.ClearErrors(); + IsParseArc = true; + FormatIndex = -1; // It's parser + Offset = 0; + return S_OK; + } } } #endif - } - for (int i = 0; i < orderIndices.Size(); i++) + if (!Archive) + return S_FALSE; + return S_OK; +} + +HRESULT CArc::OpenStream(const COpenOptions &op) +{ + RINOK(OpenStream2(op)); + // PrintNumber("op.formatIndex 3", op.formatIndex); + + if (Archive) { - if (stream) + GetRawProps.Release(); + GetRootProps.Release(); + Archive->QueryInterface(IID_IArchiveGetRawProps, (void **)&GetRawProps); + Archive->QueryInterface(IID_IArchiveGetRootProps, (void **)&GetRootProps); + + RINOK(Archive_GetArcBoolProp(Archive, kpidIsTree, IsTree)); + RINOK(Archive_GetArcBoolProp(Archive, kpidIsDeleted, Ask_Deleted)); + RINOK(Archive_GetArcBoolProp(Archive, kpidIsAltStream, Ask_AltStream)); + RINOK(Archive_GetArcBoolProp(Archive, kpidIsAux, Ask_Aux)); + RINOK(Archive_GetArcBoolProp(Archive, kpidINode, Ask_INode)); + + const UString fileName = ExtractFileNameFromPath(Path); + UString extension; { - RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + int dotPos = fileName.ReverseFind(L'.'); + if (dotPos >= 0) + extension = fileName.Ptr(dotPos + 1); } - CMyComPtr archive; - - FormatIndex = orderIndices[i]; - RINOK(codecs->CreateInArchive(FormatIndex, archive)); - if (!archive) - continue; - #ifdef EXTERNAL_CODECS + DefaultName.Empty(); + if (FormatIndex >= 0) { - CMyComPtr setCompressCodecsInfo; - archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); - if (setCompressCodecsInfo) + const CArcInfoEx &ai = op.codecs->Formats[FormatIndex]; + if (ai.Exts.Size() == 0) + DefaultName = GetDefaultName2(fileName, L"", L""); + else { - RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); + int subExtIndex = ai.FindExtension(extension); + if (subExtIndex < 0) + subExtIndex = 0; + const CArcExtInfo &extInfo = ai.Exts[subExtIndex]; + DefaultName = GetDefaultName2(fileName, extInfo.Ext, extInfo.AddExt); } } - #endif + } - // OutputDebugStringW(codecs->Formats[FormatIndex].Name); + return S_OK; +} - HRESULT result; - if (stream) - result = archive->Open(stream, &kMaxCheckStartPosition, callback); - else - { - CMyComPtr openSeq; - archive.QueryInterface(IID_IArchiveOpenSeq, (void **)&openSeq); - if (!openSeq) - return E_NOTIMPL; - result = openSeq->OpenSeq(seqStream); - } +#ifdef _SFX - if (result == S_FALSE) - continue; - RINOK(result); +#ifdef _WIN32 + static const wchar_t *k_ExeExt = L".exe"; + static const unsigned k_ExeExt_Len = 4; +#else + static const wchar_t *k_ExeExt = L""; + static const unsigned k_ExeExt_Len = 0; +#endif - { - 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]; - if (format.Exts.Size() == 0) - DefaultName = GetDefaultName2(fileName, L"", L""); - else - { - int subExtIndex = format.FindExtension(extension); - if (subExtIndex < 0) - subExtIndex = 0; - const CArcExtInfo &extInfo = format.Exts[subExtIndex]; - DefaultName = GetDefaultName2(fileName, extInfo.Ext, extInfo.AddExt); - } - return S_OK; - } - return S_FALSE; -} +#endif -HRESULT CArc::OpenStreamOrFile( - CCodecs *codecs, - int formatIndex, - bool stdInMode, - IInStream *stream, - IArchiveOpenCallback *callback) +HRESULT CArc::OpenStreamOrFile(COpenOptions &op) { CMyComPtr fileStream; CMyComPtr seqStream; - if (stdInMode) + CInFileStream *fileStreamSpec = NULL; + if (op.stdInMode) + { seqStream = new CStdInFileStream; - else if (!stream) + op.seqStream = seqStream; + } + else if (!op.stream) { - CInFileStream *fileStreamSpec = new CInFileStream(true); + fileStreamSpec = new CInFileStream(true); fileStream = fileStreamSpec; - if (!fileStreamSpec->Open(Path)) + Path = filePath; + if (!fileStreamSpec->Open(us2fs(Path))) + { return GetLastError(); - stream = fileStream; + } + op.stream = fileStream; + #ifdef _SFX + IgnoreSplit = true; + #endif } /* if (callback) { UInt64 fileSize; - RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize)); - RINOK(callback->SetTotal(NULL, &fileSize)) + RINOK(op.stream->Seek(0, STREAM_SEEK_END, &fileSize)); + RINOK(op.callback->SetTotal(NULL, &fileSize)) } */ - return OpenStream(codecs, formatIndex, stream, seqStream, callback); + HRESULT res = OpenStream(op); + IgnoreSplit = false; + + #ifdef _SFX + + if (res != S_FALSE + || !fileStreamSpec + || !op.callbackSpec + || NonOpen_ErrorInfo.IsArc_After_NonOpen()) + return res; + { + if (filePath.Len() > k_ExeExt_Len + && MyStringCompareNoCase(filePath.RightPtr(k_ExeExt_Len), k_ExeExt) == 0) + { + const UString path2 = filePath.Left(filePath.Len() - k_ExeExt_Len); + FOR_VECTOR (i, op.codecs->Formats) + { + const CArcInfoEx &ai = op.codecs->Formats[i]; + if (ai.IsSplit()) + continue; + UString path3 = path2; + path3 += L"."; + path3 += ai.GetMainExt(); // "7z" for SFX. + Path = path3 + L".001"; + bool isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path)); + if (!isOk) + { + Path = path3; + isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path)); + } + if (isOk) + { + if (fileStreamSpec->Open(us2fs(Path))) + { + op.stream = fileStream; + NonOpen_ErrorInfo.ClearErrors_Full(); + if (OpenStream(op) == S_OK) + return S_OK; + } + } + } + } + } + + #endif + + return res; +} + +void CArchiveLink::KeepModeForNextOpen() +{ + for (int i = Arcs.Size() - 1; i >= 0; i--) + { + CMyComPtr keep; + Arcs[i].Archive->QueryInterface(IID_IArchiveKeepModeForNextOpen, (void **)&keep); + if (keep) + keep->KeepModeForNextOpen(); + } } HRESULT CArchiveLink::Close() { - for (int i = Arcs.Size() - 1; i >= 0; i--) + for (int i = Arcs.Size() - 1; i >= 0; i--) { - RINOK(Arcs[i].Archive->Close()); + RINOK(Arcs[i].Close()); } IsOpen = false; + // ErrorsText.Empty(); return S_OK; } void CArchiveLink::Release() { + // NonOpenErrorFormatIndex = -1; + NonOpen_ErrorInfo.ClearErrors(); + NonOpen_ArcPath.Empty(); while (!Arcs.IsEmpty()) Arcs.DeleteBack(); } -HRESULT CArchiveLink::Open( - CCodecs *codecs, - const CIntVector &formatIndices, - bool stdInMode, - IInStream *stream, - const UString &filePath, - IArchiveOpenCallback *callback) +/* +void CArchiveLink::Set_ErrorsText() +{ + FOR_VECTOR(i, Arcs) + { + const CArc &arc = Arcs[i]; + if (!arc.ErrorFlagsText.IsEmpty()) + { + if (!ErrorsText.IsEmpty()) + ErrorsText += L'\n'; + ErrorsText += GetUnicodeString(arc.ErrorFlagsText); + } + if (!arc.ErrorMessage.IsEmpty()) + { + if (!ErrorsText.IsEmpty()) + ErrorsText += L'\n'; + ErrorsText += arc.ErrorMessage; + } + + if (!arc.WarningMessage.IsEmpty()) + { + if (!ErrorsText.IsEmpty()) + ErrorsText += L'\n'; + ErrorsText += arc.WarningMessage; + } + } +} +*/ + +HRESULT CArchiveLink::Open(COpenOptions &op) { Release(); - if (formatIndices.Size() >= 32) + if (op.types->Size() >= 32) return E_NOTIMPL; - + HRESULT resSpec; for (;;) { resSpec = S_OK; - int formatIndex = -1; - if (formatIndices.Size() >= 1) + + op.openType = COpenType(); + if (op.types->Size() >= 1) { - if (Arcs.Size() >= formatIndices.Size()) - break; - formatIndex = formatIndices[formatIndices.Size() - Arcs.Size() - 1]; + COpenType latest; + if (Arcs.Size() < op.types->Size()) + latest = (*op.types)[op.types->Size() - Arcs.Size() - 1]; + else + { + latest = (*op.types)[0]; + if (!latest.Recursive) + break; + } + op.openType = latest; + } + else if (Arcs.Size() >= 32) + break; + + /* + op.formatIndex = -1; + if (op.types->Size() >= 1) + { + int latest; + if (Arcs.Size() < op.types->Size()) + latest = (*op.types)[op.types->Size() - Arcs.Size() - 1]; + else + { + latest = (*op.types)[0]; + if (latest != -2 && latest != -3) + break; + } + if (latest >= 0) + op.formatIndex = latest; + else if (latest == -1 || latest == -2) + { + // default + } + else if (latest == -3) + op.formatIndex = -2; + else + op.formatIndex = latest + 2; } else if (Arcs.Size() >= 32) break; + */ if (Arcs.IsEmpty()) { CArc arc; - arc.Path = filePath; + arc.filePath = op.filePath; + arc.Path = op.filePath; arc.SubfileIndex = (UInt32)(Int32)-1; - RINOK(arc.OpenStreamOrFile(codecs, formatIndex, stdInMode, stream, callback)); + HRESULT result = arc.OpenStreamOrFile(op); + if (result != S_OK) + { + if (result == S_FALSE) + { + NonOpen_ErrorInfo = arc.NonOpen_ErrorInfo; + // NonOpenErrorFormatIndex = arc.ErrorFormatIndex; + NonOpen_ArcPath = arc.Path; + } + return result; + } Arcs.Add(arc); continue; } - + + // PrintNumber("op.formatIndex 11", op.formatIndex); + const CArc &arc = Arcs.Back(); - - resSpec = (formatIndices.Size() == 0 ? S_OK : E_NOTIMPL); - + + if (op.types->Size() > Arcs.Size()) + resSpec = E_NOTIMPL; + UInt32 mainSubfile; { NCOM::CPropVariant prop; @@ -427,41 +2890,68 @@ HRESULT CArchiveLink::Open( break; } - + CMyComPtr getStream; if (arc.Archive->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream) != S_OK || !getStream) break; - + CMyComPtr subSeqStream; if (getStream->GetStream(mainSubfile, &subSeqStream) != S_OK || !subSeqStream) break; - + CMyComPtr subStream; if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK || !subStream) break; - + CArc arc2; RINOK(arc.GetItemPath(mainSubfile, arc2.Path)); - + + bool zerosTailIsAllowed; + RINOK(Archive_GetItemBoolProp(arc.Archive, mainSubfile, kpidZerosTailIsAllowed, zerosTailIsAllowed)); + CMyComPtr setSubArchiveName; - callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); + op.callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); if (setSubArchiveName) setSubArchiveName->SetSubArchiveName(arc2.Path); - + arc2.SubfileIndex = mainSubfile; - HRESULT result = arc2.OpenStream(codecs, formatIndex, subStream, NULL, callback); - resSpec = (formatIndices.Size() == 0 ? S_OK : S_FALSE); + + // CIntVector incl; + CIntVector excl; + + COpenOptions op2; + #ifndef _SFX + op2.props = op.props; + #endif + op2.codecs = op.codecs; + // op2.types = &incl; + op2.openType = op.openType; + op2.openType.ZerosTailIsAllowed = zerosTailIsAllowed; + op2.excludedFormats = ! + op2.stdInMode = false; + op2.stream = subStream; + op2.filePath = arc2.Path; + op2.callback = op.callback; + op2.callbackSpec = op.callbackSpec; + + + HRESULT result = arc2.OpenStream(op2); + resSpec = (op.types->Size() == 0 ? S_OK : S_FALSE); if (result == S_FALSE) + { + NonOpen_ErrorInfo = arc2.ErrorInfo; + NonOpen_ArcPath = arc2.Path; break; + } RINOK(result); RINOK(arc.GetItemMTime(mainSubfile, arc2.MTime, arc2.MTimeDefined)); Arcs.Add(arc2); } IsOpen = !Arcs.IsEmpty(); - return S_OK; + return resSpec; } -static void SetCallback(const UString &filePath, +static void SetCallback(const FString &filePath, IOpenCallbackUI *callbackUI, IArchiveOpenCallback *reOpenCallback, CMyComPtr &callback) @@ -471,19 +2961,12 @@ static void SetCallback(const UString &filePath, openCallbackSpec->Callback = callbackUI; openCallbackSpec->ReOpenCallback = reOpenCallback; - UString fullName; - int fileNamePartStartIndex; - NFile::NDirectory::MyGetFullPathName(filePath, fullName, fileNamePartStartIndex); - openCallbackSpec->Init( - fullName.Left(fileNamePartStartIndex), - fullName.Mid(fileNamePartStartIndex)); + FString dirPrefix, fileName; + NFile::NDir::GetFullPathAndSplit(filePath, dirPrefix, fileName); + openCallbackSpec->Init(dirPrefix, fileName); } -HRESULT CArchiveLink::Open2(CCodecs *codecs, - const CIntVector &formatIndices, - bool stdInMode, - IInStream *stream, - const UString &filePath, +HRESULT CArchiveLink::Open2(COpenOptions &op, IOpenCallbackUI *callbackUI) { VolumesSize = 0; @@ -491,46 +2974,237 @@ HRESULT CArchiveLink::Open2(CCodecs *codecs, CMyComPtr callback = openCallbackSpec; openCallbackSpec->Callback = callbackUI; - UString fullName, prefix, name; - if (!stream && !stdInMode) + FString prefix, name; + if (!op.stream && !op.stdInMode) { - int fileNamePartStartIndex; - if (!NFile::NDirectory::MyGetFullPathName(filePath, fullName, fileNamePartStartIndex)) - return GetLastError(); - prefix = fullName.Left(fileNamePartStartIndex); - name = fullName.Mid(fileNamePartStartIndex); + NFile::NDir::GetFullPathAndSplit(us2fs(op.filePath), prefix, name); openCallbackSpec->Init(prefix, name); } else { - openCallbackSpec->SetSubArchiveName(filePath); + openCallbackSpec->SetSubArchiveName(op.filePath); } - RINOK(Open(codecs, formatIndices, stdInMode, stream, filePath, callback)); - VolumePaths.Add(prefix + name); - for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++) - VolumePaths.Add(prefix + openCallbackSpec->FileNames[i]); - VolumesSize = openCallbackSpec->TotalSize; + op.callback = callback; + op.callbackSpec = openCallbackSpec; + RINOK(Open(op)); + // VolumePaths.Add(fs2us(prefix + name)); + + FOR_VECTOR (i, openCallbackSpec->FileNames_WasUsed) + { + if (openCallbackSpec->FileNames_WasUsed[i]) + { + VolumePaths.Add(fs2us(prefix) + openCallbackSpec->FileNames[i]); + VolumesSize += openCallbackSpec->FileSizes[i]; + } + } + // VolumesSize = openCallbackSpec->TotalSize; return S_OK; } -HRESULT CArchiveLink::ReOpen(CCodecs *codecs, const UString &filePath, - IArchiveOpenCallback *callback) +HRESULT CArc::ReOpen(const COpenOptions &op) +{ + ErrorInfo.ClearErrors(); + ErrorInfo.ErrorFormatIndex = -1; + + UInt64 fileSize = 0; + if (op.stream) + { + RINOK(op.stream->Seek(0, STREAM_SEEK_END, &fileSize)); + RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); + } + FileSize = fileSize; + + CMyComPtr stream2; + Int64 globalOffset = GetGlobalOffset(); + if (globalOffset <= 0) + stream2 = op.stream; + else + { + CTailInStream *tailStreamSpec = new CTailInStream; + stream2 = tailStreamSpec; + tailStreamSpec->Stream = op.stream; + tailStreamSpec->Offset = globalOffset; + tailStreamSpec->Init(); + RINOK(tailStreamSpec->SeekToStart()); + } + + // There are archives with embedded STUBs (like ZIP), so we must support signature scanning + // But for another archives we can use 0 here. So the code can be fixed !!! + UInt64 maxStartPosition = kMaxCheckStartPosition; + HRESULT res = Archive->Open(stream2, &maxStartPosition, op.callback); + + if (res == S_OK) + { + RINOK(ReadBasicProps(Archive, globalOffset, res)); + ArcStreamOffset = globalOffset; + if (ArcStreamOffset != 0) + InStream = op.stream; + } + return res; +} + + +HRESULT CArchiveLink::ReOpen(COpenOptions &op) { if (Arcs.Size() > 1) return E_NOTIMPL; - if (Arcs.Size() == 0) - return Open2(codecs, CIntVector(), false, NULL, filePath, 0); + CObjectVector inc; + CIntVector excl; - CMyComPtr openCallbackNew; - SetCallback(filePath, NULL, callback, openCallbackNew); + op.types = &inc; + op.excludedFormats = ! + op.stdInMode = false; + op.stream = NULL; + if (Arcs.Size() == 0) // ??? + return Open2(op, NULL); + CMyComPtr openCallbackNew; + SetCallback(us2fs(op.filePath), NULL, op.callback, openCallbackNew); CInFileStream *fileStreamSpec = new CInFileStream(true); CMyComPtr stream(fileStreamSpec); - if (!fileStreamSpec->Open(filePath)) + if (!fileStreamSpec->Open(us2fs(op.filePath))) return GetLastError(); - HRESULT res = GetArchive()->Open(stream, &kMaxCheckStartPosition, callback); + op.stream = stream; + + CArc &arc = Arcs[0]; + HRESULT res = arc.ReOpen(op); IsOpen = (res == S_OK); return res; } + +#ifndef _SFX + +bool ParseComplexSize(const wchar_t *s, UInt64 &result) +{ + result = 0; + const wchar_t *end; + UInt64 number = ConvertStringToUInt64(s, &end); + if (end == s) + return false; + if (*end == 0) + { + result = number; + return true; + } + if (end[1] != 0) + return false; + unsigned numBits; + switch (MyCharLower_Ascii(*end)) + { + case 'b': result = number; return true; + case 'k': numBits = 10; break; + case 'm': numBits = 20; break; + case 'g': numBits = 30; break; + case 't': numBits = 40; break; + default: return false; + } + if (number >= ((UInt64)1 << (64 - numBits))) + return false; + result = number << numBits; + return true; +} + +static bool ParseTypeParams(const UString &s, COpenType &type) +{ + if (s[0] == 0) + return true; + if (s[1] == 0) + { + switch ((unsigned)(Byte)s[0]) + { + case 'e': type.EachPos = true; return true; + case 'a': type.CanReturnArc = true; return true; + case 'r': type.Recursive = true; return true; + } + return false; + } + if (s[0] == 's') + { + UInt64 result; + if (!ParseComplexSize(s.Ptr(1), result)) + return false; + type.MaxStartOffset = result; + type.MaxStartOffset_Defined = true; + return true; + } + + return false; +} + +bool ParseType(CCodecs &codecs, const UString &s, COpenType &type) +{ + int pos2 = s.Find(':'); + UString name; + if (pos2 < 0) + { + name = s; + pos2 = s.Len(); + } + else + { + name = s.Left(pos2); + pos2++; + } + + int index = codecs.FindFormatForArchiveType(name); + type.Recursive = false; + + if (index < 0) + { + if (name[0] == '*') + { + if (name[1] != 0) + return false; + } + else if (name[0] == '#') + { + if (name[1] != 0) + return false; + type.CanReturnArc = false; + type.CanReturnParser = true; + } + else + return false; + } + + type.FormatIndex = index; + + for (unsigned i = pos2; i < s.Len();) + { + int next = s.Find(':', i); + if (next < 0) + next = s.Len(); + UString name = s.Mid(i, next - i); + if (name.IsEmpty()) + return false; + if (!ParseTypeParams(name, type)) + return false; + i = next + 1; + } + + return true; +} + +bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector &types) +{ + types.Clear(); + for (unsigned pos = 0; pos < s.Len();) + { + int pos2 = s.Find('.', pos); + if (pos2 < 0) + pos2 = s.Len(); + UString name = s.Mid(pos, pos2 - pos); + if (name.IsEmpty()) + return false; + COpenType type; + if (!ParseType(codecs, name, type)) + return false; + types.Add(type); + pos = pos2 + 1; + } + return true; +} + +#endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.h index 4a003ee63..f2a5ce9fe 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.h +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.h @@ -3,49 +3,309 @@ #ifndef __OPEN_ARCHIVE_H #define __OPEN_ARCHIVE_H -#include "Common/MyString.h" - -#include "Windows/FileFind.h" - -#include "../../Archive/IArchive.h" +#include "../../../Windows/PropVariant.h" #include "ArchiveOpenCallback.h" #include "LoadCodecs.h" +#include "Property.h" -HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result); -HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result); +HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw(); +HRESULT Archive_IsItem_Folder(IInArchive *arc, UInt32 index, bool &result) throw(); +HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw(); +HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw(); +HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &deleted) throw(); -struct CArc +/* +struct COptionalOpenProperties { + UString FormatName; + CObjectVector Props; +}; +*/ + +#ifdef _SFX +#define OPEN_PROPS_DECL +#else +#define OPEN_PROPS_DECL const CObjectVector *props; +// #define OPEN_PROPS_DECL , const CObjectVector *props +#endif + +struct COpenSpecFlags +{ + // bool CanReturnFull; + bool CanReturnFrontal; + bool CanReturnTail; + bool CanReturnMid; + + bool CanReturn_NonStart() const { return CanReturnTail || CanReturnMid; } + + COpenSpecFlags(): + // CanReturnFull(true), + CanReturnFrontal(false), + CanReturnTail(false), + CanReturnMid(false) + {} +}; + +struct COpenType +{ + int FormatIndex; + + COpenSpecFlags SpecForcedType; + COpenSpecFlags SpecMainType; + COpenSpecFlags SpecWrongExt; + COpenSpecFlags SpecUnknownExt; + + bool Recursive; + + bool CanReturnArc; + bool CanReturnParser; + bool EachPos; + + // bool SkipSfxStub; + // bool ExeAsUnknown; + + bool ZerosTailIsAllowed; + + bool MaxStartOffset_Defined; + UInt64 MaxStartOffset; + + const COpenSpecFlags &GetSpec(bool isForced, bool isMain, bool isUnknown) const + { + return isForced ? SpecForcedType : (isMain ? SpecMainType : (isUnknown ? SpecUnknownExt : SpecWrongExt)); + } + + COpenType(): + FormatIndex(-1), + Recursive(true), + CanReturnArc(true), + CanReturnParser(false), + EachPos(false), + // SkipSfxStub(true), + // ExeAsUnknown(true), + ZerosTailIsAllowed(false), + MaxStartOffset_Defined(false), + MaxStartOffset(0) + { + SpecForcedType.CanReturnFrontal = true; + SpecForcedType.CanReturnTail = true; + SpecForcedType.CanReturnMid = true; + + SpecMainType.CanReturnFrontal = true; + + SpecUnknownExt.CanReturnTail = true; // for sfx + SpecUnknownExt.CanReturnMid = true; + SpecUnknownExt.CanReturnFrontal = true; // for alt streams of sfx with pad + + // ZerosTailIsAllowed = true; + } +}; + +struct COpenOptions +{ + CCodecs *codecs; + COpenType openType; + const CObjectVector *types; + const CIntVector *excludedFormats; + + IInStream *stream; + ISequentialInStream *seqStream; + IArchiveOpenCallback *callback; + COpenCallbackImp *callbackSpec; + OPEN_PROPS_DECL + // bool openOnlySpecifiedByExtension, + + bool stdInMode; + UString filePath; + + COpenOptions(): + codecs(NULL), + types(NULL), + excludedFormats(NULL), + stream(NULL), + seqStream(NULL), + callback(NULL), + callbackSpec(NULL), + stdInMode(false) + {} + +}; + +UInt32 GetOpenArcErrorFlags(const NWindows::NCOM::CPropVariant &prop, bool *isDefinedProp = NULL); + +struct CArcErrorInfo +{ + bool ThereIsTail; + bool UnexpecedEnd; + bool IgnoreTail; // all are zeros + // bool NonZerosTail; + bool ErrorFlags_Defined; + UInt32 ErrorFlags; + UInt32 WarningFlags; + int ErrorFormatIndex; // - 1 means no Error. + // if FormatIndex == ErrorFormatIndex, the archive is open with offset + UInt64 TailSize; + + /* if CArc is Open OK with some format: + - ErrorFormatIndex shows error format index, if extension is incorrect + - other variables show message and warnings of archive that is open */ + + UString ErrorMessage; + UString WarningMessage; + + // call IsArc_After_NonOpen only if Open returns S_FALSE + bool IsArc_After_NonOpen() const + { + return (ErrorFlags_Defined && (ErrorFlags & kpv_ErrorFlags_IsNotArc) == 0); + } + + + CArcErrorInfo(): + ThereIsTail(false), + UnexpecedEnd(false), + IgnoreTail(false), + // NonZerosTail(false), + ErrorFlags_Defined(false), + ErrorFlags(0), + WarningFlags(0), + ErrorFormatIndex(-1), + TailSize(0) + {} + + void ClearErrors(); + + void ClearErrors_Full() + { + ErrorFormatIndex = -1; + ClearErrors(); + } + + bool IsThereErrorOrWarning() const + { + return ErrorFlags != 0 + || WarningFlags != 0 + || NeedTailWarning() + || UnexpecedEnd + || !ErrorMessage.IsEmpty() + || !WarningMessage.IsEmpty(); + } + + bool AreThereErrors() const { return ErrorFlags != 0 || UnexpecedEnd; } + bool AreThereWarnings() const { return WarningFlags != 0 || NeedTailWarning(); } + + bool NeedTailWarning() const { return !IgnoreTail && ThereIsTail; } + + UInt32 GetWarningFlags() const + { + UInt32 a = WarningFlags; + if (NeedTailWarning() && (ErrorFlags & kpv_ErrorFlags_DataAfterEnd) == 0) + a |= kpv_ErrorFlags_DataAfterEnd; + return a; + } + + UInt32 GetErrorFlags() const + { + UInt32 a = ErrorFlags; + if (UnexpecedEnd) + a |= kpv_ErrorFlags_UnexpectedEnd; + return a; + } +}; + +class CArc +{ + HRESULT PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr &archive); + HRESULT CheckZerosTail(const COpenOptions &op, UInt64 offset); + HRESULT OpenStream2(const COpenOptions &options); + +public: CMyComPtr Archive; + CMyComPtr InStream; + // we use InStream in 2 cases (ArcStreamOffset != 0): + // 1) if we use additional cache stream + // 2) we reopen sfx archive with CTailInStream + + CMyComPtr GetRawProps; + CMyComPtr GetRootProps; + + CArcErrorInfo ErrorInfo; // for OK archives + CArcErrorInfo NonOpen_ErrorInfo; // ErrorInfo for mainArchive (false OPEN) + UString Path; + UString filePath; UString DefaultName; - int FormatIndex; + int FormatIndex; // - 1 means Parser. int SubfileIndex; FILETIME MTime; bool MTimeDefined; - UString ErrorMessage; - CArc(): MTimeDefined(false) {} + Int64 Offset; // it's offset of start of archive inside stream that is open by Archive Handler + UInt64 PhySize; + // UInt64 OkPhySize; + bool PhySizeDefined; + // bool OkPhySize_Defined; + UInt64 FileSize; + UInt64 AvailPhySize; // PhySize, but it's reduced if exceed end of file + // bool offsetDefined; + + UInt64 ArcStreamOffset; // offset of stream that is open by Archive Handler + Int64 GetGlobalOffset() const { return ArcStreamOffset + Offset; } // it's global offset of archive + + // AString ErrorFlagsText; + + bool IsParseArc; + + bool IsTree; + + bool Ask_Deleted; + bool Ask_AltStream; + bool Ask_Aux; + bool Ask_INode; + + bool IgnoreSplit; // don't try split handler + + // void Set_ErrorFlagsText(); + + CArc(): + MTimeDefined(false), + IsTree(false), + Ask_Deleted(false), + Ask_AltStream(false), + Ask_Aux(false), + Ask_INode(false), + IgnoreSplit(false) + {} + + HRESULT ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes); + + // ~CArc(); + + HRESULT Close() + { + InStream.Release(); + return Archive->Close(); + } + + // AltStream's name is concatenated with base file name in one string in parts.Back() + HRESULT GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const; HRESULT GetItemPath(UInt32 index, UString &result) const; + + // GetItemPath2 adds [DELETED] dir prefix for deleted items. + HRESULT GetItemPath2(UInt32 index, UString &result) const; + + HRESULT GetItemSize(UInt32 index, UInt64 &size, bool &defined) const; HRESULT GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const; HRESULT IsItemAnti(UInt32 index, bool &result) const - { return GetArchiveItemBoolProp(Archive, index, kpidIsAnti, result); } - - HRESULT OpenStream( - CCodecs *codecs, - int formatIndex, - IInStream *stream, - ISequentialInStream *seqStream, - IArchiveOpenCallback *callback); - - HRESULT OpenStreamOrFile( - CCodecs *codecs, - int formatIndex, - bool stdInMode, - IInStream *stream, - IArchiveOpenCallback *callback); + { return Archive_GetItemBoolProp(Archive, index, kpidIsAnti, result); } + + + HRESULT OpenStream(const COpenOptions &options); + HRESULT OpenStreamOrFile(COpenOptions &options); + + HRESULT ReOpen(const COpenOptions &options); + + HRESULT CreateNewTailStream(CMyComPtr &stream); }; struct CArchiveLink @@ -55,33 +315,32 @@ struct CArchiveLink UInt64 VolumesSize; bool IsOpen; + // int NonOpenErrorFormatIndex; // - 1 means no Error. + UString NonOpen_ArcPath; + + CArcErrorInfo NonOpen_ErrorInfo; + + // UString ErrorsText; + // void Set_ErrorsText(); + CArchiveLink(): VolumesSize(0), IsOpen(false) {} + void KeepModeForNextOpen(); HRESULT Close(); void Release(); ~CArchiveLink() { Release(); } + const CArc *GetArc() const { return &Arcs.Back(); } IInArchive *GetArchive() const { return Arcs.Back().Archive; } + IArchiveGetRawProps *GetArchiveGetRawProps() const { return Arcs.Back().GetRawProps; } + IArchiveGetRootProps *GetArchiveGetRootProps() const { return Arcs.Back().GetRootProps; } + + HRESULT Open(COpenOptions &options); - HRESULT Open( - CCodecs *codecs, - const CIntVector &formatIndices, - bool stdInMode, - IInStream *stream, - const UString &filePath, - IArchiveOpenCallback *callback); - - HRESULT Open2( - CCodecs *codecs, - const CIntVector &formatIndices, - bool stdInMode, - IInStream *stream, - const UString &filePath, - IOpenCallbackUI *callbackUI); - - HRESULT ReOpen( - CCodecs *codecs, - const UString &filePath, - IArchiveOpenCallback *callback); + HRESULT Open2(COpenOptions &options, IOpenCallbackUI *callbackUI); + + HRESULT ReOpen(COpenOptions &options); }; +bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector &types); + #endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.cpp index dacaca5f9..5ba8c7a89 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.cpp +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.cpp @@ -2,33 +2,29 @@ #include "StdAfx.h" -#include "Common/IntToString.h" +#include "../../../../C/CpuArch.h" -#include "Windows/FileFind.h" -#include "Windows/PropVariantConversions.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/FileFind.h" +#include "../../../Windows/FileIO.h" +#include "../../../Windows/PropVariantConv.h" #include "../../PropID.h" #include "PropIDUtils.h" -using namespace NWindows; +#define Get16(x) GetUi16(x) +#define Get32(x) GetUi32(x) -void ConvertUInt32ToHex(UInt32 value, wchar_t *s) -{ - for (int i = 0; i < 8; i++) - { - int t = value & 0xF; - value >>= 4; - s[7 - i] = (wchar_t)((t < 10) ? (L'0' + t) : (L'A' + (t - 10))); - } - s[8] = L'\0'; -} +using namespace NWindows; -static const char g_WinAttrib[17] = "RHS8DAdNTsrCOnE_"; +static const char g_WinAttribChars[16 + 1] = "RHS8DAdNTsLCOnE_"; /* 0 READONLY 1 HIDDEN -3 SYSTEM +2 SYSTEM 4 DIRECTORY 5 ARCHIVE @@ -45,46 +41,45 @@ static const char g_WinAttrib[17] = "RHS8DAdNTsrCOnE_"; 16 VIRTUAL */ +void ConvertWinAttribToString(char *s, UInt32 wa) +{ + for (int i = 0; i < 16; i++) + if ((wa & (1 << i)) && i != 7) + *s++ = g_WinAttribChars[i]; + *s = 0; +} + 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'-'; +#define MY_ATTR_CHAR(a, n, c) ((a) & (1 << (n))) ? c : '-'; -UString ConvertPropertyToString(const PROPVARIANT &prop, PROPID propID, bool full) +void ConvertPropertyToShortString(char *dest, const PROPVARIANT &prop, PROPID propID, bool full) throw() { - switch(propID) + *dest = 0; + if (prop.vt == VT_FILETIME) + { + FILETIME localFileTime; + if ((prop.filetime.dwHighDateTime == 0 && + prop.filetime.dwLowDateTime == 0) || + !::FileTimeToLocalFileTime(&prop.filetime, &localFileTime)) + return; + ConvertFileTimeToString(localFileTime, dest, true, full); + return; + } + switch (propID) { - case kpidCTime: - case kpidATime: - case kpidMTime: - { - if (prop.vt != VT_FILETIME) - break; - FILETIME localFileTime; - if ((prop.filetime.dwHighDateTime == 0 && - prop.filetime.dwLowDateTime == 0) || - !::FileTimeToLocalFileTime(&prop.filetime, &localFileTime)) - return UString(); - return ConvertFileTimeToString(localFileTime, true, full); - } case kpidCRC: { if (prop.vt != VT_UI4) break; - wchar_t temp[12]; - ConvertUInt32ToHex(prop.ulVal, temp); - return temp; + ConvertUInt32ToHex8Digits(prop.ulVal, dest); + return; } case kpidAttrib: { if (prop.vt != VT_UI4) break; - UInt32 a = prop.ulVal; - wchar_t sz[32]; - int pos = 0; - for (int i = 0; i < 16; i++) - if (a & (1 << i) && i != 7) - sz[pos++] = g_WinAttrib[i]; - sz[pos] = '\0'; - return sz; + ConvertWinAttribToString(dest, prop.ulVal); + return; } case kpidPosixAttrib: { @@ -92,29 +87,469 @@ UString ConvertPropertyToString(const PROPVARIANT &prop, PROPID propID, bool ful break; UString res; UInt32 a = prop.ulVal; - wchar_t temp[16]; - temp[0] = kPosixTypes[(a >> 12) & 0xF]; + dest[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'); + dest[7 - i] = MY_ATTR_CHAR(a, i + 2, 'r'); + dest[8 - i] = MY_ATTR_CHAR(a, i + 1, 'w'); + dest[9 - i] = MY_ATTR_CHAR(a, i + 0, '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; + if ((a & 0x800) != 0) dest[3] = ((a & (1 << 6)) ? 's' : 'S'); + if ((a & 0x400) != 0) dest[6] = ((a & (1 << 3)) ? 's' : 'S'); + if ((a & 0x200) != 0) dest[9] = ((a & (1 << 0)) ? 't' : 'T'); + dest[10] = 0; a &= ~(UInt32)0xFFFF; if (a != 0) { - ConvertUInt32ToHex(a, temp); - res = UString(temp) + L' ' + res; + dest[10] = ' '; + ConvertUInt32ToHex8Digits(a, dest + 11); + } + return; + } + case kpidINode: + { + if (prop.vt != VT_UI8) + break; + ConvertUInt32ToString((UInt32)(prop.uhVal.QuadPart >> 48), dest); + dest += strlen(dest); + *dest++ = '-'; + UInt64 low = prop.uhVal.QuadPart & (((UInt64)1 << 48) - 1); + ConvertUInt64ToString(low, dest); + return; + } + case kpidVa: + { + UInt64 v = 0; + if (ConvertPropVariantToUInt64(prop, v)) + { + dest[0] = '0'; + dest[1] = 'x'; + ConvertUInt64ToHex(prop.ulVal, dest + 2); + return; + } + break; + } + } + ConvertPropVariantToShortString(prop, dest); +} + +void ConvertPropertyToString(UString &dest, const PROPVARIANT &prop, PROPID propID, bool full) +{ + if (prop.vt == VT_BSTR) + { + dest = prop.bstrVal; + return; + } + char temp[64]; + ConvertPropertyToShortString(temp, prop, propID, full); + int len = MyStringLen(temp); + wchar_t *str = dest.GetBuffer(len); + for (int i = 0; i < len; i++) + str[i] = temp[i]; + dest.ReleaseBuffer(len); +} + +static inline char GetHex(Byte value) +{ + return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} + +#ifndef _SFX + +static inline void AddHexToString(AString &res, Byte value) +{ + res += GetHex((Byte)(value >> 4)); + res += GetHex((Byte)(value & 0xF)); + res += ' '; +} + +/* +static AString Data_To_Hex(const Byte *data, size_t size) +{ + AString s; + for (size_t i = 0; i < size; i++) + AddHexToString(s, data[i]); + return s; +} +*/ + +static const char *sidNames[] = +{ + "0", + "Dialup", + "Network", + "Batch", + "Interactive", + "Logon", // S-1-5-5-X-Y + "Service", + "Anonymous", + "Proxy", + "EnterpriseDC", + "Self", + "AuthenticatedUsers", + "RestrictedCode", + "TerminalServer", + "RemoteInteractiveLogon", + "ThisOrganization", + "16", + "IUserIIS", + "LocalSystem", + "LocalService", + "NetworkService", + "Domains" +}; + +struct CSecID2Name +{ + UInt32 n; + const char *sz; +}; + +const CSecID2Name sid_32_Names[] = +{ + { 544, "Administrators" }, + { 545, "Users" }, + { 546, "Guests" }, + { 547, "PowerUsers" }, + { 548, "AccountOperators" }, + { 549, "ServerOperators" }, + { 550, "PrintOperators" }, + { 551, "BackupOperators" }, + { 552, "Replicators" }, + { 553, "Backup Operators" }, + { 554, "PreWindows2000CompatibleAccess" }, + { 555, "RemoteDesktopUsers" }, + { 556, "NetworkConfigurationOperators" }, + { 557, "IncomingForestTrustBuilders" }, + { 558, "PerformanceMonitorUsers" }, + { 559, "PerformanceLogUsers" }, + { 560, "WindowsAuthorizationAccessGroup" }, + { 561, "TerminalServerLicenseServers" }, + { 562, "DistributedCOMUsers" }, + { 569, "CryptographicOperators" }, + { 573, "EventLogReaders" }, + { 574, "CertificateServiceDCOMAccess" } +}; + +static const CSecID2Name sid_21_Names[] = +{ + { 500, "Administrator" }, + { 501, "Guest" }, + { 502, "KRBTGT" }, + { 512, "DomainAdmins" }, + { 513, "DomainUsers" }, + { 515, "DomainComputers" }, + { 516, "DomainControllers" }, + { 517, "CertPublishers" }, + { 518, "SchemaAdmins" }, + { 519, "EnterpriseAdmins" }, + { 520, "GroupPolicyCreatorOwners" }, + { 553, "RASandIASServers" }, + { 553, "RASandIASServers" }, + { 571, "AllowedRODCPasswordReplicationGroup" }, + { 572, "DeniedRODCPasswordReplicationGroup" } +}; + +struct CServicesToName +{ + UInt32 n[5]; + const char *sz; +}; + +static const CServicesToName services_to_name[] = +{ + { { 0x38FB89B5, 0xCBC28419, 0x6D236C5C, 0x6E770057, 0x876402C0 } , "TrustedInstaller" } +}; + +static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize) +{ + sidSize = 0; + if (lim < 8) + { + s += "ERROR"; + return; + } + UInt32 rev = p[0]; + if (rev != 1) + { + s += "UNSUPPORTED"; + return; + } + UInt32 num = p[1]; + if (8 + num * 4 > lim) + { + s += "ERROR"; + return; + } + sidSize = 8 + num * 4; + UInt32 authority = GetBe32(p + 4); + + if (p[2] == 0 && p[3] == 0 && authority == 5 && num >= 1) + { + UInt32 v0 = Get32(p + 8); + if (v0 < ARRAY_SIZE(sidNames)) + { + s += sidNames[v0]; + return; + } + if (v0 == 32 && num == 2) + { + UInt32 v1 = Get32(p + 12); + for (int i = 0; i < ARRAY_SIZE(sid_32_Names); i++) + if (sid_32_Names[i].n == v1) + { + s += sid_32_Names[i].sz; + return; + } + } + if (v0 == 21 && num == 5) + { + UInt32 v4 = Get32(p + 8 + 4 * 4); + for (int i = 0; i < ARRAY_SIZE(sid_21_Names); i++) + if (sid_21_Names[i].n == v4) + { + s += sid_21_Names[i].sz; + return; + } + } + if (v0 == 80 && num == 6) + { + for (int i = 0; i < ARRAY_SIZE(services_to_name); i++) + { + const CServicesToName &sn = services_to_name[i]; + int j; + for (j = 0; j < 5 && sn.n[j] == Get32(p + 8 + 4 + j * 4); j++); + if (j == 5) + { + s += sn.sz; + return; + } } - return res; } } - return ConvertPropVariantToString(prop); + + char sz[16]; + s += "S-1-"; + if (p[2] == 0 && p[3] == 0) + { + ConvertUInt32ToString(authority, sz); + s += sz; + } + else + { + s += "0x"; + for (int i = 2; i < 8; i++) + AddHexToString(s, p[i]); + } + for (UInt32 i = 0; i < num; i++) + { + s += '-'; + ConvertUInt32ToString(Get32(p + 8 + i * 4), sz); + s += sz; + } +} + +static void ParseOwner(AString &s, const Byte *p, UInt32 size, UInt32 pos) +{ + if (pos > size) + { + s += "ERROR"; + return; + } + UInt32 sidSize = 0; + ParseSid(s, p + pos, size - pos, sidSize); +} + +static void AddUInt32ToString(AString &s, UInt32 val) +{ + char sz[16]; + ConvertUInt32ToString(val, sz); + s += sz; +} + +static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName, UInt32 flags, UInt32 offset) +{ + UInt32 control = Get16(p + 2); + if ((flags & control) == 0) + return; + UInt32 pos = Get32(p + offset); + s += ' '; + s += strName; + if (pos >= size) + return; + p += pos; + size -= pos; + if (size < 8) + return; + if (Get16(p) != 2) // revision + return; + // UInt32 aclSize = Get16(p + 2); + UInt32 num = Get32(p + 4); + AddUInt32ToString(s, num); + /* + if (num >= (1 << 16)) + return; + if (aclSize > size) + return; + size = aclSize; + size -= 8; + p += 8; + for (UInt32 i = 0 ; i < num; i++) + { + if (size <= 8) + return; + // Byte type = p[0]; + // Byte flags = p[1]; + // UInt32 aceSize = Get16(p + 2); + // UInt32 mask = Get32(p + 4); + p += 8; + size -= 8; + + UInt32 sidSize = 0; + s += ' '; + s += ParseSid(p, size, sidSize); + if (sidSize == 0) + return; + p += sidSize; + size -= sidSize; + } + if (size != 0) + s += " ERROR"; + */ +} + +#define MY_SE_OWNER_DEFAULTED (0x0001) +#define MY_SE_GROUP_DEFAULTED (0x0002) +#define MY_SE_DACL_PRESENT (0x0004) +#define MY_SE_DACL_DEFAULTED (0x0008) +#define MY_SE_SACL_PRESENT (0x0010) +#define MY_SE_SACL_DEFAULTED (0x0020) +#define MY_SE_DACL_AUTO_INHERIT_REQ (0x0100) +#define MY_SE_SACL_AUTO_INHERIT_REQ (0x0200) +#define MY_SE_DACL_AUTO_INHERITED (0x0400) +#define MY_SE_SACL_AUTO_INHERITED (0x0800) +#define MY_SE_DACL_PROTECTED (0x1000) +#define MY_SE_SACL_PROTECTED (0x2000) +#define MY_SE_RM_CONTROL_VALID (0x4000) +#define MY_SE_SELF_RELATIVE (0x8000) + +void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s) +{ + s.Empty(); + if (size < 20 || size > (1 << 18)) + { + s += "ERROR"; + return; + } + if (Get16(data) != 1) // revision + { + s += "UNSUPPORTED"; + return; + } + ParseOwner(s, data, size, Get32(data + 4)); + s += ' '; + ParseOwner(s, data, size, Get32(data + 8)); + ParseAcl(s, data, size, "s:", MY_SE_SACL_PRESENT, 12); + ParseAcl(s, data, size, "d:", MY_SE_DACL_PRESENT, 16); + s += ' '; + AddUInt32ToString(s, size); + // s += '\n'; + // s += Data_To_Hex(data, size); +} + +#ifdef _WIN32 + +static bool CheckSid(const Byte *data, UInt32 size, UInt32 pos) +{ + if (pos >= size) + return false; + size -= pos; + if (size < 8) + return false; + UInt32 rev = data[pos]; + if (rev != 1) + return false; + UInt32 num = data[pos + 1]; + return (8 + num * 4 <= size); +} + +static bool CheckAcl(const Byte *p, UInt32 size, UInt32 flags, UInt32 offset) +{ + UInt32 control = Get16(p + 2); + if ((flags & control) == 0) + return true; + UInt32 pos = Get32(p + offset); + if (pos >= size) + return false; + p += pos; + size -= pos; + if (size < 8) + return false; + UInt32 aclSize = Get16(p + 2); + return (aclSize <= size); +} + +bool CheckNtSecure(const Byte *data, UInt32 size) +{ + if (size < 20) + return false; + if (Get16(data) != 1) // revision + return true; // windows function can handle such error, so we allow it + if (size > (1 << 18)) + return false; + if (!CheckSid(data, size, Get32(data + 4))) return false; + if (!CheckSid(data, size, Get32(data + 8))) return false; + if (!CheckAcl(data, size, MY_SE_SACL_PRESENT, 12)) return false; + if (!CheckAcl(data, size, MY_SE_DACL_PRESENT, 16)) return false; + return true; +} + +#endif + +#ifdef _WIN32 +bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s) +{ + s.Empty(); + NFile::CReparseAttr attr; + if (attr.Parse(data, size)) + { + if (!attr.IsSymLink()) + s += L"Junction: "; + s += attr.GetPath(); + if (!attr.IsOkNamePair()) + { + s += L" : "; + s += attr.PrintName; + } + return true; + } + + if (size < 8) + return false; + UInt32 tag = Get32(data); + UInt32 len = Get16(data + 4); + if (len + 8 > size) + return false; + if (Get16(data + 6) != 0) // padding + return false; + + char hex[16]; + ConvertUInt32ToHex8Digits(tag, hex); + s.AddAsciiStr(hex); + s += L' '; + + data += 8; + + for (UInt32 i = 0; i < len; i++) + { + Byte b = ((const Byte *)data)[i]; + s += (wchar_t)GetHex((Byte)((b >> 4) & 0xF)); + s += (wchar_t)GetHex((Byte)(b & 0xF)); + } + return true; } +#endif + +#endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.h index ca14d091d..3ee2981de 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.h +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.h @@ -3,10 +3,15 @@ #ifndef __PROPID_UTILS_H #define __PROPID_UTILS_H -#include "Common/MyString.h" -#include "Common/Types.h" +#include "../../../Common/MyString.h" -void ConvertUInt32ToHex(UInt32 value, wchar_t *s); -UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full = true); +// provide at least 64 bytes for buffer including zero-end +void ConvertPropertyToShortString(char *dest, const PROPVARIANT &propVariant, PROPID propID, bool full = true) throw(); +void ConvertPropertyToString(UString &dest, const PROPVARIANT &propVariant, PROPID propID, bool full = true); + +bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s); +void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s); +bool CheckNtSecure(const Byte *data, UInt32 size); +void ConvertWinAttribToString(char *s, UInt32 wa); #endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Property.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/Property.h index 9fd340cbc..8b57a2a64 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/Property.h +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/Property.h @@ -1,9 +1,9 @@ // Property.h -#ifndef __PROPERTY_H -#define __PROPERTY_H +#ifndef __7Z_PROPERTY_H +#define __7Z_PROPERTY_H -#include "Common/MyString.h" +#include "../../../Common/MyString.h" struct CProperty { diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/SetProperties.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/SetProperties.cpp index 4827f2a78..64b9d92a6 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/SetProperties.cpp +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/SetProperties.cpp @@ -2,25 +2,26 @@ #include "StdAfx.h" -#include "SetProperties.h" +#include "../../../Common/MyCom.h" +#include "../../../Common/MyString.h" +#include "../../../Common/StringToInt.h" -#include "Windows/PropVariant.h" -#include "Common/MyString.h" -#include "Common/StringToInt.h" -#include "Common/MyCom.h" +#include "../../../Windows/PropVariant.h" #include "../../Archive/IArchive.h" +#include "SetProperties.h" + using namespace NWindows; using namespace NCOM; static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop) { - const wchar_t *endPtr; - UInt64 result = ConvertStringToUInt64(s, &endPtr); - if (endPtr - (const wchar_t *)s != s.Length()) + const wchar_t *end; + UInt64 result = ConvertStringToUInt64(s, &end); + if (*end != 0 || s.IsEmpty()) prop = s; - else if (result <= 0xFFFFFFFF) + else if (result <= (UInt32)0xFFFFFFFF) prop = (UInt32)result; else prop = result; @@ -39,8 +40,8 @@ HRESULT SetProperties(IUnknown *unknown, const CObjectVector &propert CPropVariant *values = new CPropVariant[properties.Size()]; try { - int i; - for(i = 0; i < properties.Size(); i++) + unsigned i; + for (i = 0; i < properties.Size(); i++) { const CProperty &property = properties[i]; NCOM::CPropVariant propVariant; @@ -49,13 +50,13 @@ HRESULT SetProperties(IUnknown *unknown, const CObjectVector &propert { if (!name.IsEmpty()) { - wchar_t c = name[name.Length() - 1]; + wchar_t c = name.Back(); if (c == L'-') propVariant = false; else if (c == L'+') propVariant = true; if (propVariant.vt != VT_EMPTY) - name = name.Left(name.Length() - 1); + name.DeleteBack(); } } else @@ -64,9 +65,9 @@ HRESULT SetProperties(IUnknown *unknown, const CObjectVector &propert values[i] = propVariant; } CRecordVector names; - for(i = 0; i < realNames.Size(); i++) + for (i = 0; i < realNames.Size(); i++) names.Add((const wchar_t *)realNames[i]); - + RINOK(setProperties->SetProperties(&names.Front(), values, names.Size())); } catch(...) diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.cpp index 061e77730..b7e422a29 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.cpp +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.cpp @@ -2,21 +2,22 @@ #include "StdAfx.h" +#include "../../../Common/Wildcard.h" + #include "SortUtils.h" -#include "Common/Wildcard.h" -static int CompareStrings(const int *p1, const int *p2, void *param) +static int CompareStrings(const unsigned *p1, const unsigned *p2, void *param) { const UStringVector &strings = *(const UStringVector *)param; return CompareFileNames(strings[*p1], strings[*p2]); } -void SortFileNames(const UStringVector &strings, CIntVector &indices) +void SortFileNames(const UStringVector &strings, CUIntVector &indices) { - indices.Clear(); - int numItems = strings.Size(); - indices.Reserve(numItems); - for(int i = 0; i < numItems; i++) - indices.Add(i); + unsigned numItems = strings.Size(); + indices.ClearAndSetSize(numItems); + unsigned *vals = &indices[0]; + for (unsigned i = 0; i < numItems; i++) + vals[i] = i; indices.Sort(CompareStrings, (void *)&strings); } diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.h index e15224611..8e42e0682 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.h +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.h @@ -1,10 +1,10 @@ // SortUtils.h -#ifndef __SORTUTLS_H -#define __SORTUTLS_H +#ifndef __SORT_UTLS_H +#define __SORT_UTLS_H -#include "Common/MyString.h" +#include "../../../Common/MyString.h" -void SortFileNames(const UStringVector &strings, CIntVector &indices); +void SortFileNames(const UStringVector &strings, CUIntVector &indices); #endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.cpp index eeaec1802..0c13ae158 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.cpp +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.cpp @@ -2,19 +2,18 @@ #include "StdAfx.h" -#include "TempFiles.h" +#include "../../../Windows/FileDir.h" -#include "Windows/FileDir.h" -#include "Windows/FileIO.h" +#include "TempFiles.h" using namespace NWindows; using namespace NFile; void CTempFiles::Clear() { - while(!Paths.IsEmpty()) + while (!Paths.IsEmpty()) { - NDirectory::DeleteFileAlways((LPCWSTR)Paths.Back()); + NDir::DeleteFileAlways(Paths.Back()); Paths.DeleteBack(); } } diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.h index eb474a760..4099e6558 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.h +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.h @@ -1,15 +1,15 @@ // TempFiles.h -#ifndef __TEMPFILES_H -#define __TEMPFILES_H +#ifndef __TEMP_FILES_H +#define __TEMP_FILES_H -#include "Common/MyString.h" +#include "../../../Common/MyString.h" class CTempFiles { void Clear(); public: - UStringVector Paths; + FStringVector Paths; ~CTempFiles() { Clear(); } }; diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Update.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/Update.cpp index a5db3c18e..4697dca46 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/Update.cpp +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/Update.cpp @@ -4,21 +4,19 @@ #include "Update.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" -#ifdef _WIN32 -#include "Windows/DLL.h" -#endif - -#include "Windows/FileDir.h" -#include "Windows/FileFind.h" -#include "Windows/FileName.h" -#include "Windows/PropVariant.h" -#include "Windows/PropVariantConversions.h" -#include "Windows/Time.h" +#include "../../../Windows/DLL.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/PropVariantConv.h" +#include "../../../Windows/TimeUtils.h" #include "../../Common/FileStreams.h" +#include "../../Common/LimitedStreams.h" #include "../../Compress/CopyCoder.h" @@ -38,36 +36,71 @@ static const char *kUpdateIsNotSupoorted = using namespace NWindows; using namespace NCOM; using namespace NFile; +using namespace NDir; using namespace NName; -#ifdef _WIN32 -static const wchar_t *kTempFolderPrefix = L"7zE"; +static CFSTR kTempFolderPrefix = FTEXT("7zE"); + +#ifdef ENV_UNIX +FString GetModuleDirPrefix() +{ + FString s; + + const char *p7zip_home_dir = getenv("P7ZIP_HOME_DIR"); + if (p7zip_home_dir) { + return MultiByteToUnicodeString(p7zip_home_dir,CP_ACP); + } + + return FTEXT(".") FSTRING_PATH_SEPARATOR; +} #endif +static bool DeleteEmptyFolderAndEmptySubFolders(const FString &path) +{ + NFind::CFileInfo fileInfo; + FString pathPrefix = path + FCHAR_PATH_SEPARATOR; + { + NFind::CEnumerator enumerator(pathPrefix + FCHAR_ANY_MASK); + while (enumerator.Next(fileInfo)) + { + if (fileInfo.IsDir()) + if (!DeleteEmptyFolderAndEmptySubFolders(pathPrefix + fileInfo.Name)) + return false; + } + } + /* + // we don't need clear read-only for folders + if (!MySetFileAttributes(path, 0)) + return false; + */ + return RemoveDir(path); +} + + using namespace NUpdateArchive; class COutMultiVolStream: public IOutStream, public CMyUnknownImp { - int _streamIndex; // required stream + unsigned _streamIndex; // required stream UInt64 _offsetPos; // offset from start of _streamIndex index UInt64 _absPos; UInt64 _length; - struct CSubStreamInfo + struct CAltStreamInfo { COutFileStream *StreamSpec; CMyComPtr Stream; - UString Name; + FString Name; UInt64 Pos; UInt64 RealSize; }; - CObjectVector Streams; + CObjectVector Streams; public: // CMyComPtr VolumeCallback; CRecordVector Sizes; - UString Prefix; + FString Prefix; CTempFiles *TempFiles; void Init() @@ -78,6 +111,7 @@ public: _length = 0; } + bool SetMTime(const FILETIME *mTime); HRESULT Close(); MY_UNKNOWN_IMP1(IOutStream) @@ -92,12 +126,12 @@ public: HRESULT COutMultiVolStream::Close() { HRESULT res = S_OK; - for (int i = 0; i < Streams.Size(); i++) + FOR_VECTOR (i, Streams) { - CSubStreamInfo &s = Streams[i]; - if (s.StreamSpec) + COutFileStream *s = Streams[i].StreamSpec; + if (s) { - HRESULT res2 = s.StreamSpec->Close(); + HRESULT res2 = s->Close(); if (res2 != S_OK) res = res2; } @@ -105,40 +139,53 @@ HRESULT COutMultiVolStream::Close() return res; } +bool COutMultiVolStream::SetMTime(const FILETIME *mTime) +{ + bool res = true; + FOR_VECTOR (i, Streams) + { + COutFileStream *s = Streams[i].StreamSpec; + if (s) + if (!s->SetMTime(mTime)) + res = false; + } + return res; +} + STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (processedSize != NULL) *processedSize = 0; - while(size > 0) + while (size > 0) { if (_streamIndex >= Streams.Size()) { - CSubStreamInfo subStream; + CAltStreamInfo altStream; - wchar_t temp[16]; + FChar temp[16]; ConvertUInt32ToString(_streamIndex + 1, temp); - UString res = temp; - while (res.Length() < 3) - res = UString(L'0') + res; - UString name = Prefix + res; - subStream.StreamSpec = new COutFileStream; - subStream.Stream = subStream.StreamSpec; - if (!subStream.StreamSpec->Create(name, false)) + FString res = temp; + while (res.Len() < 3) + res = FString(FTEXT('0')) + res; + FString name = Prefix + res; + altStream.StreamSpec = new COutFileStream; + altStream.Stream = altStream.StreamSpec; + if (!altStream.StreamSpec->Create(name, false)) return ::GetLastError(); { // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS); TempFiles->Paths.Add(name); } - subStream.Pos = 0; - subStream.RealSize = 0; - subStream.Name = name; - Streams.Add(subStream); + altStream.Pos = 0; + altStream.RealSize = 0; + altStream.Name = name; + Streams.Add(altStream); continue; } - CSubStreamInfo &subStream = Streams[_streamIndex]; + CAltStreamInfo &altStream = Streams[_streamIndex]; - int index = _streamIndex; + unsigned index = _streamIndex; if (index >= Sizes.Size()) index = Sizes.Size() - 1; UInt64 volSize = Sizes[index]; @@ -149,29 +196,29 @@ STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr _streamIndex++; continue; } - if (_offsetPos != subStream.Pos) + if (_offsetPos != altStream.Pos) { // CMyComPtr outStream; - // RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); - RINOK(subStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); - subStream.Pos = _offsetPos; + // RINOK(altStream.Stream.QueryInterface(IID_IOutStream, &outStream)); + RINOK(altStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); + altStream.Pos = _offsetPos; } - UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - subStream.Pos); + UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - altStream.Pos); UInt32 realProcessed; - RINOK(subStream.Stream->Write(data, curSize, &realProcessed)); + RINOK(altStream.Stream->Write(data, curSize, &realProcessed)); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; - subStream.Pos += realProcessed; + altStream.Pos += realProcessed; _offsetPos += realProcessed; _absPos += realProcessed; if (_absPos > _length) _length = _absPos; - if (_offsetPos > subStream.RealSize) - subStream.RealSize = _offsetPos; + if (_offsetPos > altStream.RealSize) + altStream.RealSize = _offsetPos; if (processedSize != NULL) *processedSize += realProcessed; - if (subStream.Pos == volSize) + if (altStream.Pos == volSize) { _streamIndex++; _offsetPos = 0; @@ -187,17 +234,11 @@ STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *n { if (seekOrigin >= 3) return STG_E_INVALIDFUNCTION; - switch(seekOrigin) + switch (seekOrigin) { - case STREAM_SEEK_SET: - _absPos = offset; - break; - case STREAM_SEEK_CUR: - _absPos += offset; - break; - case STREAM_SEEK_END: - _absPos = _length + offset; - break; + case STREAM_SEEK_SET: _absPos = offset; break; + case STREAM_SEEK_CUR: _absPos += offset; break; + case STREAM_SEEK_END: _absPos = _length + offset; break; } _offsetPos = _absPos; if (newPosition != NULL) @@ -210,24 +251,24 @@ STDMETHODIMP COutMultiVolStream::SetSize(UInt64 newSize) { if (newSize < 0) return E_INVALIDARG; - int i = 0; + unsigned i = 0; while (i < Streams.Size()) { - CSubStreamInfo &subStream = Streams[i++]; - if ((UInt64)newSize < subStream.RealSize) + CAltStreamInfo &altStream = Streams[i++]; + if ((UInt64)newSize < altStream.RealSize) { - RINOK(subStream.Stream->SetSize(newSize)); - subStream.RealSize = newSize; + RINOK(altStream.Stream->SetSize(newSize)); + altStream.RealSize = newSize; break; } - newSize -= subStream.RealSize; + newSize -= altStream.RealSize; } while (i < Streams.Size()) { { - CSubStreamInfo &subStream = Streams.Back(); - subStream.Stream.Release(); - NDirectory::DeleteFileAlways(subStream.Name); + CAltStreamInfo &altStream = Streams.Back(); + altStream.Stream.Release(); + DeleteFileAlways(altStream.Name); } Streams.DeleteBack(); } @@ -237,7 +278,67 @@ STDMETHODIMP COutMultiVolStream::SetSize(UInt64 newSize) return S_OK; } -static const wchar_t *kDefaultArchiveType = L"7z"; +void CArchivePath::ParseFromPath(const UString &path, EArcNameMode mode) +{ + OriginalPath = path; + + SplitPathToParts_2(path, Prefix, Name); + + if (mode == k_ArcNameMode_Add) + return; + if (mode == k_ArcNameMode_Exact) + { + BaseExtension.Empty(); + return; + } + + int dotPos = Name.ReverseFind(L'.'); + if (dotPos < 0) + return; + if ((unsigned)dotPos == Name.Len() - 1) + { + Name.DeleteBack(); + BaseExtension.Empty(); + return; + } + const UString ext = Name.Ptr(dotPos + 1); + if (BaseExtension.IsEqualToNoCase(ext)) + { + BaseExtension = ext; + Name.DeleteFrom(dotPos); + } + else + BaseExtension.Empty(); +} + +UString CArchivePath::GetFinalPath() const +{ + UString path = GetPathWithoutExt(); + if (!BaseExtension.IsEmpty()) + path += UString(L'.') + BaseExtension; + return path; +} + +UString CArchivePath::GetFinalVolPath() const +{ + UString path = GetPathWithoutExt(); + if (!BaseExtension.IsEmpty()) + path += UString(L'.') + VolExtension; + return path; +} + +FString CArchivePath::GetTempPath() const +{ + FString path = TempPrefix + us2fs(Name); + if (!BaseExtension.IsEmpty()) + path += FString(FTEXT('.')) + us2fs(BaseExtension); + path += FTEXT(".tmp"); + path += TempPostfix; + return path; +} + +static const wchar_t *kDefaultArcType = L"7z"; +static const wchar_t *kDefaultArcExt = L"7z"; static const wchar_t *kSFXExtension = #ifdef _WIN32 L"exe"; @@ -245,40 +346,58 @@ static const wchar_t *kSFXExtension = L""; #endif -bool CUpdateOptions::Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath) +bool CUpdateOptions::InitFormatIndex(const CCodecs *codecs, + const CObjectVector &types, const UString &arcPath) { - if (formatIndices.Size() > 1) + if (types.Size() > 1) return false; - int arcTypeIndex = -1; - if (formatIndices.Size() != 0) - arcTypeIndex = formatIndices[0]; - if (arcTypeIndex >= 0) - MethodMode.FormatIndex = arcTypeIndex; + // int arcTypeIndex = -1; + if (types.Size() != 0) + { + MethodMode.Type = types[0]; + MethodMode.Type_Defined = true; + } + if (MethodMode.Type.FormatIndex < 0) + { + // MethodMode.Type = -1; + MethodMode.Type = COpenType(); + if (ArcNameMode != k_ArcNameMode_Add) + { + MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveName(arcPath); + if (MethodMode.Type.FormatIndex >= 0) + MethodMode.Type_Defined = true; + } + } + return true; +} + +bool CUpdateOptions::SetArcPath(const CCodecs *codecs, const UString &arcPath) +{ + UString typeExt; + int formatIndex = MethodMode.Type.FormatIndex; + if (formatIndex < 0) + { + typeExt = kDefaultArcExt; + } else { - MethodMode.FormatIndex = codecs->FindFormatForArchiveName(arcPath); - // It works incorrectly for update command if archive has some non-default extension! - if (MethodMode.FormatIndex < 0) - MethodMode.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArchiveType); + const CArcInfoEx &arcInfo = codecs->Formats[formatIndex]; + if (!arcInfo.UpdateEnabled) + return false; + typeExt = arcInfo.GetMainExt(); } - if (MethodMode.FormatIndex < 0) - return false; - const CArcInfoEx &arcInfo = codecs->Formats[MethodMode.FormatIndex]; - if (!arcInfo.UpdateEnabled) - return false; - UString typeExt = arcInfo.GetMainExt(); UString ext = typeExt; if (SfxMode) ext = kSFXExtension; ArchivePath.BaseExtension = ext; ArchivePath.VolExtension = typeExt; - ArchivePath.ParseFromPath(arcPath); - for (int i = 0; i < Commands.Size(); i++) + ArchivePath.ParseFromPath(arcPath, ArcNameMode); + FOR_VECTOR (i, Commands) { CUpdateArchiveCommand &uc = Commands[i]; uc.ArchivePath.BaseExtension = ext; uc.ArchivePath.VolExtension = typeExt; - uc.ArchivePath.ParseFromPath(uc.UserArchivePath); + uc.ArchivePath.ParseFromPath(uc.UserArchivePath, ArcNameMode); } return true; } @@ -288,7 +407,7 @@ struct CUpdateProduceCallbackImp: public IUpdateProduceCallback { const CObjectVector *_arcItems; IUpdateCallbackUI *_callback; - + CUpdateProduceCallbackImp(const CObjectVector *a, IUpdateCallbackUI *callback): _arcItems(a), _callback(callback) {} virtual HRESULT ShowDeleteFile(int arcIndex); @@ -300,36 +419,98 @@ HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(int arcIndex) } */ +bool CRenamePair::Prepare() +{ + if (RecursedType != NRecursedType::kNonRecursed) + return false; + if (!WildcardParsing) + return true; + return !DoesNameContainWildcard(OldName); +} + +extern bool g_CaseSensitive; + +static int CompareTwoNames(const wchar_t *s1, const wchar_t *s2) +{ + for (int i = 0;; i++) + { + wchar_t c1 = s1[i]; + wchar_t c2 = s2[i]; + if (c1 == 0 || c2 == 0) + return i; + if (c1 == c2) + continue; + if (!g_CaseSensitive && (MyCharUpper(c1) == MyCharUpper(c2))) + continue; + if (IsCharDirLimiter(c1) && IsCharDirLimiter(c2)) + continue; + return i; + } +} + +bool CRenamePair::GetNewPath(bool isFolder, const UString &src, UString &dest) const +{ + int num = CompareTwoNames(OldName, src); + if (OldName[num] == 0) + { + if (src[num] != 0 && !IsCharDirLimiter(src[num]) && num != 0 && !IsCharDirLimiter(src[num - 1])) + return false; + } + else + { + // OldName[num] != 0 + // OldName = "1\1a.txt" + // src = "1" + + if (!isFolder || + src[num] != 0 || + !IsCharDirLimiter(OldName[num]) || + OldName[num + 1] != 0) + return false; + } + dest = NewName + src.Ptr(num); + return true; +} + +static int GetReverseSlashPos(const UString &name) +{ + int slashPos = name.ReverseFind(L'/'); + #ifdef _WIN32 + int slash1Pos = name.ReverseFind(L'\\'); + slashPos = MyMax(slashPos, slash1Pos); + #endif + return slashPos; +} + static HRESULT Compress( + const CUpdateOptions &options, CCodecs *codecs, const CActionSet &actionSet, - IInArchive *archive, - const CCompressionMethodMode &compressionMethod, + const CArc *arc, CArchivePath &archivePath, const CObjectVector &arcItems, - bool shareForWrite, - bool stdInMode, - /* const UString & stdInFileName, */ - bool stdOutMode, + Byte *processedItemsStatuses, const CDirItems &dirItems, - bool sfxMode, - const UString &sfxModule, - const CRecordVector &volumesSizes, + const CDirItem *parentDirItem, CTempFiles &tempFiles, CUpdateErrorInfo &errorInfo, IUpdateCallbackUI *callback) { CMyComPtr outArchive; - if (archive != NULL) + int formatIndex = options.MethodMode.Type.FormatIndex; + if (arc) { - CMyComPtr archive2 = archive; + formatIndex = arc->FormatIndex; + if (formatIndex < 0) + return E_NOTIMPL; + CMyComPtr archive2 = arc->Archive; HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive); if (result != S_OK) throw kUpdateIsNotSupoorted; } else { - RINOK(codecs->CreateOutArchive(compressionMethod.FormatIndex, outArchive)); + RINOK(codecs->CreateOutArchive(formatIndex, outArchive)); #ifdef EXTERNAL_CODECS { @@ -344,12 +525,12 @@ static HRESULT Compress( } if (outArchive == 0) throw kUpdateIsNotSupoorted; - + NFileTimeType::EEnum fileTimeType; UInt32 value; RINOK(outArchive->GetFileTimeType(&value)); - switch(value) + switch (value) { case NFileTimeType::kWindows: case NFileTimeType::kUnix: @@ -360,8 +541,69 @@ static HRESULT Compress( return E_FAIL; } + { + const CArcInfoEx &arcInfo = codecs->Formats[formatIndex]; + if (options.AltStreams.Val && !arcInfo.Flags_AltStreams()) + return E_NOTIMPL; + if (options.NtSecurity.Val && !arcInfo.Flags_NtSecure()) + return E_NOTIMPL; + } + CRecordVector updatePairs2; + UStringVector newNames; + + if (options.RenamePairs.Size() != 0) + { + FOR_VECTOR (i, arcItems) + { + const CArcItem &ai = arcItems[i]; + bool needRename = false; + UString dest; + if (ai.Censored) + { + FOR_VECTOR (j, options.RenamePairs) + { + const CRenamePair &rp = options.RenamePairs[j]; + if (rp.GetNewPath(ai.IsDir, ai.Name, dest)) + { + needRename = true; + break; + } + if (ai.IsAltStream) + { + int colonPos = ai.Name.ReverseFind(':'); + int slashPosPos = GetReverseSlashPos(ai.Name); + if (colonPos > slashPosPos) + { + UString mainName = ai.Name.Left(colonPos); + /* + actually we must improve that code to support cases + with folder renaming like: rn arc dir1\ dir2\ + */ + if (rp.GetNewPath(false, mainName, dest)) + { + needRename = true; + dest += ':'; + dest += ai.Name.Ptr(colonPos + 1); + break; + } + } + } + } + } + CUpdatePair2 up2; + up2.SetAs_NoChangeArcItem(ai.IndexInServer); + if (needRename) + { + up2.NewProps = true; + RINOK(arc->IsItemAnti(i, up2.IsAnti)); + up2.NewNameIndex = newNames.Add(dest); + } + updatePairs2.Add(up2); + } + } + else { CRecordVector updatePairs; GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!! @@ -370,61 +612,81 @@ static HRESULT Compress( } UInt32 numFiles = 0; - for (int i = 0; i < updatePairs2.Size(); i++) + FOR_VECTOR (i, updatePairs2) if (updatePairs2[i].NewData) numFiles++; - + RINOK(callback->SetNumFiles(numFiles)); - CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr updateCallback(updateCallbackSpec); - - updateCallbackSpec->ShareForWrite = shareForWrite; - updateCallbackSpec->StdInMode = stdInMode; + + updateCallbackSpec->ShareForWrite = options.OpenShareForWrite; + updateCallbackSpec->StdInMode = options.StdInMode; updateCallbackSpec->Callback = callback; + + if (arc) + { + // we set Archive to allow to transfer GetProperty requests back to DLL. + updateCallbackSpec->Archive = arc->Archive; + updateCallbackSpec->GetRawProps = arc->GetRawProps; + updateCallbackSpec->GetRootProps = arc->GetRootProps; + } + updateCallbackSpec->DirItems = &dirItems; + updateCallbackSpec->ParentDirItem = parentDirItem; + + updateCallbackSpec->StoreNtSecurity = options.NtSecurity.Val; + updateCallbackSpec->StoreHardLinks = options.HardLinks.Val; + updateCallbackSpec->StoreSymLinks = options.SymLinks.Val; + updateCallbackSpec->ArcItems = &arcItems; updateCallbackSpec->UpdatePairs = &updatePairs2; + updateCallbackSpec->ProcessedItemsStatuses = processedItemsStatuses; + + if (options.RenamePairs.Size() != 0) + updateCallbackSpec->NewNames = &newNames; + + CMyComPtr outSeekStream; CMyComPtr outStream; - if (!stdOutMode) + if (!options.StdOutMode) { - UString resultPath; - int pos; - if (!NFile::NDirectory::MyGetFullPathName(archivePath.GetFinalPath(), resultPath, pos)) + FString dirPrefix; + if (!GetOnlyDirPrefix(us2fs(archivePath.GetFinalPath()), dirPrefix)) throw 1417161; - NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos)); + CreateComplexDir(dirPrefix); } COutFileStream *outStreamSpec = NULL; COutMultiVolStream *volStreamSpec = NULL; - if (volumesSizes.Size() == 0) + if (options.VolumesSizes.Size() == 0) { - if (stdOutMode) + if (options.StdOutMode) outStream = new CStdOutFileStream; else { outStreamSpec = new COutFileStream; - outStream = outStreamSpec; + outSeekStream = outStreamSpec; + outStream = outSeekStream; bool isOK = false; - UString realPath; + FString realPath; for (int i = 0; i < (1 << 16); i++) { if (archivePath.Temp) { if (i > 0) { - wchar_t s[16]; + FChar s[16]; ConvertUInt32ToString(i, s); archivePath.TempPostfix = s; } realPath = archivePath.GetTempPath(); } else - realPath = archivePath.GetFinalPath(); + realPath = us2fs(archivePath.GetFinalPath()); if (outStreamSpec->Create(realPath, false)) { tempFiles.Paths.Add(realPath); @@ -447,12 +709,16 @@ static HRESULT Compress( } else { - if (stdOutMode) + if (options.StdOutMode) return E_FAIL; + if (arc && arc->GetGlobalOffset() > 0) + return E_NOTIMPL; + volStreamSpec = new COutMultiVolStream; - outStream = volStreamSpec; - volStreamSpec->Sizes = volumesSizes; - volStreamSpec->Prefix = archivePath.GetFinalPath() + UString(L"."); + outSeekStream = volStreamSpec; + outStream = outSeekStream; + volStreamSpec->Sizes = options.VolumesSizes; + volStreamSpec->Prefix = us2fs(archivePath.GetFinalVolPath() + L"."); volStreamSpec->TempFiles = &tempFiles; volStreamSpec->Init(); @@ -464,29 +730,29 @@ static HRESULT Compress( */ } - RINOK(SetProperties(outArchive, compressionMethod.Properties)); + RINOK(SetProperties(outArchive, options.MethodMode.Properties)); - if (sfxMode) + if (options.SfxMode) { CInFileStream *sfxStreamSpec = new CInFileStream; CMyComPtr sfxStream(sfxStreamSpec); - if (!sfxStreamSpec->Open(sfxModule)) + if (!sfxStreamSpec->Open(options.SfxModule)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"7-Zip cannot open SFX module"; - errorInfo.FileName = sfxModule; + errorInfo.FileName = options.SfxModule; return E_FAIL; } CMyComPtr sfxOutStream; COutFileStream *outStreamSpec = NULL; - if (volumesSizes.Size() == 0) + if (options.VolumesSizes.Size() == 0) sfxOutStream = outStream; else { outStreamSpec = new COutFileStream; sfxOutStream = outStreamSpec; - UString realPath = archivePath.GetFinalPath(); + FString realPath = us2fs(archivePath.GetFinalPath()); if (!outStreamSpec->Create(realPath, false)) { errorInfo.SystemError = ::GetLastError(); @@ -502,9 +768,61 @@ static HRESULT Compress( } } - HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(), updateCallback); + CMyComPtr tailStream; + + if (options.SfxMode || !arc || arc->ArcStreamOffset == 0) + tailStream = outStream; + else + { + // Int64 globalOffset = arc->GetGlobalOffset(); + RINOK(arc->InStream->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(NCompress::CopyStream_ExactSize(arc->InStream, outStream, arc->ArcStreamOffset, NULL)); + if (options.StdOutMode) + tailStream = outStream; + else + { + CTailOutStream *tailStreamSpec = new CTailOutStream; + tailStream = tailStreamSpec; + tailStreamSpec->Stream = outSeekStream; + tailStreamSpec->Offset = arc->ArcStreamOffset; + tailStreamSpec->Init(); + } + } + + + HRESULT result = outArchive->UpdateItems(tailStream, updatePairs2.Size(), updateCallback); callback->Finilize(); RINOK(result); + + + if (options.SetArcMTime) + { + FILETIME ft; + ft.dwLowDateTime = 0; + ft.dwHighDateTime = 0; + FOR_VECTOR (i, updatePairs2) + { + CUpdatePair2 &pair2 = updatePairs2[i]; + const FILETIME *ft2 = NULL; + if (pair2.NewProps && pair2.DirIndex >= 0) + ft2 = &dirItems.Items[pair2.DirIndex].MTime; + else if (pair2.UseArcProps && pair2.ArcIndex >= 0) + ft2 = &arcItems[pair2.ArcIndex].MTime; + if (ft2) + { + if (::CompareFileTime(&ft, ft2) < 0) + ft = *ft2; + } + } + if (ft.dwLowDateTime != 0 || ft.dwHighDateTime != 0) + { + if (outStreamSpec) + outStreamSpec->SetMTime(&ft); + else if (volStreamSpec) + volStreamSpec->SetMTime(&ft);; + } + } + if (outStreamSpec) result = outStreamSpec->Close(); else if (volStreamSpec) @@ -512,7 +830,9 @@ static HRESULT Compress( return result; } -HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor, +static HRESULT EnumerateInArchiveItems( + // bool storeStreamsMode, + const NWildcard::CCensor &censor, const CArc &arc, CObjectVector &arcItems) { @@ -520,23 +840,21 @@ HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor, UInt32 numItems; IInArchive *archive = arc.Archive; RINOK(archive->GetNumberOfItems(&numItems)); - arcItems.Reserve(numItems); + arcItems.ClearAndReserve(numItems); for (UInt32 i = 0; i < numItems; i++) { CArcItem ai; RINOK(arc.GetItemPath(i, ai.Name)); - RINOK(IsArchiveItemFolder(archive, i, ai.IsDir)); - ai.Censored = censor.CheckPath(ai.Name, !ai.IsDir); + RINOK(Archive_IsItem_Folder(archive, i, ai.IsDir)); + RINOK(Archive_IsItem_AltStream(archive, i, ai.IsAltStream)); + /* + if (!storeStreamsMode && ai.IsAltStream) + continue; + */ + ai.Censored = censor.CheckPath(ai.IsAltStream, ai.Name, !ai.IsDir); RINOK(arc.GetItemMTime(i, ai.MTime, ai.MTimeDefined)); - - { - CPropVariant prop; - RINOK(archive->GetProperty(i, kpidSize, &prop)); - ai.SizeDefined = (prop.vt != VT_EMPTY); - if (ai.SizeDefined) - ai.Size = ConvertPropVariantToUInt64(prop); - } + RINOK(arc.GetItemSize(i, ai.Size, ai.SizeDefined)); { CPropVariant prop; @@ -544,7 +862,7 @@ HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor, if (prop.vt == VT_UI4) { ai.TimeType = (int)(NFileTimeType::EEnum)prop.ulVal; - switch(ai.TimeType) + switch (ai.TimeType) { case NFileTimeType::kWindows: case NFileTimeType::kUnix: @@ -557,99 +875,102 @@ HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor, } ai.IndexInServer = i; - arcItems.Add(ai); + arcItems.AddInReserved(ai); } return S_OK; } - -static HRESULT UpdateWithItemLists( - CCodecs *codecs, - CUpdateOptions &options, - IInArchive *archive, - const CObjectVector &arcItems, - CDirItems &dirItems, - CTempFiles &tempFiles, - CUpdateErrorInfo &errorInfo, - IUpdateCallbackUI2 *callback) +struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback { - for(int i = 0; i < options.Commands.Size(); i++) + IUpdateCallbackUI2 *Callback; + HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) { - CUpdateArchiveCommand &command = options.Commands[i]; - if (options.StdOutMode) - { - RINOK(callback->StartArchive(L"stdout", archive != 0)); - } - else - { - RINOK(callback->StartArchive(command.ArchivePath.GetFinalPath(), - i == 0 && options.UpdateArchiveItself && archive != 0)); - } - - RINOK(Compress( - codecs, - command.ActionSet, archive, - options.MethodMode, - command.ArchivePath, - arcItems, - options.OpenShareForWrite, - options.StdInMode, - /* options.StdInFileName, */ - options.StdOutMode, - dirItems, - options.SfxMode, options.SfxModule, - options.VolumesSizes, - tempFiles, - errorInfo, callback)); - - RINOK(callback->FinishArchive()); + return Callback->ScanProgress(numFolders, numFiles, totalSize, path, isDir); } - return S_OK; -} +}; #if defined(_WIN32) && !defined(UNDER_CE) -class CCurrentDirRestorer + +#include + +#endif + +struct CRefSortPair { - UString _path; -public: - CCurrentDirRestorer() { NFile::NDirectory::MyGetCurrentDirectory(_path); } - ~CCurrentDirRestorer() { RestoreDirectory();} - bool RestoreDirectory() { return BOOLToBool(NFile::NDirectory::MySetCurrentDirectory(_path)); } + int Len; + int Index; }; -#endif -struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } + +static int CompareRefSortPair(const CRefSortPair *a1, const CRefSortPair *a2, void *) { - IUpdateCallbackUI2 *Callback; - HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) + RINOZ(-MyCompare(a1->Len, a2->Len)); + return MyCompare(a1->Index, a2->Index); +} + +static int GetNumSlashes(const FChar *s) +{ + for (int numSlashes = 0;;) { - return Callback->ScanProgress(numFolders, numFiles, path); + FChar c = *s++; + if (c == 0) + return numSlashes; + if ( + #ifdef _WIN32 + c == FTEXT('\\') || + #endif + c == FTEXT('/')) + numSlashes++; } -}; +} #ifdef _WIN32 -typedef ULONG (FAR PASCAL MY_MAPISENDDOCUMENTS)( - ULONG_PTR ulUIParam, - LPSTR lpszDelimChar, - LPSTR lpszFilePaths, - LPSTR lpszFileNames, - ULONG ulReserved -); -typedef MY_MAPISENDDOCUMENTS FAR *MY_LPMAPISENDDOCUMENTS; +void ConvertToLongNames(NWildcard::CCensor &censor); #endif HRESULT UpdateArchive( CCodecs *codecs, - const NWildcard::CCensor &censor, + const CObjectVector &types, + const UString &cmdArcPath2, + NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateErrorInfo &errorInfo, IOpenCallbackUI *openCallback, - IUpdateCallbackUI2 *callback) + IUpdateCallbackUI2 *callback, + bool needSetPath) { if (options.StdOutMode && options.EMailMode) return E_FAIL; - if (options.VolumesSizes.Size() > 0 && (options.EMailMode || options.SfxMode)) + if (types.Size() > 1) + return E_NOTIMPL; + + bool renameMode = !options.RenamePairs.IsEmpty(); + if (renameMode) + { + if (options.Commands.Size() != 1) + return E_FAIL; + } + + if (options.DeleteAfterCompressing) + { + if (options.Commands.Size() != 1) + return E_NOTIMPL; + const CActionSet &as = options.Commands[0].ActionSet; + for (int i = 2; i < NPairState::kNumValues; i++) + if (as.StateActions[i] != NPairAction::kCompress) + return E_NOTIMPL; + } + + censor.AddPathsToCensor(options.PathMode); + #ifdef _WIN32 + ConvertToLongNames(censor); + #endif + censor.ExtendExclude(); + + + if (options.VolumesSizes.Size() > 0 && (options.EMailMode /* || options.SfxMode */)) return E_NOTIMPL; if (options.SfxMode) @@ -663,40 +984,96 @@ HRESULT UpdateArchive( errorInfo.Message = L"SFX file is not specified"; return E_FAIL; } - UString name = options.SfxModule; - #ifdef UNDER_CE - if (!NFind::DoesFileExist(name)) - #else - if (!NDirectory::MySearchPath(NULL, name, NULL, options.SfxModule)) - #endif + bool found = false; + if (options.SfxModule.Find(FCHAR_PATH_SEPARATOR) < 0) { - errorInfo.SystemError = ::GetLastError(); - errorInfo.Message = L"7-Zip cannot find specified SFX module"; - errorInfo.FileName = name; - return E_FAIL; + const FString fullName = ::GetModuleDirPrefix() + options.SfxModule; + if (NFind::DoesFileExist(fullName)) + { + options.SfxModule = fullName; + found = true; + } + } + if (!found) + { + if (!NFind::DoesFileExist(options.SfxModule)) + { + errorInfo.SystemError = ::GetLastError(); + errorInfo.Message = L"7-Zip cannot find specified SFX module"; + errorInfo.FileName = options.SfxModule; + return E_FAIL; + } } } - CArchiveLink arcLink; - const UString arcPath = options.ArchivePath.GetFinalPath(); - if (!options.ArchivePath.OriginalPath.IsEmpty()) + + if (needSetPath) { - NFind::CFileInfoW fi; - if (fi.Find(arcPath)) + if (!options.InitFormatIndex(codecs, types, cmdArcPath2) || + !options.SetArcPath(codecs, cmdArcPath2)) + return E_NOTIMPL; + } + UString arcPath = options.ArchivePath.GetFinalPath(); + + if (cmdArcPath2.IsEmpty()) + { + if (options.MethodMode.Type.FormatIndex < 0) + throw "type of archive is not specified"; + } + else + { + NFind::CFileInfo fi; + if (!fi.Find(us2fs(arcPath))) + { + if (renameMode) + throw "can't find archive";; + if (options.MethodMode.Type.FormatIndex < 0) + { + if (!options.SetArcPath(codecs, cmdArcPath2)) + return E_NOTIMPL; + } + } + else { if (fi.IsDir()) throw "there is no such archive"; + if (fi.IsDevice) + return E_NOTIMPL; if (options.VolumesSizes.Size() > 0) return E_NOTIMPL; - CIntVector formatIndices; - if (options.MethodMode.FormatIndex >= 0) - formatIndices.Add(options.MethodMode.FormatIndex); - HRESULT result = arcLink.Open2(codecs, formatIndices, false, NULL, arcPath, openCallback); + CObjectVector types; + // change it. + if (options.MethodMode.Type_Defined) + types.Add(options.MethodMode.Type); + // We need to set Properties to open archive only in some cases (WIM archives). + + CIntVector excl; + COpenOptions op; + #ifndef _SFX + op.props = &options.MethodMode.Properties; + #endif + op.codecs = codecs; + op.types = &types; + op.excludedFormats = ! + op.stdInMode = false; + op.stream = NULL; + op.filePath = arcPath; + + HRESULT result = arcLink.Open2(op, openCallback); + if (result == E_ABORT) return result; - RINOK(callback->OpenResult(arcPath, result)); + + const wchar_t *errorArcType = NULL; + if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex > 0) + errorArcType = codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name; + RINOK(callback->OpenResult(arcPath, result, errorArcType)); + /* + if (result == S_FALSE) + return E_FAIL; + */ RINOK(result); if (arcLink.VolumePaths.Size() > 1) { @@ -704,21 +1081,48 @@ HRESULT UpdateArchive( errorInfo.Message = L"Updating for multivolume archives is not implemented"; return E_NOTIMPL; } - + CArc &arc = arcLink.Arcs.Back(); arc.MTimeDefined = !fi.IsDevice; arc.MTime = fi.MTime; + + if (arc.ErrorInfo.ThereIsTail) + { + errorInfo.SystemError = (DWORD)E_NOTIMPL; + errorInfo.Message = L"There is some data block after the end of the archive"; + return E_NOTIMPL; + } + if (options.MethodMode.Type.FormatIndex < 0) + { + options.MethodMode.Type.FormatIndex = arcLink.GetArc()->FormatIndex; + if (!options.SetArcPath(codecs, cmdArcPath2)) + return E_NOTIMPL; + } } } - else + + if (options.MethodMode.Type.FormatIndex < 0) { - /* - if (archiveType.IsEmpty()) - throw "type of archive is not specified"; - */ + options.MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArcType); + if (options.MethodMode.Type.FormatIndex < 0) + return E_NOTIMPL; } + bool thereIsInArchive = arcLink.IsOpen; + if (!thereIsInArchive && renameMode) + return E_FAIL; + CDirItems dirItems; + CDirItem parentDirItem; + CDirItem *parentDirItem_Ptr = NULL; + + /* + FStringVector requestedPaths; + FStringVector *requestedPaths_Ptr = NULL; + if (options.DeleteAfterCompressing) + requestedPaths_Ptr = &requestedPaths; + */ + if (options.StdInMode) { CDirItem di; @@ -732,7 +1136,8 @@ HRESULT UpdateArchive( else { bool needScanning = false; - for(int i = 0; i < options.Commands.Size(); i++) + if (!renameMode) + FOR_VECTOR (i, options.Commands) if (options.Commands[i].ActionSet.NeedScanning()) needScanning = true; if (needScanning) @@ -740,12 +1145,21 @@ HRESULT UpdateArchive( CEnumDirItemUpdateCallback enumCallback; enumCallback.Callback = callback; RINOK(callback->StartScanning()); - UStringVector errorPaths; - CRecordVector errorCodes; - HRESULT res = EnumerateItems(censor, dirItems, &enumCallback, errorPaths, errorCodes); - for (int i = 0; i < errorPaths.Size(); i++) + + dirItems.SymLinks = options.SymLinks.Val; + + #if defined(_WIN32) && !defined(UNDER_CE) + dirItems.ReadSecure = options.NtSecurity.Val; + #endif + + dirItems.ScanAltStreams = options.AltStreams.Val; + HRESULT res = EnumerateItems(censor, + options.PathMode, + options.AddPathPrefix, + dirItems, &enumCallback); + FOR_VECTOR (i, dirItems.ErrorPaths) { - RINOK(callback->CanNotFindError(errorPaths[i], errorCodes[i])); + RINOK(callback->CanNotFindError(fs2us(dirItems.ErrorPaths[i]), dirItems.ErrorCodes[i])); } if (res != S_OK) { @@ -754,14 +1168,46 @@ HRESULT UpdateArchive( return res; } RINOK(callback->FinishScanning()); + + if (censor.Pairs.Size() == 1) + { + NFind::CFileInfo fi; + FString prefix = us2fs(censor.Pairs[0].Prefix) + FTEXT("."); + // UString prefix = censor.Pairs[0].Prefix; + /* + if (prefix.Back() == WCHAR_PATH_SEPARATOR) + { + prefix.DeleteBack(); + } + */ + if (fi.Find(prefix)) + if (fi.IsDir()) + { + parentDirItem.Size = fi.Size; + parentDirItem.CTime = fi.CTime; + parentDirItem.ATime = fi.ATime; + parentDirItem.MTime = fi.MTime; + parentDirItem.Attrib = fi.Attrib; + parentDirItem_Ptr = &parentDirItem; + + int secureIndex = -1; + #if defined(_WIN32) && !defined(UNDER_CE) + if (options.NtSecurity.Val) + dirItems.AddSecurityItem(prefix, secureIndex); + #endif + parentDirItem.SecureIndex = secureIndex; + + parentDirItem_Ptr = &parentDirItem; + } + } } } - UString tempDirPrefix; + FString tempDirPrefix; bool usesTempDir = false; - + #ifdef _WIN32 - NDirectory::CTempDirectoryW tempDirectory; + CTempDir tempDirectory; if (options.EMailMode && options.EMailRemoveAfter) { tempDirectory.Create(kTempFolderPrefix); @@ -775,8 +1221,6 @@ HRESULT UpdateArchive( bool createTempFile = false; - bool thereIsInArchive = arcLink.IsOpen; - if (!options.StdOutMode && options.UpdateArchiveItself) { CArchivePath &ap = options.Commands[0].ArchivePath; @@ -787,27 +1231,28 @@ HRESULT UpdateArchive( createTempFile = true; ap.Temp = true; if (!options.WorkingDir.IsEmpty()) - { ap.TempPrefix = options.WorkingDir; - NormalizeDirPathPrefix(ap.TempPrefix); - } + else + ap.TempPrefix = us2fs(ap.Prefix); + NormalizeDirPathPrefix(ap.TempPrefix); } } - for(int i = 0; i < options.Commands.Size(); i++) + unsigned i; + for (i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; if (usesTempDir) { // Check it - ap.Prefix = tempDirPrefix; + ap.Prefix = fs2us(tempDirPrefix); // ap.Temp = true; // ap.TempPrefix = tempDirPrefix; } if (!options.StdOutMode && (i > 0 || !createTempFile)) { - const UString &path = ap.GetFinalPath(); + const FString path = us2fs(ap.GetFinalPath()); if (NFind::DoesFileOrDirExist(path)) { errorInfo.SystemError = 0; @@ -821,13 +1266,64 @@ HRESULT UpdateArchive( CObjectVector arcItems; if (thereIsInArchive) { - RINOK(EnumerateInArchiveItems(censor, arcLink.Arcs.Back(), arcItems)); + RINOK(EnumerateInArchiveItems( + // options.StoreAltStreams, + censor, arcLink.Arcs.Back(), arcItems)); + } + + /* + FStringVector processedFilePaths; + FStringVector *processedFilePaths_Ptr = NULL; + if (options.DeleteAfterCompressing) + processedFilePaths_Ptr = &processedFilePaths; + */ + + CByteBuffer processedItems; + if (options.DeleteAfterCompressing) + { + unsigned num = dirItems.Items.Size(); + processedItems.Alloc(num); + for (i = 0; i < num; i++) + processedItems[i] = 0; + } + + for (i = 0; i < options.Commands.Size(); i++) + { + const CArc *arc = thereIsInArchive ? arcLink.GetArc() : 0; + // IInArchiveExtra *archiveExtra = thereIsInArchive ? arcLink.GetArchiveExtra() : 0; + // IArchiveGetRootProps *archiveGetRootProps = thereIsInArchive ? arcLink.GetArchiveGetRootProps() : 0; + CUpdateArchiveCommand &command = options.Commands[i]; + UString name; + bool isUpdating; + if (options.StdOutMode) + { + name = L"stdout"; + isUpdating = arc != 0; + } + else + { + name = command.ArchivePath.GetFinalPath(); + isUpdating = (i == 0 && options.UpdateArchiveItself && arc != 0); + } + RINOK(callback->StartArchive(name, isUpdating)) + + RINOK(Compress(options, + codecs, + command.ActionSet, + arc, + command.ArchivePath, + arcItems, + options.DeleteAfterCompressing ? (Byte *)processedItems : NULL, + + dirItems, + parentDirItem_Ptr, + + tempFiles, + errorInfo, callback)); + + RINOK(callback->FinishArchive()); } - RINOK(UpdateWithItemLists(codecs, options, - thereIsInArchive ? arcLink.GetArchive() : 0, - arcItems, dirItems, - tempFiles, errorInfo, callback)); if (thereIsInArchive) { @@ -841,21 +1337,21 @@ HRESULT UpdateArchive( try { CArchivePath &ap = options.Commands[0].ArchivePath; - const UString &tempPath = ap.GetTempPath(); + const FString &tempPath = ap.GetTempPath(); if (thereIsInArchive) - if (!NDirectory::DeleteFileAlways(arcPath)) + if (!DeleteFileAlways(us2fs(arcPath))) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"7-Zip cannot delete the file"; - errorInfo.FileName = arcPath; + errorInfo.FileName = us2fs(arcPath); return E_FAIL; } - if (!NDirectory::MyMoveFile(tempPath, arcPath)) + if (!MyMoveFile(tempPath, us2fs(arcPath))) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"7-Zip cannot move the file"; errorInfo.FileName = tempPath; - errorInfo.FileName2 = arcPath; + errorInfo.FileName2 = us2fs(arcPath); return E_FAIL; } } @@ -865,30 +1361,42 @@ HRESULT UpdateArchive( } } + #if defined(_WIN32) && !defined(UNDER_CE) if (options.EMailMode) { NDLL::CLibrary mapiLib; - if (!mapiLib.Load(TEXT("Mapi32.dll"))) + if (!mapiLib.Load(FTEXT("Mapi32.dll"))) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"7-Zip cannot load Mapi32.dll"; return E_FAIL; } - MY_LPMAPISENDDOCUMENTS fnSend = (MY_LPMAPISENDDOCUMENTS)mapiLib.GetProc("MAPISendDocuments"); + + /* + LPMAPISENDDOCUMENTS fnSend = (LPMAPISENDDOCUMENTS)mapiLib.GetProc("MAPISendDocuments"); if (fnSend == 0) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"7-Zip cannot find MAPISendDocuments function"; return E_FAIL; } - UStringVector fullPaths; - int i; - for(i = 0; i < options.Commands.Size(); i++) + */ + LPMAPISENDMAIL sendMail = (LPMAPISENDMAIL)mapiLib.GetProc("MAPISendMail"); + if (sendMail == 0) + { + errorInfo.SystemError = ::GetLastError(); + errorInfo.Message = L"7-Zip cannot find MAPISendMail function"; + return E_FAIL; + } + + FStringVector fullPaths; + unsigned i; + for (i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; - UString arcPath; - if (!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath)) + FString arcPath; + if (!MyGetFullPathName(us2fs(ap.GetFinalPath()), arcPath)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"GetFullPathName error"; @@ -897,16 +1405,86 @@ HRESULT UpdateArchive( fullPaths.Add(arcPath); } CCurrentDirRestorer curDirRestorer; - for(i = 0; i < fullPaths.Size(); i++) + for (i = 0; i < fullPaths.Size(); i++) { - UString arcPath = fullPaths[i]; + UString arcPath = fs2us(fullPaths[i]); UString fileName = ExtractFileNameFromPath(arcPath); AString path = GetAnsiString(arcPath); AString name = GetAnsiString(fileName); // Warning!!! MAPISendDocuments function changes Current directory - fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0); + // fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0); + + MapiFileDesc f; + memset(&f, 0, sizeof(f)); + f.nPosition = 0xFFFFFFFF; + f.lpszPathName = (char *)(const char *)path; + f.lpszFileName = (char *)(const char *)name; + + MapiMessage m; + memset(&m, 0, sizeof(m)); + m.nFileCount = 1; + m.lpFiles = &f; + + const AString addr = GetAnsiString(options.EMailAddress); + MapiRecipDesc rec; + if (!addr.IsEmpty()) + { + memset(&rec, 0, sizeof(rec)); + rec.ulRecipClass = MAPI_TO; + rec.lpszAddress = (char *)(const char *)addr; + m.nRecipCount = 1; + m.lpRecips = &rec; + } + + sendMail((LHANDLE)0, 0, &m, MAPI_DIALOG, 0); } } #endif + + if (options.DeleteAfterCompressing) + { + CRecordVector pairs; + FStringVector foldersNames; + for (i = 0; i < dirItems.Items.Size(); i++) + { + const CDirItem &dirItem = dirItems.Items[i]; + FString phyPath = us2fs(dirItems.GetPhyPath(i)); + if (dirItem.IsDir()) + { + CRefSortPair pair; + pair.Index = i; + pair.Len = GetNumSlashes(phyPath); + pairs.Add(pair); + } + else + { + if (processedItems[i] != 0 || dirItem.Size == 0) + { + DeleteFileAlways(phyPath); + } + else + { + // file was skipped + /* + errorInfo.SystemError = 0; + errorInfo.Message = L"file was not processed"; + errorInfo.FileName = phyPath; + return E_FAIL; + */ + } + } + } + + pairs.Sort(CompareRefSortPair, NULL); + for (i = 0; i < pairs.Size(); i++) + { + FString phyPath = us2fs(dirItems.GetPhyPath(pairs[i].Index)); + if (NFind::DoesDirExist(phyPath)) + { + // printf("delete %S\n", phyPath); + RemoveDir(phyPath); + } + } + } return S_OK; } diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Update.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/Update.h index ade001303..b2fdb4647 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/Update.h +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/Update.h @@ -3,14 +3,22 @@ #ifndef __COMMON_UPDATE_H #define __COMMON_UPDATE_H -#include "Common/Wildcard.h" +#include "../../../Common/Wildcard.h" #include "ArchiveOpenCallback.h" #include "LoadCodecs.h" +#include "OpenArchive.h" #include "Property.h" #include "UpdateAction.h" #include "UpdateCallback.h" +enum EArcNameMode +{ + k_ArcNameMode_Smart, + k_ArcNameMode_Exact, + k_ArcNameMode_Add, +}; + struct CArchivePath { UString OriginalPath; @@ -21,57 +29,16 @@ struct CArchivePath UString VolExtension; // archive type extension for volumes bool Temp; - UString TempPrefix; // path(folder) for temp location - UString TempPostfix; + FString TempPrefix; // path(folder) for temp location + FString TempPostfix; CArchivePath(): Temp(false) {}; - - void ParseFromPath(const UString &path) - { - OriginalPath = path; - - SplitPathToParts(path, Prefix, Name); - int dotPos = Name.ReverseFind(L'.'); - if (dotPos < 0) - return; - if (dotPos == Name.Length() - 1) - { - Name = Name.Left(dotPos); - BaseExtension.Empty(); - return; - } - if (BaseExtension.CompareNoCase(Name.Mid(dotPos + 1)) == 0) - { - BaseExtension = Name.Mid(dotPos + 1); - Name = Name.Left(dotPos); - } - else - BaseExtension.Empty(); - } - - UString GetPathWithoutExt() const - { - return Prefix + Name; - } - UString GetFinalPath() const - { - UString path = GetPathWithoutExt(); - if (!BaseExtension.IsEmpty()) - path += UString(L'.') + BaseExtension; - return path; - } - - - UString GetTempPath() const - { - UString path = TempPrefix + Name; - if (!BaseExtension.IsEmpty()) - path += UString(L'.') + BaseExtension; - path += L".tmp"; - path += TempPostfix; - return path; - } + void ParseFromPath(const UString &path, EArcNameMode mode); + UString GetPathWithoutExt() const { return Prefix + Name; } + UString GetFinalPath() const; + UString GetFinalVolPath() const; + FString GetTempPath() const; }; struct CUpdateArchiveCommand @@ -83,9 +50,31 @@ struct CUpdateArchiveCommand struct CCompressionMethodMode { - int FormatIndex; + bool Type_Defined; + COpenType Type; CObjectVector Properties; - CCompressionMethodMode(): FormatIndex(-1) {} + + CCompressionMethodMode(): Type_Defined(false) {} +}; + +namespace NRecursedType { enum EEnum +{ + kRecursed, + kWildcardOnlyRecursed, + kNonRecursed +};} + +struct CRenamePair +{ + UString OldName; + UString NewName; + bool WildcardParsing; + NRecursedType::EEnum RecursedType; + + CRenamePair(): WildcardParsing(true), RecursedType(NRecursedType::kNonRecursed) {} + + bool Prepare(); + bool GetNewPath(bool isFolder, const UString &src, UString &dest) const; }; struct CUpdateOptions @@ -95,39 +84,60 @@ struct CUpdateOptions CObjectVector Commands; bool UpdateArchiveItself; CArchivePath ArchivePath; - + EArcNameMode ArcNameMode; + bool SfxMode; - UString SfxModule; - + FString SfxModule; + bool OpenShareForWrite; bool StdInMode; UString StdInFileName; bool StdOutMode; - + bool EMailMode; bool EMailRemoveAfter; UString EMailAddress; - UString WorkingDir; + FString WorkingDir; + NWildcard::ECensorPathMode PathMode; + UString AddPathPrefix; + + CBoolPair NtSecurity; + CBoolPair AltStreams; + CBoolPair HardLinks; + CBoolPair SymLinks; + + bool DeleteAfterCompressing; + + bool SetArcMTime; - bool Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath); + CObjectVector RenamePairs; + + bool InitFormatIndex(const CCodecs *codecs, const CObjectVector &types, const UString &arcPath); + bool SetArcPath(const CCodecs *codecs, const UString &arcPath); CUpdateOptions(): UpdateArchiveItself(true), + ArcNameMode(k_ArcNameMode_Smart), SfxMode(false), OpenShareForWrite(false), StdInMode(false), StdOutMode(false), EMailMode(false), - EMailRemoveAfter(false) + EMailRemoveAfter(false), + PathMode(NWildcard::k_RelatPath), + + DeleteAfterCompressing(false), + SetArcMTime(false) + {}; - void SetAddActionCommand() + void SetActionCommand_Add() { Commands.Clear(); CUpdateArchiveCommand c; - c.ActionSet = NUpdateArchive::kAddActionSet; + c.ActionSet = NUpdateArchive::k_ActionSet_Add; Commands.Add(c); } @@ -137,8 +147,8 @@ struct CUpdateOptions struct CErrorInfo { DWORD SystemError; - UString FileName; - UString FileName2; + FString FileName; + FString FileName2; UString Message; // UStringVector ErrorPaths; // CRecordVector ErrorCodes; @@ -151,9 +161,9 @@ struct CUpdateErrorInfo: public CErrorInfo #define INTERFACE_IUpdateCallbackUI2(x) \ INTERFACE_IUpdateCallbackUI(x) \ - virtual HRESULT OpenResult(const wchar_t *name, HRESULT result) x; \ + virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, const wchar_t *errorArcType) x; \ virtual HRESULT StartScanning() x; \ - virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) x; \ + virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) x; \ virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \ virtual HRESULT FinishScanning() x; \ virtual HRESULT StartArchive(const wchar_t *name, bool updating) x; \ @@ -166,10 +176,13 @@ struct IUpdateCallbackUI2: public IUpdateCallbackUI HRESULT UpdateArchive( CCodecs *codecs, - const NWildcard::CCensor &censor, + const CObjectVector &types, + const UString &cmdArcPath2, + NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateErrorInfo &errorInfo, IOpenCallbackUI *openCallback, - IUpdateCallbackUI2 *callback); + IUpdateCallbackUI2 *callback, + bool needSetPath); #endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.cpp index 879a49c57..a80db7212 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.cpp +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.cpp @@ -6,7 +6,7 @@ namespace NUpdateArchive { -const CActionSet kAddActionSet = +const CActionSet k_ActionSet_Add = {{ NPairAction::kCopy, NPairAction::kCopy, @@ -17,7 +17,7 @@ const CActionSet kAddActionSet = NPairAction::kCompress }}; -const CActionSet kUpdateActionSet = +const CActionSet k_ActionSet_Update = {{ NPairAction::kCopy, NPairAction::kCopy, @@ -28,7 +28,7 @@ const CActionSet kUpdateActionSet = NPairAction::kCompress }}; -const CActionSet kFreshActionSet = +const CActionSet k_ActionSet_Fresh = {{ NPairAction::kCopy, NPairAction::kCopy, @@ -39,7 +39,7 @@ const CActionSet kFreshActionSet = NPairAction::kCompress }}; -const CActionSet kSynchronizeActionSet = +const CActionSet k_ActionSet_Sync = {{ NPairAction::kCopy, NPairAction::kIgnore, @@ -50,7 +50,7 @@ const CActionSet kSynchronizeActionSet = NPairAction::kCompress, }}; -const CActionSet kDeleteActionSet = +const CActionSet k_ActionSet_Delete = {{ NPairAction::kCopy, NPairAction::kIgnore, diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.h index 0ac1c1080..b6645cbdd 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.h +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.h @@ -7,7 +7,7 @@ namespace NUpdateArchive { namespace NPairState { - const int kNumValues = 7; + const unsigned kNumValues = 7; enum EEnum { kNotMasked = 0, @@ -19,7 +19,7 @@ namespace NUpdateArchive { kUnknowNewerFiles }; } - + namespace NPairAction { enum EEnum @@ -30,13 +30,22 @@ namespace NUpdateArchive { kCompressAsAnti }; } - + struct CActionSet { NPairAction::EEnum StateActions[NPairState::kNumValues]; + + bool IsEqualTo(const CActionSet &a) const + { + for (unsigned i = 0; i < NPairState::kNumValues; i++) + if (StateActions[i] != a.StateActions[i]) + return false; + return true; + } + bool NeedScanning() const { - int i; + unsigned i; for (i = 0; i < NPairState::kNumValues; i++) if (StateActions[i] == NPairAction::kCompress) return true; @@ -46,12 +55,12 @@ namespace NUpdateArchive { return false; } }; - - extern const CActionSet kAddActionSet; - extern const CActionSet kUpdateActionSet; - extern const CActionSet kFreshActionSet; - extern const CActionSet kSynchronizeActionSet; - extern const CActionSet kDeleteActionSet; + + extern const CActionSet k_ActionSet_Add; + extern const CActionSet k_ActionSet_Update; + extern const CActionSet k_ActionSet_Fresh; + extern const CActionSet k_ActionSet_Sync; + extern const CActionSet k_ActionSet_Delete; } #endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.cpp index 0f229058c..609ece856 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.cpp +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.cpp @@ -2,18 +2,32 @@ #include "StdAfx.h" -#include "Common/ComTry.h" -#include "Common/Defs.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.h" +#include "../../../Common/ComTry.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/Wildcard.h" -#include "Windows/PropVariant.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/Synchronization.h" #include "../../Common/FileStreams.h" +#include "../../Common/StreamObjects.h" #include "UpdateCallback.h" +#if defined(_WIN32) && !defined(UNDER_CE) +#define _USE_SECURITY_CODE +#include "../../../Windows/SecurityUtils.h" +#endif + using namespace NWindows; +using namespace NFile; + +#ifdef _USE_SECURITY_CODE +bool InitLocalPrivileges(); +#endif CArchiveUpdateCallback::CArchiveUpdateCallback(): Callback(0), @@ -22,8 +36,19 @@ CArchiveUpdateCallback::CArchiveUpdateCallback(): DirItems(0), ArcItems(0), UpdatePairs(0), - NewNames(0) - {} + NewNames(0), + KeepOriginalItemNames(false), + ProcessedItemsStatuses(NULL), + ParentDirItem(NULL), + StoreNtSecurity(false), + StoreHardLinks(false), + StoreSymLinks(false), + _hardIndex_From((UInt32)(Int32)-1) +{ + #ifdef _USE_SECURITY_CODE + _saclEnabled = InitLocalPrivileges(); + #endif +} STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size) @@ -49,7 +74,7 @@ STDMETHODIMP CArchiveUpdateCallback::SetRatioInfo(const UInt64 *inSize, const UI /* -STATPROPSTG kProperties[] = +static const STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidIsDir, VT_BOOL}, @@ -63,7 +88,7 @@ STATPROPSTG kProperties[] = STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **) { - return CStatPropEnumerator::CreateEnumerator(kProperties, sizeof(kProperties) / sizeof(kProperties[0]), enumerator); + return CStatPropEnumerator::CreateEnumerator(kProps, ARRAY_SIZE(kProps), enumerator); } */ @@ -73,11 +98,11 @@ STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index, COM_TRY_BEGIN RINOK(Callback->CheckBreak()); const CUpdatePair2 &up = (*UpdatePairs)[index]; - if (newData != NULL) *newData = BoolToInt(up.NewData); - if (newProps != NULL) *newProps = BoolToInt(up.NewProps); - if (indexInArchive != NULL) + if (newData) *newData = BoolToInt(up.NewData); + if (newProps) *newProps = BoolToInt(up.NewProps); + if (indexInArchive) { - *indexInArchive = (UInt32)-1; + *indexInArchive = (UInt32)(Int32)-1; if (up.ExistInArchive()) *indexInArchive = (ArcItems == 0) ? up.ArcIndex : (*ArcItems)[up.ArcIndex].IndexInServer; } @@ -85,40 +110,289 @@ STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index, COM_TRY_END } -STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +STDMETHODIMP CArchiveUpdateCallback::GetRootProp(PROPID propID, PROPVARIANT *value) { - COM_TRY_BEGIN - const CUpdatePair2 &up = (*UpdatePairs)[index]; - NWindows::NCOM::CPropVariant prop; - - if (propID == kpidIsAnti) + NCOM::CPropVariant prop; + switch (propID) { - prop = up.IsAnti; - prop.Detach(value); + case kpidIsDir: prop = true; break; + case kpidAttrib: if (ParentDirItem) prop = ParentDirItem->Attrib; break; + case kpidCTime: if (ParentDirItem) prop = ParentDirItem->CTime; break; + case kpidATime: if (ParentDirItem) prop = ParentDirItem->ATime; break; + case kpidMTime: if (ParentDirItem) prop = ParentDirItem->MTime; break; + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CArchiveUpdateCallback::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType) +{ + *parentType = NParentType::kDir; + *parent = (UInt32)(Int32)-1; + return S_OK; +} + +STDMETHODIMP CArchiveUpdateCallback::GetNumRawProps(UInt32 *numProps) +{ + *numProps = 0; + if (StoreNtSecurity) + *numProps = 1; + return S_OK; +} + +STDMETHODIMP CArchiveUpdateCallback::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID) +{ + *name = NULL; + *propID = kpidNtSecure; + return S_OK; +} + +STDMETHODIMP CArchiveUpdateCallback::GetRootRawProp(PROPID + #ifdef _USE_SECURITY_CODE + propID + #endif + , const void **data, UInt32 *dataSize, UInt32 *propType) +{ + *data = 0; + *dataSize = 0; + *propType = 0; + if (!StoreNtSecurity) return S_OK; + #ifdef _USE_SECURITY_CODE + if (propID == kpidNtSecure) + { + if (StdInMode) + return S_OK; + + if (ParentDirItem) + { + if (ParentDirItem->SecureIndex < 0) + return S_OK; + const CByteBuffer &buf = DirItems->SecureBlocks.Bufs[ParentDirItem->SecureIndex]; + *data = buf; + *dataSize = (UInt32)buf.Size(); + *propType = NPropDataType::kRaw; + return S_OK; + } + + if (GetRootProps) + return GetRootProps->GetRootRawProp(propID, data, dataSize, propType); } + #endif + return S_OK; +} - if (up.IsAnti) +// #ifdef _USE_SECURITY_CODE +// #endif + +STDMETHODIMP CArchiveUpdateCallback::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) +{ + *data = 0; + *dataSize = 0; + *propType = 0; + + if (propID == kpidNtSecure || + propID == kpidNtReparse) { - switch(propID) + if (StdInMode) + return S_OK; + + const CUpdatePair2 &up = (*UpdatePairs)[index]; + if (up.UseArcProps && up.ExistInArchive() && GetRawProps) + return GetRawProps->GetRawProp( + ArcItems ? (*ArcItems)[up.ArcIndex].IndexInServer : up.ArcIndex, + propID, data, dataSize, propType); + { - case kpidIsDir: - case kpidPath: - break; - case kpidSize: - prop = (UInt64)0; + const CUpdatePair2 &up = (*UpdatePairs)[index]; + /* + if (!up.NewData) + return E_FAIL; + */ + if (up.IsAnti) + return S_OK; + + #ifndef UNDER_CE + const CDirItem &di = DirItems->Items[up.DirIndex]; + #endif + + #ifdef _USE_SECURITY_CODE + if (propID == kpidNtSecure) + { + if (!StoreNtSecurity) + return S_OK; + if (di.SecureIndex < 0) + return S_OK; + const CByteBuffer &buf = DirItems->SecureBlocks.Bufs[di.SecureIndex]; + *data = buf; + *dataSize = (UInt32)buf.Size(); + *propType = NPropDataType::kRaw; + } + else + #endif + { + // propID == kpidNtReparse + if (!StoreSymLinks) + return S_OK; + #if 0 // #ifndef UNDER_CE + const CByteBuffer *buf = &di.ReparseData2; + if (buf->Size() == 0) + buf = &di.ReparseData; + if (buf->Size() != 0) + { + *data = *buf; + *dataSize = (UInt32)buf->Size(); + *propType = NPropDataType::kRaw; + } + #endif + } + + return S_OK; + } + } + + return S_OK; +} + +#ifndef UNDER_CE + +static UString GetRelativePath(const UString &to, const UString &from) +{ + UStringVector partsTo, partsFrom; + SplitPathToParts(to, partsTo); + SplitPathToParts(from, partsFrom); + + unsigned i; + for (i = 0;; i++) + { + if (i + 1 >= partsFrom.Size() || + i + 1 >= partsTo.Size()) + break; + if (CompareFileNames(partsFrom[i], partsTo[i]) != 0) + break; + } + + if (i == 0) + { + #ifdef _WIN32 + if (NName::IsDrivePath(to) || + NName::IsDrivePath(from)) + return to; + #endif + } + + UString s; + unsigned k; + + for (k = i + 1; k < partsFrom.Size(); k++) + s += L".." WSTRING_PATH_SEPARATOR; + + for (k = i; k < partsTo.Size(); k++) + { + if (k != i) + s += WCHAR_PATH_SEPARATOR; + s += partsTo[k]; + } + + return s; +} + +#endif + +STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + const CUpdatePair2 &up = (*UpdatePairs)[index]; + NCOM::CPropVariant prop; + + if (up.NewData) + { + /* + if (propID == kpidIsHardLink) + { + prop = _isHardLink; + prop.Detach(value); + return S_OK; + } + */ + if (propID == kpidSymLink) + { + if (index == _hardIndex_From) + { + prop.Detach(value); + return S_OK; + } + if (up.DirIndex >= 0) + { + #if 0 // #ifndef UNDER_CE + const CDirItem &di = DirItems->Items[up.DirIndex]; + // if (di.IsDir()) + { + CReparseAttr attr; + if (attr.Parse(di.ReparseData, di.ReparseData.Size())) + { + UString simpleName = attr.GetPath(); + if (attr.IsRelative()) + prop = simpleName; + else + { + const UString phyPath = DirItems->GetPhyPath(up.DirIndex); + FString fullPath; + if (NDir::MyGetFullPathName(us2fs(phyPath), fullPath)) + { + prop = GetRelativePath(simpleName, fs2us(fullPath)); + } + } + prop.Detach(value); + return S_OK; + } + } + #endif + } + } + else if (propID == kpidHardLink) + { + if (index == _hardIndex_From) + { + const CKeyKeyValPair &pair = _map[_hardIndex_To]; + const CUpdatePair2 &up2 = (*UpdatePairs)[pair.Value]; + prop = DirItems->GetLogPath(up2.DirIndex); prop.Detach(value); return S_OK; - default: + } + if (up.DirIndex >= 0) + { prop.Detach(value); return S_OK; + } } } - - if (up.ExistOnDisk()) + + if (up.IsAnti + && propID != kpidIsDir + && propID != kpidPath + && propID != kpidIsAltStream) + { + switch (propID) + { + case kpidSize: prop = (UInt64)0; break; + case kpidIsAnti: prop = true; break; + } + } + else if (propID == kpidPath && up.NewNameIndex >= 0) + prop = (*NewNames)[up.NewNameIndex]; + else if (propID == kpidShortName && up.NewNameIndex >= 0 && up.IsMainRenameItem) + { + // we can generate new ShortName here; + } + else if ((up.UseArcProps + || (KeepOriginalItemNames && (propID == kpidPath || propID == kpidIsAltStream))) + && up.ExistInArchive() && Archive) + return Archive->GetProperty(ArcItems ? (*ArcItems)[up.ArcIndex].IndexInServer : up.ArcIndex, propID, value); + else if (up.ExistOnDisk()) { const CDirItem &di = DirItems->Items[up.DirIndex]; - switch(propID) + switch (propID) { case kpidPath: prop = DirItems->GetLogPath(up.DirIndex); break; case kpidIsDir: prop = di.IsDir(); break; @@ -127,27 +401,10 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR case kpidCTime: prop = di.CTime; break; case kpidATime: prop = di.ATime; break; case kpidMTime: prop = di.MTime; break; - } - } - else - { - if (propID == kpidPath) - { - if (up.NewNameIndex >= 0) - { - prop = (*NewNames)[up.NewNameIndex]; - prop.Detach(value); - return S_OK; - } - } - if (up.ExistInArchive() && Archive) - { - UInt32 indexInArchive; - if (ArcItems == 0) - indexInArchive = up.ArcIndex; - else - indexInArchive = (*ArcItems)[up.ArcIndex].IndexInServer; - return Archive->GetProperty(indexInArchive, propID, value); + case kpidIsAltStream: prop = di.IsAltStream; break; + #if defined(_WIN32) && !defined(UNDER_CE) + // case kpidShortName: prop = di.ShortName; break; + #endif } } prop.Detach(value); @@ -155,24 +412,46 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR COM_TRY_END } +static NSynchronization::CCriticalSection CS; + STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) { COM_TRY_BEGIN + *inStream = NULL; const CUpdatePair2 &up = (*UpdatePairs)[index]; if (!up.NewData) return E_FAIL; - + RINOK(Callback->CheckBreak()); RINOK(Callback->Finilize()); + bool isDir = IsDir(up); + if (up.IsAnti) { - return Callback->GetStream((*ArcItems)[up.ArcIndex].Name, true); + UString name; + if (up.ArcIndex >= 0) + name = (*ArcItems)[up.ArcIndex].Name; + else if (up.DirIndex >= 0) + name = DirItems->GetLogPath(up.DirIndex); + RINOK(Callback->GetStream(name, true)); + + /* 9.33: fixed. Handlers expect real stream object for files, even for anti-file. + so we return empty stream */ + + if (!isDir) + { + CBufInStream *inStreamSpec = new CBufInStream(); + CMyComPtr inStreamLoc = inStreamSpec; + inStreamSpec->Init(NULL, 0); + *inStream = inStreamLoc.Detach(); + } + return S_OK; } - const CDirItem &di = DirItems->Items[up.DirIndex]; + RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex), false)); - - if (di.IsDir()) + + if (isDir) return S_OK; if (StdInMode) @@ -185,13 +464,61 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr inStreamLoc(inStreamSpec); + + inStreamSpec->SupportHardLinks = StoreHardLinks; + const UString path = DirItems->GetPhyPath(up.DirIndex); - if (!inStreamSpec->OpenShared(path, ShareForWrite)) + + #if defined(_WIN32) && !defined(UNDER_CE) + if (DirItems->Items[up.DirIndex].AreReparseData()) + { + if (!inStreamSpec->File.OpenReparse(us2fs(path))) + { + return Callback->OpenFileError(path, ::GetLastError()); + } + } + else + #endif + if (!inStreamSpec->OpenShared(us2fs(path), ShareForWrite)) { return Callback->OpenFileError(path, ::GetLastError()); } + +#if 0 // FIXME + if (StoreHardLinks) + { + CStreamFileProps props; + if (inStreamSpec->GetProps2(&props) == S_OK) + { + if (props.NumLinks > 1) + { + CKeyKeyValPair pair; + pair.Key1 = props.VolID; + pair.Key2 = props.FileID_Low; + pair.Value = index; + unsigned numItems = _map.Size(); + unsigned pairIndex = _map.AddToUniqueSorted2(pair); + if (numItems == _map.Size()) + { + // const CKeyKeyValPair &pair2 = _map.Pairs[pairIndex]; + _hardIndex_From = index; + _hardIndex_To = pairIndex; + // we could return NULL as stream, but it's better to return real stream + // return S_OK; + } + } + } + } +#endif + + if (ProcessedItemsStatuses) + { + NSynchronization::CCriticalSectionLock lock(CS); + ProcessedItemsStatuses[up.DirIndex] = 1; + } *inStream = inStreamLoc.Detach(); } + return S_OK; COM_TRY_END } @@ -216,12 +543,12 @@ STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) { COM_TRY_BEGIN - wchar_t temp[16]; + FChar temp[16]; ConvertUInt32ToString(index + 1, temp); - UString res = temp; - while (res.Length() < 2) - res = UString(L'0') + res; - UString fileName = VolName; + FString res = temp; + while (res.Len() < 2) + res.InsertAtFront(FTEXT('0')); + FString fileName = VolName; fileName += L'.'; fileName += res; fileName += VolExt; diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.h index 9a20c3159..81982e61d 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.h +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.h @@ -1,10 +1,9 @@ // UpdateCallback.h -#ifndef __UPDATECALLBACK_H -#define __UPDATECALLBACK_H +#ifndef __UPDATE_CALLBACK_H +#define __UPDATE_CALLBACK_H -#include "Common/MyCom.h" -#include "Common/MyString.h" +#include "../../../Common/MyCom.h" #include "../../IPassword.h" #include "../../ICoder.h" @@ -32,16 +31,43 @@ struct IUpdateCallbackUI INTERFACE_IUpdateCallbackUI(=0) }; +struct CKeyKeyValPair +{ + UInt64 Key1; + UInt64 Key2; + unsigned Value; + + int Compare(const CKeyKeyValPair &a) const + { + if (Key1 < a.Key1) return -1; + if (Key1 > a.Key1) return 1; + return MyCompare(Key2, a.Key2); + } +}; + + class CArchiveUpdateCallback: public IArchiveUpdateCallback2, + public IArchiveGetRawProps, + public IArchiveGetRootProps, public ICryptoGetTextPassword2, public ICryptoGetTextPassword, public ICompressProgressInfo, public CMyUnknownImp { + #if defined(_WIN32) && !defined(UNDER_CE) + bool _saclEnabled; + #endif + CRecordVector _map; + + UInt32 _hardIndex_From; + UInt32 _hardIndex_To; + public: - MY_UNKNOWN_IMP4( + MY_UNKNOWN_IMP6( IArchiveUpdateCallback2, + IArchiveGetRawProps, + IArchiveGetRootProps, ICryptoGetTextPassword2, ICryptoGetTextPassword, ICompressProgressInfo) @@ -49,26 +75,48 @@ public: STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); INTERFACE_IArchiveUpdateCallback2(;) + INTERFACE_IArchiveGetRawProps(;) + INTERFACE_IArchiveGetRootProps(;) STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); STDMETHOD(CryptoGetTextPassword)(BSTR *password); -public: CRecordVector VolumesSizes; - UString VolName; - UString VolExt; + FString VolName; + FString VolExt; IUpdateCallbackUI *Callback; bool ShareForWrite; bool StdInMode; + const CDirItems *DirItems; + const CDirItem *ParentDirItem; + const CObjectVector *ArcItems; const CRecordVector *UpdatePairs; const UStringVector *NewNames; CMyComPtr Archive; + CMyComPtr GetRawProps; + CMyComPtr GetRootProps; + + bool KeepOriginalItemNames; + bool StoreNtSecurity; + bool StoreHardLinks; + bool StoreSymLinks; + + Byte *ProcessedItemsStatuses; CArchiveUpdateCallback(); + + bool IsDir(const CUpdatePair2 &up) const + { + if (up.DirIndex >= 0) + return DirItems->Items[up.DirIndex].IsDir(); + else if (up.ArcIndex >= 0) + return (*ArcItems)[up.ArcIndex].IsDir; + return false; + } }; #endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.cpp index d9396a583..95afdd694 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.cpp +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.cpp @@ -4,10 +4,9 @@ #include -#include "Common/Defs.h" -#include "Common/Wildcard.h" +#include "../../../Common/Wildcard.h" -#include "Windows/Time.h" +#include "../../../Windows/TimeUtils.h" #include "SortUtils.h" #include "UpdatePair.h" @@ -17,7 +16,7 @@ using namespace NTime; static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2) { - switch(fileTimeType) + switch (fileTimeType) { case NFileTimeType::kWindows: return ::CompareFileTime(&time1, &time2); @@ -28,28 +27,49 @@ static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time FileTimeToUnixTime(time2, unixTime2); return MyCompare(unixTime1, unixTime2); } + case NFileTimeType::kDOS: + { + UInt32 dosTime1, dosTime2; + FileTimeToDosTime(time1, dosTime1); + FileTimeToDosTime(time2, dosTime2); + return MyCompare(dosTime1, dosTime2); + } } throw 4191618; } -static const wchar_t *kDuplicateFileNameMessage = L"Duplicate filename:"; -static const wchar_t *kNotCensoredCollisionMessaged = L"Internal file name collision (file on disk, file in archive):"; +static const char *k_Duplicate_inArc_Message = "Duplicate filename in archive:"; +static const char *k_Duplicate_inDir_Message = "Duplicate filename on disk:"; +static const char *k_NotCensoredCollision_Message = "Internal file name collision (file on disk, file in archive):"; -static void ThrowError(const UString &message, const UString &s1, const UString &s2) +static void ThrowError(const char *message, const UString &s1, const UString &s2) { - UString m = message; - m += L'\n'; - m += s1; - m += L'\n'; - m += s2; + UString m; + m.SetFromAscii(message); + m += L'\n'; m += s1; + m += L'\n'; m += s2; throw m; } -static void TestDuplicateString(const UStringVector &strings, const CIntVector &indices) +static int CompareArcItemsBase(const CArcItem &ai1, const CArcItem &ai2) { - for(int i = 0; i + 1 < indices.Size(); i++) - if (CompareFileNames(strings[indices[i]], strings[indices[i + 1]]) == 0) - ThrowError(kDuplicateFileNameMessage, strings[indices[i]], strings[indices[i + 1]]); + int res = CompareFileNames(ai1.Name, ai2.Name); + if (res != 0) + return res; + if (ai1.IsDir != ai2.IsDir) + return ai1.IsDir ? -1 : 1; + return 0; +} + +static int CompareArcItems(const unsigned *p1, const unsigned *p2, void *param) +{ + unsigned i1 = *p1; + unsigned i2 = *p2; + const CObjectVector &arcItems = *(const CObjectVector *)param; + int res = CompareArcItemsBase(arcItems[i1], arcItems[i2]); + if (res != 0) + return res; + return MyCompare(i1, i2); } void GetUpdatePairInfoList( @@ -58,48 +78,103 @@ void GetUpdatePairInfoList( NFileTimeType::EEnum fileTimeType, CRecordVector &updatePairs) { - CIntVector dirIndices, arcIndices; - - int numDirItems = dirItems.Items.Size(); - int numArcItems = arcItems.Size(); - - + CUIntVector dirIndices, arcIndices; + + unsigned numDirItems = dirItems.Items.Size(); + unsigned numArcItems = arcItems.Size(); + + CIntArr duplicatedArcItem(numArcItems); { - UStringVector arcNames; - arcNames.Reserve(numArcItems); - for (int i = 0; i < numArcItems; i++) - arcNames.Add(arcItems[i].Name); - SortFileNames(arcNames, arcIndices); - TestDuplicateString(arcNames, arcIndices); + int *vals = &duplicatedArcItem[0]; + for (unsigned i = 0; i < numArcItems; i++) + vals[i] = 0; + } + + { + arcIndices.ClearAndSetSize(numArcItems); + { + unsigned *vals = &arcIndices[0]; + for (unsigned i = 0; i < numArcItems; i++) + vals[i] = i; + } + arcIndices.Sort(CompareArcItems, (void *)&arcItems); + for (unsigned i = 0; i + 1 < numArcItems; i++) + if (CompareArcItemsBase( + arcItems[arcIndices[i]], + arcItems[arcIndices[i + 1]]) == 0) + { + duplicatedArcItem[i] = 1; + duplicatedArcItem[i + 1] = -1; + } } UStringVector dirNames; { - dirNames.Reserve(numDirItems); - for (int i = 0; i < numDirItems; i++) - dirNames.Add(dirItems.GetLogPath(i)); + dirNames.ClearAndReserve(numDirItems); + unsigned i; + for (i = 0; i < numDirItems; i++) + dirNames.AddInReserved(dirItems.GetLogPath(i)); SortFileNames(dirNames, dirIndices); - TestDuplicateString(dirNames, dirIndices); + for (i = 0; i + 1 < numDirItems; i++) + { + const UString &s1 = dirNames[dirIndices[i]]; + const UString &s2 = dirNames[dirIndices[i + 1]]; + if (CompareFileNames(s1, s2) == 0) + ThrowError(k_Duplicate_inDir_Message, s1, s2); + } } - - int dirIndex = 0, arcIndex = 0; - while (dirIndex < numDirItems && arcIndex < numArcItems) + + unsigned dirIndex = 0; + unsigned arcIndex = 0; + + int prevHostFile = -1; + const UString *prevHostName = NULL; + + while (dirIndex < numDirItems || arcIndex < numArcItems) { CUpdatePair pair; - int dirIndex2 = dirIndices[dirIndex]; - int arcIndex2 = arcIndices[arcIndex]; - const CDirItem &di = dirItems.Items[dirIndex2]; - const CArcItem &ai = arcItems[arcIndex2]; - int compareResult = CompareFileNames(dirNames[dirIndex2], ai.Name); + + int dirIndex2 = -1; + int arcIndex2 = -1; + const CDirItem *di = NULL; + const CArcItem *ai = NULL; + + int compareResult = -1; + const UString *name = NULL; + + if (dirIndex < numDirItems) + { + dirIndex2 = dirIndices[dirIndex]; + di = &dirItems.Items[dirIndex2]; + } + + if (arcIndex < numArcItems) + { + arcIndex2 = arcIndices[arcIndex]; + ai = &arcItems[arcIndex2]; + compareResult = 1; + if (dirIndex < numDirItems) + { + compareResult = CompareFileNames(dirNames[dirIndex2], ai->Name); + if (compareResult == 0) + { + if (di->IsDir() != ai->IsDir) + compareResult = (ai->IsDir ? 1 : -1); + } + } + } + if (compareResult < 0) { + name = &dirNames[dirIndex2]; pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; pair.DirIndex = dirIndex2; dirIndex++; } else if (compareResult > 0) { - pair.State = ai.Censored ? + name = &ai->Name; + pair.State = ai->Censored ? NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked; pair.ArcIndex = arcIndex2; @@ -107,43 +182,50 @@ void GetUpdatePairInfoList( } else { - if (!ai.Censored) - ThrowError(kNotCensoredCollisionMessaged, dirNames[dirIndex2], ai.Name); + int dupl = duplicatedArcItem[arcIndex]; + if (dupl != 0) + ThrowError(k_Duplicate_inArc_Message, ai->Name, arcItems[arcIndices[arcIndex + dupl]].Name); + + name = &dirNames[dirIndex2]; + if (!ai->Censored) + ThrowError(k_NotCensoredCollision_Message, *name, ai->Name); + pair.DirIndex = dirIndex2; pair.ArcIndex = arcIndex2; - switch (ai.MTimeDefined ? MyCompareTime( - ai.TimeType != - 1 ? (NFileTimeType::EEnum)ai.TimeType : fileTimeType, - di.MTime, ai.MTime): 0) + + switch (ai->MTimeDefined ? MyCompareTime( + ai->TimeType != - 1 ? (NFileTimeType::EEnum)ai->TimeType : fileTimeType, + di->MTime, ai->MTime): 0) { case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break; - case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break; + case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break; default: - pair.State = (ai.SizeDefined && di.Size == ai.Size) ? + pair.State = (ai->SizeDefined && di->Size == ai->Size) ? NUpdateArchive::NPairState::kSameFiles : NUpdateArchive::NPairState::kUnknowNewerFiles; } + dirIndex++; arcIndex++; } - updatePairs.Add(pair); - } - for (; dirIndex < numDirItems; dirIndex++) - { - CUpdatePair pair; - pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; - pair.DirIndex = dirIndices[dirIndex]; - updatePairs.Add(pair); - } - - for (; arcIndex < numArcItems; arcIndex++) - { - CUpdatePair pair; - int arcIndex2 = arcIndices[arcIndex]; - pair.State = arcItems[arcIndex2].Censored ? - NUpdateArchive::NPairState::kOnlyInArchive: - NUpdateArchive::NPairState::kNotMasked; - pair.ArcIndex = arcIndex2; + if ((di && di->IsAltStream) || + (ai && ai->IsAltStream)) + { + if (prevHostName) + { + unsigned hostLen = prevHostName->Len(); + if (name->Len() > hostLen) + if ((*name)[hostLen] == ':' && CompareFileNames(*prevHostName, name->Left(hostLen)) == 0) + pair.HostIndex = prevHostFile; + } + } + else + { + prevHostFile = updatePairs.Size(); + prevHostName = name; + } + updatePairs.Add(pair); } diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.h index 3a332649c..296d3b097 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.h +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.h @@ -13,7 +13,9 @@ struct CUpdatePair NUpdateArchive::NPairState::EEnum State; int ArcIndex; int DirIndex; - CUpdatePair(): ArcIndex(-1), DirIndex(-1) {} + int HostIndex; // >= 0 for alt streams only, contains index of host pair + + CUpdatePair(): ArcIndex(-1), DirIndex(-1), HostIndex(-1) {} }; void GetUpdatePairInfoList( diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.cpp index c21db3b2a..2c4c28583 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.cpp +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.cpp @@ -14,17 +14,17 @@ void UpdateProduce( CRecordVector &operationChain, IUpdateProduceCallback *callback) { - for (int i = 0; i < updatePairs.Size(); i++) + FOR_VECTOR (i, updatePairs) { const CUpdatePair &pair = updatePairs[i]; CUpdatePair2 up2; - up2.IsAnti = false; up2.DirIndex = pair.DirIndex; up2.ArcIndex = pair.ArcIndex; up2.NewData = up2.NewProps = true; - - switch(actionSet.StateActions[pair.State]) + up2.UseArcProps = false; + + switch (actionSet.StateActions[pair.State]) { case NPairAction::kIgnore: /* @@ -39,17 +39,32 @@ void UpdateProduce( case NPairAction::kCopy: if (pair.State == NPairState::kOnlyOnDisk) throw kUpdateActionSetCollision; + if (pair.State == NPairState::kOnlyInArchive) + { + if (pair.HostIndex >= 0) + { + /* + ignore alt stream if + 1) no such alt stream in Disk + 2) there is Host file in disk + */ + if (updatePairs[pair.HostIndex].DirIndex >= 0) + continue; + } + } up2.NewData = up2.NewProps = false; + up2.UseArcProps = true; break; - + case NPairAction::kCompress: if (pair.State == NPairState::kOnlyInArchive || pair.State == NPairState::kNotMasked) throw kUpdateActionSetCollision; break; - + case NPairAction::kCompressAsAnti: up2.IsAnti = true; + up2.UseArcProps = (pair.ArcIndex >= 0); break; } operationChain.Add(up2); diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.h index e18648cd9..ef7b0f7a3 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.h +++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.h @@ -9,16 +9,36 @@ struct CUpdatePair2 { bool NewData; bool NewProps; - bool IsAnti; - + bool UseArcProps; // if (UseArcProps && NewProps), we want to change only some properties. + bool IsAnti; // if (!IsAnti) we use other ways to detect Anti status + int DirIndex; int ArcIndex; int NewNameIndex; + bool IsMainRenameItem; + + void SetAs_NoChangeArcItem(int arcIndex) + { + NewData = NewProps = false; + UseArcProps = true; + IsAnti = false; + ArcIndex = arcIndex; + } + bool ExistOnDisk() const { return DirIndex != -1; } bool ExistInArchive() const { return ArcIndex != -1; } - CUpdatePair2(): IsAnti(false), DirIndex(-1), ArcIndex(-1), NewNameIndex(-1) {} + CUpdatePair2(): + NewData(false), + NewProps(false), + UseArcProps(false), + IsAnti(false), + DirIndex(-1), + ArcIndex(-1), + NewNameIndex(-1), + IsMainRenameItem(false) + {} }; struct IUpdateProduceCallback diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/WorkDir.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/WorkDir.cpp deleted file mode 100644 index 28d36df9e..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/WorkDir.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// WorkDir.cpp - -#include "StdAfx.h" - -#include "Common/StringConvert.h" -#include "Common/Wildcard.h" - -#include "Windows/FileDir.h" -#include "Windows/FileName.h" - -#include "WorkDir.h" - -using namespace NWindows; -using namespace NFile; - -UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path) -{ - NWorkDir::NMode::EEnum mode = workDirInfo.Mode; - #if !defined(UNDER_CE) && defined(_WIN32) - if (workDirInfo.ForRemovableOnly) - { - mode = NWorkDir::NMode::kCurrent; - UString prefix = path.Left(3); - if (prefix[1] == L':' && prefix[2] == L'\\') - { - UINT driveType = GetDriveType(GetSystemString(prefix, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP)); - if (driveType == DRIVE_CDROM || driveType == DRIVE_REMOVABLE) - mode = workDirInfo.Mode; - } - /* - CParsedPath parsedPath; - parsedPath.ParsePath(archiveName); - UINT driveType = GetDriveType(parsedPath.Prefix); - if ((driveType != DRIVE_CDROM) && (driveType != DRIVE_REMOVABLE)) - mode = NZipSettings::NWorkDir::NMode::kCurrent; - */ - } - #endif - switch(mode) - { - case NWorkDir::NMode::kCurrent: - { - return ExtractDirPrefixFromPath(path); - } - case NWorkDir::NMode::kSpecified: - { - UString tempDir = workDirInfo.Path; - NName::NormalizeDirPathPrefix(tempDir); - return tempDir; - } - default: - { - UString tempDir; - if (!NDirectory::MyGetTempPath(tempDir)) - throw 141717; - return tempDir; - } - } -} diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/WorkDir.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/WorkDir.h deleted file mode 100644 index 0643d67a4..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/WorkDir.h +++ /dev/null @@ -1,10 +0,0 @@ -// WorkDir.h - -#ifndef __WORKDIR_H -#define __WORKDIR_H - -#include "ZipRegistry.h" - -UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path); - -#endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ZipRegistry.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/ZipRegistry.h deleted file mode 100644 index 378353868..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ZipRegistry.h +++ /dev/null @@ -1,105 +0,0 @@ -// ZipRegistry.h - -#ifndef __ZIP_REGISTRY_H -#define __ZIP_REGISTRY_H - -#include "Common/MyString.h" -#include "Common/Types.h" - -#include "ExtractMode.h" - -namespace NExtract -{ - struct CInfo - { - NPathMode::EEnum PathMode; - NOverwriteMode::EEnum OverwriteMode; - bool ShowPassword; - UStringVector Paths; - - void Save() const; - void Load(); - }; -} - -namespace NCompression -{ - struct CFormatOptions - { - UInt32 Level; - UInt32 Dictionary; - UInt32 Order; - UInt32 BlockLogSize; - UInt32 NumThreads; - - CSysString FormatID; - UString Method; - UString Options; - UString EncryptionMethod; - - void ResetForLevelChange() - { - BlockLogSize = NumThreads = Level = Dictionary = Order = UInt32(-1); - Method.Empty(); - // Options.Empty(); - // EncryptionMethod.Empty(); - } - CFormatOptions() { ResetForLevelChange(); } - }; - - struct CInfo - { - UInt32 Level; - bool ShowPassword; - bool EncryptHeaders; - UString ArcType; - UStringVector ArcPaths; - - CObjectVector Formats; - - void Save() const; - void Load(); - }; -} - -namespace NWorkDir -{ - namespace NMode - { - enum EEnum - { - kSystem, - kCurrent, - kSpecified - }; - } - struct CInfo - { - NMode::EEnum Mode; - UString Path; - bool ForRemovableOnly; - - void SetForRemovableOnlyDefault() { ForRemovableOnly = true; } - void SetDefault() - { - Mode = NMode::kSystem; - Path.Empty(); - SetForRemovableOnlyDefault(); - } - - void Save() const; - void Load(); - }; -} - - -struct CContextMenuInfo -{ - bool Cascaded; - UInt32 Flags; - - void Save() const; - void Load(); -}; - -#endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/BenchCon.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Console/BenchCon.cpp deleted file mode 100644 index 35e868c9b..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Console/BenchCon.cpp +++ /dev/null @@ -1,297 +0,0 @@ -// BenchCon.cpp - -#include "StdAfx.h" - -#include "../../../Common/IntToString.h" -#include "../../../Common/MyCom.h" - -#if !defined(_7ZIP_ST) || defined(_WIN32) -#include "../../../Windows/System.h" -#endif - -#include "../Common/Bench.h" - -#include "BenchCon.h" -#include "ConsoleClose.h" - -struct CTotalBenchRes -{ - UInt64 NumIterations; - UInt64 Rating; - UInt64 Usage; - UInt64 RPU; - void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; } - void Normalize() - { - if (NumIterations == 0) - return; - Rating /= NumIterations; - Usage /= NumIterations; - RPU /= NumIterations; - NumIterations = 1; - } - void SetMid(const CTotalBenchRes &r1, const CTotalBenchRes &r2) - { - Rating = (r1.Rating + r2.Rating) / 2; - Usage = (r1.Usage + r2.Usage) / 2; - RPU = (r1.RPU + r2.RPU) / 2; - NumIterations = (r1.NumIterations + r2.NumIterations) / 2; - } -}; - -struct CBenchCallback: public IBenchCallback -{ - CTotalBenchRes EncodeRes; - CTotalBenchRes DecodeRes; - FILE *f; - void Init() { EncodeRes.Init(); DecodeRes.Init(); } - void Normalize() { EncodeRes.Normalize(); DecodeRes.Normalize(); } - UInt32 dictionarySize; - HRESULT SetEncodeResult(const CBenchInfo &info, bool final); - HRESULT SetDecodeResult(const CBenchInfo &info, bool final); -}; - -static void NormalizeVals(UInt64 &v1, UInt64 &v2) -{ - while (v1 > 1000000) - { - v1 >>= 1; - v2 >>= 1; - } -} - -static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) -{ - UInt64 elTime = elapsedTime; - NormalizeVals(freq, elTime); - if (elTime == 0) - elTime = 1; - return value * freq / elTime; -} - -static void PrintNumber(FILE *f, UInt64 value, int size) -{ - char s[32]; - ConvertUInt64ToString(value, s); - fprintf(f, " "); - for (int len = (int)strlen(s); len < size; len++) - fprintf(f, " "); - fputs(s, f); -} - -static void PrintRating(FILE *f, UInt64 rating) -{ - PrintNumber(f, rating / 1000000, 6); -} - -static void PrintResults(FILE *f, UInt64 usage, UInt64 rpu, UInt64 rating) -{ - PrintNumber(f, (usage + 5000) / 10000, 5); - PrintRating(f, rpu); - PrintRating(f, rating); -} - - -static void PrintResults(FILE *f, const CBenchInfo &info, UInt64 rating, CTotalBenchRes &res) -{ - UInt64 speed = MyMultDiv64(info.UnpackSize, info.GlobalTime, info.GlobalFreq); - PrintNumber(f, speed / 1024, 7); - UInt64 usage = GetUsage(info); - UInt64 rpu = GetRatingPerUsage(info, rating); - PrintResults(f, usage, rpu, rating); - res.NumIterations++; - res.RPU += rpu; - res.Rating += rating; - res.Usage += usage; -} - -static void PrintTotals(FILE *f, const CTotalBenchRes &res) -{ - fprintf(f, " "); - PrintResults(f, res.Usage, res.RPU, res.Rating); -} - - -HRESULT CBenchCallback::SetEncodeResult(const CBenchInfo &info, bool final) -{ - if (NConsoleClose::TestBreakSignal()) - return E_ABORT; - if (final) - { - UInt64 rating = GetCompressRating(dictionarySize, info.GlobalTime, info.GlobalFreq, info.UnpackSize); - PrintResults(f, info, rating, EncodeRes); - } - return S_OK; -} - -static const char *kSep = " | "; - - -HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final) -{ - if (NConsoleClose::TestBreakSignal()) - return E_ABORT; - if (final) - { - UInt64 rating = GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations); - fputs(kSep, f); - CBenchInfo info2 = info; - info2.UnpackSize *= info2.NumIterations; - info2.PackSize *= info2.NumIterations; - info2.NumIterations = 1; - PrintResults(f, info2, rating, DecodeRes); - } - return S_OK; -} - -static void PrintRequirements(FILE *f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads) -{ - fprintf(f, "\nRAM %s ", sizeString); - PrintNumber(f, (size >> 20), 5); - fprintf(f, " MB, # %s %3d", threadsString, (unsigned int)numThreads); -} - -HRESULT LzmaBenchCon( - DECL_EXTERNAL_CODECS_LOC_VARS - FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary) -{ - if (!CrcInternalTest()) - return S_FALSE; - #ifndef _7ZIP_ST - UInt64 ramSize = NWindows::NSystem::GetRamSize(); // - UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); - PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs); - if (numThreads == (UInt32)-1) - numThreads = numCPUs; - if (numThreads > 1) - numThreads &= ~1; - if (dictionary == (UInt32)-1) - { - int dicSizeLog; - for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--) - if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize) - break; - dictionary = (1 << dicSizeLog); - } - #else - if (dictionary == (UInt32)-1) - dictionary = (1 << 22); - numThreads = 1; - #endif - - PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dictionary), "Benchmark threads: ", numThreads); - - CBenchCallback callback; - callback.Init(); - callback.f = f; - - fprintf(f, "\n\nDict Compressing | Decompressing\n "); - int j; - for (j = 0; j < 2; j++) - { - fprintf(f, " Speed Usage R/U Rating"); - if (j == 0) - fputs(kSep, f); - } - fprintf(f, "\n "); - for (j = 0; j < 2; j++) - { - fprintf(f, " KB/s %% MIPS MIPS"); - if (j == 0) - fputs(kSep, f); - } - fprintf(f, "\n\n"); - for (UInt32 i = 0; i < numIterations; i++) - { - const int kStartDicLog = 22; - int pow = (dictionary < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog; - while (((UInt32)1 << pow) > dictionary) - pow--; - for (; ((UInt32)1 << pow) <= dictionary; pow++) - { - fprintf(f, "%2d:", pow); - callback.dictionarySize = (UInt32)1 << pow; - HRESULT res = LzmaBench( - EXTERNAL_CODECS_LOC_VARS - numThreads, callback.dictionarySize, &callback); - fprintf(f, "\n"); - RINOK(res); - } - } - callback.Normalize(); - fprintf(f, "----------------------------------------------------------------\nAvr:"); - PrintTotals(f, callback.EncodeRes); - fprintf(f, " "); - PrintTotals(f, callback.DecodeRes); - fprintf(f, "\nTot:"); - CTotalBenchRes midRes; - midRes.SetMid(callback.EncodeRes, callback.DecodeRes); - PrintTotals(f, midRes); - fprintf(f, "\n"); - return S_OK; -} - -struct CTempValues -{ - UInt64 *Values; - CTempValues(UInt32 num) { Values = new UInt64[num]; } - ~CTempValues() { delete []Values; } -}; - -HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary) -{ - if (!CrcInternalTest()) - return S_FALSE; - - #ifndef _7ZIP_ST - UInt64 ramSize = NWindows::NSystem::GetRamSize(); - UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); - PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs); - if (numThreads == (UInt32)-1) - numThreads = numCPUs; - #else - numThreads = 1; - #endif - if (dictionary == (UInt32)-1) - dictionary = (1 << 24); - - CTempValues speedTotals(numThreads); - fprintf(f, "\n\nSize"); - for (UInt32 ti = 0; ti < numThreads; ti++) - { - fprintf(f, " %5d", ti + 1); - speedTotals.Values[ti] = 0; - } - fprintf(f, "\n\n"); - - UInt64 numSteps = 0; - for (UInt32 i = 0; i < numIterations; i++) - { - for (int pow = 10; pow < 32; pow++) - { - UInt32 bufSize = (UInt32)1 << pow; - if (bufSize > dictionary) - break; - fprintf(f, "%2d: ", pow); - UInt64 speed; - for (UInt32 ti = 0; ti < numThreads; ti++) - { - if (NConsoleClose::TestBreakSignal()) - return E_ABORT; - RINOK(CrcBench(ti + 1, bufSize, speed)); - PrintNumber(f, (speed >> 20), 5); - speedTotals.Values[ti] += speed; - } - fprintf(f, "\n"); - numSteps++; - } - } - if (numSteps != 0) - { - fprintf(f, "\nAvg:"); - for (UInt32 ti = 0; ti < numThreads; ti++) - PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), 5); - fprintf(f, "\n"); - } - return S_OK; -} diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/BenchCon.h b/src/libs/7zip/unix/CPP/7zip/UI/Console/BenchCon.h deleted file mode 100644 index 966a83a6a..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Console/BenchCon.h +++ /dev/null @@ -1,16 +0,0 @@ -// BenchCon.h - -#ifndef __BENCH_CON_H -#define __BENCH_CON_H - -#include - -#include "../../Common/CreateCoder.h" - -HRESULT LzmaBenchCon( - DECL_EXTERNAL_CODECS_LOC_VARS - FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary); - -HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary); - -#endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/Console.pri b/src/libs/7zip/unix/CPP/7zip/UI/Console/Console.pri new file mode 100644 index 000000000..cdb025475 --- /dev/null +++ b/src/libs/7zip/unix/CPP/7zip/UI/Console/Console.pri @@ -0,0 +1,2 @@ +HEADERS += $$7ZIP_BASE/CPP/7zip/UI/Console/PercentPrinter.h +SOURCES += $$7ZIP_BASE/CPP/7zip/UI/Console/PercentPrinter.cpp diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/ConsoleClose.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Console/ConsoleClose.cpp deleted file mode 100644 index 9bb2082bf..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Console/ConsoleClose.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// ConsoleClose.cpp - -#include "StdAfx.h" - -#include "ConsoleClose.h" - -#include - -static int g_BreakCounter = 0; -static const int kBreakAbortThreshold = 2; - -namespace NConsoleClose { - -static void HandlerRoutine(int) -{ - g_BreakCounter++; - if (g_BreakCounter < kBreakAbortThreshold) - return ; - exit(EXIT_FAILURE); -} - -bool TestBreakSignal() -{ - return (g_BreakCounter > 0); -} - -void CheckCtrlBreak() -{ - if (TestBreakSignal()) - throw CCtrlBreakException(); -} - -CCtrlHandlerSetter::CCtrlHandlerSetter() -{ - memo_sig_int = signal(SIGINT,HandlerRoutine); // CTRL-C - if (memo_sig_int == SIG_ERR) - throw "SetConsoleCtrlHandler fails (SIGINT)"; - memo_sig_term = signal(SIGTERM,HandlerRoutine); // for kill -15 (before "kill -9") - if (memo_sig_term == SIG_ERR) - throw "SetConsoleCtrlHandler fails (SIGTERM)"; -} - -CCtrlHandlerSetter::~CCtrlHandlerSetter() -{ - signal(SIGINT,memo_sig_int); // CTRL-C - signal(SIGTERM,memo_sig_term); // kill {pid} -} - -} diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/ConsoleClose.h b/src/libs/7zip/unix/CPP/7zip/UI/Console/ConsoleClose.h deleted file mode 100644 index 042aaf2d6..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Console/ConsoleClose.h +++ /dev/null @@ -1,26 +0,0 @@ -// ConsoleCloseUtils.h - -#ifndef __CONSOLECLOSEUTILS_H -#define __CONSOLECLOSEUTILS_H - -namespace NConsoleClose { - -bool TestBreakSignal(); - -class CCtrlHandlerSetter -{ - void (*memo_sig_int)(int); - void (*memo_sig_term)(int); -public: - CCtrlHandlerSetter(); - virtual ~CCtrlHandlerSetter(); -}; - -class CCtrlBreakException -{}; - -void CheckCtrlBreak(); - -} - -#endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp deleted file mode 100644 index af65739c3..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp +++ /dev/null @@ -1,228 +0,0 @@ -// ExtractCallbackConsole.h - -#include "StdAfx.h" - -#include "ExtractCallbackConsole.h" -#include "UserInputUtils.h" -#include "ConsoleClose.h" - -#include "Common/Wildcard.h" - -#include "Windows/FileDir.h" -#include "Windows/FileFind.h" -#include "Windows/Time.h" -#include "Windows/Defs.h" -#include "Windows/PropVariant.h" -#include "Windows/Error.h" -#include "Windows/PropVariantConversions.h" - -#include "../../Common/FilePathAutoRename.h" - -#include "../Common/ExtractingFilePath.h" - -using namespace NWindows; -using namespace NFile; -using namespace NDirectory; - -static const char *kTestString = "Testing "; -static const char *kExtractString = "Extracting "; -static const char *kSkipString = "Skipping "; - -// static const char *kCantAutoRename = "can not create file with auto name\n"; -// static const char *kCantRenameFile = "can not rename existing file\n"; -// static const char *kCantDeleteOutputFile = "can not delete output file "; -static const char *kError = "ERROR: "; -static const char *kMemoryExceptionMessage = "Can't allocate required memory!"; - -static const char *kProcessing = "Processing archive: "; -static const char *kEverythingIsOk = "Everything is Ok"; -static const char *kNoFiles = "No files to process"; - -static const char *kUnsupportedMethod = "Unsupported Method"; -static const char *kCrcFailed = "CRC Failed"; -static const char *kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?"; -static const char *kDataError = "Data Error"; -static const char *kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?"; -static const char *kUnknownError = "Unknown Error"; - -STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64) -{ - if (NConsoleClose::TestBreakSignal()) - return E_ABORT; - return S_OK; -} - -STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *) -{ - if (NConsoleClose::TestBreakSignal()) - return E_ABORT; - return S_OK; -} - -STDMETHODIMP CExtractCallbackConsole::AskOverwrite( - const wchar_t *existName, const FILETIME *, const UInt64 *, - const wchar_t *newName, const FILETIME *, const UInt64 *, - Int32 *answer) -{ - (*OutStream) << "file " << existName << - "\nalready exists. Overwrite with " << endl; - (*OutStream) << newName; - - NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream); - - switch(overwriteAnswer) - { - case NUserAnswerMode::kQuit: return E_ABORT; - case NUserAnswerMode::kNo: *answer = NOverwriteAnswer::kNo; break; - case NUserAnswerMode::kNoAll: *answer = NOverwriteAnswer::kNoToAll; break; - case NUserAnswerMode::kYesAll: *answer = NOverwriteAnswer::kYesToAll; break; - case NUserAnswerMode::kYes: *answer = NOverwriteAnswer::kYes; break; - case NUserAnswerMode::kAutoRenameAll: *answer = NOverwriteAnswer::kAutoRename; break; - default: return E_FAIL; - } - return S_OK; -} - -STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 askExtractMode, const UInt64 *position) -{ - switch (askExtractMode) - { - case NArchive::NExtract::NAskMode::kExtract: (*OutStream) << kExtractString; break; - case NArchive::NExtract::NAskMode::kTest: (*OutStream) << kTestString; break; - case NArchive::NExtract::NAskMode::kSkip: (*OutStream) << kSkipString; break; - }; - (*OutStream) << name; - if (position != 0) - (*OutStream) << " <" << *position << ">"; - return S_OK; -} - -STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message) -{ - (*OutStream) << message << endl; - NumFileErrorsInCurrentArchive++; - NumFileErrors++; - return S_OK; -} - -STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult, bool encrypted) -{ - switch(operationResult) - { - case NArchive::NExtract::NOperationResult::kOK: - break; - default: - { - NumFileErrorsInCurrentArchive++; - NumFileErrors++; - (*OutStream) << " "; - switch(operationResult) - { - case NArchive::NExtract::NOperationResult::kUnSupportedMethod: - (*OutStream) << kUnsupportedMethod; - break; - case NArchive::NExtract::NOperationResult::kCRCError: - (*OutStream) << (encrypted ? kCrcFailedEncrypted: kCrcFailed); - break; - case NArchive::NExtract::NOperationResult::kDataError: - (*OutStream) << (encrypted ? kDataErrorEncrypted : kDataError); - break; - default: - (*OutStream) << kUnknownError; - } - } - } - (*OutStream) << endl; - return S_OK; -} - -#ifndef _NO_CRYPTO - -HRESULT CExtractCallbackConsole::SetPassword(const UString &password) -{ - PasswordIsDefined = true; - Password = password; - return S_OK; -} - -STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password) -{ - if (!PasswordIsDefined) - { - Password = GetPassword(OutStream); - PasswordIsDefined = true; - } - return StringToBstr(Password, password); -} - -#endif - -HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name) -{ - NumArchives++; - NumFileErrorsInCurrentArchive = 0; - (*OutStream) << endl << kProcessing << name << endl; - return S_OK; -} - -HRESULT CExtractCallbackConsole::OpenResult(const wchar_t * /* name */, HRESULT result, bool encrypted) -{ - (*OutStream) << endl; - if (result != S_OK) - { - (*OutStream) << "Error: "; - if (result == S_FALSE) - { - (*OutStream) << (encrypted ? - "Can not open encrypted archive. Wrong password?" : - "Can not open file as archive"); - } - else - { - if (result == E_OUTOFMEMORY) - (*OutStream) << "Can't allocate required memory"; - else - (*OutStream) << NError::MyFormatMessage(result); - } - (*OutStream) << endl; - NumArchiveErrors++; - } - return S_OK; -} - -HRESULT CExtractCallbackConsole::ThereAreNoFiles() -{ - (*OutStream) << endl << kNoFiles << endl; - return S_OK; -} - -HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result) -{ - if (result == S_OK) - { - (*OutStream) << endl; - if (NumFileErrorsInCurrentArchive == 0) - (*OutStream) << kEverythingIsOk << endl; - else - { - NumArchiveErrors++; - (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrentArchive << endl; - } - } - if (result == S_OK) - return result; - NumArchiveErrors++; - if (result == E_ABORT || result == ERROR_DISK_FULL) - return result; - (*OutStream) << endl << kError; - if (result == E_OUTOFMEMORY) - (*OutStream) << kMemoryExceptionMessage; - else - { - UString message; - NError::MyFormatMessage(result, message); - (*OutStream) << message; - } - (*OutStream) << endl; - return S_OK; -} diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/ExtractCallbackConsole.h b/src/libs/7zip/unix/CPP/7zip/UI/Console/ExtractCallbackConsole.h deleted file mode 100644 index e42ca6f40..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Console/ExtractCallbackConsole.h +++ /dev/null @@ -1,73 +0,0 @@ -// ExtractCallbackConsole.h - -#ifndef __EXTRACTCALLBACKCONSOLE_H -#define __EXTRACTCALLBACKCONSOLE_H - -#include "Common/MyString.h" -#include "Common/StdOutStream.h" -#include "../../Common/FileStreams.h" -#include "../../IPassword.h" -#include "../../Archive/IArchive.h" -#include "../Common/ArchiveExtractCallback.h" - -class CExtractCallbackConsole: - public IExtractCallbackUI, - #ifndef _NO_CRYPTO - public ICryptoGetTextPassword, - #endif - public CMyUnknownImp -{ -public: - MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback) - #ifndef _NO_CRYPTO - MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword) - #endif - MY_QUERYINTERFACE_END - MY_ADDREF_RELEASE - - STDMETHOD(SetTotal)(UInt64 total); - STDMETHOD(SetCompleted)(const UInt64 *completeValue); - - // IFolderArchiveExtractCallback - STDMETHOD(AskOverwrite)( - const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, - const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, - Int32 *answer); - STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position); - - STDMETHOD(MessageError)(const wchar_t *message); - STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted); - - HRESULT BeforeOpen(const wchar_t *name); - HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted); - HRESULT ThereAreNoFiles(); - HRESULT ExtractResult(HRESULT result); - - - #ifndef _NO_CRYPTO - HRESULT SetPassword(const UString &password); - STDMETHOD(CryptoGetTextPassword)(BSTR *password); - - bool PasswordIsDefined; - UString Password; - - #endif - - UInt64 NumArchives; - UInt64 NumArchiveErrors; - UInt64 NumFileErrors; - UInt64 NumFileErrorsInCurrentArchive; - - CStdOutStream *OutStream; - - void Init() - { - NumArchives = 0; - NumArchiveErrors = 0; - NumFileErrors = 0; - NumFileErrorsInCurrentArchive = 0; - } - -}; - -#endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/List.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Console/List.cpp deleted file mode 100644 index f747cfda8..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Console/List.cpp +++ /dev/null @@ -1,654 +0,0 @@ -// List.cpp - -#include "StdAfx.h" - -#include "Common/IntToString.h" -#include "Common/MyCom.h" -#include "Common/StdOutStream.h" -#include "Common/StringConvert.h" - -#include "Windows/Error.h" -#include "Windows/FileDir.h" -#include "Windows/PropVariant.h" -#include "Windows/PropVariantConversions.h" - -#include "../../Archive/IArchive.h" - -#include "../Common/OpenArchive.h" -#include "../Common/PropIDUtils.h" - -#include "ConsoleClose.h" -#include "List.h" -#include "OpenCallbackConsole.h" - -using namespace NWindows; - -struct CPropIdToName -{ - PROPID PropID; - const wchar_t *Name; -}; - -static const CPropIdToName kPropIdToName[] = -{ - { kpidPath, L"Path" }, - { kpidName, L"Name" }, - { kpidIsDir, L"Folder" }, - { kpidSize, L"Size" }, - { kpidPackSize, L"Packed Size" }, - { kpidAttrib, L"Attributes" }, - { kpidCTime, L"Created" }, - { kpidATime, L"Accessed" }, - { kpidMTime, L"Modified" }, - { kpidSolid, L"Solid" }, - { kpidCommented, L"Commented" }, - { kpidEncrypted, L"Encrypted" }, - { kpidSplitBefore, L"Split Before" }, - { kpidSplitAfter, L"Split After" }, - { kpidDictionarySize, L"Dictionary Size" }, - { kpidCRC, L"CRC" }, - { kpidType, L"Type" }, - { kpidIsAnti, L"Anti" }, - { kpidMethod, L"Method" }, - { kpidHostOS, L"Host OS" }, - { kpidFileSystem, L"File System" }, - { kpidUser, L"User" }, - { kpidGroup, L"Group" }, - { kpidBlock, L"Block" }, - { kpidComment, L"Comment" }, - { kpidPosition, L"Position" }, - { kpidPrefix, L"Prefix" }, - { kpidNumSubDirs, L"Folders" }, - { kpidNumSubFiles, L"Files" }, - { kpidUnpackVer, L"Version" }, - { kpidVolume, L"Volume" }, - { kpidIsVolume, L"Multivolume" }, - { kpidOffset, L"Offset" }, - { kpidLinks, L"Links" }, - { kpidNumBlocks, L"Blocks" }, - { kpidNumVolumes, L"Volumes" }, - - { kpidBit64, L"64-bit" }, - { kpidBigEndian, L"Big-endian" }, - { kpidCpu, L"CPU" }, - { kpidPhySize, L"Physical Size" }, - { kpidHeadersSize, L"Headers Size" }, - { kpidChecksum, L"Checksum" }, - { kpidCharacts, L"Characteristics" }, - { kpidVa, L"Virtual Address" }, - { kpidId, L"ID" }, - { kpidShortName, L"Short Name" }, - { kpidCreatorApp, L"Creator Application"}, - { kpidSectorSize, L"Sector Size" }, - { kpidPosixAttrib, L"Mode" }, - { kpidLink, L"Link" }, - { kpidError, L"Error" }, - - { kpidTotalSize, L"Total Size" }, - { kpidFreeSpace, L"Free Space" }, - { kpidClusterSize, L"Cluster Size" }, - { kpidVolumeName, L"Label" } -}; - -static const char kEmptyAttribChar = '.'; - -static const char *kListing = "Listing archive: "; -static const wchar_t *kFilesMessage = L"files"; -static const wchar_t *kDirsMessage = L"folders"; - -static void GetAttribString(DWORD wa, bool isDir, char *s) -{ - s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : kEmptyAttribChar; - s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0) ? 'R': kEmptyAttribChar; - s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 'H': kEmptyAttribChar; - s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 'S': kEmptyAttribChar; - s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 'A': kEmptyAttribChar; - s[5] = '\0'; -} - -enum EAdjustment -{ - kLeft, - kCenter, - kRight -}; - -struct CFieldInfo -{ - PROPID PropID; - UString Name; - EAdjustment TitleAdjustment; - EAdjustment TextAdjustment; - int PrefixSpacesWidth; - int Width; -}; - -struct CFieldInfoInit -{ - PROPID PropID; - const wchar_t *Name; - EAdjustment TitleAdjustment; - EAdjustment TextAdjustment; - int PrefixSpacesWidth; - int Width; -}; - -static CFieldInfoInit kStandardFieldTable[] = -{ - { kpidMTime, L" Date Time", kLeft, kLeft, 0, 19 }, - { kpidAttrib, L"Attr", kRight, kCenter, 1, 5 }, - { kpidSize, L"Size", kRight, kRight, 1, 12 }, - { kpidPackSize, L"Compressed", kRight, kRight, 1, 12 }, - { kpidPath, L"Name", kLeft, kLeft, 2, 24 } -}; - -static void PrintSpaces(int numSpaces) -{ - for (int i = 0; i < numSpaces; i++) - g_StdOut << ' '; -} - -static void PrintString(EAdjustment adjustment, int width, const UString &textString) -{ - const int numSpaces = width - textString.Length(); - int numLeftSpaces = 0; - switch (adjustment) - { - case kLeft: - numLeftSpaces = 0; - break; - case kCenter: - numLeftSpaces = numSpaces / 2; - break; - case kRight: - numLeftSpaces = numSpaces; - break; - } - PrintSpaces(numLeftSpaces); - g_StdOut << textString; - PrintSpaces(numSpaces - numLeftSpaces); -} - -class CFieldPrinter -{ - CObjectVector _fields; -public: - void Clear() { _fields.Clear(); } - void Init(const CFieldInfoInit *standardFieldTable, int numItems); - HRESULT Init(IInArchive *archive); - void PrintTitle(); - void PrintTitleLines(); - HRESULT PrintItemInfo(const CArc &arc, UInt32 index, bool techMode); - HRESULT PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, - const UInt64 *size, const UInt64 *compressedSize); -}; - -void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems) -{ - Clear(); - for (int i = 0; i < numItems; i++) - { - CFieldInfo fieldInfo; - const CFieldInfoInit &fieldInfoInit = standardFieldTable[i]; - fieldInfo.PropID = fieldInfoInit.PropID; - fieldInfo.Name = fieldInfoInit.Name; - fieldInfo.TitleAdjustment = fieldInfoInit.TitleAdjustment; - fieldInfo.TextAdjustment = fieldInfoInit.TextAdjustment; - fieldInfo.PrefixSpacesWidth = fieldInfoInit.PrefixSpacesWidth; - fieldInfo.Width = fieldInfoInit.Width; - _fields.Add(fieldInfo); - } -} - -static UString GetPropName(PROPID propID, BSTR name) -{ - for (int i = 0; i < sizeof(kPropIdToName) / sizeof(kPropIdToName[0]); i++) - { - const CPropIdToName &propIdToName = kPropIdToName[i]; - if (propIdToName.PropID == propID) - return propIdToName.Name; - } - if (name) - return name; - wchar_t s[16]; - ConvertUInt32ToString(propID, s); - return s; -} - -HRESULT CFieldPrinter::Init(IInArchive *archive) -{ - Clear(); - UInt32 numProps; - RINOK(archive->GetNumberOfProperties(&numProps)); - for (UInt32 i = 0; i < numProps; i++) - { - CMyComBSTR name; - PROPID propID; - VARTYPE vt; - RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt)); - CFieldInfo fieldInfo; - fieldInfo.PropID = propID; - fieldInfo.Name = GetPropName(propID, name); - _fields.Add(fieldInfo); - } - return S_OK; -} - -void CFieldPrinter::PrintTitle() -{ - for (int i = 0; i < _fields.Size(); i++) - { - const CFieldInfo &fieldInfo = _fields[i]; - PrintSpaces(fieldInfo.PrefixSpacesWidth); - PrintString(fieldInfo.TitleAdjustment, - ((fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width), fieldInfo.Name); - } -} - -void CFieldPrinter::PrintTitleLines() -{ - for (int i = 0; i < _fields.Size(); i++) - { - const CFieldInfo &fieldInfo = _fields[i]; - PrintSpaces(fieldInfo.PrefixSpacesWidth); - for (int i = 0; i < fieldInfo.Width; i++) - g_StdOut << '-'; - } -} - - -static BOOL IsFileTimeZero(CONST FILETIME *lpFileTime) -{ - return (lpFileTime->dwLowDateTime == 0) && (lpFileTime->dwHighDateTime == 0); -} - -static const char *kEmptyTimeString = " "; -static void PrintTime(const NCOM::CPropVariant &prop) -{ - if (prop.vt != VT_FILETIME) - throw "incorrect item"; - if (IsFileTimeZero(&prop.filetime)) - g_StdOut << kEmptyTimeString; - else - { - FILETIME localFileTime; - if (!FileTimeToLocalFileTime(&prop.filetime, &localFileTime)) - throw "FileTimeToLocalFileTime error"; - char s[32]; - if (ConvertFileTimeToString(localFileTime, s, true, true)) - g_StdOut << s; - else - g_StdOut << kEmptyTimeString; - } -} - -HRESULT CFieldPrinter::PrintItemInfo(const CArc &arc, UInt32 index, bool techMode) -{ - /* - if (techMode) - { - g_StdOut << "Index = "; - g_StdOut << (UInt64)index; - g_StdOut << endl; - } - */ - for (int i = 0; i < _fields.Size(); i++) - { - const CFieldInfo &fieldInfo = _fields[i]; - if (!techMode) - PrintSpaces(fieldInfo.PrefixSpacesWidth); - - NCOM::CPropVariant prop; - if (fieldInfo.PropID == kpidPath) - { - UString s; - RINOK(arc.GetItemPath(index, s)); - prop = s; - } - else - { - RINOK(arc.Archive->GetProperty(index, fieldInfo.PropID, &prop)); - } - if (techMode) - { - g_StdOut << fieldInfo.Name << " = "; - } - int width = (fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width; - if (fieldInfo.PropID == kpidAttrib && (prop.vt == VT_EMPTY || prop.vt == VT_UI4)) - { - UInt32 attrib = (prop.vt == VT_EMPTY) ? 0 : prop.ulVal; - bool isFolder; - RINOK(IsArchiveItemFolder(arc.Archive, index, isFolder)); - char s[8]; - GetAttribString(attrib, isFolder, s); - g_StdOut << s; - } - else if (prop.vt == VT_EMPTY) - { - if (!techMode) - PrintSpaces(width); - } - else if (fieldInfo.PropID == kpidMTime) - { - PrintTime(prop); - } - else if (prop.vt == VT_BSTR) - { - if (techMode) - g_StdOut << prop.bstrVal; - else - PrintString(fieldInfo.TextAdjustment, width, prop.bstrVal); - } - else - { - UString s = ConvertPropertyToString(prop, fieldInfo.PropID); - s.Replace(wchar_t(0xA), L' '); - s.Replace(wchar_t(0xD), L' '); - - if (techMode) - g_StdOut << s; - else - PrintString(fieldInfo.TextAdjustment, width, s); - } - if (techMode) - g_StdOut << endl; - } - return S_OK; -} - -static void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value) -{ - wchar_t textString[32] = { 0 }; - if (value != NULL) - ConvertUInt64ToString(*value, textString); - PrintString(adjustment, width, textString); -} - - -HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, - const UInt64 *size, const UInt64 *compressedSize) -{ - for (int i = 0; i < _fields.Size(); i++) - { - const CFieldInfo &fieldInfo = _fields[i]; - PrintSpaces(fieldInfo.PrefixSpacesWidth); - NCOM::CPropVariant prop; - if (fieldInfo.PropID == kpidSize) - PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, size); - else if (fieldInfo.PropID == kpidPackSize) - PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, compressedSize); - else if (fieldInfo.PropID == kpidPath) - { - wchar_t textString[32]; - ConvertUInt64ToString(numFiles, textString); - UString temp = textString; - temp += L" "; - temp += kFilesMessage; - temp += L", "; - ConvertUInt64ToString(numDirs, textString); - temp += textString; - temp += L" "; - temp += kDirsMessage; - PrintString(fieldInfo.TextAdjustment, 0, temp); - } - else - PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, L""); - } - return S_OK; -} - -bool GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &value) -{ - NCOM::CPropVariant prop; - if (archive->GetProperty(index, propID, &prop) != S_OK) - throw "GetPropertyValue error"; - if (prop.vt == VT_EMPTY) - return false; - value = ConvertPropVariantToUInt64(prop); - return true; -} - -static void PrintPropPair(const wchar_t *name, const wchar_t *value) -{ - g_StdOut << name << " = " << value << endl; -} - -HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, - bool stdInMode, - UStringVector &arcPaths, UStringVector &arcPathsFull, - const NWildcard::CCensorNode &wildcardCensor, - bool enableHeaders, bool techMode, - #ifndef _NO_CRYPTO - bool &passwordEnabled, UString &password, - #endif - UInt64 &numErrors) -{ - numErrors = 0; - CFieldPrinter fieldPrinter; - if (!techMode) - fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0])); - - UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0; - UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0; - int numArcs = /* stdInMode ? 1 : */ arcPaths.Size(); - for (int i = 0; i < numArcs; i++) - { - const UString &archiveName = arcPaths[i]; - UInt64 arcPackSize = 0; - if (!stdInMode) - { - NFile::NFind::CFileInfoW fi; - if (!fi.Find(archiveName) || fi.IsDir()) - { - g_StdOut << endl << "Error: " << archiveName << " is not file" << endl; - numErrors++; - continue; - } - arcPackSize = fi.Size; - } - - CArchiveLink archiveLink; - - COpenCallbackConsole openCallback; - openCallback.OutStream = &g_StdOut; - - #ifndef _NO_CRYPTO - - openCallback.PasswordIsDefined = passwordEnabled; - openCallback.Password = password; - - #endif - - HRESULT result = archiveLink.Open2(codecs, formatIndices, stdInMode, NULL, archiveName, &openCallback); - if (result != S_OK) - { - if (result == E_ABORT) - return result; - g_StdOut << endl << "Error: " << archiveName << ": "; - if (result == S_FALSE) - { - #ifndef _NO_CRYPTO - if (openCallback.Open_WasPasswordAsked()) - g_StdOut << "Can not open encrypted archive. Wrong password?"; - else - #endif - g_StdOut << "Can not open file as archive"; - } - else if (result == E_OUTOFMEMORY) - g_StdOut << "Can't allocate required memory"; - else - g_StdOut << NError::MyFormatMessage(result); - g_StdOut << endl; - numErrors++; - continue; - } - - if (!stdInMode) - for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) - { - int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]); - if (index >= 0 && index > i) - { - arcPaths.Delete(index); - arcPathsFull.Delete(index); - numArcs = arcPaths.Size(); - } - } - - if (enableHeaders) - { - g_StdOut << endl << kListing << archiveName << endl << endl; - - for (int i = 0; i < archiveLink.Arcs.Size(); i++) - { - const CArc &arc = archiveLink.Arcs[i]; - - 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) - { - for (UInt32 j = 0; j < numProps; j++) - { - CMyComBSTR name; - PROPID propID; - VARTYPE vt; - RINOK(archive->GetArchivePropertyInfo(j, &name, &propID, &vt)); - NCOM::CPropVariant prop; - RINOK(archive->GetArchiveProperty(propID, &prop)); - UString s = ConvertPropertyToString(prop, propID); - if (!s.IsEmpty()) - PrintPropPair(GetPropName(propID, name), s); - } - } - if (i != archiveLink.Arcs.Size() - 1) - { - UInt32 numProps; - g_StdOut << "----\n"; - if (archive->GetNumberOfProperties(&numProps) == S_OK) - { - UInt32 mainIndex = archiveLink.Arcs[i + 1].SubfileIndex; - for (UInt32 j = 0; j < numProps; j++) - { - CMyComBSTR name; - PROPID propID; - VARTYPE vt; - RINOK(archive->GetPropertyInfo(j, &name, &propID, &vt)); - NCOM::CPropVariant prop; - RINOK(archive->GetProperty(mainIndex, propID, &prop)); - UString s = ConvertPropertyToString(prop, propID); - if (!s.IsEmpty()) - PrintPropPair(GetPropName(propID, name), s); - } - } - } - - } - g_StdOut << endl; - if (techMode) - g_StdOut << "----------\n"; - } - - if (enableHeaders && !techMode) - { - fieldPrinter.PrintTitle(); - g_StdOut << endl; - fieldPrinter.PrintTitleLines(); - g_StdOut << endl; - } - - const CArc &arc = archiveLink.Arcs.Back(); - IInArchive *archive = arc.Archive; - if (techMode) - { - RINOK(fieldPrinter.Init(archive)); - } - UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0; - UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0; - UInt32 numItems; - RINOK(archive->GetNumberOfItems(&numItems)); - for (UInt32 i = 0; i < numItems; i++) - { - if (NConsoleClose::TestBreakSignal()) - return E_ABORT; - - UString filePath; - HRESULT res = arc.GetItemPath(i, filePath); - if (stdInMode && res == E_INVALIDARG) - break; - RINOK(res); - - bool isFolder; - RINOK(IsArchiveItemFolder(archive, i, isFolder)); - if (!wildcardCensor.CheckPath(filePath, !isFolder)) - continue; - - fieldPrinter.PrintItemInfo(arc, i, techMode); - - UInt64 packSize, unpackSize; - if (!GetUInt64Value(archive, i, kpidSize, unpackSize)) - unpackSize = 0; - else - totalUnPackSizePointer = &totalUnPackSize; - if (!GetUInt64Value(archive, i, kpidPackSize, packSize)) - packSize = 0; - else - totalPackSizePointer = &totalPackSize; - - g_StdOut << endl; - - if (isFolder) - numDirs++; - else - numFiles++; - totalPackSize += packSize; - totalUnPackSize += unpackSize; - } - - if (!stdInMode && totalPackSizePointer == 0) - { - if (archiveLink.VolumePaths.Size() != 0) - arcPackSize += archiveLink.VolumesSize; - totalPackSize = (numFiles == 0) ? 0 : arcPackSize; - totalPackSizePointer = &totalPackSize; - } - if (totalUnPackSizePointer == 0 && numFiles == 0) - { - totalUnPackSize = 0; - totalUnPackSizePointer = &totalUnPackSize; - } - if (enableHeaders && !techMode) - { - fieldPrinter.PrintTitleLines(); - g_StdOut << endl; - fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer); - g_StdOut << endl; - } - if (totalPackSizePointer != 0) - { - totalPackSizePointer2 = &totalPackSize2; - totalPackSize2 += totalPackSize; - } - if (totalUnPackSizePointer != 0) - { - totalUnPackSizePointer2 = &totalUnPackSize2; - totalUnPackSize2 += totalUnPackSize; - } - numFiles2 += numFiles; - numDirs2 += numDirs; - } - if (enableHeaders && !techMode && numArcs > 1) - { - g_StdOut << endl; - fieldPrinter.PrintTitleLines(); - g_StdOut << endl; - fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2); - g_StdOut << endl; - g_StdOut << "Archives: " << numArcs << endl; - } - return S_OK; -} diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/List.h b/src/libs/7zip/unix/CPP/7zip/UI/Console/List.h deleted file mode 100644 index 97d9fb15a..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Console/List.h +++ /dev/null @@ -1,20 +0,0 @@ -// List.h - -#ifndef __LIST_H -#define __LIST_H - -#include "Common/Wildcard.h" -#include "../Common/LoadCodecs.h" - -HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, - bool stdInMode, - UStringVector &archivePaths, UStringVector &archivePathsFull, - const NWildcard::CCensorNode &wildcardCensor, - bool enableHeaders, bool techMode, - #ifndef _NO_CRYPTO - bool &passwordEnabled, UString &password, - #endif - UInt64 &errors); - -#endif - diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/Main.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Console/Main.cpp deleted file mode 100644 index cebfe2e42..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Console/Main.cpp +++ /dev/null @@ -1,628 +0,0 @@ -// Main.cpp - -#include "StdAfx.h" - -#if defined( _7ZIP_LARGE_PAGES) -#include "../../../../C/Alloc.h" -#endif - -#include "Common/MyInitGuid.h" - -#include "Common/CommandLineParser.h" -#include "Common/IntToString.h" -#include "Common/MyException.h" -#include "Common/StdOutStream.h" -#include "Common/StringConvert.h" -#include "Common/StringToInt.h" - -#include "Windows/Error.h" -#ifdef _WIN32 -#include "Windows/MemoryLock.h" -#endif - -#include "../Common/ArchiveCommandLine.h" -#include "../Common/ExitCode.h" -#include "../Common/Extract.h" -#ifdef EXTERNAL_CODECS -#include "../Common/LoadCodecs.h" -#endif - -#include "BenchCon.h" -#include "ExtractCallbackConsole.h" -#include "List.h" -#include "OpenCallbackConsole.h" -#include "UpdateCallbackConsole.h" - -#include "../../MyVersion.h" - -#include "myPrivate.h" -#include "Windows/System.h" - -using namespace NWindows; -using namespace NFile; -using namespace NCommandLineParser; - -// HINSTANCE g_hInstance = 0; -extern CStdOutStream *g_StdStream; - -static const char *kCopyrightString = "\n7-Zip" -#ifndef EXTERNAL_CODECS -" (A)" -#endif - -#ifdef _WIN64 -" [64]" -#endif - -" " MY_VERSION_COPYRIGHT_DATE "\n" -"p7zip Version " P7ZIP_VERSION ; - -static const char *kHelpString = - "\nUsage: 7z" -#ifdef _NO_CRYPTO - "r" -#else -#ifndef EXTERNAL_CODECS - "a" -#endif -#endif - " [...] [...]\n" - " [<@listfiles...>]\n" - "\n" - "\n" - " a: Add files to archive\n" - " b: Benchmark\n" - " d: Delete files from archive\n" - " e: Extract files from archive (without using directory names)\n" - " l: List contents of archive\n" -// " l[a|t][f]: List contents of archive\n" -// " a - with Additional fields\n" -// " t - with all fields\n" -// " f - with Full pathnames\n" - " t: Test integrity of archive\n" - " u: Update files to archive\n" - " x: eXtract files with full paths\n" - "\n" - " -ai[r[-|0]]{@listfile|!wildcard}: Include archives\n" - " -ax[r[-|0]]{@listfile|!wildcard}: eXclude archives\n" - " -bd: Disable percentage indicator\n" - " -i[r[-|0]]{@listfile|!wildcard}: Include filenames\n" - " -m{Parameters}: set compression Method\n" - " -o{Directory}: set Output directory\n" - #ifndef _NO_CRYPTO - " -p{Password}: set Password\n" - #endif - " -r[-|0]: Recurse subdirectories\n" - " -scs{UTF-8 | WIN | DOS}: set charset for list files\n" - " -sfx[{name}]: Create SFX archive\n" - " -si[{name}]: read data from stdin\n" - " -slt: show technical information for l (List) command\n" - " -so: write data to stdout\n" - " -ssc[-]: set sensitive case mode\n" - " -t{Type}: Set type of archive\n" - " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]: Update options\n" - " -v{Size}[b|k|m|g]: Create volumes\n" - " -w[{path}]: assign Work directory. Empty path means a temporary directory\n" - " -x[r[-|0]]]{@listfile|!wildcard}: eXclude filenames\n" - " -y: assume Yes on all queries\n"; - -// --------------------------- -// exception messages - -static const char *kEverythingIsOk = "Everything is Ok"; -static const char *kUserErrorMessage = "Incorrect command line"; -static const char *kNoFormats = "7-Zip cannot find the code that works with archives."; -static const char *kUnsupportedArcTypeMessage = "Unsupported archive type"; - -static const wchar_t *kDefaultSfxModule = L"7zCon.sfx"; - -static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code) -{ - s << message << endl; - throw code; -} - -static void PrintHelpAndExit(CStdOutStream &s) -{ - s << kHelpString; - ShowMessageAndThrowException(s, kUserErrorMessage, NExitCode::kUserError); -} - -#ifndef _WIN32 -static void GetArguments(int numArgs, const char *args[], UStringVector &parts) -{ - parts.Clear(); - for (int i = 0; i < numArgs; i++) - { - UString s = MultiByteToUnicodeString(args[i]); - parts.Add(s); - } -} -#endif - -static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp) -{ - s << kCopyrightString << " (locale=" << my_getlocale() <<",Utf16="; - if (global_use_utf16_conversion) s << "on"; - else s << "off"; - s << ",HugeFiles="; - if (sizeof(off_t) >= 8) s << "on,"; - else s << "off,"; - int nbcpu = NWindows::NSystem::GetNumberOfProcessors(); - if (nbcpu > 1) s << nbcpu << " CPUs)\n"; - else s << nbcpu << " CPU)\n"; - - if (needHelp) - s << kHelpString; -} - -#ifdef EXTERNAL_CODECS -static void PrintString(CStdOutStream &stdStream, const AString &s, int size) -{ - int len = s.Length(); - stdStream << s; - for (int i = len; i < size; i++) - stdStream << ' '; -} -#endif - -static void PrintString(CStdOutStream &stdStream, const UString &s, int size) -{ - int len = s.Length(); - stdStream << s; - for (int i = len; i < size; i++) - stdStream << ' '; -} - -static inline char GetHex(Byte value) -{ - return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); -} - -int Main2( - #ifndef _WIN32 - int numArgs, const char *args[] - #endif -) -{ - #if defined(_WIN32) && !defined(UNDER_CE) - SetFileApisToOEM(); - #endif - - UStringVector commandStrings; - #ifdef _WIN32 - NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); - #else - // GetArguments(numArgs, args, commandStrings); - extern void mySplitCommandLine(int numArgs,const char *args[],UStringVector &parts); - mySplitCommandLine(numArgs,args,commandStrings); - #endif - - if (commandStrings.Size() == 1) - { - ShowCopyrightAndHelp(g_StdOut, true); - return 0; - } - commandStrings.Delete(0); - - CArchiveCommandLineOptions options; - - CArchiveCommandLineParser parser; - - parser.Parse1(commandStrings, options); - - if (options.HelpMode) - { - ShowCopyrightAndHelp(g_StdOut, true); - return 0; - } - - #if defined(_7ZIP_LARGE_PAGES) - if (options.LargePages) - { - SetLargePageSize(); -#ifdef _WIN32 - NSecurity::EnableLockMemoryPrivilege(); -#endif - } - #endif - - CStdOutStream &stdStream = options.StdOutMode ? g_StdErr : g_StdOut; - g_StdStream = &stdStream; - - if (options.EnableHeaders) - ShowCopyrightAndHelp(stdStream, false); - - parser.Parse2(options); - - CCodecs *codecs = new CCodecs; - CMyComPtr< - #ifdef EXTERNAL_CODECS - ICompressCodecsInfo - #else - IUnknown - #endif - > compressCodecsInfo = codecs; - HRESULT result = codecs->Load(); - if (result != S_OK) - throw CSystemException(result); - - bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); - - if (codecs->Formats.Size() == 0 && - (isExtractGroupCommand || - options.Command.CommandType == NCommandType::kList || - options.Command.IsFromUpdateGroup())) - throw kNoFormats; - - CIntVector formatIndices; - if (!codecs->FindFormatForArchiveType(options.ArcType, formatIndices)) - throw kUnsupportedArcTypeMessage; - - if (options.Command.CommandType == NCommandType::kInfo) - { - stdStream << endl << "Formats:" << endl; - int i; - for (i = 0; i < codecs->Formats.Size(); i++) - { - const CArcInfoEx &arc = codecs->Formats[i]; - #ifdef EXTERNAL_CODECS - if (arc.LibIndex >= 0) - { - char s[16]; - ConvertUInt32ToString(arc.LibIndex, s); - PrintString(stdStream, s, 2); - } - else - #endif - stdStream << " "; - stdStream << ' '; - stdStream << (char)(arc.UpdateEnabled ? 'C' : ' '); - stdStream << (char)(arc.KeepName ? 'K' : ' '); - stdStream << " "; - PrintString(stdStream, arc.Name, 6); - stdStream << " "; - UString s; - for (int t = 0; t < arc.Exts.Size(); t++) - { - const CArcExtInfo &ext = arc.Exts[t]; - s += ext.Ext; - if (!ext.AddExt.IsEmpty()) - { - s += L" ("; - s += ext.AddExt; - s += L')'; - } - s += L' '; - } - PrintString(stdStream, s, 14); - stdStream << " "; - const CByteBuffer &sig = arc.StartSignature; - for (size_t j = 0; j < sig.GetCapacity(); j++) - { - Byte b = sig[j]; - if (b > 0x20 && b < 0x80) - { - stdStream << (char)b; - } - else - { - stdStream << GetHex((Byte)((b >> 4) & 0xF)); - stdStream << GetHex((Byte)(b & 0xF)); - } - stdStream << ' '; - } - stdStream << endl; - } - stdStream << endl << "Codecs:" << endl; - - #ifdef EXTERNAL_CODECS - UInt32 numMethods; - if (codecs->GetNumberOfMethods(&numMethods) == S_OK) - for (UInt32 j = 0; j < numMethods; j++) - { - int libIndex = codecs->GetCodecLibIndex(j); - if (libIndex >= 0) - { - char s[16]; - ConvertUInt32ToString(libIndex, s); - PrintString(stdStream, s, 2); - } - else - stdStream << " "; - stdStream << ' '; - stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' '); - UInt64 id; - stdStream << " "; - HRESULT res = codecs->GetCodecId(j, id); - if (res != S_OK) - id = (UInt64)(Int64)-1; - char s[32]; - ConvertUInt64ToString(id, s, 16); - PrintString(stdStream, s, 8); - stdStream << " "; - PrintString(stdStream, codecs->GetCodecName(j), 11); - stdStream << endl; - /* - if (res != S_OK) - throw "incorrect Codec ID"; - */ - } - #endif - return S_OK; - } - else if (options.Command.CommandType == NCommandType::kBenchmark) - { - if (options.Method.CompareNoCase(L"CRC") == 0) - { - HRESULT res = CrcBenchCon((FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize); - if (res != S_OK) - { - if (res == S_FALSE) - { - stdStream << "\nCRC Error\n"; - return NExitCode::kFatalError; - } - throw CSystemException(res); - } - } - else - { - HRESULT res; - #ifdef EXTERNAL_CODECS - CObjectVector externalCodecs; - res = LoadExternalCodecs(compressCodecsInfo, externalCodecs); - if (res != S_OK) - throw CSystemException(res); - #endif - res = LzmaBenchCon( - #ifdef EXTERNAL_CODECS - compressCodecsInfo, &externalCodecs, - #endif - (FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize); - if (res != S_OK) - { - if (res == S_FALSE) - { - stdStream << "\nDecoding Error\n"; - return NExitCode::kFatalError; - } - throw CSystemException(res); - } - } - } - else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) - { - if (isExtractGroupCommand) - { - CExtractCallbackConsole *ecs = new CExtractCallbackConsole; - CMyComPtr extractCallback = ecs; - - ecs->OutStream = &stdStream; - - #ifndef _NO_CRYPTO - ecs->PasswordIsDefined = options.PasswordEnabled; - ecs->Password = options.Password; - #endif - - ecs->Init(); - - COpenCallbackConsole openCallback; - openCallback.OutStream = &stdStream; - - #ifndef _NO_CRYPTO - openCallback.PasswordIsDefined = options.PasswordEnabled; - openCallback.Password = options.Password; - #endif - - CExtractOptions eo; - eo.StdInMode = options.StdInMode; - eo.StdOutMode = options.StdOutMode; - eo.PathMode = options.Command.GetPathMode(); - eo.TestMode = options.Command.IsTestMode(); - eo.OverwriteMode = options.OverwriteMode; - eo.OutputDir = options.OutputDir; - eo.YesToAll = options.YesToAll; - eo.CalcCrc = options.CalcCrc; - #if !defined(_7ZIP_ST) && !defined(_SFX) - eo.Properties = options.ExtractProperties; - #endif - UString errorMessage; - CDecompressStat stat; - HRESULT result = DecompressArchives( - codecs, - formatIndices, - options.ArchivePathsSorted, - options.ArchivePathsFullSorted, - options.WildcardCensor.Pairs.Front().Head, - eo, &openCallback, ecs, errorMessage, stat); - if (!errorMessage.IsEmpty()) - { - stdStream << endl << "Error: " << errorMessage; - if (result == S_OK) - result = E_FAIL; - } - - stdStream << endl; - if (ecs->NumArchives > 1) - stdStream << "Archives: " << ecs->NumArchives << endl; - if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0) - { - if (ecs->NumArchives > 1) - { - stdStream << endl; - if (ecs->NumArchiveErrors != 0) - stdStream << "Archive Errors: " << ecs->NumArchiveErrors << endl; - if (ecs->NumFileErrors != 0) - stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl; - } - if (result != S_OK) - throw CSystemException(result); - return NExitCode::kFatalError; - } - if (result != S_OK) - throw CSystemException(result); - if (stat.NumFolders != 0) - stdStream << "Folders: " << stat.NumFolders << endl; - if (stat.NumFiles != 1 || stat.NumFolders != 0) - stdStream << "Files: " << stat.NumFiles << endl; - stdStream - << "Size: " << stat.UnpackSize << endl - << "Compressed: " << stat.PackSize << endl; - if (options.CalcCrc) - { - char s[16]; - ConvertUInt32ToHexWithZeros(stat.CrcSum, s); - stdStream << "CRC: " << s << endl; - } - } - else - { - UInt64 numErrors = 0; - HRESULT result = ListArchives( - codecs, - formatIndices, - options.StdInMode, - options.ArchivePathsSorted, - options.ArchivePathsFullSorted, - options.WildcardCensor.Pairs.Front().Head, - options.EnableHeaders, - options.TechMode, - #ifndef _NO_CRYPTO - options.PasswordEnabled, - options.Password, - #endif - numErrors); - if (numErrors > 0) - { - g_StdOut << endl << "Errors: " << numErrors; - return NExitCode::kFatalError; - } - if (result != S_OK) - throw CSystemException(result); - } - } - else if (options.Command.IsFromUpdateGroup()) - { - CUpdateOptions &uo = options.UpdateOptions; - if (uo.SfxMode && uo.SfxModule.IsEmpty()) - uo.SfxModule = kDefaultSfxModule; - - COpenCallbackConsole openCallback; - openCallback.OutStream = &stdStream; - - #ifndef _NO_CRYPTO - bool passwordIsDefined = - options.PasswordEnabled && !options.Password.IsEmpty(); - openCallback.PasswordIsDefined = passwordIsDefined; - openCallback.Password = options.Password; - #endif - - CUpdateCallbackConsole callback; - callback.EnablePercents = options.EnablePercents; - - #ifndef _NO_CRYPTO - callback.PasswordIsDefined = passwordIsDefined; - callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty(); - callback.Password = options.Password; - #endif - callback.StdOutMode = uo.StdOutMode; - callback.Init(&stdStream); - - CUpdateErrorInfo errorInfo; - - if (!uo.Init(codecs, formatIndices, options.ArchiveName)) - throw kUnsupportedArcTypeMessage; - HRESULT result = UpdateArchive(codecs, - options.WildcardCensor, uo, - errorInfo, &openCallback, &callback); - -#ifdef ENV_UNIX - if (uo.SfxMode) - { - void myAddExeFlag(const UString &name); - for(int i = 0; i < uo.Commands.Size(); i++) - { - CUpdateArchiveCommand &command = uo.Commands[i]; - if (!uo.StdOutMode) - { - myAddExeFlag(command.ArchivePath.GetFinalPath()); - } - } - } -#endif - - int exitCode = NExitCode::kSuccess; - if (callback.CantFindFiles.Size() > 0) - { - stdStream << endl; - stdStream << "WARNINGS for files:" << endl << endl; - int numErrors = callback.CantFindFiles.Size(); - for (int i = 0; i < numErrors; i++) - { - stdStream << callback.CantFindFiles[i] << " : "; - stdStream << NError::MyFormatMessageW(callback.CantFindCodes[i]) << endl; - } - stdStream << "----------------" << endl; - stdStream << "WARNING: Cannot find " << numErrors << " file"; - if (numErrors > 1) - stdStream << "s"; - stdStream << endl; - exitCode = NExitCode::kWarning; - } - - if (result != S_OK) - { - UString message; - if (!errorInfo.Message.IsEmpty()) - { - message += errorInfo.Message; - message += L"\n"; - } - if (!errorInfo.FileName.IsEmpty()) - { - message += errorInfo.FileName; - message += L"\n"; - } - if (!errorInfo.FileName2.IsEmpty()) - { - message += errorInfo.FileName2; - message += L"\n"; - } - if (errorInfo.SystemError != 0) - { - message += NError::MyFormatMessageW(errorInfo.SystemError); - message += L"\n"; - } - if (!message.IsEmpty()) - stdStream << L"\nError:\n" << message; - throw CSystemException(result); - } - int numErrors = callback.FailedFiles.Size(); - if (numErrors == 0) - { - if (callback.CantFindFiles.Size() == 0) - stdStream << kEverythingIsOk << endl; - } - else - { - stdStream << endl; - stdStream << "WARNINGS for files:" << endl << endl; - for (int i = 0; i < numErrors; i++) - { - stdStream << callback.FailedFiles[i] << " : "; - stdStream << NError::MyFormatMessageW(callback.FailedCodes[i]) << endl; - } - stdStream << "----------------" << endl; - stdStream << "WARNING: Cannot open " << numErrors << " file"; - if (numErrors > 1) - stdStream << "s"; - stdStream << endl; - exitCode = NExitCode::kWarning; - } - return exitCode; - } - else - PrintHelpAndExit(stdStream); - return 0; -} diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/MainAr.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Console/MainAr.cpp deleted file mode 100644 index 68059575b..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Console/MainAr.cpp +++ /dev/null @@ -1,127 +0,0 @@ -// MainAr.cpp - -#include "StdAfx.h" - -#include "Common/NewHandler.h" // FIXME - -#include "Common/MyException.h" -#include "Common/StdOutStream.h" - -#include "Windows/Error.h" -#include "Windows/NtCheck.h" - -#include "../Common/ArchiveCommandLine.h" -#include "../Common/ExitCode.h" - -#include "ConsoleClose.h" - -using namespace NWindows; - -CStdOutStream *g_StdStream = 0; - -extern int Main2( - #ifndef _WIN32 - int numArgs, const char *args[] - #endif -); - -static const char *kExceptionErrorMessage = "\n\nError:\n"; -static const char *kUserBreak = "\nBreak signaled\n"; -static const char *kMemoryExceptionMessage = "\n\nERROR: Can't allocate required memory!\n"; -static const char *kUnknownExceptionMessage = "\n\nUnknown Error\n"; -static const char *kInternalExceptionMessage = "\n\nInternal Error #"; - -#define NT_CHECK_FAIL_ACTION (*g_StdStream) << "Unsupported Windows version"; return NExitCode::kFatalError; - -int MY_CDECL main -( - #ifndef _WIN32 - int numArgs, const char *args[] - #endif -) -{ - g_StdStream = &g_StdOut; - - NT_CHECK - - NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter; - int res = 0; - try - { - res = Main2( - #ifndef _WIN32 - numArgs, args - #endif - ); - } - catch(const CNewException &) - { - (*g_StdStream) << kMemoryExceptionMessage; - return (NExitCode::kMemoryError); - } - catch(const NConsoleClose::CCtrlBreakException &) - { - (*g_StdStream) << endl << kUserBreak; - return (NExitCode::kUserBreak); - } - catch(const CArchiveCommandLineException &e) - { - (*g_StdStream) << kExceptionErrorMessage << e << endl; - return (NExitCode::kUserError); - } - catch(const CSystemException &systemError) - { - if (systemError.ErrorCode == E_OUTOFMEMORY) - { - (*g_StdStream) << kMemoryExceptionMessage; - return (NExitCode::kMemoryError); - } - if (systemError.ErrorCode == E_ABORT) - { - (*g_StdStream) << endl << kUserBreak; - return (NExitCode::kUserBreak); - } - UString message; - NError::MyFormatMessage(systemError.ErrorCode, message); - (*g_StdStream) << endl << endl << "System error:" << endl << message << endl; - return (NExitCode::kFatalError); - } - catch(NExitCode::EEnum &exitCode) - { - (*g_StdStream) << kInternalExceptionMessage << exitCode << endl; - return (exitCode); - } - /* - catch(const NExitCode::CMultipleErrors &multipleErrors) - { - (*g_StdStream) << endl << multipleErrors.NumErrors << " errors" << endl; - return (NExitCode::kFatalError); - } - */ - catch(const UString &s) - { - (*g_StdStream) << kExceptionErrorMessage << s << endl; - return (NExitCode::kFatalError); - } - catch(const AString &s) - { - (*g_StdStream) << kExceptionErrorMessage << s << endl; - return (NExitCode::kFatalError); - } - catch(const char *s) - { - (*g_StdStream) << kExceptionErrorMessage << s << endl; - return (NExitCode::kFatalError); - } - catch(int t) - { - (*g_StdStream) << kInternalExceptionMessage << t << endl; - return (NExitCode::kFatalError); - } - catch(...) - { - (*g_StdStream) << kUnknownExceptionMessage; - return (NExitCode::kFatalError); - } - return res; -} diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/OpenCallbackConsole.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Console/OpenCallbackConsole.cpp deleted file mode 100644 index 7dba2ad5d..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Console/OpenCallbackConsole.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// OpenCallbackConsole.cpp - -#include "StdAfx.h" - -#include "OpenCallbackConsole.h" - -#include "ConsoleClose.h" -#include "UserInputUtils.h" - -HRESULT COpenCallbackConsole::Open_CheckBreak() -{ - if (NConsoleClose::TestBreakSignal()) - return E_ABORT; - return S_OK; -} - -HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *, const UInt64 *) -{ - return Open_CheckBreak(); -} - -HRESULT COpenCallbackConsole::Open_SetCompleted(const UInt64 *, const UInt64 *) -{ - return Open_CheckBreak(); -} - -#ifndef _NO_CRYPTO - -HRESULT COpenCallbackConsole::Open_CryptoGetTextPassword(BSTR *password) -{ - PasswordWasAsked = true; - RINOK(Open_CheckBreak()); - if (!PasswordIsDefined) - { - Password = GetPassword(OutStream); - PasswordIsDefined = true; - } - return StringToBstr(Password, password); -} - -HRESULT COpenCallbackConsole::Open_GetPasswordIfAny(UString &password) -{ - if (PasswordIsDefined) - password = Password; - return S_OK; -} - -bool COpenCallbackConsole::Open_WasPasswordAsked() -{ - return PasswordWasAsked; -} - -void COpenCallbackConsole::Open_ClearPasswordWasAskedFlag() -{ - PasswordWasAsked = false; -} - -#endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/OpenCallbackConsole.h b/src/libs/7zip/unix/CPP/7zip/UI/Console/OpenCallbackConsole.h deleted file mode 100644 index c002e6a72..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Console/OpenCallbackConsole.h +++ /dev/null @@ -1,24 +0,0 @@ -// OpenCallbackConsole.h - -#ifndef __OPENCALLBACKCONSOLE_H -#define __OPENCALLBACKCONSOLE_H - -#include "Common/StdOutStream.h" -#include "../Common/ArchiveOpenCallback.h" - -class COpenCallbackConsole: public IOpenCallbackUI -{ -public: - INTERFACE_IOpenCallbackUI(;) - - CStdOutStream *OutStream; - - #ifndef _NO_CRYPTO - bool PasswordIsDefined; - bool PasswordWasAsked; - UString Password; - COpenCallbackConsole(): PasswordIsDefined(false), PasswordWasAsked(false) {} - #endif -}; - -#endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.cpp index 28452b177..f2889957a 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.cpp +++ b/src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.cpp @@ -2,18 +2,18 @@ #include "StdAfx.h" -#include "Common/IntToString.h" -#include "Common/MyString.h" +#include "../../../Common/Defs.h" +#include "../../../Common/IntToString.h" #include "PercentPrinter.h" -const int kPaddingSize = 2; -const int kPercentsSize = 4; -const int kMaxExtraSize = kPaddingSize + 32 + kPercentsSize; +static const unsigned kPaddingSize = 2; +static const unsigned kPercentsSize = 4; +static const unsigned kMaxExtraSize = kPaddingSize + 32 + kPercentsSize; -static void ClearPrev(char *p, int num) +static void ClearPrev(char *p, unsigned num) { - int i; + unsigned i; for (i = 0; i < num; i++) *p++ = '\b'; for (i = 0; i < num; i++) *p++ = ' '; for (i = 0; i < num; i++) *p++ = '\b'; @@ -51,18 +51,30 @@ void CPercentPrinter::PrintNewLine() void CPercentPrinter::RePrintRatio() { char s[32]; - ConvertUInt64ToString(((m_Total == 0) ? 0 : (m_CurValue * 100 / m_Total)), s); - int size = (int)strlen(s); - s[size++] = '%'; - s[size] = '\0'; + unsigned size; + { + char c = '%'; + UInt64 value = 0; + if (m_Total == (UInt64)(Int64)-1) + { + value = m_CurValue >> 20; + c = 'M'; + } + else if (m_Total != 0) + value = m_CurValue * 100 / m_Total; + ConvertUInt64ToString(value, s); + size = (unsigned)strlen(s); + s[size++] = c; + s[size] = '\0'; + } - int extraSize = kPaddingSize + MyMax(size, kPercentsSize); + unsigned extraSize = kPaddingSize + MyMax(size, kPercentsSize); if (extraSize < m_NumExtraChars) extraSize = m_NumExtraChars; char fullString[kMaxExtraSize * 3]; char *p = fullString; - int i; + unsigned i; if (m_NumExtraChars == 0) { for (i = 0; i < extraSize; i++) @@ -73,7 +85,7 @@ void CPercentPrinter::RePrintRatio() for (i = 0; i < m_NumExtraChars; i++) *p++ = '\b'; m_NumExtraChars = extraSize; - for (; size < m_NumExtraChars; size++) + for (; size < extraSize; size++) *p++ = ' '; MyStringCopy(p, s); (*OutStream) << fullString; diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.h b/src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.h index 97f2e6adb..509bab5fc 100644 --- a/src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.h +++ b/src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.h @@ -1,10 +1,9 @@ // PercentPrinter.h -#ifndef __PERCENTPRINTER_H -#define __PERCENTPRINTER_H +#ifndef __PERCENT_PRINTER_H +#define __PERCENT_PRINTER_H -#include "Common/Types.h" -#include "Common/StdOutStream.h" +#include "../../../Common/StdOutStream.h" class CPercentPrinter { @@ -12,12 +11,12 @@ class CPercentPrinter UInt64 m_PrevValue; UInt64 m_CurValue; UInt64 m_Total; - int m_NumExtraChars; + unsigned m_NumExtraChars; public: CStdOutStream *OutStream; CPercentPrinter(UInt64 minStepSize = 1): m_MinStepSize(minStepSize), - m_PrevValue(0), m_CurValue(0), m_Total(1), m_NumExtraChars(0) {} + m_PrevValue(0), m_CurValue(0), m_Total((UInt64)(Int64)-1), m_NumExtraChars(0) {} void SetTotal(UInt64 total) { m_Total = total; m_PrevValue = 0; } void SetRatio(UInt64 doneValue) { m_CurValue = doneValue; } void PrintString(const char *s); diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp deleted file mode 100644 index e0eb4dec7..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp +++ /dev/null @@ -1,261 +0,0 @@ -// UpdateCallbackConsole.cpp - -#include "StdAfx.h" - -#include "UpdateCallbackConsole.h" - -#include "Windows/Error.h" -#ifndef _7ZIP_ST -#include "Windows/Synchronization.h" -#endif - -#include "ConsoleClose.h" -#include "UserInputUtils.h" - -using namespace NWindows; - -#ifndef _7ZIP_ST -static NSynchronization::CCriticalSection g_CriticalSection; -#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection); -#else -#define MT_LOCK -#endif - -static const wchar_t *kEmptyFileAlias = L"[Content]"; - -static const char *kCreatingArchiveMessage = "Creating archive "; -static const char *kUpdatingArchiveMessage = "Updating archive "; -static const char *kScanningMessage = "Scanning"; - - -HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result) -{ - (*OutStream) << endl; - if (result != S_OK) - (*OutStream) << "Error: " << name << " is not supported archive" << endl; - return S_OK; -} - -HRESULT CUpdateCallbackConsole::StartScanning() -{ - (*OutStream) << kScanningMessage; - return S_OK; -} - -HRESULT CUpdateCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, const wchar_t * /* path */) -{ - return CheckBreak(); -} - -HRESULT CUpdateCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError) -{ - CantFindFiles.Add(name); - CantFindCodes.Add(systemError); - // m_PercentPrinter.ClosePrint(); - if (!m_WarningsMode) - { - (*OutStream) << endl << endl; - m_PercentPrinter.PrintNewLine(); - m_WarningsMode = true; - } - m_PercentPrinter.PrintString(name); - m_PercentPrinter.PrintString(": WARNING: "); - m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError)); - m_PercentPrinter.PrintNewLine(); - return S_OK; -} - -HRESULT CUpdateCallbackConsole::FinishScanning() -{ - (*OutStream) << endl << endl; - return S_OK; -} - -HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating) -{ - if(updating) - (*OutStream) << kUpdatingArchiveMessage; - else - (*OutStream) << kCreatingArchiveMessage; - if (name != 0) - (*OutStream) << name; - else - (*OutStream) << "StdOut"; - (*OutStream) << endl << endl; - return S_OK; -} - -HRESULT CUpdateCallbackConsole::FinishArchive() -{ - (*OutStream) << endl; - return S_OK; -} - -HRESULT CUpdateCallbackConsole::CheckBreak() -{ - if (NConsoleClose::TestBreakSignal()) - return E_ABORT; - return S_OK; -} - -HRESULT CUpdateCallbackConsole::Finilize() -{ - MT_LOCK - if (m_NeedBeClosed) - { - if (EnablePercents) - { - m_PercentPrinter.ClosePrint(); - } - if (!StdOutMode && m_NeedNewLine) - { - m_PercentPrinter.PrintNewLine(); - m_NeedNewLine = false; - } - m_NeedBeClosed = false; - } - return S_OK; -} - -HRESULT CUpdateCallbackConsole::SetNumFiles(UInt64 /* numFiles */) -{ - return S_OK; -} - -HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size) -{ - MT_LOCK - if (EnablePercents) - m_PercentPrinter.SetTotal(size); - return S_OK; -} - -HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue) -{ - MT_LOCK - if (completeValue != NULL) - { - if (EnablePercents) - { - m_PercentPrinter.SetRatio(*completeValue); - m_PercentPrinter.PrintRatio(); - m_NeedBeClosed = true; - } - } - if (NConsoleClose::TestBreakSignal()) - return E_ABORT; - return S_OK; -} - -HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */) -{ - if (NConsoleClose::TestBreakSignal()) - return E_ABORT; - return S_OK; -} - -HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isAnti) -{ - MT_LOCK - if (StdOutMode) - return S_OK; - if(isAnti) - m_PercentPrinter.PrintString("Anti item "); - else - m_PercentPrinter.PrintString("Compressing "); - if (name[0] == 0) - name = kEmptyFileAlias; - m_PercentPrinter.PrintString(name); - if (EnablePercents) - m_PercentPrinter.RePrintRatio(); - return S_OK; -} - -HRESULT CUpdateCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError) -{ - MT_LOCK - FailedCodes.Add(systemError); - FailedFiles.Add(name); - // if (systemError == ERROR_SHARING_VIOLATION) - { - m_PercentPrinter.ClosePrint(); - m_PercentPrinter.PrintNewLine(); - m_PercentPrinter.PrintString("WARNING: "); - m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError)); - return S_FALSE; - } - // return systemError; -} - -HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 ) -{ - m_NeedBeClosed = true; - m_NeedNewLine = true; - return S_OK; -} - -HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) -{ - *password = NULL; - - #ifdef _NO_CRYPTO - - *passwordIsDefined = false; - return S_OK; - - #else - - if (!PasswordIsDefined) - { - if (AskPassword) - { - Password = GetPassword(OutStream,true); - PasswordIsDefined = true; - } - } - *passwordIsDefined = BoolToInt(PasswordIsDefined); - return StringToBstr(Password, password); - - #endif -} - -HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password) -{ - *password = NULL; - - #ifdef _NO_CRYPTO - - return E_NOTIMPL; - - #else - - if (!PasswordIsDefined) - { - { - Password = GetPassword(OutStream); - PasswordIsDefined = true; - } - } - return StringToBstr(Password, password); - - #endif -} - -/* -HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name) -{ - // MT_LOCK - if (StdOutMode) - return S_OK; - RINOK(Finilize()); - m_PercentPrinter.PrintString("Deleting "); - if (name[0] == 0) - name = kEmptyFileAlias; - m_PercentPrinter.PrintString(name); - if (EnablePercents) - m_PercentPrinter.RePrintRatio(); - m_NeedBeClosed = true; - m_NeedNewLine = true; - return S_OK; -} -*/ diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/UpdateCallbackConsole.h b/src/libs/7zip/unix/CPP/7zip/UI/Console/UpdateCallbackConsole.h deleted file mode 100644 index 5ffe3eb7a..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Console/UpdateCallbackConsole.h +++ /dev/null @@ -1,62 +0,0 @@ -// UpdateCallbackConsole.h - -#ifndef __UPDATE_CALLBACK_CONSOLE_H -#define __UPDATE_CALLBACK_CONSOLE_H - -#include "Common/StdOutStream.h" - -#include "../Common/Update.h" - -#include "PercentPrinter.h" - -class CUpdateCallbackConsole: public IUpdateCallbackUI2 -{ - CPercentPrinter m_PercentPrinter; - bool m_NeedBeClosed; - bool m_NeedNewLine; - - bool m_WarningsMode; - - CStdOutStream *OutStream; -public: - bool EnablePercents; - bool StdOutMode; - - #ifndef _NO_CRYPTO - bool PasswordIsDefined; - UString Password; - bool AskPassword; - #endif - - CUpdateCallbackConsole(): - m_PercentPrinter(1 << 16), - #ifndef _NO_CRYPTO - PasswordIsDefined(false), - AskPassword(false), - #endif - StdOutMode(false), - EnablePercents(true), - m_WarningsMode(false) - {} - - ~CUpdateCallbackConsole() { Finilize(); } - void Init(CStdOutStream *outStream) - { - m_NeedBeClosed = false; - m_NeedNewLine = false; - FailedFiles.Clear(); - FailedCodes.Clear(); - OutStream = outStream; - m_PercentPrinter.OutStream = outStream; - } - - INTERFACE_IUpdateCallbackUI2(;) - - UStringVector FailedFiles; - CRecordVector FailedCodes; - - UStringVector CantFindFiles; - CRecordVector CantFindCodes; -}; - -#endif diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/UserInputUtils.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Console/UserInputUtils.cpp deleted file mode 100644 index 4733e4ffb..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Console/UserInputUtils.cpp +++ /dev/null @@ -1,96 +0,0 @@ -// UserInputUtils.cpp - -#include "StdAfx.h" - -#include "Common/StdInStream.h" -#include "Common/StringConvert.h" - -#include "UserInputUtils.h" - -#ifdef USE_FLTK -// the programs like file-roller or xarchiver do not support archives with password -// these programs freeze because p7zip is waiting for a password -// defining USE_FLTK allows p7zip to use a popup in order to ask the password. -#include -#include -#include -#else -#ifdef ENV_HAVE_GETPASS -#include -#include -#include "Common/MyException.h" -#endif -#endif - -static const char kYes = 'Y'; -static const char kNo = 'N'; -static const char kYesAll = 'A'; -static const char kNoAll = 'S'; -static const char kAutoRenameAll = 'U'; -static const char kQuit = 'Q'; - -static const char *kFirstQuestionMessage = "?\n"; -static const char *kHelpQuestionMessage = - "(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename all / (Q)uit? "; - -// return true if pressed Quite; - -NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream) -{ - (*outStream) << kFirstQuestionMessage; - for (;;) - { - (*outStream) << kHelpQuestionMessage; - outStream->Flush(); - AString scannedString = g_StdIn.ScanStringUntilNewLine(); - scannedString.Trim(); - if (!scannedString.IsEmpty()) - switch( - ::MyCharUpper( - #ifdef UNDER_CE - (wchar_t) - #endif - scannedString[0])) - { - case kYes: - return NUserAnswerMode::kYes; - case kNo: - return NUserAnswerMode::kNo; - case kYesAll: - return NUserAnswerMode::kYesAll; - case kNoAll: - return NUserAnswerMode::kNoAll; - case kAutoRenameAll: - return NUserAnswerMode::kAutoRenameAll; - case kQuit: - return NUserAnswerMode::kQuit; - } - } -} - -UString GetPassword(CStdOutStream *outStream,bool verify) -{ -#ifdef USE_FLTK - const char *r = fl_password("Enter password", 0); - AString oemPassword = ""; - if (r) oemPassword = r; -#else /* USE_FLTK */ -#ifdef ENV_HAVE_GETPASS - (*outStream) << "\nEnter password (will not be echoed) :"; - outStream->Flush(); - AString oemPassword = getpass(""); - if (verify) - { - (*outStream) << "Verify password (will not be echoed) :"; - outStream->Flush(); - AString oemPassword2 = getpass(""); - if (oemPassword != oemPassword2) throw "password verification failed"; - } -#else - (*outStream) << "\nEnter password:"; - outStream->Flush(); - AString oemPassword = g_StdIn.ScanStringUntilNewLine(); -#endif -#endif /* USE_FLTK */ - return MultiByteToUnicodeString(oemPassword, CP_OEMCP); -} diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/UserInputUtils.h b/src/libs/7zip/unix/CPP/7zip/UI/Console/UserInputUtils.h deleted file mode 100644 index 8c575194d..000000000 --- a/src/libs/7zip/unix/CPP/7zip/UI/Console/UserInputUtils.h +++ /dev/null @@ -1,24 +0,0 @@ -// UserInputUtils.h - -#ifndef __USERINPUTUTILS_H -#define __USERINPUTUTILS_H - -#include "Common/StdOutStream.h" - -namespace NUserAnswerMode { - -enum EEnum -{ - kYes, - kNo, - kYesAll, - kNoAll, - kAutoRenameAll, - kQuit -}; -} - -NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream); -UString GetPassword(CStdOutStream *outStream,bool verify = false); - -#endif -- cgit v1.2.3