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/win/7zC.txt | 194 -- src/libs/7zip/win/7zFormat.txt | 471 --- src/libs/7zip/win/C/7z.h | 203 -- src/libs/7zip/win/C/7zAlloc.c | 76 - src/libs/7zip/win/C/7zAlloc.h | 15 - src/libs/7zip/win/C/7zBuf.c | 36 - src/libs/7zip/win/C/7zBuf.h | 39 - src/libs/7zip/win/C/7zBuf2.c | 45 - src/libs/7zip/win/C/7zCrc.c | 69 +- src/libs/7zip/win/C/7zCrc.h | 4 +- src/libs/7zip/win/C/7zCrcOpt.c | 40 +- src/libs/7zip/win/C/7zDec.c | 470 --- src/libs/7zip/win/C/7zFile.c | 284 -- src/libs/7zip/win/C/7zFile.h | 83 - src/libs/7zip/win/C/7zIn.c | 1402 --------- src/libs/7zip/win/C/7zStream.c | 6 +- src/libs/7zip/win/C/7zTypes.h | 256 ++ src/libs/7zip/win/C/7zVersion.h | 11 +- src/libs/7zip/win/C/Alloc.c | 10 +- src/libs/7zip/win/C/Bcj2.c | 132 - src/libs/7zip/win/C/Bcj2.h | 38 - src/libs/7zip/win/C/Bra.c | 12 +- src/libs/7zip/win/C/Bra.h | 20 +- src/libs/7zip/win/C/Bra86.c | 99 +- src/libs/7zip/win/C/BraIA64.c | 14 +- src/libs/7zip/win/C/C.pri | 48 + src/libs/7zip/win/C/Compiler.h | 28 + src/libs/7zip/win/C/CpuArch.c | 28 +- src/libs/7zip/win/C/CpuArch.h | 16 +- src/libs/7zip/win/C/Delta.c | 2 + src/libs/7zip/win/C/Delta.h | 12 +- src/libs/7zip/win/C/LzFind.c | 6 +- src/libs/7zip/win/C/LzFind.h | 12 +- src/libs/7zip/win/C/LzFindMt.c | 33 +- src/libs/7zip/win/C/LzFindMt.h | 14 +- src/libs/7zip/win/C/Lzma2Dec.c | 42 +- src/libs/7zip/win/C/Lzma2Dec.h | 10 +- src/libs/7zip/win/C/Lzma2Enc.c | 40 +- src/libs/7zip/win/C/Lzma2Enc.h | 10 +- src/libs/7zip/win/C/Lzma86.h | 111 - src/libs/7zip/win/C/Lzma86Dec.c | 56 - src/libs/7zip/win/C/Lzma86Enc.c | 108 - src/libs/7zip/win/C/LzmaDec.c | 78 +- src/libs/7zip/win/C/LzmaDec.h | 16 +- src/libs/7zip/win/C/LzmaEnc.c | 80 +- src/libs/7zip/win/C/LzmaEnc.h | 14 +- src/libs/7zip/win/C/LzmaLib.c | 46 - src/libs/7zip/win/C/LzmaLib.h | 135 - src/libs/7zip/win/C/MtCoder.c | 6 +- src/libs/7zip/win/C/MtCoder.h | 4 +- src/libs/7zip/win/C/Precomp.h | 10 + src/libs/7zip/win/C/RotateDefs.h | 8 +- src/libs/7zip/win/C/Sha256.c | 4 +- src/libs/7zip/win/C/Sha256.h | 4 +- src/libs/7zip/win/C/Threads.c | 27 +- src/libs/7zip/win/C/Threads.h | 26 +- src/libs/7zip/win/C/Types.h | 254 -- src/libs/7zip/win/C/Xz.c | 2 + src/libs/7zip/win/C/Xz.h | 47 +- src/libs/7zip/win/C/XzCrc64.c | 89 +- src/libs/7zip/win/C/XzCrc64.h | 4 +- src/libs/7zip/win/C/XzCrc64Opt.c | 69 + src/libs/7zip/win/C/XzDec.c | 108 +- src/libs/7zip/win/C/XzEnc.c | 309 +- src/libs/7zip/win/C/XzEnc.h | 32 +- src/libs/7zip/win/C/XzIn.c | 55 +- src/libs/7zip/win/CPP/7zip/7zip.pri | 6 + src/libs/7zip/win/CPP/7zip/Archive/7z/7z.pri | 30 + .../win/CPP/7zip/Archive/7z/7zCompressionMode.cpp | 3 - .../win/CPP/7zip/Archive/7z/7zCompressionMode.h | 9 +- src/libs/7zip/win/CPP/7zip/Archive/7z/7zDecode.cpp | 153 +- src/libs/7zip/win/CPP/7zip/Archive/7z/7zDecode.h | 13 +- src/libs/7zip/win/CPP/7zip/Archive/7z/7zEncode.cpp | 136 +- src/libs/7zip/win/CPP/7zip/Archive/7z/7zEncode.h | 2 + .../7zip/win/CPP/7zip/Archive/7z/7zExtract.cpp | 58 +- .../win/CPP/7zip/Archive/7z/7zFolderInStream.cpp | 4 +- .../win/CPP/7zip/Archive/7z/7zFolderInStream.h | 2 +- .../win/CPP/7zip/Archive/7z/7zFolderOutStream.cpp | 2 +- .../win/CPP/7zip/Archive/7z/7zFolderOutStream.h | 6 +- .../7zip/win/CPP/7zip/Archive/7z/7zHandler.cpp | 717 +++-- src/libs/7zip/win/CPP/7zip/Archive/7z/7zHandler.h | 84 +- .../7zip/win/CPP/7zip/Archive/7z/7zHandlerOut.cpp | 708 ++++- src/libs/7zip/win/CPP/7zip/Archive/7z/7zHeader.cpp | 5 + src/libs/7zip/win/CPP/7zip/Archive/7z/7zHeader.h | 14 +- src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.cpp | 1459 +++++---- src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.h | 359 ++- src/libs/7zip/win/CPP/7zip/Archive/7z/7zItem.h | 214 +- src/libs/7zip/win/CPP/7zip/Archive/7z/7zOut.cpp | 481 +-- src/libs/7zip/win/CPP/7zip/Archive/7z/7zOut.h | 211 +- .../7zip/win/CPP/7zip/Archive/7z/7zProperties.cpp | 56 +- .../7zip/win/CPP/7zip/Archive/7z/7zRegister.cpp | 23 +- .../7zip/win/CPP/7zip/Archive/7z/7zSpecStream.cpp | 10 +- src/libs/7zip/win/CPP/7zip/Archive/7z/7zUpdate.cpp | 708 +++-- src/libs/7zip/win/CPP/7zip/Archive/7z/7zUpdate.h | 44 +- src/libs/7zip/win/CPP/7zip/Archive/7z/StdAfx.cpp | 3 - src/libs/7zip/win/CPP/7zip/Archive/7z/StdAfx.h | 3 +- src/libs/7zip/win/CPP/7zip/Archive/Archive.def | 6 - src/libs/7zip/win/CPP/7zip/Archive/Archive.pri | 6 + src/libs/7zip/win/CPP/7zip/Archive/Archive2.def | 9 - .../7zip/win/CPP/7zip/Archive/ArchiveExports.cpp | 135 - .../win/CPP/7zip/Archive/Common/CoderMixer2.cpp | 74 +- .../7zip/win/CPP/7zip/Archive/Common/CoderMixer2.h | 19 +- .../win/CPP/7zip/Archive/Common/CoderMixer2MT.cpp | 60 +- .../win/CPP/7zip/Archive/Common/CoderMixer2MT.h | 15 +- .../7zip/win/CPP/7zip/Archive/Common/Common.pri | 19 + .../7zip/Archive/Common/CrossThreadProgress.cpp | 15 - .../CPP/7zip/Archive/Common/CrossThreadProgress.h | 37 - .../win/CPP/7zip/Archive/Common/DummyOutStream.cpp | 19 +- .../win/CPP/7zip/Archive/Common/DummyOutStream.h | 7 +- .../win/CPP/7zip/Archive/Common/HandlerOut.cpp | 618 +--- .../7zip/win/CPP/7zip/Archive/Common/HandlerOut.h | 80 +- .../CPP/7zip/Archive/Common/InStreamWithCRC.cpp | 32 +- .../win/CPP/7zip/Archive/Common/ItemNameUtils.cpp | 41 +- .../win/CPP/7zip/Archive/Common/ItemNameUtils.h | 7 +- .../win/CPP/7zip/Archive/Common/MultiStream.cpp | 57 +- .../7zip/win/CPP/7zip/Archive/Common/MultiStream.h | 13 +- .../win/CPP/7zip/Archive/Common/OutStreamWithCRC.h | 1 + .../CPP/7zip/Archive/Common/ParseProperties.cpp | 177 -- .../win/CPP/7zip/Archive/Common/ParseProperties.h | 16 +- src/libs/7zip/win/CPP/7zip/Archive/Common/StdAfx.h | 3 +- src/libs/7zip/win/CPP/7zip/Archive/DllExports2.cpp | 74 - src/libs/7zip/win/CPP/7zip/Archive/IArchive.h | 336 +- src/libs/7zip/win/CPP/7zip/Archive/LzmaHandler.cpp | 348 ++- .../7zip/win/CPP/7zip/Archive/SplitHandler.cpp | 267 +- src/libs/7zip/win/CPP/7zip/Archive/StdAfx.h | 3 +- src/libs/7zip/win/CPP/7zip/Archive/XzHandler.cpp | 752 +++-- src/libs/7zip/win/CPP/7zip/Common/CWrappers.cpp | 44 +- src/libs/7zip/win/CPP/7zip/Common/CWrappers.h | 37 +- src/libs/7zip/win/CPP/7zip/Common/Common.pri | 40 + src/libs/7zip/win/CPP/7zip/Common/CreateCoder.cpp | 218 +- src/libs/7zip/win/CPP/7zip/Common/CreateCoder.h | 41 +- .../win/CPP/7zip/Common/FilePathAutoRename.cpp | 28 +- .../7zip/win/CPP/7zip/Common/FilePathAutoRename.h | 10 +- src/libs/7zip/win/CPP/7zip/Common/FileStreams.cpp | 231 +- src/libs/7zip/win/CPP/7zip/Common/FileStreams.h | 76 +- src/libs/7zip/win/CPP/7zip/Common/FilterCoder.cpp | 24 +- src/libs/7zip/win/CPP/7zip/Common/FilterCoder.h | 22 +- src/libs/7zip/win/CPP/7zip/Common/InBuffer.cpp | 122 +- src/libs/7zip/win/CPP/7zip/Common/InBuffer.h | 101 +- .../7zip/win/CPP/7zip/Common/InOutTempBuffer.cpp | 15 +- .../7zip/win/CPP/7zip/Common/InOutTempBuffer.h | 4 +- .../7zip/win/CPP/7zip/Common/LimitedStreams.cpp | 255 +- src/libs/7zip/win/CPP/7zip/Common/LimitedStreams.h | 142 +- src/libs/7zip/win/CPP/7zip/Common/MethodId.cpp | 27 - src/libs/7zip/win/CPP/7zip/Common/MethodId.h | 2 +- src/libs/7zip/win/CPP/7zip/Common/MethodProps.cpp | 484 ++- src/libs/7zip/win/CPP/7zip/Common/MethodProps.h | 178 +- src/libs/7zip/win/CPP/7zip/Common/OffsetStream.cpp | 35 - src/libs/7zip/win/CPP/7zip/Common/OffsetStream.h | 25 - src/libs/7zip/win/CPP/7zip/Common/OutBuffer.cpp | 57 +- src/libs/7zip/win/CPP/7zip/Common/OutBuffer.h | 37 +- .../7zip/win/CPP/7zip/Common/ProgressUtils.cpp | 2 +- src/libs/7zip/win/CPP/7zip/Common/PropId.cpp | 99 + src/libs/7zip/win/CPP/7zip/Common/RegisterArc.h | 67 +- src/libs/7zip/win/CPP/7zip/Common/RegisterCodec.h | 48 +- src/libs/7zip/win/CPP/7zip/Common/StdAfx.h | 3 +- src/libs/7zip/win/CPP/7zip/Common/StreamBinder.cpp | 148 +- src/libs/7zip/win/CPP/7zip/Common/StreamBinder.h | 36 +- .../7zip/win/CPP/7zip/Common/StreamObjects.cpp | 75 +- src/libs/7zip/win/CPP/7zip/Common/StreamObjects.h | 31 +- src/libs/7zip/win/CPP/7zip/Common/StreamUtils.cpp | 8 +- src/libs/7zip/win/CPP/7zip/Common/StreamUtils.h | 12 +- src/libs/7zip/win/CPP/7zip/Common/UniqBlocks.cpp | 56 + src/libs/7zip/win/CPP/7zip/Common/UniqBlocks.h | 30 + src/libs/7zip/win/CPP/7zip/Common/VirtThread.cpp | 14 +- src/libs/7zip/win/CPP/7zip/Common/VirtThread.h | 11 +- src/libs/7zip/win/CPP/7zip/Compress/Bcj2Coder.cpp | 176 +- src/libs/7zip/win/CPP/7zip/Compress/Bcj2Coder.h | 55 +- src/libs/7zip/win/CPP/7zip/Compress/BranchMisc.cpp | 42 +- .../7zip/win/CPP/7zip/Compress/CodecExports.cpp | 160 - src/libs/7zip/win/CPP/7zip/Compress/Compress.pri | 30 + src/libs/7zip/win/CPP/7zip/Compress/CopyCoder.cpp | 21 +- src/libs/7zip/win/CPP/7zip/Compress/CopyCoder.h | 1 + .../7zip/win/CPP/7zip/Compress/DeltaFilter.cpp | 17 +- .../7zip/win/CPP/7zip/Compress/Lzma2Decoder.cpp | 4 +- .../7zip/win/CPP/7zip/Compress/Lzma2Encoder.cpp | 2 +- src/libs/7zip/win/CPP/7zip/Compress/Lzma2Encoder.h | 2 +- .../7zip/win/CPP/7zip/Compress/LzmaDecoder.cpp | 18 +- src/libs/7zip/win/CPP/7zip/Compress/LzmaDecoder.h | 8 +- .../7zip/win/CPP/7zip/Compress/LzmaEncoder.cpp | 34 +- src/libs/7zip/win/CPP/7zip/Compress/LzmaEncoder.h | 4 +- src/libs/7zip/win/CPP/7zip/Compress/RangeCoder.h | 30 +- .../7zip/win/CPP/7zip/Compress/RangeCoderBit.h | 16 +- src/libs/7zip/win/CPP/7zip/Compress/StdAfx.h | 2 +- src/libs/7zip/win/CPP/7zip/Guid.txt | 38 +- src/libs/7zip/win/CPP/7zip/ICoder.h | 29 +- src/libs/7zip/win/CPP/7zip/IPassword.h | 3 +- src/libs/7zip/win/CPP/7zip/IProgress.h | 2 +- src/libs/7zip/win/CPP/7zip/IStream.h | 89 +- src/libs/7zip/win/CPP/7zip/MyVersion.h | 8 - src/libs/7zip/win/CPP/7zip/PropID.h | 66 +- .../win/CPP/7zip/UI/Common/ArchiveCommandLine.cpp | 1139 ++++--- .../win/CPP/7zip/UI/Common/ArchiveCommandLine.h | 79 +- .../CPP/7zip/UI/Common/ArchiveExtractCallback.cpp | 999 +++++- .../CPP/7zip/UI/Common/ArchiveExtractCallback.h | 208 +- .../7zip/win/CPP/7zip/UI/Common/ArchiveName.cpp | 54 - src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveName.h | 10 - .../win/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp | 42 +- .../win/CPP/7zip/UI/Common/ArchiveOpenCallback.h | 36 +- src/libs/7zip/win/CPP/7zip/UI/Common/Bench.cpp | 1028 ------- src/libs/7zip/win/CPP/7zip/UI/Common/Bench.h | 42 - src/libs/7zip/win/CPP/7zip/UI/Common/Common.pri | 44 + .../7zip/win/CPP/7zip/UI/Common/DefaultName.cpp | 6 +- src/libs/7zip/win/CPP/7zip/UI/Common/DefaultName.h | 6 +- src/libs/7zip/win/CPP/7zip/UI/Common/DirItem.h | 91 +- .../7zip/win/CPP/7zip/UI/Common/EnumDirItems.cpp | 676 +++- .../7zip/win/CPP/7zip/UI/Common/EnumDirItems.h | 18 +- src/libs/7zip/win/CPP/7zip/UI/Common/ExitCode.h | 27 - src/libs/7zip/win/CPP/7zip/UI/Common/Extract.cpp | 368 ++- src/libs/7zip/win/CPP/7zip/UI/Common/Extract.h | 54 +- src/libs/7zip/win/CPP/7zip/UI/Common/ExtractMode.h | 42 +- .../win/CPP/7zip/UI/Common/ExtractingFilePath.cpp | 114 +- .../win/CPP/7zip/UI/Common/ExtractingFilePath.h | 12 +- src/libs/7zip/win/CPP/7zip/UI/Common/HashCalc.cpp | 361 +++ src/libs/7zip/win/CPP/7zip/UI/Common/HashCalc.h | 107 + .../win/CPP/7zip/UI/Common/IFileExtractCallback.h | 32 +- .../7zip/win/CPP/7zip/UI/Common/LoadCodecs.cpp | 769 +++-- src/libs/7zip/win/CPP/7zip/UI/Common/LoadCodecs.h | 190 +- .../7zip/win/CPP/7zip/UI/Common/OpenArchive.cpp | 3247 ++++++++++++++++++-- src/libs/7zip/win/CPP/7zip/UI/Common/OpenArchive.h | 351 ++- .../7zip/win/CPP/7zip/UI/Common/PropIDUtils.cpp | 547 +++- src/libs/7zip/win/CPP/7zip/UI/Common/PropIDUtils.h | 13 +- src/libs/7zip/win/CPP/7zip/UI/Common/Property.h | 6 +- .../7zip/win/CPP/7zip/UI/Common/SetProperties.cpp | 31 +- src/libs/7zip/win/CPP/7zip/UI/Common/SortUtils.cpp | 17 +- src/libs/7zip/win/CPP/7zip/UI/Common/SortUtils.h | 8 +- src/libs/7zip/win/CPP/7zip/UI/Common/StdAfx.h | 5 +- src/libs/7zip/win/CPP/7zip/UI/Common/TempFiles.cpp | 9 +- src/libs/7zip/win/CPP/7zip/UI/Common/TempFiles.h | 8 +- src/libs/7zip/win/CPP/7zip/UI/Common/Update.cpp | 1111 +++++-- src/libs/7zip/win/CPP/7zip/UI/Common/Update.h | 147 +- .../7zip/win/CPP/7zip/UI/Common/UpdateAction.cpp | 10 +- .../7zip/win/CPP/7zip/UI/Common/UpdateAction.h | 29 +- .../7zip/win/CPP/7zip/UI/Common/UpdateCallback.cpp | 453 ++- .../7zip/win/CPP/7zip/UI/Common/UpdateCallback.h | 64 +- .../7zip/win/CPP/7zip/UI/Common/UpdatePair.cpp | 207 +- src/libs/7zip/win/CPP/7zip/UI/Common/UpdatePair.h | 4 +- .../7zip/win/CPP/7zip/UI/Common/UpdateProduce.cpp | 27 +- .../7zip/win/CPP/7zip/UI/Common/UpdateProduce.h | 26 +- src/libs/7zip/win/CPP/7zip/UI/Common/WorkDir.cpp | 59 - src/libs/7zip/win/CPP/7zip/UI/Common/WorkDir.h | 10 - src/libs/7zip/win/CPP/7zip/UI/Common/ZipRegistry.h | 105 - src/libs/7zip/win/CPP/7zip/UI/Console/BenchCon.cpp | 297 -- src/libs/7zip/win/CPP/7zip/UI/Console/BenchCon.h | 16 - src/libs/7zip/win/CPP/7zip/UI/Console/Console.pri | 4 + .../7zip/win/CPP/7zip/UI/Console/ConsoleClose.cpp | 73 - .../7zip/win/CPP/7zip/UI/Console/ConsoleClose.h | 24 - .../CPP/7zip/UI/Console/ExtractCallbackConsole.cpp | 228 -- .../CPP/7zip/UI/Console/ExtractCallbackConsole.h | 73 - src/libs/7zip/win/CPP/7zip/UI/Console/List.cpp | 654 ---- src/libs/7zip/win/CPP/7zip/UI/Console/List.h | 20 - src/libs/7zip/win/CPP/7zip/UI/Console/Main.cpp | 598 ---- src/libs/7zip/win/CPP/7zip/UI/Console/MainAr.cpp | 125 - .../CPP/7zip/UI/Console/OpenCallbackConsole.cpp | 58 - .../win/CPP/7zip/UI/Console/OpenCallbackConsole.h | 24 - .../win/CPP/7zip/UI/Console/PercentPrinter.cpp | 40 +- .../7zip/win/CPP/7zip/UI/Console/PercentPrinter.h | 11 +- src/libs/7zip/win/CPP/7zip/UI/Console/StdAfx.cpp | 3 - src/libs/7zip/win/CPP/7zip/UI/Console/StdAfx.h | 3 +- .../CPP/7zip/UI/Console/UpdateCallbackConsole.cpp | 261 -- .../CPP/7zip/UI/Console/UpdateCallbackConsole.h | 62 - .../win/CPP/7zip/UI/Console/UserInputUtils.cpp | 87 - .../7zip/win/CPP/7zip/UI/Console/UserInputUtils.h | 24 - src/libs/7zip/win/CPP/Common/AutoPtr.h | 35 - src/libs/7zip/win/CPP/Common/Buffer.h | 77 - src/libs/7zip/win/CPP/Common/CRC.cpp | 7 - src/libs/7zip/win/CPP/Common/C_FileIO.cpp | 88 - src/libs/7zip/win/CPP/Common/C_FileIO.h | 47 - src/libs/7zip/win/CPP/Common/ComTry.h | 2 +- src/libs/7zip/win/CPP/Common/CommandLineParser.cpp | 265 +- src/libs/7zip/win/CPP/Common/CommandLineParser.h | 51 +- src/libs/7zip/win/CPP/Common/Common.h | 13 + src/libs/7zip/win/CPP/Common/Common.pri | 35 + src/libs/7zip/win/CPP/Common/DynamicBuffer.h | 50 - src/libs/7zip/win/CPP/Common/IntToString.cpp | 149 +- src/libs/7zip/win/CPP/Common/IntToString.h | 23 +- src/libs/7zip/win/CPP/Common/ListFileUtils.cpp | 120 +- src/libs/7zip/win/CPP/Common/ListFileUtils.h | 11 +- src/libs/7zip/win/CPP/Common/MyBuffer.h | 237 ++ src/libs/7zip/win/CPP/Common/MyCom.h | 63 +- src/libs/7zip/win/CPP/Common/MyGuidDef.h | 2 +- src/libs/7zip/win/CPP/Common/MyInitGuid.h | 23 + src/libs/7zip/win/CPP/Common/MyString.cpp | 1175 ++++++- src/libs/7zip/win/CPP/Common/MyString.h | 922 +++--- src/libs/7zip/win/CPP/Common/MyTypes.h | 30 + src/libs/7zip/win/CPP/Common/MyUnknown.h | 2 +- src/libs/7zip/win/CPP/Common/MyVector.cpp | 87 - src/libs/7zip/win/CPP/Common/MyVector.h | 577 +++- src/libs/7zip/win/CPP/Common/MyWindows.cpp | 145 + src/libs/7zip/win/CPP/Common/MyWindows.h | 30 +- src/libs/7zip/win/CPP/Common/NewHandler.cpp | 66 +- src/libs/7zip/win/CPP/Common/NewHandler.h | 56 +- src/libs/7zip/win/CPP/Common/StdAfx.h | 3 +- src/libs/7zip/win/CPP/Common/StdInStream.cpp | 107 - src/libs/7zip/win/CPP/Common/StdInStream.h | 32 - src/libs/7zip/win/CPP/Common/StdOutStream.cpp | 86 +- src/libs/7zip/win/CPP/Common/StdOutStream.h | 61 +- src/libs/7zip/win/CPP/Common/StringConvert.cpp | 90 +- src/libs/7zip/win/CPP/Common/StringConvert.h | 10 +- src/libs/7zip/win/CPP/Common/StringToInt.cpp | 144 +- src/libs/7zip/win/CPP/Common/StringToInt.h | 23 +- src/libs/7zip/win/CPP/Common/Types.h | 11 - src/libs/7zip/win/CPP/Common/UTFConvert.cpp | 61 +- src/libs/7zip/win/CPP/Common/UTFConvert.h | 5 +- src/libs/7zip/win/CPP/Common/Wildcard.cpp | 391 ++- src/libs/7zip/win/CPP/Common/Wildcard.h | 101 +- src/libs/7zip/win/CPP/Windows/DLL.cpp | 130 +- src/libs/7zip/win/CPP/Windows/DLL.h | 25 +- src/libs/7zip/win/CPP/Windows/Error.cpp | 50 - src/libs/7zip/win/CPP/Windows/Error.h | 33 - src/libs/7zip/win/CPP/Windows/FileDir.cpp | 1050 +++---- src/libs/7zip/win/CPP/Windows/FileDir.h | 180 +- src/libs/7zip/win/CPP/Windows/FileFind.cpp | 605 ++-- src/libs/7zip/win/CPP/Windows/FileFind.h | 127 +- src/libs/7zip/win/CPP/Windows/FileIO.cpp | 430 ++- src/libs/7zip/win/CPP/Windows/FileIO.h | 217 +- src/libs/7zip/win/CPP/Windows/FileLink.cpp | 426 +++ src/libs/7zip/win/CPP/Windows/FileMapping.cpp | 12 - src/libs/7zip/win/CPP/Windows/FileMapping.h | 8 +- src/libs/7zip/win/CPP/Windows/FileName.cpp | 675 +++- src/libs/7zip/win/CPP/Windows/FileName.h | 69 +- src/libs/7zip/win/CPP/Windows/MemoryLock.cpp | 82 - src/libs/7zip/win/CPP/Windows/MemoryLock.h | 15 - src/libs/7zip/win/CPP/Windows/NtCheck.h | 44 - src/libs/7zip/win/CPP/Windows/PropVariant.cpp | 105 +- src/libs/7zip/win/CPP/Windows/PropVariant.h | 97 +- src/libs/7zip/win/CPP/Windows/PropVariantConv.cpp | 99 + src/libs/7zip/win/CPP/Windows/PropVariantConv.h | 30 + .../win/CPP/Windows/PropVariantConversions.cpp | 105 - .../7zip/win/CPP/Windows/PropVariantConversions.h | 14 - src/libs/7zip/win/CPP/Windows/Registry.cpp | 369 --- src/libs/7zip/win/CPP/Windows/Registry.h | 85 - src/libs/7zip/win/CPP/Windows/SecurityUtils.cpp | 179 ++ src/libs/7zip/win/CPP/Windows/SecurityUtils.h | 167 + src/libs/7zip/win/CPP/Windows/StdAfx.h | 3 +- src/libs/7zip/win/CPP/Windows/System.h | 2 +- src/libs/7zip/win/CPP/Windows/Thread.h | 2 +- src/libs/7zip/win/CPP/Windows/Time.cpp | 170 - src/libs/7zip/win/CPP/Windows/Time.h | 21 - src/libs/7zip/win/CPP/Windows/TimeUtils.cpp | 203 ++ src/libs/7zip/win/CPP/Windows/TimeUtils.h | 23 + src/libs/7zip/win/CPP/Windows/Windows.pri | 29 + src/libs/7zip/win/Methods.txt | 152 - src/libs/7zip/win/history.txt | 271 -- src/libs/7zip/win/lzma.txt | 598 ---- src/libs/7zip/win/win.pri | 142 +- 346 files changed, 25319 insertions(+), 21524 deletions(-) delete mode 100644 src/libs/7zip/win/7zC.txt delete mode 100644 src/libs/7zip/win/7zFormat.txt delete mode 100644 src/libs/7zip/win/C/7z.h delete mode 100644 src/libs/7zip/win/C/7zAlloc.c delete mode 100644 src/libs/7zip/win/C/7zAlloc.h delete mode 100644 src/libs/7zip/win/C/7zBuf.c delete mode 100644 src/libs/7zip/win/C/7zBuf.h delete mode 100644 src/libs/7zip/win/C/7zBuf2.c delete mode 100644 src/libs/7zip/win/C/7zDec.c delete mode 100644 src/libs/7zip/win/C/7zFile.c delete mode 100644 src/libs/7zip/win/C/7zFile.h delete mode 100644 src/libs/7zip/win/C/7zIn.c create mode 100644 src/libs/7zip/win/C/7zTypes.h delete mode 100644 src/libs/7zip/win/C/Bcj2.c delete mode 100644 src/libs/7zip/win/C/Bcj2.h create mode 100644 src/libs/7zip/win/C/C.pri create mode 100644 src/libs/7zip/win/C/Compiler.h delete mode 100644 src/libs/7zip/win/C/Lzma86.h delete mode 100644 src/libs/7zip/win/C/Lzma86Dec.c delete mode 100644 src/libs/7zip/win/C/Lzma86Enc.c delete mode 100644 src/libs/7zip/win/C/LzmaLib.c delete mode 100644 src/libs/7zip/win/C/LzmaLib.h create mode 100644 src/libs/7zip/win/C/Precomp.h delete mode 100644 src/libs/7zip/win/C/Types.h create mode 100644 src/libs/7zip/win/C/XzCrc64Opt.c create mode 100644 src/libs/7zip/win/CPP/7zip/7zip.pri create mode 100644 src/libs/7zip/win/CPP/7zip/Archive/7z/7z.pri delete mode 100644 src/libs/7zip/win/CPP/7zip/Archive/7z/7zCompressionMode.cpp delete mode 100644 src/libs/7zip/win/CPP/7zip/Archive/7z/StdAfx.cpp delete mode 100644 src/libs/7zip/win/CPP/7zip/Archive/Archive.def create mode 100644 src/libs/7zip/win/CPP/7zip/Archive/Archive.pri delete mode 100644 src/libs/7zip/win/CPP/7zip/Archive/Archive2.def delete mode 100644 src/libs/7zip/win/CPP/7zip/Archive/ArchiveExports.cpp create mode 100644 src/libs/7zip/win/CPP/7zip/Archive/Common/Common.pri delete mode 100644 src/libs/7zip/win/CPP/7zip/Archive/Common/CrossThreadProgress.cpp delete mode 100644 src/libs/7zip/win/CPP/7zip/Archive/Common/CrossThreadProgress.h delete mode 100644 src/libs/7zip/win/CPP/7zip/Archive/Common/ParseProperties.cpp delete mode 100644 src/libs/7zip/win/CPP/7zip/Archive/DllExports2.cpp create mode 100644 src/libs/7zip/win/CPP/7zip/Common/Common.pri delete mode 100644 src/libs/7zip/win/CPP/7zip/Common/MethodId.cpp delete mode 100644 src/libs/7zip/win/CPP/7zip/Common/OffsetStream.cpp delete mode 100644 src/libs/7zip/win/CPP/7zip/Common/OffsetStream.h create mode 100644 src/libs/7zip/win/CPP/7zip/Common/PropId.cpp create mode 100644 src/libs/7zip/win/CPP/7zip/Common/UniqBlocks.cpp create mode 100644 src/libs/7zip/win/CPP/7zip/Common/UniqBlocks.h delete mode 100644 src/libs/7zip/win/CPP/7zip/Compress/CodecExports.cpp create mode 100644 src/libs/7zip/win/CPP/7zip/Compress/Compress.pri delete mode 100644 src/libs/7zip/win/CPP/7zip/MyVersion.h delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveName.cpp delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveName.h delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Common/Bench.cpp delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Common/Bench.h create mode 100644 src/libs/7zip/win/CPP/7zip/UI/Common/Common.pri delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Common/ExitCode.h create mode 100644 src/libs/7zip/win/CPP/7zip/UI/Common/HashCalc.cpp create mode 100644 src/libs/7zip/win/CPP/7zip/UI/Common/HashCalc.h delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Common/WorkDir.cpp delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Common/WorkDir.h delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Common/ZipRegistry.h delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Console/BenchCon.cpp delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Console/BenchCon.h create mode 100644 src/libs/7zip/win/CPP/7zip/UI/Console/Console.pri delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Console/ConsoleClose.cpp delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Console/ConsoleClose.h delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Console/ExtractCallbackConsole.h delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Console/List.cpp delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Console/List.h delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Console/Main.cpp delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Console/MainAr.cpp delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Console/OpenCallbackConsole.cpp delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Console/OpenCallbackConsole.h delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Console/StdAfx.cpp delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Console/UpdateCallbackConsole.h delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Console/UserInputUtils.cpp delete mode 100644 src/libs/7zip/win/CPP/7zip/UI/Console/UserInputUtils.h delete mode 100644 src/libs/7zip/win/CPP/Common/AutoPtr.h delete mode 100644 src/libs/7zip/win/CPP/Common/Buffer.h delete mode 100644 src/libs/7zip/win/CPP/Common/CRC.cpp delete mode 100644 src/libs/7zip/win/CPP/Common/C_FileIO.cpp delete mode 100644 src/libs/7zip/win/CPP/Common/C_FileIO.h create mode 100644 src/libs/7zip/win/CPP/Common/Common.h create mode 100644 src/libs/7zip/win/CPP/Common/Common.pri delete mode 100644 src/libs/7zip/win/CPP/Common/DynamicBuffer.h create mode 100644 src/libs/7zip/win/CPP/Common/MyBuffer.h create mode 100644 src/libs/7zip/win/CPP/Common/MyTypes.h delete mode 100644 src/libs/7zip/win/CPP/Common/MyVector.cpp create mode 100644 src/libs/7zip/win/CPP/Common/MyWindows.cpp delete mode 100644 src/libs/7zip/win/CPP/Common/StdInStream.cpp delete mode 100644 src/libs/7zip/win/CPP/Common/StdInStream.h delete mode 100644 src/libs/7zip/win/CPP/Common/Types.h delete mode 100644 src/libs/7zip/win/CPP/Windows/Error.cpp delete mode 100644 src/libs/7zip/win/CPP/Windows/Error.h create mode 100644 src/libs/7zip/win/CPP/Windows/FileLink.cpp delete mode 100644 src/libs/7zip/win/CPP/Windows/FileMapping.cpp delete mode 100644 src/libs/7zip/win/CPP/Windows/MemoryLock.cpp delete mode 100644 src/libs/7zip/win/CPP/Windows/MemoryLock.h delete mode 100644 src/libs/7zip/win/CPP/Windows/NtCheck.h create mode 100644 src/libs/7zip/win/CPP/Windows/PropVariantConv.cpp create mode 100644 src/libs/7zip/win/CPP/Windows/PropVariantConv.h delete mode 100644 src/libs/7zip/win/CPP/Windows/PropVariantConversions.cpp delete mode 100644 src/libs/7zip/win/CPP/Windows/PropVariantConversions.h delete mode 100644 src/libs/7zip/win/CPP/Windows/Registry.cpp delete mode 100644 src/libs/7zip/win/CPP/Windows/Registry.h create mode 100644 src/libs/7zip/win/CPP/Windows/SecurityUtils.cpp create mode 100644 src/libs/7zip/win/CPP/Windows/SecurityUtils.h delete mode 100644 src/libs/7zip/win/CPP/Windows/Time.cpp delete mode 100644 src/libs/7zip/win/CPP/Windows/Time.h create mode 100644 src/libs/7zip/win/CPP/Windows/TimeUtils.cpp create mode 100644 src/libs/7zip/win/CPP/Windows/TimeUtils.h create mode 100644 src/libs/7zip/win/CPP/Windows/Windows.pri delete mode 100644 src/libs/7zip/win/Methods.txt delete mode 100644 src/libs/7zip/win/history.txt delete mode 100644 src/libs/7zip/win/lzma.txt (limited to 'src/libs/7zip/win') diff --git a/src/libs/7zip/win/7zC.txt b/src/libs/7zip/win/7zC.txt deleted file mode 100644 index 5d5d06d7b..000000000 --- a/src/libs/7zip/win/7zC.txt +++ /dev/null @@ -1,194 +0,0 @@ -7z ANSI-C Decoder 4.62 ----------------------- - -7z ANSI-C provides 7z/LZMA decoding. -7z ANSI-C version is simplified version ported from C++ code. - -LZMA is default and general compression method of 7z format -in 7-Zip compression program (www.7-zip.org). LZMA provides high -compression ratio and very fast decompression. - - -LICENSE -------- - -7z ANSI-C Decoder is part of the LZMA SDK. -LZMA SDK is written and placed in the public domain by Igor Pavlov. - -Files ---------------------- - -7zDecode.* - Low level 7z decoding -7zExtract.* - High level 7z decoding -7zHeader.* - .7z format constants -7zIn.* - .7z archive opening -7zItem.* - .7z structures -7zMain.c - Test application - - -How To Use ----------- - -You must download 7-Zip program from www.7-zip.org. - -You can create .7z archive with 7z.exe or 7za.exe: - - 7za.exe a archive.7z *.htm -r -mx -m0fb=255 - -If you have big number of files in archive, and you need fast extracting, -you can use partly-solid archives: - - 7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K - -In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only -512KB for extracting one file from such archive. - - -Limitations of current version of 7z ANSI-C Decoder ---------------------------------------------------- - - - It reads only "FileName", "Size", "LastWriteTime" and "CRC" information for each file in archive. - - It supports only LZMA and Copy (no compression) methods with BCJ or BCJ2 filters. - - It converts original UTF-16 Unicode file names to UTF-8 Unicode file names. - -These limitations will be fixed in future versions. - - -Using 7z ANSI-C Decoder Test application: ------------------------------------------ - -Usage: 7zDec - -: - e: Extract files from archive - l: List contents of archive - t: Test integrity of archive - -Example: - - 7zDec l archive.7z - -lists contents of archive.7z - - 7zDec e archive.7z - -extracts files from archive.7z to current folder. - - -How to use .7z Decoder ----------------------- - -Memory allocation -~~~~~~~~~~~~~~~~~ - -7z Decoder uses two memory pools: -1) Temporary pool -2) Main pool -Such scheme can allow you to avoid fragmentation of allocated blocks. - - -Steps for using 7z decoder --------------------------- - -Use code at 7zMain.c as example. - -1) Declare variables: - inStream /* implements ILookInStream interface */ - CSzArEx db; /* 7z archive database structure */ - ISzAlloc allocImp; /* memory functions for main pool */ - ISzAlloc allocTempImp; /* memory functions for temporary pool */ - -2) call CrcGenerateTable(); function to initialize CRC structures. - -3) call SzArEx_Init(&db); function to initialize db structures. - -4) call SzArEx_Open(&db, inStream, &allocMain, &allocTemp) to open archive - -This function opens archive "inStream" and reads headers to "db". -All items in "db" will be allocated with "allocMain" functions. -SzArEx_Open function allocates and frees temporary structures by "allocTemp" functions. - -5) List items or Extract items - - Listing code: - ~~~~~~~~~~~~~ - { - UInt32 i; - for (i = 0; i < db.db.NumFiles; i++) - { - CFileItem *f = db.db.Files + i; - printf("%10d %s\n", (int)f->Size, f->Name); - } - } - - Extracting code: - ~~~~~~~~~~~~~~~~ - - SZ_RESULT SzAr_Extract( - CArchiveDatabaseEx *db, - ILookInStream *inStream, - UInt32 fileIndex, /* index of file */ - UInt32 *blockIndex, /* index of solid block */ - Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ - size_t *outBufferSize, /* buffer size for output buffer */ - size_t *offset, /* offset of stream for required file in *outBuffer */ - size_t *outSizeProcessed, /* size of file in *outBuffer */ - ISzAlloc *allocMain, - ISzAlloc *allocTemp); - - If you need to decompress more than one file, you can send these values from previous call: - blockIndex, - outBuffer, - outBufferSize, - You can consider "outBuffer" as cache of solid block. If your archive is solid, - it will increase decompression speed. - - After decompressing you must free "outBuffer": - allocImp.Free(outBuffer); - -6) call SzArEx_Free(&db, allocImp.Free) to free allocated items in "db". - - - - -Memory requirements for .7z decoding ------------------------------------- - -Memory usage for Archive opening: - - Temporary pool: - - Memory for uncompressed .7z headers - - some other temporary blocks - - Main pool: - - Memory for database: - Estimated size of one file structures in solid archive: - - Size (4 or 8 Bytes) - - CRC32 (4 bytes) - - LastWriteTime (8 bytes) - - Some file information (4 bytes) - - File Name (variable length) + pointer + allocation structures - -Memory usage for archive Decompressing: - - Temporary pool: - - Memory for LZMA decompressing structures - - Main pool: - - Memory for decompressed solid block - - Memory for temprorary buffers, if BCJ2 fileter is used. Usually these - temprorary buffers can be about 15% of solid block size. - - -7z Decoder doesn't allocate memory for compressed blocks. -Instead of this, you must allocate buffer with desired -size before calling 7z Decoder. Use 7zMain.c as example. - - -Defines -------- - -_SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr. - - ---- - -http://www.7-zip.org -http://www.7-zip.org/sdk.html -http://www.7-zip.org/support.html diff --git a/src/libs/7zip/win/7zFormat.txt b/src/libs/7zip/win/7zFormat.txt deleted file mode 100644 index e1cf7380d..000000000 --- a/src/libs/7zip/win/7zFormat.txt +++ /dev/null @@ -1,471 +0,0 @@ -7z Format description (2.30 Beta 25) ------------------------------------ - -This file contains description of 7z archive format. -7z archive can contain files compressed with any method. -See "Methods.txt" for description for defined compressing methods. - - -Format structure Overview -------------------------- - -Some fields can be optional. - -Archive structure -~~~~~~~~~~~~~~~~~ -SignatureHeader -[PackedStreams] -[PackedStreamsForHeaders] -[ - Header - or - { - Packed Header - HeaderInfo - } -] - - - -Header structure -~~~~~~~~~~~~~~~~ -{ - ArchiveProperties - AdditionalStreams - { - PackInfo - { - PackPos - NumPackStreams - Sizes[NumPackStreams] - CRCs[NumPackStreams] - } - CodersInfo - { - NumFolders - Folders[NumFolders] - { - NumCoders - CodersInfo[NumCoders] - { - ID - NumInStreams; - NumOutStreams; - PropertiesSize - Properties[PropertiesSize] - } - NumBindPairs - BindPairsInfo[NumBindPairs] - { - InIndex; - OutIndex; - } - PackedIndices - } - UnPackSize[Folders][Folders.NumOutstreams] - CRCs[NumFolders] - } - SubStreamsInfo - { - NumUnPackStreamsInFolders[NumFolders]; - UnPackSizes[] - CRCs[] - } - } - MainStreamsInfo - { - (Same as in AdditionalStreams) - } - FilesInfo - { - NumFiles - Properties[] - { - ID - Size - Data - } - } -} - -HeaderInfo structure -~~~~~~~~~~~~~~~~~~~~ -{ - (Same as in AdditionalStreams) -} - - - -Notes about Notation and encoding ---------------------------------- - -7z uses little endian encoding. - -7z archive format has optional headers that are marked as -[] -Header -[] - -REAL_UINT64 means real UINT64. - -UINT64 means real UINT64 encoded with the following scheme: - - Size of encoding sequence depends from first byte: - First_Byte Extra_Bytes Value - (binary) - 0xxxxxxx : ( xxxxxxx ) - 10xxxxxx BYTE y[1] : ( xxxxxx << (8 * 1)) + y - 110xxxxx BYTE y[2] : ( xxxxx << (8 * 2)) + y - ... - 1111110x BYTE y[6] : ( x << (8 * 6)) + y - 11111110 BYTE y[7] : y - 11111111 BYTE y[8] : y - - - -Property IDs ------------- - -0x00 = kEnd, - -0x01 = kHeader, - -0x02 = kArchiveProperties, - -0x03 = kAdditionalStreamsInfo, -0x04 = kMainStreamsInfo, -0x05 = kFilesInfo, - -0x06 = kPackInfo, -0x07 = kUnPackInfo, -0x08 = kSubStreamsInfo, - -0x09 = kSize, -0x0A = kCRC, - -0x0B = kFolder, - -0x0C = kCodersUnPackSize, -0x0D = kNumUnPackStream, - -0x0E = kEmptyStream, -0x0F = kEmptyFile, -0x10 = kAnti, - -0x11 = kName, -0x12 = kCreationTime, -0x13 = kLastAccessTime, -0x14 = kLastWriteTime, -0x15 = kWinAttributes, -0x16 = kComment, - -0x17 = kEncodedHeader, - - -7z format headers ------------------ - -SignatureHeader -~~~~~~~~~~~~~~~ - BYTE kSignature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; - - ArchiveVersion - { - BYTE Major; // now = 0 - BYTE Minor; // now = 2 - }; - - UINT32 StartHeaderCRC; - - StartHeader - { - REAL_UINT64 NextHeaderOffset - REAL_UINT64 NextHeaderSize - UINT32 NextHeaderCRC - } - - -........................... - - -ArchiveProperties -~~~~~~~~~~~~~~~~~ -BYTE NID::kArchiveProperties (0x02) -for (;;) -{ - BYTE PropertyType; - if (aType == 0) - break; - UINT64 PropertySize; - BYTE PropertyData[PropertySize]; -} - - -Digests (NumStreams) -~~~~~~~~~~~~~~~~~~~~~ - BYTE AllAreDefined - if (AllAreDefined == 0) - { - for(NumStreams) - BIT Defined - } - UINT32 CRCs[NumDefined] - - -PackInfo -~~~~~~~~~~~~ - BYTE NID::kPackInfo (0x06) - UINT64 PackPos - UINT64 NumPackStreams - - [] - BYTE NID::kSize (0x09) - UINT64 PackSizes[NumPackStreams] - [] - - [] - BYTE NID::kCRC (0x0A) - PackStreamDigests[NumPackStreams] - [] - - BYTE NID::kEnd - - -Folder -~~~~~~ - UINT64 NumCoders; - for (NumCoders) - { - BYTE - { - 0:3 DecompressionMethod.IDSize - 4: - 0 - IsSimple - 1 - Is not simple - 5: - 0 - No Attributes - 1 - There Are Attributes - 7: - 0 - Last Method in Alternative_Method_List - 1 - There are more alternative methods - } - BYTE DecompressionMethod.ID[DecompressionMethod.IDSize] - if (!IsSimple) - { - UINT64 NumInStreams; - UINT64 NumOutStreams; - } - if (DecompressionMethod[0] != 0) - { - UINT64 PropertiesSize - BYTE Properties[PropertiesSize] - } - } - - NumBindPairs = NumOutStreamsTotal - 1; - - for (NumBindPairs) - { - UINT64 InIndex; - UINT64 OutIndex; - } - - NumPackedStreams = NumInStreamsTotal - NumBindPairs; - if (NumPackedStreams > 1) - for(NumPackedStreams) - { - UINT64 Index; - }; - - - - -Coders Info -~~~~~~~~~~~ - - BYTE NID::kUnPackInfo (0x07) - - - BYTE NID::kFolder (0x0B) - UINT64 NumFolders - BYTE External - switch(External) - { - case 0: - Folders[NumFolders] - case 1: - UINT64 DataStreamIndex - } - - - BYTE ID::kCodersUnPackSize (0x0C) - for(Folders) - for(Folder.NumOutStreams) - UINT64 UnPackSize; - - - [] - BYTE NID::kCRC (0x0A) - UnPackDigests[NumFolders] - [] - - - - BYTE NID::kEnd - - - -SubStreams Info -~~~~~~~~~~~~~~ - BYTE NID::kSubStreamsInfo; (0x08) - - [] - BYTE NID::kNumUnPackStream; (0x0D) - UINT64 NumUnPackStreamsInFolders[NumFolders]; - [] - - - [] - BYTE NID::kSize (0x09) - UINT64 UnPackSizes[] - [] - - - [] - BYTE NID::kCRC (0x0A) - Digests[Number of streams with unknown CRC] - [] - - - BYTE NID::kEnd - - -Streams Info -~~~~~~~~~~~~ - - [] - PackInfo - [] - - - [] - CodersInfo - [] - - - [] - SubStreamsInfo - [] - - BYTE NID::kEnd - - -FilesInfo -~~~~~~~~~ - BYTE NID::kFilesInfo; (0x05) - UINT64 NumFiles - - for (;;) - { - BYTE PropertyType; - if (aType == 0) - break; - - UINT64 Size; - - switch(PropertyType) - { - kEmptyStream: (0x0E) - for(NumFiles) - BIT IsEmptyStream - - kEmptyFile: (0x0F) - for(EmptyStreams) - BIT IsEmptyFile - - kAnti: (0x10) - for(EmptyStreams) - BIT IsAntiFile - - case kCreationTime: (0x12) - case kLastAccessTime: (0x13) - case kLastWriteTime: (0x14) - BYTE AllAreDefined - if (AllAreDefined == 0) - { - for(NumFiles) - BIT TimeDefined - } - BYTE External; - if(External != 0) - UINT64 DataIndex - [] - for(Definded Items) - UINT32 Time - [] - - kNames: (0x11) - BYTE External; - if(External != 0) - UINT64 DataIndex - [] - for(Files) - { - wchar_t Names[NameSize]; - wchar_t 0; - } - [] - - kAttributes: (0x15) - BYTE AllAreDefined - if (AllAreDefined == 0) - { - for(NumFiles) - BIT AttributesAreDefined - } - BYTE External; - if(External != 0) - UINT64 DataIndex - [] - for(Definded Attributes) - UINT32 Attributes - [] - } - } - - -Header -~~~~~~ - BYTE NID::kHeader (0x01) - - [] - ArchiveProperties - [] - - [] - BYTE NID::kAdditionalStreamsInfo; (0x03) - StreamsInfo - [] - - [] - BYTE NID::kMainStreamsInfo; (0x04) - StreamsInfo - [] - - [] - FilesInfo - [] - - BYTE NID::kEnd - - -HeaderInfo -~~~~~~~~~~ - [] - BYTE NID::kEncodedHeader; (0x17) - StreamsInfo for Encoded Header - [] - - ---- -End of document diff --git a/src/libs/7zip/win/C/7z.h b/src/libs/7zip/win/C/7z.h deleted file mode 100644 index 01c4cac6a..000000000 --- a/src/libs/7zip/win/C/7z.h +++ /dev/null @@ -1,203 +0,0 @@ -/* 7z.h -- 7z interface -2010-03-11 : Igor Pavlov : Public domain */ - -#ifndef __7Z_H -#define __7Z_H - -#include "7zBuf.h" - -EXTERN_C_BEGIN - -#define k7zStartHeaderSize 0x20 -#define k7zSignatureSize 6 -extern Byte k7zSignature[k7zSignatureSize]; -#define k7zMajorVersion 0 - -enum EIdEnum -{ - k7zIdEnd, - k7zIdHeader, - k7zIdArchiveProperties, - k7zIdAdditionalStreamsInfo, - k7zIdMainStreamsInfo, - k7zIdFilesInfo, - k7zIdPackInfo, - k7zIdUnpackInfo, - k7zIdSubStreamsInfo, - k7zIdSize, - k7zIdCRC, - k7zIdFolder, - k7zIdCodersUnpackSize, - k7zIdNumUnpackStream, - k7zIdEmptyStream, - k7zIdEmptyFile, - k7zIdAnti, - k7zIdName, - k7zIdCTime, - k7zIdATime, - k7zIdMTime, - k7zIdWinAttributes, - k7zIdComment, - k7zIdEncodedHeader, - k7zIdStartPos, - k7zIdDummy -}; - -typedef struct -{ - UInt32 NumInStreams; - UInt32 NumOutStreams; - UInt64 MethodID; - CBuf Props; -} CSzCoderInfo; - -void SzCoderInfo_Init(CSzCoderInfo *p); -void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc); - -typedef struct -{ - UInt32 InIndex; - UInt32 OutIndex; -} CSzBindPair; - -typedef struct -{ - CSzCoderInfo *Coders; - CSzBindPair *BindPairs; - UInt32 *PackStreams; - UInt64 *UnpackSizes; - UInt32 NumCoders; - UInt32 NumBindPairs; - UInt32 NumPackStreams; - int UnpackCRCDefined; - UInt32 UnpackCRC; - - UInt32 NumUnpackStreams; -} CSzFolder; - -void SzFolder_Init(CSzFolder *p); -UInt64 SzFolder_GetUnpackSize(CSzFolder *p); -int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex); -UInt32 SzFolder_GetNumOutStreams(CSzFolder *p); -UInt64 SzFolder_GetUnpackSize(CSzFolder *p); - -SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes, - ILookInStream *stream, UInt64 startPos, - Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); - -typedef struct -{ - UInt32 Low; - UInt32 High; -} CNtfsFileTime; - -typedef struct -{ - CNtfsFileTime MTime; - UInt64 Size; - UInt32 Crc; - UInt32 Attrib; - Byte HasStream; - Byte IsDir; - Byte IsAnti; - Byte CrcDefined; - Byte MTimeDefined; - Byte AttribDefined; -} CSzFileItem; - -void SzFile_Init(CSzFileItem *p); - -typedef struct -{ - UInt64 *PackSizes; - Byte *PackCRCsDefined; - UInt32 *PackCRCs; - CSzFolder *Folders; - CSzFileItem *Files; - UInt32 NumPackStreams; - UInt32 NumFolders; - UInt32 NumFiles; -} CSzAr; - -void SzAr_Init(CSzAr *p); -void SzAr_Free(CSzAr *p, ISzAlloc *alloc); - - -/* - SzExtract extracts file from archive - - *outBuffer must be 0 before first call for each new archive. - - Extracting cache: - If you need to decompress more than one file, you can send - these values from previous call: - *blockIndex, - *outBuffer, - *outBufferSize - You can consider "*outBuffer" as cache of solid block. If your archive is solid, - it will increase decompression speed. - - If you use external function, you can declare these 3 cache variables - (blockIndex, outBuffer, outBufferSize) as static in that external function. - - Free *outBuffer and set *outBuffer to 0, if you want to flush cache. -*/ - -typedef struct -{ - CSzAr db; - - UInt64 startPosAfterHeader; - UInt64 dataPos; - - UInt32 *FolderStartPackStreamIndex; - UInt64 *PackStreamStartPositions; - UInt32 *FolderStartFileIndex; - UInt32 *FileIndexToFolderIndexMap; - - size_t *FileNameOffsets; /* in 2-byte steps */ - CBuf FileNames; /* UTF-16-LE */ -} CSzArEx; - -void SzArEx_Init(CSzArEx *p); -void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc); -UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); -int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); - -/* -if dest == NULL, the return value specifies the required size of the buffer, - in 16-bit characters, including the null-terminating character. -if dest != NULL, the return value specifies the number of 16-bit characters that - are written to the dest, including the null-terminating character. */ - -size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest); - -SRes SzArEx_Extract( - const CSzArEx *db, - ILookInStream *inStream, - UInt32 fileIndex, /* index of file */ - UInt32 *blockIndex, /* index of solid block */ - Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ - size_t *outBufferSize, /* buffer size for output buffer */ - size_t *offset, /* offset of stream for required file in *outBuffer */ - size_t *outSizeProcessed, /* size of file in *outBuffer */ - ISzAlloc *allocMain, - ISzAlloc *allocTemp); - - -/* -SzArEx_Open Errors: -SZ_ERROR_NO_ARCHIVE -SZ_ERROR_ARCHIVE -SZ_ERROR_UNSUPPORTED -SZ_ERROR_MEM -SZ_ERROR_CRC -SZ_ERROR_INPUT_EOF -SZ_ERROR_FAIL -*/ - -SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp); - -EXTERN_C_END - -#endif diff --git a/src/libs/7zip/win/C/7zAlloc.c b/src/libs/7zip/win/C/7zAlloc.c deleted file mode 100644 index 964b28db3..000000000 --- a/src/libs/7zip/win/C/7zAlloc.c +++ /dev/null @@ -1,76 +0,0 @@ -/* 7zAlloc.c -- Allocation functions -2010-10-29 : Igor Pavlov : Public domain */ - -#include "7zAlloc.h" - -/* #define _SZ_ALLOC_DEBUG */ -/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ - -#ifdef _SZ_ALLOC_DEBUG - -#ifdef _WIN32 -#include -#endif - -#include -int g_allocCount = 0; -int g_allocCountTemp = 0; - -#endif - -void *SzAlloc(void *p, size_t size) -{ - p = p; - if (size == 0) - return 0; - #ifdef _SZ_ALLOC_DEBUG - fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); - g_allocCount++; - #endif - return malloc(size); -} - -void SzFree(void *p, void *address) -{ - p = p; - #ifdef _SZ_ALLOC_DEBUG - if (address != 0) - { - g_allocCount--; - fprintf(stderr, "\nFree; count = %10d", g_allocCount); - } - #endif - free(address); -} - -void *SzAllocTemp(void *p, size_t size) -{ - p = p; - if (size == 0) - return 0; - #ifdef _SZ_ALLOC_DEBUG - fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); - g_allocCountTemp++; - #ifdef _WIN32 - return HeapAlloc(GetProcessHeap(), 0, size); - #endif - #endif - return malloc(size); -} - -void SzFreeTemp(void *p, void *address) -{ - p = p; - #ifdef _SZ_ALLOC_DEBUG - if (address != 0) - { - g_allocCountTemp--; - fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); - } - #ifdef _WIN32 - HeapFree(GetProcessHeap(), 0, address); - return; - #endif - #endif - free(address); -} diff --git a/src/libs/7zip/win/C/7zAlloc.h b/src/libs/7zip/win/C/7zAlloc.h deleted file mode 100644 index 3344e9373..000000000 --- a/src/libs/7zip/win/C/7zAlloc.h +++ /dev/null @@ -1,15 +0,0 @@ -/* 7zAlloc.h -- Allocation functions -2010-10-29 : Igor Pavlov : Public domain */ - -#ifndef __7Z_ALLOC_H -#define __7Z_ALLOC_H - -#include - -void *SzAlloc(void *p, size_t size); -void SzFree(void *p, void *address); - -void *SzAllocTemp(void *p, size_t size); -void SzFreeTemp(void *p, void *address); - -#endif diff --git a/src/libs/7zip/win/C/7zBuf.c b/src/libs/7zip/win/C/7zBuf.c deleted file mode 100644 index 14e7f4e2b..000000000 --- a/src/libs/7zip/win/C/7zBuf.c +++ /dev/null @@ -1,36 +0,0 @@ -/* 7zBuf.c -- Byte Buffer -2008-03-28 -Igor Pavlov -Public domain */ - -#include "7zBuf.h" - -void Buf_Init(CBuf *p) -{ - p->data = 0; - p->size = 0; -} - -int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc) -{ - p->size = 0; - if (size == 0) - { - p->data = 0; - return 1; - } - p->data = (Byte *)alloc->Alloc(alloc, size); - if (p->data != 0) - { - p->size = size; - return 1; - } - return 0; -} - -void Buf_Free(CBuf *p, ISzAlloc *alloc) -{ - alloc->Free(alloc, p->data); - p->data = 0; - p->size = 0; -} diff --git a/src/libs/7zip/win/C/7zBuf.h b/src/libs/7zip/win/C/7zBuf.h deleted file mode 100644 index e9f2f316d..000000000 --- a/src/libs/7zip/win/C/7zBuf.h +++ /dev/null @@ -1,39 +0,0 @@ -/* 7zBuf.h -- Byte Buffer -2009-02-07 : Igor Pavlov : Public domain */ - -#ifndef __7Z_BUF_H -#define __7Z_BUF_H - -#include "Types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct -{ - Byte *data; - size_t size; -} CBuf; - -void Buf_Init(CBuf *p); -int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc); -void Buf_Free(CBuf *p, ISzAlloc *alloc); - -typedef struct -{ - Byte *data; - size_t size; - size_t pos; -} CDynBuf; - -void DynBuf_Construct(CDynBuf *p); -void DynBuf_SeekToBeg(CDynBuf *p); -int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc); -void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/libs/7zip/win/C/7zBuf2.c b/src/libs/7zip/win/C/7zBuf2.c deleted file mode 100644 index 8d17e0dcf..000000000 --- a/src/libs/7zip/win/C/7zBuf2.c +++ /dev/null @@ -1,45 +0,0 @@ -/* 7zBuf2.c -- Byte Buffer -2008-10-04 : Igor Pavlov : Public domain */ - -#include -#include "7zBuf.h" - -void DynBuf_Construct(CDynBuf *p) -{ - p->data = 0; - p->size = 0; - p->pos = 0; -} - -void DynBuf_SeekToBeg(CDynBuf *p) -{ - p->pos = 0; -} - -int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc) -{ - if (size > p->size - p->pos) - { - size_t newSize = p->pos + size; - Byte *data; - newSize += newSize / 4; - data = (Byte *)alloc->Alloc(alloc, newSize); - if (data == 0) - return 0; - p->size = newSize; - memcpy(data, p->data, p->pos); - alloc->Free(alloc, p->data); - p->data = data; - } - memcpy(p->data + p->pos, buf, size); - p->pos += size; - return 1; -} - -void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc) -{ - alloc->Free(alloc, p->data); - p->data = 0; - p->size = 0; - p->pos = 0; -} diff --git a/src/libs/7zip/win/C/7zCrc.c b/src/libs/7zip/win/C/7zCrc.c index a92084961..5f32380dd 100644 --- a/src/libs/7zip/win/C/7zCrc.c +++ b/src/libs/7zip/win/C/7zCrc.c @@ -1,41 +1,33 @@ -/* 7zCrc.c -- CRC32 calculation -2009-11-23 : Igor Pavlov : Public domain */ +/* 7zCrc.c -- CRC32 init +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include "7zCrc.h" #include "CpuArch.h" #define kCrcPoly 0xEDB88320 -#ifdef MY_CPU_LE -#define CRC_NUM_TABLES 8 +#ifdef MY_CPU_X86_OR_AMD64 + #define CRC_NUM_TABLES 8 + UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); +#elif defined(MY_CPU_LE) + #define CRC_NUM_TABLES 4 #else -#define CRC_NUM_TABLES 1 + #define CRC_NUM_TABLES 5 + #define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24)) + UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table); +#endif + +#ifndef MY_CPU_BE + UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); #endif typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); -static CRC_FUNC g_CrcUpdate; +CRC_FUNC g_CrcUpdate; UInt32 g_CrcTable[256 * CRC_NUM_TABLES]; -#if CRC_NUM_TABLES == 1 - -#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) - -static UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table) -{ - const Byte *p = (const Byte *)data; - for (; size > 0; size--, p++) - v = CRC_UPDATE_BYTE_2(v, *p); - return v; -} - -#else - -UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); -UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); - -#endif - UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) { return g_CrcUpdate(v, data, size, g_CrcTable); @@ -57,18 +49,37 @@ void MY_FAST_CALL CrcGenerateTable() r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); g_CrcTable[i] = r; } - #if CRC_NUM_TABLES == 1 - g_CrcUpdate = CrcUpdateT1; - #else for (; i < 256 * CRC_NUM_TABLES; i++) { UInt32 r = g_CrcTable[i - 256]; g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); } + + #ifdef MY_CPU_LE + g_CrcUpdate = CrcUpdateT4; - #ifdef MY_CPU_X86_OR_AMD64 + + #if CRC_NUM_TABLES == 8 if (!CPU_Is_InOrder()) g_CrcUpdate = CrcUpdateT8; #endif + + #else + { + #ifndef MY_CPU_BE + UInt32 k = 1; + if (*(const Byte *)&k == 1) + g_CrcUpdate = CrcUpdateT4; + else + #endif + { + for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--) + { + UInt32 x = g_CrcTable[i - 256]; + g_CrcTable[i] = CRC_UINT32_SWAP(x); + } + g_CrcUpdate = CrcUpdateT1_BeT4; + } + } #endif } diff --git a/src/libs/7zip/win/C/7zCrc.h b/src/libs/7zip/win/C/7zCrc.h index 38e3e5fbc..8fd579587 100644 --- a/src/libs/7zip/win/C/7zCrc.h +++ b/src/libs/7zip/win/C/7zCrc.h @@ -1,10 +1,10 @@ /* 7zCrc.h -- CRC32 calculation -2009-11-21 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __7Z_CRC_H #define __7Z_CRC_H -#include "Types.h" +#include "7zTypes.h" EXTERN_C_BEGIN diff --git a/src/libs/7zip/win/C/7zCrcOpt.c b/src/libs/7zip/win/C/7zCrcOpt.c index 6c766a209..ce132b5d4 100644 --- a/src/libs/7zip/win/C/7zCrcOpt.c +++ b/src/libs/7zip/win/C/7zCrcOpt.c @@ -1,12 +1,14 @@ -/* 7zCrcOpt.c -- CRC32 calculation : optimized version -2009-11-23 : Igor Pavlov : Public domain */ +/* 7zCrcOpt.c -- CRC32 calculation +2013-11-12 : Igor Pavlov : Public domain */ -#include "CpuArch.h" +#include "Precomp.h" -#ifdef MY_CPU_LE +#include "CpuArch.h" #define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) +#ifndef MY_CPU_BE + UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table) { const Byte *p = (const Byte *)data; @@ -32,3 +34,33 @@ UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const U } #endif + + +#ifndef MY_CPU_LE + +#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24)) + +UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + v = CRC_UINT32_SWAP(v); + table += 0x100; + for (; size >= 4; size -= 4, p += 4) + { + v ^= *(const UInt32 *)p; + v = + table[0x000 + (v & 0xFF)] ^ + table[0x100 + ((v >> 8) & 0xFF)] ^ + table[0x200 + ((v >> 16) & 0xFF)] ^ + table[0x300 + ((v >> 24))]; + } + table -= 0x100; + v = CRC_UINT32_SWAP(v); + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +#endif diff --git a/src/libs/7zip/win/C/7zDec.c b/src/libs/7zip/win/C/7zDec.c deleted file mode 100644 index b6d809956..000000000 --- a/src/libs/7zip/win/C/7zDec.c +++ /dev/null @@ -1,470 +0,0 @@ -/* 7zDec.c -- Decoding from 7z folder -2010-11-02 : Igor Pavlov : Public domain */ - -#include - -/* #define _7ZIP_PPMD_SUPPPORT */ - -#include "7z.h" - -#include "Bcj2.h" -#include "Bra.h" -#include "CpuArch.h" -#include "LzmaDec.h" -#include "Lzma2Dec.h" -#ifdef _7ZIP_PPMD_SUPPPORT -#include "Ppmd7.h" -#endif - -#define k_Copy 0 -#define k_LZMA2 0x21 -#define k_LZMA 0x30101 -#define k_BCJ 0x03030103 -#define k_PPC 0x03030205 -#define k_ARM 0x03030501 -#define k_ARMT 0x03030701 -#define k_SPARC 0x03030805 -#define k_BCJ2 0x0303011B - -#ifdef _7ZIP_PPMD_SUPPPORT - -#define k_PPMD 0x30401 - -typedef struct -{ - IByteIn p; - const Byte *cur; - const Byte *end; - const Byte *begin; - UInt64 processed; - Bool extra; - SRes res; - ILookInStream *inStream; -} CByteInToLook; - -static Byte ReadByte(void *pp) -{ - CByteInToLook *p = (CByteInToLook *)pp; - if (p->cur != p->end) - return *p->cur++; - if (p->res == SZ_OK) - { - size_t size = p->cur - p->begin; - p->processed += size; - p->res = p->inStream->Skip(p->inStream, size); - size = (1 << 25); - p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size); - p->cur = p->begin; - p->end = p->begin + size; - if (size != 0) - return *p->cur++;; - } - p->extra = True; - return 0; -} - -static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, - Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) -{ - CPpmd7 ppmd; - CByteInToLook s; - SRes res = SZ_OK; - - s.p.Read = ReadByte; - s.inStream = inStream; - s.begin = s.end = s.cur = NULL; - s.extra = False; - s.res = SZ_OK; - s.processed = 0; - - if (coder->Props.size != 5) - return SZ_ERROR_UNSUPPORTED; - - { - unsigned order = coder->Props.data[0]; - UInt32 memSize = GetUi32(coder->Props.data + 1); - if (order < PPMD7_MIN_ORDER || - order > PPMD7_MAX_ORDER || - memSize < PPMD7_MIN_MEM_SIZE || - memSize > PPMD7_MAX_MEM_SIZE) - return SZ_ERROR_UNSUPPORTED; - Ppmd7_Construct(&ppmd); - if (!Ppmd7_Alloc(&ppmd, memSize, allocMain)) - return SZ_ERROR_MEM; - Ppmd7_Init(&ppmd, order); - } - { - CPpmd7z_RangeDec rc; - Ppmd7z_RangeDec_CreateVTable(&rc); - rc.Stream = &s.p; - if (!Ppmd7z_RangeDec_Init(&rc)) - res = SZ_ERROR_DATA; - else if (s.extra) - res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); - else - { - SizeT i; - for (i = 0; i < outSize; i++) - { - int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p); - if (s.extra || sym < 0) - break; - outBuffer[i] = (Byte)sym; - } - if (i != outSize) - res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); - else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc)) - res = SZ_ERROR_DATA; - } - } - Ppmd7_Free(&ppmd, allocMain); - return res; -} - -#endif - - -static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, - Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) -{ - CLzmaDec state; - SRes res = SZ_OK; - - LzmaDec_Construct(&state); - RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain)); - state.dic = outBuffer; - state.dicBufSize = outSize; - LzmaDec_Init(&state); - - for (;;) - { - Byte *inBuf = NULL; - size_t lookahead = (1 << 18); - if (lookahead > inSize) - lookahead = (size_t)inSize; - res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead); - if (res != SZ_OK) - break; - - { - SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; - ELzmaStatus status; - res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); - lookahead -= inProcessed; - inSize -= inProcessed; - if (res != SZ_OK) - break; - if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos)) - { - if (state.dicBufSize != outSize || lookahead != 0 || - (status != LZMA_STATUS_FINISHED_WITH_MARK && - status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)) - res = SZ_ERROR_DATA; - break; - } - res = inStream->Skip((void *)inStream, inProcessed); - if (res != SZ_OK) - break; - } - } - - LzmaDec_FreeProbs(&state, allocMain); - return res; -} - -static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, - Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) -{ - CLzma2Dec state; - SRes res = SZ_OK; - - Lzma2Dec_Construct(&state); - if (coder->Props.size != 1) - return SZ_ERROR_DATA; - RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain)); - state.decoder.dic = outBuffer; - state.decoder.dicBufSize = outSize; - Lzma2Dec_Init(&state); - - for (;;) - { - Byte *inBuf = NULL; - size_t lookahead = (1 << 18); - if (lookahead > inSize) - lookahead = (size_t)inSize; - res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead); - if (res != SZ_OK) - break; - - { - SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos; - ELzmaStatus status; - res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); - lookahead -= inProcessed; - inSize -= inProcessed; - if (res != SZ_OK) - break; - if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos)) - { - if (state.decoder.dicBufSize != outSize || lookahead != 0 || - (status != LZMA_STATUS_FINISHED_WITH_MARK)) - res = SZ_ERROR_DATA; - break; - } - res = inStream->Skip((void *)inStream, inProcessed); - if (res != SZ_OK) - break; - } - } - - Lzma2Dec_FreeProbs(&state, allocMain); - return res; -} - -static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) -{ - while (inSize > 0) - { - void *inBuf; - size_t curSize = (1 << 18); - if (curSize > inSize) - curSize = (size_t)inSize; - RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize)); - if (curSize == 0) - return SZ_ERROR_INPUT_EOF; - memcpy(outBuffer, inBuf, curSize); - outBuffer += curSize; - inSize -= curSize; - RINOK(inStream->Skip((void *)inStream, curSize)); - } - return SZ_OK; -} - -static Bool IS_MAIN_METHOD(UInt32 m) -{ - switch(m) - { - case k_Copy: - case k_LZMA: - case k_LZMA2: - #ifdef _7ZIP_PPMD_SUPPPORT - case k_PPMD: - #endif - return True; - } - return False; -} - -static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c) -{ - return - c->NumInStreams == 1 && - c->NumOutStreams == 1 && - c->MethodID <= (UInt32)0xFFFFFFFF && - IS_MAIN_METHOD((UInt32)c->MethodID); -} - -#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1) - -static SRes CheckSupportedFolder(const CSzFolder *f) -{ - if (f->NumCoders < 1 || f->NumCoders > 4) - return SZ_ERROR_UNSUPPORTED; - if (!IS_SUPPORTED_CODER(&f->Coders[0])) - return SZ_ERROR_UNSUPPORTED; - if (f->NumCoders == 1) - { - if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0) - return SZ_ERROR_UNSUPPORTED; - return SZ_OK; - } - if (f->NumCoders == 2) - { - CSzCoderInfo *c = &f->Coders[1]; - if (c->MethodID > (UInt32)0xFFFFFFFF || - c->NumInStreams != 1 || - c->NumOutStreams != 1 || - f->NumPackStreams != 1 || - f->PackStreams[0] != 0 || - f->NumBindPairs != 1 || - f->BindPairs[0].InIndex != 1 || - f->BindPairs[0].OutIndex != 0) - return SZ_ERROR_UNSUPPORTED; - switch ((UInt32)c->MethodID) - { - case k_BCJ: - case k_ARM: - break; - default: - return SZ_ERROR_UNSUPPORTED; - } - return SZ_OK; - } - if (f->NumCoders == 4) - { - if (!IS_SUPPORTED_CODER(&f->Coders[1]) || - !IS_SUPPORTED_CODER(&f->Coders[2]) || - !IS_BCJ2(&f->Coders[3])) - return SZ_ERROR_UNSUPPORTED; - if (f->NumPackStreams != 4 || - f->PackStreams[0] != 2 || - f->PackStreams[1] != 6 || - f->PackStreams[2] != 1 || - f->PackStreams[3] != 0 || - f->NumBindPairs != 3 || - f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || - f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || - f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) - return SZ_ERROR_UNSUPPORTED; - return SZ_OK; - } - return SZ_ERROR_UNSUPPORTED; -} - -static UInt64 GetSum(const UInt64 *values, UInt32 index) -{ - UInt64 sum = 0; - UInt32 i; - for (i = 0; i < index; i++) - sum += values[i]; - return sum; -} - -#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break; - -static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes, - ILookInStream *inStream, UInt64 startPos, - Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, - Byte *tempBuf[]) -{ - UInt32 ci; - SizeT tempSizes[3] = { 0, 0, 0}; - SizeT tempSize3 = 0; - Byte *tempBuf3 = 0; - - RINOK(CheckSupportedFolder(folder)); - - for (ci = 0; ci < folder->NumCoders; ci++) - { - CSzCoderInfo *coder = &folder->Coders[ci]; - - if (IS_MAIN_METHOD((UInt32)coder->MethodID)) - { - UInt32 si = 0; - UInt64 offset; - UInt64 inSize; - Byte *outBufCur = outBuffer; - SizeT outSizeCur = outSize; - if (folder->NumCoders == 4) - { - UInt32 indices[] = { 3, 2, 0 }; - UInt64 unpackSize = folder->UnpackSizes[ci]; - si = indices[ci]; - if (ci < 2) - { - Byte *temp; - outSizeCur = (SizeT)unpackSize; - if (outSizeCur != unpackSize) - return SZ_ERROR_MEM; - temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur); - if (temp == 0 && outSizeCur != 0) - return SZ_ERROR_MEM; - outBufCur = tempBuf[1 - ci] = temp; - tempSizes[1 - ci] = outSizeCur; - } - else if (ci == 2) - { - if (unpackSize > outSize) /* check it */ - return SZ_ERROR_PARAM; - tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); - tempSize3 = outSizeCur = (SizeT)unpackSize; - } - else - return SZ_ERROR_UNSUPPORTED; - } - offset = GetSum(packSizes, si); - inSize = packSizes[si]; - RINOK(LookInStream_SeekTo(inStream, startPos + offset)); - - if (coder->MethodID == k_Copy) - { - if (inSize != outSizeCur) /* check it */ - return SZ_ERROR_DATA; - RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); - } - else if (coder->MethodID == k_LZMA) - { - RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); - } - else if (coder->MethodID == k_LZMA2) - { - RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); - } - else - { - #ifdef _7ZIP_PPMD_SUPPPORT - RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); - #else - return SZ_ERROR_UNSUPPORTED; - #endif - } - } - else if (coder->MethodID == k_BCJ2) - { - UInt64 offset = GetSum(packSizes, 1); - UInt64 s3Size = packSizes[1]; - SRes res; - if (ci != 3) - return SZ_ERROR_UNSUPPORTED; - RINOK(LookInStream_SeekTo(inStream, startPos + offset)); - tempSizes[2] = (SizeT)s3Size; - if (tempSizes[2] != s3Size) - return SZ_ERROR_MEM; - tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]); - if (tempBuf[2] == 0 && tempSizes[2] != 0) - return SZ_ERROR_MEM; - res = SzDecodeCopy(s3Size, inStream, tempBuf[2]); - RINOK(res) - - res = Bcj2_Decode( - tempBuf3, tempSize3, - tempBuf[0], tempSizes[0], - tempBuf[1], tempSizes[1], - tempBuf[2], tempSizes[2], - outBuffer, outSize); - RINOK(res) - } - else - { - if (ci != 1) - return SZ_ERROR_UNSUPPORTED; - switch(coder->MethodID) - { - case k_BCJ: - { - UInt32 state; - x86_Convert_Init(state); - x86_Convert(outBuffer, outSize, 0, &state, 0); - break; - } - CASE_BRA_CONV(ARM) - default: - return SZ_ERROR_UNSUPPORTED; - } - } - } - return SZ_OK; -} - -SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes, - ILookInStream *inStream, UInt64 startPos, - Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) -{ - Byte *tempBuf[3] = { 0, 0, 0}; - int i; - SRes res = SzFolder_Decode2(folder, packSizes, inStream, startPos, - outBuffer, (SizeT)outSize, allocMain, tempBuf); - for (i = 0; i < 3; i++) - IAlloc_Free(allocMain, tempBuf[i]); - return res; -} diff --git a/src/libs/7zip/win/C/7zFile.c b/src/libs/7zip/win/C/7zFile.c deleted file mode 100644 index a66c9e9d0..000000000 --- a/src/libs/7zip/win/C/7zFile.c +++ /dev/null @@ -1,284 +0,0 @@ -/* 7zFile.c -- File IO -2009-11-24 : Igor Pavlov : Public domain */ - -#include "7zFile.h" - -#ifndef USE_WINDOWS_FILE - -#ifndef UNDER_CE -#include -#endif - -#else - -/* - ReadFile and WriteFile functions in Windows have BUG: - If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) - from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES - (Insufficient system resources exist to complete the requested service). - Probably in some version of Windows there are problems with other sizes: - for 32 MB (maybe also for 16 MB). - And message can be "Network connection was lost" -*/ - -#define kChunkSizeMax (1 << 22) - -#endif - -void File_Construct(CSzFile *p) -{ - #ifdef USE_WINDOWS_FILE - p->handle = INVALID_HANDLE_VALUE; - #else - p->file = NULL; - #endif -} - -#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE) -static WRes File_Open(CSzFile *p, const char *name, int writeMode) -{ - #ifdef USE_WINDOWS_FILE - p->handle = CreateFileA(name, - writeMode ? GENERIC_WRITE : GENERIC_READ, - FILE_SHARE_READ, NULL, - writeMode ? CREATE_ALWAYS : OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL); - return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); - #else - p->file = fopen(name, writeMode ? "wb+" : "rb"); - return (p->file != 0) ? 0 : - #ifdef UNDER_CE - 2; /* ENOENT */ - #else - errno; - #endif - #endif -} - -WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); } -WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); } -#endif - -#ifdef USE_WINDOWS_FILE -static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode) -{ - p->handle = CreateFileW(name, - writeMode ? GENERIC_WRITE : GENERIC_READ, - FILE_SHARE_READ, NULL, - writeMode ? CREATE_ALWAYS : OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL); - return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); -} -WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); } -WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); } -#endif - -WRes File_Close(CSzFile *p) -{ - #ifdef USE_WINDOWS_FILE - if (p->handle != INVALID_HANDLE_VALUE) - { - if (!CloseHandle(p->handle)) - return GetLastError(); - p->handle = INVALID_HANDLE_VALUE; - } - #else - if (p->file != NULL) - { - int res = fclose(p->file); - if (res != 0) - return res; - p->file = NULL; - } - #endif - return 0; -} - -WRes File_Read(CSzFile *p, void *data, size_t *size) -{ - size_t originalSize = *size; - if (originalSize == 0) - return 0; - - #ifdef USE_WINDOWS_FILE - - *size = 0; - do - { - DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; - DWORD processed = 0; - BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL); - data = (void *)((Byte *)data + processed); - originalSize -= processed; - *size += processed; - if (!res) - return GetLastError(); - if (processed == 0) - break; - } - while (originalSize > 0); - return 0; - - #else - - *size = fread(data, 1, originalSize, p->file); - if (*size == originalSize) - return 0; - return ferror(p->file); - - #endif -} - -WRes File_Write(CSzFile *p, const void *data, size_t *size) -{ - size_t originalSize = *size; - if (originalSize == 0) - return 0; - - #ifdef USE_WINDOWS_FILE - - *size = 0; - do - { - DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; - DWORD processed = 0; - BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL); - data = (void *)((Byte *)data + processed); - originalSize -= processed; - *size += processed; - if (!res) - return GetLastError(); - if (processed == 0) - break; - } - while (originalSize > 0); - return 0; - - #else - - *size = fwrite(data, 1, originalSize, p->file); - if (*size == originalSize) - return 0; - return ferror(p->file); - - #endif -} - -WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin) -{ - #ifdef USE_WINDOWS_FILE - - LARGE_INTEGER value; - DWORD moveMethod; - value.LowPart = (DWORD)*pos; - value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */ - switch (origin) - { - case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break; - case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break; - case SZ_SEEK_END: moveMethod = FILE_END; break; - default: return ERROR_INVALID_PARAMETER; - } - value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod); - if (value.LowPart == 0xFFFFFFFF) - { - WRes res = GetLastError(); - if (res != NO_ERROR) - return res; - } - *pos = ((Int64)value.HighPart << 32) | value.LowPart; - return 0; - - #else - - int moveMethod; - int res; - switch (origin) - { - case SZ_SEEK_SET: moveMethod = SEEK_SET; break; - case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break; - case SZ_SEEK_END: moveMethod = SEEK_END; break; - default: return 1; - } - res = fseek(p->file, (long)*pos, moveMethod); - *pos = ftell(p->file); - return res; - - #endif -} - -WRes File_GetLength(CSzFile *p, UInt64 *length) -{ - #ifdef USE_WINDOWS_FILE - - DWORD sizeHigh; - DWORD sizeLow = GetFileSize(p->handle, &sizeHigh); - if (sizeLow == 0xFFFFFFFF) - { - DWORD res = GetLastError(); - if (res != NO_ERROR) - return res; - } - *length = (((UInt64)sizeHigh) << 32) + sizeLow; - return 0; - - #else - - long pos = ftell(p->file); - int res = fseek(p->file, 0, SEEK_END); - *length = ftell(p->file); - fseek(p->file, pos, SEEK_SET); - return res; - - #endif -} - - -/* ---------- FileSeqInStream ---------- */ - -static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size) -{ - CFileSeqInStream *p = (CFileSeqInStream *)pp; - return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ; -} - -void FileSeqInStream_CreateVTable(CFileSeqInStream *p) -{ - p->s.Read = FileSeqInStream_Read; -} - - -/* ---------- FileInStream ---------- */ - -static SRes FileInStream_Read(void *pp, void *buf, size_t *size) -{ - CFileInStream *p = (CFileInStream *)pp; - return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ; -} - -static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin) -{ - CFileInStream *p = (CFileInStream *)pp; - return File_Seek(&p->file, pos, origin); -} - -void FileInStream_CreateVTable(CFileInStream *p) -{ - p->s.Read = FileInStream_Read; - p->s.Seek = FileInStream_Seek; -} - - -/* ---------- FileOutStream ---------- */ - -static size_t FileOutStream_Write(void *pp, const void *data, size_t size) -{ - CFileOutStream *p = (CFileOutStream *)pp; - File_Write(&p->file, data, &size); - return size; -} - -void FileOutStream_CreateVTable(CFileOutStream *p) -{ - p->s.Write = FileOutStream_Write; -} diff --git a/src/libs/7zip/win/C/7zFile.h b/src/libs/7zip/win/C/7zFile.h deleted file mode 100644 index 84538c03f..000000000 --- a/src/libs/7zip/win/C/7zFile.h +++ /dev/null @@ -1,83 +0,0 @@ -/* 7zFile.h -- File IO -2009-11-24 : Igor Pavlov : Public domain */ - -#ifndef __7Z_FILE_H -#define __7Z_FILE_H - -#ifdef _WIN32 -#define USE_WINDOWS_FILE -#endif - -#ifdef USE_WINDOWS_FILE -#include -#else -#include -#endif - -#include "Types.h" - -EXTERN_C_BEGIN - -/* ---------- File ---------- */ - -typedef struct -{ - #ifdef USE_WINDOWS_FILE - HANDLE handle; - #else - FILE *file; - #endif -} CSzFile; - -void File_Construct(CSzFile *p); -#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE) -WRes InFile_Open(CSzFile *p, const char *name); -WRes OutFile_Open(CSzFile *p, const char *name); -#endif -#ifdef USE_WINDOWS_FILE -WRes InFile_OpenW(CSzFile *p, const WCHAR *name); -WRes OutFile_OpenW(CSzFile *p, const WCHAR *name); -#endif -WRes File_Close(CSzFile *p); - -/* reads max(*size, remain file's size) bytes */ -WRes File_Read(CSzFile *p, void *data, size_t *size); - -/* writes *size bytes */ -WRes File_Write(CSzFile *p, const void *data, size_t *size); - -WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin); -WRes File_GetLength(CSzFile *p, UInt64 *length); - - -/* ---------- FileInStream ---------- */ - -typedef struct -{ - ISeqInStream s; - CSzFile file; -} CFileSeqInStream; - -void FileSeqInStream_CreateVTable(CFileSeqInStream *p); - - -typedef struct -{ - ISeekInStream s; - CSzFile file; -} CFileInStream; - -void FileInStream_CreateVTable(CFileInStream *p); - - -typedef struct -{ - ISeqOutStream s; - CSzFile file; -} CFileOutStream; - -void FileOutStream_CreateVTable(CFileOutStream *p); - -EXTERN_C_END - -#endif diff --git a/src/libs/7zip/win/C/7zIn.c b/src/libs/7zip/win/C/7zIn.c deleted file mode 100644 index ec93a43ff..000000000 --- a/src/libs/7zip/win/C/7zIn.c +++ /dev/null @@ -1,1402 +0,0 @@ -/* 7zIn.c -- 7z Input functions -2010-10-29 : Igor Pavlov : Public domain */ - -#include - -#include "7z.h" -#include "7zCrc.h" -#include "CpuArch.h" - -Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; - -#define RINOM(x) { if ((x) == 0) return SZ_ERROR_MEM; } - -#define NUM_FOLDER_CODERS_MAX 32 -#define NUM_CODER_STREAMS_MAX 32 - -void SzCoderInfo_Init(CSzCoderInfo *p) -{ - Buf_Init(&p->Props); -} - -void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc) -{ - Buf_Free(&p->Props, alloc); - SzCoderInfo_Init(p); -} - -void SzFolder_Init(CSzFolder *p) -{ - p->Coders = 0; - p->BindPairs = 0; - p->PackStreams = 0; - p->UnpackSizes = 0; - p->NumCoders = 0; - p->NumBindPairs = 0; - p->NumPackStreams = 0; - p->UnpackCRCDefined = 0; - p->UnpackCRC = 0; - p->NumUnpackStreams = 0; -} - -void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc) -{ - UInt32 i; - if (p->Coders) - for (i = 0; i < p->NumCoders; i++) - SzCoderInfo_Free(&p->Coders[i], alloc); - IAlloc_Free(alloc, p->Coders); - IAlloc_Free(alloc, p->BindPairs); - IAlloc_Free(alloc, p->PackStreams); - IAlloc_Free(alloc, p->UnpackSizes); - SzFolder_Init(p); -} - -UInt32 SzFolder_GetNumOutStreams(CSzFolder *p) -{ - UInt32 result = 0; - UInt32 i; - for (i = 0; i < p->NumCoders; i++) - result += p->Coders[i].NumOutStreams; - return result; -} - -int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex) -{ - UInt32 i; - for (i = 0; i < p->NumBindPairs; i++) - if (p->BindPairs[i].InIndex == inStreamIndex) - return i; - return -1; -} - - -int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex) -{ - UInt32 i; - for (i = 0; i < p->NumBindPairs; i++) - if (p->BindPairs[i].OutIndex == outStreamIndex) - return i; - return -1; -} - -UInt64 SzFolder_GetUnpackSize(CSzFolder *p) -{ - int i = (int)SzFolder_GetNumOutStreams(p); - if (i == 0) - return 0; - for (i--; i >= 0; i--) - if (SzFolder_FindBindPairForOutStream(p, i) < 0) - return p->UnpackSizes[i]; - /* throw 1; */ - return 0; -} - -void SzFile_Init(CSzFileItem *p) -{ - p->HasStream = 1; - p->IsDir = 0; - p->IsAnti = 0; - p->CrcDefined = 0; - p->MTimeDefined = 0; -} - -void SzAr_Init(CSzAr *p) -{ - p->PackSizes = 0; - p->PackCRCsDefined = 0; - p->PackCRCs = 0; - p->Folders = 0; - p->Files = 0; - p->NumPackStreams = 0; - p->NumFolders = 0; - p->NumFiles = 0; -} - -void SzAr_Free(CSzAr *p, ISzAlloc *alloc) -{ - UInt32 i; - if (p->Folders) - for (i = 0; i < p->NumFolders; i++) - SzFolder_Free(&p->Folders[i], alloc); - - IAlloc_Free(alloc, p->PackSizes); - IAlloc_Free(alloc, p->PackCRCsDefined); - IAlloc_Free(alloc, p->PackCRCs); - IAlloc_Free(alloc, p->Folders); - IAlloc_Free(alloc, p->Files); - SzAr_Init(p); -} - - -void SzArEx_Init(CSzArEx *p) -{ - SzAr_Init(&p->db); - p->FolderStartPackStreamIndex = 0; - p->PackStreamStartPositions = 0; - p->FolderStartFileIndex = 0; - p->FileIndexToFolderIndexMap = 0; - p->FileNameOffsets = 0; - Buf_Init(&p->FileNames); -} - -void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) -{ - IAlloc_Free(alloc, p->FolderStartPackStreamIndex); - IAlloc_Free(alloc, p->PackStreamStartPositions); - IAlloc_Free(alloc, p->FolderStartFileIndex); - IAlloc_Free(alloc, p->FileIndexToFolderIndexMap); - - IAlloc_Free(alloc, p->FileNameOffsets); - Buf_Free(&p->FileNames, alloc); - - SzAr_Free(&p->db, alloc); - SzArEx_Init(p); -} - -/* -UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const -{ - return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; -} - -UInt64 GetFilePackSize(int fileIndex) const -{ - int folderIndex = FileIndexToFolderIndexMap[fileIndex]; - if (folderIndex >= 0) - { - const CSzFolder &folderInfo = Folders[folderIndex]; - if (FolderStartFileIndex[folderIndex] == fileIndex) - return GetFolderFullPackSize(folderIndex); - } - return 0; -} -*/ - -#define MY_ALLOC(T, p, size, alloc) { if ((size) == 0) p = 0; else \ - if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == 0) return SZ_ERROR_MEM; } - -static SRes SzArEx_Fill(CSzArEx *p, ISzAlloc *alloc) -{ - UInt32 startPos = 0; - UInt64 startPosSize = 0; - UInt32 i; - UInt32 folderIndex = 0; - UInt32 indexInFolder = 0; - MY_ALLOC(UInt32, p->FolderStartPackStreamIndex, p->db.NumFolders, alloc); - for (i = 0; i < p->db.NumFolders; i++) - { - p->FolderStartPackStreamIndex[i] = startPos; - startPos += p->db.Folders[i].NumPackStreams; - } - - MY_ALLOC(UInt64, p->PackStreamStartPositions, p->db.NumPackStreams, alloc); - - for (i = 0; i < p->db.NumPackStreams; i++) - { - p->PackStreamStartPositions[i] = startPosSize; - startPosSize += p->db.PackSizes[i]; - } - - MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders, alloc); - MY_ALLOC(UInt32, p->FileIndexToFolderIndexMap, p->db.NumFiles, alloc); - - for (i = 0; i < p->db.NumFiles; i++) - { - CSzFileItem *file = p->db.Files + i; - int emptyStream = !file->HasStream; - if (emptyStream && indexInFolder == 0) - { - p->FileIndexToFolderIndexMap[i] = (UInt32)-1; - continue; - } - if (indexInFolder == 0) - { - /* - v3.13 incorrectly worked with empty folders - v4.07: Loop for skipping empty folders - */ - for (;;) - { - if (folderIndex >= p->db.NumFolders) - return SZ_ERROR_ARCHIVE; - p->FolderStartFileIndex[folderIndex] = i; - if (p->db.Folders[folderIndex].NumUnpackStreams != 0) - break; - folderIndex++; - } - } - p->FileIndexToFolderIndexMap[i] = folderIndex; - if (emptyStream) - continue; - indexInFolder++; - if (indexInFolder >= p->db.Folders[folderIndex].NumUnpackStreams) - { - folderIndex++; - indexInFolder = 0; - } - } - return SZ_OK; -} - - -UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder) -{ - return p->dataPos + - p->PackStreamStartPositions[p->FolderStartPackStreamIndex[folderIndex] + indexInFolder]; -} - -int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize) -{ - UInt32 packStreamIndex = p->FolderStartPackStreamIndex[folderIndex]; - CSzFolder *folder = p->db.Folders + folderIndex; - UInt64 size = 0; - UInt32 i; - for (i = 0; i < folder->NumPackStreams; i++) - { - UInt64 t = size + p->db.PackSizes[packStreamIndex + i]; - if (t < size) /* check it */ - return SZ_ERROR_FAIL; - size = t; - } - *resSize = size; - return SZ_OK; -} - - -/* -SRes SzReadTime(const CObjectVector &dataVector, - CObjectVector &files, UInt64 type) -{ - CBoolVector boolVector; - RINOK(ReadBoolVector2(files.Size(), boolVector)) - - CStreamSwitch streamSwitch; - RINOK(streamSwitch.Set(this, &dataVector)); - - for (int i = 0; i < files.Size(); i++) - { - CSzFileItem &file = files[i]; - CArchiveFileTime fileTime; - bool defined = boolVector[i]; - if (defined) - { - UInt32 low, high; - RINOK(SzReadUInt32(low)); - RINOK(SzReadUInt32(high)); - fileTime.dwLowDateTime = low; - fileTime.dwHighDateTime = high; - } - switch(type) - { - case k7zIdCTime: file.IsCTimeDefined = defined; if (defined) file.CTime = fileTime; break; - case k7zIdATime: file.IsATimeDefined = defined; if (defined) file.ATime = fileTime; break; - case k7zIdMTime: file.IsMTimeDefined = defined; if (defined) file.MTime = fileTime; break; - } - } - return SZ_OK; -} -*/ - -static int TestSignatureCandidate(Byte *testBytes) -{ - size_t i; - for (i = 0; i < k7zSignatureSize; i++) - if (testBytes[i] != k7zSignature[i]) - return 0; - return 1; -} - -typedef struct _CSzState -{ - Byte *Data; - size_t Size; -}CSzData; - -static SRes SzReadByte(CSzData *sd, Byte *b) -{ - if (sd->Size == 0) - return SZ_ERROR_ARCHIVE; - sd->Size--; - *b = *sd->Data++; - return SZ_OK; -} - -static SRes SzReadBytes(CSzData *sd, Byte *data, size_t size) -{ - size_t i; - for (i = 0; i < size; i++) - { - RINOK(SzReadByte(sd, data + i)); - } - return SZ_OK; -} - -static SRes SzReadUInt32(CSzData *sd, UInt32 *value) -{ - int i; - *value = 0; - for (i = 0; i < 4; i++) - { - Byte b; - RINOK(SzReadByte(sd, &b)); - *value |= ((UInt32)(b) << (8 * i)); - } - return SZ_OK; -} - -static SRes SzReadNumber(CSzData *sd, UInt64 *value) -{ - Byte firstByte; - Byte mask = 0x80; - int i; - RINOK(SzReadByte(sd, &firstByte)); - *value = 0; - for (i = 0; i < 8; i++) - { - Byte b; - if ((firstByte & mask) == 0) - { - UInt64 highPart = firstByte & (mask - 1); - *value += (highPart << (8 * i)); - return SZ_OK; - } - RINOK(SzReadByte(sd, &b)); - *value |= ((UInt64)b << (8 * i)); - mask >>= 1; - } - return SZ_OK; -} - -static SRes SzReadNumber32(CSzData *sd, UInt32 *value) -{ - UInt64 value64; - RINOK(SzReadNumber(sd, &value64)); - if (value64 >= 0x80000000) - return SZ_ERROR_UNSUPPORTED; - if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2))) - return SZ_ERROR_UNSUPPORTED; - *value = (UInt32)value64; - return SZ_OK; -} - -static SRes SzReadID(CSzData *sd, UInt64 *value) -{ - return SzReadNumber(sd, value); -} - -static SRes SzSkeepDataSize(CSzData *sd, UInt64 size) -{ - if (size > sd->Size) - return SZ_ERROR_ARCHIVE; - sd->Size -= (size_t)size; - sd->Data += (size_t)size; - return SZ_OK; -} - -static SRes SzSkeepData(CSzData *sd) -{ - UInt64 size; - RINOK(SzReadNumber(sd, &size)); - return SzSkeepDataSize(sd, size); -} - -static SRes SzReadArchiveProperties(CSzData *sd) -{ - for (;;) - { - UInt64 type; - RINOK(SzReadID(sd, &type)); - if (type == k7zIdEnd) - break; - SzSkeepData(sd); - } - return SZ_OK; -} - -static SRes SzWaitAttribute(CSzData *sd, UInt64 attribute) -{ - for (;;) - { - UInt64 type; - RINOK(SzReadID(sd, &type)); - if (type == attribute) - return SZ_OK; - if (type == k7zIdEnd) - return SZ_ERROR_ARCHIVE; - RINOK(SzSkeepData(sd)); - } -} - -static SRes SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc) -{ - Byte b = 0; - Byte mask = 0; - size_t i; - MY_ALLOC(Byte, *v, numItems, alloc); - for (i = 0; i < numItems; i++) - { - if (mask == 0) - { - RINOK(SzReadByte(sd, &b)); - mask = 0x80; - } - (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0); - mask >>= 1; - } - return SZ_OK; -} - -static SRes SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc) -{ - Byte allAreDefined; - size_t i; - RINOK(SzReadByte(sd, &allAreDefined)); - if (allAreDefined == 0) - return SzReadBoolVector(sd, numItems, v, alloc); - MY_ALLOC(Byte, *v, numItems, alloc); - for (i = 0; i < numItems; i++) - (*v)[i] = 1; - return SZ_OK; -} - -static SRes SzReadHashDigests( - CSzData *sd, - size_t numItems, - Byte **digestsDefined, - UInt32 **digests, - ISzAlloc *alloc) -{ - size_t i; - RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, alloc)); - MY_ALLOC(UInt32, *digests, numItems, alloc); - for (i = 0; i < numItems; i++) - if ((*digestsDefined)[i]) - { - RINOK(SzReadUInt32(sd, (*digests) + i)); - } - return SZ_OK; -} - -static SRes SzReadPackInfo( - CSzData *sd, - UInt64 *dataOffset, - UInt32 *numPackStreams, - UInt64 **packSizes, - Byte **packCRCsDefined, - UInt32 **packCRCs, - ISzAlloc *alloc) -{ - UInt32 i; - RINOK(SzReadNumber(sd, dataOffset)); - RINOK(SzReadNumber32(sd, numPackStreams)); - - RINOK(SzWaitAttribute(sd, k7zIdSize)); - - MY_ALLOC(UInt64, *packSizes, (size_t)*numPackStreams, alloc); - - for (i = 0; i < *numPackStreams; i++) - { - RINOK(SzReadNumber(sd, (*packSizes) + i)); - } - - for (;;) - { - UInt64 type; - RINOK(SzReadID(sd, &type)); - if (type == k7zIdEnd) - break; - if (type == k7zIdCRC) - { - RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, alloc)); - continue; - } - RINOK(SzSkeepData(sd)); - } - if (*packCRCsDefined == 0) - { - MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, alloc); - MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, alloc); - for (i = 0; i < *numPackStreams; i++) - { - (*packCRCsDefined)[i] = 0; - (*packCRCs)[i] = 0; - } - } - return SZ_OK; -} - -static SRes SzReadSwitch(CSzData *sd) -{ - Byte external; - RINOK(SzReadByte(sd, &external)); - return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED; -} - -static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc) -{ - UInt32 numCoders, numBindPairs, numPackStreams, i; - UInt32 numInStreams = 0, numOutStreams = 0; - - RINOK(SzReadNumber32(sd, &numCoders)); - if (numCoders > NUM_FOLDER_CODERS_MAX) - return SZ_ERROR_UNSUPPORTED; - folder->NumCoders = numCoders; - - MY_ALLOC(CSzCoderInfo, folder->Coders, (size_t)numCoders, alloc); - - for (i = 0; i < numCoders; i++) - SzCoderInfo_Init(folder->Coders + i); - - for (i = 0; i < numCoders; i++) - { - Byte mainByte; - CSzCoderInfo *coder = folder->Coders + i; - { - unsigned idSize, j; - Byte longID[15]; - RINOK(SzReadByte(sd, &mainByte)); - idSize = (unsigned)(mainByte & 0xF); - RINOK(SzReadBytes(sd, longID, idSize)); - if (idSize > sizeof(coder->MethodID)) - return SZ_ERROR_UNSUPPORTED; - coder->MethodID = 0; - for (j = 0; j < idSize; j++) - coder->MethodID |= (UInt64)longID[idSize - 1 - j] << (8 * j); - - if ((mainByte & 0x10) != 0) - { - RINOK(SzReadNumber32(sd, &coder->NumInStreams)); - RINOK(SzReadNumber32(sd, &coder->NumOutStreams)); - if (coder->NumInStreams > NUM_CODER_STREAMS_MAX || - coder->NumOutStreams > NUM_CODER_STREAMS_MAX) - return SZ_ERROR_UNSUPPORTED; - } - else - { - coder->NumInStreams = 1; - coder->NumOutStreams = 1; - } - if ((mainByte & 0x20) != 0) - { - UInt64 propertiesSize = 0; - RINOK(SzReadNumber(sd, &propertiesSize)); - if (!Buf_Create(&coder->Props, (size_t)propertiesSize, alloc)) - return SZ_ERROR_MEM; - RINOK(SzReadBytes(sd, coder->Props.data, (size_t)propertiesSize)); - } - } - while ((mainByte & 0x80) != 0) - { - RINOK(SzReadByte(sd, &mainByte)); - RINOK(SzSkeepDataSize(sd, (mainByte & 0xF))); - if ((mainByte & 0x10) != 0) - { - UInt32 n; - RINOK(SzReadNumber32(sd, &n)); - RINOK(SzReadNumber32(sd, &n)); - } - if ((mainByte & 0x20) != 0) - { - UInt64 propertiesSize = 0; - RINOK(SzReadNumber(sd, &propertiesSize)); - RINOK(SzSkeepDataSize(sd, propertiesSize)); - } - } - numInStreams += coder->NumInStreams; - numOutStreams += coder->NumOutStreams; - } - - if (numOutStreams == 0) - return SZ_ERROR_UNSUPPORTED; - - folder->NumBindPairs = numBindPairs = numOutStreams - 1; - MY_ALLOC(CSzBindPair, folder->BindPairs, (size_t)numBindPairs, alloc); - - for (i = 0; i < numBindPairs; i++) - { - CSzBindPair *bp = folder->BindPairs + i; - RINOK(SzReadNumber32(sd, &bp->InIndex)); - RINOK(SzReadNumber32(sd, &bp->OutIndex)); - } - - if (numInStreams < numBindPairs) - return SZ_ERROR_UNSUPPORTED; - - folder->NumPackStreams = numPackStreams = numInStreams - numBindPairs; - MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackStreams, alloc); - - if (numPackStreams == 1) - { - for (i = 0; i < numInStreams ; i++) - if (SzFolder_FindBindPairForInStream(folder, i) < 0) - break; - if (i == numInStreams) - return SZ_ERROR_UNSUPPORTED; - folder->PackStreams[0] = i; - } - else - for (i = 0; i < numPackStreams; i++) - { - RINOK(SzReadNumber32(sd, folder->PackStreams + i)); - } - return SZ_OK; -} - -static SRes SzReadUnpackInfo( - CSzData *sd, - UInt32 *numFolders, - CSzFolder **folders, /* for alloc */ - ISzAlloc *alloc, - ISzAlloc *allocTemp) -{ - UInt32 i; - RINOK(SzWaitAttribute(sd, k7zIdFolder)); - RINOK(SzReadNumber32(sd, numFolders)); - { - RINOK(SzReadSwitch(sd)); - - MY_ALLOC(CSzFolder, *folders, (size_t)*numFolders, alloc); - - for (i = 0; i < *numFolders; i++) - SzFolder_Init((*folders) + i); - - for (i = 0; i < *numFolders; i++) - { - RINOK(SzGetNextFolderItem(sd, (*folders) + i, alloc)); - } - } - - RINOK(SzWaitAttribute(sd, k7zIdCodersUnpackSize)); - - for (i = 0; i < *numFolders; i++) - { - UInt32 j; - CSzFolder *folder = (*folders) + i; - UInt32 numOutStreams = SzFolder_GetNumOutStreams(folder); - - MY_ALLOC(UInt64, folder->UnpackSizes, (size_t)numOutStreams, alloc); - - for (j = 0; j < numOutStreams; j++) - { - RINOK(SzReadNumber(sd, folder->UnpackSizes + j)); - } - } - - for (;;) - { - UInt64 type; - RINOK(SzReadID(sd, &type)); - if (type == k7zIdEnd) - return SZ_OK; - if (type == k7zIdCRC) - { - SRes res; - Byte *crcsDefined = 0; - UInt32 *crcs = 0; - res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp); - if (res == SZ_OK) - { - for (i = 0; i < *numFolders; i++) - { - CSzFolder *folder = (*folders) + i; - folder->UnpackCRCDefined = crcsDefined[i]; - folder->UnpackCRC = crcs[i]; - } - } - IAlloc_Free(allocTemp, crcs); - IAlloc_Free(allocTemp, crcsDefined); - RINOK(res); - continue; - } - RINOK(SzSkeepData(sd)); - } -} - -static SRes SzReadSubStreamsInfo( - CSzData *sd, - UInt32 numFolders, - CSzFolder *folders, - UInt32 *numUnpackStreams, - UInt64 **unpackSizes, - Byte **digestsDefined, - UInt32 **digests, - ISzAlloc *allocTemp) -{ - UInt64 type = 0; - UInt32 i; - UInt32 si = 0; - UInt32 numDigests = 0; - - for (i = 0; i < numFolders; i++) - folders[i].NumUnpackStreams = 1; - *numUnpackStreams = numFolders; - - for (;;) - { - RINOK(SzReadID(sd, &type)); - if (type == k7zIdNumUnpackStream) - { - *numUnpackStreams = 0; - for (i = 0; i < numFolders; i++) - { - UInt32 numStreams; - RINOK(SzReadNumber32(sd, &numStreams)); - folders[i].NumUnpackStreams = numStreams; - *numUnpackStreams += numStreams; - } - continue; - } - if (type == k7zIdCRC || type == k7zIdSize) - break; - if (type == k7zIdEnd) - break; - RINOK(SzSkeepData(sd)); - } - - if (*numUnpackStreams == 0) - { - *unpackSizes = 0; - *digestsDefined = 0; - *digests = 0; - } - else - { - *unpackSizes = (UInt64 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt64)); - RINOM(*unpackSizes); - *digestsDefined = (Byte *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(Byte)); - RINOM(*digestsDefined); - *digests = (UInt32 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt32)); - RINOM(*digests); - } - - for (i = 0; i < numFolders; i++) - { - /* - v3.13 incorrectly worked with empty folders - v4.07: we check that folder is empty - */ - UInt64 sum = 0; - UInt32 j; - UInt32 numSubstreams = folders[i].NumUnpackStreams; - if (numSubstreams == 0) - continue; - if (type == k7zIdSize) - for (j = 1; j < numSubstreams; j++) - { - UInt64 size; - RINOK(SzReadNumber(sd, &size)); - (*unpackSizes)[si++] = size; - sum += size; - } - (*unpackSizes)[si++] = SzFolder_GetUnpackSize(folders + i) - sum; - } - if (type == k7zIdSize) - { - RINOK(SzReadID(sd, &type)); - } - - for (i = 0; i < *numUnpackStreams; i++) - { - (*digestsDefined)[i] = 0; - (*digests)[i] = 0; - } - - - for (i = 0; i < numFolders; i++) - { - UInt32 numSubstreams = folders[i].NumUnpackStreams; - if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) - numDigests += numSubstreams; - } - - - si = 0; - for (;;) - { - if (type == k7zIdCRC) - { - int digestIndex = 0; - Byte *digestsDefined2 = 0; - UInt32 *digests2 = 0; - SRes res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp); - if (res == SZ_OK) - { - for (i = 0; i < numFolders; i++) - { - CSzFolder *folder = folders + i; - UInt32 numSubstreams = folder->NumUnpackStreams; - if (numSubstreams == 1 && folder->UnpackCRCDefined) - { - (*digestsDefined)[si] = 1; - (*digests)[si] = folder->UnpackCRC; - si++; - } - else - { - UInt32 j; - for (j = 0; j < numSubstreams; j++, digestIndex++) - { - (*digestsDefined)[si] = digestsDefined2[digestIndex]; - (*digests)[si] = digests2[digestIndex]; - si++; - } - } - } - } - IAlloc_Free(allocTemp, digestsDefined2); - IAlloc_Free(allocTemp, digests2); - RINOK(res); - } - else if (type == k7zIdEnd) - return SZ_OK; - else - { - RINOK(SzSkeepData(sd)); - } - RINOK(SzReadID(sd, &type)); - } -} - - -static SRes SzReadStreamsInfo( - CSzData *sd, - UInt64 *dataOffset, - CSzAr *p, - UInt32 *numUnpackStreams, - UInt64 **unpackSizes, /* allocTemp */ - Byte **digestsDefined, /* allocTemp */ - UInt32 **digests, /* allocTemp */ - ISzAlloc *alloc, - ISzAlloc *allocTemp) -{ - for (;;) - { - UInt64 type; - RINOK(SzReadID(sd, &type)); - if ((UInt64)(int)type != type) - return SZ_ERROR_UNSUPPORTED; - switch((int)type) - { - case k7zIdEnd: - return SZ_OK; - case k7zIdPackInfo: - { - RINOK(SzReadPackInfo(sd, dataOffset, &p->NumPackStreams, - &p->PackSizes, &p->PackCRCsDefined, &p->PackCRCs, alloc)); - break; - } - case k7zIdUnpackInfo: - { - RINOK(SzReadUnpackInfo(sd, &p->NumFolders, &p->Folders, alloc, allocTemp)); - break; - } - case k7zIdSubStreamsInfo: - { - RINOK(SzReadSubStreamsInfo(sd, p->NumFolders, p->Folders, - numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp)); - break; - } - default: - return SZ_ERROR_UNSUPPORTED; - } - } -} - -size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest) -{ - size_t len = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex]; - if (dest != 0) - { - size_t i; - const Byte *src = p->FileNames.data + (p->FileNameOffsets[fileIndex] * 2); - for (i = 0; i < len; i++) - dest[i] = GetUi16(src + i * 2); - } - return len; -} - -static SRes SzReadFileNames(const Byte *p, size_t size, UInt32 numFiles, size_t *sizes) -{ - UInt32 i; - size_t pos = 0; - for (i = 0; i < numFiles; i++) - { - sizes[i] = pos; - for (;;) - { - if (pos >= size) - return SZ_ERROR_ARCHIVE; - if (p[pos * 2] == 0 && p[pos * 2 + 1] == 0) - break; - pos++; - } - pos++; - } - sizes[i] = pos; - return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE; -} - -static SRes SzReadHeader2( - CSzArEx *p, /* allocMain */ - CSzData *sd, - UInt64 **unpackSizes, /* allocTemp */ - Byte **digestsDefined, /* allocTemp */ - UInt32 **digests, /* allocTemp */ - Byte **emptyStreamVector, /* allocTemp */ - Byte **emptyFileVector, /* allocTemp */ - Byte **lwtVector, /* allocTemp */ - ISzAlloc *allocMain, - ISzAlloc *allocTemp) -{ - UInt64 type; - UInt32 numUnpackStreams = 0; - UInt32 numFiles = 0; - CSzFileItem *files = 0; - UInt32 numEmptyStreams = 0; - UInt32 i; - - RINOK(SzReadID(sd, &type)); - - if (type == k7zIdArchiveProperties) - { - RINOK(SzReadArchiveProperties(sd)); - RINOK(SzReadID(sd, &type)); - } - - - if (type == k7zIdMainStreamsInfo) - { - RINOK(SzReadStreamsInfo(sd, - &p->dataPos, - &p->db, - &numUnpackStreams, - unpackSizes, - digestsDefined, - digests, allocMain, allocTemp)); - p->dataPos += p->startPosAfterHeader; - RINOK(SzReadID(sd, &type)); - } - - if (type == k7zIdEnd) - return SZ_OK; - if (type != k7zIdFilesInfo) - return SZ_ERROR_ARCHIVE; - - RINOK(SzReadNumber32(sd, &numFiles)); - p->db.NumFiles = numFiles; - - MY_ALLOC(CSzFileItem, files, (size_t)numFiles, allocMain); - - p->db.Files = files; - for (i = 0; i < numFiles; i++) - SzFile_Init(files + i); - - for (;;) - { - UInt64 type; - UInt64 size; - RINOK(SzReadID(sd, &type)); - if (type == k7zIdEnd) - break; - RINOK(SzReadNumber(sd, &size)); - if (size > sd->Size) - return SZ_ERROR_ARCHIVE; - if ((UInt64)(int)type != type) - { - RINOK(SzSkeepDataSize(sd, size)); - } - else - switch((int)type) - { - case k7zIdName: - { - size_t namesSize; - RINOK(SzReadSwitch(sd)); - namesSize = (size_t)size - 1; - if ((namesSize & 1) != 0) - return SZ_ERROR_ARCHIVE; - if (!Buf_Create(&p->FileNames, namesSize, allocMain)) - return SZ_ERROR_MEM; - MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain); - memcpy(p->FileNames.data, sd->Data, namesSize); - RINOK(SzReadFileNames(sd->Data, namesSize >> 1, numFiles, p->FileNameOffsets)) - RINOK(SzSkeepDataSize(sd, namesSize)); - break; - } - case k7zIdEmptyStream: - { - RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp)); - numEmptyStreams = 0; - for (i = 0; i < numFiles; i++) - if ((*emptyStreamVector)[i]) - numEmptyStreams++; - break; - } - case k7zIdEmptyFile: - { - RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp)); - break; - } - case k7zIdWinAttributes: - { - RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); - RINOK(SzReadSwitch(sd)); - for (i = 0; i < numFiles; i++) - { - CSzFileItem *f = &files[i]; - Byte defined = (*lwtVector)[i]; - f->AttribDefined = defined; - f->Attrib = 0; - if (defined) - { - RINOK(SzReadUInt32(sd, &f->Attrib)); - } - } - IAlloc_Free(allocTemp, *lwtVector); - *lwtVector = NULL; - break; - } - case k7zIdMTime: - { - RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); - RINOK(SzReadSwitch(sd)); - for (i = 0; i < numFiles; i++) - { - CSzFileItem *f = &files[i]; - Byte defined = (*lwtVector)[i]; - f->MTimeDefined = defined; - f->MTime.Low = f->MTime.High = 0; - if (defined) - { - RINOK(SzReadUInt32(sd, &f->MTime.Low)); - RINOK(SzReadUInt32(sd, &f->MTime.High)); - } - } - IAlloc_Free(allocTemp, *lwtVector); - *lwtVector = NULL; - break; - } - default: - { - RINOK(SzSkeepDataSize(sd, size)); - } - } - } - - { - UInt32 emptyFileIndex = 0; - UInt32 sizeIndex = 0; - for (i = 0; i < numFiles; i++) - { - CSzFileItem *file = files + i; - file->IsAnti = 0; - if (*emptyStreamVector == 0) - file->HasStream = 1; - else - file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1); - if (file->HasStream) - { - file->IsDir = 0; - file->Size = (*unpackSizes)[sizeIndex]; - file->Crc = (*digests)[sizeIndex]; - file->CrcDefined = (Byte)(*digestsDefined)[sizeIndex]; - sizeIndex++; - } - else - { - if (*emptyFileVector == 0) - file->IsDir = 1; - else - file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); - emptyFileIndex++; - file->Size = 0; - file->Crc = 0; - file->CrcDefined = 0; - } - } - } - return SzArEx_Fill(p, allocMain); -} - -static SRes SzReadHeader( - CSzArEx *p, - CSzData *sd, - ISzAlloc *allocMain, - ISzAlloc *allocTemp) -{ - UInt64 *unpackSizes = 0; - Byte *digestsDefined = 0; - UInt32 *digests = 0; - Byte *emptyStreamVector = 0; - Byte *emptyFileVector = 0; - Byte *lwtVector = 0; - SRes res = SzReadHeader2(p, sd, - &unpackSizes, &digestsDefined, &digests, - &emptyStreamVector, &emptyFileVector, &lwtVector, - allocMain, allocTemp); - IAlloc_Free(allocTemp, unpackSizes); - IAlloc_Free(allocTemp, digestsDefined); - IAlloc_Free(allocTemp, digests); - IAlloc_Free(allocTemp, emptyStreamVector); - IAlloc_Free(allocTemp, emptyFileVector); - IAlloc_Free(allocTemp, lwtVector); - return res; -} - -static SRes SzReadAndDecodePackedStreams2( - ILookInStream *inStream, - CSzData *sd, - CBuf *outBuffer, - UInt64 baseOffset, - CSzAr *p, - UInt64 **unpackSizes, - Byte **digestsDefined, - UInt32 **digests, - ISzAlloc *allocTemp) -{ - - UInt32 numUnpackStreams = 0; - UInt64 dataStartPos; - CSzFolder *folder; - UInt64 unpackSize; - SRes res; - - RINOK(SzReadStreamsInfo(sd, &dataStartPos, p, - &numUnpackStreams, unpackSizes, digestsDefined, digests, - allocTemp, allocTemp)); - - dataStartPos += baseOffset; - if (p->NumFolders != 1) - return SZ_ERROR_ARCHIVE; - - folder = p->Folders; - unpackSize = SzFolder_GetUnpackSize(folder); - - RINOK(LookInStream_SeekTo(inStream, dataStartPos)); - - if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp)) - return SZ_ERROR_MEM; - - res = SzFolder_Decode(folder, p->PackSizes, - inStream, dataStartPos, - outBuffer->data, (size_t)unpackSize, allocTemp); - RINOK(res); - if (folder->UnpackCRCDefined) - if (CrcCalc(outBuffer->data, (size_t)unpackSize) != folder->UnpackCRC) - return SZ_ERROR_CRC; - return SZ_OK; -} - -static SRes SzReadAndDecodePackedStreams( - ILookInStream *inStream, - CSzData *sd, - CBuf *outBuffer, - UInt64 baseOffset, - ISzAlloc *allocTemp) -{ - CSzAr p; - UInt64 *unpackSizes = 0; - Byte *digestsDefined = 0; - UInt32 *digests = 0; - SRes res; - SzAr_Init(&p); - res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset, - &p, &unpackSizes, &digestsDefined, &digests, - allocTemp); - SzAr_Free(&p, allocTemp); - IAlloc_Free(allocTemp, unpackSizes); - IAlloc_Free(allocTemp, digestsDefined); - IAlloc_Free(allocTemp, digests); - return res; -} - -static SRes SzArEx_Open2( - CSzArEx *p, - ILookInStream *inStream, - ISzAlloc *allocMain, - ISzAlloc *allocTemp) -{ - Byte header[k7zStartHeaderSize]; - Int64 startArcPos; - UInt64 nextHeaderOffset, nextHeaderSize; - size_t nextHeaderSizeT; - UInt32 nextHeaderCRC; - CBuf buffer; - SRes res; - - startArcPos = 0; - RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR)); - - RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)); - - if (!TestSignatureCandidate(header)) - return SZ_ERROR_NO_ARCHIVE; - if (header[6] != k7zMajorVersion) - return SZ_ERROR_UNSUPPORTED; - - nextHeaderOffset = GetUi64(header + 12); - nextHeaderSize = GetUi64(header + 20); - nextHeaderCRC = GetUi32(header + 28); - - p->startPosAfterHeader = startArcPos + k7zStartHeaderSize; - - if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) - return SZ_ERROR_CRC; - - nextHeaderSizeT = (size_t)nextHeaderSize; - if (nextHeaderSizeT != nextHeaderSize) - return SZ_ERROR_MEM; - if (nextHeaderSizeT == 0) - return SZ_OK; - if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize || - nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize) - return SZ_ERROR_NO_ARCHIVE; - - { - Int64 pos = 0; - RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END)); - if ((UInt64)pos < startArcPos + nextHeaderOffset || - (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset || - (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) - return SZ_ERROR_INPUT_EOF; - } - - RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset)); - - if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp)) - return SZ_ERROR_MEM; - - res = LookInStream_Read(inStream, buffer.data, nextHeaderSizeT); - if (res == SZ_OK) - { - res = SZ_ERROR_ARCHIVE; - if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC) - { - CSzData sd; - UInt64 type; - sd.Data = buffer.data; - sd.Size = buffer.size; - res = SzReadID(&sd, &type); - if (res == SZ_OK) - { - if (type == k7zIdEncodedHeader) - { - CBuf outBuffer; - Buf_Init(&outBuffer); - res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, p->startPosAfterHeader, allocTemp); - if (res != SZ_OK) - Buf_Free(&outBuffer, allocTemp); - else - { - Buf_Free(&buffer, allocTemp); - buffer.data = outBuffer.data; - buffer.size = outBuffer.size; - sd.Data = buffer.data; - sd.Size = buffer.size; - res = SzReadID(&sd, &type); - } - } - } - if (res == SZ_OK) - { - if (type == k7zIdHeader) - res = SzReadHeader(p, &sd, allocMain, allocTemp); - else - res = SZ_ERROR_UNSUPPORTED; - } - } - } - Buf_Free(&buffer, allocTemp); - return res; -} - -SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp) -{ - SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp); - if (res != SZ_OK) - SzArEx_Free(p, allocMain); - return res; -} - -SRes SzArEx_Extract( - const CSzArEx *p, - ILookInStream *inStream, - UInt32 fileIndex, - UInt32 *blockIndex, - Byte **outBuffer, - size_t *outBufferSize, - size_t *offset, - size_t *outSizeProcessed, - ISzAlloc *allocMain, - ISzAlloc *allocTemp) -{ - UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; - SRes res = SZ_OK; - *offset = 0; - *outSizeProcessed = 0; - if (folderIndex == (UInt32)-1) - { - IAlloc_Free(allocMain, *outBuffer); - *blockIndex = folderIndex; - *outBuffer = 0; - *outBufferSize = 0; - return SZ_OK; - } - - if (*outBuffer == 0 || *blockIndex != folderIndex) - { - CSzFolder *folder = p->db.Folders + folderIndex; - UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder); - size_t unpackSize = (size_t)unpackSizeSpec; - UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0); - - if (unpackSize != unpackSizeSpec) - return SZ_ERROR_MEM; - *blockIndex = folderIndex; - IAlloc_Free(allocMain, *outBuffer); - *outBuffer = 0; - - RINOK(LookInStream_SeekTo(inStream, startOffset)); - - if (res == SZ_OK) - { - *outBufferSize = unpackSize; - if (unpackSize != 0) - { - *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize); - if (*outBuffer == 0) - res = SZ_ERROR_MEM; - } - if (res == SZ_OK) - { - res = SzFolder_Decode(folder, - p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex], - inStream, startOffset, - *outBuffer, unpackSize, allocTemp); - if (res == SZ_OK) - { - if (folder->UnpackCRCDefined) - { - if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC) - res = SZ_ERROR_CRC; - } - } - } - } - } - if (res == SZ_OK) - { - UInt32 i; - CSzFileItem *fileItem = p->db.Files + fileIndex; - *offset = 0; - for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) - *offset += (UInt32)p->db.Files[i].Size; - *outSizeProcessed = (size_t)fileItem->Size; - if (*offset + *outSizeProcessed > *outBufferSize) - return SZ_ERROR_FAIL; - if (fileItem->CrcDefined && CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->Crc) - res = SZ_ERROR_CRC; - } - return res; -} diff --git a/src/libs/7zip/win/C/7zStream.c b/src/libs/7zip/win/C/7zStream.c index 0ebb7b5f9..88f9c42b1 100644 --- a/src/libs/7zip/win/C/7zStream.c +++ b/src/libs/7zip/win/C/7zStream.c @@ -1,9 +1,11 @@ /* 7zStream.c -- 7z Stream functions -2010-03-11 : Igor Pavlov : Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include -#include "Types.h" +#include "7zTypes.h" SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType) { diff --git a/src/libs/7zip/win/C/7zTypes.h b/src/libs/7zip/win/C/7zTypes.h new file mode 100644 index 000000000..778413ef4 --- /dev/null +++ b/src/libs/7zip/win/C/7zTypes.h @@ -0,0 +1,256 @@ +/* 7zTypes.h -- Basic types +2013-11-12 : Igor Pavlov : Public domain */ + +#ifndef __7Z_TYPES_H +#define __7Z_TYPES_H + +#ifdef _WIN32 +/* #include */ +#endif + +#include + +#ifndef EXTERN_C_BEGIN +#ifdef __cplusplus +#define EXTERN_C_BEGIN extern "C" { +#define EXTERN_C_END } +#else +#define EXTERN_C_BEGIN +#define EXTERN_C_END +#endif +#endif + +EXTERN_C_BEGIN + +#define SZ_OK 0 + +#define SZ_ERROR_DATA 1 +#define SZ_ERROR_MEM 2 +#define SZ_ERROR_CRC 3 +#define SZ_ERROR_UNSUPPORTED 4 +#define SZ_ERROR_PARAM 5 +#define SZ_ERROR_INPUT_EOF 6 +#define SZ_ERROR_OUTPUT_EOF 7 +#define SZ_ERROR_READ 8 +#define SZ_ERROR_WRITE 9 +#define SZ_ERROR_PROGRESS 10 +#define SZ_ERROR_FAIL 11 +#define SZ_ERROR_THREAD 12 + +#define SZ_ERROR_ARCHIVE 16 +#define SZ_ERROR_NO_ARCHIVE 17 + +typedef int SRes; + +#ifdef _WIN32 +/* typedef DWORD WRes; */ +typedef unsigned WRes; +#else +typedef int WRes; +#endif + +#ifndef RINOK +#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } +#endif + +typedef unsigned char Byte; +typedef short Int16; +typedef unsigned short UInt16; + +#ifdef _LZMA_UINT32_IS_ULONG +typedef long Int32; +typedef unsigned long UInt32; +#else +typedef int Int32; +typedef unsigned int UInt32; +#endif + +#ifdef _SZ_NO_INT_64 + +/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. + NOTES: Some code will work incorrectly in that case! */ + +typedef long Int64; +typedef unsigned long UInt64; + +#else + +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#define UINT64_CONST(n) n +#else +typedef long long int Int64; +typedef unsigned long long int UInt64; +#define UINT64_CONST(n) n ## ULL +#endif + +#endif + +#ifdef _LZMA_NO_SYSTEM_SIZE_T +typedef UInt32 SizeT; +#else +typedef size_t SizeT; +#endif + +typedef int Bool; +#define True 1 +#define False 0 + + +#ifdef _WIN32 +#define MY_STD_CALL __stdcall +#else +#define MY_STD_CALL +#endif + +#ifdef _MSC_VER + +#if _MSC_VER >= 1300 +#define MY_NO_INLINE __declspec(noinline) +#else +#define MY_NO_INLINE +#endif + +#define MY_CDECL __cdecl +#define MY_FAST_CALL __fastcall + +#else + +#define MY_NO_INLINE +#define MY_CDECL +#define MY_FAST_CALL + +#endif + + +/* The following interfaces use first parameter as pointer to structure */ + +typedef struct +{ + Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */ +} IByteIn; + +typedef struct +{ + void (*Write)(void *p, Byte b); +} IByteOut; + +typedef struct +{ + SRes (*Read)(void *p, void *buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) < input(*size)) is allowed */ +} ISeqInStream; + +/* it can return SZ_ERROR_INPUT_EOF */ +SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); +SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); +SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); + +typedef struct +{ + size_t (*Write)(void *p, const void *buf, size_t size); + /* Returns: result - the number of actually written bytes. + (result < size) means error */ +} ISeqOutStream; + +typedef enum +{ + SZ_SEEK_SET = 0, + SZ_SEEK_CUR = 1, + SZ_SEEK_END = 2 +} ESzSeek; + +typedef struct +{ + SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +} ISeekInStream; + +typedef struct +{ + SRes (*Look)(void *p, const void **buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) > input(*size)) is not allowed + (output(*size) < input(*size)) is allowed */ + SRes (*Skip)(void *p, size_t offset); + /* offset must be <= output(*size) of Look */ + + SRes (*Read)(void *p, void *buf, size_t *size); + /* reads directly (without buffer). It's same as ISeqInStream::Read */ + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +} ILookInStream; + +SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); +SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); + +/* reads via ILookInStream::Read */ +SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); +SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); + +#define LookToRead_BUF_SIZE (1 << 14) + +typedef struct +{ + ILookInStream s; + ISeekInStream *realStream; + size_t pos; + size_t size; + Byte buf[LookToRead_BUF_SIZE]; +} CLookToRead; + +void LookToRead_CreateVTable(CLookToRead *p, int lookahead); +void LookToRead_Init(CLookToRead *p); + +typedef struct +{ + ISeqInStream s; + ILookInStream *realStream; +} CSecToLook; + +void SecToLook_CreateVTable(CSecToLook *p); + +typedef struct +{ + ISeqInStream s; + ILookInStream *realStream; +} CSecToRead; + +void SecToRead_CreateVTable(CSecToRead *p); + +typedef struct +{ + SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); + /* Returns: result. (result != SZ_OK) means break. + Value (UInt64)(Int64)-1 for size means unknown value. */ +} ICompressProgress; + +typedef struct +{ + void *(*Alloc)(void *p, size_t size); + void (*Free)(void *p, void *address); /* address can be 0 */ +} ISzAlloc; + +#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) +#define IAlloc_Free(p, a) (p)->Free((p), a) + +#ifdef _WIN32 + +#define CHAR_PATH_SEPARATOR '\\' +#define WCHAR_PATH_SEPARATOR L'\\' +#define STRING_PATH_SEPARATOR "\\" +#define WSTRING_PATH_SEPARATOR L"\\" + +#else + +#define CHAR_PATH_SEPARATOR '/' +#define WCHAR_PATH_SEPARATOR L'/' +#define STRING_PATH_SEPARATOR "/" +#define WSTRING_PATH_SEPARATOR L"/" + +#endif + +EXTERN_C_END + +#endif diff --git a/src/libs/7zip/win/C/7zVersion.h b/src/libs/7zip/win/C/7zVersion.h index 9d99c5dff..475918352 100644 --- a/src/libs/7zip/win/C/7zVersion.h +++ b/src/libs/7zip/win/C/7zVersion.h @@ -1,7 +1,10 @@ #define MY_VER_MAJOR 9 -#define MY_VER_MINOR 20 -#define MY_VER_BUILD 0 -#define MY_VERSION "9.20" -#define MY_DATE "2010-11-18" +#define MY_VER_MINOR 38 +#define MY_VER_BUILD 00 +#define MY_VERSION "9.38 beta" +// #define MY_7ZIP_VERSION "9.38" +#define MY_DATE "2015-01-03" +#undef MY_COPYRIGHT +#undef MY_VERSION_COPYRIGHT_DATE #define MY_COPYRIGHT ": Igor Pavlov : Public domain" #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE diff --git a/src/libs/7zip/win/C/Alloc.c b/src/libs/7zip/win/C/Alloc.c index 358a7b526..1f3f6c661 100644 --- a/src/libs/7zip/win/C/Alloc.c +++ b/src/libs/7zip/win/C/Alloc.c @@ -1,7 +1,7 @@ /* Alloc.c -- Memory allocation functions -2008-09-24 -Igor Pavlov -Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #ifdef _WIN32 #include @@ -99,7 +99,7 @@ void *BigAlloc(size_t size) #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); #endif - + #ifdef _7ZIP_LARGE_PAGES if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18)) { @@ -118,7 +118,7 @@ void BigFree(void *address) if (address != 0) fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); #endif - + if (address == 0) return; VirtualFree(address, 0, MEM_RELEASE); diff --git a/src/libs/7zip/win/C/Bcj2.c b/src/libs/7zip/win/C/Bcj2.c deleted file mode 100644 index 20199ce56..000000000 --- a/src/libs/7zip/win/C/Bcj2.c +++ /dev/null @@ -1,132 +0,0 @@ -/* Bcj2.c -- Converter for x86 code (BCJ2) -2008-10-04 : Igor Pavlov : Public domain */ - -#include "Bcj2.h" - -#ifdef _LZMA_PROB32 -#define CProb UInt32 -#else -#define CProb UInt16 -#endif - -#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80) -#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)) - -#define kNumTopBits 24 -#define kTopValue ((UInt32)1 << kNumTopBits) - -#define kNumBitModelTotalBits 11 -#define kBitModelTotal (1 << kNumBitModelTotalBits) -#define kNumMoveBits 5 - -#define RC_READ_BYTE (*buffer++) -#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; } -#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \ - { int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }} - -#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; } - -#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) -#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE; -#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE; - -int Bcj2_Decode( - const Byte *buf0, SizeT size0, - const Byte *buf1, SizeT size1, - const Byte *buf2, SizeT size2, - const Byte *buf3, SizeT size3, - Byte *outBuf, SizeT outSize) -{ - CProb p[256 + 2]; - SizeT inPos = 0, outPos = 0; - - const Byte *buffer, *bufferLim; - UInt32 range, code; - Byte prevByte = 0; - - unsigned int i; - for (i = 0; i < sizeof(p) / sizeof(p[0]); i++) - p[i] = kBitModelTotal >> 1; - - buffer = buf3; - bufferLim = buffer + size3; - RC_INIT2 - - if (outSize == 0) - return SZ_OK; - - for (;;) - { - Byte b; - CProb *prob; - UInt32 bound; - UInt32 ttt; - - SizeT limit = size0 - inPos; - if (outSize - outPos < limit) - limit = outSize - outPos; - while (limit != 0) - { - Byte b = buf0[inPos]; - outBuf[outPos++] = b; - if (IsJ(prevByte, b)) - break; - inPos++; - prevByte = b; - limit--; - } - - if (limit == 0 || outPos == outSize) - break; - - b = buf0[inPos++]; - - if (b == 0xE8) - prob = p + prevByte; - else if (b == 0xE9) - prob = p + 256; - else - prob = p + 257; - - IF_BIT_0(prob) - { - UPDATE_0(prob) - prevByte = b; - } - else - { - UInt32 dest; - const Byte *v; - UPDATE_1(prob) - if (b == 0xE8) - { - v = buf1; - if (size1 < 4) - return SZ_ERROR_DATA; - buf1 += 4; - size1 -= 4; - } - else - { - v = buf2; - if (size2 < 4) - return SZ_ERROR_DATA; - buf2 += 4; - size2 -= 4; - } - dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) | - ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4); - outBuf[outPos++] = (Byte)dest; - if (outPos == outSize) - break; - outBuf[outPos++] = (Byte)(dest >> 8); - if (outPos == outSize) - break; - outBuf[outPos++] = (Byte)(dest >> 16); - if (outPos == outSize) - break; - outBuf[outPos++] = prevByte = (Byte)(dest >> 24); - } - } - return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA; -} diff --git a/src/libs/7zip/win/C/Bcj2.h b/src/libs/7zip/win/C/Bcj2.h deleted file mode 100644 index dbc054148..000000000 --- a/src/libs/7zip/win/C/Bcj2.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Bcj2.h -- Converter for x86 code (BCJ2) -2009-02-07 : Igor Pavlov : Public domain */ - -#ifndef __BCJ2_H -#define __BCJ2_H - -#include "Types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* -Conditions: - outSize <= FullOutputSize, - where FullOutputSize is full size of output stream of x86_2 filter. - -If buf0 overlaps outBuf, there are two required conditions: - 1) (buf0 >= outBuf) - 2) (buf0 + size0 >= outBuf + FullOutputSize). - -Returns: - SZ_OK - SZ_ERROR_DATA - Data error -*/ - -int Bcj2_Decode( - const Byte *buf0, SizeT size0, - const Byte *buf1, SizeT size1, - const Byte *buf2, SizeT size2, - const Byte *buf3, SizeT size3, - Byte *outBuf, SizeT outSize); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/libs/7zip/win/C/Bra.c b/src/libs/7zip/win/C/Bra.c index 2e47b1413..33f7a391c 100644 --- a/src/libs/7zip/win/C/Bra.c +++ b/src/libs/7zip/win/C/Bra.c @@ -1,6 +1,8 @@ /* Bra.c -- Converters for RISC code 2010-04-16 : Igor Pavlov : Public domain */ +#include "Precomp.h" + #include "Bra.h" SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) @@ -48,14 +50,14 @@ SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) ((UInt32)data[i + 0] << 11) | (((UInt32)data[i + 3] & 0x7) << 8) | (data[i + 2]); - + src <<= 1; if (encoding) dest = ip + (UInt32)i + src; else dest = src - (ip + (UInt32)i); dest >>= 1; - + data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7)); data[i + 0] = (Byte)(dest >> 11); data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7)); @@ -80,7 +82,7 @@ SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) ((UInt32)data[i + 1] << 16) | ((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 3] & (~3)); - + UInt32 dest; if (encoding) dest = ip + (UInt32)i + src; @@ -113,14 +115,14 @@ SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) ((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 3]); UInt32 dest; - + src <<= 2; if (encoding) dest = ip + i + src; else dest = src - (ip + i); dest >>= 2; - + dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; data[i + 0] = (Byte)(dest >> 24); diff --git a/src/libs/7zip/win/C/Bra.h b/src/libs/7zip/win/C/Bra.h index 5748c1c05..184c291a7 100644 --- a/src/libs/7zip/win/C/Bra.h +++ b/src/libs/7zip/win/C/Bra.h @@ -1,35 +1,33 @@ /* Bra.h -- Branch converters for executables -2009-02-07 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __BRA_H #define __BRA_H -#include "Types.h" +#include "7zTypes.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN /* These functions convert relative addresses to absolute addresses in CALL instructions to increase the compression ratio. - + In: data - data buffer size - size of data ip - current virtual Instruction Pinter (IP) value state - state variable for x86 converter encoding - 0 (for decoding), 1 (for encoding) - + Out: state - state variable for x86 converter Returns: The number of processed bytes. If you call these functions with multiple calls, you must start next call with first byte after block of processed bytes. - + Type Endian Alignment LookAhead - + x86 little 1 4 ARMT little 2 2 ARM little 4 0 @@ -61,8 +59,6 @@ SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); -#ifdef __cplusplus -} -#endif +EXTERN_C_END #endif diff --git a/src/libs/7zip/win/C/Bra86.c b/src/libs/7zip/win/C/Bra86.c index 1ee0e709b..6db15e7ec 100644 --- a/src/libs/7zip/win/C/Bra86.c +++ b/src/libs/7zip/win/C/Bra86.c @@ -1,85 +1,82 @@ /* Bra86.c -- Converter for x86 code (BCJ) -2008-10-04 : Igor Pavlov : Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ -#include "Bra.h" +#include "Precomp.h" -#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) +#include "Bra.h" -const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; -const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; +#define Test86MSByte(b) ((((b) + 1) & 0xFE) == 0) SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) { - SizeT bufferPos = 0, prevPosT; - UInt32 prevMask = *state & 0x7; + SizeT pos = 0; + UInt32 mask = *state & 7; if (size < 5) return 0; + size -= 4; ip += 5; - prevPosT = (SizeT)0 - 1; for (;;) { - Byte *p = data + bufferPos; - Byte *limit = data + size - 4; + Byte *p = data + pos; + const Byte *limit = data + size; for (; p < limit; p++) if ((*p & 0xFE) == 0xE8) break; - bufferPos = (SizeT)(p - data); - if (p >= limit) - break; - prevPosT = bufferPos - prevPosT; - if (prevPosT > 3) - prevMask = 0; - else + { - prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7; - if (prevMask != 0) + SizeT d = (SizeT)(p - data - pos); + pos = (SizeT)(p - data); + if (p >= limit) { - Byte b = p[4 - kMaskToBitNumber[prevMask]]; - if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b)) + *state = (d > 2 ? 0 : mask >> (unsigned)d); + return pos; + } + if (d > 2) + mask = 0; + else + { + mask >>= (unsigned)d; + if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(mask >> 1) + 1]))) { - prevPosT = bufferPos; - prevMask = ((prevMask << 1) & 0x7) | 1; - bufferPos++; + mask = (mask >> 1) | 4; + pos++; continue; } } } - prevPosT = bufferPos; if (Test86MSByte(p[4])) { - UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); - UInt32 dest; - for (;;) + UInt32 v = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); + UInt32 cur = ip + (UInt32)pos; + pos += 5; + if (encoding) + v += cur; + else + v -= cur; + if (mask != 0) { - Byte b; - int index; - if (encoding) - dest = (ip + (UInt32)bufferPos) + src; - else - dest = src - (ip + (UInt32)bufferPos); - if (prevMask == 0) - break; - index = kMaskToBitNumber[prevMask] * 8; - b = (Byte)(dest >> (24 - index)); - if (!Test86MSByte(b)) - break; - src = dest ^ ((1 << (32 - index)) - 1); + unsigned sh = (mask & 6) << 2; + if (Test86MSByte((Byte)(v >> sh))) + { + v ^= (((UInt32)0x100 << sh) - 1); + if (encoding) + v += cur; + else + v -= cur; + } + mask = 0; } - p[4] = (Byte)(~(((dest >> 24) & 1) - 1)); - p[3] = (Byte)(dest >> 16); - p[2] = (Byte)(dest >> 8); - p[1] = (Byte)dest; - bufferPos += 5; + p[1] = (Byte)v; + p[2] = (Byte)(v >> 8); + p[3] = (Byte)(v >> 16); + p[4] = (Byte)(0 - ((v >> 24) & 1)); } else { - prevMask = ((prevMask << 1) & 0x7) | 1; - bufferPos++; + mask = (mask >> 1) | 4; + pos++; } } - prevPosT = bufferPos - prevPosT; - *state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7)); - return bufferPos; } diff --git a/src/libs/7zip/win/C/BraIA64.c b/src/libs/7zip/win/C/BraIA64.c index 0b4ee85bc..aa1a44e1e 100644 --- a/src/libs/7zip/win/C/BraIA64.c +++ b/src/libs/7zip/win/C/BraIA64.c @@ -1,5 +1,7 @@ /* BraIA64.c -- Converter for IA-64 code -2008-10-04 : Igor Pavlov : Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include "Bra.h" @@ -42,20 +44,20 @@ SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF); UInt32 dest; src |= ((UInt32)(instNorm >> 36) & 1) << 20; - + src <<= 4; - + if (encoding) dest = ip + (UInt32)i + src; else dest = src - (ip + (UInt32)i); - + dest >>= 4; - + instNorm &= ~((UInt64)(0x8FFFFF) << 13); instNorm |= ((UInt64)(dest & 0xFFFFF) << 13); instNorm |= ((UInt64)(dest & 0x100000) << (36 - 20)); - + instruction &= (1 << bitRes) - 1; instruction |= (instNorm << bitRes); for (j = 0; j < 6; j++) diff --git a/src/libs/7zip/win/C/C.pri b/src/libs/7zip/win/C/C.pri new file mode 100644 index 000000000..23d688642 --- /dev/null +++ b/src/libs/7zip/win/C/C.pri @@ -0,0 +1,48 @@ +HEADERS += $$7ZIP_BASE/C/7zCrc.h \ + $$7ZIP_BASE/C/7zTypes.h \ + $$7ZIP_BASE/C/7zVersion.h \ + $$7ZIP_BASE/C/Alloc.h \ + $$7ZIP_BASE/C/Bra.h \ + $$7ZIP_BASE/C/Compiler.h \ + $$7ZIP_BASE/C/CpuArch.h \ + $$7ZIP_BASE/C/Delta.h \ + $$7ZIP_BASE/C/LzFind.h \ + $$7ZIP_BASE/C/LzFindMt.h \ + $$7ZIP_BASE/C/LzHash.h \ + $$7ZIP_BASE/C/Lzma2Dec.h \ + $$7ZIP_BASE/C/Lzma2Enc.h \ + $$7ZIP_BASE/C/LzmaDec.h \ + $$7ZIP_BASE/C/LzmaEnc.h \ + $$7ZIP_BASE/C/MtCoder.h \ + $$7ZIP_BASE/C/Precomp.h \ + $$7ZIP_BASE/C/RotateDefs.h \ + $$7ZIP_BASE/C/Sha256.h \ + $$7ZIP_BASE/C/Threads.h \ + $$7ZIP_BASE/C/Xz.h \ + $$7ZIP_BASE/C/XzCrc64.h \ + $$7ZIP_BASE/C/XzEnc.h + +SOURCES += $$7ZIP_BASE/C/7zCrc.c \ + $$7ZIP_BASE/C/7zCrcOpt.c \ + $$7ZIP_BASE/C/7zStream.c \ + $$7ZIP_BASE/C/Alloc.c \ + $$7ZIP_BASE/C/Bra.c \ + $$7ZIP_BASE/C/Bra86.c \ + $$7ZIP_BASE/C/BraIA64.c \ + $$7ZIP_BASE/C/CpuArch.c \ + $$7ZIP_BASE/C/Delta.c \ + $$7ZIP_BASE/C/LzFind.c \ + $$7ZIP_BASE/C/LzFindMt.c \ + $$7ZIP_BASE/C/Lzma2Dec.c \ + $$7ZIP_BASE/C/Lzma2Enc.c \ + $$7ZIP_BASE/C/LzmaDec.c \ + $$7ZIP_BASE/C/LzmaEnc.c \ + $$7ZIP_BASE/C/MtCoder.c \ + $$7ZIP_BASE/C/Sha256.c \ + $$7ZIP_BASE/C/Threads.c \ + $$7ZIP_BASE/C/Xz.c \ + $$7ZIP_BASE/C/XzCrc64.c \ + $$7ZIP_BASE/C/XzCrc64Opt.c \ + $$7ZIP_BASE/C/XzDec.c \ + $$7ZIP_BASE/C/XzEnc.c \ + $$7ZIP_BASE/C/XzIn.c diff --git a/src/libs/7zip/win/C/Compiler.h b/src/libs/7zip/win/C/Compiler.h new file mode 100644 index 000000000..6e964897e --- /dev/null +++ b/src/libs/7zip/win/C/Compiler.h @@ -0,0 +1,28 @@ +/* Compiler.h -- Compiler ypes +2013-11-12 : Igor Pavlov : Public domain */ + +#ifndef __7Z_COMPILER_H +#define __7Z_COMPILER_H + +#ifdef _MSC_VER + + #ifdef UNDER_CE + #define RPC_NO_WINDOWS_H + /* #pragma warning(disable : 4115) // '_RPC_ASYNC_STATE' : named type definition in parentheses */ + #pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union + #pragma warning(disable : 4214) // nonstandard extension used : bit field types other than int + #endif + + #if _MSC_VER >= 1300 + #pragma warning(disable : 4996) // This function or variable may be unsafe + #else + #pragma warning(disable : 4511) // copy constructor could not be generated + #pragma warning(disable : 4512) // assignment operator could not be generated + #pragma warning(disable : 4702) // unreachable code + #pragma warning(disable : 4710) // not inlined + #pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information + #endif + +#endif + +#endif diff --git a/src/libs/7zip/win/C/CpuArch.c b/src/libs/7zip/win/C/CpuArch.c index 260cc1f45..4feb028a2 100644 --- a/src/libs/7zip/win/C/CpuArch.c +++ b/src/libs/7zip/win/C/CpuArch.c @@ -1,5 +1,7 @@ /* CpuArch.c -- CPU specific code -2010-10-26: Igor Pavlov : Public domain */ +2012-05-29: Igor Pavlov : Public domain */ + +#include "Precomp.h" #include "CpuArch.h" @@ -9,6 +11,10 @@ #define USE_ASM #endif +#if !defined(USE_ASM) && _MSC_VER >= 1500 +#include +#endif + #if defined(USE_ASM) && !defined(MY_CPU_AMD64) static UInt32 CheckFlag(UInt32 flag) { @@ -73,15 +79,23 @@ static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) #else __asm__ __volatile__ ( + #if defined(MY_CPU_X86) && defined(__PIC__) + "mov %%ebx, %%edi;" + "cpuid;" + "xchgl %%ebx, %%edi;" + : "=a" (*a) , + "=D" (*b) , + #else "cpuid" : "=a" (*a) , "=b" (*b) , + #endif "=c" (*c) , "=d" (*d) : "0" (function)) ; #endif - + #else int CPUInfo[4]; @@ -135,7 +149,14 @@ Bool CPU_Is_InOrder() firm = x86cpuid_GetFirm(&p); switch (firm) { - case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C)); + case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && ( + /* Atom CPU */ + model == 0x100C /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */ + || model == 0x2006 /* 45 nm, Z6xx */ + || model == 0x2007 /* 32 nm, Z2460 */ + || model == 0x3005 /* 32 nm, Z2760 */ + || model == 0x3006 /* 32 nm, N2xxx, D2xxx */ + ))); case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA))); case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF)); } @@ -143,6 +164,7 @@ Bool CPU_Is_InOrder() } #if !defined(MY_CPU_AMD64) && defined(_WIN32) +#include static Bool CPU_Sys_Is_SSE_Supported() { OSVERSIONINFO vi; diff --git a/src/libs/7zip/win/C/CpuArch.h b/src/libs/7zip/win/C/CpuArch.h index 01930c7e6..4fee00937 100644 --- a/src/libs/7zip/win/C/CpuArch.h +++ b/src/libs/7zip/win/C/CpuArch.h @@ -1,10 +1,10 @@ /* CpuArch.h -- CPU specific code -2010-10-26: Igor Pavlov : Public domain */ +2013-11-12: Igor Pavlov : Public domain */ #ifndef __CPU_ARCH_H #define __CPU_ARCH_H -#include "Types.h" +#include "7zTypes.h" EXTERN_C_BEGIN @@ -52,7 +52,7 @@ If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of pla #define MY_CPU_LE #endif -#if defined(__BIG_ENDIAN__) +#if defined(__BIG_ENDIAN__) || defined(__m68k__) || defined(__ARMEB__) || defined(__MIPSEB__) #define MY_CPU_BE #endif @@ -62,9 +62,9 @@ Stop_Compiling_Bad_Endian #ifdef MY_CPU_LE_UNALIGN -#define GetUi16(p) (*(const UInt16 *)(p)) -#define GetUi32(p) (*(const UInt32 *)(p)) -#define GetUi64(p) (*(const UInt64 *)(p)) +#define GetUi16(p) (*(const UInt16 *)(const void *)(p)) +#define GetUi32(p) (*(const UInt32 *)(const void *)(p)) +#define GetUi64(p) (*(const UInt64 *)(const void *)(p)) #define SetUi16(p, d) *(UInt16 *)(p) = (d); #define SetUi32(p, d) *(UInt32 *)(p) = (d); #define SetUi64(p, d) *(UInt64 *)(p) = (d); @@ -99,6 +99,8 @@ Stop_Compiling_Bad_Endian #if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) +#include + #pragma intrinsic(_byteswap_ulong) #pragma intrinsic(_byteswap_uint64) #define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) @@ -116,7 +118,7 @@ Stop_Compiling_Bad_Endian #endif -#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]) +#define GetBe16(p) ((UInt16)(((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1])) #ifdef MY_CPU_X86_OR_AMD64 diff --git a/src/libs/7zip/win/C/Delta.c b/src/libs/7zip/win/C/Delta.c index 2b327f15f..e3edd21ed 100644 --- a/src/libs/7zip/win/C/Delta.c +++ b/src/libs/7zip/win/C/Delta.c @@ -1,6 +1,8 @@ /* Delta.c -- Delta converter 2009-05-26 : Igor Pavlov : Public domain */ +#include "Precomp.h" + #include "Delta.h" void Delta_Init(Byte *state) diff --git a/src/libs/7zip/win/C/Delta.h b/src/libs/7zip/win/C/Delta.h index 0d4cd6274..2fa54ad67 100644 --- a/src/libs/7zip/win/C/Delta.h +++ b/src/libs/7zip/win/C/Delta.h @@ -1,14 +1,12 @@ /* Delta.h -- Delta converter -2009-04-15 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __DELTA_H #define __DELTA_H -#include "Types.h" +#include "7zTypes.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN #define DELTA_STATE_SIZE 256 @@ -16,8 +14,6 @@ void Delta_Init(Byte *state); void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size); void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size); -#ifdef __cplusplus -} -#endif +EXTERN_C_END #endif diff --git a/src/libs/7zip/win/C/LzFind.c b/src/libs/7zip/win/C/LzFind.c index e3ecb0542..9a4d25b80 100644 --- a/src/libs/7zip/win/C/LzFind.c +++ b/src/libs/7zip/win/C/LzFind.c @@ -1,6 +1,8 @@ /* LzFind.c -- Match finder for LZ algorithms 2009-04-22 : Igor Pavlov : Public domain */ +#include "Precomp.h" + #include #include "LzFind.h" @@ -512,7 +514,7 @@ static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) delta2 = p->pos - p->hash[hash2Value]; curMatch = p->hash[kFix3HashSize + hashValue]; - + p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos; @@ -546,7 +548,7 @@ static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) delta2 = p->pos - p->hash[ hash2Value]; delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; curMatch = p->hash[kFix4HashSize + hashValue]; - + p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; diff --git a/src/libs/7zip/win/C/LzFind.h b/src/libs/7zip/win/C/LzFind.h index 010c4b92b..706143d25 100644 --- a/src/libs/7zip/win/C/LzFind.h +++ b/src/libs/7zip/win/C/LzFind.h @@ -1,14 +1,12 @@ /* LzFind.h -- Match finder for LZ algorithms -2009-04-22 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __LZ_FIND_H #define __LZ_FIND_H -#include "Types.h" +#include "7zTypes.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN typedef UInt32 CLzRef; @@ -108,8 +106,6 @@ UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); -#ifdef __cplusplus -} -#endif +EXTERN_C_END #endif diff --git a/src/libs/7zip/win/C/LzFindMt.c b/src/libs/7zip/win/C/LzFindMt.c index aa41ed98a..8be0adaaf 100644 --- a/src/libs/7zip/win/C/LzFindMt.c +++ b/src/libs/7zip/win/C/LzFindMt.c @@ -1,5 +1,7 @@ /* LzFindMt.c -- multithreaded Match finder for LZ algorithms -2009-09-20 : Igor Pavlov : Public domain */ +2014-12-29 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include "LzHash.h" @@ -58,7 +60,7 @@ void MtSync_StopWriting(CMtSync *p) p->csWasEntered = False; } Semaphore_Release1(&p->freeSemaphore); - + Event_Wait(&p->wasStopped); while (myNumBlocks++ != p->numProcessedBlocks) @@ -97,7 +99,7 @@ void MtSync_Destruct(CMtSync *p) #define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } -static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks) +static SRes MtSync_Create2(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks) { if (p->wasCreated) return SZ_OK; @@ -108,18 +110,18 @@ static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart)); RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStarted)); RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped)); - + RINOK_THREAD(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks)); RINOK_THREAD(Semaphore_Create(&p->filledSemaphore, 0, numBlocks)); p->needStart = True; - + RINOK_THREAD(Thread_Create(&p->thread, startAddress, obj)); p->wasCreated = True; return SZ_OK; } -static SRes MtSync_Create(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks) +static SRes MtSync_Create(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks) { SRes res = MtSync_Create2(p, startAddress, obj, numBlocks); if (res != SZ_OK) @@ -385,7 +387,7 @@ void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex) CriticalSection_Enter(&sync->cs); sync->csWasEntered = True; } - + BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize); if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize) @@ -451,13 +453,12 @@ void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc) #define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks) #define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks) -static unsigned MY_STD_CALL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } -static unsigned MY_STD_CALL BtThreadFunc2(void *p) +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p) { Byte allocaDummy[0x180]; - int i = 0; - for (i = 0; i < 16; i++) - allocaDummy[i] = (Byte)i; + allocaDummy[0] = 0; + allocaDummy[1] = allocaDummy[0]; BtThreadFunc((CMatchFinderMt *)p); return 0; } @@ -561,7 +562,7 @@ UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH2_CALC - + curMatch2 = hash[hash2Value]; hash[hash2Value] = lzPos; @@ -584,7 +585,7 @@ UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) curMatch2 = hash[ hash2Value]; curMatch3 = hash[kFix3HashSize + hash3Value]; - + hash[ hash2Value] = hash[kFix3HashSize + hash3Value] = lzPos; @@ -616,11 +617,11 @@ UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH4_CALC - + curMatch2 = hash[ hash2Value]; curMatch3 = hash[kFix3HashSize + hash3Value]; curMatch4 = hash[kFix4HashSize + hash4Value]; - + hash[ hash2Value] = hash[kFix3HashSize + hash3Value] = hash[kFix4HashSize + hash4Value] = diff --git a/src/libs/7zip/win/C/LzFindMt.h b/src/libs/7zip/win/C/LzFindMt.h index b985af5fe..65cc12783 100644 --- a/src/libs/7zip/win/C/LzFindMt.h +++ b/src/libs/7zip/win/C/LzFindMt.h @@ -1,5 +1,5 @@ /* LzFindMt.h -- multithreaded Match finder for LZ algorithms -2009-02-07 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __LZ_FIND_MT_H #define __LZ_FIND_MT_H @@ -7,9 +7,7 @@ #include "LzFind.h" #include "Threads.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN #define kMtHashBlockSize (1 << 13) #define kMtHashNumBlocks (1 << 3) @@ -62,7 +60,7 @@ typedef struct _CMatchFinderMt const UInt32 *crc; Mf_Mix_Matches MixMatchesFunc; - + /* LZ + BT */ CMtSync btSync; Byte btDummy[kMtCacheLineDummy]; @@ -85,7 +83,7 @@ typedef struct _CMatchFinderMt /* BT + Hash */ CMtSync hashSync; /* Byte hashDummy[kMtCacheLineDummy]; */ - + /* Hash */ Mf_GetHeads GetHeadsFunc; CMatchFinder *MatchFinder; @@ -98,8 +96,6 @@ SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddB void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); -#ifdef __cplusplus -} -#endif +EXTERN_C_END #endif diff --git a/src/libs/7zip/win/C/Lzma2Dec.c b/src/libs/7zip/win/C/Lzma2Dec.c index 7ea1cc953..e7dcc2725 100644 --- a/src/libs/7zip/win/C/Lzma2Dec.c +++ b/src/libs/7zip/win/C/Lzma2Dec.c @@ -1,8 +1,10 @@ /* Lzma2Dec.c -- LZMA2 Decoder -2009-05-03 : Igor Pavlov : Public domain */ +2010-12-15 : Igor Pavlov : Public domain */ /* #define SHOW_DEBUG_INFO */ +#include "Precomp.h" + #ifdef SHOW_DEBUG_INFO #include #endif @@ -114,17 +116,17 @@ static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b) else p->unpackSize = (UInt32)(p->control & 0x1F) << 16; return LZMA2_STATE_UNPACK0; - + case LZMA2_STATE_UNPACK0: p->unpackSize |= (UInt32)b << 8; return LZMA2_STATE_UNPACK1; - + case LZMA2_STATE_UNPACK1: p->unpackSize |= (UInt32)b; p->unpackSize++; PRF(printf(" %8d", p->unpackSize)); return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0; - + case LZMA2_STATE_PACK0: p->packSize = (UInt32)b << 8; return LZMA2_STATE_PACK1; @@ -199,7 +201,7 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, SizeT destSizeCur = dicLimit - dicPos; SizeT srcSizeCur = inSize - *srcLen; ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY; - + if (p->unpackSize <= destSizeCur) { destSizeCur = (SizeT)p->unpackSize; @@ -250,7 +252,7 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, Bool initState = (mode > 0); if ((!initDic && p->needInitDic) || (!initState && p->needInitState)) return SZ_ERROR_DATA; - + LzmaDec_InitDicAndState(&p->decoder, initDic, initState); p->needInitDic = False; p->needInitState = False; @@ -258,9 +260,9 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, } if (srcSizeCur > p->packSize) srcSizeCur = (SizeT)p->packSize; - + res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status); - + src += srcSizeCur; *srcLen += srcSizeCur; p->packSize -= (UInt32)srcSizeCur; @@ -330,27 +332,21 @@ SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte * SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc) { - CLzma2Dec decoder; + CLzma2Dec p; SRes res; SizeT outSize = *destLen, inSize = *srcLen; - Byte props[LZMA_PROPS_SIZE]; - - Lzma2Dec_Construct(&decoder); - *destLen = *srcLen = 0; *status = LZMA_STATUS_NOT_SPECIFIED; - decoder.decoder.dic = dest; - decoder.decoder.dicBufSize = outSize; - - RINOK(Lzma2Dec_GetOldProps(prop, props)); - RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc)); - + Lzma2Dec_Construct(&p); + RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc)); + p.decoder.dic = dest; + p.decoder.dicBufSize = outSize; + Lzma2Dec_Init(&p); *srcLen = inSize; - res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status); - *destLen = decoder.decoder.dicPos; + res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); + *destLen = p.decoder.dicPos; if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) res = SZ_ERROR_INPUT_EOF; - - LzmaDec_FreeProbs(&decoder.decoder, alloc); + Lzma2Dec_FreeProbs(&p, alloc); return res; } diff --git a/src/libs/7zip/win/C/Lzma2Dec.h b/src/libs/7zip/win/C/Lzma2Dec.h index 6bc07bbc1..367daf6b3 100644 --- a/src/libs/7zip/win/C/Lzma2Dec.h +++ b/src/libs/7zip/win/C/Lzma2Dec.h @@ -1,14 +1,12 @@ /* Lzma2Dec.h -- LZMA2 Decoder -2009-05-03 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __LZMA2_DEC_H #define __LZMA2_DEC_H #include "LzmaDec.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN /* ---------- State Interface ---------- */ @@ -77,8 +75,6 @@ Returns: SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); -#ifdef __cplusplus -} -#endif +EXTERN_C_END #endif diff --git a/src/libs/7zip/win/C/Lzma2Enc.c b/src/libs/7zip/win/C/Lzma2Enc.c index e97597f63..5d67cc344 100644 --- a/src/libs/7zip/win/C/Lzma2Enc.c +++ b/src/libs/7zip/win/C/Lzma2Enc.c @@ -1,5 +1,7 @@ /* Lzma2Enc.c -- LZMA2 Encoder -2010-09-24 : Igor Pavlov : Public domain */ +2012-06-19 : Igor Pavlov : Public domain */ + +#include "Precomp.h" /* #include */ #include @@ -83,11 +85,11 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf, if (packSize < lzHeaderSize) return SZ_ERROR_OUTPUT_EOF; packSize -= lzHeaderSize; - + LzmaEnc_SaveState(p->enc); res = LzmaEnc_CodeOneMemBlock(p->enc, p->needInitState, outBuf + lzHeaderSize, &packSize, LZMA2_PACK_SIZE_MAX, &unpackSize); - + PRF(printf("\npackSize = %7d unpackSize = %7d ", packSize, unpackSize)); if (unpackSize == 0) @@ -146,10 +148,10 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf, outBuf[destPos++] = (Byte)u; outBuf[destPos++] = (Byte)(pm >> 8); outBuf[destPos++] = (Byte)pm; - + if (p->needInitProp) outBuf[destPos++] = p->props; - + p->needInitProp = False; p->needInitState = False; destPos += packSize; @@ -216,8 +218,7 @@ void Lzma2EncProps_Normalize(CLzma2EncProps *p) t3 = t1n * t2; p->lzmaProps.numThreads = t1; - p->numBlockThreads = t2; - p->numTotalThreads = t3; + LzmaEncProps_Normalize(&p->lzmaProps); if (p->blockSize == 0) @@ -231,6 +232,21 @@ void Lzma2EncProps_Normalize(CLzma2EncProps *p) if (blockSize < dictSize) blockSize = dictSize; p->blockSize = (size_t)blockSize; } + if (t2 > 1) + { + UInt64 temp = p->lzmaProps.reduceSize + p->blockSize - 1; + if (temp > p->lzmaProps.reduceSize) + { + UInt64 numBlocks = temp / p->blockSize; + if (numBlocks < t2) + { + t2 = (UInt32)numBlocks; + t3 = t1 * t2; + } + } + } + p->numBlockThreads = t2; + p->numTotalThreads = t3; } static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize) @@ -244,7 +260,7 @@ typedef struct { Byte propEncoded; CLzma2EncProps props; - + Byte *outBuf; ISzAlloc *alloc; @@ -322,10 +338,10 @@ static SRes MtCallbackImp_Code(void *pp, unsigned index, Byte *dest, size_t *des if (srcSize != 0) { RINOK(Lzma2EncInt_Init(p, &mainEncoder->props)); - + RINOK(LzmaEnc_MemPrepare(p->enc, src, srcSize, LZMA2_KEEP_WINDOW_SIZE, mainEncoder->alloc, mainEncoder->allocBig)); - + while (p->srcPos < srcSize) { size_t packSize = destLim - *destSize; @@ -460,7 +476,7 @@ SRes Lzma2Enc_Encode(CLzma2EncHandle pp, mtCallback.funcTable.Code = MtCallbackImp_Code; mtCallback.lzma2Enc = p; - + p->mtCoder.progress = progress; p->mtCoder.inStream = inStream; p->mtCoder.outStream = outStream; @@ -470,7 +486,7 @@ SRes Lzma2Enc_Encode(CLzma2EncHandle pp, p->mtCoder.blockSize = p->props.blockSize; p->mtCoder.destBlockSize = p->props.blockSize + (p->props.blockSize >> 10) + 16; p->mtCoder.numThreads = p->props.numBlockThreads; - + return MtCoder_Code(&p->mtCoder); } #endif diff --git a/src/libs/7zip/win/C/Lzma2Enc.h b/src/libs/7zip/win/C/Lzma2Enc.h index 283525581..f409f184c 100644 --- a/src/libs/7zip/win/C/Lzma2Enc.h +++ b/src/libs/7zip/win/C/Lzma2Enc.h @@ -1,14 +1,12 @@ /* Lzma2Enc.h -- LZMA2 Encoder -2009-02-07 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __LZMA2_ENC_H #define __LZMA2_ENC_H #include "LzmaEnc.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN typedef struct { @@ -59,8 +57,6 @@ SRes Lzma2Encode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); */ -#ifdef __cplusplus -} -#endif +EXTERN_C_END #endif diff --git a/src/libs/7zip/win/C/Lzma86.h b/src/libs/7zip/win/C/Lzma86.h deleted file mode 100644 index 6acbd888a..000000000 --- a/src/libs/7zip/win/C/Lzma86.h +++ /dev/null @@ -1,111 +0,0 @@ -/* Lzma86.h -- LZMA + x86 (BCJ) Filter -2009-08-14 : Igor Pavlov : Public domain */ - -#ifndef __LZMA86_H -#define __LZMA86_H - -#include "Types.h" - -EXTERN_C_BEGIN - -#define LZMA86_SIZE_OFFSET (1 + 5) -#define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8) - -/* -It's an example for LZMA + x86 Filter use. -You can use .lzma86 extension, if you write that stream to file. -.lzma86 header adds one additional byte to standard .lzma header. -.lzma86 header (14 bytes): - Offset Size Description - 0 1 = 0 - no filter, pure LZMA - = 1 - x86 filter + LZMA - 1 1 lc, lp and pb in encoded form - 2 4 dictSize (little endian) - 6 8 uncompressed size (little endian) - - -Lzma86_Encode -------------- -level - compression level: 0 <= level <= 9, the default value for "level" is 5. - -dictSize - The dictionary size in bytes. The maximum value is - 128 MB = (1 << 27) bytes for 32-bit version - 1 GB = (1 << 30) bytes for 64-bit version - The default value is 16 MB = (1 << 24) bytes, for level = 5. - It's recommended to use the dictionary that is larger than 4 KB and - that can be calculated as (1 << N) or (3 << N) sizes. - For better compression ratio dictSize must be >= inSize. - -filterMode: - SZ_FILTER_NO - no Filter - SZ_FILTER_YES - x86 Filter - SZ_FILTER_AUTO - it tries both alternatives to select best. - Encoder will use 2 or 3 passes: - 2 passes when FILTER_NO provides better compression. - 3 passes when FILTER_YES provides better compression. - -Lzma86Encode allocates Data with MyAlloc functions. -RAM Requirements for compressing: - RamSize = dictionarySize * 11.5 + 6MB + FilterBlockSize - filterMode FilterBlockSize - SZ_FILTER_NO 0 - SZ_FILTER_YES inSize - SZ_FILTER_AUTO inSize - - -Return code: - SZ_OK - OK - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_PARAM - Incorrect paramater - SZ_ERROR_OUTPUT_EOF - output buffer overflow - SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) -*/ - -enum ESzFilterMode -{ - SZ_FILTER_NO, - SZ_FILTER_YES, - SZ_FILTER_AUTO -}; - -SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, - int level, UInt32 dictSize, int filterMode); - - -/* -Lzma86_GetUnpackSize: - In: - src - input data - srcLen - input data size - Out: - unpackSize - size of uncompressed stream - Return code: - SZ_OK - OK - SZ_ERROR_INPUT_EOF - Error in headers -*/ - -SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize); - -/* -Lzma86_Decode: - In: - dest - output data - destLen - output data size - src - input data - srcLen - input data size - Out: - destLen - processed output size - srcLen - processed input size - Return code: - SZ_OK - OK - SZ_ERROR_DATA - Data error - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_UNSUPPORTED - unsupported file - SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer -*/ - -SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen); - -EXTERN_C_END - -#endif diff --git a/src/libs/7zip/win/C/Lzma86Dec.c b/src/libs/7zip/win/C/Lzma86Dec.c deleted file mode 100644 index fe7726097..000000000 --- a/src/libs/7zip/win/C/Lzma86Dec.c +++ /dev/null @@ -1,56 +0,0 @@ -/* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder -2009-08-14 : Igor Pavlov : Public domain */ - -#include "Lzma86.h" - -#include "Alloc.h" -#include "Bra.h" -#include "LzmaDec.h" - -static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } -static void SzFree(void *p, void *address) { p = p; MyFree(address); } - -SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize) -{ - unsigned i; - if (srcLen < LZMA86_HEADER_SIZE) - return SZ_ERROR_INPUT_EOF; - *unpackSize = 0; - for (i = 0; i < sizeof(UInt64); i++) - *unpackSize += ((UInt64)src[LZMA86_SIZE_OFFSET + i]) << (8 * i); - return SZ_OK; -} - -SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen) -{ - ISzAlloc g_Alloc = { SzAlloc, SzFree }; - SRes res; - int useFilter; - SizeT inSizePure; - ELzmaStatus status; - - if (*srcLen < LZMA86_HEADER_SIZE) - return SZ_ERROR_INPUT_EOF; - - useFilter = src[0]; - - if (useFilter > 1) - { - *destLen = 0; - return SZ_ERROR_UNSUPPORTED; - } - - inSizePure = *srcLen - LZMA86_HEADER_SIZE; - res = LzmaDecode(dest, destLen, src + LZMA86_HEADER_SIZE, &inSizePure, - src + 1, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &status, &g_Alloc); - *srcLen = inSizePure + LZMA86_HEADER_SIZE; - if (res != SZ_OK) - return res; - if (useFilter == 1) - { - UInt32 x86State; - x86_Convert_Init(x86State); - x86_Convert(dest, *destLen, 0, &x86State, 0); - } - return SZ_OK; -} diff --git a/src/libs/7zip/win/C/Lzma86Enc.c b/src/libs/7zip/win/C/Lzma86Enc.c deleted file mode 100644 index 2ea4ac2da..000000000 --- a/src/libs/7zip/win/C/Lzma86Enc.c +++ /dev/null @@ -1,108 +0,0 @@ -/* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder -2009-08-14 : Igor Pavlov : Public domain */ - -#include - -#include "Lzma86.h" - -#include "Alloc.h" -#include "Bra.h" -#include "LzmaEnc.h" - -#define SZE_OUT_OVERFLOW SZE_DATA_ERROR - -static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } -static void SzFree(void *p, void *address) { p = p; MyFree(address); } - -int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, - int level, UInt32 dictSize, int filterMode) -{ - ISzAlloc g_Alloc = { SzAlloc, SzFree }; - size_t outSize2 = *destLen; - Byte *filteredStream; - Bool useFilter; - int mainResult = SZ_ERROR_OUTPUT_EOF; - CLzmaEncProps props; - LzmaEncProps_Init(&props); - props.level = level; - props.dictSize = dictSize; - - *destLen = 0; - if (outSize2 < LZMA86_HEADER_SIZE) - return SZ_ERROR_OUTPUT_EOF; - - { - int i; - UInt64 t = srcLen; - for (i = 0; i < 8; i++, t >>= 8) - dest[LZMA86_SIZE_OFFSET + i] = (Byte)t; - } - - filteredStream = 0; - useFilter = (filterMode != SZ_FILTER_NO); - if (useFilter) - { - if (srcLen != 0) - { - filteredStream = (Byte *)MyAlloc(srcLen); - if (filteredStream == 0) - return SZ_ERROR_MEM; - memcpy(filteredStream, src, srcLen); - } - { - UInt32 x86State; - x86_Convert_Init(x86State); - x86_Convert(filteredStream, srcLen, 0, &x86State, 1); - } - } - - { - size_t minSize = 0; - Bool bestIsFiltered = False; - - /* passes for SZ_FILTER_AUTO: - 0 - BCJ + LZMA - 1 - LZMA - 2 - BCJ + LZMA agaian, if pass 0 (BCJ + LZMA) is better. - */ - int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1; - - int i; - for (i = 0; i < numPasses; i++) - { - size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE; - size_t outPropsSize = 5; - SRes curRes; - Bool curModeIsFiltered = (numPasses > 1 && i == numPasses - 1); - if (curModeIsFiltered && !bestIsFiltered) - break; - if (useFilter && i == 0) - curModeIsFiltered = True; - - curRes = LzmaEncode(dest + LZMA86_HEADER_SIZE, &outSizeProcessed, - curModeIsFiltered ? filteredStream : src, srcLen, - &props, dest + 1, &outPropsSize, 0, - NULL, &g_Alloc, &g_Alloc); - - if (curRes != SZ_ERROR_OUTPUT_EOF) - { - if (curRes != SZ_OK) - { - mainResult = curRes; - break; - } - if (outSizeProcessed <= minSize || mainResult != SZ_OK) - { - minSize = outSizeProcessed; - bestIsFiltered = curModeIsFiltered; - mainResult = SZ_OK; - } - } - } - dest[0] = (bestIsFiltered ? 1 : 0); - *destLen = LZMA86_HEADER_SIZE + minSize; - } - if (useFilter) - MyFree(filteredStream); - return mainResult; -} diff --git a/src/libs/7zip/win/C/LzmaDec.c b/src/libs/7zip/win/C/LzmaDec.c index 2036761bf..b1a2ad150 100644 --- a/src/libs/7zip/win/C/LzmaDec.c +++ b/src/libs/7zip/win/C/LzmaDec.c @@ -1,5 +1,7 @@ /* LzmaDec.c -- LZMA Decoder -2009-09-20 : Igor Pavlov : Public domain */ +2015-01-01 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include "LzmaDec.h" @@ -44,6 +46,13 @@ i -= 0x40; } #endif +#define NORMAL_LITER_DEC GET_BIT(prob + symbol, symbol) +#define MATCHED_LITER_DEC \ + matchByte <<= 1; \ + bit = (matchByte & offs); \ + probLit = prob + offs + bit + symbol; \ + GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) + #define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } #define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) @@ -141,7 +150,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte Byte *dic = p->dic; SizeT dicBufSize = p->dicBufSize; SizeT dicPos = p->dicPos; - + UInt32 processedPos = p->processedPos; UInt32 checkDicSize = p->checkDicSize; unsigned len = 0; @@ -171,24 +180,47 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte { state -= (state < 4) ? state : 3; symbol = 1; - do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); + #ifdef _LZMA_SIZE_OPT + do { NORMAL_LITER_DEC } while (symbol < 0x100); + #else + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + #endif } else { - unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + unsigned matchByte = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; unsigned offs = 0x100; state -= (state < 10) ? 3 : 6; symbol = 1; + #ifdef _LZMA_SIZE_OPT do { unsigned bit; CLzmaProb *probLit; - matchByte <<= 1; - bit = (matchByte & offs); - probLit = prob + offs + bit + symbol; - GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) + MATCHED_LITER_DEC } while (symbol < 0x100); + #else + { + unsigned bit; + CLzmaProb *probLit; + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + } + #endif } dic[dicPos++] = (Byte)symbol; processedPos++; @@ -324,7 +356,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte { NORMALIZE range >>= 1; - + { UInt32 t; code -= range; @@ -442,8 +474,9 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) p->processedPos += len; p->remainLen -= len; - while (len-- != 0) + while (len != 0) { + len--; dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; dicPos++; } @@ -722,7 +755,7 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr SizeT inSize = *srcLen; (*srcLen) = 0; LzmaDec_WriteRem(p, dicLimit); - + *status = LZMA_STATUS_NOT_SPECIFIED; while (p->remainLen != kMatchSpecLenStart) @@ -768,7 +801,7 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr if (p->needInitState) LzmaDec_InitStateReal(p); - + if (p->tempBufSize == 0) { SizeT processed; @@ -899,12 +932,12 @@ SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) { UInt32 dicSize; Byte d; - + if (size < LZMA_PROPS_SIZE) return SZ_ERROR_UNSUPPORTED; else dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); - + if (dicSize < LZMA_DIC_MIN) dicSize = LZMA_DIC_MIN; p->dicSize = dicSize; @@ -972,28 +1005,21 @@ SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, { CLzmaDec p; SRes res; - SizeT inSize = *srcLen; - SizeT outSize = *destLen; - *srcLen = *destLen = 0; + SizeT outSize = *destLen, inSize = *srcLen; + *destLen = *srcLen = 0; + *status = LZMA_STATUS_NOT_SPECIFIED; if (inSize < RC_INIT_SIZE) return SZ_ERROR_INPUT_EOF; - LzmaDec_Construct(&p); - res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); - if (res != 0) - return res; + RINOK(LzmaDec_AllocateProbs(&p, propData, propSize, alloc)); p.dic = dest; p.dicBufSize = outSize; - LzmaDec_Init(&p); - *srcLen = inSize; res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); - + *destLen = p.dicPos; if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) res = SZ_ERROR_INPUT_EOF; - - (*destLen) = p.dicPos; LzmaDec_FreeProbs(&p, alloc); return res; } diff --git a/src/libs/7zip/win/C/LzmaDec.h b/src/libs/7zip/win/C/LzmaDec.h index bf7f084ba..63efc351f 100644 --- a/src/libs/7zip/win/C/LzmaDec.h +++ b/src/libs/7zip/win/C/LzmaDec.h @@ -1,14 +1,12 @@ /* LzmaDec.h -- LZMA Decoder -2009-02-07 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __LZMA_DEC_H #define __LZMA_DEC_H -#include "Types.h" +#include "7zTypes.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN /* #define _LZMA_PROB32 */ /* _LZMA_PROB32 can increase the speed on some CPUs, @@ -130,7 +128,7 @@ LzmaDec_Allocate* can return: SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties */ - + SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); @@ -159,7 +157,7 @@ void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); */ /* LzmaDec_DecodeToDic - + The decoding to internal dictionary buffer (CLzmaDec::dic). You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! @@ -224,8 +222,6 @@ SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); -#ifdef __cplusplus -} -#endif +EXTERN_C_END #endif diff --git a/src/libs/7zip/win/C/LzmaEnc.c b/src/libs/7zip/win/C/LzmaEnc.c index cf131388a..bf3cc2ddb 100644 --- a/src/libs/7zip/win/C/LzmaEnc.c +++ b/src/libs/7zip/win/C/LzmaEnc.c @@ -1,5 +1,7 @@ /* LzmaEnc.c -- LZMA Encoder -2010-04-16 : Igor Pavlov : Public domain */ +2014-12-29 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include @@ -18,7 +20,7 @@ #endif #ifdef SHOW_STAT -static int ttt = 0; +static unsigned g_STAT_OFFSET = 0; #endif #define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1) @@ -46,6 +48,7 @@ void LzmaEncProps_Init(CLzmaEncProps *p) { p->level = 5; p->dictSize = p->mc = 0; + p->reduceSize = (UInt64)(Int64)-1; p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; p->writeEndMark = 0; } @@ -56,6 +59,15 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p) if (level < 0) level = 5; p->level = level; if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26))); + if (p->dictSize > p->reduceSize) + { + unsigned i; + for (i = 11; i <= 30; i++) + { + if ((UInt32)p->reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; } + if ((UInt32)p->reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; } + } + } if (p->lc < 0) p->lc = 3; if (p->lp < 0) p->lp = 0; if (p->pb < 0) p->pb = 2; @@ -109,7 +121,7 @@ void LzmaEnc_FastPosInit(Byte *g_FastPos) int c = 2, slotFast; g_FastPos[0] = 0; g_FastPos[1] = 1; - + for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++) { UInt32 k = (1 << ((slotFast >> 1) - 1)); @@ -246,7 +258,7 @@ typedef struct CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; CLzmaProb posAlignEncoder[1 << kNumAlignBits]; - + CLenPriceEnc lenEnc; CLenPriceEnc repLenEnc; @@ -269,7 +281,7 @@ typedef struct #ifndef _7ZIP_ST Byte pad[128]; #endif - + UInt32 optimumEndIndex; UInt32 optimumCurrentIndex; @@ -277,7 +289,7 @@ typedef struct UInt32 numPairs; UInt32 numAvail; COptimal opt[kNumOpts]; - + #ifndef LZMA_LOG_BSR Byte g_FastPos[1 << kNumLogBits]; #endif @@ -311,14 +323,14 @@ typedef struct CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; CLzmaProb posAlignEncoder[1 << kNumAlignBits]; - + CLenPriceEnc lenEnc; CLenPriceEnc repLenEnc; unsigned lclp; Bool fastMode; - + CRangeEnc rc; Bool writeEndMark; @@ -329,7 +341,6 @@ typedef struct SRes result; UInt32 dictSize; - UInt32 matchFinderCycles; int needInit; @@ -398,7 +409,6 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) props.dictSize > ((UInt32)1 << kDicLogSizeMaxCompress) || props.dictSize > ((UInt32)1 << 30)) return SZ_ERROR_PARAM; p->dictSize = props.dictSize; - p->matchFinderCycles = props.mc; { unsigned fb = props.fb; if (fb < 5) @@ -508,7 +518,7 @@ static void RangeEnc_FlushStream(CRangeEnc *p) static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) { - if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0) + if ((UInt32)p->low < (UInt32)0xFF000000 || (unsigned)(p->low >> 32) != 0) { Byte temp = p->cache; do @@ -534,7 +544,7 @@ static void RangeEnc_FlushData(CRangeEnc *p) RangeEnc_ShiftLow(p); } -static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits) +static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, unsigned numBits) { do { @@ -803,9 +813,10 @@ static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 static void MovePos(CLzmaEnc *p, UInt32 num) { #ifdef SHOW_STAT - ttt += num; + g_STAT_OFFSET += num; printf("\n MovePos %d", num); #endif + if (num != 0) { p->additionalOffset += num; @@ -818,15 +829,17 @@ static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes) UInt32 lenRes = 0, numPairs; p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); + #ifdef SHOW_STAT - printf("\n i = %d numPairs = %d ", ttt, numPairs / 2); - ttt++; + printf("\n i = %d numPairs = %d ", g_STAT_OFFSET, numPairs / 2); + g_STAT_OFFSET++; { UInt32 i; for (i = 0; i < numPairs; i += 2) printf("%2d %6d | ", p->matches[i], p->matches[i + 1]); } #endif + if (numPairs > 0) { lenRes = p->matches[numPairs - 2]; @@ -909,10 +922,10 @@ static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur) { UInt32 posPrev = posMem; UInt32 backCur = backMem; - + backMem = p->opt[posPrev].backPrev; posMem = p->opt[posPrev].posPrev; - + p->opt[posPrev].backPrev = backCur; p->opt[posPrev].posPrev = cur; cur = posPrev; @@ -943,7 +956,7 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) return lenRes; } p->optimumCurrentIndex = p->optimumEndIndex = 0; - + if (p->additionalOffset == 0) mainLen = ReadMatchDistances(p, &numPairs); else @@ -1241,7 +1254,7 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]); repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); - + if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState); @@ -1303,7 +1316,7 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) } } } - + startLen = 2; /* speed optimization */ { UInt32 repIndex; @@ -1334,10 +1347,10 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) } while (--lenTest >= 2); lenTest = lenTestTemp; - + if (repIndex == 0) startLen = lenTest + 1; - + /* if (_maxMode) */ { UInt32 lenTest2 = lenTest + 1; @@ -1361,7 +1374,7 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) nextRepMatchPrice = curAndLenCharPrice + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); - + /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 curAndLenPrice; @@ -1416,7 +1429,7 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) curAndLenPrice += p->distancesPrices[lenToPosState][curBack]; else curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask]; - + opt = &p->opt[cur + lenTest]; if (curAndLenPrice < opt->price) { @@ -1450,7 +1463,7 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) nextRepMatchPrice = curAndLenCharPrice + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); - + /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 offset = cur + lenTest + 1 + lenTest2; @@ -1562,7 +1575,7 @@ static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes) MovePos(p, repLen - 1); return repLen; } - + if (mainLen < 2 || numAvail <= 2) return 1; @@ -1576,7 +1589,7 @@ static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes) (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist))) return 1; } - + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; for (i = 0; i < LZMA_NUM_REPS; i++) { @@ -1837,7 +1850,7 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize pos -= LZMA_NUM_REPS; GetPosSlot(pos, posSlot); RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot); - + if (posSlot >= kStartPosModelIndex) { UInt32 footerBits = ((posSlot >> 1) - 1); @@ -1897,12 +1910,10 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { UInt32 beforeSize = kNumOpts; - Bool btMode; if (!RangeEnc_Alloc(&p->rc, alloc)) return SZ_ERROR_MEM; - btMode = (p->matchFinderBase.btMode != 0); #ifndef _7ZIP_ST - p->mtMode = (p->multiThread && !p->fastMode && btMode); + p->mtMode = (p->multiThread && !p->fastMode && (p->matchFinderBase.btMode != 0)); #endif { @@ -2142,7 +2153,7 @@ SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, p->rc.outStream = &outStream.funcTable; res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize); - + *unpackSize = (UInt32)(p->nowPos64 - nowPos64); *destLen -= outStream.rem; if (outStream.overflow) @@ -2157,9 +2168,8 @@ static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) #ifndef _7ZIP_ST Byte allocaDummy[0x300]; - int i = 0; - for (i = 0; i < 16; i++) - allocaDummy[i] = (Byte)i; + allocaDummy[0] = 0; + allocaDummy[1] = allocaDummy[0]; #endif for (;;) diff --git a/src/libs/7zip/win/C/LzmaEnc.h b/src/libs/7zip/win/C/LzmaEnc.h index 200d60eb8..cffe220bb 100644 --- a/src/libs/7zip/win/C/LzmaEnc.h +++ b/src/libs/7zip/win/C/LzmaEnc.h @@ -1,14 +1,12 @@ /* LzmaEnc.h -- LZMA Encoder -2009-02-07 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __LZMA_ENC_H #define __LZMA_ENC_H -#include "Types.h" +#include "7zTypes.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN #define LZMA_PROPS_SIZE 5 @@ -18,6 +16,8 @@ typedef struct _CLzmaEncProps UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version (1 << 12) <= dictSize <= (1 << 30) for 64-bit version default = (1 << 24) */ + UInt64 reduceSize; /* estimated size of data that will be compressed. default = 0xFFFFFFFF. + Encoder uses this value to reduce dictionary size */ int lc; /* 0 <= lc <= 8, default = 3 */ int lp; /* 0 <= lp <= 4, default = 0 */ int pb; /* 0 <= pb <= 4, default = 2 */ @@ -73,8 +73,6 @@ SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); -#ifdef __cplusplus -} -#endif +EXTERN_C_END #endif diff --git a/src/libs/7zip/win/C/LzmaLib.c b/src/libs/7zip/win/C/LzmaLib.c deleted file mode 100644 index 02a511857..000000000 --- a/src/libs/7zip/win/C/LzmaLib.c +++ /dev/null @@ -1,46 +0,0 @@ -/* LzmaLib.c -- LZMA library wrapper -2008-08-05 -Igor Pavlov -Public domain */ - -#include "LzmaEnc.h" -#include "LzmaDec.h" -#include "Alloc.h" -#include "LzmaLib.h" - -static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } -static void SzFree(void *p, void *address) { p = p; MyFree(address); } -static ISzAlloc g_Alloc = { SzAlloc, SzFree }; - -MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, - unsigned char *outProps, size_t *outPropsSize, - int level, /* 0 <= level <= 9, default = 5 */ - unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */ - int lc, /* 0 <= lc <= 8, default = 3 */ - int lp, /* 0 <= lp <= 4, default = 0 */ - int pb, /* 0 <= pb <= 4, default = 2 */ - int fb, /* 5 <= fb <= 273, default = 32 */ - int numThreads /* 1 or 2, default = 2 */ -) -{ - CLzmaEncProps props; - LzmaEncProps_Init(&props); - props.level = level; - props.dictSize = dictSize; - props.lc = lc; - props.lp = lp; - props.pb = pb; - props.fb = fb; - props.numThreads = numThreads; - - return LzmaEncode(dest, destLen, src, srcLen, &props, outProps, outPropsSize, 0, - NULL, &g_Alloc, &g_Alloc); -} - - -MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen, - const unsigned char *props, size_t propsSize) -{ - ELzmaStatus status; - return LzmaDecode(dest, destLen, src, srcLen, props, (unsigned)propsSize, LZMA_FINISH_ANY, &status, &g_Alloc); -} diff --git a/src/libs/7zip/win/C/LzmaLib.h b/src/libs/7zip/win/C/LzmaLib.h deleted file mode 100644 index 76c99ce75..000000000 --- a/src/libs/7zip/win/C/LzmaLib.h +++ /dev/null @@ -1,135 +0,0 @@ -/* LzmaLib.h -- LZMA library interface -2009-04-07 : Igor Pavlov : Public domain */ - -#ifndef __LZMA_LIB_H -#define __LZMA_LIB_H - -#include "Types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define MY_STDAPI int MY_STD_CALL - -#define LZMA_PROPS_SIZE 5 - -/* -RAM requirements for LZMA: - for compression: (dictSize * 11.5 + 6 MB) + state_size - for decompression: dictSize + state_size - state_size = (4 + (1.5 << (lc + lp))) KB - by default (lc=3, lp=0), state_size = 16 KB. - -LZMA properties (5 bytes) format - Offset Size Description - 0 1 lc, lp and pb in encoded form. - 1 4 dictSize (little endian). -*/ - -/* -LzmaCompress ------------- - -outPropsSize - - In: the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. - Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. - - LZMA Encoder will use defult values for any parameter, if it is - -1 for any from: level, loc, lp, pb, fb, numThreads - 0 for dictSize - -level - compression level: 0 <= level <= 9; - - level dictSize algo fb - 0: 16 KB 0 32 - 1: 64 KB 0 32 - 2: 256 KB 0 32 - 3: 1 MB 0 32 - 4: 4 MB 0 32 - 5: 16 MB 1 32 - 6: 32 MB 1 32 - 7+: 64 MB 1 64 - - The default value for "level" is 5. - - algo = 0 means fast method - algo = 1 means normal method - -dictSize - The dictionary size in bytes. The maximum value is - 128 MB = (1 << 27) bytes for 32-bit version - 1 GB = (1 << 30) bytes for 64-bit version - The default value is 16 MB = (1 << 24) bytes. - It's recommended to use the dictionary that is larger than 4 KB and - that can be calculated as (1 << N) or (3 << N) sizes. - -lc - The number of literal context bits (high bits of previous literal). - It can be in the range from 0 to 8. The default value is 3. - Sometimes lc=4 gives the gain for big files. - -lp - The number of literal pos bits (low bits of current position for literals). - It can be in the range from 0 to 4. The default value is 0. - The lp switch is intended for periodical data when the period is equal to 2^lp. - For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's - better to set lc=0, if you change lp switch. - -pb - The number of pos bits (low bits of current position). - It can be in the range from 0 to 4. The default value is 2. - The pb switch is intended for periodical data when the period is equal 2^pb. - -fb - Word size (the number of fast bytes). - It can be in the range from 5 to 273. The default value is 32. - Usually, a big number gives a little bit better compression ratio and - slower compression process. - -numThreads - The number of thereads. 1 or 2. The default value is 2. - Fast mode (algo = 0) can use only 1 thread. - -Out: - destLen - processed output size -Returns: - SZ_OK - OK - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_PARAM - Incorrect paramater - SZ_ERROR_OUTPUT_EOF - output buffer overflow - SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) -*/ - -MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, - unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */ - int level, /* 0 <= level <= 9, default = 5 */ - unsigned dictSize, /* default = (1 << 24) */ - int lc, /* 0 <= lc <= 8, default = 3 */ - int lp, /* 0 <= lp <= 4, default = 0 */ - int pb, /* 0 <= pb <= 4, default = 2 */ - int fb, /* 5 <= fb <= 273, default = 32 */ - int numThreads /* 1 or 2, default = 2 */ - ); - -/* -LzmaUncompress --------------- -In: - dest - output data - destLen - output data size - src - input data - srcLen - input data size -Out: - destLen - processed output size - srcLen - processed input size -Returns: - SZ_OK - OK - SZ_ERROR_DATA - Data error - SZ_ERROR_MEM - Memory allocation arror - SZ_ERROR_UNSUPPORTED - Unsupported properties - SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer (src) -*/ - -MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen, - const unsigned char *props, size_t propsSize); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/libs/7zip/win/C/MtCoder.c b/src/libs/7zip/win/C/MtCoder.c index 946fbbc70..3d4dd2d14 100644 --- a/src/libs/7zip/win/C/MtCoder.c +++ b/src/libs/7zip/win/C/MtCoder.c @@ -1,6 +1,8 @@ /* MtCoder.c -- Multi-thread Coder 2010-09-24 : Igor Pavlov : Public domain */ +#include "Precomp.h" + #include #include "MtCoder.h" @@ -190,9 +192,9 @@ static SRes MtThread_Process(CMtThread *p, Bool *stop) *stop = True; if (Event_Wait(&p->canRead) != 0) return SZ_ERROR_THREAD; - + next = GET_NEXT_THREAD(p); - + if (p->stopReading) { next->stopReading = True; diff --git a/src/libs/7zip/win/C/MtCoder.h b/src/libs/7zip/win/C/MtCoder.h index f0f06da28..e2cbdc3ab 100644 --- a/src/libs/7zip/win/C/MtCoder.h +++ b/src/libs/7zip/win/C/MtCoder.h @@ -14,7 +14,7 @@ typedef struct CAutoResetEvent startEvent; CAutoResetEvent finishedEvent; int stop; - + THREAD_FUNC_TYPE func; LPVOID param; THREAD_FUNC_RET_TYPE res; @@ -75,7 +75,7 @@ typedef struct _CMtCoder size_t blockSize; size_t destBlockSize; unsigned numThreads; - + ISeqInStream *inStream; ISeqOutStream *outStream; ICompressProgress *progress; diff --git a/src/libs/7zip/win/C/Precomp.h b/src/libs/7zip/win/C/Precomp.h new file mode 100644 index 000000000..e8ff8b40e --- /dev/null +++ b/src/libs/7zip/win/C/Precomp.h @@ -0,0 +1,10 @@ +/* Precomp.h -- StdAfx +2013-11-12 : Igor Pavlov : Public domain */ + +#ifndef __7Z_PRECOMP_H +#define __7Z_PRECOMP_H + +#include "Compiler.h" +/* #include "7zTypes.h" */ + +#endif diff --git a/src/libs/7zip/win/C/RotateDefs.h b/src/libs/7zip/win/C/RotateDefs.h index c3a1385ce..1b83e5ea1 100644 --- a/src/libs/7zip/win/C/RotateDefs.h +++ b/src/libs/7zip/win/C/RotateDefs.h @@ -1,5 +1,5 @@ /* RotateDefs.h -- Rotate functions -2009-02-07 : Igor Pavlov : Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ #ifndef __ROTATE_DEFS_H #define __ROTATE_DEFS_H @@ -7,6 +7,12 @@ #ifdef _MSC_VER #include + +// #if (_MSC_VER >= 1200) +#pragma intrinsic(_rotl) +#pragma intrinsic(_rotr) +// #endif + #define rotlFixed(x, n) _rotl((x), (n)) #define rotrFixed(x, n) _rotr((x), (n)) diff --git a/src/libs/7zip/win/C/Sha256.c b/src/libs/7zip/win/C/Sha256.c index eb4fc61fc..10df0874f 100644 --- a/src/libs/7zip/win/C/Sha256.c +++ b/src/libs/7zip/win/C/Sha256.c @@ -2,6 +2,8 @@ 2010-06-11 : Igor Pavlov : Public domain This code is based on public domain code from Wei Dai's Crypto++ library. */ +#include "Precomp.h" + #include "RotateDefs.h" #include "Sha256.h" @@ -133,7 +135,7 @@ static void Sha256_Transform(UInt32 *state, const UInt32 *data) for (j = 0; j < 8; j++) state[j] += T[j]; #endif - + /* Wipe variables */ /* memset(W, 0, sizeof(W)); */ /* memset(T, 0, sizeof(T)); */ diff --git a/src/libs/7zip/win/C/Sha256.h b/src/libs/7zip/win/C/Sha256.h index 530f513ec..3f455dbc0 100644 --- a/src/libs/7zip/win/C/Sha256.h +++ b/src/libs/7zip/win/C/Sha256.h @@ -1,10 +1,10 @@ /* Sha256.h -- SHA-256 Hash -2010-06-11 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __CRYPTO_SHA256_H #define __CRYPTO_SHA256_H -#include "Types.h" +#include "7zTypes.h" EXTERN_C_BEGIN diff --git a/src/libs/7zip/win/C/Threads.c b/src/libs/7zip/win/C/Threads.c index 7af1da2e2..5c67a1e26 100644 --- a/src/libs/7zip/win/C/Threads.c +++ b/src/libs/7zip/win/C/Threads.c @@ -1,5 +1,7 @@ /* Threads.c -- multithreading library -2009-09-20 : Igor Pavlov : Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #ifndef _WIN32_WCE #include @@ -29,14 +31,21 @@ WRes Handle_WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE) WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) { - unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ - *p = - #ifdef UNDER_CE - CreateThread(0, 0, func, param, 0, &threadId); - #else - (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId); - #endif - /* maybe we must use errno here, but probably GetLastError() is also OK. */ + /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ + + #ifdef UNDER_CE + + DWORD threadId; + *p = CreateThread(0, 0, func, param, 0, &threadId); + + #else + + unsigned threadId; + *p = (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId); + + #endif + + /* maybe we must use errno here, but probably GetLastError() is also OK. */ return HandleToWRes(*p); } diff --git a/src/libs/7zip/win/C/Threads.h b/src/libs/7zip/win/C/Threads.h index d0ddd80e2..9b3e1c556 100644 --- a/src/libs/7zip/win/C/Threads.h +++ b/src/libs/7zip/win/C/Threads.h @@ -1,15 +1,17 @@ /* Threads.h -- multithreading library -2009-03-27 : Igor Pavlov : Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ #ifndef __7Z_THREADS_H #define __7Z_THREADS_H -#include "Types.h" - -#ifdef __cplusplus -extern "C" { +#ifdef _WIN32 +#include #endif +#include "7zTypes.h" + +EXTERN_C_BEGIN + WRes HandlePtr_Close(HANDLE *h); WRes Handle_WaitObject(HANDLE h); @@ -18,7 +20,15 @@ typedef HANDLE CThread; #define Thread_WasCreated(p) (*(p) != NULL) #define Thread_Close(p) HandlePtr_Close(p) #define Thread_Wait(p) Handle_WaitObject(*(p)) -typedef unsigned THREAD_FUNC_RET_TYPE; + +typedef +#ifdef UNDER_CE + DWORD +#else + unsigned +#endif + THREAD_FUNC_RET_TYPE; + #define THREAD_FUNC_CALL_TYPE MY_STD_CALL #define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *); @@ -52,8 +62,6 @@ WRes CriticalSection_Init(CCriticalSection *p); #define CriticalSection_Enter(p) EnterCriticalSection(p) #define CriticalSection_Leave(p) LeaveCriticalSection(p) -#ifdef __cplusplus -} -#endif +EXTERN_C_END #endif diff --git a/src/libs/7zip/win/C/Types.h b/src/libs/7zip/win/C/Types.h deleted file mode 100644 index 7732c240c..000000000 --- a/src/libs/7zip/win/C/Types.h +++ /dev/null @@ -1,254 +0,0 @@ -/* Types.h -- Basic types -2010-10-09 : Igor Pavlov : Public domain */ - -#ifndef __7Z_TYPES_H -#define __7Z_TYPES_H - -#include - -#ifdef _WIN32 -#include -#endif - -#ifndef EXTERN_C_BEGIN -#ifdef __cplusplus -#define EXTERN_C_BEGIN extern "C" { -#define EXTERN_C_END } -#else -#define EXTERN_C_BEGIN -#define EXTERN_C_END -#endif -#endif - -EXTERN_C_BEGIN - -#define SZ_OK 0 - -#define SZ_ERROR_DATA 1 -#define SZ_ERROR_MEM 2 -#define SZ_ERROR_CRC 3 -#define SZ_ERROR_UNSUPPORTED 4 -#define SZ_ERROR_PARAM 5 -#define SZ_ERROR_INPUT_EOF 6 -#define SZ_ERROR_OUTPUT_EOF 7 -#define SZ_ERROR_READ 8 -#define SZ_ERROR_WRITE 9 -#define SZ_ERROR_PROGRESS 10 -#define SZ_ERROR_FAIL 11 -#define SZ_ERROR_THREAD 12 - -#define SZ_ERROR_ARCHIVE 16 -#define SZ_ERROR_NO_ARCHIVE 17 - -typedef int SRes; - -#ifdef _WIN32 -typedef DWORD WRes; -#else -typedef int WRes; -#endif - -#ifndef RINOK -#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } -#endif - -typedef unsigned char Byte; -typedef short Int16; -typedef unsigned short UInt16; - -#ifdef _LZMA_UINT32_IS_ULONG -typedef long Int32; -typedef unsigned long UInt32; -#else -typedef int Int32; -typedef unsigned int UInt32; -#endif - -#ifdef _SZ_NO_INT_64 - -/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. - NOTES: Some code will work incorrectly in that case! */ - -typedef long Int64; -typedef unsigned long UInt64; - -#else - -#if defined(_MSC_VER) || defined(__BORLANDC__) -typedef __int64 Int64; -typedef unsigned __int64 UInt64; -#define UINT64_CONST(n) n -#else -typedef long long int Int64; -typedef unsigned long long int UInt64; -#define UINT64_CONST(n) n ## ULL -#endif - -#endif - -#ifdef _LZMA_NO_SYSTEM_SIZE_T -typedef UInt32 SizeT; -#else -typedef size_t SizeT; -#endif - -typedef int Bool; -#define True 1 -#define False 0 - - -#ifdef _WIN32 -#define MY_STD_CALL __stdcall -#else -#define MY_STD_CALL -#endif - -#ifdef _MSC_VER - -#if _MSC_VER >= 1300 -#define MY_NO_INLINE __declspec(noinline) -#else -#define MY_NO_INLINE -#endif - -#define MY_CDECL __cdecl -#define MY_FAST_CALL __fastcall - -#else - -#define MY_CDECL -#define MY_FAST_CALL - -#endif - - -/* The following interfaces use first parameter as pointer to structure */ - -typedef struct -{ - Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */ -} IByteIn; - -typedef struct -{ - void (*Write)(void *p, Byte b); -} IByteOut; - -typedef struct -{ - SRes (*Read)(void *p, void *buf, size_t *size); - /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. - (output(*size) < input(*size)) is allowed */ -} ISeqInStream; - -/* it can return SZ_ERROR_INPUT_EOF */ -SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); -SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); -SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); - -typedef struct -{ - size_t (*Write)(void *p, const void *buf, size_t size); - /* Returns: result - the number of actually written bytes. - (result < size) means error */ -} ISeqOutStream; - -typedef enum -{ - SZ_SEEK_SET = 0, - SZ_SEEK_CUR = 1, - SZ_SEEK_END = 2 -} ESzSeek; - -typedef struct -{ - SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ - SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); -} ISeekInStream; - -typedef struct -{ - SRes (*Look)(void *p, const void **buf, size_t *size); - /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. - (output(*size) > input(*size)) is not allowed - (output(*size) < input(*size)) is allowed */ - SRes (*Skip)(void *p, size_t offset); - /* offset must be <= output(*size) of Look */ - - SRes (*Read)(void *p, void *buf, size_t *size); - /* reads directly (without buffer). It's same as ISeqInStream::Read */ - SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); -} ILookInStream; - -SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); -SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); - -/* reads via ILookInStream::Read */ -SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); -SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); - -#define LookToRead_BUF_SIZE (1 << 14) - -typedef struct -{ - ILookInStream s; - ISeekInStream *realStream; - size_t pos; - size_t size; - Byte buf[LookToRead_BUF_SIZE]; -} CLookToRead; - -void LookToRead_CreateVTable(CLookToRead *p, int lookahead); -void LookToRead_Init(CLookToRead *p); - -typedef struct -{ - ISeqInStream s; - ILookInStream *realStream; -} CSecToLook; - -void SecToLook_CreateVTable(CSecToLook *p); - -typedef struct -{ - ISeqInStream s; - ILookInStream *realStream; -} CSecToRead; - -void SecToRead_CreateVTable(CSecToRead *p); - -typedef struct -{ - SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); - /* Returns: result. (result != SZ_OK) means break. - Value (UInt64)(Int64)-1 for size means unknown value. */ -} ICompressProgress; - -typedef struct -{ - void *(*Alloc)(void *p, size_t size); - void (*Free)(void *p, void *address); /* address can be 0 */ -} ISzAlloc; - -#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) -#define IAlloc_Free(p, a) (p)->Free((p), a) - -#ifdef _WIN32 - -#define CHAR_PATH_SEPARATOR '\\' -#define WCHAR_PATH_SEPARATOR L'\\' -#define STRING_PATH_SEPARATOR "\\" -#define WSTRING_PATH_SEPARATOR L"\\" - -#else - -#define CHAR_PATH_SEPARATOR '/' -#define WCHAR_PATH_SEPARATOR L'/' -#define STRING_PATH_SEPARATOR "/" -#define WSTRING_PATH_SEPARATOR L"/" - -#endif - -EXTERN_C_END - -#endif diff --git a/src/libs/7zip/win/C/Xz.c b/src/libs/7zip/win/C/Xz.c index 18caba2c1..fbc732a8a 100644 --- a/src/libs/7zip/win/C/Xz.c +++ b/src/libs/7zip/win/C/Xz.c @@ -1,6 +1,8 @@ /* Xz.c - Xz 2009-04-15 : Igor Pavlov : Public domain */ +#include "Precomp.h" + #include "7zCrc.h" #include "CpuArch.h" #include "Xz.h" diff --git a/src/libs/7zip/win/C/Xz.h b/src/libs/7zip/win/C/Xz.h index 2cfa1b789..9268d5bc6 100644 --- a/src/libs/7zip/win/C/Xz.h +++ b/src/libs/7zip/win/C/Xz.h @@ -1,5 +1,5 @@ /* Xz.h - Xz interface -2010-09-17 : Igor Pavlov : Public domain */ +2014-12-30 : Igor Pavlov : Public domain */ #ifndef __XZ_H #define __XZ_H @@ -199,7 +199,7 @@ typedef struct unsigned indexPreSize; CXzStreamFlags streamFlags; - + UInt32 blockHeaderSize; UInt64 packSize; UInt64 unpackSize; @@ -209,7 +209,9 @@ typedef struct UInt64 indexPos; UInt64 padSize; - UInt64 numStreams; + UInt64 numStartedStreams; + UInt64 numFinishedStreams; + UInt64 numTotalBlocks; UInt32 crc; CMixCoder decoder; @@ -220,33 +222,54 @@ typedef struct Byte buf[XZ_BLOCK_HEADER_SIZE_MAX]; } CXzUnpacker; -SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc); +void XzUnpacker_Construct(CXzUnpacker *p, ISzAlloc *alloc); +void XzUnpacker_Init(CXzUnpacker *p); void XzUnpacker_Free(CXzUnpacker *p); /* finishMode: It has meaning only if the decoding reaches output limit (*destLen). - LZMA_FINISH_ANY - use smallest number of input bytes - LZMA_FINISH_END - read EndOfStream marker after decoding + CODER_FINISH_ANY - use smallest number of input bytes + CODER_FINISH_END - read EndOfStream marker after decoding Returns: SZ_OK status: - LZMA_STATUS_FINISHED_WITH_MARK - LZMA_STATUS_NOT_FINISHED - SZ_ERROR_DATA - Data error + CODER_STATUS_NOT_FINISHED, + CODER_STATUS_NEEDS_MORE_INPUT - maybe there are more xz streams, + call XzUnpacker_IsStreamWasFinished to check that current stream was finished SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_UNSUPPORTED - Unsupported properties - SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). + SZ_ERROR_DATA - Data error + SZ_ERROR_UNSUPPORTED - Unsupported method or method properties + SZ_ERROR_CRC - CRC error + // SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). + + SZ_ERROR_NO_ARCHIVE - the error with xz Stream Header with one of the following reasons: + - xz Stream Signature failure + - CRC32 of xz Stream Header is failed + - The size of Stream padding is not multiple of four bytes. + It's possible to get that error, if xz stream was finished and the stream + contains some another data. In that case you can call XzUnpacker_GetExtraSize() + function to get real size of xz stream. */ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, - const Byte *src, SizeT *srcLen, /* int srcWasFinished, */ int finishMode, + const Byte *src, SizeT *srcLen, ECoderFinishMode finishMode, ECoderStatus *status); Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p); +/* +Call XzUnpacker_GetExtraSize after XzUnpacker_Code function to detect real size of +xz stream in two cases: +XzUnpacker_Code() returns: + res == SZ_OK && status == CODER_STATUS_NEEDS_MORE_INPUT + res == SZ_ERROR_NO_ARCHIVE +*/ + +UInt64 XzUnpacker_GetExtraSize(CXzUnpacker *p); + EXTERN_C_END #endif diff --git a/src/libs/7zip/win/C/XzCrc64.c b/src/libs/7zip/win/C/XzCrc64.c index 0369554b7..2c04c0af4 100644 --- a/src/libs/7zip/win/C/XzCrc64.c +++ b/src/libs/7zip/win/C/XzCrc64.c @@ -1,33 +1,90 @@ /* XzCrc64.c -- CRC64 calculation -2010-04-16 : Igor Pavlov : Public domain */ +2011-06-28 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include "XzCrc64.h" +#include "CpuArch.h" #define kCrc64Poly UINT64_CONST(0xC96C5795D7870F42) -UInt64 g_Crc64Table[256]; -void MY_FAST_CALL Crc64GenerateTable(void) +#ifdef MY_CPU_LE + #define CRC_NUM_TABLES 4 +#else + #define CRC_NUM_TABLES 5 + #define CRC_UINT64_SWAP(v) \ + ((v >> 56) | \ + ((v >> 40) & ((UInt64)0xFF << 8)) | \ + ((v >> 24) & ((UInt64)0xFF << 16)) | \ + ((v >> 8) & ((UInt64)0xFF << 24)) | \ + ((v << 8) & ((UInt64)0xFF << 32)) | \ + ((v << 24) & ((UInt64)0xFF << 40)) | \ + ((v << 40) & ((UInt64)0xFF << 48)) | \ + (v << 56)) + UInt64 MY_FAST_CALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table); +#endif + +#ifndef MY_CPU_BE + UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table); +#endif + +typedef UInt64 (MY_FAST_CALL *CRC_FUNC)(UInt64 v, const void *data, size_t size, const UInt64 *table); + +static CRC_FUNC g_Crc64Update; +UInt64 g_Crc64Table[256 * CRC_NUM_TABLES]; + +UInt64 MY_FAST_CALL Crc64Update(UInt64 v, const void *data, size_t size) +{ + return g_Crc64Update(v, data, size, g_Crc64Table); +} + +UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size) +{ + return g_Crc64Update(CRC64_INIT_VAL, data, size, g_Crc64Table) ^ CRC64_INIT_VAL; +} + +void MY_FAST_CALL Crc64GenerateTable() { UInt32 i; for (i = 0; i < 256; i++) { UInt64 r = i; - int j; + unsigned j; for (j = 0; j < 8; j++) - r = (r >> 1) ^ ((UInt64)kCrc64Poly & ~((r & 1) - 1)); + r = (r >> 1) ^ (kCrc64Poly & ~((r & 1) - 1)); g_Crc64Table[i] = r; } -} + for (; i < 256 * CRC_NUM_TABLES; i++) + { + UInt64 r = g_Crc64Table[i - 256]; + g_Crc64Table[i] = g_Crc64Table[r & 0xFF] ^ (r >> 8); + } -UInt64 MY_FAST_CALL Crc64Update(UInt64 v, const void *data, size_t size) -{ - const Byte *p = (const Byte *)data; - for (; size > 0 ; size--, p++) - v = CRC64_UPDATE_BYTE(v, *p); - return v; -} + #ifdef MY_CPU_LE -UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size) -{ - return CRC64_GET_DIGEST(Crc64Update(CRC64_INIT_VAL, data, size)); + g_Crc64Update = XzCrc64UpdateT4; + + + + + + + #else + { + #ifndef MY_CPU_BE + UInt32 k = 1; + if (*(const Byte *)&k == 1) + g_Crc64Update = XzCrc64UpdateT4; + else + #endif + { + for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--) + { + UInt64 x = g_Crc64Table[i - 256]; + g_Crc64Table[i] = CRC_UINT64_SWAP(x); + } + g_Crc64Update = XzCrc64UpdateT1_BeT4; + } + } + #endif } diff --git a/src/libs/7zip/win/C/XzCrc64.h b/src/libs/7zip/win/C/XzCrc64.h index 0e8efd7ea..08dbc330c 100644 --- a/src/libs/7zip/win/C/XzCrc64.h +++ b/src/libs/7zip/win/C/XzCrc64.h @@ -1,12 +1,12 @@ /* XzCrc64.h -- CRC64 calculation -2010-04-16 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __XZ_CRC64_H #define __XZ_CRC64_H #include -#include "Types.h" +#include "7zTypes.h" EXTERN_C_BEGIN diff --git a/src/libs/7zip/win/C/XzCrc64Opt.c b/src/libs/7zip/win/C/XzCrc64Opt.c new file mode 100644 index 000000000..dccae1c19 --- /dev/null +++ b/src/libs/7zip/win/C/XzCrc64Opt.c @@ -0,0 +1,69 @@ +/* XzCrc64Opt.c -- CRC64 calculation +2011-06-28 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "CpuArch.h" + +#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +#ifndef MY_CPU_BE + +UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + for (; size >= 4; size -= 4, p += 4) + { + UInt32 d = (UInt32)v ^ *(const UInt32 *)p; + v = (v >> 32) ^ + table[0x300 + ((d ) & 0xFF)] ^ + table[0x200 + ((d >> 8) & 0xFF)] ^ + table[0x100 + ((d >> 16) & 0xFF)] ^ + table[0x000 + ((d >> 24))]; + } + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +#endif + + +#ifndef MY_CPU_LE + +#define CRC_UINT64_SWAP(v) \ + ((v >> 56) | \ + ((v >> 40) & ((UInt64)0xFF << 8)) | \ + ((v >> 24) & ((UInt64)0xFF << 16)) | \ + ((v >> 8) & ((UInt64)0xFF << 24)) | \ + ((v << 8) & ((UInt64)0xFF << 32)) | \ + ((v << 24) & ((UInt64)0xFF << 40)) | \ + ((v << 40) & ((UInt64)0xFF << 48)) | \ + (v << 56)) + +UInt64 MY_FAST_CALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + v = CRC_UINT64_SWAP(v); + table += 0x100; + for (; size >= 4; size -= 4, p += 4) + { + UInt32 d = (UInt32)(v >> 32) ^ *(const UInt32 *)p; + v = (v << 32) ^ + table[0x000 + ((d ) & 0xFF)] ^ + table[0x100 + ((d >> 8) & 0xFF)] ^ + table[0x200 + ((d >> 16) & 0xFF)] ^ + table[0x300 + ((d >> 24))]; + } + table -= 0x100; + v = CRC_UINT64_SWAP(v); + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +#endif diff --git a/src/libs/7zip/win/C/XzDec.c b/src/libs/7zip/win/C/XzDec.c index 40f1a2a45..6eef587d3 100644 --- a/src/libs/7zip/win/C/XzDec.c +++ b/src/libs/7zip/win/C/XzDec.c @@ -1,5 +1,7 @@ /* XzDec.c -- Xz Decode -2010-04-16 : Igor Pavlov : Public domain */ +2014-12-30 : Igor Pavlov : Public domain */ + +#include "Precomp.h" /* #define XZ_DUMP */ @@ -18,7 +20,8 @@ #include "Lzma2Dec.h" #ifdef USE_SUBBLOCK -#include "SbDec.h" +#include "Bcj3Dec.c" +#include "SbDec.c" #endif #include "Xz.h" @@ -72,7 +75,6 @@ SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *a { CBraState *p = ((CBraState *)pp); alloc = alloc; - p->encodeMode = 0; p->ip = 0; if (p->methodId == XZ_ID_Delta) { @@ -195,7 +197,7 @@ static SRes BraState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, return SZ_OK; } -SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, ISzAlloc *alloc) +SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAlloc *alloc) { CBraState *decoder; if (id != XZ_ID_Delta && @@ -207,10 +209,11 @@ SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, ISzAlloc *alloc) id != XZ_ID_SPARC) return SZ_ERROR_UNSUPPORTED; p->p = 0; - decoder = alloc->Alloc(alloc, sizeof(CBraState)); + decoder = (CBraState *)alloc->Alloc(alloc, sizeof(CBraState)); if (decoder == 0) return SZ_ERROR_MEM; decoder->methodId = (UInt32)id; + decoder->encodeMode = encodeMode; p->p = decoder; p->Free = BraState_Free; p->SetProps = BraState_SetProps; @@ -225,8 +228,8 @@ SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, ISzAlloc *alloc) static void SbState_Free(void *pp, ISzAlloc *alloc) { - CSubblockDec *p = (CSubblockDec *)pp; - SubblockDec_Free(p, alloc); + CSbDec *p = (CSbDec *)pp; + SbDec_Free(p); alloc->Free(alloc, pp); } @@ -240,24 +243,32 @@ static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAl static void SbState_Init(void *pp) { - SubblockDec_Init((CSubblockDec *)pp); + SbDec_Init((CSbDec *)pp); } static SRes SbState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished) { - ECoderStatus status; - SRes res = SubblockDec_Decode((CSubblockDec *)pp, dest, destLen, src, srcLen, finishMode, &status); + CSbDec *p = (CSbDec *)pp; + SRes res; srcWasFinished = srcWasFinished; - *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK); + p->dest = dest; + p->destLen = *destLen; + p->src = src; + p->srcLen = *srcLen; + p->finish = finishMode; /* change it */ + res = SbDec_Decode((CSbDec *)pp); + *destLen -= p->destLen; + *srcLen -= p->srcLen; + *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */ return res; } SRes SbState_SetFromMethod(IStateCoder *p, ISzAlloc *alloc) { - CSubblockDec *decoder; + CSbDec *decoder; p->p = 0; - decoder = alloc->Alloc(alloc, sizeof(CSubblockDec)); + decoder = alloc->Alloc(alloc, sizeof(CSbDec)); if (decoder == 0) return SZ_ERROR_MEM; p->p = decoder; @@ -265,7 +276,8 @@ SRes SbState_SetFromMethod(IStateCoder *p, ISzAlloc *alloc) p->SetProps = SbState_SetProps; p->Init = SbState_Init; p->Code = SbState_Code; - SubblockDec_Construct(decoder); + SbDec_Construct(decoder); + SbDec_SetAlloc(decoder, alloc); return SZ_OK; } #endif @@ -295,7 +307,7 @@ static SRes Lzma2State_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *sr { ELzmaStatus status; /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */ - SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, finishMode, &status); + SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status); srcWasFinished = srcWasFinished; *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK); return res; @@ -303,7 +315,7 @@ static SRes Lzma2State_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *sr static SRes Lzma2State_SetFromMethod(IStateCoder *p, ISzAlloc *alloc) { - CLzma2Dec *decoder = alloc->Alloc(alloc, sizeof(CLzma2Dec)); + CLzma2Dec *decoder = (CLzma2Dec *)alloc->Alloc(alloc, sizeof(CLzma2Dec)); p->p = decoder; if (decoder == 0) return SZ_ERROR_MEM; @@ -337,7 +349,10 @@ void MixCoder_Free(CMixCoder *p) } p->numCoders = 0; if (p->buf) + { p->alloc->Free(p->alloc, p->buf); + p->buf = 0; /* 9.31: the BUG was fixed */ + } } void MixCoder_Init(CMixCoder *p) @@ -369,7 +384,7 @@ SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId) } if (coderIndex == 0) return SZ_ERROR_UNSUPPORTED; - return BraState_SetFromMethod(sc, methodId, p->alloc); + return BraState_SetFromMethod(sc, methodId, 0, p->alloc); } SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen, @@ -385,7 +400,7 @@ SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen, if (p->buf == 0) { - p->buf = p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1)); + p->buf = (Byte *)p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1)); if (p->buf == 0) return SZ_ERROR_MEM; } @@ -411,7 +426,7 @@ SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen, const Byte *srcCur; int srcFinishedCur; int encodingWasFinished; - + if (i == 0) { srcCur = src; @@ -424,7 +439,7 @@ SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen, srcLenCur = p->size[i - 1] - p->pos[i - 1]; srcFinishedCur = p->finished[i - 1]; } - + if (i == p->numCoders - 1) { destCur = dest; @@ -437,7 +452,7 @@ SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen, destCur = p->buf + (CODER_BUF_SIZE * i); destLenCur = CODER_BUF_SIZE; } - + res = coder->Code(coder->p, destCur, &destLenCur, srcCur, &srcLenCur, srcFinishedCur, finishMode, &encodingWasFinished); if (!encodingWasFinished) @@ -464,7 +479,7 @@ SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen, p->pos[i] = 0; p->finished[i] = encodingWasFinished; } - + if (res != SZ_OK) return res; @@ -587,13 +602,20 @@ SRes XzDec_Init(CMixCoder *p, const CXzBlock *block) return SZ_OK; } -SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc) +void XzUnpacker_Init(CXzUnpacker *p) { - MixCoder_Construct(&p->decoder, alloc); p->state = XZ_STATE_STREAM_HEADER; p->pos = 0; - p->numStreams = 0; - return SZ_OK; + p->numStartedStreams = 0; + p->numFinishedStreams = 0; + p->numTotalBlocks = 0; + p->padSize = 0; +} + +void XzUnpacker_Construct(CXzUnpacker *p, ISzAlloc *alloc) +{ + MixCoder_Construct(&p->decoder, alloc); + XzUnpacker_Init(p); } void XzUnpacker_Free(CXzUnpacker *p) @@ -602,7 +624,7 @@ void XzUnpacker_Free(CXzUnpacker *p) } SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, - const Byte *src, SizeT *srcLen, int finishMode, ECoderStatus *status) + const Byte *src, SizeT *srcLen, ECoderFinishMode finishMode, ECoderStatus *status) { SizeT destLenOrig = *destLen; SizeT srcLenOrig = *srcLen; @@ -623,20 +645,20 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, *status = CODER_STATUS_NOT_FINISHED; return SZ_OK; } - + res = MixCoder_Code(&p->decoder, dest, &destLen2, src, &srcLen2, False, finishMode, status); XzCheck_Update(&p->check, dest, destLen2); - + (*srcLen) += srcLen2; src += srcLen2; p->packSize += srcLen2; - + (*destLen) += destLen2; dest += destLen2; p->unpackSize += destLen2; - + RINOK(res); - + if (*status == CODER_STATUS_FINISHED_WITH_MARK) { Byte temp[32]; @@ -645,14 +667,14 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, Sha256_Update(&p->sha, temp, num); p->indexSize += num; p->numBlocks++; - + p->state = XZ_STATE_BLOCK_FOOTER; p->pos = 0; p->alignPos = 0; } else if (srcLen2 == 0 && destLen2 == 0) return SZ_OK; - + continue; } @@ -662,7 +684,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, return SZ_OK; } - switch(p->state) + switch (p->state) { case XZ_STATE_STREAM_HEADER: { @@ -676,6 +698,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, else { RINOK(Xz_ParseHeader(&p->streamFlags, p->buf)); + p->numStartedStreams++; p->state = XZ_STATE_BLOCK_HEADER; Sha256_Init(&p->sha); p->indexSize = 0; @@ -716,6 +739,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, else { RINOK(XzBlock_Parse(&p->block, p->buf)); + p->numTotalBlocks++; p->state = XZ_STATE_BLOCK; p->packSize = 0; p->unpackSize = 0; @@ -833,7 +857,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, if (p->pos == XZ_STREAM_FOOTER_SIZE) { p->state = XZ_STATE_STREAM_PADDING; - p->numStreams++; + p->numFinishedStreams++; p->padSize = 0; if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf)) return SZ_ERROR_CRC; @@ -858,7 +882,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, } break; } - + case XZ_STATE_BLOCK: break; /* to disable GCC warning */ } } @@ -873,3 +897,13 @@ Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p) { return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0); } + +UInt64 XzUnpacker_GetExtraSize(CXzUnpacker *p) +{ + UInt64 num = 0; + if (p->state == XZ_STATE_STREAM_PADDING) + num += p->padSize; + else if (p->state == XZ_STATE_STREAM_HEADER) + num += p->padSize + p->pos; + return num; +} diff --git a/src/libs/7zip/win/C/XzEnc.c b/src/libs/7zip/win/C/XzEnc.c index 721b4e765..56680fcd8 100644 --- a/src/libs/7zip/win/C/XzEnc.c +++ b/src/libs/7zip/win/C/XzEnc.c @@ -1,5 +1,7 @@ /* XzEnc.c -- Xz Encode -2009-06-04 : Igor Pavlov : Public domain */ +2014-12-30 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include #include @@ -9,7 +11,9 @@ #include "Bra.h" #include "CpuArch.h" #ifdef USE_SUBBLOCK -#include "SbEnc.h" +#include "Bcj3Enc.c" +#include "SbFind.c" +#include "SbEnc.c" #endif #include "XzEnc.h" @@ -130,7 +134,7 @@ SRes Xz_AddIndexRecord(CXzStream *p, UInt64 unpackSize, UInt64 totalSize, ISzAll CXzBlockSizes *blocks; if (newSize / sizeof(CXzBlockSizes) != num) return SZ_ERROR_MEM; - blocks = alloc->Alloc(alloc, newSize); + blocks = (CXzBlockSizes *)alloc->Alloc(alloc, newSize); if (blocks == 0) return SZ_ERROR_MEM; if (p->numBlocks != 0) @@ -198,158 +202,147 @@ static size_t MyWrite(void *pp, const void *data, size_t size) /* ---------- CSeqInFilter ---------- */ -/* -typedef struct _IFilter -{ - void *p; - void (*Free)(void *p, ISzAlloc *alloc); - SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAlloc *alloc); - void (*Init)(void *p); - size_t (*Filter)(void *p, Byte *data, SizeT destLen); -} IFilter; - -#define FILT_BUF_SIZE (1 << 19) +#define FILTER_BUF_SIZE (1 << 20) typedef struct { ISeqInStream p; ISeqInStream *realStream; - UInt32 x86State; - UInt32 ip; - UInt64 processed; - CXzCheck check; - Byte buf[FILT_BUF_SIZE]; - UInt32 bufferPos; - UInt32 convertedPosBegin; - UInt32 convertedPosEnd; - IFilter *filter; + IStateCoder StateCoder; + Byte *buf; + size_t curPos; + size_t endPos; + int srcWasFinished; } CSeqInFilter; static SRes SeqInFilter_Read(void *pp, void *data, size_t *size) { CSeqInFilter *p = (CSeqInFilter *)pp; - size_t remSize = *size; + size_t sizeOriginal = *size; + if (sizeOriginal == 0) + return SZ_OK; *size = 0; - - while (remSize > 0) + for (;;) { - int i; - if (p->convertedPosBegin != p->convertedPosEnd) + if (!p->srcWasFinished && p->curPos == p->endPos) { - UInt32 sizeTemp = p->convertedPosEnd - p->convertedPosBegin; - if (remSize < sizeTemp) - sizeTemp = (UInt32)remSize; - memmove(data, p->buf + p->convertedPosBegin, sizeTemp); - p->convertedPosBegin += sizeTemp; - data = (void *)((Byte *)data + sizeTemp); - remSize -= sizeTemp; - *size += sizeTemp; - break; + p->curPos = 0; + p->endPos = FILTER_BUF_SIZE; + RINOK(p->realStream->Read(p->realStream, p->buf, &p->endPos)); + if (p->endPos == 0) + p->srcWasFinished = 1; } - for (i = 0; p->convertedPosEnd + i < p->bufferPos; i++) - p->buf[i] = p->buf[i + p->convertedPosEnd]; - p->bufferPos = i; - p->convertedPosBegin = p->convertedPosEnd = 0; { - size_t processedSizeTemp = FILT_BUF_SIZE - p->bufferPos; - RINOK(p->realStream->Read(p->realStream, p->buf + p->bufferPos, &processedSizeTemp)); - p->bufferPos = p->bufferPos + (UInt32)processedSizeTemp; - } - p->convertedPosEnd = (UInt32)p->filter->Filter(p->filter->p, p->buf, p->bufferPos); - if (p->convertedPosEnd == 0) - { - if (p->bufferPos == 0) - break; - else - { - p->convertedPosEnd = p->bufferPos; - continue; - } - } - if (p->convertedPosEnd > p->bufferPos) - { - for (; p->bufferPos < p->convertedPosEnd; p->bufferPos++) - p->buf[p->bufferPos] = 0; - p->convertedPosEnd = (UInt32)p->filter->Filter(p->filter->p, p->buf, p->bufferPos); + SizeT srcLen = p->endPos - p->curPos; + int wasFinished; + SRes res; + *size = sizeOriginal; + res = p->StateCoder.Code(p->StateCoder.p, data, size, p->buf + p->curPos, &srcLen, + p->srcWasFinished, CODER_FINISH_ANY, &wasFinished); + p->curPos += srcLen; + if (*size != 0 || srcLen == 0 || res != 0) + return res; } } +} + +static void SeqInFilter_Construct(CSeqInFilter *p) +{ + p->buf = NULL; + p->p.Read = SeqInFilter_Read; +} + +static void SeqInFilter_Free(CSeqInFilter *p) +{ + if (p->buf) + { + g_Alloc.Free(&g_Alloc, p->buf); + p->buf = NULL; + } +} + +SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAlloc *alloc); + +static SRes SeqInFilter_Init(CSeqInFilter *p, const CXzFilter *props) +{ + if (!p->buf) + { + p->buf = g_Alloc.Alloc(&g_Alloc, FILTER_BUF_SIZE); + if (!p->buf) + return SZ_ERROR_MEM; + } + p->curPos = p->endPos = 0; + p->srcWasFinished = 0; + RINOK(BraState_SetFromMethod(&p->StateCoder, props->id, 1, &g_Alloc)); + RINOK(p->StateCoder.SetProps(p->StateCoder.p, props->props, props->propsSize, &g_Alloc)); + p->StateCoder.Init(p->StateCoder.p); return SZ_OK; } -*/ -/* +/* ---------- CSbEncInStream ---------- */ + +#ifdef USE_SUBBLOCK + typedef struct { ISeqInStream p; - ISeqInStream *realStream; - CMixCoder mixCoder; - Byte buf[FILT_BUF_SIZE]; - UInt32 bufPos; - UInt32 bufSize; -} CMixCoderSeqInStream; + ISeqInStream *inStream; + CSbEnc enc; +} CSbEncInStream; -static SRes CMixCoderSeqInStream_Read(void *pp, void *data, size_t *size) +static SRes SbEncInStream_Read(void *pp, void *data, size_t *size) { - CMixCoderSeqInStream *p = (CMixCoderSeqInStream *)pp; - SRes res = SZ_OK; - size_t remSize = *size; - *size = 0; - while (remSize > 0) + CSbEncInStream *p = (CSbEncInStream *)pp; + size_t sizeOriginal = *size; + if (sizeOriginal == 0) + return S_OK; + for (;;) { - if (p->bufPos == p->bufSize) - { - size_t curSize; - p->bufPos = p->bufSize = 0; - if (*size != 0) - break; - curSize = FILT_BUF_SIZE; - RINOK(p->realStream->Read(p->realStream, p->buf, &curSize)); - p->bufSize = (UInt32)curSize; - } + if (p->enc.needRead && !p->enc.readWasFinished) { - SizeT destLen = remSize; - SizeT srcLen = p->bufSize - p->bufPos; - res = MixCoder_Code(&p->mixCoder, data, &destLen, p->buf + p->bufPos, &srcLen, 0); - data = (void *)((Byte *)data + destLen); - remSize -= destLen; - *size += destLen; - p->bufPos += srcLen; + size_t processed = p->enc.needReadSizeMax; + RINOK(p->inStream->Read(p->inStream, p->enc.buf + p->enc.readPos, &processed)); + p->enc.readPos += processed; + if (processed == 0) + { + p->enc.readWasFinished = True; + p->enc.isFinalFinished = True; + } + p->enc.needRead = False; } + *size = sizeOriginal; + RINOK(SbEnc_Read(&p->enc, data, size)); + if (*size != 0 || !p->enc.needRead) + return S_OK; } - return res; } -*/ -#ifdef USE_SUBBLOCK -typedef struct +void SbEncInStream_Construct(CSbEncInStream *p, ISzAlloc *alloc) { - ISeqInStream p; - CSubblockEnc sb; - UInt64 processed; -} CSbEncInStream; + SbEnc_Construct(&p->enc, alloc); + p->p.Read = SbEncInStream_Read; +} -void SbEncInStream_Init(CSbEncInStream *p) +SRes SbEncInStream_Init(CSbEncInStream *p) { - p->processed = 0; - SubblockEnc_Init(&p->sb); + return SbEnc_Init(&p->enc); } -static SRes SbEncInStream_Read(void *pp, void *data, size_t *size) +void SbEncInStream_Free(CSbEncInStream *p) { - CSbEncInStream *p = (CSbEncInStream *)pp; - SRes res = SubblockEnc_Read(&p->sb, data, size); - p->processed += *size; - return res; + SbEnc_Free(&p->enc); } + #endif + typedef struct { - /* CMixCoderSeqInStream inStream; */ CLzma2EncHandle lzma2; #ifdef USE_SUBBLOCK CSbEncInStream sb; #endif + CSeqInFilter filter; ISzAlloc *alloc; ISzAlloc *bigAlloc; } CLzma2WithFilters; @@ -361,9 +354,9 @@ static void Lzma2WithFilters_Construct(CLzma2WithFilters *p, ISzAlloc *alloc, IS p->bigAlloc = bigAlloc; p->lzma2 = NULL; #ifdef USE_SUBBLOCK - p->sb.p.Read = SbEncInStream_Read; - SubblockEnc_Construct(&p->sb.sb, p->alloc); + SbEncInStream_Construct(&p->sb, alloc); #endif + SeqInFilter_Construct(&p->filter); } static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p) @@ -376,8 +369,9 @@ static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p) static void Lzma2WithFilters_Free(CLzma2WithFilters *p) { + SeqInFilter_Free(&p->filter); #ifdef USE_SUBBLOCK - SubblockEnc_Free(&p->sb.sb); + SbEncInStream_Free(&p->sb); #endif if (p->lzma2) { @@ -386,17 +380,28 @@ static void Lzma2WithFilters_Free(CLzma2WithFilters *p) } } -static SRes Xz_Compress(CXzStream *xz, - CLzma2WithFilters *lzmaf, - ISeqOutStream *outStream, - ISeqInStream *inStream, - const CLzma2EncProps *lzma2Props, - Bool useSubblock, - ICompressProgress *progress) +void XzProps_Init(CXzProps *p) +{ + p->lzma2Props = 0; + p->filterProps = 0; + p->checkId = XZ_CHECK_CRC32; +} + +void XzFilterProps_Init(CXzFilterProps *p) { - xz->flags = XZ_CHECK_CRC32; + p->id = 0; + p->delta = 0; + p->ip= 0; + p->ipDefined = False; +} + +static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf, + ISeqOutStream *outStream, ISeqInStream *inStream, + const CXzProps *props, ICompressProgress *progress) +{ + xz->flags = (Byte)props->checkId; - RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, lzma2Props)); + RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, props->lzma2Props)); RINOK(Xz_WriteHeader(xz->flags, outStream)); { @@ -404,15 +409,27 @@ static SRes Xz_Compress(CXzStream *xz, CSeqSizeOutStream seqSizeOutStream; CXzBlock block; int filterIndex = 0; - + CXzFilter *filter = NULL; + const CXzFilterProps *fp = props->filterProps; + XzBlock_ClearFlags(&block); - XzBlock_SetNumFilters(&block, 1 + (useSubblock ? 1 : 0)); - - if (useSubblock) + XzBlock_SetNumFilters(&block, 1 + (fp ? 1 : 0)); + + if (fp) { - CXzFilter *f = &block.filters[filterIndex++]; - f->id = XZ_ID_Subblock; - f->propsSize = 0; + filter = &block.filters[filterIndex++]; + filter->id = fp->id; + filter->propsSize = 0; + if (fp->id == XZ_ID_Delta) + { + filter->props[0] = (Byte)(fp->delta - 1); + filter->propsSize = 1; + } + else if (fp->ipDefined) + { + SetUi32(filter->props, fp->ip); + filter->propsSize = 4; + } } { @@ -425,27 +442,37 @@ static SRes Xz_Compress(CXzStream *xz, seqSizeOutStream.p.Write = MyWrite; seqSizeOutStream.realStream = outStream; seqSizeOutStream.processed = 0; - + RINOK(XzBlock_WriteHeader(&block, &seqSizeOutStream.p)); - + checkInStream.p.Read = SeqCheckInStream_Read; checkInStream.realStream = inStream; SeqCheckInStream_Init(&checkInStream, XzFlags_GetCheckType(xz->flags)); - - #ifdef USE_SUBBLOCK - if (useSubblock) + + if (fp) { - lzmaf->sb.sb.inStream = &checkInStream.p; - SubblockEnc_Init(&lzmaf->sb.sb); + #ifdef USE_SUBBLOCK + if (fp->id == XZ_ID_Subblock) + { + lzmaf->sb.inStream = &checkInStream.p; + RINOK(SbEncInStream_Init(&lzmaf->sb)); + } + else + #endif + { + lzmaf->filter.realStream = &checkInStream.p; + RINOK(SeqInFilter_Init(&lzmaf->filter, filter)); + } } - #endif - + { UInt64 packPos = seqSizeOutStream.processed; SRes res = Lzma2Enc_Encode(lzmaf->lzma2, &seqSizeOutStream.p, + fp ? #ifdef USE_SUBBLOCK - useSubblock ? &lzmaf->sb.p: + (fp->id == XZ_ID_Subblock) ? &lzmaf->sb.p: #endif + &lzmaf->filter.p: &checkInStream.p, progress); RINOK(res); @@ -467,8 +494,7 @@ static SRes Xz_Compress(CXzStream *xz, } SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream, - const CLzma2EncProps *lzma2Props, Bool useSubblock, - ICompressProgress *progress) + const CXzProps *props, ICompressProgress *progress) { SRes res; CXzStream xz; @@ -477,8 +503,7 @@ SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream, Lzma2WithFilters_Construct(&lzmaf, &g_Alloc, &g_BigAlloc); res = Lzma2WithFilters_Create(&lzmaf); if (res == SZ_OK) - res = Xz_Compress(&xz, &lzmaf, outStream, inStream, - lzma2Props, useSubblock, progress); + res = Xz_Compress(&xz, &lzmaf, outStream, inStream, props, progress); Lzma2WithFilters_Free(&lzmaf); Xz_Free(&xz, &g_Alloc); return res; diff --git a/src/libs/7zip/win/C/XzEnc.h b/src/libs/7zip/win/C/XzEnc.h index 13390df8b..c3c19eca0 100644 --- a/src/libs/7zip/win/C/XzEnc.h +++ b/src/libs/7zip/win/C/XzEnc.h @@ -1,5 +1,5 @@ /* XzEnc.h -- Xz Encode -2009-04-15 : Igor Pavlov : Public domain */ +2011-02-07 : Igor Pavlov : Public domain */ #ifndef __XZ_ENC_H #define __XZ_ENC_H @@ -8,18 +8,32 @@ #include "Xz.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN + +typedef struct +{ + UInt32 id; + UInt32 delta; + UInt32 ip; + int ipDefined; +} CXzFilterProps; + +void XzFilterProps_Init(CXzFilterProps *p); + +typedef struct +{ + const CLzma2EncProps *lzma2Props; + const CXzFilterProps *filterProps; + unsigned checkId; +} CXzProps; + +void XzProps_Init(CXzProps *p); SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream, - const CLzma2EncProps *lzma2Props, Bool useSubblock, - ICompressProgress *progress); + const CXzProps *props, ICompressProgress *progress); SRes Xz_EncodeEmpty(ISeqOutStream *outStream); -#ifdef __cplusplus -} -#endif +EXTERN_C_END #endif diff --git a/src/libs/7zip/win/C/XzIn.c b/src/libs/7zip/win/C/XzIn.c index 7f0f6af8d..ed9eac31a 100644 --- a/src/libs/7zip/win/C/XzIn.c +++ b/src/libs/7zip/win/C/XzIn.c @@ -1,5 +1,7 @@ /* XzIn.c - Xz input -2009-06-19 : Igor Pavlov : Public domain */ +2014-12-30 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include @@ -70,7 +72,7 @@ SRes XzBlock_ReadFooter(CXzBlock *p, CXzStreamFlags f, ISeqInStream *inStream) static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAlloc *alloc) { - size_t i, numBlocks, crcStartPos, pos = 1; + size_t i, numBlocks, pos = 1; UInt32 crc; if (size < 5 || buf[0] != 0) @@ -88,8 +90,7 @@ static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAlloc * if (numBlocks != numBlocks64 || numBlocks * 2 > size) return SZ_ERROR_ARCHIVE; } - - crcStartPos = pos; + Xz_Free(p, alloc); if (numBlocks != 0) { @@ -149,44 +150,43 @@ static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOff RINOK(SeekFromCur(stream, startOffset)); RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE)); - + if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0) { - Int64 i = 0; + UInt32 total = 0; *startOffset += XZ_STREAM_FOOTER_SIZE; for (;;) { - int j; - size_t processedSize; + size_t i; #define TEMP_BUF_SIZE (1 << 10) Byte tempBuf[TEMP_BUF_SIZE]; - if (*startOffset < XZ_STREAM_FOOTER_SIZE || i > (1 << 16)) + if (*startOffset < XZ_STREAM_FOOTER_SIZE || total > (1 << 16)) return SZ_ERROR_NO_ARCHIVE; - processedSize = (*startOffset > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)*startOffset; - i += processedSize; - *startOffset = -(Int64)processedSize; + i = (*startOffset > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)*startOffset; + total += (UInt32)i; + *startOffset = -(Int64)i; RINOK(SeekFromCur(stream, startOffset)); - RINOK(LookInStream_Read2(stream, tempBuf, processedSize, SZ_ERROR_NO_ARCHIVE)); - for (j = (int)processedSize; j >= 0; j--) - if (tempBuf[j -1] != 0) + RINOK(LookInStream_Read2(stream, tempBuf, i, SZ_ERROR_NO_ARCHIVE)); + for (; i != 0; i--) + if (tempBuf[i - 1] != 0) break; - if (j != 0) + if (i != 0) { - if ((j & 3) != 0) - return SZ_ERROR_NO_ARCHIVE; - *startOffset += j; - if (*startOffset < XZ_STREAM_FOOTER_SIZE) - return SZ_ERROR_NO_ARCHIVE; - *startOffset -= XZ_STREAM_FOOTER_SIZE; - RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET)); - RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE)); - if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0) + if ((i & 3) != 0) return SZ_ERROR_NO_ARCHIVE; + *startOffset += i; break; } } + if (*startOffset < XZ_STREAM_FOOTER_SIZE) + return SZ_ERROR_NO_ARCHIVE; + *startOffset -= XZ_STREAM_FOOTER_SIZE; + RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET)); + RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE)); + if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0) + return SZ_ERROR_NO_ARCHIVE; } - + p->flags = (CXzStreamFlags)GetBe16(buf + 8); if (!XzFlags_IsSupported(p->flags)) @@ -291,7 +291,8 @@ SRes Xzs_ReadBackward(CXzs *p, ILookInStream *stream, Int64 *startOffset, ICompr if (data == 0) return SZ_ERROR_MEM; p->numAllocated = newNum; - memcpy(data, p->streams, p->num * sizeof(CXzStream)); + if (p->num != 0) + memcpy(data, p->streams, p->num * sizeof(CXzStream)); alloc->Free(alloc, p->streams); p->streams = (CXzStream *)data; } diff --git a/src/libs/7zip/win/CPP/7zip/7zip.pri b/src/libs/7zip/win/CPP/7zip/7zip.pri new file mode 100644 index 000000000..a2b70a1f2 --- /dev/null +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7z.pri b/src/libs/7zip/win/CPP/7zip/Archive/7z/7z.pri new file mode 100644 index 000000000..7763cf705 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/7z/7z.pri @@ -0,0 +1,30 @@ +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 \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/StdAfx.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/win/CPP/7zip/Archive/7z/7zCompressionMode.cpp b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zCompressionMode.cpp deleted file mode 100644 index 6774fc482..000000000 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zCompressionMode.cpp +++ /dev/null @@ -1,3 +0,0 @@ -// CompressionMethod.cpp - -#include "StdAfx.h" diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zCompressionMode.h b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zCompressionMode.h index 55bbc68ee..5cde97c38 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zCompressionMode.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zDecode.cpp b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zDecode.cpp index 425a34157..973966bd3 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zDecode.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zDecode.h b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zDecode.h index d8a424a36..54e9d2b52 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zDecode.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zEncode.cpp b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zEncode.cpp index 87996bc0e..5f1436fc7 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zEncode.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zEncode.h b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zEncode.h index 4909a6e89..8e20bdb5f 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zEncode.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zExtract.cpp b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zExtract.cpp index d55f38e13..bb350455c 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zExtract.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zFolderInStream.cpp b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zFolderInStream.cpp index edd276bc1..3f420a513 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zFolderInStream.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zFolderInStream.h b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zFolderInStream.h index 6df3672a1..4ed4b2dd2 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zFolderInStream.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zFolderOutStream.cpp b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zFolderOutStream.cpp index 22c4600ec..847f65bf2 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zFolderOutStream.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zFolderOutStream.h b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zFolderOutStream.h index f9bb1af42..cc2d77343 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zFolderOutStream.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zHandler.cpp b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zHandler.cpp index 4ab7afa87..ed65dc20c 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zHandler.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zHandler.h b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zHandler.h index 56062d464..677a3e10a 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zHandler.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zHandlerOut.cpp index a8ccab6df..7de5b8140 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zHandlerOut.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zHeader.cpp b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zHeader.cpp index 5b5f2fb37..acff2fdd8 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zHeader.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zHeader.h b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zHeader.h index 30622b90e..61dad655d 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zHeader.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zIn.cpp b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.cpp index 0feb81d2c..28ec5e083 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zIn.h b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.h index 971f27b2a..98f61c81e 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zItem.h b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zItem.h index 34f10775c..c112f83fd 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zItem.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zOut.cpp b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zOut.cpp index 0c8aa7e8c..e20858ea7 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zOut.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zOut.h b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zOut.h index 7b1b528e6..391ca9d02 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zOut.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zProperties.cpp b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zProperties.cpp index fd4af49c7..a29f8abe9 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zProperties.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zRegister.cpp b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zRegister.cpp index 6e9bf6b99..37ea29d30 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zRegister.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zSpecStream.cpp b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zSpecStream.cpp index 06969636d..8e45d9875 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zSpecStream.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/7zUpdate.cpp b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zUpdate.cpp index ee7f55c04..26faf2a18 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zUpdate.cpp +++ b/src/libs/7zip/win/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" @@ -24,15 +25,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 @@ -67,19 +59,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(); @@ -119,11 +112,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); } */ @@ -134,15 +128,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( @@ -156,25 +154,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 = @@ -207,7 +211,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; @@ -246,7 +250,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), @@ -257,64 +263,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 @@ -322,124 +398,109 @@ struct CSolidGroup CRecordVector Indices; }; -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; } -#ifdef USE_86_FILTER -static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult) +static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &m) { - methodResult.Id = methodID; - methodResult.NumInStreams = numInStreams; - methodResult.NumOutStreams = 1; + m.Id = methodID; + m.NumInStreams = numInStreams; + m.NumOutStreams = 1; } -static void MakeExeMethod(const CCompressionMethodMode &method, - bool bcj2Filter, CCompressionMethodMode &exeMethod) +static void AddBcj2Methods(CCompressionMethodMode &mode) { - exeMethod = method; + 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(CCompressionMethodMode &mode, + bool useFilters, bool addFilter, bool bcj2Filter) +{ + if (!mode.Binds.IsEmpty() || !useFilters || mode.Methods.Size() > 2) + return; + if (mode.Methods.Size() == 2) + { + if (mode.Methods[0].Id == k_BCJ2) + AddBcj2Methods(mode); + return; + } + if (!addFilter) + return; + bcj2Filter = bcj2Filter; + #ifdef USE_86_FILTER if (bcj2Filter) { - CMethodFull 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: @@ -448,11 +509,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; @@ -462,14 +523,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; } @@ -477,7 +538,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; @@ -576,13 +637,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 @@ -601,6 +662,7 @@ public: Fos = FosSpec; Result = E_FAIL; } + ~CThreadDecoder() { CVirtThread::WaitThreadFinish(); } virtual void Execute(); }; @@ -609,21 +671,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 ); } @@ -638,7 +699,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) @@ -669,20 +730,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 @@ -694,6 +766,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)); @@ -701,23 +776,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++) { @@ -726,7 +801,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; @@ -753,7 +828,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); @@ -772,7 +848,7 @@ HRESULT Update( } UInt64 inSizeForReduce = 0; - int i; + unsigned i; for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; @@ -789,32 +865,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; @@ -830,7 +904,7 @@ HRESULT Update( { int dotPos = ui.Name.ReverseFind(L'.'); if (dotPos >= 0) - filteredGroup = IsExeExt(ui.Name.Mid(dotPos + 1)); + filteredGroup = IsExeExt(ui.Name.Ptr(dotPos + 1)); } groups[GetGroupIndex(method.PasswordIsDefined, filteredGroup)].Indices.Add(i); } @@ -842,7 +916,7 @@ HRESULT Update( if (needEncryptedRepack) { getPasswordSpec = new CCryptoGetTextPassword; - threadDecoder.GetTextPassword = getPasswordSpec; + threadDecoder.getTextPassword = getPasswordSpec; if (options.Method->PasswordIsDefined) getPasswordSpec->Password = options.Method->Password; @@ -852,31 +926,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)) { @@ -903,36 +1065,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; @@ -946,44 +1108,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++; @@ -1002,30 +1172,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; @@ -1038,7 +1218,7 @@ HRESULT Update( newDatabase.Files.Add(file); */ } - + for (i = 0; i < numFiles;) { UInt64 totalSize = 0; @@ -1057,7 +1237,7 @@ HRESULT Update( if (numSubFiles == 0) prevExtension = ext; else - if (ext.CompareNoCase(prevExtension) != 0) + if (!ext.IsEqualToNoCase(prevExtension)) break; } } @@ -1067,38 +1247,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]; @@ -1122,7 +1307,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. @@ -1134,42 +1326,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/win/CPP/7zip/Archive/7z/7zUpdate.h b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zUpdate.h index 31e362246..aee2d5ed3 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zUpdate.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/7z/StdAfx.cpp b/src/libs/7zip/win/CPP/7zip/Archive/7z/StdAfx.cpp deleted file mode 100644 index d0feea85c..000000000 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/StdAfx.cpp +++ /dev/null @@ -1,3 +0,0 @@ -// StdAfx.cpp - -#include "StdAfx.h" diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/StdAfx.h b/src/libs/7zip/win/CPP/7zip/Archive/7z/StdAfx.h index 2e4be10b2..2854ff3e9 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/StdAfx.h +++ b/src/libs/7zip/win/CPP/7zip/Archive/7z/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" -#include "../../../Common/NewHandler.h" +#include "../../../Common/Common.h" #endif diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Archive.def b/src/libs/7zip/win/CPP/7zip/Archive/Archive.def deleted file mode 100644 index 55b530b2d..000000000 --- a/src/libs/7zip/win/CPP/7zip/Archive/Archive.def +++ /dev/null @@ -1,6 +0,0 @@ -EXPORTS - CreateObject PRIVATE - GetHandlerProperty PRIVATE - GetNumberOfFormats PRIVATE - GetHandlerProperty2 PRIVATE - CreateObject PRIVATE diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Archive.pri b/src/libs/7zip/win/CPP/7zip/Archive/Archive.pri new file mode 100644 index 000000000..e8a1c7832 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Archive.pri @@ -0,0 +1,6 @@ +HEADERS += $$7ZIP_BASE/CPP/7zip/Archive/IArchive.h \ + $$7ZIP_BASE/CPP/7zip/Archive/StdAfx.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/win/CPP/7zip/Archive/Archive2.def b/src/libs/7zip/win/CPP/7zip/Archive/Archive2.def deleted file mode 100644 index 885d39d14..000000000 --- a/src/libs/7zip/win/CPP/7zip/Archive/Archive2.def +++ /dev/null @@ -1,9 +0,0 @@ -EXPORTS - CreateObject PRIVATE - GetHandlerProperty PRIVATE - GetNumberOfFormats PRIVATE - GetHandlerProperty2 PRIVATE - CreateObject PRIVATE - GetNumberOfMethods PRIVATE - GetMethodProperty PRIVATE - SetLargePageMode PRIVATE diff --git a/src/libs/7zip/win/CPP/7zip/Archive/ArchiveExports.cpp b/src/libs/7zip/win/CPP/7zip/Archive/ArchiveExports.cpp deleted file mode 100644 index c7908b591..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/Archive/Common/CoderMixer2.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2.cpp index 0b06a489f..e562fec58 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/Common/CoderMixer2.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2.h index a03722d61..50e7077ae 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2MT.cpp index d76450bd1..36b252600 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2MT.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/Common/CoderMixer2MT.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2MT.h index d1c7f4d07..2190cf867 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2MT.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/Common/Common.pri b/src/libs/7zip/win/CPP/7zip/Archive/Common/Common.pri new file mode 100644 index 000000000..e808619d3 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/Common.pri @@ -0,0 +1,19 @@ +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 \ + $$7ZIP_BASE/CPP/7zip/Archive/Common/StdAfx.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/win/CPP/7zip/Archive/Common/CrossThreadProgress.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/CrossThreadProgress.cpp deleted file mode 100644 index a974b54c7..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/Archive/Common/CrossThreadProgress.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/CrossThreadProgress.h deleted file mode 100644 index 7e0b10538..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/Archive/Common/DummyOutStream.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/DummyOutStream.cpp index 54bcfec11..7c4f54879 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/Common/DummyOutStream.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/Common/DummyOutStream.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/DummyOutStream.h index 13d5b62ca..b5a51fc07 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/Common/DummyOutStream.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/Common/HandlerOut.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/HandlerOut.cpp index 70ad47aad..7b875fbd0 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/Common/HandlerOut.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/Common/HandlerOut.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/HandlerOut.h index 72ea40321..eba2a19e1 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/Common/HandlerOut.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/Common/InStreamWithCRC.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/InStreamWithCRC.cpp index 569a56f3b..a2d688328 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/Common/InStreamWithCRC.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/ItemNameUtils.cpp index a5e0dc0be..7cd3037be 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/Common/ItemNameUtils.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/Common/ItemNameUtils.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/ItemNameUtils.h index 5eafacb12..d0dc76a41 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/Common/ItemNameUtils.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/Common/MultiStream.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/MultiStream.cpp index 04d11cafb..17f749058 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/Common/MultiStream.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/Common/MultiStream.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/MultiStream.h index 3fceb7cce..93aff33bf 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/Common/MultiStream.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/Common/OutStreamWithCRC.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/OutStreamWithCRC.h index 115b442aa..09b899bbd 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/Common/OutStreamWithCRC.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/Common/ParseProperties.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/ParseProperties.cpp deleted file mode 100644 index 5cd849e29..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/Archive/Common/ParseProperties.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/ParseProperties.h index 6f80f6344..1038a8c02 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/Common/ParseProperties.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/Common/StdAfx.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/StdAfx.h index 2e4be10b2..2854ff3e9 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/Common/StdAfx.h +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" -#include "../../../Common/NewHandler.h" +#include "../../../Common/Common.h" #endif diff --git a/src/libs/7zip/win/CPP/7zip/Archive/DllExports2.cpp b/src/libs/7zip/win/CPP/7zip/Archive/DllExports2.cpp deleted file mode 100644 index ad14ff06a..000000000 --- a/src/libs/7zip/win/CPP/7zip/Archive/DllExports2.cpp +++ /dev/null @@ -1,74 +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; - -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; -} - -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/win/CPP/7zip/Archive/IArchive.h b/src/libs/7zip/win/CPP/7zip/Archive/IArchive.h index 853202767..a15a97f16 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/IArchive.h +++ b/src/libs/7zip/win/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,32 @@ 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 HRESULT (WINAPI *Func_CreateObject)(const GUID *clsID, const GUID *iid, void **outObject); + + typedef UInt32 (WINAPI *Func_IsArc)(const Byte *p, size_t size); + typedef HRESULT (WINAPI *Func_GetIsArc)(UInt32 formatIndex, Func_IsArc *isArc); + + typedef HRESULT (WINAPI *Func_GetNumberOfFormats)(UInt32 *numFormats); + typedef HRESULT (WINAPI *Func_GetHandlerProperty)(PROPID propID, PROPVARIANT *value); + typedef HRESULT (WINAPI *Func_GetHandlerProperty2)(UInt32 index, PROPID propID, PROPVARIANT *value); + + typedef HRESULT (WINAPI *Func_SetCaseSensitive)(Int32 caseSensitive); + typedef HRESULT (WINAPI *Func_SetLargePageMode)(); + + typedef IOutArchive * (*Func_CreateOutArchive)(); + typedef IInArchive * (*Func_CreateInArchive)(); +} + #endif diff --git a/src/libs/7zip/win/CPP/7zip/Archive/LzmaHandler.cpp b/src/libs/7zip/win/CPP/7zip/Archive/LzmaHandler.cpp index a83e6a1ad..279cdefb7 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/LzmaHandler.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/SplitHandler.cpp b/src/libs/7zip/win/CPP/7zip/Archive/SplitHandler.cpp index 5d84de4ed..db9f49aa0 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/SplitHandler.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Archive/StdAfx.h b/src/libs/7zip/win/CPP/7zip/Archive/StdAfx.h index ef555ec12..1cbd7feae 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/StdAfx.h +++ b/src/libs/7zip/win/CPP/7zip/Archive/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../Common/MyWindows.h" -#include "../../Common/NewHandler.h" +#include "../../Common/Common.h" #endif diff --git a/src/libs/7zip/win/CPP/7zip/Archive/XzHandler.cpp b/src/libs/7zip/win/CPP/7zip/Archive/XzHandler.cpp index 64b7a5863..789f41a72 100644 --- a/src/libs/7zip/win/CPP/7zip/Archive/XzHandler.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/CWrappers.cpp b/src/libs/7zip/win/CPP/7zip/Common/CWrappers.cpp index 358f0b503..a15794e2a 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/CWrappers.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/CWrappers.h b/src/libs/7zip/win/CPP/7zip/Common/CWrappers.h index 80a8a1b61..4fe7dea3e 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/CWrappers.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/Common.pri b/src/libs/7zip/win/CPP/7zip/Common/Common.pri new file mode 100644 index 000000000..e6b054a24 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Common/Common.pri @@ -0,0 +1,40 @@ +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/StdAfx.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/win/CPP/7zip/Common/CreateCoder.cpp b/src/libs/7zip/win/CPP/7zip/Common/CreateCoder.cpp index cc82a0db5..01ccbe12a 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/CreateCoder.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/CreateCoder.h b/src/libs/7zip/win/CPP/7zip/Common/CreateCoder.h index bf0e96a38..fe1f6ccfe 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/CreateCoder.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/FilePathAutoRename.cpp b/src/libs/7zip/win/CPP/7zip/Common/FilePathAutoRename.cpp index 7d6e36f14..958360fac 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/FilePathAutoRename.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/FilePathAutoRename.h b/src/libs/7zip/win/CPP/7zip/Common/FilePathAutoRename.h index 3ef87f482..7b576591c 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/FilePathAutoRename.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/FileStreams.cpp b/src/libs/7zip/win/CPP/7zip/Common/FileStreams.cpp index 426a0d3d6..77e5463e6 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/FileStreams.cpp +++ b/src/libs/7zip/win/CPP/7zip/Common/FileStreams.cpp @@ -29,42 +29,15 @@ static inline HRESULT ConvertBoolToHRESULT(bool result) #endif } -bool CInFileStream::Open(LPCTSTR fileName) -{ - return File.Open(fileName); -} - -#ifdef USE_WIN_FILE -#ifndef _UNICODE -bool CInFileStream::Open(LPCWSTR fileName) -{ - return File.Open(fileName); -} -#endif -#endif - -bool CInFileStream::OpenShared(LPCTSTR fileName, bool shareForWrite) -{ - return File.OpenShared(fileName, shareForWrite); -} - -#ifdef USE_WIN_FILE -#ifndef _UNICODE -bool CInFileStream::OpenShared(LPCWSTR fileName, bool shareForWrite) -{ - return File.OpenShared(fileName, shareForWrite); -} -#endif -#endif - #ifdef SUPPORT_DEVICE_FILE static const UInt32 kClusterSize = 1 << 18; CInFileStream::CInFileStream(): VirtPos(0), PhyPos(0), - Buffer(0), - BufferSize(0) + Buf(0), + BufSize(0), + SupportHardLinks(false) { } @@ -73,50 +46,50 @@ CInFileStream::CInFileStream(): CInFileStream::~CInFileStream() { #ifdef SUPPORT_DEVICE_FILE - MidFree(Buffer); + MidFree(Buf); #endif } STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef USE_WIN_FILE - + #ifdef SUPPORT_DEVICE_FILE - if (processedSize != NULL) + if (processedSize) *processedSize = 0; if (size == 0) return S_OK; if (File.IsDeviceFile) { - if (File.LengthDefined) + if (File.SizeDefined) { - if (VirtPos >= File.Length) - return VirtPos == File.Length ? S_OK : E_FAIL; - UInt64 rem = File.Length - VirtPos; + 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; - UInt64 mask2 = ~(UInt64)mask; + const UInt64 mask2 = ~(UInt64)mask; UInt64 alignedPos = VirtPos & mask2; - if (BufferSize > 0 && BufferStartPos == alignedPos) + if (BufSize > 0 && BufStartPos == alignedPos) { UInt32 pos = (UInt32)VirtPos & mask; - if (pos >= BufferSize) + if (pos >= BufSize) return S_OK; - UInt32 rem = MyMin(BufferSize - pos, size); - memcpy(data, Buffer + pos, rem); + UInt32 rem = MyMin(BufSize - pos, size); + memcpy(data, Buf + pos, rem); VirtPos += rem; - if (processedSize != NULL) + if (processedSize) *processedSize += rem; return S_OK; } - - bool useBuffer = false; + + bool useBuf = false; if ((VirtPos & mask) != 0 || ((ptrdiff_t)data & mask) != 0 ) - useBuffer = true; + useBuf = true; else { UInt64 end = VirtPos + size; @@ -124,12 +97,12 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { end &= mask2; if (end <= VirtPos) - useBuffer = true; + useBuf = true; else size = (UInt32)(end - VirtPos); } } - if (!useBuffer) + if (!useBuf) break; if (alignedPos != PhyPos) { @@ -140,24 +113,24 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) PhyPos = realNewPosition; } - BufferStartPos = alignedPos; + BufStartPos = alignedPos; UInt32 readSize = kClusterSize; - if (File.LengthDefined) - readSize = (UInt32)MyMin(File.Length - PhyPos, (UInt64)kClusterSize); + if (File.SizeDefined) + readSize = (UInt32)MyMin(File.Size - PhyPos, (UInt64)kClusterSize); - if (Buffer == 0) + if (!Buf) { - Buffer = (Byte *)MidAlloc(kClusterSize); - if (Buffer == 0) + Buf = (Byte *)MidAlloc(kClusterSize); + if (!Buf) return E_OUTOFMEMORY; } - bool result = File.Read1(Buffer, readSize, BufferSize); + bool result = File.Read1(Buf, readSize, BufSize); if (!result) return ConvertBoolToHRESULT(result); - if (BufferSize == 0) + if (BufSize == 0) return S_OK; - PhyPos += BufferSize; + PhyPos += BufSize; } if (VirtPos != PhyPos) @@ -173,22 +146,22 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) 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; @@ -198,30 +171,33 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) #ifdef UNDER_CE STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { - size_t s2 = fread(data, 1, size, stdout); - if (processedSize != 0) + size_t s2 = fread(data, 1, size, stdin); + int error = ferror(stdin); + if (processedSize) *processedSize = s2; - return (s2 = size) ? S_OK : E_FAIL; + if (s2 <= size && error == 0) + return S_OK; + return E_FAIL; } #else STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 - + DWORD realProcessedSize; UInt32 sizeTemp = (1 << 20); if (sizeTemp > size) sizeTemp = size; BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, sizeTemp, &realProcessedSize, NULL); - if (processedSize != NULL) + 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 @@ -231,17 +207,16 @@ 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) return STG_E_INVALIDFUNCTION; @@ -249,43 +224,44 @@ STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, #ifdef USE_WIN_FILE #ifdef SUPPORT_DEVICE_FILE - if (File.IsDeviceFile) + if (File.IsDeviceFile && (File.SizeDefined || seekOrigin != STREAM_SEEK_END)) { - UInt64 newVirtPos = offset; - switch(seekOrigin) + switch (seekOrigin) { case STREAM_SEEK_SET: break; - case STREAM_SEEK_CUR: newVirtPos += VirtPos; break; - case STREAM_SEEK_END: newVirtPos += File.Length; break; + case STREAM_SEEK_CUR: offset += VirtPos; break; + case STREAM_SEEK_END: offset += File.Size; break; default: return STG_E_INVALIDFUNCTION; } - VirtPos = newVirtPos; + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + VirtPos = offset; if (newPosition) - *newPosition = newVirtPos; + *newPosition = offset; return S_OK; } #endif - + UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); - + #ifdef SUPPORT_DEVICE_FILE PhyPos = VirtPos = realNewPosition; #endif - 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 } @@ -294,6 +270,43 @@ STDMETHODIMP CInFileStream::GetSize(UInt64 *size) return ConvertBoolToHRESULT(File.GetLength(*size)); } +#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 @@ -310,25 +323,25 @@ 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) @@ -337,19 +350,19 @@ STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo 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 } @@ -372,14 +385,14 @@ STDMETHODIMP COutFileStream::SetSize(UInt64 newSize) STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { size_t s2 = fwrite(data, 1, size, stdout); - if (processedSize != 0) + if (processedSize) *processedSize = s2; - return (s2 = size) ? S_OK : E_FAIL; + 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 @@ -396,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 { @@ -411,10 +424,10 @@ 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 } diff --git a/src/libs/7zip/win/CPP/7zip/Common/FileStreams.h b/src/libs/7zip/win/CPP/7zip/Common/FileStreams.h index 895745d36..cce71e582 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/FileStreams.h +++ b/src/libs/7zip/win/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 #ifdef _WIN32 #define USE_WIN_FILE #endif +#include "../../Common/MyString.h" + #ifdef USE_WIN_FILE #include "../../Windows/FileIO.h" #else @@ -20,47 +22,63 @@ class CInFileStream: public IInStream, public IStreamGetSize, + #ifdef USE_WIN_FILE + public IStreamGetProps, + public IStreamGetProps2, + #endif public CMyUnknownImp { public: #ifdef USE_WIN_FILE NWindows::NFile::NIO::CInFile File; + #ifdef SUPPORT_DEVICE_FILE UInt64 VirtPos; UInt64 PhyPos; - UInt64 BufferStartPos; - Byte *Buffer; - UInt32 BufferSize; + UInt64 BufStartPos; + Byte *Buf; + UInt32 BufSize; #endif + #else NC::NFile::NIO::CInFile File; #endif + + bool SupportHardLinks; + virtual ~CInFileStream(); #ifdef SUPPORT_DEVICE_FILE CInFileStream(); #endif - - bool Open(LPCTSTR fileName); - #ifdef USE_WIN_FILE - #ifndef _UNICODE - bool Open(LPCWSTR fileName); - #endif - #endif - bool OpenShared(LPCTSTR fileName, bool shareForWrite); + bool Open(CFSTR fileName) + { + return File.Open(fileName); + } + + bool OpenShared(CFSTR fileName, bool shareForWrite) + { + return File.OpenShared(fileName, shareForWrite); + } + + MY_QUERYINTERFACE_BEGIN2(IInStream) + MY_QUERYINTERFACE_ENTRY(IStreamGetSize) #ifdef USE_WIN_FILE - #ifndef _UNICODE - bool OpenShared(LPCWSTR fileName, bool shareForWrite); - #endif + MY_QUERYINTERFACE_ENTRY(IStreamGetProps) + MY_QUERYINTERFACE_ENTRY(IStreamGetProps2) #endif - - MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) + 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); + #ifdef USE_WIN_FILE + STDMETHOD(GetProps)(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib); + STDMETHOD(GetProps2)(CStreamFileProps *props); + #endif }; class CStdInFileStream: @@ -78,40 +96,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/win/CPP/7zip/Common/FilterCoder.cpp b/src/libs/7zip/win/CPP/7zip/Common/FilterCoder.cpp index 696735278..3a2023b35 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/FilterCoder.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/FilterCoder.h b/src/libs/7zip/win/CPP/7zip/Common/FilterCoder.h index 8132a6dd7..2b8f142f5 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/FilterCoder.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/InBuffer.cpp b/src/libs/7zip/win/CPP/7zip/Common/InBuffer.cpp index ad4f8825e..133d95b38 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/InBuffer.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/InBuffer.h b/src/libs/7zip/win/CPP/7zip/Common/InBuffer.h index 75625bfd9..dd3c66808 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/InBuffer.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/InOutTempBuffer.cpp b/src/libs/7zip/win/CPP/7zip/Common/InOutTempBuffer.cpp index dfe8b3d32..be65ba32f 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/InOutTempBuffer.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/InOutTempBuffer.h b/src/libs/7zip/win/CPP/7zip/Common/InOutTempBuffer.h index 073f95acf..256d72420 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/InOutTempBuffer.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/LimitedStreams.cpp b/src/libs/7zip/win/CPP/7zip/Common/LimitedStreams.cpp index 1837e3201..5f20dcda4 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/LimitedStreams.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/LimitedStreams.h b/src/libs/7zip/win/CPP/7zip/Common/LimitedStreams.h index 2cbe18e48..b14616f3b 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/LimitedStreams.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/MethodId.cpp b/src/libs/7zip/win/CPP/7zip/Common/MethodId.cpp deleted file mode 100644 index b797b6857..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/Common/MethodId.h b/src/libs/7zip/win/CPP/7zip/Common/MethodId.h index 54ebc9f7d..28b615fcd 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/MethodId.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/MethodProps.cpp b/src/libs/7zip/win/CPP/7zip/Common/MethodProps.cpp index 5836d0f84..ff61995b7 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/MethodProps.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/MethodProps.h b/src/libs/7zip/win/CPP/7zip/Common/MethodProps.h index 8127e21ee..39e2ee937 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/MethodProps.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/OffsetStream.cpp b/src/libs/7zip/win/CPP/7zip/Common/OffsetStream.cpp deleted file mode 100644 index c5e4e6da4..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/Common/OffsetStream.h b/src/libs/7zip/win/CPP/7zip/Common/OffsetStream.h deleted file mode 100644 index de9d06dd0..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/Common/OutBuffer.cpp b/src/libs/7zip/win/CPP/7zip/Common/OutBuffer.cpp index 2e5debd83..4ba34a053 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/OutBuffer.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/OutBuffer.h b/src/libs/7zip/win/CPP/7zip/Common/OutBuffer.h index 62e77caae..0baad3636 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/OutBuffer.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/ProgressUtils.cpp b/src/libs/7zip/win/CPP/7zip/Common/ProgressUtils.cpp index f24ff6b6f..bac45c1c2 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/ProgressUtils.cpp +++ b/src/libs/7zip/win/CPP/7zip/Common/ProgressUtils.cpp @@ -1,4 +1,4 @@ -// ProgressUtils.h +// ProgressUtils.cpp #include "StdAfx.h" diff --git a/src/libs/7zip/win/CPP/7zip/Common/PropId.cpp b/src/libs/7zip/win/CPP/7zip/Common/PropId.cpp new file mode 100644 index 000000000..10daef715 --- /dev/null +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/RegisterArc.h b/src/libs/7zip/win/CPP/7zip/Common/RegisterArc.h index 9b8cbd39d..82bd09673 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/RegisterArc.h +++ b/src/libs/7zip/win/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[16]; - 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/win/CPP/7zip/Common/RegisterCodec.h b/src/libs/7zip/win/CPP/7zip/Common/RegisterCodec.h index d53c4344a..0c6662a6c 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/RegisterCodec.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/StdAfx.h b/src/libs/7zip/win/CPP/7zip/Common/StdAfx.h index ef555ec12..1cbd7feae 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/StdAfx.h +++ b/src/libs/7zip/win/CPP/7zip/Common/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../Common/MyWindows.h" -#include "../../Common/NewHandler.h" +#include "../../Common/Common.h" #endif diff --git a/src/libs/7zip/win/CPP/7zip/Common/StreamBinder.cpp b/src/libs/7zip/win/CPP/7zip/Common/StreamBinder.cpp index 03f886258..7a4c0ed26 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/StreamBinder.cpp +++ b/src/libs/7zip/win/CPP/7zip/Common/StreamBinder.cpp @@ -2,149 +2,125 @@ #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() { - RINOK(_allBytesAreWritenEvent.Create(true)); - RINOK(_thereAreBytesToReadEvent.Create()); - return _readStreamIsClosedEvent.Create(); + RINOK(_canWrite_Event.Create(true)); + RINOK(_canRead_Event.Create()); + return _readingWasClosed_Event.Create(); } 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/win/CPP/7zip/Common/StreamBinder.h b/src/libs/7zip/win/CPP/7zip/Common/StreamBinder.h index 48f68e60f..f3fb53228 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/StreamBinder.h +++ b/src/libs/7zip/win/CPP/7zip/Common/StreamBinder.h @@ -1,32 +1,34 @@ // 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::CManualResetEvent _allBytesAreWritenEvent; - NWindows::NSynchronization::CManualResetEvent _thereAreBytesToReadEvent; - NWindows::NSynchronization::CManualResetEvent _readStreamIsClosedEvent; - UInt32 _bufferSize; - const void *_buffer; + NWindows::NSynchronization::CManualResetEvent _canWrite_Event; + NWindows::NSynchronization::CManualResetEvent _canRead_Event; + NWindows::NSynchronization::CManualResetEvent _readingWasClosed_Event; + bool _waitWrite; + UInt32 _bufSize; + const void *_buf; public: - // bool ReadingWasClosed; UInt64 ProcessedSize; - CStreamBinder() {} - 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/win/CPP/7zip/Common/StreamObjects.cpp b/src/libs/7zip/win/CPP/7zip/Common/StreamObjects.cpp index 3c86c3aeb..7721c3a7e 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/StreamObjects.cpp +++ b/src/libs/7zip/win/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(dest, _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/win/CPP/7zip/Common/StreamObjects.h b/src/libs/7zip/win/CPP/7zip/Common/StreamObjects.h index 5c8b5e51b..d0c86b566 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/StreamObjects.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/StreamUtils.cpp b/src/libs/7zip/win/CPP/7zip/Common/StreamUtils.cpp index 049e4aa17..1402f4205 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/StreamUtils.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/StreamUtils.h b/src/libs/7zip/win/CPP/7zip/Common/StreamUtils.h index f1cfd1848..ae914c004 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/StreamUtils.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/UniqBlocks.cpp b/src/libs/7zip/win/CPP/7zip/Common/UniqBlocks.cpp new file mode 100644 index 000000000..7fcc88f5e --- /dev/null +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/UniqBlocks.h b/src/libs/7zip/win/CPP/7zip/Common/UniqBlocks.h new file mode 100644 index 000000000..9c08b09f4 --- /dev/null +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/VirtThread.cpp b/src/libs/7zip/win/CPP/7zip/Common/VirtThread.cpp index cf39bd023..77e3c1acf 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/VirtThread.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Common/VirtThread.h b/src/libs/7zip/win/CPP/7zip/Common/VirtThread.h index f14a1f223..ebee158ca 100644 --- a/src/libs/7zip/win/CPP/7zip/Common/VirtThread.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Compress/Bcj2Coder.cpp b/src/libs/7zip/win/CPP/7zip/Compress/Bcj2Coder.cpp index 684da5abf..9da6b9c28 100644 --- a/src/libs/7zip/win/CPP/7zip/Compress/Bcj2Coder.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Compress/Bcj2Coder.h b/src/libs/7zip/win/CPP/7zip/Compress/Bcj2Coder.h index 79a713f17..e7bd37951 100644 --- a/src/libs/7zip/win/CPP/7zip/Compress/Bcj2Coder.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Compress/BranchMisc.cpp b/src/libs/7zip/win/CPP/7zip/Compress/BranchMisc.cpp index 423b723ab..239f25138 100644 --- a/src/libs/7zip/win/CPP/7zip/Compress/BranchMisc.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Compress/CodecExports.cpp b/src/libs/7zip/win/CPP/7zip/Compress/CodecExports.cpp deleted file mode 100644 index 4ff1c0fcb..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/Compress/Compress.pri b/src/libs/7zip/win/CPP/7zip/Compress/Compress.pri new file mode 100644 index 000000000..db923a868 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Compress/Compress.pri @@ -0,0 +1,30 @@ +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 \ + $$7ZIP_BASE/CPP/7zip/Compress/StdAfx.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/win/CPP/7zip/Compress/CopyCoder.cpp b/src/libs/7zip/win/CPP/7zip/Compress/CopyCoder.cpp index f71692a77..f0863202a 100644 --- a/src/libs/7zip/win/CPP/7zip/Compress/CopyCoder.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Compress/CopyCoder.h b/src/libs/7zip/win/CPP/7zip/Compress/CopyCoder.h index c5445ccf8..5e0bb6436 100644 --- a/src/libs/7zip/win/CPP/7zip/Compress/CopyCoder.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Compress/DeltaFilter.cpp b/src/libs/7zip/win/CPP/7zip/Compress/DeltaFilter.cpp index 2e421acf4..d8378a60e 100644 --- a/src/libs/7zip/win/CPP/7zip/Compress/DeltaFilter.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Compress/Lzma2Decoder.cpp b/src/libs/7zip/win/CPP/7zip/Compress/Lzma2Decoder.cpp index 322015e29..b20ae5f5e 100644 --- a/src/libs/7zip/win/CPP/7zip/Compress/Lzma2Decoder.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Compress/Lzma2Encoder.cpp b/src/libs/7zip/win/CPP/7zip/Compress/Lzma2Encoder.cpp index 5e4c71bea..f867881c0 100644 --- a/src/libs/7zip/win/CPP/7zip/Compress/Lzma2Encoder.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Compress/Lzma2Encoder.h b/src/libs/7zip/win/CPP/7zip/Compress/Lzma2Encoder.h index f0fb74d33..6a2318076 100644 --- a/src/libs/7zip/win/CPP/7zip/Compress/Lzma2Encoder.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Compress/LzmaDecoder.cpp b/src/libs/7zip/win/CPP/7zip/Compress/LzmaDecoder.cpp index b7c260bd9..d378ba668 100644 --- a/src/libs/7zip/win/CPP/7zip/Compress/LzmaDecoder.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Compress/LzmaDecoder.h b/src/libs/7zip/win/CPP/7zip/Compress/LzmaDecoder.h index d28a4634b..140c48b9c 100644 --- a/src/libs/7zip/win/CPP/7zip/Compress/LzmaDecoder.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Compress/LzmaEncoder.cpp b/src/libs/7zip/win/CPP/7zip/Compress/LzmaEncoder.cpp index 9bdedaeb6..484d04523 100644 --- a/src/libs/7zip/win/CPP/7zip/Compress/LzmaEncoder.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/Compress/LzmaEncoder.h b/src/libs/7zip/win/CPP/7zip/Compress/LzmaEncoder.h index 904c0002c..7e15a132d 100644 --- a/src/libs/7zip/win/CPP/7zip/Compress/LzmaEncoder.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Compress/RangeCoder.h b/src/libs/7zip/win/CPP/7zip/Compress/RangeCoder.h index 1eb2a6d47..1555bd705 100644 --- a/src/libs/7zip/win/CPP/7zip/Compress/RangeCoder.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Compress/RangeCoderBit.h b/src/libs/7zip/win/CPP/7zip/Compress/RangeCoderBit.h index b5a1830d6..0eddd5586 100644 --- a/src/libs/7zip/win/CPP/7zip/Compress/RangeCoderBit.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/Compress/StdAfx.h b/src/libs/7zip/win/CPP/7zip/Compress/StdAfx.h index 99a8aa46d..1cbd7feae 100644 --- a/src/libs/7zip/win/CPP/7zip/Compress/StdAfx.h +++ b/src/libs/7zip/win/CPP/7zip/Compress/StdAfx.h @@ -3,6 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../Common/MyWindows.h" +#include "../../Common/Common.h" #endif diff --git a/src/libs/7zip/win/CPP/7zip/Guid.txt b/src/libs/7zip/win/CPP/7zip/Guid.txt index 59a743b96..c1e7446be 100644 --- a/src/libs/7zip/win/CPP/7zip/Guid.txt +++ b/src/libs/7zip/win/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/win/CPP/7zip/ICoder.h b/src/libs/7zip/win/CPP/7zip/ICoder.h index a518de463..74ee0e453 100644 --- a/src/libs/7zip/win/CPP/7zip/ICoder.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/IPassword.h b/src/libs/7zip/win/CPP/7zip/IPassword.h index 3ca7b090e..7ea45537e 100644 --- a/src/libs/7zip/win/CPP/7zip/IPassword.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/IProgress.h b/src/libs/7zip/win/CPP/7zip/IProgress.h index d6093f173..a270e693b 100644 --- a/src/libs/7zip/win/CPP/7zip/IProgress.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/IStream.h b/src/libs/7zip/win/CPP/7zip/IStream.h index 165e8baad..48643e7b3 100644 --- a/src/libs/7zip/win/CPP/7zip/IStream.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/MyVersion.h b/src/libs/7zip/win/CPP/7zip/MyVersion.h deleted file mode 100644 index eda88db08..000000000 --- a/src/libs/7zip/win/CPP/7zip/MyVersion.h +++ /dev/null @@ -1,8 +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 diff --git a/src/libs/7zip/win/CPP/7zip/PropID.h b/src/libs/7zip/win/CPP/7zip/PropID.h index 8f8885263..82a7462bb 100644 --- a/src/libs/7zip/win/CPP/7zip/PropID.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveCommandLine.cpp index 8ae2e15e8..769d21604 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveCommandLine.cpp +++ b/src/libs/7zip/win/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" #endif #include "ArchiveCommandLine.h" @@ -48,6 +50,30 @@ 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 { @@ -86,19 +112,47 @@ enum Enum kTechMode, kShareForWrite, 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 }; } @@ -110,135 +164,127 @@ 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"SCS", NSwitchType::kUnLimitedPostString, false, 0}, - { L"SCC", NSwitchType::kUnLimitedPostString, false, 0}, - { L"SLT", NSwitchType::kSimple, false }, - { L"SSW", NSwitchType::kSimple, false }, - { L"SSC", NSwitchType::kPostChar, false, 0, 0, L"-" }, - { L"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" }, + { "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) -{ - throw CArchiveCommandLineException(errorMessage); -} - -static void ThrowUserErrorException() -{ - ThrowException(kUserErrorMessage); -} - -// --------------------------- - -bool CArchiveCommand::IsFromExtractGroup() const +bool CArcCommand::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: @@ -246,170 +292,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); + AddToCensorFromListFile(renamePairs, censor, s.Ptr(1), true, type, wildcardMatching, codePage); + else if (renamePairs) + { + if (oldIndex == -1) + oldIndex = startIndex; + else + { + // 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; + } + } else - AddNameToCensor(wildcardCensor, s, true, type); + AddNameToCensor(censor, s, true, type, wildcardMatching); + } + + if (oldIndex != -1) + { + throw CArcCmdLineException("There is no second file name for rename pair:", nonSwitchStrings[oldIndex]); } } #ifdef _WIN32 -static void ParseMapWithPaths(NWildcard::CCensor &wildcardCensor, - const UString &switchParam, bool include, - NRecursedType::EEnum commonRecursedType) + +struct CEventSetEnd { - 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 - { - 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++) - { - wchar_t c = curData[i]; - if (c == L'\0') - { - AddNameToCensor(wildcardCensor, name, include, commonRecursedType); - name.Empty(); - } - else - name += c; - } - if (!name.IsEmpty()) - ThrowException("data error"); - } - catch(...) - { - UnmapViewOfFile(data); - throw; - } - UnmapViewOfFile(data); - } - + 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 @@ -418,20 +575,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::CFileInfo fi; + const FString path = us2fs(prefix + name); + if (NFile::NName::IsDevicePath(path)) return; - NFind::CFileInfoW fi; - if (fi.Find(prefix + name)) - name = fi.Name; + 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()); } } @@ -440,17 +602,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; @@ -463,13 +630,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); @@ -478,9 +645,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; @@ -489,35 +657,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}; - -const UString kUpdatePairActionIDSet = L"0123"; //Ignore, Copy, Compress, Create Anti +static const wchar_t *kUpdatePairStateIDSet = L"pqrxyzw"; +static const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1}; -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++; @@ -530,10 +699,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) { @@ -547,7 +718,7 @@ static void ParseUpdateCommandString(CUpdateOptions &options, UString postString; if (!ParseUpdateCommandString2(updateString, actionSet, postString)) - ThrowUserErrorException(); + break; if (postString.IsEmpty()) { if (options.UpdateArchiveItself) @@ -555,64 +726,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, @@ -620,20 +750,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; @@ -645,22 +775,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); } } @@ -670,38 +800,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); @@ -711,62 +831,67 @@ 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 _WIN32 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 } struct CCodePagePair { - const wchar_t *Name; - UINT CodePage; + const char *Name; + Int32 CodePage; }; +static const unsigned kNumByteOnlyCodePages = 3; + static CCodePagePair g_CodePagePairs[] = { - { L"UTF-8", CP_UTF8 }, - { L"WIN", CP_ACP }, - { L"DOS", CP_OEMCP } + { "utf-8", CP_UTF8 }, + { "win", CP_ACP }, + { "dos", CP_OEMCP }, + { "utf-16le", MY__CP_UTF16 }, + { "utf-16be", MY__CP_UTF16BE } }; -static int FindCharset(const NCommandLineParser::CParser &parser, int keyIndex, int defaultVal) +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(); - name.MakeUpper(); - int i; - for (i = 0; i < sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0]); i++) + 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.Compare(pair.Name) == 0) + if (name.IsEqualTo(pair.Name)) return pair.CodePage; } - if (i == sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0])) - ThrowUserErrorException(); - return -1; -} - -static bool ConvertStringToUInt32(const wchar_t *s, UInt32 &v) -{ - 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; } -void EnumerateDirItemsAndSort(NWildcard::CCensor &wildcardCensor, +void EnumerateDirItemsAndSort( + bool storeAltStreams, + NWildcard::CCensor &censor, + NWildcard::ECensorPathMode censorPathMode, + const UString &addPathPrefix, UStringVector &sortedPaths, UStringVector &sortedFullPaths) { @@ -774,59 +899,92 @@ void EnumerateDirItemsAndSort(NWildcard::CCensor &wildcardCensor, { CDirItems dirItems; { - UStringVector errorPaths; - CRecordVector errorCodes; - HRESULT res = EnumerateItems(wildcardCensor, dirItems, NULL, errorPaths, errorCodes); - if (res != S_OK || errorPaths.Size() > 0) - throw "cannot find archive"; + 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 (int i = 0; i < dirItems.Items.Size(); i++) + FOR_VECTOR (i, dirItems.Items) { const CDirItem &dirItem = dirItems.Items[i]; if (!dirItem.IsDir()) paths.Add(dirItems.GetPhyPath(i)); } } - + if (paths.Size() == 0) - throw "there is no such archive"; - + throw CArcCmdLineException(kCannotFindArchive); + UStringVector fullPaths; - - int i; + + unsigned i; for (i = 0; i < paths.Size(); i++) { - UString fullPath; - NFile::NDirectory::MyGetFullPathName(paths[i], fullPath); - fullPaths.Add(fullPath); + FString fullPath; + NFile::NDir::MyGetFullPathName(us2fs(paths[i]), fullPath); + fullPaths.Add(fs2us(fullPath)); } - CIntVector indices; + CUIntVector indices; SortFileNames(fullPaths, indices); - sortedPaths.Reserve(indices.Size()); - sortedFullPaths.Reserve(indices.Size()); + sortedPaths.ClearAndReserve(indices.Size()); + sortedFullPaths.ClearAndReserve(indices.Size()); for (i = 0; i < indices.Size(); i++) { - int index = indices[i]; - sortedPaths.Add(paths[index]); - sortedFullPaths.Add(fullPaths[index]); + 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]); } } -void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) +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) @@ -834,43 +992,55 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) else recursedType = NRecursedType::kNonRecursed; - g_CodePage = FindCharset(parser, NKey::kConsoleCharSet, -1); - UINT codePage = FindCharset(parser, NKey::kListfileCharSet, CP_UTF8); + bool wildcardMatching = true; + if (parser[NKey::kDisableWildcardParsing].ThereIs) + wildcardMatching = false; + + g_CodePage = FindCharset(parser, NKey::kConsoleCharSet, true, -1); + Int32 codePage = FindCharset(parser, NKey::kListfileCharSet, false, CP_UTF8); 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; @@ -886,28 +1056,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; + + 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(); - NWildcard::CCensor archiveWildcardCensor; + // 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); + AddSwitchWildcardsToCensor(arcCensor, parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, wildcardMatching, codePage); if (thereIsArchiveName) - AddNameToCensor(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed); + 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) { @@ -917,54 +1132,76 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) } else { - EnumerateDirItemsAndSort(archiveWildcardCensor, - options.ArchivePathsSorted, - options.ArchivePathsFullSorted); + EnumerateDirItemsAndSort( + false, // scanAltStreams + arcCensor, + NWildcard::k_RelatPath, + UString(), // addPathPrefix + options.ArchivePathsSorted, + options.ArchivePathsFullSorted); } - + 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); + + updateOptions.MethodMode.Properties = options.Properties; if (parser[NKey::kShareForWrite].ThereIs) updateOptions.OpenShareForWrite = true; - options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs; + updateOptions.PathMode = censorPathMode; - if (options.EnablePercents) - { - if ((options.StdOutMode && !options.IsStdErrTerminal) || - (!options.StdOutMode && !options.IsStdOutTerminal)) - options.EnablePercents = false; - } + 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; @@ -975,68 +1212,46 @@ 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; + if (parser[NKey::kShareForWrite].ThereIs) + hashOptions.OpenShareForWrite = true; + hashOptions.StdInMode = options.StdInMode; + hashOptions.AltStreamsMode = options.AltStreams.Val; + } else if (options.Command.CommandType == NCommandType::kInfo) { } else - ThrowUserErrorException(); - options.WildcardCensor.ExtendExclude(); + throw 9815676711; } diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveCommandLine.h b/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveCommandLine.h index e8f601df4..87e6619e6 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveCommandLine.h +++ b/src/libs/7zip/win/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 _WIN32 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/win/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp index 4c0cc90b5..250f66797 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveExtractCallback.h index 367e4b07d..fe7ef42bb 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveExtractCallback.h +++ b/src/libs/7zip/win/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 + +#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/win/CPP/7zip/UI/Common/ArchiveName.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveName.cpp deleted file mode 100644 index c3684def8..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/ArchiveName.h b/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveName.h deleted file mode 100644 index 9513fb2ba..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp index e7e617131..4157aa4f1 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp +++ b/src/libs/7zip/win/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,41 +60,32 @@ 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() { 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; + FString fullPath; + if (!NFile::NName::GetFullPath(_folderPrefix, us2fs(name), fullPath)) + return S_FALSE; if (!_fileInfo.Find(fullPath)) return S_FALSE; if (_fileInfo.IsDir()) @@ -103,12 +94,14 @@ STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStre 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/win/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveOpenCallback.h index c6651e8f9..3352eadef 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveOpenCallback.h +++ b/src/libs/7zip/win/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; + 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/win/CPP/7zip/UI/Common/Bench.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/Bench.cpp deleted file mode 100644 index 282f405f1..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/Bench.h b/src/libs/7zip/win/CPP/7zip/UI/Common/Bench.h deleted file mode 100644 index a8d02a19b..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/Common.pri b/src/libs/7zip/win/CPP/7zip/UI/Common/Common.pri new file mode 100644 index 000000000..9d829d2af --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/UI/Common/Common.pri @@ -0,0 +1,44 @@ +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/StdAfx.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/win/CPP/7zip/UI/Common/DefaultName.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/DefaultName.cpp index 4335e2731..ce0b327b5 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/DefaultName.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/DefaultName.h b/src/libs/7zip/win/CPP/7zip/UI/Common/DefaultName.h index 9764ff871..df1645602 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/DefaultName.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/DirItem.h b/src/libs/7zip/win/CPP/7zip/UI/Common/DirItem.h index 29cc60d93..82203c03a 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/DirItem.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/EnumDirItems.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/EnumDirItems.cpp index ba03ea35c..1e9562a0e 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/EnumDirItems.cpp +++ b/src/libs/7zip/win/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; + 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 { - NFind::CEnumeratorW enumerator(phyPrefix + (wchar_t)kAnyStringWildcard); + #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, (PSECURITY_DESCRIPTOR)(Byte *)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, (PSECURITY_DESCRIPTOR)(Byte *)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::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; } +#ifndef UNDER_CE + +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) +{ + 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; + } + + #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 UString &phyPrefix, +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, - UStringVector &errorPaths, - CRecordVector &errorCodes) + 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); + + #ifndef UNDER_CE + { + CDirItem &dirItem = dirItems.Items.Back(); + dirItems.SetLinkInfo(dirItem, fi, phyPrefix); + if (dirItem.ReparseData.Size() != 0) + continue; + } + #endif + + dirItems.TotalSize += fi.Size; + + #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; + 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)) { 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/win/CPP/7zip/UI/Common/EnumDirItems.h b/src/libs/7zip/win/CPP/7zip/UI/Common/EnumDirItems.h index d0ce950e3..803a64e7d 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/EnumDirItems.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/ExitCode.h b/src/libs/7zip/win/CPP/7zip/UI/Common/ExitCode.h deleted file mode 100644 index b6d7d4dfc..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/Extract.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/Extract.cpp index ca2c8c73d..13d2ad29a 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/Extract.cpp +++ b/src/libs/7zip/win/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]; + const FString &arcPath = us2fs(arcPaths[i]); if (!fi.Find(arcPath)) 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)) || 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/win/CPP/7zip/UI/Common/Extract.h b/src/libs/7zip/win/CPP/7zip/UI/Common/Extract.h index 5a939ed23..052b2f7d3 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/Extract.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/ExtractMode.h b/src/libs/7zip/win/CPP/7zip/UI/Common/ExtractMode.h index b448fb30a..a54376705 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/ExtractMode.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/ExtractingFilePath.cpp index 8f31708b6..852fd5adb 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/ExtractingFilePath.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/ExtractingFilePath.h b/src/libs/7zip/win/CPP/7zip/UI/Common/ExtractingFilePath.h index da28bfc23..751248a97 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/ExtractingFilePath.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/HashCalc.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/HashCalc.cpp new file mode 100644 index 000000000..2d13a2af1 --- /dev/null +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/HashCalc.h b/src/libs/7zip/win/CPP/7zip/UI/Common/HashCalc.h new file mode 100644 index 000000000..68e2404cc --- /dev/null +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/IFileExtractCallback.h b/src/libs/7zip/win/CPP/7zip/UI/Common/IFileExtractCallback.h index e8dcdce5f..7bb852795 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/IFileExtractCallback.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/LoadCodecs.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/LoadCodecs.cpp index 856e47fbc..a1d801b04 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/LoadCodecs.cpp +++ b/src/libs/7zip/win/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,84 +31,167 @@ static const UINT kIconTypesResId = 100; #endif #ifdef _WIN32 -#include "Windows/Registry.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/Registry.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 - return CSysString(); // FIX IT - #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(); + 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; } @@ -111,34 +203,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) @@ -146,13 +252,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) @@ -160,132 +267,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(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; @@ -294,25 +419,26 @@ HRESULT CCodecs::LoadFormats() #ifdef NEW_FOLDER_INTERFACE void CCodecIcons::LoadIcons(HMODULE m) { - 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; } } @@ -324,10 +450,10 @@ void CCodecIcons::LoadIcons(HMODULE m) bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const { 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; @@ -335,7 +461,8 @@ bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const } return false; } -#endif + +#endif // EXTERNAL_CODECS #ifdef _7ZIP_LARGE_PAGES extern "C" @@ -344,7 +471,7 @@ extern "C" } #endif -HRESULT CCodecs::LoadDll(const CSysString &dllPath, bool needCheckDll) +HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll) { if (needCheckDll) { @@ -354,9 +481,7 @@ HRESULT CCodecs::LoadDll(const CSysString &dllPath, bool needCheckDll) } 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)) @@ -368,23 +493,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) + { + 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) { - int startSize = Codecs.Size(); + 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; } } } @@ -393,9 +526,9 @@ HRESULT CCodecs::LoadDll(const CSysString &dllPath, bool needCheckDll) return res; } -HRESULT CCodecs::LoadDllsFromFolder(const CSysString &folderPrefix) +HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPrefix) { - NFile::NFind::CEnumerator enumerator(folderPrefix + CSysString(TEXT("*"))); + NFile::NFind::CEnumerator enumerator(folderPrefix + FCHAR_ANY_MASK); NFile::NFind::CFileInfo fi; while (enumerator.Next(fi)) { @@ -408,46 +541,63 @@ 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 - InternalIcons.LoadIcons(g_hInstance); + InternalIcons.LoadIcons(g_hInstance); #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; } @@ -455,17 +605,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; + if (ext.IsEqualToNoCase(L"exe")) return -1; - UString ext = arcPath.Mid(dotPos + 1); - for (int i = 0; i < Formats.Size(); i++) + FOR_VECTOR (i, Formats) { const CArcInfoEx &arc = Formats[i]; + /* if (!arc.UpdateEnabled) continue; + */ if (arc.FindExtension(ext) >= 0) return i; } @@ -476,7 +631,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; @@ -484,8 +639,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; } @@ -493,12 +648,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"*") { @@ -511,24 +668,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; } @@ -539,27 +711,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) + if (propID == NMethodPropID::kDecoderIsAssigned || + propID == NMethodPropID::kEncoderIsAssigned) { - NWindows::NCOM::CPropVariant propVariant; - propVariant = ci.DecoderIsAssigned; - propVariant.Detach(value); - return S_OK; - } - if (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) @@ -568,14 +736,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) @@ -584,35 +752,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) @@ -622,11 +808,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; @@ -638,7 +834,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; @@ -646,11 +842,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; @@ -659,8 +851,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; @@ -671,11 +862,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/win/CPP/7zip/UI/Common/LoadCodecs.h b/src/libs/7zip/win/CPP/7zip/UI/Common/LoadCodecs.h index a633dd2e1..d254ae659 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/LoadCodecs.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/OpenArchive.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/OpenArchive.cpp index 56a630467..4efbc9cc7 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/OpenArchive.cpp +++ b/src/libs/7zip/win/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; + fileStreamSpec = new CInFileStream; 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,238 @@ 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; + + op.types = &inc; + op.excludedFormats = ! + op.stdInMode = false; + op.stream = NULL; + if (Arcs.Size() == 0) // ??? + return Open2(op, NULL); CMyComPtr openCallbackNew; - SetCallback(filePath, NULL, callback, openCallbackNew); + SetCallback(us2fs(op.filePath), NULL, op.callback, openCallbackNew); CInFileStream *fileStreamSpec = new CInFileStream; 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/win/CPP/7zip/UI/Common/OpenArchive.h b/src/libs/7zip/win/CPP/7zip/UI/Common/OpenArchive.h index 4a003ee63..2ee743adc 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/OpenArchive.h +++ b/src/libs/7zip/win/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), + EachPos(false), + CanReturnArc(true), + CanReturnParser(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/win/CPP/7zip/UI/Common/PropIDUtils.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/PropIDUtils.cpp index dacaca5f9..8f27cc0d1 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/PropIDUtils.cpp +++ b/src/libs/7zip/win/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,467 @@ 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 + +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 diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/PropIDUtils.h b/src/libs/7zip/win/CPP/7zip/UI/Common/PropIDUtils.h index ca14d091d..3ee2981de 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/PropIDUtils.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/Property.h b/src/libs/7zip/win/CPP/7zip/UI/Common/Property.h index 9fd340cbc..8b57a2a64 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/Property.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/SetProperties.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/SetProperties.cpp index 4827f2a78..64b9d92a6 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/SetProperties.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/SortUtils.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/SortUtils.cpp index 061e77730..b7e422a29 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/SortUtils.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/SortUtils.h b/src/libs/7zip/win/CPP/7zip/UI/Common/SortUtils.h index e15224611..8e42e0682 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/SortUtils.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/StdAfx.h b/src/libs/7zip/win/CPP/7zip/UI/Common/StdAfx.h index 9a8e7d21a..2854ff3e9 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/StdAfx.h +++ b/src/libs/7zip/win/CPP/7zip/UI/Common/StdAfx.h @@ -1,9 +1,8 @@ -// stdafx.h +// StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" -#include "../../../Common/NewHandler.h" +#include "../../../Common/Common.h" #endif diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/TempFiles.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/TempFiles.cpp index eeaec1802..0c13ae158 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/TempFiles.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/TempFiles.h b/src/libs/7zip/win/CPP/7zip/UI/Common/TempFiles.h index eb474a760..4099e6558 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/TempFiles.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/Update.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/Update.cpp index a57ec2a6b..e3d538f10 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/Update.cpp +++ b/src/libs/7zip/win/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,9 +36,33 @@ static const char *kUpdateIsNotSupoorted = using namespace NWindows; using namespace NCOM; using namespace NFile; +using namespace NDir; using namespace NName; -static const wchar_t *kTempFolderPrefix = L"7zE"; +static CFSTR kTempFolderPrefix = FTEXT("7zE"); + + +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; @@ -48,24 +70,24 @@ 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() @@ -76,6 +98,7 @@ public: _length = 0; } + bool SetMTime(const FILETIME *mTime); HRESULT Close(); MY_UNKNOWN_IMP1(IOutStream) @@ -90,12 +113,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; } @@ -103,40 +126,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]; @@ -147,29 +183,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; @@ -185,17 +221,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) @@ -208,24 +238,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(); } @@ -235,7 +265,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"; @@ -243,40 +333,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; } @@ -286,7 +394,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); @@ -298,36 +406,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 { @@ -342,12 +512,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: @@ -358,8 +528,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!!! @@ -368,61 +599,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); @@ -445,12 +696,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(); @@ -462,29 +717,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(); @@ -500,9 +755,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) @@ -510,7 +817,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) { @@ -518,23 +827,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; @@ -542,7 +849,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: @@ -555,99 +862,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) @@ -661,40 +971,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 = NDLL::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) + { + 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::CFileInfoW fi; - if (fi.Find(arcPath)) + 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) { @@ -702,21 +1068,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; @@ -730,7 +1123,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) @@ -738,12 +1132,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) { @@ -752,14 +1155,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); @@ -773,8 +1208,6 @@ HRESULT UpdateArchive( bool createTempFile = false; - bool thereIsInArchive = arcLink.IsOpen; - if (!options.StdOutMode && options.UpdateArchiveItself) { CArchivePath &ap = options.Commands[0].ArchivePath; @@ -785,27 +1218,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; @@ -819,13 +1253,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) { @@ -839,21 +1324,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; } } @@ -863,30 +1348,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"; @@ -895,16 +1392,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/win/CPP/7zip/UI/Common/Update.h b/src/libs/7zip/win/CPP/7zip/UI/Common/Update.h index ade001303..ff53cd992 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/Update.h +++ b/src/libs/7zip/win/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; - bool Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath); + CBoolPair NtSecurity; + CBoolPair AltStreams; + CBoolPair HardLinks; + CBoolPair SymLinks; + + bool DeleteAfterCompressing; + + bool SetArcMTime; + + CObjectVector RenamePairs; + + bool InitFormatIndex(const CCodecs *codecs, const CObjectVector &types, const UString &arcPath); + bool SetArcPath(const CCodecs *codecs, const UString &arcPath); CUpdateOptions(): UpdateArchiveItself(true), SfxMode(false), - OpenShareForWrite(false), StdInMode(false), StdOutMode(false), EMailMode(false), - EMailRemoveAfter(false) + EMailRemoveAfter(false), + OpenShareForWrite(false), + ArcNameMode(k_ArcNameMode_Smart), + 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/win/CPP/7zip/UI/Common/UpdateAction.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateAction.cpp index 879a49c57..a80db7212 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateAction.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/UpdateAction.h b/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateAction.h index 0ac1c1080..8c7609fb4 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateAction.h +++ b/src/libs/7zip/win/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]; + + const 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/win/CPP/7zip/UI/Common/UpdateCallback.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateCallback.cpp index 0f229058c..e490cde24 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateCallback.cpp +++ b/src/libs/7zip/win/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; + #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) + { + #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,59 @@ 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 (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; + } + } + } + } + + if (ProcessedItemsStatuses) + { + NSynchronization::CCriticalSectionLock lock(CS); + ProcessedItemsStatuses[up.DirIndex] = 1; + } *inStream = inStreamLoc.Detach(); } + return S_OK; COM_TRY_END } @@ -216,12 +541,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/win/CPP/7zip/UI/Common/UpdateCallback.h b/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateCallback.h index 9a20c3159..81982e61d 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateCallback.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/UpdatePair.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/UpdatePair.cpp index a43a9e770..95afdd694 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdatePair.cpp +++ b/src/libs/7zip/win/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); @@ -39,24 +38,38 @@ static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time 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( @@ -65,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); + { + int *vals = &duplicatedArcItem[0]; + for (unsigned i = 0; i < numArcItems; i++) + vals[i] = 0; + } + { - UStringVector arcNames; - arcNames.Reserve(numArcItems); - for (int i = 0; i < numArcItems; i++) - arcNames.Add(arcItems[i].Name); - SortFileNames(arcNames, arcIndices); - TestDuplicateString(arcNames, arcIndices); + 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; @@ -114,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/win/CPP/7zip/UI/Common/UpdatePair.h b/src/libs/7zip/win/CPP/7zip/UI/Common/UpdatePair.h index 3a332649c..296d3b097 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdatePair.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/UpdateProduce.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateProduce.cpp index c21db3b2a..2c4c28583 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateProduce.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/UpdateProduce.h b/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateProduce.h index e18648cd9..ef7b0f7a3 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateProduce.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/WorkDir.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/WorkDir.cpp deleted file mode 100644 index 164118e2c..000000000 --- a/src/libs/7zip/win/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; - #ifndef UNDER_CE - 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/win/CPP/7zip/UI/Common/WorkDir.h b/src/libs/7zip/win/CPP/7zip/UI/Common/WorkDir.h deleted file mode 100644 index 0643d67a4..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/UI/Common/ZipRegistry.h b/src/libs/7zip/win/CPP/7zip/UI/Common/ZipRegistry.h deleted file mode 100644 index 378353868..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/UI/Console/BenchCon.cpp b/src/libs/7zip/win/CPP/7zip/UI/Console/BenchCon.cpp deleted file mode 100644 index 35e868c9b..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/UI/Console/BenchCon.h b/src/libs/7zip/win/CPP/7zip/UI/Console/BenchCon.h deleted file mode 100644 index 966a83a6a..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/UI/Console/Console.pri b/src/libs/7zip/win/CPP/7zip/UI/Console/Console.pri new file mode 100644 index 000000000..14668f8b3 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/UI/Console/Console.pri @@ -0,0 +1,4 @@ +HEADERS += $$7ZIP_BASE/CPP/7zip/UI/Console/PercentPrinter.h \ + $$7ZIP_BASE/CPP/7zip/UI/Common/StdAfx.h + +SOURCES += $$7ZIP_BASE/CPP/7zip/UI/Console/PercentPrinter.cpp diff --git a/src/libs/7zip/win/CPP/7zip/UI/Console/ConsoleClose.cpp b/src/libs/7zip/win/CPP/7zip/UI/Console/ConsoleClose.cpp deleted file mode 100644 index 5acae942d..000000000 --- a/src/libs/7zip/win/CPP/7zip/UI/Console/ConsoleClose.cpp +++ /dev/null @@ -1,73 +0,0 @@ -// ConsoleClose.cpp - -#include "StdAfx.h" - -#include "ConsoleClose.h" - -static int g_BreakCounter = 0; -static const int kBreakAbortThreshold = 2; - -namespace NConsoleClose { - -#if !defined(UNDER_CE) && defined(_WIN32) -static BOOL WINAPI HandlerRoutine(DWORD ctrlType) -{ - if (ctrlType == CTRL_LOGOFF_EVENT) - { - // printf("\nCTRL_LOGOFF_EVENT\n"); - return TRUE; - } - - g_BreakCounter++; - if (g_BreakCounter < kBreakAbortThreshold) - return TRUE; - return FALSE; - /* - switch(ctrlType) - { - case CTRL_C_EVENT: - case CTRL_BREAK_EVENT: - if (g_BreakCounter < kBreakAbortThreshold) - return TRUE; - } - return FALSE; - */ -} -#endif - -bool TestBreakSignal() -{ - #ifdef UNDER_CE - return false; - #else - /* - if (g_BreakCounter > 0) - return true; - */ - return (g_BreakCounter > 0); - #endif -} - -void CheckCtrlBreak() -{ - if (TestBreakSignal()) - throw CCtrlBreakException(); -} - -CCtrlHandlerSetter::CCtrlHandlerSetter() -{ - #if !defined(UNDER_CE) && defined(_WIN32) - if(!SetConsoleCtrlHandler(HandlerRoutine, TRUE)) - throw "SetConsoleCtrlHandler fails"; - #endif -} - -CCtrlHandlerSetter::~CCtrlHandlerSetter() -{ - #if !defined(UNDER_CE) && defined(_WIN32) - if(!SetConsoleCtrlHandler(HandlerRoutine, FALSE)) - throw "SetConsoleCtrlHandler fails"; - #endif -} - -} diff --git a/src/libs/7zip/win/CPP/7zip/UI/Console/ConsoleClose.h b/src/libs/7zip/win/CPP/7zip/UI/Console/ConsoleClose.h deleted file mode 100644 index 9019c4ce2..000000000 --- a/src/libs/7zip/win/CPP/7zip/UI/Console/ConsoleClose.h +++ /dev/null @@ -1,24 +0,0 @@ -// ConsoleCloseUtils.h - -#ifndef __CONSOLECLOSEUTILS_H -#define __CONSOLECLOSEUTILS_H - -namespace NConsoleClose { - -bool TestBreakSignal(); - -class CCtrlHandlerSetter -{ -public: - CCtrlHandlerSetter(); - virtual ~CCtrlHandlerSetter(); -}; - -class CCtrlBreakException -{}; - -void CheckCtrlBreak(); - -} - -#endif diff --git a/src/libs/7zip/win/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/src/libs/7zip/win/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp deleted file mode 100644 index af65739c3..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/UI/Console/ExtractCallbackConsole.h b/src/libs/7zip/win/CPP/7zip/UI/Console/ExtractCallbackConsole.h deleted file mode 100644 index e42ca6f40..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/UI/Console/List.cpp b/src/libs/7zip/win/CPP/7zip/UI/Console/List.cpp deleted file mode 100644 index f747cfda8..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/UI/Console/List.h b/src/libs/7zip/win/CPP/7zip/UI/Console/List.h deleted file mode 100644 index 97d9fb15a..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/UI/Console/Main.cpp b/src/libs/7zip/win/CPP/7zip/UI/Console/Main.cpp deleted file mode 100644 index 9bd451f83..000000000 --- a/src/libs/7zip/win/CPP/7zip/UI/Console/Main.cpp +++ /dev/null @@ -1,598 +0,0 @@ -// Main.cpp - -#include "StdAfx.h" - -#if defined( _WIN32) && 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" - -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"; - -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" - " -ssw: compress shared files\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; - // s << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << "\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); - #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(_WIN32) && defined(_7ZIP_LARGE_PAGES) - if (options.LargePages) - { - SetLargePageSize(); - NSecurity::EnableLockMemoryPrivilege(); - } - #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); - - 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/win/CPP/7zip/UI/Console/MainAr.cpp b/src/libs/7zip/win/CPP/7zip/UI/Console/MainAr.cpp deleted file mode 100644 index c54a3d098..000000000 --- a/src/libs/7zip/win/CPP/7zip/UI/Console/MainAr.cpp +++ /dev/null @@ -1,125 +0,0 @@ -// MainAr.cpp - -#include "StdAfx.h" - -#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/win/CPP/7zip/UI/Console/OpenCallbackConsole.cpp b/src/libs/7zip/win/CPP/7zip/UI/Console/OpenCallbackConsole.cpp deleted file mode 100644 index 7dba2ad5d..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/UI/Console/OpenCallbackConsole.h b/src/libs/7zip/win/CPP/7zip/UI/Console/OpenCallbackConsole.h deleted file mode 100644 index c002e6a72..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/UI/Console/PercentPrinter.cpp b/src/libs/7zip/win/CPP/7zip/UI/Console/PercentPrinter.cpp index 28452b177..f2889957a 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Console/PercentPrinter.cpp +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Console/PercentPrinter.h b/src/libs/7zip/win/CPP/7zip/UI/Console/PercentPrinter.h index 97f2e6adb..509bab5fc 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Console/PercentPrinter.h +++ b/src/libs/7zip/win/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/win/CPP/7zip/UI/Console/StdAfx.cpp b/src/libs/7zip/win/CPP/7zip/UI/Console/StdAfx.cpp deleted file mode 100644 index d0feea85c..000000000 --- a/src/libs/7zip/win/CPP/7zip/UI/Console/StdAfx.cpp +++ /dev/null @@ -1,3 +0,0 @@ -// StdAfx.cpp - -#include "StdAfx.h" diff --git a/src/libs/7zip/win/CPP/7zip/UI/Console/StdAfx.h b/src/libs/7zip/win/CPP/7zip/UI/Console/StdAfx.h index 2e4be10b2..2854ff3e9 100644 --- a/src/libs/7zip/win/CPP/7zip/UI/Console/StdAfx.h +++ b/src/libs/7zip/win/CPP/7zip/UI/Console/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" -#include "../../../Common/NewHandler.h" +#include "../../../Common/Common.h" #endif diff --git a/src/libs/7zip/win/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/src/libs/7zip/win/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp deleted file mode 100644 index 7f3373197..000000000 --- a/src/libs/7zip/win/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); - 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/win/CPP/7zip/UI/Console/UpdateCallbackConsole.h b/src/libs/7zip/win/CPP/7zip/UI/Console/UpdateCallbackConsole.h deleted file mode 100644 index 5ffe3eb7a..000000000 --- a/src/libs/7zip/win/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/win/CPP/7zip/UI/Console/UserInputUtils.cpp b/src/libs/7zip/win/CPP/7zip/UI/Console/UserInputUtils.cpp deleted file mode 100644 index 754680090..000000000 --- a/src/libs/7zip/win/CPP/7zip/UI/Console/UserInputUtils.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// UserInputUtils.cpp - -#include "StdAfx.h" - -#include "Common/StdInStream.h" -#include "Common/StringConvert.h" - -#include "UserInputUtils.h" - -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; - } - } -} - -#ifdef _WIN32 -#ifndef UNDER_CE -#define MY_DISABLE_ECHO -#endif -#endif - -UString GetPassword(CStdOutStream *outStream) -{ - (*outStream) << "\nEnter password" - #ifdef MY_DISABLE_ECHO - " (will not be echoed)" - #endif - ":"; - outStream->Flush(); - - #ifdef MY_DISABLE_ECHO - HANDLE console = GetStdHandle(STD_INPUT_HANDLE); - bool wasChanged = false; - DWORD mode = 0; - if (console != INVALID_HANDLE_VALUE && console != 0) - if (GetConsoleMode(console, &mode)) - wasChanged = (SetConsoleMode(console, mode & ~ENABLE_ECHO_INPUT) != 0); - UString res = g_StdIn.ScanUStringUntilNewLine(); - if (wasChanged) - SetConsoleMode(console, mode); - (*outStream) << "\n"; - outStream->Flush(); - return res; - #else - return g_StdIn.ScanUStringUntilNewLine(); - #endif -} diff --git a/src/libs/7zip/win/CPP/7zip/UI/Console/UserInputUtils.h b/src/libs/7zip/win/CPP/7zip/UI/Console/UserInputUtils.h deleted file mode 100644 index 8b5232b3f..000000000 --- a/src/libs/7zip/win/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); - -#endif diff --git a/src/libs/7zip/win/CPP/Common/AutoPtr.h b/src/libs/7zip/win/CPP/Common/AutoPtr.h deleted file mode 100644 index 006d31551..000000000 --- a/src/libs/7zip/win/CPP/Common/AutoPtr.h +++ /dev/null @@ -1,35 +0,0 @@ -// Common/AutoPtr.h - -#ifndef __COMMON_AUTOPTR_H -#define __COMMON_AUTOPTR_H - -template class CMyAutoPtr -{ - T *_p; -public: - CMyAutoPtr(T *p = 0) : _p(p) {} - CMyAutoPtr(CMyAutoPtr& p): _p(p.release()) {} - CMyAutoPtr& operator=(CMyAutoPtr& p) - { - reset(p.release()); - return (*this); - } - ~CMyAutoPtr() { delete _p; } - T& operator*() const { return *_p; } - // T* operator->() const { return (&**this); } - T* get() const { return _p; } - T* release() - { - T *tmp = _p; - _p = 0; - return tmp; - } - void reset(T* p = 0) - { - if (p != _p) - delete _p; - _p = p; - } -}; - -#endif diff --git a/src/libs/7zip/win/CPP/Common/Buffer.h b/src/libs/7zip/win/CPP/Common/Buffer.h deleted file mode 100644 index 118fe11fc..000000000 --- a/src/libs/7zip/win/CPP/Common/Buffer.h +++ /dev/null @@ -1,77 +0,0 @@ -// Common/Buffer.h - -#ifndef __COMMON_BUFFER_H -#define __COMMON_BUFFER_H - -#include "Defs.h" - -template class CBuffer -{ -protected: - size_t _capacity; - T *_items; -public: - void Free() - { - delete []_items; - _items = 0; - _capacity = 0; - } - CBuffer(): _capacity(0), _items(0) {}; - CBuffer(const CBuffer &buffer): _capacity(0), _items(0) { *this = buffer; } - CBuffer(size_t size): _items(0), _capacity(0) { SetCapacity(size); } - virtual ~CBuffer() { delete []_items; } - operator T *() { return _items; }; - operator const T *() const { return _items; }; - size_t GetCapacity() const { return _capacity; } - void SetCapacity(size_t newCapacity) - { - if (newCapacity == _capacity) - return; - T *newBuffer; - if (newCapacity > 0) - { - newBuffer = new T[newCapacity]; - if (_capacity > 0) - memmove(newBuffer, _items, MyMin(_capacity, newCapacity) * sizeof(T)); - } - else - newBuffer = 0; - delete []_items; - _items = newBuffer; - _capacity = newCapacity; - } - CBuffer& operator=(const CBuffer &buffer) - { - Free(); - if (buffer._capacity > 0) - { - SetCapacity(buffer._capacity); - memmove(_items, buffer._items, buffer._capacity * sizeof(T)); - } - return *this; - } -}; - -template -bool operator==(const CBuffer& b1, const CBuffer& b2) -{ - if (b1.GetCapacity() != b2.GetCapacity()) - return false; - for (size_t i = 0; i < b1.GetCapacity(); i++) - if (b1[i] != b2[i]) - return false; - return true; -} - -template -bool operator!=(const CBuffer& b1, const CBuffer& b2) -{ - return !(b1 == b2); -} - -typedef CBuffer CCharBuffer; -typedef CBuffer CWCharBuffer; -typedef CBuffer CByteBuffer; - -#endif diff --git a/src/libs/7zip/win/CPP/Common/CRC.cpp b/src/libs/7zip/win/CPP/Common/CRC.cpp deleted file mode 100644 index 9a9f81fb7..000000000 --- a/src/libs/7zip/win/CPP/Common/CRC.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// Common/CRC.cpp - -#include "StdAfx.h" - -#include "../../C/7zCrc.h" - -struct CCRCTableInit { CCRCTableInit() { CrcGenerateTable(); } } g_CRCTableInit; diff --git a/src/libs/7zip/win/CPP/Common/C_FileIO.cpp b/src/libs/7zip/win/CPP/Common/C_FileIO.cpp deleted file mode 100644 index b4893d658..000000000 --- a/src/libs/7zip/win/CPP/Common/C_FileIO.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// Common/C_FileIO.h - -#include "C_FileIO.h" - -#include -#include - -namespace NC { -namespace NFile { -namespace NIO { - -bool CFileBase::OpenBinary(const char *name, int flags) -{ - #ifdef O_BINARY - flags |= O_BINARY; - #endif - Close(); - _handle = ::open(name, flags, 0666); - return _handle != -1; -} - -bool CFileBase::Close() -{ - if (_handle == -1) - return true; - if (close(_handle) != 0) - return false; - _handle = -1; - return true; -} - -bool CFileBase::GetLength(UInt64 &length) const -{ - off_t curPos = Seek(0, SEEK_CUR); - off_t lengthTemp = Seek(0, SEEK_END); - Seek(curPos, SEEK_SET); - length = (UInt64)lengthTemp; - return true; -} - -off_t CFileBase::Seek(off_t distanceToMove, int moveMethod) const -{ - return ::lseek(_handle, distanceToMove, moveMethod); -} - -///////////////////////// -// CInFile - -bool CInFile::Open(const char *name) -{ - return CFileBase::OpenBinary(name, O_RDONLY); -} - -bool CInFile::OpenShared(const char *name, bool) -{ - return Open(name); -} - -ssize_t CInFile::Read(void *data, size_t size) -{ - return read(_handle, data, size); -} - -///////////////////////// -// COutFile - -bool COutFile::Create(const char *name, bool createAlways) -{ - if (createAlways) - { - Close(); - _handle = ::creat(name, 0666); - return _handle != -1; - } - return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY); -} - -bool COutFile::Open(const char *name, DWORD creationDisposition) -{ - return Create(name, false); -} - -ssize_t COutFile::Write(const void *data, size_t size) -{ - return write(_handle, data, size); -} - -}}} diff --git a/src/libs/7zip/win/CPP/Common/C_FileIO.h b/src/libs/7zip/win/CPP/Common/C_FileIO.h deleted file mode 100644 index 27aa56869..000000000 --- a/src/libs/7zip/win/CPP/Common/C_FileIO.h +++ /dev/null @@ -1,47 +0,0 @@ -// Common/C_FileIO.h - -#ifndef __COMMON_C_FILEIO_H -#define __COMMON_C_FILEIO_H - -#include -#include - -#include "Types.h" -#include "MyWindows.h" - -namespace NC { -namespace NFile { -namespace NIO { - -class CFileBase -{ -protected: - int _handle; - bool OpenBinary(const char *name, int flags); -public: - CFileBase(): _handle(-1) {}; - ~CFileBase() { Close(); } - bool Close(); - bool GetLength(UInt64 &length) const; - off_t Seek(off_t distanceToMove, int moveMethod) const; -}; - -class CInFile: public CFileBase -{ -public: - bool Open(const char *name); - bool OpenShared(const char *name, bool shareForWrite); - ssize_t Read(void *data, size_t size); -}; - -class COutFile: public CFileBase -{ -public: - bool Create(const char *name, bool createAlways); - bool Open(const char *name, DWORD creationDisposition); - ssize_t Write(const void *data, size_t size); -}; - -}}} - -#endif diff --git a/src/libs/7zip/win/CPP/Common/ComTry.h b/src/libs/7zip/win/CPP/Common/ComTry.h index fb4ef0459..c8aa4aedc 100644 --- a/src/libs/7zip/win/CPP/Common/ComTry.h +++ b/src/libs/7zip/win/CPP/Common/ComTry.h @@ -9,7 +9,7 @@ #define COM_TRY_BEGIN try { #define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; } - + // catch(const CNewException &) { return E_OUTOFMEMORY; } // catch(const CSystemException &e) { return e.ErrorCode; } // catch(...) { return E_FAIL; } diff --git a/src/libs/7zip/win/CPP/Common/CommandLineParser.cpp b/src/libs/7zip/win/CPP/Common/CommandLineParser.cpp index 80b467fcb..ac9ae1960 100644 --- a/src/libs/7zip/win/CPP/Common/CommandLineParser.cpp +++ b/src/libs/7zip/win/CPP/Common/CommandLineParser.cpp @@ -4,6 +4,20 @@ #include "CommandLineParser.h" +static bool IsString1PrefixedByString2_NoCase(const wchar_t *u, const char *a) +{ + for (;;) + { + char c = *a; + if (c == 0) + return true; + if (MyCharLower_Ascii(c) != MyCharLower_Ascii(*u)) + return false; + a++; + u++; + } +} + namespace NCommandLineParser { bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2) @@ -11,13 +25,13 @@ bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2) dest1.Empty(); dest2.Empty(); bool quoteMode = false; - int i; - for (i = 0; i < src.Length(); i++) + unsigned i; + for (i = 0; i < src.Len(); i++) { wchar_t c = src[i]; - if (c == L' ' && !quoteMode) + if ((c == L' ' || c == L'\t') && !quoteMode) { - dest2 = src.Mid(i + 1); + dest2 = src.Ptr(i + 1); return i != 0; } if (c == L'\"') @@ -45,21 +59,18 @@ void SplitCommandLine(const UString &s, UStringVector &parts) } -static const wchar_t kSwitchID1 = '-'; -// static const wchar_t kSwitchID2 = '/'; - -static const wchar_t kSwitchMinus = '-'; -static const wchar_t *kStopSwitchParsing = L"--"; +static const char *kStopSwitchParsing = "--"; -static bool IsItSwitchChar(wchar_t c) +static bool inline IsItSwitchChar(wchar_t c) { - return (c == kSwitchID1 /*|| c == kSwitchID2 */); + return (c == '-'); } -CParser::CParser(int numSwitches): - _numSwitches(numSwitches) +CParser::CParser(unsigned numSwitches): + _numSwitches(numSwitches), + _switches(0) { - _switches = new CSwitchResult[_numSwitches]; + _switches = new CSwitchResult[numSwitches]; } CParser::~CParser() @@ -67,163 +78,121 @@ CParser::~CParser() delete []_switches; } -void CParser::ParseStrings(const CSwitchForm *switchForms, - const UStringVector &commandStrings) + +// if (s) contains switch then function updates switch structures +// out: true, if (s) is a switch +bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) { - int numCommandStrings = commandStrings.Size(); - bool stopSwitch = false; - for (int i = 0; i < numCommandStrings; i++) + if (s.IsEmpty() || !IsItSwitchChar(s[0])) + return false; + + unsigned pos = 1; + unsigned switchIndex = 0; + int maxLen = -1; + + for (unsigned i = 0; i < _numSwitches; i++) { - const UString &s = commandStrings[i]; - if (stopSwitch) - NonSwitchStrings.Add(s); - else - if (s == kStopSwitchParsing) - stopSwitch = true; - else - if (!ParseString(s, switchForms)) - NonSwitchStrings.Add(s); + const char *key = switchForms[i].Key; + unsigned switchLen = MyStringLen(key); + if ((int)switchLen <= maxLen || pos + switchLen > s.Len()) + continue; + if (IsString1PrefixedByString2_NoCase((const wchar_t *)s + pos, key)) + { + switchIndex = i; + maxLen = switchLen; + } } -} -// if string contains switch then function updates switch structures -// out: (string is a switch) -bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) -{ - int len = s.Length(); - if (len == 0) + if (maxLen < 0) + { + ErrorMessage = "Unknown switch:"; return false; - int pos = 0; - if (!IsItSwitchChar(s[pos])) + } + + pos += maxLen; + + CSwitchResult &sw = _switches[switchIndex]; + const CSwitchForm &form = switchForms[switchIndex]; + + if (!form.Multi && sw.ThereIs) + { + ErrorMessage = "Multiple instances for switch:"; return false; - while (pos < len) + } + + sw.ThereIs = true; + + int rem = s.Len() - pos; + if (rem < form.MinLen) { - if (IsItSwitchChar(s[pos])) - pos++; - const int kNoLen = -1; - int matchedSwitchIndex = 0; // GCC Warning - int maxLen = kNoLen; - for (int switchIndex = 0; switchIndex < _numSwitches; switchIndex++) - { - int switchLen = MyStringLen(switchForms[switchIndex].IDString); - if (switchLen <= maxLen || pos + switchLen > len) - continue; + ErrorMessage = "Too short switch:"; + return false; + } + + sw.WithMinus = false; + sw.PostCharIndex = -1; - UString temp = s + pos; - temp = temp.Left(switchLen); - if (temp.CompareNoCase(switchForms[switchIndex].IDString) == 0) - // if (_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0) + switch (form.Type) + { + case NSwitchType::kMinus: + if (rem != 0) { - matchedSwitchIndex = switchIndex; - maxLen = switchLen; + sw.WithMinus = (s[pos] == '-'); + if (sw.WithMinus) + pos++; } - } - if (maxLen == kNoLen) - throw "maxLen == kNoLen"; - CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex]; - const CSwitchForm &switchForm = switchForms[matchedSwitchIndex]; - if ((!switchForm.Multi) && matchedSwitch.ThereIs) - throw "switch must be single"; - matchedSwitch.ThereIs = true; - pos += maxLen; - int tailSize = len - pos; - NSwitchType::EEnum type = switchForm.Type; - switch(type) - { - case NSwitchType::kPostMinus: - { - if (tailSize == 0) - matchedSwitch.WithMinus = false; - else - { - matchedSwitch.WithMinus = (s[pos] == kSwitchMinus); - if (matchedSwitch.WithMinus) - pos++; - } - break; - } - case NSwitchType::kPostChar: - { - if (tailSize < switchForm.MinLen) - throw "switch is not full"; - UString set = switchForm.PostCharSet; - const int kEmptyCharValue = -1; - if (tailSize == 0) - matchedSwitch.PostCharIndex = kEmptyCharValue; - else - { - int index = set.Find(s[pos]); - if (index < 0) - matchedSwitch.PostCharIndex = kEmptyCharValue; - else - { - matchedSwitch.PostCharIndex = index; - pos++; - } - } - break; - } - case NSwitchType::kLimitedPostString: - case NSwitchType::kUnLimitedPostString: + break; + + case NSwitchType::kChar: + if (rem != 0) + { + wchar_t c = s[pos]; + if (c <= 0x7F) { - int minLen = switchForm.MinLen; - if (tailSize < minLen) - throw "switch is not full"; - if (type == NSwitchType::kUnLimitedPostString) - { - matchedSwitch.PostStrings.Add(s.Mid(pos)); - return true; - } - int maxLen = switchForm.MaxLen; - UString stringSwitch = s.Mid(pos, minLen); - pos += minLen; - for (int i = minLen; i < maxLen && pos < len; i++, pos++) - { - wchar_t c = s[pos]; - if (IsItSwitchChar(c)) - break; - stringSwitch += c; - } - matchedSwitch.PostStrings.Add(stringSwitch); - break; + sw.PostCharIndex = FindCharPosInString(form.PostCharSet, (char)c); + if (sw.PostCharIndex >= 0) + pos++; } - case NSwitchType::kSimple: - break; - } + } + break; + + case NSwitchType::kString: + sw.PostStrings.Add((const wchar_t *)s + pos); + return true; + } + if (pos != s.Len()) + { + ErrorMessage = "Too long switch:"; + return false; } return true; } -const CSwitchResult& CParser::operator[](size_t index) const -{ - return _switches[index]; -} - -///////////////////////////////// -// Command parsing procedures - -int ParseCommand(int numCommandForms, const CCommandForm *commandForms, - const UString &commandString, UString &postString) +bool CParser::ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings) { - for (int i = 0; i < numCommandForms; i++) + ErrorLine.Empty(); + bool stopSwitch = false; + FOR_VECTOR (i, commandStrings) { - const UString id = commandForms[i].IDString; - if (commandForms[i].PostStringMode) + const UString &s = commandStrings[i]; + if (!stopSwitch) { - if (commandString.Find(id) == 0) + if (s.IsEqualTo(kStopSwitchParsing)) { - postString = commandString.Mid(id.Length()); - return i; + stopSwitch = true; + continue; } - } - else - if (commandString == id) + if (!s.IsEmpty() && IsItSwitchChar(s[0])) { - postString.Empty(); - return i; + if (ParseString(s, switchForms)) + continue; + ErrorLine = s; + return false; } + } + NonSwitchStrings.Add(s); } - return -1; + return true; } - + } diff --git a/src/libs/7zip/win/CPP/Common/CommandLineParser.h b/src/libs/7zip/win/CPP/Common/CommandLineParser.h index 3d0b41dd4..e3e6e6b14 100644 --- a/src/libs/7zip/win/CPP/Common/CommandLineParser.h +++ b/src/libs/7zip/win/CPP/Common/CommandLineParser.h @@ -10,63 +10,54 @@ namespace NCommandLineParser { bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2); void SplitCommandLine(const UString &s, UStringVector &parts); -namespace NSwitchType { +namespace NSwitchType +{ enum EEnum { kSimple, - kPostMinus, - kLimitedPostString, - kUnLimitedPostString, - kPostChar + kMinus, + kString, + kChar }; } struct CSwitchForm { - const wchar_t *IDString; - NSwitchType::EEnum Type; + const char *Key; + Byte Type; bool Multi; - int MinLen; - int MaxLen; - const wchar_t *PostCharSet; + Byte MinLen; + // int MaxLen; + const char *PostCharSet; }; struct CSwitchResult { bool ThereIs; bool WithMinus; - UStringVector PostStrings; int PostCharIndex; + UStringVector PostStrings; + CSwitchResult(): ThereIs(false) {}; }; - + class CParser { - int _numSwitches; + unsigned _numSwitches; CSwitchResult *_switches; + bool ParseString(const UString &s, const CSwitchForm *switchForms); public: UStringVector NonSwitchStrings; - CParser(int numSwitches); - ~CParser(); - void ParseStrings(const CSwitchForm *switchForms, - const UStringVector &commandStrings); - const CSwitchResult& operator[](size_t index) const; -}; - -///////////////////////////////// -// Command parsing procedures + AString ErrorMessage; + UString ErrorLine; -struct CCommandForm -{ - const wchar_t *IDString; - bool PostStringMode; + CParser(unsigned numSwitches); + ~CParser(); + bool ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings); + const CSwitchResult& operator[](size_t index) const { return _switches[index]; } }; -// Returns: Index of form and postString; -1, if there is no match -int ParseCommand(int numCommandForms, const CCommandForm *commandForms, - const UString &commandString, UString &postString); - } #endif diff --git a/src/libs/7zip/win/CPP/Common/Common.h b/src/libs/7zip/win/CPP/Common/Common.h new file mode 100644 index 000000000..9dd30f4be --- /dev/null +++ b/src/libs/7zip/win/CPP/Common/Common.h @@ -0,0 +1,13 @@ +// Common.h + +#ifndef __COMMON_COMMON_H +#define __COMMON_COMMON_H + +#include "../../C/Compiler.h" + +#include "MyWindows.h" +#include "NewHandler.h" + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[1])) + +#endif diff --git a/src/libs/7zip/win/CPP/Common/Common.pri b/src/libs/7zip/win/CPP/Common/Common.pri new file mode 100644 index 000000000..ecc997d89 --- /dev/null +++ b/src/libs/7zip/win/CPP/Common/Common.pri @@ -0,0 +1,35 @@ +HEADERS += $$7ZIP_BASE/CPP/Common/CommandLineParser.h \ + $$7ZIP_BASE/CPP/Common/ComTry.h \ + $$7ZIP_BASE/CPP/Common/Common.h \ + $$7ZIP_BASE/CPP/Common/Defs.h \ + $$7ZIP_BASE/CPP/Common/IntToString.h \ + $$7ZIP_BASE/CPP/Common/ListFileUtils.h \ + $$7ZIP_BASE/CPP/Common/MyBuffer.h \ + $$7ZIP_BASE/CPP/Common/MyCom.h \ + $$7ZIP_BASE/CPP/Common/MyException.h \ + $$7ZIP_BASE/CPP/Common/MyGuidDef.h \ + $$7ZIP_BASE/CPP/Common/MyInitGuid.h \ + $$7ZIP_BASE/CPP/Common/MyString.h \ + $$7ZIP_BASE/CPP/Common/MyTypes.h \ + $$7ZIP_BASE/CPP/Common/MyUnknown.h \ + $$7ZIP_BASE/CPP/Common/MyVector.h \ + $$7ZIP_BASE/CPP/Common/MyWindows.h \ + $$7ZIP_BASE/CPP/Common/NewHandler.h \ + $$7ZIP_BASE/CPP/Common/StdAfx.h \ + $$7ZIP_BASE/CPP/Common/StdOutStream.h \ + $$7ZIP_BASE/CPP/Common/StringConvert.h \ + $$7ZIP_BASE/CPP/Common/StringToInt.h \ + $$7ZIP_BASE/CPP/Common/UTFConvert.h \ + $$7ZIP_BASE/CPP/Common/Wildcard.h + +SOURCES += $$7ZIP_BASE/CPP/Common/CommandLineParser.cpp \ + $$7ZIP_BASE/CPP/Common/IntToString.cpp \ + $$7ZIP_BASE/CPP/Common/ListFileUtils.cpp \ + $$7ZIP_BASE/CPP/Common/MyString.cpp \ + $$7ZIP_BASE/CPP/Common/MyWindows.cpp \ + $$7ZIP_BASE/CPP/Common/NewHandler.cpp \ + $$7ZIP_BASE/CPP/Common/StdOutStream.cpp \ + $$7ZIP_BASE/CPP/Common/StringConvert.cpp \ + $$7ZIP_BASE/CPP/Common/StringToInt.cpp \ + $$7ZIP_BASE/CPP/Common/UTFConvert.cpp \ + $$7ZIP_BASE/CPP/Common/Wildcard.cpp diff --git a/src/libs/7zip/win/CPP/Common/DynamicBuffer.h b/src/libs/7zip/win/CPP/Common/DynamicBuffer.h deleted file mode 100644 index eaac123e1..000000000 --- a/src/libs/7zip/win/CPP/Common/DynamicBuffer.h +++ /dev/null @@ -1,50 +0,0 @@ -// Common/DynamicBuffer.h - -#ifndef __COMMON_DYNAMIC_BUFFER_H -#define __COMMON_DYNAMIC_BUFFER_H - -#include "Buffer.h" - -template class CDynamicBuffer: public CBuffer -{ - void GrowLength(size_t size) - { - size_t delta; - if (this->_capacity > 64) - delta = this->_capacity / 4; - else if (this->_capacity > 8) - delta = 16; - else - delta = 4; - delta = MyMax(delta, size); - size_t newCap = this->_capacity + delta; - if (newCap < delta) - newCap = this->_capacity + size; - this->SetCapacity(newCap); - } -public: - CDynamicBuffer(): CBuffer() {}; - CDynamicBuffer(const CDynamicBuffer &buffer): CBuffer(buffer) {}; - CDynamicBuffer(size_t size): CBuffer(size) {}; - CDynamicBuffer& operator=(const CDynamicBuffer &buffer) - { - this->Free(); - if (buffer._capacity > 0) - { - this->SetCapacity(buffer._capacity); - memmove(this->_items, buffer._items, buffer._capacity * sizeof(T)); - } - return *this; - } - void EnsureCapacity(size_t capacity) - { - if (this->_capacity < capacity) - GrowLength(capacity - this->_capacity); - } -}; - -typedef CDynamicBuffer CCharDynamicBuffer; -typedef CDynamicBuffer CWCharDynamicBuffer; -typedef CDynamicBuffer CByteDynamicBuffer; - -#endif diff --git a/src/libs/7zip/win/CPP/Common/IntToString.cpp b/src/libs/7zip/win/CPP/Common/IntToString.cpp index 013fee527..ed217c72c 100644 --- a/src/libs/7zip/win/CPP/Common/IntToString.cpp +++ b/src/libs/7zip/win/CPP/Common/IntToString.cpp @@ -4,74 +4,143 @@ #include "IntToString.h" -void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base) +#define CONVERT_INT_TO_STR(charType, tempSize) \ + unsigned char temp[tempSize]; unsigned i = 0; \ + while (val >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(val % 10)); val /= 10; } \ + *s++ = (charType)('0' + (unsigned)val); \ + while (i != 0) { i--; *s++ = temp[i]; } \ + *s = 0; + +void ConvertUInt32ToString(UInt32 val, char *s) throw() { - if (base < 2 || base > 36) + CONVERT_INT_TO_STR(char, 16); +} + +void ConvertUInt64ToString(UInt64 val, char *s) throw() +{ + if (val <= (UInt32)0xFFFFFFFF) { - *s = '\0'; + ConvertUInt32ToString((UInt32)val, s); return; } - char temp[72]; - int pos = 0; - do + CONVERT_INT_TO_STR(char, 24); +} + +void ConvertUInt64ToOct(UInt64 val, char *s) throw() +{ + UInt64 v = val; + unsigned i; + for (i = 1;; i++) { - int delta = (int)(value % base); - temp[pos++] = (char)((delta < 10) ? ('0' + delta) : ('a' + (delta - 10))); - value /= base; + v >>= 3; + if (v == 0) + break; } - while (value != 0); + s[i] = 0; do - *s++ = temp[--pos]; - while (pos > 0); - *s = '\0'; + { + unsigned t = (unsigned)(val & 0x7); + val >>= 3; + s[--i] = (char)('0' + t); + } + while (i); } -void ConvertUInt64ToString(UInt64 value, wchar_t *s) +void ConvertUInt32ToHex(UInt32 val, char *s) throw() { - wchar_t temp[32]; - int pos = 0; + UInt32 v = val; + unsigned i; + for (i = 1;; i++) + { + v >>= 4; + if (v == 0) + break; + } + s[i] = 0; do { - temp[pos++] = (wchar_t)(L'0' + (int)(value % 10)); - value /= 10; + unsigned t = (unsigned)((val & 0xF)); + val >>= 4; + s[--i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); } - while (value != 0); + while (i); +} + +void ConvertUInt64ToHex(UInt64 val, char *s) throw() +{ + UInt64 v = val; + unsigned i; + for (i = 1;; i++) + { + v >>= 4; + if (v == 0) + break; + } + s[i] = 0; do - *s++ = temp[--pos]; - while (pos > 0); - *s = L'\0'; + { + unsigned t = (unsigned)((val & 0xF)); + val >>= 4; + s[--i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } + while (i); } -void ConvertUInt32ToString(UInt32 value, char *s) { ConvertUInt64ToString(value, s); } -void ConvertUInt32ToString(UInt32 value, wchar_t *s) { ConvertUInt64ToString(value, s); } +void ConvertUInt32ToHex8Digits(UInt32 val, char *s) throw() +{ + s[8] = 0; + for (int i = 7; i >= 0; i--) + { + unsigned t = val & 0xF; + val >>= 4; + s[i] = (char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))); + } +} -void ConvertInt64ToString(Int64 value, char *s) +/* +void ConvertUInt32ToHex8Digits(UInt32 val, wchar_t *s) { - if (value < 0) + s[8] = 0; + for (int i = 7; i >= 0; i--) { - *s++ = '-'; - value = -value; + unsigned t = val & 0xF; + val >>= 4; + s[i] = (wchar_t)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))); + } +} +*/ + +void ConvertUInt32ToString(UInt32 val, wchar_t *s) throw() +{ + CONVERT_INT_TO_STR(wchar_t, 16); +} + +void ConvertUInt64ToString(UInt64 val, wchar_t *s) throw() +{ + if (val <= (UInt32)0xFFFFFFFF) + { + ConvertUInt32ToString((UInt32)val, s); + return; } - ConvertUInt64ToString(value, s); + CONVERT_INT_TO_STR(wchar_t, 24); } -void ConvertInt64ToString(Int64 value, wchar_t *s) +void ConvertInt64ToString(Int64 val, char *s) throw() { - if (value < 0) + if (val < 0) { - *s++ = L'-'; - value = -value; + *s++ = '-'; + val = -val; } - ConvertUInt64ToString(value, s); + ConvertUInt64ToString(val, s); } -void ConvertUInt32ToHexWithZeros(UInt32 value, char *s) +void ConvertInt64ToString(Int64 val, wchar_t *s) throw() { - for (int i = 0; i < 8; i++) + if (val < 0) { - int t = value & 0xF; - value >>= 4; - s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + *s++ = L'-'; + val = -val; } - s[8] = '\0'; + ConvertUInt64ToString(val, s); } diff --git a/src/libs/7zip/win/CPP/Common/IntToString.h b/src/libs/7zip/win/CPP/Common/IntToString.h index 782f930c5..69605ab76 100644 --- a/src/libs/7zip/win/CPP/Common/IntToString.h +++ b/src/libs/7zip/win/CPP/Common/IntToString.h @@ -3,17 +3,22 @@ #ifndef __COMMON_INT_TO_STRING_H #define __COMMON_INT_TO_STRING_H -#include -#include "Types.h" +#include "MyTypes.h" -void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base = 10); -void ConvertUInt64ToString(UInt64 value, wchar_t *s); -void ConvertInt64ToString(Int64 value, char *s); -void ConvertInt64ToString(Int64 value, wchar_t *s); +void ConvertUInt32ToString(UInt32 value, char *s) throw(); +void ConvertUInt64ToString(UInt64 value, char *s) throw(); -void ConvertUInt32ToString(UInt32 value, char *s); -void ConvertUInt32ToString(UInt32 value, wchar_t *s); +void ConvertUInt32ToString(UInt32 value, wchar_t *s) throw(); +void ConvertUInt64ToString(UInt64 value, wchar_t *s) throw(); -void ConvertUInt32ToHexWithZeros(UInt32 value, char *s); +void ConvertUInt64ToOct(UInt64 value, char *s) throw(); + +void ConvertUInt32ToHex(UInt32 value, char *s) throw(); +void ConvertUInt64ToHex(UInt64 value, char *s) throw(); +void ConvertUInt32ToHex8Digits(UInt32 value, char *s) throw(); +// void ConvertUInt32ToHex8Digits(UInt32 value, wchar_t *s) throw(); + +void ConvertInt64ToString(Int64 value, char *s) throw(); +void ConvertInt64ToString(Int64 value, wchar_t *s) throw(); #endif diff --git a/src/libs/7zip/win/CPP/Common/ListFileUtils.cpp b/src/libs/7zip/win/CPP/Common/ListFileUtils.cpp index c1c682a2c..4d7faeca3 100644 --- a/src/libs/7zip/win/CPP/Common/ListFileUtils.cpp +++ b/src/libs/7zip/win/CPP/Common/ListFileUtils.cpp @@ -2,74 +2,116 @@ #include "StdAfx.h" -#include "MyWindows.h" +#include "../../C/CpuArch.h" + #include "../Windows/FileIO.h" #include "ListFileUtils.h" +#include "MyBuffer.h" #include "StringConvert.h" #include "UTFConvert.h" -static const char kQuoteChar = '\"'; -static void RemoveQuote(UString &s) +static const char kQuoteChar = '\"'; + +static void AddName(UStringVector &strings, UString &s) { - if (s.Length() >= 2) - if (s[0] == kQuoteChar && s[s.Length() - 1] == kQuoteChar) - s = s.Mid(1, s.Length() - 2); + s.Trim(); + if (s.Len() >= 2 && s[0] == kQuoteChar && s.Back() == kQuoteChar) + { + s.DeleteBack(); + s.Delete(0); + } + if (!s.IsEmpty()) + strings.Add(s); } -bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &resultStrings, UINT codePage) +bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage) { NWindows::NFile::NIO::CInFile file; if (!file.Open(fileName)) return false; - UInt64 length; - if (!file.GetLength(length)) - return false; - if (length > ((UInt32)1 << 31)) + UInt64 fileSize; + if (!file.GetLength(fileSize)) return false; - AString s; - char *p = s.GetBuffer((int)length + 1); - UInt32 processed; - if (!file.Read(p, (UInt32)length, processed)) + if (fileSize >= ((UInt32)1 << 31) - 32) return false; - p[(UInt32)length] = 0; - s.ReleaseBuffer(); - file.Close(); - UString u; - #ifdef CP_UTF8 - if (codePage == CP_UTF8) + if (codePage == MY__CP_UTF16 || codePage == MY__CP_UTF16BE) { - if (!ConvertUTF8ToUnicode(s, u)) + if ((fileSize & 1) != 0) + return false; + CByteArr buf((size_t)fileSize); + UInt32 processed; + if (!file.Read(buf, (UInt32)fileSize, processed)) return false; + if (processed != fileSize) + return false; + file.Close(); + unsigned num = (unsigned)fileSize / 2; + wchar_t *p = u.GetBuffer(num); + if (codePage == MY__CP_UTF16) + for (unsigned i = 0; i < num; i++) + { + wchar_t c = GetUi16(buf + i * 2); + if (c == 0) + return false; + p[i] = c; + } + else + for (unsigned i = 0; i < num; i++) + { + wchar_t c = (wchar_t)GetBe16(buf + i * 2); + if (c == 0) + return false; + p[i] = c; + } + u.ReleaseBuffer(num); } else - #endif - u = MultiByteToUnicodeString(s, codePage); - if (!u.IsEmpty()) { - if (u[0] == 0xFEFF) - u.Delete(0); + AString s; + char *p = s.GetBuffer((unsigned)fileSize); + UInt32 processed; + if (!file.Read(p, (UInt32)fileSize, processed)) + return false; + if (processed != fileSize) + return false; + file.Close(); + p[processed] = 0; + s.ReleaseBuffer(); + if (s.Len() != processed) + return false; + + // #ifdef CP_UTF8 + if (codePage == CP_UTF8) + { + if (!ConvertUTF8ToUnicode(s, u)) + return false; + } + else + // #endif + MultiByteToUnicodeString2(u, s, codePage); } - UString t; - for (int i = 0; i < u.Length(); i++) + const wchar_t kGoodBOM = 0xFEFF; + const wchar_t kBadBOM = 0xFFFE; + + UString s; + unsigned i = 0; + for (; i < u.Len() && u[i] == kGoodBOM; i++); + for (; i < u.Len(); i++) { wchar_t c = u[i]; + if (c == kGoodBOM || c == kBadBOM) + return false; if (c == L'\n' || c == 0xD) { - t.Trim(); - RemoveQuote(t); - if (!t.IsEmpty()) - resultStrings.Add(t); - t.Empty(); + AddName(strings, s); + s.Empty(); } else - t += c; + s += c; } - t.Trim(); - RemoveQuote(t); - if (!t.IsEmpty()) - resultStrings.Add(t); + AddName(strings, s); return true; } diff --git a/src/libs/7zip/win/CPP/Common/ListFileUtils.h b/src/libs/7zip/win/CPP/Common/ListFileUtils.h index c58a8bd42..e8d833fdb 100644 --- a/src/libs/7zip/win/CPP/Common/ListFileUtils.h +++ b/src/libs/7zip/win/CPP/Common/ListFileUtils.h @@ -1,11 +1,14 @@ // Common/ListFileUtils.h -#ifndef __COMMON_LISTFILEUTILS_H -#define __COMMON_LISTFILEUTILS_H +#ifndef __COMMON_LIST_FILE_UTILS_H +#define __COMMON_LIST_FILE_UTILS_H #include "MyString.h" -#include "Types.h" +#include "MyTypes.h" -bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP); +#define MY__CP_UTF16 1200 +#define MY__CP_UTF16BE 1201 + +bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP); #endif diff --git a/src/libs/7zip/win/CPP/Common/MyBuffer.h b/src/libs/7zip/win/CPP/Common/MyBuffer.h new file mode 100644 index 000000000..7bd79f6f4 --- /dev/null +++ b/src/libs/7zip/win/CPP/Common/MyBuffer.h @@ -0,0 +1,237 @@ +// Common/MyBuffer.h + +#ifndef __COMMON_MY_BUFFER_H +#define __COMMON_MY_BUFFER_H + +#include "Defs.h" + +template class CBuffer +{ + T *_items; + size_t _size; + + void CopyToEmpty(const CBuffer &buffer) + { + if (buffer._size > 0) + { + _items = new T[buffer._size]; + memcpy(_items, buffer._items, buffer._size * sizeof(T)); + _size = buffer._size; + } + } +public: + void Free() + { + if (_items) + { + delete []_items; + _items = 0; + } + _size = 0; + } + + CBuffer(): _items(0), _size(0) {}; + CBuffer(size_t size): _items(0), _size(0) { _items = new T[size]; _size = size; } + CBuffer(const CBuffer &buffer): _items(0), _size(0) { CopyToEmpty(buffer); } + ~CBuffer() { delete []_items; } + + operator T *() { return _items; }; + operator const T *() const { return _items; }; + size_t Size() const { return _size; } + + void Alloc(size_t size) + { + if (size != _size) + { + Free(); + if (size != 0) + { + _items = new T[size]; + _size = size; + } + } + } + + void AllocAtLeast(size_t size) + { + if (size > _size) + { + Free(); + _items = new T[size]; + _size = size; + } + } + + void CopyFrom(const T *data, size_t size) + { + Alloc(size); + memcpy(_items, data, size * sizeof(T)); + } + + void ChangeSize_KeepData(size_t newSize, size_t keepSize) + { + if (newSize == _size) + return; + T *newBuffer = NULL; + if (newSize > 0) + { + newBuffer = new T[newSize]; + if (_size > 0) + memcpy(newBuffer, _items, MyMin(MyMin(_size, keepSize), newSize) * sizeof(T)); + } + delete []_items; + _items = newBuffer; + _size = newSize; + } + + CBuffer& operator=(const CBuffer &buffer) + { + Free(); + CopyToEmpty(buffer); + return *this; + } +}; + +template +bool operator==(const CBuffer& b1, const CBuffer& b2) +{ + size_t size1 = b1.Size(); + if (size1 != b2.Size()) + return false; + return memcmp(b1, b2, size1 * sizeof(T)) == 0; +} + +template +bool operator!=(const CBuffer& b1, const CBuffer& b2) +{ + size_t size1 = b1.Size(); + if (size1 == b2.Size()) + return false; + return memcmp(b1, b2, size1 * sizeof(T)) != 0; +} + + +typedef CBuffer CCharBuffer; +typedef CBuffer CWCharBuffer; +typedef CBuffer CByteBuffer; + + +template class CObjArray +{ +protected: + T *_items; +private: + // we disable constructors + CObjArray(const CObjArray &buffer); + void operator=(const CObjArray &buffer); +public: + void Free() + { + delete []_items; + _items = 0; + } + CObjArray(size_t size): _items(0) { if (size != 0) _items = new T[size]; } + CObjArray(): _items(0) {}; + ~CObjArray() { delete []_items; } + + operator T *() { return _items; }; + operator const T *() const { return _items; }; + + void Alloc(size_t newSize) + { + delete []_items; + _items = 0; + _items = new T[newSize]; + } +}; + +typedef CObjArray CByteArr; +typedef CObjArray CBoolArr; +typedef CObjArray CIntArr; + +// #define CRecArray CObjArray + +template class CObjArray2 +{ +// protected: + T *_items; + unsigned _size; + + CObjArray2(const CObjArray2 &buffer); + void operator=(const CObjArray2 &buffer); +public: + + void Free() + { + delete []_items; + _items = 0; + _size = 0; + } + CObjArray2(): _items(0), _size(0) {}; + /* + CObjArray2(const CObjArray2 &buffer): _items(0), _size(0) + { + size_t newSize = buffer._size; + if (newSize > 0) + { + T *newBuffer = new T[newSize];; + _items = newBuffer; + _size = newSize; + const T *src = buffer; + for (size_t i = 0; i < newSize; i++) + newBuffer[i] = src[i]; + } + } + */ + /* + CObjArray2(size_t size): _items(0), _size(0) + { + if (size != 0) + { + _items = new T[size]; + _size = size; + } + } + */ + + ~CObjArray2() { delete []_items; } + + operator T *() { return _items; }; + operator const T *() const { return _items; }; + + unsigned Size() const { return (unsigned)_size; } + bool IsEmpty() const { return _size == 0; } + + // SetSize doesn't keep old items. It allocates new array if size is not equal + void SetSize(unsigned size) + { + if (size == _size) + return; + T *newBuffer = NULL; + if (size > 0) + newBuffer = new T[size]; + delete []_items; + _items = newBuffer; + _size = size; + } + + /* + CObjArray2& operator=(const CObjArray2 &buffer) + { + Free(); + size_t newSize = buffer._size; + if (newSize > 0) + { + T *newBuffer = new T[newSize];; + _items = newBuffer; + _size = newSize; + const T *src = buffer; + for (size_t i = 0; i < newSize; i++) + newBuffer[i] = src[i]; + } + return *this; + } + */ +}; + +#endif diff --git a/src/libs/7zip/win/CPP/Common/MyCom.h b/src/libs/7zip/win/CPP/Common/MyCom.h index 2f00c258f..466407cde 100644 --- a/src/libs/7zip/win/CPP/Common/MyCom.h +++ b/src/libs/7zip/win/CPP/Common/MyCom.h @@ -1,9 +1,10 @@ // MyCom.h -#ifndef __MYCOM_H -#define __MYCOM_H +#ifndef __MY_COM_H +#define __MY_COM_H #include "MyWindows.h" +#include "NewHandler.h" #ifndef RINOK #define RINOK(x) { HRESULT __result_ = (x); if (__result_ != S_OK) return __result_; } @@ -14,14 +15,9 @@ class CMyComPtr { T* _p; public: - // typedef T _PtrClass; - CMyComPtr() { _p = NULL;} - CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); } - CMyComPtr(const CMyComPtr& lp) - { - if ((_p = lp._p) != NULL) - _p->AddRef(); - } + CMyComPtr(): _p(NULL) {} + CMyComPtr(T* p) throw() { if ((_p = p) != NULL) p->AddRef(); } + CMyComPtr(const CMyComPtr& lp) throw() { if ((_p = lp._p) != NULL) _p->AddRef(); } ~CMyComPtr() { if (_p) _p->Release(); } void Release() { if (_p) { _p->Release(); _p = NULL; } } operator T*() const { return (T*)_p; } @@ -30,7 +26,7 @@ public: T* operator->() const { return _p; } T* operator=(T* p) { - if (p != 0) + if (p) p->AddRef(); if (_p) _p->Release(); @@ -40,7 +36,6 @@ public: T* operator=(const CMyComPtr& lp) { return (*this = lp._p); } bool operator!() const { return (_p == NULL); } // bool operator==(T* pT) const { return _p == pT; } - // Compare two objects for equivalence void Attach(T* p2) { Release(); @@ -70,7 +65,7 @@ public: } */ template - HRESULT QueryInterface(REFGUID iid, Q** pp) const + HRESULT QueryInterface(REFGUID iid, Q** pp) const throw() { return _p->QueryInterface(iid, (void**)pp); } @@ -81,13 +76,14 @@ public: inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr) { *bstr = ::SysAllocString(src); - return (*bstr != 0) ? S_OK : E_OUTOFMEMORY; + return (*bstr != NULL) ? S_OK : E_OUTOFMEMORY; } class CMyComBSTR { -public: BSTR m_str; +public: + CMyComBSTR(): m_str(NULL) {} CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); } // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } @@ -119,7 +115,7 @@ public: m_str = ::SysAllocString(src); return *this; } - unsigned int Length() const { return ::SysStringLen(m_str); } + // unsigned Len() const { return ::SysStringLen(m_str); } operator BSTR() const { return m_str; } BSTR* operator&() { return &m_str; } BSTR MyCopy() const @@ -143,7 +139,7 @@ public: ::SysFreeString(m_str); m_str = NULL; } - bool operator!() const { return (m_str == NULL); } + bool operator!() const { return (m_str == NULL); } }; ////////////////////////////////////////////////////////// @@ -156,22 +152,22 @@ public: }; #define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ - (REFGUID iid, void **outObject) { +(REFGUID iid, void **outObject) throw() { *outObject = NULL; -#define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \ - { *outObject = (void *)(i *)this; AddRef(); return S_OK; } +#define MY_QUERYINTERFACE_ENTRY(i) else if (iid == IID_ ## i) \ + { *outObject = (void *)(i *)this; } #define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \ - { *outObject = (void *)(IUnknown *)(i *)this; AddRef(); return S_OK; } + { *outObject = (void *)(IUnknown *)(i *)this; } #define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ MY_QUERYINTERFACE_ENTRY(i) -#define MY_QUERYINTERFACE_END return E_NOINTERFACE; } +#define MY_QUERYINTERFACE_END else return E_NOINTERFACE; AddRef(); return S_OK; } #define MY_ADDREF_RELEASE \ -STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \ +STDMETHOD_(ULONG, AddRef)() throw() { return ++__m_RefCount; } \ STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ return __m_RefCount; delete this; return 0; } @@ -222,4 +218,25 @@ STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ MY_QUERYINTERFACE_ENTRY(i5) \ ) +#define MY_UNKNOWN_IMP6(i1, i2, i3, i4, i5, i6) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + MY_QUERYINTERFACE_ENTRY(i4) \ + MY_QUERYINTERFACE_ENTRY(i5) \ + MY_QUERYINTERFACE_ENTRY(i6) \ + ) + +#define MY_UNKNOWN_IMP7(i1, i2, i3, i4, i5, i6, i7) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + MY_QUERYINTERFACE_ENTRY(i4) \ + MY_QUERYINTERFACE_ENTRY(i5) \ + MY_QUERYINTERFACE_ENTRY(i6) \ + MY_QUERYINTERFACE_ENTRY(i7) \ + ) + #endif diff --git a/src/libs/7zip/win/CPP/Common/MyGuidDef.h b/src/libs/7zip/win/CPP/Common/MyGuidDef.h index 3c52cc07d..68745870e 100644 --- a/src/libs/7zip/win/CPP/Common/MyGuidDef.h +++ b/src/libs/7zip/win/CPP/Common/MyGuidDef.h @@ -3,7 +3,7 @@ #ifndef GUID_DEFINED #define GUID_DEFINED -#include "Types.h" +#include "MyTypes.h" typedef struct { UInt32 Data1; diff --git a/src/libs/7zip/win/CPP/Common/MyInitGuid.h b/src/libs/7zip/win/CPP/Common/MyInitGuid.h index d6a486980..279fba5d6 100644 --- a/src/libs/7zip/win/CPP/Common/MyInitGuid.h +++ b/src/libs/7zip/win/CPP/Common/MyInitGuid.h @@ -3,20 +3,43 @@ #ifndef __COMMON_MY_INITGUID_H #define __COMMON_MY_INITGUID_H +/* +This file must be included only to one C++ file in project before +declarations of COM interfaces with DEFINE_GUID macro. + +Each GUID must be initialized exactly once in project. +There are two different versions of the DEFINE_GUID macro in guiddef.h (MyGuidDef.h): + - if INITGUID is not defined: DEFINE_GUID declares an external reference to the symbol name. + - if INITGUID is defined: DEFINE_GUID initializes the symbol name to the value of the GUID. + +Also we need IID_IUnknown that is initialized in some file for linking: + MSVC: by default the linker uses some lib file that contains IID_IUnknown + MinGW: add -luuid switch for linker + WinCE: we define IID_IUnknown in this file + Other: we define IID_IUnknown in this file +*/ + #ifdef _WIN32 + #ifdef UNDER_CE #include #endif + #include + #ifdef UNDER_CE DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); #endif + #else + #define INITGUID #include "MyGuidDef.h" DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); + #endif + #endif diff --git a/src/libs/7zip/win/CPP/Common/MyString.cpp b/src/libs/7zip/win/CPP/Common/MyString.cpp index 3d1ce2b84..6fbfa334b 100644 --- a/src/libs/7zip/win/CPP/Common/MyString.cpp +++ b/src/libs/7zip/win/CPP/Common/MyString.cpp @@ -2,32 +2,104 @@ #include "StdAfx.h" -#ifndef _WIN32 +#ifdef _WIN32 +#include +#include +#else #include #endif -#ifndef _UNICODE +#if !defined(_UNICODE) || !defined(USE_UNICODE_FSTRING) #include "StringConvert.h" #endif #include "MyString.h" +#define MY_STRING_NEW(_T_, _size_) new _T_[_size_] +// #define MY_STRING_NEW(_T_, _size_) ((_T_ *)my_new((size_t)(_size_) * sizeof(_T_))) + +/* +inline const char* MyStringGetNextCharPointer(const char *p) throw() +{ + #if defined(_WIN32) && !defined(UNDER_CE) + return CharNextA(p); + #else + return p + 1; + #endif +} +*/ + +int FindCharPosInString(const char *s, char c) throw() +{ + for (const char *p = s;; p++) + { + if (*p == c) + return (int)(p - s); + if (*p == 0) + return -1; + // MyStringGetNextCharPointer(p); + } +} + +int FindCharPosInString(const wchar_t *s, wchar_t c) throw() +{ + for (const wchar_t *p = s;; p++) + { + if (*p == c) + return (int)(p - s); + if (*p == 0) + return -1; + } +} + +/* +void MyStringUpper_Ascii(wchar_t *s) +{ + for (;;) + { + wchar_t c = *s; + if (c == 0) + return; + *s++ = MyCharUpper_Ascii(c); + } +} +*/ + +void MyStringLower_Ascii(wchar_t *s) throw() +{ + for (;;) + { + wchar_t c = *s; + if (c == 0) + return; + *s++ = MyCharLower_Ascii(c); + } +} #ifdef _WIN32 -#ifndef _UNICODE +#ifdef _UNICODE -wchar_t MyCharUpper(wchar_t c) +// wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } +// wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } +// for WinCE - FString - char +// const char *MyStringGetPrevCharPointer(const char * /* base */, const char *p) { return p - 1; } + +#else + +// const char * MyStringGetPrevCharPointer(const char *base, const char *p) throw() { return CharPrevA(base, p); } +// char * MyStringUpper(char *s) { return CharUpperA(s); } +// char * MyStringLower(char *s) { return CharLowerA(s); } + +wchar_t MyCharUpper_WIN(wchar_t c) throw() { - if (c == 0) - return 0; - wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); + wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) - return (wchar_t)(unsigned int)(UINT_PTR)res; - const int kBufferSize = 4; - char s[kBufferSize + 1]; - int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); - if (numChars == 0 || numChars > kBufferSize) + return (wchar_t)(unsigned)(UINT_PTR)res; + const int kBufSize = 4; + char s[kBufSize + 1]; + int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0); + if (numChars == 0 || numChars > kBufSize) return c; s[numChars] = 0; ::CharUpperA(s); @@ -35,24 +107,25 @@ wchar_t MyCharUpper(wchar_t c) return c; } -wchar_t MyCharLower(wchar_t c) +/* +wchar_t MyCharLower_WIN(wchar_t c) { - if (c == 0) - return 0; - wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); + wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) - return (wchar_t)(unsigned int)(UINT_PTR)res; - const int kBufferSize = 4; - char s[kBufferSize + 1]; - int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); - if (numChars == 0 || numChars > kBufferSize) + return (wchar_t)(unsigned)(UINT_PTR)res; + const int kBufSize = 4; + char s[kBufSize + 1]; + int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0); + if (numChars == 0 || numChars > kBufSize) return c; s[numChars] = 0; ::CharLowerA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } +*/ +/* wchar_t * MyStringUpper(wchar_t *s) { if (s == 0) @@ -62,9 +135,12 @@ wchar_t * MyStringUpper(wchar_t *s) return res; AString a = UnicodeStringToMultiByte(s); a.MakeUpper(); - return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); + MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); + return s; } +*/ +/* wchar_t * MyStringLower(wchar_t *s) { if (s == 0) @@ -74,110 +150,149 @@ wchar_t * MyStringLower(wchar_t *s) return res; AString a = UnicodeStringToMultiByte(s); a.MakeLower(); - return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); + MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); + return s; } +*/ #endif -/* -inline int ConvertCompareResult(int r) { return r - 2; } +#endif -int MyStringCollate(const wchar_t *s1, const wchar_t *s2) +bool IsString1PrefixedByString2(const char *s1, const char *s2) throw() { - int res = CompareStringW( - LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1); - #ifdef _UNICODE - return ConvertCompareResult(res); - #else - if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) - return ConvertCompareResult(res); - return MyStringCollate(UnicodeStringToMultiByte(s1), - UnicodeStringToMultiByte(s2)); - #endif + for (;;) + { + unsigned char c2 = (unsigned char)*s2++; if (c2 == 0) return true; + unsigned char c1 = (unsigned char)*s1++; if (c1 != c2) return false; + } } -#ifndef UNDER_CE -int MyStringCollate(const char *s1, const char *s2) +bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw() { - return ConvertCompareResult(CompareStringA( - LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1)); + for (;;) + { + wchar_t c1 = *s1++; + wchar_t c2 = *s2++; + if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2)) return false; + if (c1 == 0) return true; + } } -int MyStringCollateNoCase(const char *s1, const char *s2) +// ---------- ASCII ---------- + +bool AString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw() { - return ConvertCompareResult(CompareStringA( - LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1)); + const char *s1 = _chars; + for (;;) + { + char c2 = *s++; + if (c2 == 0) + return true; + char c1 = *s1++; + if (MyCharLower_Ascii(c1) != + MyCharLower_Ascii(c2)) + return false; + } } -#endif -int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) +bool UString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw() { - int res = CompareStringW( - LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1); - #ifdef _UNICODE - return ConvertCompareResult(res); - #else - if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) - return ConvertCompareResult(res); - return MyStringCollateNoCase(UnicodeStringToMultiByte(s1), - UnicodeStringToMultiByte(s2)); - #endif + const wchar_t *s1 = _chars; + for (;;) + { + char c2 = *s++; + if (c2 == 0) + return true; + wchar_t c1 = *s1++; + if (MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2)) + return false; + } } -*/ -#else +bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw() +{ + for (;;) + { + unsigned char c = *a; + if (c != *u) + return false; + if (c == 0) + return true; + a++; + u++; + } +} -wchar_t MyCharUpper(wchar_t c) +bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw() { - return toupper(c); + for (;;) + { + char c1 = *s1++; + char c2 = *s2++; + if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2)) + return false; + if (c1 == 0) + return true; + } } -/* -int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) +bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw() { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; - wchar_t u1 = MyCharUpper(c1); - wchar_t u2 = MyCharUpper(c2); - - if (u1 < u2) return -1; - if (u1 > u2) return 1; - if (u1 == 0) return 0; + if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2)) + return false; + if (c1 == 0) + return true; } } -*/ -#endif +bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw() +{ + for (;;) + { + wchar_t c1 = *s1++; + char c2 = *s2++; + if (c1 != (unsigned char)c2 && (c1 > 0x7F || MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2))) + return false; + if (c1 == 0) + return true; + } +} -int MyStringCompare(const char *s1, const char *s2) +bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw() { for (;;) { - unsigned char c1 = (unsigned char)*s1++; - unsigned char c2 = (unsigned char)*s2++; - if (c1 < c2) return -1; - if (c1 > c2) return 1; - if (c1 == 0) return 0; + wchar_t c2 = *s2++; if (c2 == 0) return true; + wchar_t c1 = *s1++; if (c1 != c2) return false; } } -int MyStringCompare(const wchar_t *s1, const wchar_t *s2) +// NTFS order: uses upper case +int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw() { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; - if (c1 < c2) return -1; - if (c1 > c2) return 1; + if (c1 != c2) + { + wchar_t u1 = MyCharUpper(c1); + wchar_t u2 = MyCharUpper(c2); + if (u1 < u2) return -1; + if (u1 > u2) return 1; + } if (c1 == 0) return 0; } } -int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) +int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) throw() { - for (;;) + for (; num != 0; num--) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; @@ -190,11 +305,911 @@ int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) } if (c1 == 0) return 0; } + return 0; +} + + +// ---------- AString ---------- + +void AString::InsertSpace(unsigned &index, unsigned size) +{ + Grow(size); + MoveItems(index + size, index); +} + +void AString::ReAlloc(unsigned newLimit) +{ + if (newLimit < _len || newLimit >= 0x20000000) throw 20130220; + // MY_STRING_REALLOC(_chars, char, newLimit + 1, _len + 1); + char *newBuf = MY_STRING_NEW(char, newLimit + 1); + memcpy(newBuf, _chars, (size_t)(_len + 1)); \ + MY_STRING_DELETE(_chars); + _chars = newBuf; + + _limit = newLimit; +} + +void AString::SetStartLen(unsigned len) +{ + _chars = 0; + _chars = MY_STRING_NEW(char, len + 1); + _len = len; + _limit = len; +} + +void AString::Grow_1() +{ + unsigned next = _len; + next += next / 2; + next += 16; + next &= ~(unsigned)15; + ReAlloc(next - 1); +} + +void AString::Grow(unsigned n) +{ + unsigned freeSize = _limit - _len; + if (n <= freeSize) + return; + + unsigned next = _len + n; + next += next / 2; + next += 16; + next &= ~(unsigned)15; + ReAlloc(next - 1); +} + +/* +AString::AString(unsigned num, const char *s) +{ + unsigned len = MyStringLen(s); + if (num > len) + num = len; + SetStartLen(num); + memcpy(_chars, s, num); + _chars[num] = 0; +} +*/ + +AString::AString(unsigned num, const AString &s) +{ + if (num > s._len) + num = s._len; + SetStartLen(num); + memcpy(_chars, s._chars, num); + _chars[num] = 0; +} + +AString::AString(const AString &s, char c) +{ + SetStartLen(s.Len() + 1); + char *chars = _chars; + unsigned len = s.Len(); + memcpy(chars, s, len); + chars[len] = c; + chars[len + 1] = 0; +} + +AString::AString(const char *s1, unsigned num1, const char *s2, unsigned num2) +{ + SetStartLen(num1 + num2); + char *chars = _chars; + memcpy(chars, s1, num1); + memcpy(chars + num1, s2, num2 + 1); +} + +AString operator+(const AString &s1, const AString &s2) { return AString(s1, s1.Len(), s2, s2.Len()); } +AString operator+(const AString &s1, const char *s2) { return AString(s1, s1.Len(), s2, MyStringLen(s2)); } +AString operator+(const char *s1, const AString &s2) { return AString(s1, MyStringLen(s1), s2, s2.Len()); } + +AString::AString() +{ + _chars = 0; + _chars = MY_STRING_NEW(char, 4); + _len = 0; + _limit = 4 - 1; + _chars[0] = 0; +} + +AString::AString(char c) +{ + SetStartLen(1); + _chars[0] = c; + _chars[1] = 0; +} + +AString::AString(const char *s) +{ + SetStartLen(MyStringLen(s)); + MyStringCopy(_chars, s); +} + +AString::AString(const AString &s) +{ + SetStartLen(s._len); + MyStringCopy(_chars, s._chars); +} + +AString &AString::operator=(char c) +{ + if (1 > _limit) + { + char *newBuf = MY_STRING_NEW(char, 1 + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = 1; + } + _len = 1; + _chars[0] = c; + _chars[1] = 0; + return *this; +} + +AString &AString::operator=(const char *s) +{ + unsigned len = MyStringLen(s); + if (len > _limit) + { + char *newBuf = MY_STRING_NEW(char, len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + _len = len; + MyStringCopy(_chars, s); + return *this; +} + +AString &AString::operator=(const AString &s) +{ + if (&s == this) + return *this; + unsigned len = s._len; + if (len > _limit) + { + char *newBuf = MY_STRING_NEW(char, len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + _len = len; + MyStringCopy(_chars, s._chars); + return *this; +} + +AString &AString::operator+=(const char *s) +{ + unsigned len = MyStringLen(s); + Grow(len); + MyStringCopy(_chars + _len, s); + _len += len; + return *this; +} + +AString &AString::operator+=(const AString &s) +{ + Grow(s._len); + MyStringCopy(_chars + _len, s._chars); + _len += s._len; + return *this; +} + +void AString::SetFrom(const char *s, unsigned len) // no check +{ + if (len > _limit) + { + char *newBuf = MY_STRING_NEW(char, len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + memcpy(_chars, s, len); + _chars[len] = 0; + _len = len; +} + +int AString::Find(const AString &s, unsigned startIndex) const throw() +{ + if (s.IsEmpty()) + return startIndex; + for (; startIndex < _len; startIndex++) + { + unsigned j; + for (j = 0; j < s._len && startIndex + j < _len; j++) + if (_chars[startIndex + j] != s._chars[j]) + break; + if (j == s._len) + return (int)startIndex; + } + return -1; +} + +int AString::ReverseFind(char c) const throw() +{ + if (_len == 0) + return -1; + const char *p = _chars + _len - 1; + for (;;) + { + if (*p == c) + return (int)(p - _chars); + if (p == _chars) + return -1; + p--; // p = GetPrevCharPointer(_chars, p); + } +} + +void AString::TrimLeft() throw() +{ + const char *p = _chars; + for (;; p++) + { + char c = *p; + if (c != ' ' && c != '\n' && c != '\t') + break; + } + unsigned pos = (unsigned)(p - _chars); + if (pos != 0) + { + MoveItems(0, pos); + _len -= pos; + } +} + +void AString::TrimRight() throw() +{ + const char *p = _chars; + int i; + for (i = _len - 1; i >= 0; i--) + { + char c = p[i]; + if (c != ' ' && c != '\n' && c != '\t') + break; + } + i++; + if ((unsigned)i != _len) + { + _chars[i] = 0; + _len = i; + } +} + +void AString::InsertAtFront(char c) +{ + if (_limit == _len) + Grow_1(); + MoveItems(1, 0); + _chars[0] = c; + _len++; +} + +/* +void AString::Insert(unsigned index, char c) +{ + InsertSpace(index, 1); + _chars[index] = c; + _len++; +} +*/ + +void AString::Insert(unsigned index, const char *s) +{ + unsigned num = MyStringLen(s); + if (num != 0) + { + InsertSpace(index, num); + memcpy(_chars + index, s, num); + _len += num; + } +} + +void AString::Insert(unsigned index, const AString &s) +{ + unsigned num = s.Len(); + if (num != 0) + { + InsertSpace(index, num); + memcpy(_chars + index, s, num); + _len += num; + } +} + +void AString::RemoveChar(char ch) throw() +{ + int pos = Find(ch); + if (pos < 0) + return; + const char *src = _chars; + char *dest = _chars + pos; + pos++; + unsigned len = _len; + for (; (unsigned)pos < len; pos++) + { + char c = src[(unsigned)pos]; + if (c != ch) + *dest++ = c; + } + *dest = 0; + _len = (unsigned)(dest - _chars); +} + +// !!!!!!!!!!!!!!! test it if newChar = '\0' +void AString::Replace(char oldChar, char newChar) throw() +{ + if (oldChar == newChar) + return; // 0; + // unsigned number = 0; + int pos = 0; + while ((unsigned)pos < _len) + { + pos = Find(oldChar, pos); + if (pos < 0) + break; + _chars[pos] = newChar; + pos++; + // number++; + } + return; // number; +} + +void AString::Replace(const AString &oldString, const AString &newString) +{ + if (oldString.IsEmpty()) + return; // 0; + if (oldString == newString) + return; // 0; + unsigned oldLen = oldString.Len(); + unsigned newLen = newString.Len(); + // unsigned number = 0; + int pos = 0; + while ((unsigned)pos < _len) + { + pos = Find(oldString, pos); + if (pos < 0) + break; + Delete(pos, oldLen); + Insert(pos, newString); + pos += newLen; + // number++; + } + // return number; +} + +void AString::Delete(unsigned index) throw() +{ + MoveItems(index, index + 1); + _len--; +} + +void AString::Delete(unsigned index, unsigned count) throw() +{ + if (index + count > _len) + count = _len - index; + if (count > 0) + { + MoveItems(index, index + count); + _len -= count; + } +} + +void AString::DeleteFrontal(unsigned num) throw() +{ + if (num != 0) + { + MoveItems(0, num); + _len -= num; + } +} + +/* +AString operator+(const AString &s1, const AString &s2) +{ + AString result(s1); + result += s2; + return result; +} + +AString operator+(const AString &s, const char *chars) +{ + AString result(s); + result += chars; + return result; } +AString operator+(const char *chars, const AString &s) +{ + AString result(chars); + result += s; + return result; +} + +AString operator+(const AString &s, char c) +{ + AString result(s); + result += c; + return result; +} +*/ + +/* +AString operator+(char c, const AString &s) +{ + AString result(c); + result += s; + return result; +} +*/ + + + + +// ---------- UString ---------- + +void UString::InsertSpace(unsigned index, unsigned size) +{ + Grow(size); + MoveItems(index + size, index); +} + +void UString::ReAlloc(unsigned newLimit) +{ + if (newLimit < _len || newLimit >= 0x20000000) throw 20130221; + // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, _len + 1); + wchar_t *newBuf = MY_STRING_NEW(wchar_t, newLimit + 1); + wmemcpy(newBuf, _chars, _len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + + _limit = newLimit; +} + +void UString::SetStartLen(unsigned len) +{ + _chars = 0; + _chars = MY_STRING_NEW(wchar_t, len + 1); + _len = len; + _limit = len; +} + +void UString::Grow_1() +{ + unsigned next = _len; + next += next / 2; + next += 16; + next &= ~(unsigned)15; + ReAlloc(next - 1); +} + +void UString::Grow(unsigned n) +{ + unsigned freeSize = _limit - _len; + if (n <= freeSize) + return; + + unsigned next = _len + n; + next += next / 2; + next += 16; + next &= ~(unsigned)15; + ReAlloc(next - 1); +} + + +UString::UString(unsigned num, const wchar_t *s) +{ + unsigned len = MyStringLen(s); + if (num > len) + num = len; + SetStartLen(num); + wmemcpy(_chars, s, num); + _chars[num] = 0; +} + + +UString::UString(unsigned num, const UString &s) +{ + if (num > s._len) + num = s._len; + SetStartLen(num); + wmemcpy(_chars, s._chars, num); + _chars[num] = 0; +} + +UString::UString(const UString &s, wchar_t c) +{ + SetStartLen(s.Len() + 1); + wchar_t *chars = _chars; + unsigned len = s.Len(); + wmemcpy(chars, s, len); + chars[len] = c; + chars[len + 1] = 0; +} + +UString::UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2) +{ + SetStartLen(num1 + num2); + wchar_t *chars = _chars; + wmemcpy(chars, s1, num1); + wmemcpy(chars + num1, s2, num2 + 1); +} + +UString operator+(const UString &s1, const UString &s2) { return UString(s1, s1.Len(), s2, s2.Len()); } +UString operator+(const UString &s1, const wchar_t *s2) { return UString(s1, s1.Len(), s2, MyStringLen(s2)); } +UString operator+(const wchar_t *s1, const UString &s2) { return UString(s1, MyStringLen(s1), s2, s2.Len()); } + +UString::UString() +{ + _chars = 0; + _chars = MY_STRING_NEW(wchar_t, 4); + _len = 0; + _limit = 4 - 1; + _chars[0] = 0; +} + +UString::UString(wchar_t c) +{ + SetStartLen(1); + _chars[0] = c; + _chars[1] = 0; +} + +UString::UString(const wchar_t *s) +{ + SetStartLen(MyStringLen(s)); + MyStringCopy(_chars, s); +} + +UString::UString(const UString &s) +{ + SetStartLen(s._len); + MyStringCopy(_chars, s._chars); +} + +UString &UString::operator=(wchar_t c) +{ + if (1 > _limit) + { + wchar_t *newBuf = MY_STRING_NEW(wchar_t, 1 + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = 1; + } + _len = 1; + _chars[0] = c; + _chars[1] = 0; + return *this; +} + +UString &UString::operator=(const wchar_t *s) +{ + unsigned len = MyStringLen(s); + if (len > _limit) + { + wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + _len = len; + MyStringCopy(_chars, s); + return *this; +} + +UString &UString::operator=(const UString &s) +{ + if (&s == this) + return *this; + unsigned len = s._len; + if (len > _limit) + { + wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + _len = len; + MyStringCopy(_chars, s._chars); + return *this; +} + +UString &UString::operator+=(const wchar_t *s) +{ + unsigned len = MyStringLen(s); + Grow(len); + MyStringCopy(_chars + _len, s); + _len += len; + return *this; +} + +UString &UString::operator+=(const UString &s) +{ + Grow(s._len); + MyStringCopy(_chars + _len, s._chars); + _len += s._len; + return *this; +} + +void UString::SetFrom(const wchar_t *s, unsigned len) // no check +{ + if (len > _limit) + { + wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + wmemcpy(_chars, s, len); + _chars[len] = 0; + _len = len; +} + +void UString::SetFromAscii(const char *s) +{ + unsigned len = MyStringLen(s); + if (len > _limit) + { + wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + wchar_t *chars = _chars; + for (unsigned i = 0; i < len; i++) + chars[i] = s[i]; + chars[len] = 0; + _len = len; +} + +void UString::AddAsciiStr(const char *s) +{ + unsigned len = MyStringLen(s); + Grow(len); + wchar_t *chars = _chars + _len; + for (unsigned i = 0; i < len; i++) + chars[i] = s[i]; + chars[len] = 0; + _len += len; +} + + + +int UString::Find(const UString &s, unsigned startIndex) const throw() +{ + if (s.IsEmpty()) + return startIndex; + for (; startIndex < _len; startIndex++) + { + unsigned j; + for (j = 0; j < s._len && startIndex + j < _len; j++) + if (_chars[startIndex + j] != s._chars[j]) + break; + if (j == s._len) + return (int)startIndex; + } + return -1; +} + +int UString::ReverseFind(wchar_t c) const throw() +{ + if (_len == 0) + return -1; + const wchar_t *p = _chars + _len - 1; + for (;;) + { + if (*p == c) + return (int)(p - _chars); + if (p == _chars) + return -1; + p--; + } +} + +void UString::TrimLeft() throw() +{ + const wchar_t *p = _chars; + for (;; p++) + { + wchar_t c = *p; + if (c != ' ' && c != '\n' && c != '\t') + break; + } + unsigned pos = (unsigned)(p - _chars); + if (pos != 0) + { + MoveItems(0, pos); + _len -= pos; + } +} + +void UString::TrimRight() throw() +{ + const wchar_t *p = _chars; + int i; + for (i = _len - 1; i >= 0; i--) + { + wchar_t c = p[i]; + if (c != ' ' && c != '\n' && c != '\t') + break; + } + i++; + if ((unsigned)i != _len) + { + _chars[i] = 0; + _len = i; + } +} + +void UString::InsertAtFront(wchar_t c) +{ + if (_limit == _len) + Grow_1(); + MoveItems(1, 0); + _chars[0] = c; + _len++; +} + +/* +void UString::Insert(unsigned index, wchar_t c) +{ + InsertSpace(index, 1); + _chars[index] = c; + _len++; +} +*/ + +void UString::Insert(unsigned index, const wchar_t *s) +{ + unsigned num = MyStringLen(s); + if (num != 0) + { + InsertSpace(index, num); + wmemcpy(_chars + index, s, num); + _len += num; + } +} + +void UString::Insert(unsigned index, const UString &s) +{ + unsigned num = s.Len(); + if (num != 0) + { + InsertSpace(index, num); + wmemcpy(_chars + index, s, num); + _len += num; + } +} + +void UString::RemoveChar(wchar_t ch) throw() +{ + int pos = Find(ch); + if (pos < 0) + return; + const wchar_t *src = _chars; + wchar_t *dest = _chars + pos; + pos++; + unsigned len = _len; + for (; (unsigned)pos < len; pos++) + { + wchar_t c = src[(unsigned)pos]; + if (c != ch) + *dest++ = c; + } + *dest = 0; + _len = (unsigned)(dest - _chars); +} + +// !!!!!!!!!!!!!!! test it if newChar = '\0' +void UString::Replace(wchar_t oldChar, wchar_t newChar) throw() +{ + if (oldChar == newChar) + return; // 0; + // unsigned number = 0; + int pos = 0; + while ((unsigned)pos < _len) + { + pos = Find(oldChar, pos); + if (pos < 0) + break; + _chars[pos] = newChar; + pos++; + // number++; + } + return; // number; +} + +void UString::Replace(const UString &oldString, const UString &newString) +{ + if (oldString.IsEmpty()) + return; // 0; + if (oldString == newString) + return; // 0; + unsigned oldLen = oldString.Len(); + unsigned newLen = newString.Len(); + // unsigned number = 0; + int pos = 0; + while ((unsigned)pos < _len) + { + pos = Find(oldString, pos); + if (pos < 0) + break; + Delete(pos, oldLen); + Insert(pos, newString); + pos += newLen; + // number++; + } + // return number; +} + +void UString::Delete(unsigned index) throw() +{ + MoveItems(index, index + 1); + _len--; +} + +void UString::Delete(unsigned index, unsigned count) throw() +{ + if (index + count > _len) + count = _len - index; + if (count > 0) + { + MoveItems(index, index + count); + _len -= count; + } +} + +void UString::DeleteFrontal(unsigned num) throw() +{ + if (num != 0) + { + MoveItems(0, num); + _len -= num; + } +} + + +// ---------------------------------------- + /* int MyStringCompareNoCase(const char *s1, const char *s2) { return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2)); } */ + +static inline UINT GetCurrentCodePage() +{ + #if defined(UNDER_CE) || !defined(_WIN32) + return CP_ACP; + #else + return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; + #endif +} + +#ifdef USE_UNICODE_FSTRING + +#ifndef _UNICODE + +AString fs2fas(CFSTR s) +{ + return UnicodeStringToMultiByte(s, GetCurrentCodePage()); +} + +FString fas2fs(const AString &s) +{ + return MultiByteToUnicodeString(s, GetCurrentCodePage()); +} + +#endif + +#else + +UString fs2us(const FString &s) +{ + return MultiByteToUnicodeString((AString)s, GetCurrentCodePage()); +} + +FString us2fs(const wchar_t *s) +{ + return UnicodeStringToMultiByte(s, GetCurrentCodePage()); +} + +#endif diff --git a/src/libs/7zip/win/CPP/Common/MyString.h b/src/libs/7zip/win/CPP/Common/MyString.h index f483e39dc..8417815cf 100644 --- a/src/libs/7zip/win/CPP/Common/MyString.h +++ b/src/libs/7zip/win/CPP/Common/MyString.h @@ -5,623 +5,521 @@ #include -#include "MyVector.h" +#ifndef _WIN32 +#include +#include +#endif -#include +#include "MyTypes.h" +#include "MyVector.h" -template -inline int MyStringLen(const T *s) +inline unsigned MyStringLen(const char *s) { - int i; - for (i = 0; s[i] != '\0'; i++); + unsigned i; + for (i = 0; s[i] != 0; i++); return i; } -template -inline T * MyStringCopy(T *dest, const T *src) +inline void MyStringCopy(char *dest, const char *src) { - T *destStart = dest; while ((*dest++ = *src++) != 0); - return destStart; } -inline wchar_t* MyStringGetNextCharPointer(wchar_t *p) - { return (p + 1); } -inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p) - { return (p + 1); } -inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p) - { return (p - 1); } -inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p) - { return (p - 1); } +inline char *MyStpCpy(char *dest, const char *src) +{ + for (;;) + { + char c = *src; + *dest = c; + if (c == 0) + return dest; + src++; + dest++; + } +} -#ifdef _WIN32 +inline unsigned MyStringLen(const wchar_t *s) +{ + unsigned i; + for (i = 0; s[i] != 0; i++); + return i; +} -inline const char* MyStringGetNextCharPointer(const char *p) +inline void MyStringCopy(wchar_t *dest, const wchar_t *src) { - #ifdef UNDER_CE - return p + 1; - #else - return CharNextA(p); - #endif + while ((*dest++ = *src++) != 0); } -inline const char* MyStringGetPrevCharPointer(const char *base, const char *p) - { return CharPrevA(base, p); } +int FindCharPosInString(const char *s, char c) throw(); +int FindCharPosInString(const wchar_t *s, wchar_t c) throw(); -inline char MyCharUpper(char c) - { return (char)(unsigned int)(UINT_PTR)CharUpperA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } -#ifdef _UNICODE -inline wchar_t MyCharUpper(wchar_t c) - { return (wchar_t)(unsigned int)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); } -#else -wchar_t MyCharUpper(wchar_t c); +#ifdef _WIN32 + #ifndef _UNICODE + #define STRING_UNICODE_THROW + #endif #endif -#ifdef _UNICODE -inline wchar_t MyCharLower(wchar_t c) - { return (wchar_t)(unsigned int)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); } -#else -wchar_t MyCharLower(wchar_t c); +#ifndef STRING_UNICODE_THROW + #define STRING_UNICODE_THROW throw() #endif -inline char MyCharLower(char c) -#ifdef UNDER_CE - { return (char)MyCharLower((wchar_t)c); } -#else - { return (char)(unsigned int)(UINT_PTR)CharLowerA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } -#endif +/* +inline char MyCharUpper_Ascii(char c) +{ + if (c >= 'a' && c <= 'z') + return (char)(c - 0x20); + return c; +} +inline wchar_t MyCharUpper_Ascii(wchar_t c) +{ + if (c >= 'a' && c <= 'z') + return (wchar_t)(c - 0x20); + return c; +} +*/ -inline char * MyStringUpper(char *s) { return CharUpperA(s); } -#ifdef _UNICODE -inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } -#else -wchar_t * MyStringUpper(wchar_t *s); -#endif +inline char MyCharLower_Ascii(char c) +{ + if (c >= 'A' && c <= 'Z') + return (char)(c + 0x20); + return c; +} -inline char * MyStringLower(char *s) { return CharLowerA(s); } -#ifdef _UNICODE -inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } -#else -wchar_t * MyStringLower(wchar_t *s); -#endif +inline wchar_t MyCharLower_Ascii(wchar_t c) +{ + if (c >= 'A' && c <= 'Z') + return (wchar_t)(c + 0x20); + return c; +} -#else // Standard-C -wchar_t MyCharUpper(wchar_t c); -#endif +wchar_t MyCharUpper_WIN(wchar_t c) throw(); -////////////////////////////////////// -// Compare +inline wchar_t MyCharUpper(wchar_t c) throw() +{ + if (c < 'a') return c; + if (c <= 'z') return (wchar_t)(c - 0x20); + if (c <= 0x7F) return c; + #ifdef _WIN32 + #ifdef _UNICODE + return (wchar_t)(unsigned)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c); + #else + return (wchar_t)MyCharUpper_WIN(c); + #endif + #else + return (wchar_t)towupper(c); + #endif +} /* -#ifndef UNDER_CE -int MyStringCollate(const char *s1, const char *s2); -int MyStringCollateNoCase(const char *s1, const char *s2); -#endif -int MyStringCollate(const wchar_t *s1, const wchar_t *s2); -int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2); +wchar_t MyCharLower_WIN(wchar_t c) throw(); + +inline wchar_t MyCharLower(wchar_t c) throw() +{ + if (c < 'A') return c; + if (c <= 'Z') return (wchar_t)(c + 0x20); + if (c <= 0x7F) return c; + #ifdef _WIN32 + #ifdef _UNICODE + return (wchar_t)(unsigned)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c); + #else + return (wchar_t)MyCharLower_WIN(c); + #endif + #else + return (wchar_t)tolower(c); + #endif +} */ -int MyStringCompare(const char *s1, const char *s2); -int MyStringCompare(const wchar_t *s1, const wchar_t *s2); +// char *MyStringUpper(char *s) throw(); +// char *MyStringLower(char *s) throw(); + +// void MyStringUpper_Ascii(wchar_t *s) throw(); +void MyStringLower_Ascii(wchar_t *s) throw(); +// wchar_t *MyStringUpper(wchar_t *s) STRING_UNICODE_THROW; +// wchar_t *MyStringLower(wchar_t *s) STRING_UNICODE_THROW; + +bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw(); + +bool IsString1PrefixedByString2(const char *s1, const char *s2) throw(); +bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw(); -// int MyStringCompareNoCase(const char *s1, const char *s2); -int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2); +int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw(); +int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) throw(); -template -class CStringBase +// ---------- ASCII ---------- +// char values in ASCII strings must be less then 128 +bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw(); +bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw(); +bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw(); +bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw(); + +#define MY_STRING_DELETE(_p_) delete []_p_; +// #define MY_STRING_DELETE(_p_) my_delete(_p_); + +class AString { - void TrimLeftWithCharSet(const CStringBase &charSet) - { - const T *p = _chars; - while (charSet.Find(*p) >= 0 && (*p != 0)) - p = GetNextCharPointer(p); - Delete(0, (int)(p - _chars)); - } - void TrimRightWithCharSet(const CStringBase &charSet) - { - const T *p = _chars; - const T *pLast = NULL; - while (*p != 0) - { - if (charSet.Find(*p) >= 0) - { - if (pLast == NULL) - pLast = p; - } - else - pLast = NULL; - p = GetNextCharPointer(p); - } - if (pLast != NULL) - { - int i = (int)(pLast - _chars); - Delete(i, _length - i); - } + char *_chars; + unsigned _len; + unsigned _limit; - } - void MoveItems(int destIndex, int srcIndex) + void MoveItems(unsigned dest, unsigned src) { - memmove(_chars + destIndex, _chars + srcIndex, - sizeof(T) * (_length - srcIndex + 1)); - } - - void InsertSpace(int &index, int size) - { - CorrectIndex(index); - GrowLength(size); - MoveItems(index + size, index); + memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(char)); } - static const T *GetNextCharPointer(const T *p) - { return MyStringGetNextCharPointer(p); } - static const T *GetPrevCharPointer(const T *base, const T *p) - { return MyStringGetPrevCharPointer(base, p); } -protected: - T *_chars; - int _length; - int _capacity; - - void SetCapacity(int newCapacity) - { - int realCapacity = newCapacity + 1; - if (realCapacity == _capacity) - return; - /* - const int kMaxStringSize = 0x20000000; - if (newCapacity > kMaxStringSize || newCapacity < _length) - throw 1052337; - */ - T *newBuffer = new T[realCapacity]; - if (_capacity > 0) - { - for (int i = 0; i < _length; i++) - newBuffer[i] = _chars[i]; - delete []_chars; - } - _chars = newBuffer; - _chars[_length] = 0; - _capacity = realCapacity; - } + void InsertSpace(unsigned &index, unsigned size); - void GrowLength(int n) - { - int freeSize = _capacity - _length - 1; - if (n <= freeSize) - return; - int delta; - if (_capacity > 64) - delta = _capacity / 2; - else if (_capacity > 8) - delta = 16; - else - delta = 4; - if (freeSize + delta < n) - delta = n - freeSize; - SetCapacity(_capacity + delta); - } + void ReAlloc(unsigned newLimit); + void SetStartLen(unsigned len); + void Grow_1(); + void Grow(unsigned n); - void CorrectIndex(int &index) const - { - if (index > _length) - index = _length; - } + // AString(unsigned num, const char *s); + AString(unsigned num, const AString &s); + AString(const AString &s, char c); // it's for String + char + AString(const char *s1, unsigned num1, const char *s2, unsigned num2); + + friend AString operator+(const AString &s, char c) { return AString(s, c); } ; + // friend AString operator+(char c, const AString &s); // is not supported + + friend AString operator+(const AString &s1, const AString &s2); + friend AString operator+(const AString &s1, const char *s2); + friend AString operator+(const char *s1, const AString &s2); public: - CStringBase(): _chars(0), _length(0), _capacity(0) { SetCapacity(3); } - CStringBase(T c): _chars(0), _length(0), _capacity(0) - { - SetCapacity(1); - _chars[0] = c; - _chars[1] = 0; - _length = 1; - } - CStringBase(const T *chars): _chars(0), _length(0), _capacity(0) - { - int length = MyStringLen(chars); - SetCapacity(length); - MyStringCopy(_chars, chars); // can be optimized by memove() - _length = length; - } - CStringBase(const CStringBase &s): _chars(0), _length(0), _capacity(0) - { - SetCapacity(s._length); - MyStringCopy(_chars, s._chars); - _length = s._length; - } - ~CStringBase() { delete []_chars; } + AString(); + AString(char c); + AString(const char *s); + AString(const AString &s); + ~AString() { MY_STRING_DELETE(_chars); } - operator const T*() const { return _chars;} + unsigned Len() const { return _len; } + bool IsEmpty() const { return _len == 0; } + void Empty() { _len = 0; _chars[0] = 0; } - T Back() const { return _chars[_length - 1]; } + operator const char *() const { return _chars; } + const char *Ptr() const { return _chars; } + const char *Ptr(unsigned pos) const { return _chars + pos; } + const char *RightPtr(unsigned num) const { return _chars + _len - num; } + char Back() const { return _chars[_len - 1]; } + + void ReplaceOneCharAtPos(unsigned pos, char c) { _chars[pos] = c; } // The minimum size of the character buffer in characters. // This value does not include space for a null terminator. - T* GetBuffer(int minBufLength) + char *GetBuffer(unsigned minBufLen) { - if (minBufLength >= _capacity) - SetCapacity(minBufLength); + if (minBufLen > _limit) + ReAlloc(minBufLen); return _chars; } void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); } - void ReleaseBuffer(int newLength) - { - /* - if (newLength >= _capacity) - throw 282217; - */ - _chars[newLength] = 0; - _length = newLength; - } + void ReleaseBuffer(unsigned newLen) { _len = newLen; _chars[newLen] = 0; } - CStringBase& operator=(T c) - { - Empty(); - SetCapacity(1); - _chars[0] = c; - _chars[1] = 0; - _length = 1; - return *this; - } - CStringBase& operator=(const T *chars) - { - Empty(); - int length = MyStringLen(chars); - SetCapacity(length); - MyStringCopy(_chars, chars); - _length = length; - return *this; - } - CStringBase& operator=(const CStringBase& s) - { - if (&s == this) - return *this; - Empty(); - SetCapacity(s._length); - MyStringCopy(_chars, s._chars); - _length = s._length; - return *this; - } - - CStringBase& operator+=(T c) - { - GrowLength(1); - _chars[_length] = c; - _chars[++_length] = 0; - return *this; - } - CStringBase& operator+=(const T *s) - { - int len = MyStringLen(s); - GrowLength(len); - MyStringCopy(_chars + _length, s); - _length += len; - return *this; - } - CStringBase& operator+=(const CStringBase &s) - { - GrowLength(s._length); - MyStringCopy(_chars + _length, s._chars); - _length += s._length; - return *this; - } - void Empty() - { - _length = 0; - _chars[0] = 0; - } - int Length() const { return _length; } - bool IsEmpty() const { return (_length == 0); } + AString &operator=(char c); + AString &operator=(const char *s); + AString &operator=(const AString &s); - CStringBase Mid(int startIndex) const - { return Mid(startIndex, _length - startIndex); } - CStringBase Mid(int startIndex, int count) const - { - if (startIndex + count > _length) - count = _length - startIndex; - - if (startIndex == 0 && startIndex + count == _length) - return *this; - - CStringBase result; - result.SetCapacity(count); - // MyStringNCopy(result._chars, _chars + startIndex, count); - for (int i = 0; i < count; i++) - result._chars[i] = _chars[startIndex + i]; - result._chars[count] = 0; - result._length = count; - return result; - } - CStringBase Left(int count) const - { return Mid(0, count); } - CStringBase Right(int count) const + AString &operator+=(char c) { - if (count > _length) - count = _length; - return Mid(_length - count, count); + if (_limit == _len) + Grow_1(); + unsigned len = _len; + char *chars = _chars; + chars[len++] = c; + chars[len] = 0; + _len = len; + return *this; } - void MakeUpper() - { MyStringUpper(_chars); } - void MakeLower() - { MyStringLower(_chars); } + AString &operator+=(const char *s); + AString &operator+=(const AString &s); - int Compare(const CStringBase& s) const - { return MyStringCompare(_chars, s._chars); } + void SetFrom(const char *s, unsigned len); // no check + // AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); } + AString Left(unsigned count) const { return AString(count, *this); } - int Compare(const T *s) const - { return MyStringCompare(_chars, s); } + // void MakeUpper() { MyStringUpper(_chars); } + // void MakeLower() { MyStringLower(_chars); } - int CompareNoCase(const CStringBase& s) const - { return MyStringCompareNoCase(_chars, s._chars); } - int CompareNoCase(const T *s) const - { return MyStringCompareNoCase(_chars, s); } + // int Compare(const char *s) const { return MyStringCompare(_chars, s); } + // int Compare(const AString &s) const { return MyStringCompare(_chars, s._chars); } + // int CompareNoCase(const char *s) const { return MyStringCompareNoCase(_chars, s); } + // int CompareNoCase(const AString &s) const { return MyStringCompareNoCase(_chars, s._chars); } + bool IsPrefixedBy(const char *s) const { return IsString1PrefixedByString2(_chars, s); } + bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw(); - /* - int Collate(const CStringBase& s) const - { return MyStringCollate(_chars, s._chars); } - int CollateNoCase(const CStringBase& s) const - { return MyStringCollateNoCase(_chars, s._chars); } - */ - - int Find(T c) const { return Find(c, 0); } - int Find(T c, int startIndex) const + int Find(char c) const { return FindCharPosInString(_chars, c); } + int Find(char c, unsigned startIndex) const { - const T *p = _chars + startIndex; - for (;;) - { - if (*p == c) - return (int)(p - _chars); - if (*p == 0) - return -1; - p = GetNextCharPointer(p); - } + int pos = FindCharPosInString(_chars + startIndex, c); + return pos < 0 ? -1 : (int)startIndex + pos; } - int Find(const CStringBase &s) const { return Find(s, 0); } - int Find(const CStringBase &s, int startIndex) const + int ReverseFind(char c) const throw(); + int Find(const AString &s) const { return Find(s, 0); } + int Find(const AString &s, unsigned startIndex) const throw(); + + void TrimLeft() throw(); + void TrimRight() throw(); + void Trim() { - if (s.IsEmpty()) - return startIndex; - for (; startIndex < _length; startIndex++) - { - int j; - for (j = 0; j < s._length && startIndex + j < _length; j++) - if (_chars[startIndex+j] != s._chars[j]) - break; - if (j == s._length) - return startIndex; - } - return -1; + TrimRight(); + TrimLeft(); } - int ReverseFind(T c) const + + void InsertAtFront(char c); + // void Insert(unsigned index, char c); + void Insert(unsigned index, const char *s); + void Insert(unsigned index, const AString &s); + + void RemoveChar(char ch) throw(); + void Replace(char oldChar, char newChar) throw(); + void Replace(const AString &oldString, const AString &newString); + + void Delete(unsigned index) throw(); + void Delete(unsigned index, unsigned count) throw(); + void DeleteFrontal(unsigned num) throw(); + void DeleteBack() { _chars[--_len] = 0; } + void DeleteFrom(unsigned index) { - if (_length == 0) - return -1; - const T *p = _chars + _length - 1; - for (;;) + if (index < _len) { - if (*p == c) - return (int)(p - _chars); - if (p == _chars) - return -1; - p = GetPrevCharPointer(_chars, p); + _len = index; + _chars[index] = 0; } } - int FindOneOf(const CStringBase &s) const - { - for (int i = 0; i < _length; i++) - if (s.Find(_chars[i]) >= 0) - return i; - return -1; - } +}; - void TrimLeft(T c) - { - const T *p = _chars; - while (c == *p) - p = GetNextCharPointer(p); - Delete(0, p - _chars); - } - private: - CStringBase GetTrimDefaultCharSet() +bool operator<(const AString &s1, const AString &s2); +bool operator>(const AString &s1, const AString &s2); + +/* +bool operator==(const AString &s1, const AString &s2); +bool operator==(const AString &s1, const char *s2); +bool operator==(const char *s1, const AString &s2); + +bool operator!=(const AString &s1, const AString &s2); +bool operator!=(const AString &s1, const char *s2); +bool operator!=(const char *s1, const AString &s2); +*/ + +inline bool operator==(const AString &s1, const AString &s2) { return s1.Len() == s2.Len() && strcmp(s1, s2) == 0; } +inline bool operator==(const AString &s1, const char *s2) { return strcmp(s1, s2) == 0; } +inline bool operator==(const char *s1, const AString &s2) { return strcmp(s1, s2) == 0; } + +inline bool operator!=(const AString &s1, const AString &s2) { return s1.Len() != s2.Len() || strcmp(s1, s2) != 0; } +inline bool operator!=(const AString &s1, const char *s2) { return strcmp(s1, s2) != 0; } +inline bool operator!=(const char *s1, const AString &s2) { return strcmp(s1, s2) != 0; } + + + +class UString +{ + wchar_t *_chars; + unsigned _len; + unsigned _limit; + + void MoveItems(unsigned dest, unsigned src) { - CStringBase charSet; - charSet += (T)' '; - charSet += (T)'\n'; - charSet += (T)'\t'; - return charSet; + memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(wchar_t)); } - public: - void TrimLeft() + void InsertSpace(unsigned index, unsigned size); + + void ReAlloc(unsigned newLimit); + void SetStartLen(unsigned len); + void Grow_1(); + void Grow(unsigned n); + + UString(unsigned num, const wchar_t *s); // for Mid + UString(unsigned num, const UString &s); // for Left + UString(const UString &s, wchar_t c); // it's for String + char + UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2); + + friend UString operator+(const UString &s, wchar_t c) { return UString(s, c); } ; + // friend UString operator+(wchar_t c, const UString &s); // is not supported + + friend UString operator+(const UString &s1, const UString &s2); + friend UString operator+(const UString &s1, const wchar_t *s2); + friend UString operator+(const wchar_t *s1, const UString &s2); + +public: + UString(); + UString(wchar_t c); + UString(const wchar_t *s); + UString(const UString &s); + ~UString() { MY_STRING_DELETE(_chars); } + + unsigned Len() const { return _len; } + bool IsEmpty() const { return _len == 0; } + void Empty() { _len = 0; _chars[0] = 0; } + + operator const wchar_t *() const { return _chars; } + const wchar_t *Ptr() const { return _chars; } + const wchar_t *Ptr(unsigned pos) const { return _chars + pos; } + const wchar_t *RightPtr(unsigned num) const { return _chars + _len - num; } + wchar_t Back() const { return _chars[_len - 1]; } + + void ReplaceOneCharAtPos(unsigned pos, wchar_t c) { _chars[pos] = c; } + + // The minimum size of the character buffer in characters. + // This value does not include space for a null terminator. + wchar_t *GetBuffer(unsigned minBufLen) { - TrimLeftWithCharSet(GetTrimDefaultCharSet()); + if (minBufLen > _limit) + ReAlloc(minBufLen); + return _chars; } - void TrimRight() + void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); } + void ReleaseBuffer(unsigned newLen) { _len = newLen; _chars[newLen] = 0; } + + UString &operator=(wchar_t c); + UString &operator=(const wchar_t *s); + UString &operator=(const UString &s); + + UString &operator+=(wchar_t c) { - TrimRightWithCharSet(GetTrimDefaultCharSet()); + if (_limit == _len) + Grow_1(); + unsigned len = _len; + wchar_t *chars = _chars; + chars[len++] = c; + chars[len] = 0; + _len = len; + return *this; } - void TrimRight(T c) + + UString &operator+=(const wchar_t *s); + UString &operator+=(const UString &s); + + void SetFrom(const wchar_t *s, unsigned len); // no check + + void SetFromAscii(const char *s); + void AddAsciiStr(const char *s); + + UString Mid(unsigned startIndex, unsigned count) const { return UString(count, _chars + startIndex); } + UString Left(unsigned count) const { return UString(count, *this); } + + // void MakeUpper() { MyStringUpper(_chars); } + // void MakeUpper() { MyStringUpper_Ascii(_chars); } + // void MakeUpper_Ascii() { MyStringUpper_Ascii(_chars); } + void MakeLower_Ascii() { MyStringLower_Ascii(_chars); } + + bool IsEqualTo(const char *s) const { return StringsAreEqual_Ascii(_chars, s); } + bool IsEqualToNoCase(const wchar_t *s) const { return StringsAreEqualNoCase(_chars, s); } + int Compare(const wchar_t *s) const { return wcscmp(_chars, s); } + // int Compare(const UString &s) const { return MyStringCompare(_chars, s._chars); } + // int CompareNoCase(const wchar_t *s) const { return MyStringCompareNoCase(_chars, s); } + // int CompareNoCase(const UString &s) const { return MyStringCompareNoCase(_chars, s._chars); } + bool IsPrefixedBy(const wchar_t *s) const { return IsString1PrefixedByString2(_chars, s); }; + bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw(); + + int Find(wchar_t c) const { return FindCharPosInString(_chars, c); } + int Find(wchar_t c, unsigned startIndex) const { - const T *p = _chars; - const T *pLast = NULL; - while (*p != 0) - { - if (*p == c) - { - if (pLast == NULL) - pLast = p; - } - else - pLast = NULL; - p = GetNextCharPointer(p); - } - if (pLast != NULL) - { - int i = pLast - _chars; - Delete(i, _length - i); - } + int pos = FindCharPosInString(_chars + startIndex, c); + return pos < 0 ? -1 : (int)startIndex + pos; } + int Find(const UString &s) const { return Find(s, 0); } + int Find(const UString &s, unsigned startIndex) const throw(); + int ReverseFind(wchar_t c) const throw(); + + void TrimLeft() throw(); + void TrimRight() throw(); void Trim() { TrimRight(); TrimLeft(); } - int Insert(int index, T c) - { - InsertSpace(index, 1); - _chars[index] = c; - _length++; - return _length; - } - int Insert(int index, const CStringBase &s) - { - CorrectIndex(index); - if (s.IsEmpty()) - return _length; - int numInsertChars = s.Length(); - InsertSpace(index, numInsertChars); - for (int i = 0; i < numInsertChars; i++) - _chars[index + i] = s[i]; - _length += numInsertChars; - return _length; - } + void InsertAtFront(wchar_t c); + // void Insert(unsigned index, wchar_t c); + void Insert(unsigned index, const wchar_t *s); + void Insert(unsigned index, const UString &s); - // !!!!!!!!!!!!!!! test it if newChar = '\0' - int Replace(T oldChar, T newChar) - { - if (oldChar == newChar) - return 0; - int number = 0; - int pos = 0; - while (pos < Length()) - { - pos = Find(oldChar, pos); - if (pos < 0) - break; - _chars[pos] = newChar; - pos++; - number++; - } - return number; - } - int Replace(const CStringBase &oldString, const CStringBase &newString) - { - if (oldString.IsEmpty()) - return 0; - if (oldString == newString) - return 0; - int oldStringLength = oldString.Length(); - int newStringLength = newString.Length(); - int number = 0; - int pos = 0; - while (pos < _length) - { - pos = Find(oldString, pos); - if (pos < 0) - break; - Delete(pos, oldStringLength); - Insert(pos, newString); - pos += newStringLength; - number++; - } - return number; - } - int Delete(int index, int count = 1) + void RemoveChar(wchar_t ch) throw(); + void Replace(wchar_t oldChar, wchar_t newChar) throw(); + void Replace(const UString &oldString, const UString &newString); + + void Delete(unsigned index) throw(); + void Delete(unsigned index, unsigned count) throw(); + void DeleteFrontal(unsigned num) throw(); + void DeleteBack() { _chars[--_len] = 0; } + void DeleteFrom(unsigned index) { - if (index + count > _length) - count = _length - index; - if (count > 0) + if (index < _len) { - MoveItems(index, index + count); - _length -= count; + _len = index; + _chars[index] = 0; } - return _length; } - void DeleteBack() { Delete(_length - 1); } }; -template -CStringBase operator+(const CStringBase& s1, const CStringBase& s2) -{ - CStringBase result(s1); - result += s2; - return result; -} +bool operator<(const UString &s1, const UString &s2); +bool operator>(const UString &s1, const UString &s2); -template -CStringBase operator+(const CStringBase& s, T c) -{ - CStringBase result(s); - result += c; - return result; -} +inline bool operator==(const UString &s1, const UString &s2) { return s1.Len() == s2.Len() && wcscmp(s1, s2) == 0; } +inline bool operator==(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) == 0; } +inline bool operator==(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) == 0; } -template -CStringBase operator+(T c, const CStringBase& s) -{ - CStringBase result(c); - result += s; - return result; -} +inline bool operator!=(const UString &s1, const UString &s2) { return s1.Len() != s2.Len() || wcscmp(s1, s2) != 0; } +inline bool operator!=(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) != 0; } +inline bool operator!=(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) != 0; } -template -CStringBase operator+(const CStringBase& s, const T * chars) -{ - CStringBase result(s); - result += chars; - return result; -} -template -CStringBase operator+(const T * chars, const CStringBase& s) -{ - CStringBase result(chars); - result += s; - return result; -} +typedef CObjectVector AStringVector; +typedef CObjectVector UStringVector; -template -bool operator==(const CStringBase& s1, const CStringBase& s2) - { return (s1.Compare(s2) == 0); } +#ifdef _UNICODE + typedef UString CSysString; +#else + typedef AString CSysString; +#endif -template -bool operator<(const CStringBase& s1, const CStringBase& s2) - { return (s1.Compare(s2) < 0); } +typedef CObjectVector CSysStringVector; -template -bool operator==(const T *s1, const CStringBase& s2) - { return (s2.Compare(s1) == 0); } -template -bool operator==(const CStringBase& s1, const T *s2) - { return (s1.Compare(s2) == 0); } +// ---------- FString ---------- -template -bool operator!=(const CStringBase& s1, const CStringBase& s2) - { return (s1.Compare(s2) != 0); } +#ifdef _WIN32 + #define USE_UNICODE_FSTRING +#endif -template -bool operator!=(const T *s1, const CStringBase& s2) - { return (s2.Compare(s1) != 0); } +#ifdef USE_UNICODE_FSTRING -template -bool operator!=(const CStringBase& s1, const T *s2) - { return (s1.Compare(s2) != 0); } + #define __FTEXT(quote) L##quote -typedef CStringBase AString; -typedef CStringBase UString; + typedef wchar_t FChar; + typedef UString FString; -typedef CObjectVector AStringVector; -typedef CObjectVector UStringVector; + #define fs2us(_x_) (_x_) + #define us2fs(_x_) (_x_) + FString fas2fs(const AString &s); + AString fs2fas(const FChar *s); -#ifdef _UNICODE - typedef UString CSysString; #else - typedef AString CSysString; + + #define __FTEXT(quote) quote + + typedef char FChar; + typedef AString FString; + + UString fs2us(const FString &s); + FString us2fs(const wchar_t *s); + #define fas2fs(_x_) (_x_) + #define fs2fas(_x_) (_x_) + #endif -typedef CObjectVector CSysStringVector; +#define FTEXT(quote) __FTEXT(quote) + +#define FCHAR_PATH_SEPARATOR FTEXT(CHAR_PATH_SEPARATOR) +#define FSTRING_PATH_SEPARATOR FTEXT(STRING_PATH_SEPARATOR) +#define FCHAR_ANY_MASK FTEXT('*') +#define FSTRING_ANY_MASK FTEXT("*") +typedef const FChar *CFSTR; + +typedef CObjectVector FStringVector; #endif diff --git a/src/libs/7zip/win/CPP/Common/MyTypes.h b/src/libs/7zip/win/CPP/Common/MyTypes.h new file mode 100644 index 000000000..d81788816 --- /dev/null +++ b/src/libs/7zip/win/CPP/Common/MyTypes.h @@ -0,0 +1,30 @@ +// Common/MyTypes.h + +#ifndef __COMMON_MY_TYPES_H +#define __COMMON_MY_TYPES_H + +#include "../../C/7zTypes.h" + +typedef int HRes; + +struct CBoolPair +{ + bool Val; + bool Def; + + CBoolPair(): Val(false), Def(false) {} + + void Init() + { + Val = false; + Def = false; + } + + void SetTrueTrue() + { + Val = true; + Def = true; + } +}; + +#endif diff --git a/src/libs/7zip/win/CPP/Common/MyUnknown.h b/src/libs/7zip/win/CPP/Common/MyUnknown.h index e9e8666b9..8b95afd38 100644 --- a/src/libs/7zip/win/CPP/Common/MyUnknown.h +++ b/src/libs/7zip/win/CPP/Common/MyUnknown.h @@ -9,5 +9,5 @@ #else #include "MyWindows.h" #endif - + #endif diff --git a/src/libs/7zip/win/CPP/Common/MyVector.cpp b/src/libs/7zip/win/CPP/Common/MyVector.cpp deleted file mode 100644 index 3b5317688..000000000 --- a/src/libs/7zip/win/CPP/Common/MyVector.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// Common/MyVector.cpp - -#include "StdAfx.h" - -#include - -#include "MyVector.h" - -CBaseRecordVector::~CBaseRecordVector() { ClearAndFree(); } - -void CBaseRecordVector::ClearAndFree() -{ - Clear(); - delete []((unsigned char *)_items); - _capacity = 0; - _size = 0; - _items = 0; -} - -void CBaseRecordVector::Clear() { DeleteFrom(0); } -void CBaseRecordVector::DeleteBack() { Delete(_size - 1); } -void CBaseRecordVector::DeleteFrom(int index) { Delete(index, _size - index); } - -void CBaseRecordVector::ReserveOnePosition() -{ - if (_size != _capacity) - return; - unsigned delta = 1; - if (_capacity >= 64) - delta = (unsigned)_capacity / 4; - else if (_capacity >= 8) - delta = 8; - Reserve(_capacity + (int)delta); -} - -void CBaseRecordVector::Reserve(int newCapacity) -{ - // if (newCapacity <= _capacity) - if (newCapacity == _capacity) - return; - if ((unsigned)newCapacity >= ((unsigned)1 << (sizeof(unsigned) * 8 - 1))) - throw 1052353; - size_t newSize = (size_t)(unsigned)newCapacity * _itemSize; - if (newSize / _itemSize != (size_t)(unsigned)newCapacity) - throw 1052354; - unsigned char *p = NULL; - if (newSize > 0) - { - p = new unsigned char[newSize]; - if (p == 0) - throw 1052355; - int numRecordsToMove = (_size < newCapacity ? _size : newCapacity); - memcpy(p, _items, _itemSize * numRecordsToMove); - } - delete [](unsigned char *)_items; - _items = p; - _capacity = newCapacity; -} - -void CBaseRecordVector::ReserveDown() -{ - Reserve(_size); -} - -void CBaseRecordVector::MoveItems(int destIndex, int srcIndex) -{ - memmove(((unsigned char *)_items) + destIndex * _itemSize, - ((unsigned char *)_items) + srcIndex * _itemSize, - _itemSize * (_size - srcIndex)); -} - -void CBaseRecordVector::InsertOneItem(int index) -{ - ReserveOnePosition(); - MoveItems(index + 1, index); - _size++; -} - -void CBaseRecordVector::Delete(int index, int num) -{ - TestIndexAndCorrectNum(index, num); - if (num > 0) - { - MoveItems(index, index + num); - _size -= num; - } -} diff --git a/src/libs/7zip/win/CPP/Common/MyVector.h b/src/libs/7zip/win/CPP/Common/MyVector.h index 781b648bc..7e61dec31 100644 --- a/src/libs/7zip/win/CPP/Common/MyVector.h +++ b/src/libs/7zip/win/CPP/Common/MyVector.h @@ -1,92 +1,247 @@ -// Common/Vector.h +// Common/MyVector.h -#ifndef __COMMON_VECTOR_H -#define __COMMON_VECTOR_H - -#include "Defs.h" - -class CBaseRecordVector -{ - void MoveItems(int destIndex, int srcIndex); -protected: - int _capacity; - int _size; - void *_items; - size_t _itemSize; - - void ReserveOnePosition(); - void InsertOneItem(int index); - void TestIndexAndCorrectNum(int index, int &num) const - { if (index + num > _size) num = _size - index; } -public: - CBaseRecordVector(size_t itemSize): _capacity(0), _size(0), _items(0), _itemSize(itemSize) {} - virtual ~CBaseRecordVector(); - void ClearAndFree(); - int Size() const { return _size; } - bool IsEmpty() const { return (_size == 0); } - void Reserve(int newCapacity); - void ReserveDown(); - virtual void Delete(int index, int num = 1); - void Clear(); - void DeleteFrom(int index); - void DeleteBack(); -}; +#ifndef __COMMON_MY_VECTOR_H +#define __COMMON_MY_VECTOR_H template -class CRecordVector: public CBaseRecordVector +class CRecordVector { + T *_items; + unsigned _size; + unsigned _capacity; + + void MoveItems(unsigned destIndex, unsigned srcIndex) + { + memmove(_items + destIndex, _items + srcIndex, (size_t)(_size - srcIndex) * (size_t)sizeof(T)); + } + + void ReserveOnePosition() + { + if (_size == _capacity) + { + unsigned newCapacity = _capacity + (_capacity >> 2) + 1; + T *p = new T[newCapacity]; + memcpy(p, _items, (size_t)_size * (size_t)sizeof(T)); + delete []_items; + _items = p; + _capacity = newCapacity; + } + } + public: - CRecordVector(): CBaseRecordVector(sizeof(T)){}; - CRecordVector(const CRecordVector &v): CBaseRecordVector(sizeof(T)) { *this = v; } - CRecordVector& operator=(const CRecordVector &v) + + CRecordVector(): _items(0), _size(0), _capacity(0) {} + + CRecordVector(const CRecordVector &v): _items(0), _size(0), _capacity(0) + { + unsigned size = v.Size(); + if (size != 0) + { + _items = new T[size]; + _size = size; + _capacity = size; + memcpy(_items, v._items, (size_t)size * (size_t)sizeof(T)); + } + } + + unsigned Size() const { return _size; } + bool IsEmpty() const { return _size == 0; } + + void ConstructReserve(unsigned size) + { + if (size != 0) + { + _items = new T[size]; + _capacity = size; + } + } + + void Reserve(unsigned newCapacity) + { + if (newCapacity > _capacity) + { + T *p = new T[newCapacity]; + memcpy(p, _items, (size_t)_size * (size_t)sizeof(T)); + delete []_items; + _items = p; + _capacity = newCapacity; + } + } + + void ClearAndReserve(unsigned newCapacity) { Clear(); - return (*this += v); + if (newCapacity > _capacity) + { + delete []_items; + _items = NULL; + _capacity = 0; + _items = new T[newCapacity]; + _capacity = newCapacity; + } + } + + void ClearAndSetSize(unsigned newSize) + { + ClearAndReserve(newSize); + _size = newSize; } + + void ChangeSize_KeepData(unsigned newSize) + { + if (newSize > _capacity) + { + T *p = new T[newSize]; + memcpy(p, _items, (size_t)_size * (size_t)sizeof(T)); + delete []_items; + _items = p; + _capacity = newSize; + } + _size = newSize; + } + + void ReserveDown() + { + if (_size == _capacity) + return; + T *p = NULL; + if (_size != 0) + { + p = new T[_size]; + memcpy(p, _items, (size_t)_size * (size_t)sizeof(T)); + } + delete []_items; + _items = p; + _capacity = _size; + } + + ~CRecordVector() { delete []_items; } + + void ClearAndFree() + { + delete []_items; + _items = NULL; + _size = 0; + _capacity = 0; + } + + void Clear() { _size = 0; } + + void DeleteBack() { _size--; } + + void DeleteFrom(unsigned index) + { + // if (index <= _size) + _size = index; + } + + void DeleteFrontal(unsigned num) + { + if (num != 0) + { + MoveItems(0, num); + _size -= num; + } + } + + void Delete(unsigned index) + { + MoveItems(index, index + 1); + _size -= 1; + } + + /* + void Delete(unsigned index, unsigned num) + { + if (num > 0) + { + MoveItems(index, index + num); + _size -= num; + } + } + */ + + CRecordVector& operator=(const CRecordVector &v) + { + unsigned size = v.Size(); + if (size > _capacity) + { + delete []_items; + _capacity = 0; + _size = 0; + _items = NULL; + _items = new T[size]; + _capacity = size; + } + _size = size; + memcpy(_items, v._items, (size_t)size * (size_t)sizeof(T)); + return *this; + } + CRecordVector& operator+=(const CRecordVector &v) { - int size = v.Size(); - Reserve(Size() + size); - for (int i = 0; i < size; i++) - Add(v[i]); + unsigned size = v.Size(); + Reserve(_size + size); + memcpy(_items + _size, v._items, (size_t)size * (size_t)sizeof(T)); + _size += size; return *this; } - int Add(T item) + + unsigned Add(const T item) { ReserveOnePosition(); - ((T *)_items)[_size] = item; + _items[_size] = item; return _size++; } - void Insert(int index, T item) + + void AddInReserved(const T item) { - InsertOneItem(index); - ((T *)_items)[index] = item; + _items[_size++] = item; } - // T* GetPointer() const { return (T*)_items; } - // operator const T *() const { return _items; }; - const T& operator[](int index) const { return ((T *)_items)[index]; } - T& operator[](int index) { return ((T *)_items)[index]; } - const T& Front() const { return operator[](0); } - T& Front() { return operator[](0); } - const T& Back() const { return operator[](_size - 1); } - T& Back() { return operator[](_size - 1); } - void Swap(int i, int j) + void Insert(unsigned index, const T item) { - T temp = operator[](i); - operator[](i) = operator[](j); - operator[](j) = temp; + ReserveOnePosition(); + MoveItems(index + 1, index); + _items[index] = item; + _size++; } - int FindInSorted(const T& item, int left, int right) const + void MoveToFront(unsigned index) + { + if (index != 0) + { + T temp = _items[index]; + memmove(_items + 1, _items, (size_t)index * (size_t)sizeof(T)); + _items[0] = temp; + } + } + + const T& operator[](unsigned index) const { return _items[index]; } + T& operator[](unsigned index) { return _items[index]; } + const T& Front() const { return _items[0]; } + T& Front() { return _items[0]; } + const T& Back() const { return _items[_size - 1]; } + T& Back() { return _items[_size - 1]; } + + /* + void Swap(unsigned i, unsigned j) + { + T temp = _items[i]; + _items[i] = _items[j]; + _items[j] = temp; + } + */ + + int FindInSorted(const T item, unsigned left, unsigned right) const { while (left != right) { - int mid = (left + right) / 2; - const T& midValue = (*this)[mid]; - if (item == midValue) + unsigned mid = (left + right) / 2; + const T midVal = (*this)[mid]; + if (item == midVal) return mid; - if (item < midValue) + if (item < midVal) right = mid; else left = mid + 1; @@ -94,16 +249,16 @@ public: return -1; } - int FindInSorted(const T& item) const + int FindInSorted2(const T &item, unsigned left, unsigned right) const { - int left = 0, right = Size(); while (left != right) { - int mid = (left + right) / 2; - const T& midValue = (*this)[mid]; - if (item == midValue) + unsigned mid = (left + right) / 2; + const T& midVal = (*this)[mid]; + int comp = item.Compare(midVal); + if (comp == 0) return mid; - if (item < midValue) + if (comp < 0) right = mid; else left = mid + 1; @@ -111,16 +266,26 @@ public: return -1; } - int AddToUniqueSorted(const T& item) + int FindInSorted(const T item) const + { + return FindInSorted(item, 0, _size); + } + + int FindInSorted2(const T &item) const + { + return FindInSorted2(item, 0, _size); + } + + unsigned AddToUniqueSorted(const T item) { - int left = 0, right = Size(); + unsigned left = 0, right = _size; while (left != right) { - int mid = (left + right) / 2; - const T& midValue = (*this)[mid]; - if (item == midValue) + unsigned mid = (left + right) / 2; + const T midVal = (*this)[mid]; + if (item == midVal) return mid; - if (item < midValue) + if (item < midVal) right = mid; else left = mid + 1; @@ -129,12 +294,31 @@ public: return right; } - static void SortRefDown(T* p, int k, int size, int (*compare)(const T*, const T*, void *), void *param) + unsigned AddToUniqueSorted2(const T &item) + { + unsigned left = 0, right = _size; + while (left != right) + { + unsigned mid = (left + right) / 2; + const T& midVal = (*this)[mid]; + int comp = item.Compare(midVal); + if (comp == 0) + return mid; + if (comp < 0) + right = mid; + else + left = mid + 1; + } + Insert(right, item); + return right; + } + + static void SortRefDown(T* p, unsigned k, unsigned size, int (*compare)(const T*, const T*, void *), void *param) { T temp = p[k]; for (;;) { - int s = (k << 1); + unsigned s = (k << 1); if (s > size) break; if (s < size && compare(p + s + 1, p + s, param) > 0) @@ -149,12 +333,12 @@ public: void Sort(int (*compare)(const T*, const T*, void *), void *param) { - int size = _size; + unsigned size = _size; if (size <= 1) return; T* p = (&Front()) - 1; { - int i = size / 2; + unsigned i = size >> 1; do SortRefDown(p, i, size, compare, param); while (--i != 0); @@ -168,6 +352,46 @@ public: } while (size > 1); } + + static void SortRefDown2(T* p, unsigned k, unsigned size) + { + T temp = p[k]; + for (;;) + { + unsigned s = (k << 1); + if (s > size) + break; + if (s < size && p[s + 1].Compare(p[s]) > 0) + s++; + if (temp.Compare(p[s]) >= 0) + break; + p[k] = p[s]; + k = s; + } + p[k] = temp; + } + + void Sort2() + { + unsigned size = _size; + if (size <= 1) + return; + T* p = (&Front()) - 1; + { + unsigned i = size >> 1; + do + SortRefDown2(p, i, size); + while (--i != 0); + } + do + { + T temp = p[size]; + p[size--] = p[1]; + p[1] = temp; + SortRefDown2(p, 1, size); + } + while (size > 1); + } }; typedef CRecordVector CIntVector; @@ -177,76 +401,197 @@ typedef CRecordVector CByteVector; typedef CRecordVector CPointerVector; template -class CObjectVector: public CPointerVector +class CObjectVector { + CPointerVector _v; public: + unsigned Size() const { return _v.Size(); } + bool IsEmpty() const { return _v.IsEmpty(); } + void ReserveDown() { _v.ReserveDown(); } + // void Reserve(unsigned newCapacity) { _v.Reserve(newCapacity); } + void ClearAndReserve(unsigned newCapacity) { Clear(); _v.ClearAndReserve(newCapacity); } + CObjectVector() {}; - ~CObjectVector() { Clear(); }; - CObjectVector(const CObjectVector &v): CPointerVector() { *this = v; } + CObjectVector(const CObjectVector &v) + { + unsigned size = v.Size(); + _v.ConstructReserve(size); + for (unsigned i = 0; i < size; i++) + _v.AddInReserved(new T(v[i])); + } CObjectVector& operator=(const CObjectVector &v) { Clear(); - return (*this += v); + unsigned size = v.Size(); + _v.Reserve(size); + for (unsigned i = 0; i < size; i++) + _v.AddInReserved(new T(v[i])); + return *this; } + CObjectVector& operator+=(const CObjectVector &v) { - int size = v.Size(); - Reserve(Size() + size); - for (int i = 0; i < size; i++) - Add(v[i]); + unsigned size = v.Size(); + _v.Reserve(Size() + size); + for (unsigned i = 0; i < size; i++) + _v.AddInReserved(new T(v[i])); return *this; } - const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); } - T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); } - T& Front() { return operator[](0); } + + const T& operator[](unsigned index) const { return *((T *)_v[index]); } + T& operator[](unsigned index) { return *((T *)_v[index]); } const T& Front() const { return operator[](0); } - T& Back() { return operator[](_size - 1); } - const T& Back() const { return operator[](_size - 1); } - int Add(const T& item) { return CPointerVector::Add(new T(item)); } - void Insert(int index, const T& item) { CPointerVector::Insert(index, new T(item)); } - virtual void Delete(int index, int num = 1) + T& Front() { return operator[](0); } + const T& Back() const { return operator[](_v.Size() - 1); } + T& Back() { return operator[](_v.Size() - 1); } + + void MoveToFront(unsigned index) { _v.MoveToFront(index); } + + unsigned Add(const T& item) { return _v.Add(new T(item)); } + + void AddInReserved(const T& item) { _v.AddInReserved(new T(item)); } + + T& AddNew() + { + T *p = new T; + _v.Add(p); + return *p; + } + + T& AddNewInReserved() + { + T *p = new T; + _v.AddInReserved(p); + return *p; + } + + void Insert(unsigned index, const T& item) { _v.Insert(index, new T(item)); } + + T& InsertNew(unsigned index) + { + T *p = new T; + _v.Insert(index, p); + return *p; + } + + ~CObjectVector() + { + for (unsigned i = _v.Size(); i != 0;) + delete (T *)_v[--i]; + } + + void ClearAndFree() + { + Clear(); + _v.ClearAndFree(); + } + + void Clear() + { + for (unsigned i = _v.Size(); i != 0;) + delete (T *)_v[--i]; + _v.Clear(); + } + + void DeleteFrom(unsigned index) + { + unsigned size = _v.Size(); + for (unsigned i = index; i < size; i++) + delete (T *)_v[i]; + _v.DeleteFrom(index); + } + + void DeleteFrontal(unsigned num) + { + for (unsigned i = 0; i < num; i++) + delete (T *)_v[i]; + _v.DeleteFrontal(num); + } + + void DeleteBack() { - TestIndexAndCorrectNum(index, num); - for (int i = 0; i < num; i++) - delete (T *)(((void **)_items)[index + i]); - CPointerVector::Delete(index, num); + delete (T *)_v[_v.Size() - 1]; + _v.DeleteBack(); } + + void Delete(unsigned index) + { + delete (T *)_v[index]; + _v.Delete(index); + } + + /* + void Delete(unsigned index, unsigned num) + { + for (unsigned i = 0; i < num; i++) + delete (T *)_v[index + i]; + _v.Delete(index, num); + } + */ + + /* int Find(const T& item) const { - for (int i = 0; i < Size(); i++) + unsigned size = Size(); + for (unsigned i = 0; i < size; i++) if (item == (*this)[i]) return i; return -1; } + */ + int FindInSorted(const T& item) const { - int left = 0, right = Size(); + unsigned left = 0, right = Size(); while (left != right) { - int mid = (left + right) / 2; - const T& midValue = (*this)[mid]; - if (item == midValue) + unsigned mid = (left + right) / 2; + const T& midVal = (*this)[mid]; + int comp = item.Compare(midVal); + if (comp == 0) return mid; - if (item < midValue) + if (comp < 0) right = mid; else left = mid + 1; } return -1; } - int AddToSorted(const T& item) + + unsigned AddToUniqueSorted(const T& item) { - int left = 0, right = Size(); + unsigned left = 0, right = Size(); while (left != right) { - int mid = (left + right) / 2; - const T& midValue = (*this)[mid]; - if (item == midValue) + unsigned mid = (left + right) / 2; + const T& midVal = (*this)[mid]; + int comp = item.Compare(midVal); + if (comp == 0) + return mid; + if (comp < 0) + right = mid; + else + left = mid + 1; + } + Insert(right, item); + return right; + } + + /* + unsigned AddToSorted(const T& item) + { + unsigned left = 0, right = Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + const T& midVal = (*this)[mid]; + int comp = item.Compare(midVal); + if (comp == 0) { right = mid + 1; break; } - if (item < midValue) + if (comp < 0) right = mid; else left = mid + 1; @@ -254,13 +599,17 @@ public: Insert(right, item); return right; } + */ void Sort(int (*compare)(void *const *, void *const *, void *), void *param) - { CPointerVector::Sort(compare, param); } + { _v.Sort(compare, param); } static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */) - { return MyCompare(*(*((const T **)a1)), *(*((const T **)a2))); } - void Sort() { CPointerVector::Sort(CompareObjectItems, 0); } + { return (*(*((const T **)a1))).Compare(*(*((const T **)a2))); } + + void Sort() { _v.Sort(CompareObjectItems, 0); } }; +#define FOR_VECTOR(_i_, _v_) for (unsigned _i_ = 0; _i_ < (_v_).Size(); _i_++) + #endif diff --git a/src/libs/7zip/win/CPP/Common/MyWindows.cpp b/src/libs/7zip/win/CPP/Common/MyWindows.cpp new file mode 100644 index 000000000..38c93fdb2 --- /dev/null +++ b/src/libs/7zip/win/CPP/Common/MyWindows.cpp @@ -0,0 +1,145 @@ +// MyWindows.cpp + +#include "StdAfx.h" + +#ifndef _WIN32 + +#include + +#include "MyWindows.h" + +static inline void *AllocateForBSTR(size_t cb) { return ::malloc(cb); } +static inline void FreeForBSTR(void *pv) { ::free(pv);} + +/* Win32 uses DWORD (32-bit) type to store size of string before (OLECHAR *) string. + We must select CBstrSizeType for another systems (not Win32): + + if (CBstrSizeType is UINT32), + then we support only strings smaller than 4 GB. + Win32 version always has that limitation. + + if (CBstrSizeType is UINT), + (UINT can be 16/32/64-bit) + We can support strings larger than 4 GB (if UINT is 64-bit), + but sizeof(UINT) can be different in parts compiled by + different compilers/settings, + and we can't send such BSTR strings between such parts. +*/ + +typedef UINT32 CBstrSizeType; +// typedef UINT CBstrSizeType; + +#define k_BstrSize_Max 0xFFFFFFFF +// #define k_BstrSize_Max UINT_MAX +// #define k_BstrSize_Max ((UINT)(INT)-1) + +BSTR SysAllocStringByteLen(LPCSTR s, UINT len) +{ + /* Original SysAllocStringByteLen in Win32 maybe fills only unaligned null OLECHAR at the end. + We provide also aligned null OLECHAR at the end. */ + + if (len >= (k_BstrSize_Max - sizeof(OLECHAR) - sizeof(OLECHAR) - sizeof(CBstrSizeType))) + return NULL; + + UINT size = (len + sizeof(OLECHAR) + sizeof(OLECHAR) - 1) & ~(sizeof(OLECHAR) - 1); + void *p = AllocateForBSTR(size + sizeof(CBstrSizeType)); + if (!p) + return NULL; + *(CBstrSizeType *)p = (CBstrSizeType)len; + BSTR bstr = (BSTR)((CBstrSizeType *)p + 1); + if (s) + memcpy(bstr, s, len); + for (; len < size; len++) + ((Byte *)bstr)[len] = 0; + return bstr; +} + +BSTR SysAllocStringLen(const OLECHAR *s, UINT len) +{ + if (len >= (k_BstrSize_Max - sizeof(OLECHAR) - sizeof(CBstrSizeType)) / sizeof(OLECHAR)) + return NULL; + + UINT size = len * sizeof(OLECHAR); + void *p = AllocateForBSTR(size + sizeof(CBstrSizeType) + sizeof(OLECHAR)); + if (!p) + return NULL; + *(CBstrSizeType *)p = (CBstrSizeType)size; + BSTR bstr = (BSTR)((CBstrSizeType *)p + 1); + if (s) + memcpy(bstr, s, size); + bstr[len] = 0; + return bstr; +} + +BSTR SysAllocString(const OLECHAR *s) +{ + if (!s) + return 0; + const OLECHAR *s2 = s; + while (*s2 != 0) + s2++; + return SysAllocStringLen(s, (UINT)(s2 - s)); +} + +void SysFreeString(BSTR bstr) +{ + if (bstr) + FreeForBSTR((CBstrSizeType *)bstr - 1); +} + +UINT SysStringByteLen(BSTR bstr) +{ + if (!bstr) + return 0; + return *((CBstrSizeType *)bstr - 1); +} + +UINT SysStringLen(BSTR bstr) +{ + if (!bstr) + return 0; + return *((CBstrSizeType *)bstr - 1) / sizeof(OLECHAR); +} + + +HRESULT VariantClear(VARIANTARG *prop) +{ + if (prop->vt == VT_BSTR) + SysFreeString(prop->bstrVal); + prop->vt = VT_EMPTY; + return S_OK; +} + +HRESULT VariantCopy(VARIANTARG *dest, const VARIANTARG *src) +{ + HRESULT res = ::VariantClear(dest); + if (res != S_OK) + return res; + if (src->vt == VT_BSTR) + { + dest->bstrVal = SysAllocStringByteLen((LPCSTR)src->bstrVal, + SysStringByteLen(src->bstrVal)); + if (!dest->bstrVal) + return E_OUTOFMEMORY; + dest->vt = VT_BSTR; + } + else + *dest = *src; + return S_OK; +} + +LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2) +{ + if (ft1->dwHighDateTime < ft2->dwHighDateTime) return -1; + if (ft1->dwHighDateTime > ft2->dwHighDateTime) return 1; + if (ft1->dwLowDateTime < ft2->dwLowDateTime) return -1; + if (ft1->dwLowDateTime > ft2->dwLowDateTime) return 1; + return 0; +} + +DWORD GetLastError() +{ + return 0; +} + +#endif diff --git a/src/libs/7zip/win/CPP/Common/MyWindows.h b/src/libs/7zip/win/CPP/Common/MyWindows.h index 8b0e5c069..139a4e8b9 100644 --- a/src/libs/7zip/win/CPP/Common/MyWindows.h +++ b/src/libs/7zip/win/CPP/Common/MyWindows.h @@ -1,12 +1,17 @@ // MyWindows.h -#ifndef __MYWINDOWS_H -#define __MYWINDOWS_H +#ifndef __MY_WINDOWS_H +#define __MY_WINDOWS_H #ifdef _WIN32 #include +#ifdef UNDER_CE + #undef VARIANT_TRUE + #define VARIANT_TRUE ((VARIANT_BOOL)-1) +#endif + #else #include // for wchar_t @@ -14,6 +19,8 @@ #include "MyGuidDef.h" +#define WINAPI + typedef char CHAR; typedef unsigned char UCHAR; @@ -40,8 +47,8 @@ typedef UINT32 DWORD; typedef Int64 LONGLONG; typedef UInt64 ULONGLONG; -typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER; -typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER; +typedef struct _LARGE_INTEGER { LONGLONG QuadPart; } LARGE_INTEGER; +typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart; } ULARGE_INTEGER; typedef const CHAR *LPCSTR; typedef CHAR TCHAR; @@ -57,7 +64,7 @@ typedef struct _FILETIME { DWORD dwLowDateTime; DWORD dwHighDateTime; -}FILETIME; +} FILETIME; #define HRESULT LONG #define FAILED(Status) ((HRESULT)(Status)<0) @@ -145,8 +152,6 @@ typedef WORD PROPVAR_PAD1; typedef WORD PROPVAR_PAD2; typedef WORD PROPVAR_PAD3; -#ifdef __cplusplus - typedef struct tagPROPVARIANT { VARTYPE vt; @@ -177,11 +182,17 @@ typedef tagVARIANT VARIANT; typedef VARIANT VARIANTARG; MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop); -MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src); +MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, const VARIANTARG *src); -#endif +typedef struct tagSTATPROPSTG +{ + LPOLESTR lpwstrName; + PROPID propid; + VARTYPE vt; +} STATPROPSTG; MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len); +MY_EXTERN_C BSTR SysAllocStringLen(const OLECHAR *sz, UINT len); MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz); MY_EXTERN_C void SysFreeString(BSTR bstr); MY_EXTERN_C UINT SysStringByteLen(BSTR bstr); @@ -192,6 +203,7 @@ MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); #define CP_ACP 0 #define CP_OEMCP 1 +#define CP_UTF8 65001 typedef enum tagSTREAM_SEEK { diff --git a/src/libs/7zip/win/CPP/Common/NewHandler.cpp b/src/libs/7zip/win/CPP/Common/NewHandler.cpp index aad6e7d16..9072376df 100644 --- a/src/libs/7zip/win/CPP/Common/NewHandler.cpp +++ b/src/libs/7zip/win/CPP/Common/NewHandler.cpp @@ -1,5 +1,5 @@ // NewHandler.cpp - + #include "StdAfx.h" #include @@ -11,6 +11,32 @@ #ifndef DEBUG_MEMORY_LEAK #ifdef _WIN32 + +/* +void * my_new(size_t size) +{ + // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); + void *p = ::malloc(size); + if (p == 0) + throw CNewException(); + return p; +} + +void my_delete(void *p) throw() +{ + // if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); + ::free(p); +} + +void * my_Realloc(void *p, size_t newSize, size_t oldSize) +{ + void *newBuf = my_new(newSize); + memcpy(newBuf, p, oldSize); + my_delete(p); + return newBuf; +} +*/ + void * #ifdef _MSC_VER __cdecl @@ -30,18 +56,42 @@ __cdecl #endif operator delete(void *p) throw() { - /* + // if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); + ::free(p); +} + +/* +void * +#ifdef _MSC_VER +__cdecl +#endif +operator new[](size_t size) +{ + // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); + void *p = ::malloc(size); if (p == 0) - return; - ::HeapFree(::GetProcessHeap(), 0, p); - */ + throw CNewException(); + return p; +} + +void +#ifdef _MSC_VER +__cdecl +#endif +operator delete[](void *p) throw() +{ + // if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); ::free(p); } +*/ + #endif #else -#pragma init_seg(lib) +#include + +// #pragma init_seg(lib) const int kDebugSize = 1000000; static void *a[kDebugSize]; static int index = 0; @@ -51,10 +101,6 @@ void * __cdecl operator new(size_t size) { numAllocs++; void *p = HeapAlloc(GetProcessHeap(), 0, size); - if (index == 40) - { - int t = 1; - } if (index < kDebugSize) { a[index] = p; diff --git a/src/libs/7zip/win/CPP/Common/NewHandler.h b/src/libs/7zip/win/CPP/Common/NewHandler.h index 215ba05f1..e3e7422c8 100644 --- a/src/libs/7zip/win/CPP/Common/NewHandler.h +++ b/src/libs/7zip/win/CPP/Common/NewHandler.h @@ -1,16 +1,68 @@ // Common/NewHandler.h -#ifndef __COMMON_NEWHANDLER_H -#define __COMMON_NEWHANDLER_H +#ifndef __COMMON_NEW_HANDLER_H +#define __COMMON_NEW_HANDLER_H + +/* +This file must be included before any code that uses operators "delete" or "new". +Also you must compile and link "NewHandler.cpp", if you use MSVC 6.0. +The operator "new" in MSVC 6.0 doesn't throw exception "bad_alloc". +So we define another version of operator "new" that throws "CNewException" on failure. + +If you use compiler that throws exception in "new" operator (GCC or new version of MSVC), +you can compile without "NewHandler.cpp". So standard exception "bad_alloc" will be used. + +It's still allowed to use redefined version of operator "new" from "NewHandler.cpp" +with any compiler. 7-Zip's code can work with "bad_alloc" and "CNewException" exceptions. +But if you use some additional code (outside of 7-Zip's code), you must check +that redefined version of operator "new" (that throws CNewException) is not +problem for your code. + +Also we declare delete(void *p) throw() that creates smaller code. +*/ + class CNewException {}; +#ifdef WIN32 +// We can compile my_new and my_delete with _fastcall +/* +void * my_new(size_t size); +void my_delete(void *p) throw(); +// void * my_Realloc(void *p, size_t newSize, size_t oldSize); +*/ +#endif + #ifdef _WIN32 + +void * +#ifdef _MSC_VER +__cdecl +#endif +operator new(size_t size); + void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw(); + +#endif + +/* +#ifdef _WIN32 +void * +#ifdef _MSC_VER +__cdecl +#endif +operator new[](size_t size); + +void +#ifdef _MSC_VER +__cdecl +#endif +operator delete[](void *p) throw(); #endif +*/ #endif diff --git a/src/libs/7zip/win/CPP/Common/StdAfx.h b/src/libs/7zip/win/CPP/Common/StdAfx.h index b8ba1d5c4..420f5c326 100644 --- a/src/libs/7zip/win/CPP/Common/StdAfx.h +++ b/src/libs/7zip/win/CPP/Common/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -// #include "MyWindows.h" -#include "NewHandler.h" +#include "Common.h" #endif diff --git a/src/libs/7zip/win/CPP/Common/StdInStream.cpp b/src/libs/7zip/win/CPP/Common/StdInStream.cpp deleted file mode 100644 index f3dcb85f5..000000000 --- a/src/libs/7zip/win/CPP/Common/StdInStream.cpp +++ /dev/null @@ -1,107 +0,0 @@ -// Common/StdInStream.cpp - -#include "StdAfx.h" - -#include - -#include "StdInStream.h" -#include "StringConvert.h" -#include "UTFConvert.h" - -#ifdef _MSC_VER -// "was declared deprecated" disabling -#pragma warning(disable : 4996 ) -#endif - -static const char kIllegalChar = '\0'; -static const char kNewLineChar = '\n'; - -static const char *kEOFMessage = "Unexpected end of input stream"; -static const char *kReadErrorMessage ="Error reading input stream"; -static const char *kIllegalCharMessage = "Illegal character in input stream"; - -static LPCTSTR kFileOpenMode = TEXT("r"); - -extern int g_CodePage; - -CStdInStream g_StdIn(stdin); - -bool CStdInStream::Open(LPCTSTR fileName) -{ - Close(); - _stream = _tfopen(fileName, kFileOpenMode); - _streamIsOpen = (_stream != 0); - return _streamIsOpen; -} - -bool CStdInStream::Close() -{ - if (!_streamIsOpen) - return true; - _streamIsOpen = (fclose(_stream) != 0); - return !_streamIsOpen; -} - -CStdInStream::~CStdInStream() -{ - Close(); -} - -AString CStdInStream::ScanStringUntilNewLine(bool allowEOF) -{ - AString s; - for (;;) - { - int intChar = GetChar(); - if (intChar == EOF) - { - if (allowEOF) - break; - throw kEOFMessage; - } - char c = char(intChar); - if (c == kIllegalChar) - throw kIllegalCharMessage; - if (c == kNewLineChar) - break; - s += c; - } - return s; -} - -UString CStdInStream::ScanUStringUntilNewLine() -{ - AString s = ScanStringUntilNewLine(true); - int codePage = g_CodePage; - if (codePage == -1) - codePage = CP_OEMCP; - UString dest; - if (codePage == CP_UTF8) - ConvertUTF8ToUnicode(s, dest); - else - dest = MultiByteToUnicodeString(s, (UINT)codePage); - return dest; -} - -void CStdInStream::ReadToString(AString &resultString) -{ - resultString.Empty(); - int c; - while ((c = GetChar()) != EOF) - resultString += char(c); -} - -bool CStdInStream::Eof() -{ - return (feof(_stream) != 0); -} - -int CStdInStream::GetChar() -{ - int c = fgetc(_stream); // getc() doesn't work in BeOS? - if (c == EOF && !Eof()) - throw kReadErrorMessage; - return c; -} - - diff --git a/src/libs/7zip/win/CPP/Common/StdInStream.h b/src/libs/7zip/win/CPP/Common/StdInStream.h deleted file mode 100644 index 0d182cc3c..000000000 --- a/src/libs/7zip/win/CPP/Common/StdInStream.h +++ /dev/null @@ -1,32 +0,0 @@ -// Common/StdInStream.h - -#ifndef __COMMON_STDINSTREAM_H -#define __COMMON_STDINSTREAM_H - -#include - -#include "MyString.h" -#include "Types.h" - -class CStdInStream -{ - bool _streamIsOpen; - FILE *_stream; -public: - CStdInStream(): _streamIsOpen(false) {}; - CStdInStream(FILE *stream): _streamIsOpen(false), _stream(stream) {}; - ~CStdInStream(); - bool Open(LPCTSTR fileName); - bool Close(); - - AString ScanStringUntilNewLine(bool allowEOF = false); - void ReadToString(AString &resultString); - UString ScanUStringUntilNewLine(); - - bool Eof(); - int GetChar(); -}; - -extern CStdInStream g_StdIn; - -#endif diff --git a/src/libs/7zip/win/CPP/Common/StdOutStream.cpp b/src/libs/7zip/win/CPP/Common/StdOutStream.cpp index 061a76063..6aed31a31 100644 --- a/src/libs/7zip/win/CPP/Common/StdOutStream.cpp +++ b/src/libs/7zip/win/CPP/Common/StdOutStream.cpp @@ -9,21 +9,16 @@ #include "StringConvert.h" #include "UTFConvert.h" -#ifdef _MSC_VER -// "was declared deprecated" disabling -#pragma warning(disable : 4996 ) -#endif - static const char kNewLineChar = '\n'; static const char *kFileOpenMode = "wt"; extern int g_CodePage; -CStdOutStream g_StdOut(stdout); -CStdOutStream g_StdErr(stderr); +CStdOutStream g_StdOut(stdout); +CStdOutStream g_StdErr(stderr); -bool CStdOutStream::Open(const char *fileName) +bool CStdOutStream::Open(const char *fileName) throw() { Close(); _stream = fopen(fileName, kFileOpenMode); @@ -31,7 +26,7 @@ bool CStdOutStream::Open(const char *fileName) return _streamIsOpen; } -bool CStdOutStream::Close() +bool CStdOutStream::Close() throw() { if (!_streamIsOpen) return true; @@ -42,33 +37,16 @@ bool CStdOutStream::Close() return true; } -bool CStdOutStream::Flush() +bool CStdOutStream::Flush() throw() { return (fflush(_stream) == 0); } -CStdOutStream::~CStdOutStream () -{ - Close(); -} - -CStdOutStream & CStdOutStream::operator<<(CStdOutStream & (*aFunction)(CStdOutStream &)) -{ - (*aFunction)(*this); - return *this; -} - -CStdOutStream & endl(CStdOutStream & outStream) +CStdOutStream & endl(CStdOutStream & outStream) throw() { return outStream << kNewLineChar; } -CStdOutStream & CStdOutStream::operator<<(const char *s) -{ - fputs(s, _stream); - return *this; -} - CStdOutStream & CStdOutStream::operator<<(const wchar_t *s) { int codePage = g_CodePage; @@ -78,27 +56,51 @@ CStdOutStream & CStdOutStream::operator<<(const wchar_t *s) if (codePage == CP_UTF8) ConvertUnicodeToUTF8(s, dest); else - dest = UnicodeStringToMultiByte(s, (UINT)codePage); - *this << (const char *)dest; - return *this; + UnicodeStringToMultiByte2(dest, s, (UINT)codePage); + return operator<<((const char *)dest); +} + +void StdOut_Convert_UString_to_AString(const UString &s, AString &temp) +{ + int codePage = g_CodePage; + if (codePage == -1) + codePage = CP_OEMCP; + if (codePage == CP_UTF8) + ConvertUnicodeToUTF8(s, temp); + else + UnicodeStringToMultiByte2(temp, s, (UINT)codePage); +} + +void CStdOutStream::PrintUString(const UString &s, AString &temp) +{ + StdOut_Convert_UString_to_AString(s, temp); + *this << (const char *)temp; +} + +CStdOutStream & CStdOutStream::operator<<(Int32 number) throw() +{ + char s[32]; + ConvertInt64ToString(number, s); + return operator<<(s); } -CStdOutStream & CStdOutStream::operator<<(char c) +CStdOutStream & CStdOutStream::operator<<(Int64 number) throw() { - fputc(c, _stream); - return *this; + char s[32]; + ConvertInt64ToString(number, s); + return operator<<(s); } -CStdOutStream & CStdOutStream::operator<<(int number) +CStdOutStream & CStdOutStream::operator<<(UInt32 number) throw() { - char textString[32]; - ConvertInt64ToString(number, textString); - return operator<<(textString); + char s[16]; + ConvertUInt32ToString(number, s); + return operator<<(s); } -CStdOutStream & CStdOutStream::operator<<(UInt64 number) +CStdOutStream & CStdOutStream::operator<<(UInt64 number) throw() { - char textString[32]; - ConvertUInt64ToString(number, textString); - return operator<<(textString); + char s[32]; + ConvertUInt64ToString(number, s); + return operator<<(s); } diff --git a/src/libs/7zip/win/CPP/Common/StdOutStream.h b/src/libs/7zip/win/CPP/Common/StdOutStream.h index b0b2c615c..0a8c0febb 100644 --- a/src/libs/7zip/win/CPP/Common/StdOutStream.h +++ b/src/libs/7zip/win/CPP/Common/StdOutStream.h @@ -1,35 +1,62 @@ // Common/StdOutStream.h -#ifndef __COMMON_STDOUTSTREAM_H -#define __COMMON_STDOUTSTREAM_H +#ifndef __COMMON_STD_OUT_STREAM_H +#define __COMMON_STD_OUT_STREAM_H #include -#include "Types.h" +#include "MyString.h" +#include "MyTypes.h" class CStdOutStream { - bool _streamIsOpen; FILE *_stream; + bool _streamIsOpen; public: - CStdOutStream (): _streamIsOpen(false), _stream(0) {}; - CStdOutStream (FILE *stream): _streamIsOpen(false), _stream(stream) {}; - ~CStdOutStream (); + CStdOutStream(): _stream(0), _streamIsOpen(false) {}; + CStdOutStream(FILE *stream): _stream(stream), _streamIsOpen(false) {}; + ~CStdOutStream() { Close(); } + + // void AttachStdStream(FILE *stream) { _stream = stream; _streamIsOpen = false; } + // bool IsDefined() const { return _stream != NULL; } + operator FILE *() { return _stream; } - bool Open(const char *fileName); - bool Close(); - bool Flush(); - CStdOutStream & operator<<(CStdOutStream & (* aFunction)(CStdOutStream &)); - CStdOutStream & operator<<(const char *string); - CStdOutStream & operator<<(const wchar_t *string); - CStdOutStream & operator<<(char c); - CStdOutStream & operator<<(int number); - CStdOutStream & operator<<(UInt64 number); + bool Open(const char *fileName) throw(); + bool Close() throw(); + bool Flush() throw(); + + CStdOutStream & operator<<(CStdOutStream & (* func)(CStdOutStream &)) + { + (*func)(*this); + return *this; + } + + CStdOutStream & operator<<(const char *s) throw() + { + fputs(s, _stream); + return *this; + } + + CStdOutStream & operator<<(char c) throw() + { + fputc(c, _stream); + return *this; + } + + CStdOutStream & operator<<(Int32 number) throw(); + CStdOutStream & operator<<(Int64 number) throw(); + CStdOutStream & operator<<(UInt32 number) throw(); + CStdOutStream & operator<<(UInt64 number) throw(); + + CStdOutStream & operator<<(const wchar_t *s); + void PrintUString(const UString &s, AString &temp); }; -CStdOutStream & endl(CStdOutStream & outStream); +CStdOutStream & endl(CStdOutStream & outStream) throw(); extern CStdOutStream g_StdOut; extern CStdOutStream g_StdErr; +void StdOut_Convert_UString_to_AString(const UString &s, AString &temp); + #endif diff --git a/src/libs/7zip/win/CPP/Common/StringConvert.cpp b/src/libs/7zip/win/CPP/Common/StringConvert.cpp index 681895b71..0443a06ca 100644 --- a/src/libs/7zip/win/CPP/Common/StringConvert.cpp +++ b/src/libs/7zip/win/CPP/Common/StringConvert.cpp @@ -15,8 +15,8 @@ UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) if (!srcString.IsEmpty()) { int numChars = MultiByteToWideChar(codePage, 0, srcString, - srcString.Length(), resultString.GetBuffer(srcString.Length()), - srcString.Length() + 1); + srcString.Len(), resultString.GetBuffer(srcString.Len()), + srcString.Len() + 1); if (numChars == 0) throw 282228; resultString.ReleaseBuffer(numChars); @@ -24,15 +24,83 @@ UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) return resultString; } +void MultiByteToUnicodeString2(UString &dest, const AString &srcString, UINT codePage) +{ + dest.Empty(); + if (!srcString.IsEmpty()) + { + wchar_t *destBuf = dest.GetBuffer(srcString.Len()); + const char *sp = (const char *)srcString; + unsigned i; + for (i = 0;;) + { + char c = sp[i]; + if ((Byte)c >= 0x80 || c == 0) + break; + destBuf[i++] = (wchar_t)c; + } + + if (i != srcString.Len()) + { + unsigned numChars = MultiByteToWideChar(codePage, 0, sp + i, + srcString.Len() - i, destBuf + i, + srcString.Len() + 1 - i); + if (numChars == 0) + throw 282228; + i += numChars; + } + dest.ReleaseBuffer(i); + } +} + +void UnicodeStringToMultiByte2(AString &dest, const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed) +{ + dest.Empty(); + defaultCharWasUsed = false; + if (!s.IsEmpty()) + { + unsigned numRequiredBytes = s.Len() * 2; + char *destBuf = dest.GetBuffer(numRequiredBytes); + unsigned i; + const wchar_t *sp = (const wchar_t *)s; + for (i = 0;;) + { + wchar_t c = sp[i]; + if (c >= 0x80 || c == 0) + break; + destBuf[i++] = (char)c; + } + defaultCharWasUsed = false; + if (i != s.Len()) + { + BOOL defUsed; + unsigned numChars = WideCharToMultiByte(codePage, 0, sp + i, s.Len() - i, + destBuf + i, numRequiredBytes + 1 - i, + &defaultChar, &defUsed); + defaultCharWasUsed = (defUsed != FALSE); + if (numChars == 0) + throw 282229; + i += numChars; + } + dest.ReleaseBuffer(i); + } +} + +void UnicodeStringToMultiByte2(AString &dest, const UString &srcString, UINT codePage) +{ + bool defaultCharWasUsed; + UnicodeStringToMultiByte2(dest, srcString, codePage, '_', defaultCharWasUsed); +} + AString UnicodeStringToMultiByte(const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed) { AString dest; defaultCharWasUsed = false; if (!s.IsEmpty()) { - int numRequiredBytes = s.Length() * 2; + unsigned numRequiredBytes = s.Len() * 2; BOOL defUsed; - int numChars = WideCharToMultiByte(codePage, 0, s, s.Length(), + int numChars = WideCharToMultiByte(codePage, 0, s, s.Len(), dest.GetBuffer(numRequiredBytes), numRequiredBytes + 1, &defaultChar, &defUsed); defaultCharWasUsed = (defUsed != FALSE); @@ -53,7 +121,7 @@ AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) AString SystemStringToOemString(const CSysString &srcString) { AString result; - CharToOem(srcString, result.GetBuffer(srcString.Length() * 2)); + CharToOem(srcString, result.GetBuffer(srcString.Len() * 2)); result.ReleaseBuffer(); return result; } @@ -64,12 +132,12 @@ AString SystemStringToOemString(const CSysString &srcString) UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; - for (int i = 0; i < srcString.Length(); i++) - resultString += wchar_t(srcString[i]); + for (unsigned i = 0; i < srcString.Len(); i++) + resultString += (wchar_t)srcString[i]; /* if (!srcString.IsEmpty()) { - int numChars = mbstowcs(resultString.GetBuffer(srcString.Length()), srcString, srcString.Length() + 1); + int numChars = mbstowcs(resultString.GetBuffer(srcString.Len()), srcString, srcString.Len() + 1); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } @@ -80,12 +148,12 @@ UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { AString resultString; - for (int i = 0; i < srcString.Length(); i++) - resultString += char(srcString[i]); + for (unsigned i = 0; i < srcString.Len(); i++) + resultString += (char)srcString[i]; /* if (!srcString.IsEmpty()) { - int numRequiredBytes = srcString.Length() * 6 + 1; + int numRequiredBytes = srcString.Len() * 6 + 1; int numChars = wcstombs(resultString.GetBuffer(numRequiredBytes), srcString, numRequiredBytes); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); diff --git a/src/libs/7zip/win/CPP/Common/StringConvert.h b/src/libs/7zip/win/CPP/Common/StringConvert.h index cd737becb..8eea72ef2 100644 --- a/src/libs/7zip/win/CPP/Common/StringConvert.h +++ b/src/libs/7zip/win/CPP/Common/StringConvert.h @@ -3,15 +3,19 @@ #ifndef __COMMON_STRING_CONVERT_H #define __COMMON_STRING_CONVERT_H -#include "MyWindows.h" #include "MyString.h" -#include "Types.h" +#include "MyWindows.h" UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP); + +// optimized versions that work faster for ASCII strings +void MultiByteToUnicodeString2(UString &dest, const AString &srcString, UINT codePage = CP_ACP); +void UnicodeStringToMultiByte2(AString &dest, const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed); +void UnicodeStringToMultiByte2(AString &dest, const UString &srcString, UINT codePage); + AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage, char defaultChar, bool &defaultCharWasUsed); AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage = CP_ACP); - inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString) diff --git a/src/libs/7zip/win/CPP/Common/StringToInt.cpp b/src/libs/7zip/win/CPP/Common/StringToInt.cpp index 9473766bc..2023fcc2c 100644 --- a/src/libs/7zip/win/CPP/Common/StringToInt.cpp +++ b/src/libs/7zip/win/CPP/Common/StringToInt.cpp @@ -4,87 +4,141 @@ #include "StringToInt.h" -UInt64 ConvertStringToUInt64(const char *s, const char **end) +static const UInt32 k_UInt32_max = 0xFFFFFFFF; +static const UInt64 k_UInt64_max = UINT64_CONST(0xFFFFFFFFFFFFFFFF); +// static const UInt64 k_UInt64_max = (UInt64)(Int64)-1; + +#define CONVERT_STRING_TO_UINT_FUNC(uintType, charType) \ + uintType ConvertStringTo ## uintType(const charType *s, const charType **end) throw() { \ + if (end) *end = s; \ + uintType res = 0; \ + for (;; s++) { \ + charType c = *s; \ + if (c < '0' || c > '9') { if (end) *end = s; return res; } \ + if (res > (k_ ## uintType ## _max) / 10) return 0; \ + res *= 10; \ + unsigned v = (c - '0'); \ + if (res > (k_ ## uintType ## _max) - v) return 0; \ + res += v; }} + +CONVERT_STRING_TO_UINT_FUNC(UInt32, char) +CONVERT_STRING_TO_UINT_FUNC(UInt32, wchar_t) +CONVERT_STRING_TO_UINT_FUNC(UInt64, char) +CONVERT_STRING_TO_UINT_FUNC(UInt64, wchar_t) + +Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw() +{ + if (end) + *end = s; + const wchar_t *s2 = s; + if (*s == '-') + s2++; + if (*s2 == 0) + return 0; + const wchar_t *end2; + UInt32 res = ConvertStringToUInt32(s2, &end2); + if (*s == '-') + { + if (res > ((UInt32)1 << (32 - 1))) + return 0; + } + else if ((res & ((UInt32)1 << (32 - 1))) != 0) + return 0; + if (end) + *end = end2; + if (*s == '-') + return -(Int32)res; + return (Int32)res; +} + +UInt32 ConvertOctStringToUInt32(const char *s, const char **end) throw() { - UInt64 result = 0; - for (;;) + if (end) + *end = s; + UInt32 res = 0; + for (;; s++) { char c = *s; - if (c < '0' || c > '9') + if (c < '0' || c > '7') { - if (end != NULL) + if (end) *end = s; - return result; + return res; } - result *= 10; - result += (c - '0'); - s++; + if ((res & (UInt32)7 << (32 - 3)) != 0) + return 0; + res <<= 3; + res |= (unsigned)(c - '0'); } } -UInt64 ConvertOctStringToUInt64(const char *s, const char **end) +UInt64 ConvertOctStringToUInt64(const char *s, const char **end) throw() { - UInt64 result = 0; - for (;;) + if (end) + *end = s; + UInt64 res = 0; + for (;; s++) { char c = *s; if (c < '0' || c > '7') { - if (end != NULL) + if (end) *end = s; - return result; + return res; } - result <<= 3; - result += (c - '0'); - s++; + if ((res & (UInt64)7 << (64 - 3)) != 0) + return 0; + res <<= 3; + res |= (unsigned)(c - '0'); } } -UInt64 ConvertHexStringToUInt64(const char *s, const char **end) +UInt32 ConvertHexStringToUInt32(const char *s, const char **end) throw() { - UInt64 result = 0; - for (;;) + if (end) + *end = s; + UInt32 res = 0; + for (;; s++) { char c = *s; - UInt32 v; + unsigned v; if (c >= '0' && c <= '9') v = (c - '0'); else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A'); else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a'); else { - if (end != NULL) + if (end) *end = s; - return result; + return res; } - result <<= 4; - result |= v; - s++; + if ((res & (UInt32)0xF << (32 - 4)) != 0) + return 0; + res <<= 4; + res |= v; } } - -UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) +UInt64 ConvertHexStringToUInt64(const char *s, const char **end) throw() { - UInt64 result = 0; - for (;;) + if (end) + *end = s; + UInt64 res = 0; + for (;; s++) { - wchar_t c = *s; - if (c < '0' || c > '9') + char c = *s; + unsigned v; + if (c >= '0' && c <= '9') v = (c - '0'); + else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A'); + else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a'); + else { - if (end != NULL) + if (end) *end = s; - return result; + return res; } - result *= 10; - result += (c - '0'); - s++; + if ((res & (UInt64)0xF << (64 - 4)) != 0) + return 0; + res <<= 4; + res |= v; } } - - -Int64 ConvertStringToInt64(const char *s, const char **end) -{ - if (*s == '-') - return -(Int64)ConvertStringToUInt64(s + 1, end); - return ConvertStringToUInt64(s, end); -} diff --git a/src/libs/7zip/win/CPP/Common/StringToInt.h b/src/libs/7zip/win/CPP/Common/StringToInt.h index c0d860eff..5c5d7d7fe 100644 --- a/src/libs/7zip/win/CPP/Common/StringToInt.h +++ b/src/libs/7zip/win/CPP/Common/StringToInt.h @@ -1,18 +1,21 @@ // Common/StringToInt.h -#ifndef __COMMON_STRINGTOINT_H -#define __COMMON_STRINGTOINT_H +#ifndef __COMMON_STRING_TO_INT_H +#define __COMMON_STRING_TO_INT_H -#include -#include "Types.h" +#include "MyTypes.h" -UInt64 ConvertStringToUInt64(const char *s, const char **end); -UInt64 ConvertOctStringToUInt64(const char *s, const char **end); -UInt64 ConvertHexStringToUInt64(const char *s, const char **end); -UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end); +UInt32 ConvertStringToUInt32(const char *s, const char **end) throw(); +UInt64 ConvertStringToUInt64(const char *s, const char **end) throw(); +UInt32 ConvertStringToUInt32(const wchar_t *s, const wchar_t **end) throw(); +UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) throw(); -Int64 ConvertStringToInt64(const char *s, const char **end); +Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw(); -#endif +UInt32 ConvertOctStringToUInt32(const char *s, const char **end) throw(); +UInt64 ConvertOctStringToUInt64(const char *s, const char **end) throw(); +UInt32 ConvertHexStringToUInt32(const char *s, const char **end) throw(); +UInt64 ConvertHexStringToUInt64(const char *s, const char **end) throw(); +#endif diff --git a/src/libs/7zip/win/CPP/Common/Types.h b/src/libs/7zip/win/CPP/Common/Types.h deleted file mode 100644 index 9365b327f..000000000 --- a/src/libs/7zip/win/CPP/Common/Types.h +++ /dev/null @@ -1,11 +0,0 @@ -// Common/Types.h - -#ifndef __COMMON_TYPES_H -#define __COMMON_TYPES_H - -#include "../../C/Types.h" - -typedef int HRes; - -#endif - diff --git a/src/libs/7zip/win/CPP/Common/UTFConvert.cpp b/src/libs/7zip/win/CPP/Common/UTFConvert.cpp index 95362430a..38bac3331 100644 --- a/src/libs/7zip/win/CPP/Common/UTFConvert.cpp +++ b/src/libs/7zip/win/CPP/Common/UTFConvert.cpp @@ -2,18 +2,53 @@ #include "StdAfx.h" +#include "MyTypes.h" #include "UTFConvert.h" -#include "Types.h" static const Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; -static Bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, size_t srcLen) +bool CheckUTF8(const char *src) throw() +{ + for (;;) + { + Byte c; + unsigned numAdds; + c = *src++; + if (c == 0) + return true; + + if (c < 0x80) + continue; + if (c < 0xC0) + return false; + for (numAdds = 1; numAdds < 5; numAdds++) + if (c < kUtf8Limits[numAdds]) + break; + UInt32 value = (c - kUtf8Limits[numAdds - 1]); + + do + { + Byte c2 = *src++; + if (c2 < 0x80 || c2 >= 0xC0) + return false; + value <<= 6; + value |= (c2 - 0x80); + } + while (--numAdds); + + if (value >= 0x110000) + return false; + } +} + + +static Bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, size_t srcLen) throw() { size_t destPos = 0, srcPos = 0; for (;;) { Byte c; - int numAdds; + unsigned numAdds; if (srcPos == srcLen) { *destLen = destPos; @@ -46,8 +81,8 @@ static Bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, size_ value <<= 6; value |= (c2 - 0x80); } - while (--numAdds != 0); - + while (--numAdds); + if (value < 0x10000) { if (dest) @@ -124,11 +159,9 @@ bool ConvertUTF8ToUnicode(const AString &src, UString &dest) { dest.Empty(); size_t destLen = 0; - Utf8_To_Utf16(NULL, &destLen, src, src.Length()); - wchar_t *p = dest.GetBuffer((int)destLen); - Bool res = Utf8_To_Utf16(p, &destLen, src, src.Length()); - p[destLen] = 0; - dest.ReleaseBuffer(); + Utf8_To_Utf16(NULL, &destLen, src, src.Len()); + Bool res = Utf8_To_Utf16(dest.GetBuffer((unsigned)destLen), &destLen, src, src.Len()); + dest.ReleaseBuffer((unsigned)destLen); return res ? true : false; } @@ -136,10 +169,8 @@ bool ConvertUnicodeToUTF8(const UString &src, AString &dest) { dest.Empty(); size_t destLen = 0; - Utf16_To_Utf8(NULL, &destLen, src, src.Length()); - char *p = dest.GetBuffer((int)destLen); - Bool res = Utf16_To_Utf8(p, &destLen, src, src.Length()); - p[destLen] = 0; - dest.ReleaseBuffer(); + Utf16_To_Utf8(NULL, &destLen, src, src.Len()); + Bool res = Utf16_To_Utf8(dest.GetBuffer((unsigned)destLen), &destLen, src, src.Len()); + dest.ReleaseBuffer((unsigned)destLen); return res ? true : false; } diff --git a/src/libs/7zip/win/CPP/Common/UTFConvert.h b/src/libs/7zip/win/CPP/Common/UTFConvert.h index 2a14600d9..16b02fe45 100644 --- a/src/libs/7zip/win/CPP/Common/UTFConvert.h +++ b/src/libs/7zip/win/CPP/Common/UTFConvert.h @@ -1,10 +1,11 @@ // Common/UTFConvert.h -#ifndef __COMMON_UTFCONVERT_H -#define __COMMON_UTFCONVERT_H +#ifndef __COMMON_UTF_CONVERT_H +#define __COMMON_UTF_CONVERT_H #include "MyString.h" +bool CheckUTF8(const char *src) throw(); bool ConvertUTF8ToUnicode(const AString &utfString, UString &resultString); bool ConvertUnicodeToUTF8(const UString &unicodeString, AString &resultString); diff --git a/src/libs/7zip/win/CPP/Common/Wildcard.cpp b/src/libs/7zip/win/CPP/Common/Wildcard.cpp index 476ddebde..e88a1cf1c 100644 --- a/src/libs/7zip/win/CPP/Common/Wildcard.cpp +++ b/src/libs/7zip/win/CPP/Common/Wildcard.cpp @@ -2,8 +2,6 @@ #include "StdAfx.h" -#include "../../C/Types.h" - #include "Wildcard.h" bool g_CaseSensitive = @@ -13,37 +11,43 @@ bool g_CaseSensitive = true; #endif -static const wchar_t kAnyCharsChar = L'*'; -static const wchar_t kAnyCharChar = L'?'; - -#ifdef _WIN32 -static const wchar_t kDirDelimiter1 = L'\\'; -#endif -static const wchar_t kDirDelimiter2 = L'/'; - -static const UString kWildCardCharSet = L"?*"; -static const UString kIllegalWildCardFileNameChars= - L"\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA\xB\xC\xD\xE\xF" - L"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" - L"\"/:<>\\|"; +bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2) +{ + if (g_CaseSensitive) + { + for (;;) + { + wchar_t c2 = *s2++; if (c2 == 0) return true; + wchar_t c1 = *s1++; + if (MyCharUpper(c1) != + MyCharUpper(c2)) + return false; + } + } + for (;;) + { + wchar_t c2 = *s2++; if (c2 == 0) return true; + wchar_t c1 = *s1++; if (c1 != c2) return false; + } +} -static inline bool IsCharDirLimiter(wchar_t c) +int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW { - return ( - #ifdef _WIN32 - c == kDirDelimiter1 || - #endif - c == kDirDelimiter2); + if (g_CaseSensitive) + return wcscmp(s1, s2); + return MyStringCompareNoCase(s1, s2); } -int CompareFileNames(const UString &s1, const UString &s2) +#ifndef USE_UNICODE_FSTRING +int CompareFileNames(const char *s1, const char *s2) { if (g_CaseSensitive) - return s1.Compare(s2); - return s1.CompareNoCase(s2); + return wcscmp(fs2us(s1), fs2us(s2)); + return MyStringCompareNoCase(fs2us(s1), fs2us(s2)); } +#endif // ----------------------------------------- // this function compares name with mask @@ -58,7 +62,7 @@ static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name) wchar_t c = *name; if (m == 0) return (c == 0); - if (m == kAnyCharsChar) + if (m == '*') { if (EnhancedMaskTest(mask + 1, name)) return true; @@ -67,7 +71,7 @@ static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name) } else { - if (m == kAnyCharChar) + if (m == '?') { if (c == 0) return false; @@ -87,61 +91,84 @@ static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name) void SplitPathToParts(const UString &path, UStringVector &pathParts) { pathParts.Clear(); - UString name; - int len = path.Length(); + unsigned len = path.Len(); if (len == 0) return; - for (int i = 0; i < len; i++) - { - wchar_t c = path[i]; - if (IsCharDirLimiter(c)) + UString name; + unsigned prev = 0; + for (unsigned i = 0; i < len; i++) + if (IsCharDirLimiter(path[i])) { + name.SetFrom(path.Ptr(prev), i - prev); pathParts.Add(name); - name.Empty(); + prev = i + 1; } - else - name += c; - } + name.SetFrom(path.Ptr(prev), len - prev); pathParts.Add(name); } -void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name) +void SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name) { - int i; - for (i = path.Length() - 1; i >= 0; i--) - if (IsCharDirLimiter(path[i])) + const wchar_t *start = path; + const wchar_t *p = start + path.Len(); + for (; p != start; p--) + if (IsCharDirLimiter(*(p - 1))) break; - dirPrefix = path.Left(i + 1); - name = path.Mid(i + 1); + dirPrefix.SetFrom(path, (unsigned)(p - start)); + name = p; +} + +void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name) +{ + const wchar_t *start = path; + const wchar_t *p = start + path.Len(); + if (p != start) + { + if (IsCharDirLimiter(*(p - 1))) + p--; + for (; p != start; p--) + if (IsCharDirLimiter(*(p - 1))) + break; + } + dirPrefix.SetFrom(path, (unsigned)(p - start)); + name = p; } UString ExtractDirPrefixFromPath(const UString &path) { - int i; - for (i = path.Length() - 1; i >= 0; i--) - if (IsCharDirLimiter(path[i])) + const wchar_t *start = path; + const wchar_t *p = start + path.Len(); + for (; p != start; p--) + if (IsCharDirLimiter(*(p - 1))) break; - return path.Left(i + 1); + return path.Left((unsigned)(p - start)); } UString ExtractFileNameFromPath(const UString &path) { - int i; - for (i = path.Length() - 1; i >= 0; i--) - if (IsCharDirLimiter(path[i])) + const wchar_t *start = path; + const wchar_t *p = start + path.Len(); + for (; p != start; p--) + if (IsCharDirLimiter(*(p - 1))) break; - return path.Mid(i + 1); + return p; } -bool CompareWildCardWithName(const UString &mask, const UString &name) +bool DoesWildcardMatchName(const UString &mask, const UString &name) { return EnhancedMaskTest(mask, name); } -bool DoesNameContainWildCard(const UString &path) +bool DoesNameContainWildcard(const UString &path) { - return (path.FindOneOf(kWildCardCharSet) >= 0); + for (unsigned i = 0; i < path.Len(); i++) + { + wchar_t c = path[i]; + if (c == '*' || c == '?') + return true; + } + return false; } @@ -151,22 +178,36 @@ bool DoesNameContainWildCard(const UString &path) namespace NWildcard { +#ifdef _WIN32 +bool IsDriveColonName(const wchar_t *s) +{ + wchar_t c = s[0]; + return c != 0 && s[1] == ':' && s[2] == 0 && (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'); +} +#endif + /* + M = MaskParts.Size(); N = TestNameParts.Size(); File Dir -ForFile req M<=N [N-M, N) - - nonreq M=N [0, M) - - -ForDir req M 1) @@ -264,7 +340,7 @@ bool CCensorNode::AreThereIncludeItems() const { if (IncludeItems.Size() > 0) return true; - for (int i = 0; i < SubNodes.Size(); i++) + FOR_VECTOR (i, SubNodes) if (SubNodes[i].AreThereIncludeItems()) return true; return false; @@ -273,13 +349,13 @@ bool CCensorNode::AreThereIncludeItems() const bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const { const CObjectVector &items = include ? IncludeItems : ExcludeItems; - for (int i = 0; i < items.Size(); i++) + FOR_VECTOR (i, items) if (items[i].CheckPath(pathParts, isFile)) return true; return false; } -bool CCensorNode::CheckPath(UStringVector &pathParts, bool isFile, bool &include) const +bool CCensorNode::CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const { if (CheckPathCurrent(false, pathParts, isFile)) { @@ -288,30 +364,45 @@ bool CCensorNode::CheckPath(UStringVector &pathParts, bool isFile, bool &include } include = true; bool finded = CheckPathCurrent(true, pathParts, isFile); - if (pathParts.Size() == 1) + if (pathParts.Size() <= 1) return finded; int index = FindSubNode(pathParts.Front()); if (index >= 0) { UStringVector pathParts2 = pathParts; pathParts2.Delete(0); - if (SubNodes[index].CheckPath(pathParts2, isFile, include)) + if (SubNodes[index].CheckPathVect(pathParts2, isFile, include)) return true; } return finded; } -bool CCensorNode::CheckPath(const UString &path, bool isFile, bool &include) const +bool CCensorNode::CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const { UStringVector pathParts; SplitPathToParts(path, pathParts); - return CheckPath(pathParts, isFile, include); + if (CheckPathVect(pathParts, isFile, include)) + { + if (!include || !isAltStream) + return true; + } + if (isAltStream && !pathParts.IsEmpty()) + { + UString &back = pathParts.Back(); + int pos = back.Find(L':'); + if (pos > 0) + { + back.DeleteFrom(pos); + return CheckPathVect(pathParts, isFile, include); + } + } + return false; } -bool CCensorNode::CheckPath(const UString &path, bool isFile) const +bool CCensorNode::CheckPath(bool isAltStream, const UString &path, bool isFile) const { bool include; - if (CheckPath(path, isFile, include)) + if (CheckPath2(isAltStream, path, isFile, include)) return include; return false; } @@ -335,25 +426,25 @@ bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile } */ -void CCensorNode::AddItem2(bool include, const UString &path, bool recursive) +void CCensorNode::AddItem2(bool include, const UString &path, bool recursive, bool wildcardMatching) { if (path.IsEmpty()) return; bool forFile = true; bool forFolder = true; UString path2 = path; - if (IsCharDirLimiter(path[path.Length() - 1])) + if (IsCharDirLimiter(path.Back())) { - path2.Delete(path.Length() - 1); + path2.DeleteBack(); forFile = false; } - AddItem(include, path2, recursive, forFile, forFolder); + AddItem(include, path2, recursive, forFile, forFolder, wildcardMatching); } void CCensorNode::ExtendExclude(const CCensorNode &fromNodes) { ExcludeItems += fromNodes.ExcludeItems; - for (int i = 0; i < fromNodes.SubNodes.Size(); i++) + FOR_VECTOR (i, fromNodes.SubNodes) { const CCensorNode &node = fromNodes.SubNodes[i]; int subNodeIndex = FindSubNode(node.Name); @@ -365,13 +456,13 @@ void CCensorNode::ExtendExclude(const CCensorNode &fromNodes) int CCensor::FindPrefix(const UString &prefix) const { - for (int i = 0; i < Pairs.Size(); i++) + FOR_VECTOR (i, Pairs) if (CompareFileNames(Pairs[i].Prefix, prefix) == 0) return i; return -1; } -void CCensor::AddItem(bool include, const UString &path, bool recursive) +void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &path, bool recursive, bool wildcardMatching) { UStringVector pathParts; if (path.IsEmpty()) @@ -383,40 +474,82 @@ void CCensor::AddItem(bool include, const UString &path, bool recursive) forFile = false; pathParts.DeleteBack(); } - const UString &front = pathParts.Front(); - bool isAbs = false; - if (front.IsEmpty()) - isAbs = true; - else if (front.Length() == 2 && front[1] == L':') - isAbs = true; - else + + UString prefix; + + if (pathMode != k_AbsPath) { - for (int i = 0; i < pathParts.Size(); i++) + const UString &front = pathParts.Front(); + bool isAbs = false; + + if (front.IsEmpty()) + isAbs = true; + else { - const UString &part = pathParts[i]; - if (part == L".." || part == L".") - { + #ifdef _WIN32 + + if (IsDriveColonName(front)) isAbs = true; - break; + else + + #endif + + FOR_VECTOR (i, pathParts) + { + const UString &part = pathParts[i]; + if (part == L".." || part == L".") + { + isAbs = true; + break; + } + } + } + + unsigned numAbsParts = 0; + if (isAbs) + if (pathParts.Size() > 1) + numAbsParts = pathParts.Size() - 1; + else + numAbsParts = 1; + + #ifdef _WIN32 + + // \\?\ case + if (numAbsParts >= 3) + { + if (pathParts[0].IsEmpty() && + pathParts[1].IsEmpty() && + pathParts[2] == L"?") + { + prefix = + WSTRING_PATH_SEPARATOR + WSTRING_PATH_SEPARATOR L"?" + WSTRING_PATH_SEPARATOR; + numAbsParts -= 3; + pathParts.DeleteFrontal(3); } } - } - int numAbsParts = 0; - if (isAbs) - if (pathParts.Size() > 1) - numAbsParts = pathParts.Size() - 1; - else + + #endif + + if (numAbsParts > 1 && pathMode == k_FullPath) numAbsParts = 1; - UString prefix; - for (int i = 0; i < numAbsParts; i++) - { - const UString &front = pathParts.Front(); - if (DoesNameContainWildCard(front)) - break; - prefix += front; - prefix += WCHAR_PATH_SEPARATOR; - pathParts.Delete(0); + + // We can't ignore wildcard, since we don't allow wildcard in SubNodes[].Name + // if (wildcardMatching) + for (unsigned i = 0; i < numAbsParts; i++) + { + { + const UString &front = pathParts.Front(); + if (DoesNameContainWildcard(front)) + break; + prefix += front; + prefix += WCHAR_PATH_SEPARATOR; + } + pathParts.Delete(0); + } } + int index = FindPrefix(prefix); if (index < 0) index = Pairs.Add(CPair(prefix)); @@ -426,16 +559,17 @@ void CCensor::AddItem(bool include, const UString &path, bool recursive) item.ForDir = true; item.ForFile = forFile; item.Recursive = recursive; + item.WildcardMatching = wildcardMatching; Pairs[index].Head.AddItem(include, item); } -bool CCensor::CheckPath(const UString &path, bool isFile) const +bool CCensor::CheckPath(bool isAltStream, const UString &path, bool isFile) const { bool finded = false; - for (int i = 0; i < Pairs.Size(); i++) + FOR_VECTOR (i, Pairs) { bool include; - if (Pairs[i].Head.CheckPath(path, isFile, include)) + if (Pairs[i].Head.CheckPath2(isAltStream, path, isFile, include)) { if (!include) return false; @@ -447,16 +581,35 @@ bool CCensor::CheckPath(const UString &path, bool isFile) const void CCensor::ExtendExclude() { - int i; + unsigned i; for (i = 0; i < Pairs.Size(); i++) if (Pairs[i].Prefix.IsEmpty()) break; if (i == Pairs.Size()) return; - int index = i; + unsigned index = i; for (i = 0; i < Pairs.Size(); i++) if (index != i) Pairs[i].Head.ExtendExclude(Pairs[index].Head); } +void CCensor::AddPathsToCensor(ECensorPathMode censorPathMode) +{ + FOR_VECTOR(i, CensorPaths) + { + const CCensorPath &cp = CensorPaths[i]; + AddItem(censorPathMode, cp.Include, cp.Path, cp.Recursive, cp.WildcardMatching); + } + CensorPaths.Clear(); +} + +void CCensor::AddPreItem(bool include, const UString &path, bool recursive, bool wildcardMatching) +{ + CCensorPath &cp = CensorPaths.AddNew(); + cp.Path = path; + cp.Include = include; + cp.Recursive = recursive; + cp.WildcardMatching = wildcardMatching; +} + } diff --git a/src/libs/7zip/win/CPP/Common/Wildcard.h b/src/libs/7zip/win/CPP/Common/Wildcard.h index 6d4cbcece..137d71ced 100644 --- a/src/libs/7zip/win/CPP/Common/Wildcard.h +++ b/src/libs/7zip/win/CPP/Common/Wildcard.h @@ -5,51 +5,90 @@ #include "MyString.h" -int CompareFileNames(const UString &s1, const UString &s2); +int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW; +#ifndef USE_UNICODE_FSTRING + int CompareFileNames(const char *s1, const char *s2); +#endif + +bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2); + +inline bool IsCharDirLimiter(wchar_t c) +{ + return c == WCHAR_PATH_SEPARATOR + #ifdef _WIN32 + || c == L'/' + #endif + ; +} void SplitPathToParts(const UString &path, UStringVector &pathParts); -void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name); +void SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name); +void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name); // ignores dir delimiter at the end of (path) + UString ExtractDirPrefixFromPath(const UString &path); UString ExtractFileNameFromPath(const UString &path); -bool DoesNameContainWildCard(const UString &path); -bool CompareWildCardWithName(const UString &mask, const UString &name); + +bool DoesNameContainWildcard(const UString &path); +bool DoesWildcardMatchName(const UString &mask, const UString &name); namespace NWildcard { +#ifdef _WIN32 +// returns true, if name is like "a:", "c:", ... +bool IsDriveColonName(const wchar_t *s); +#endif + + struct CItem { UStringVector PathParts; bool Recursive; bool ForFile; bool ForDir; + bool WildcardMatching; + + #ifdef _WIN32 + bool IsDriveItem() const + { + return PathParts.Size() == 1 && !ForFile && ForDir && IsDriveColonName(PathParts[0]); + } + #endif + + // CItem(): WildcardMatching(true) {} + + bool AreAllAllowed() const; bool CheckPath(const UStringVector &pathParts, bool isFile) const; }; class CCensorNode { CCensorNode *Parent; + bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const; void AddItemSimple(bool include, CItem &item); - bool CheckPath(UStringVector &pathParts, bool isFile, bool &include) const; + bool CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const; public: CCensorNode(): Parent(0) { }; CCensorNode(const UString &name, CCensorNode *parent): Name(name), Parent(parent) { }; - UString Name; + + UString Name; // wildcard is not allowed here CObjectVector SubNodes; CObjectVector IncludeItems; CObjectVector ExcludeItems; + bool AreAllAllowed() const; + int FindSubNode(const UString &path) const; void AddItem(bool include, CItem &item); - void AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir); - void AddItem2(bool include, const UString &path, bool recursive); + void AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir, bool wildcardMatching); + void AddItem2(bool include, const UString &path, bool recursive, bool wildcardMatching); bool NeedCheckSubDirs() const; bool AreThereIncludeItems() const; - bool CheckPath(const UString &path, bool isFile, bool &include) const; - bool CheckPath(const UString &path, bool isFile) const; + bool CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const; + bool CheckPath(bool isAltStream, const UString &path, bool isFile) const; bool CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const; // bool CheckPathToRoot(const UString &path, bool isFile, bool include) const; @@ -60,21 +99,59 @@ struct CPair { UString Prefix; CCensorNode Head; + CPair(const UString &prefix): Prefix(prefix) { }; }; +enum ECensorPathMode +{ + k_RelatPath, // absolute prefix as Prefix, remain path in Tree + k_FullPath, // drive prefix as Prefix, remain path in Tree + k_AbsPath // full path in Tree +}; + +struct CCensorPath +{ + UString Path; + bool Include; + bool Recursive; + bool WildcardMatching; + + CCensorPath(): + Include(true), + Recursive(false), + WildcardMatching(true) + {} +}; + class CCensor { int FindPrefix(const UString &prefix) const; public: CObjectVector Pairs; + + CObjectVector CensorPaths; + bool AllAreRelative() const { return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); } - void AddItem(bool include, const UString &path, bool recursive); - bool CheckPath(const UString &path, bool isFile) const; + + void AddItem(ECensorPathMode pathMode, bool include, const UString &path, bool recursive, bool wildcardMatching); + bool CheckPath(bool isAltStream, const UString &path, bool isFile) const; void ExtendExclude(); + + void AddPathsToCensor(NWildcard::ECensorPathMode censorPathMode); + void AddPreItem(bool include, const UString &path, bool recursive, bool wildcardMatching); + void AddPreItem(const UString &path) + { + AddPreItem(true, path, false, false); + } + void AddPreItem_Wildcard() + { + AddPreItem(true, L"*", false, true); + } }; + } #endif diff --git a/src/libs/7zip/win/CPP/Windows/DLL.cpp b/src/libs/7zip/win/CPP/Windows/DLL.cpp index 5afd72d9d..cf3dd1ceb 100644 --- a/src/libs/7zip/win/CPP/Windows/DLL.cpp +++ b/src/libs/7zip/win/CPP/Windows/DLL.cpp @@ -2,109 +2,109 @@ #include "StdAfx.h" -#ifndef _UNICODE -#include "../Common/StringConvert.h" -#endif - #include "DLL.h" #ifndef _UNICODE extern bool g_IsNT; #endif +extern HINSTANCE g_hInstance; + namespace NWindows { namespace NDLL { -bool CLibrary::Free() +bool CLibrary::Free() throw() { if (_module == 0) return true; - // MessageBox(0, TEXT(""), TEXT("Free"), 0); - // Sleep(5000); if (!::FreeLibrary(_module)) return false; _module = 0; return true; } -bool CLibrary::LoadOperations(HMODULE newModule) +bool CLibrary::LoadEx(CFSTR path, DWORD flags) throw() { - if (newModule == NULL) - return false; if (!Free()) return false; - _module = newModule; - return true; -} - -bool CLibrary::LoadEx(LPCTSTR fileName, DWORD flags) -{ - // MessageBox(0, fileName, TEXT("LoadEx"), 0); - return LoadOperations(::LoadLibraryEx(fileName, NULL, flags)); -} - -bool CLibrary::Load(LPCTSTR fileName) -{ - // MessageBox(0, fileName, TEXT("Load"), 0); - // Sleep(5000); - // OutputDebugString(fileName); - // OutputDebugString(TEXT("\n")); - return LoadOperations(::LoadLibrary(fileName)); + #ifndef _UNICODE + if (!g_IsNT) + { + _module = ::LoadLibraryEx(fs2fas(path), NULL, flags); + } + else + #endif + { + _module = ::LoadLibraryExW(fs2us(path), NULL, flags); + } + return (_module != NULL); } -#ifndef _UNICODE -static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } -CSysString GetSysPath(LPCWSTR sysPath) - { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } - -bool CLibrary::LoadEx(LPCWSTR fileName, DWORD flags) +bool CLibrary::Load(CFSTR path) throw() { - if (g_IsNT) - return LoadOperations(::LoadLibraryExW(fileName, NULL, flags)); - return LoadEx(GetSysPath(fileName), flags); -} -bool CLibrary::Load(LPCWSTR fileName) -{ - if (g_IsNT) - return LoadOperations(::LoadLibraryW(fileName)); - return Load(GetSysPath(fileName)); + if (!Free()) + return false; + #ifndef _UNICODE + if (!g_IsNT) + { + _module = ::LoadLibrary(fs2fas(path)); + } + else + #endif + { + _module = ::LoadLibraryW(fs2us(path)); + } + return (_module != NULL); } -#endif -bool MyGetModuleFileName(HMODULE hModule, CSysString &result) +bool MyGetModuleFileName(FString &path) { - result.Empty(); - TCHAR fullPath[MAX_PATH + 2]; - DWORD size = ::GetModuleFileName(hModule, fullPath, MAX_PATH + 1); - if (size <= MAX_PATH && size != 0) + HMODULE hModule = g_hInstance; + path.Empty(); + #ifndef _UNICODE + if (!g_IsNT) { - result = fullPath; - return true; + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + DWORD size = ::GetModuleFileName(hModule, s, MAX_PATH + 1); + if (size <= MAX_PATH && size != 0) + { + path = fas2fs(s); + return true; + } + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + DWORD size = ::GetModuleFileNameW(hModule, s, MAX_PATH + 1); + if (size <= MAX_PATH && size != 0) + { + path = us2fs(s); + return true; + } } return false; } -#ifndef _UNICODE -bool MyGetModuleFileName(HMODULE hModule, UString &result) +#ifndef _SFX + +FString GetModuleDirPrefix() { - result.Empty(); - if (g_IsNT) + FString s; + if (MyGetModuleFileName(s)) { - wchar_t fullPath[MAX_PATH + 2]; - DWORD size = ::GetModuleFileNameW(hModule, fullPath, MAX_PATH + 1); - if (size <= MAX_PATH && size != 0) + int pos = s.ReverseFind(FCHAR_PATH_SEPARATOR); + if (pos >= 0) { - result = fullPath; - return true; + s.DeleteFrom(pos + 1); + return s; } - return false; } - CSysString resultSys; - if (!MyGetModuleFileName(hModule, resultSys)) - return false; - result = MultiByteToUnicodeString(resultSys, GetCurrentCodePage()); - return true; + return FTEXT(".") FSTRING_PATH_SEPARATOR; } + #endif }} diff --git a/src/libs/7zip/win/CPP/Windows/DLL.h b/src/libs/7zip/win/CPP/Windows/DLL.h index 4a253b326..d8848ce95 100644 --- a/src/libs/7zip/win/CPP/Windows/DLL.h +++ b/src/libs/7zip/win/CPP/Windows/DLL.h @@ -9,15 +9,13 @@ namespace NWindows { namespace NDLL { #ifdef UNDER_CE -#define My_GetProcAddress(module, proceName) GetProcAddressA(module, proceName) +#define My_GetProcAddress(module, procName) ::GetProcAddressA(module, procName) #else -#define My_GetProcAddress(module, proceName) ::GetProcAddress(module, proceName) +#define My_GetProcAddress(module, procName) ::GetProcAddress(module, procName) #endif - + class CLibrary { - bool LoadOperations(HMODULE newModule); -protected: HMODULE _module; public: CLibrary(): _module(NULL) {}; @@ -39,20 +37,15 @@ public: return m; } - bool Free(); - bool LoadEx(LPCTSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); - bool Load(LPCTSTR fileName); - #ifndef _UNICODE - bool LoadEx(LPCWSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); - bool Load(LPCWSTR fileName); - #endif + bool Free() throw(); + bool LoadEx(CFSTR path, DWORD flags = LOAD_LIBRARY_AS_DATAFILE) throw(); + bool Load(CFSTR path) throw(); FARPROC GetProc(LPCSTR procName) const { return My_GetProcAddress(_module, procName); } }; -bool MyGetModuleFileName(HMODULE hModule, CSysString &result); -#ifndef _UNICODE -bool MyGetModuleFileName(HMODULE hModule, UString &result); -#endif +bool MyGetModuleFileName(FString &path); + +FString GetModuleDirPrefix(); }} diff --git a/src/libs/7zip/win/CPP/Windows/Error.cpp b/src/libs/7zip/win/CPP/Windows/Error.cpp deleted file mode 100644 index 7b18c29cc..000000000 --- a/src/libs/7zip/win/CPP/Windows/Error.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// Windows/Error.h - -#include "StdAfx.h" - -#include "Windows/Error.h" -#ifndef _UNICODE -#include "Common/StringConvert.h" -#endif - -#ifndef _UNICODE -extern bool g_IsNT; -#endif - -namespace NWindows { -namespace NError { - -bool MyFormatMessage(DWORD messageID, CSysString &message) -{ - LPVOID msgBuf; - if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL,messageID, 0, (LPTSTR) &msgBuf,0, NULL) == 0) - return false; - message = (LPCTSTR)msgBuf; - ::LocalFree(msgBuf); - return true; -} - -#ifndef _UNICODE -bool MyFormatMessage(DWORD messageID, UString &message) -{ - if (g_IsNT) - { - LPVOID msgBuf; - if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, messageID, 0, (LPWSTR) &msgBuf, 0, NULL) == 0) - return false; - message = (LPCWSTR)msgBuf; - ::LocalFree(msgBuf); - return true; - } - CSysString messageSys; - bool result = MyFormatMessage(messageID, messageSys); - message = GetUnicodeString(messageSys); - return result; -} -#endif - -}} diff --git a/src/libs/7zip/win/CPP/Windows/Error.h b/src/libs/7zip/win/CPP/Windows/Error.h deleted file mode 100644 index 05b5cd0ea..000000000 --- a/src/libs/7zip/win/CPP/Windows/Error.h +++ /dev/null @@ -1,33 +0,0 @@ -// Windows/Error.h - -#ifndef __WINDOWS_ERROR_H -#define __WINDOWS_ERROR_H - -#include "Common/MyString.h" - -namespace NWindows { -namespace NError { - -bool MyFormatMessage(DWORD messageID, CSysString &message); -inline CSysString MyFormatMessage(DWORD messageID) -{ - CSysString message; - MyFormatMessage(messageID, message); - return message; -} -#ifdef _UNICODE -inline UString MyFormatMessageW(DWORD messageID) - { return MyFormatMessage(messageID); } -#else -bool MyFormatMessage(DWORD messageID, UString &message); -inline UString MyFormatMessageW(DWORD messageID) -{ - UString message; - MyFormatMessage(messageID, message); - return message; -} -#endif - -}} - -#endif diff --git a/src/libs/7zip/win/CPP/Windows/FileDir.cpp b/src/libs/7zip/win/CPP/Windows/FileDir.cpp index 857946031..097f81efb 100644 --- a/src/libs/7zip/win/CPP/Windows/FileDir.cpp +++ b/src/libs/7zip/win/CPP/Windows/FileDir.cpp @@ -14,81 +14,62 @@ extern bool g_IsNT; #endif +using namespace NWindows; +using namespace NFile; +using namespace NName; + namespace NWindows { namespace NFile { - -#if defined(WIN_LONG_PATH) && defined(_UNICODE) -#define WIN_LONG_PATH2 -#endif - -// SetCurrentDirectory doesn't support \\?\ prefix - -#ifdef WIN_LONG_PATH -bool GetLongPathBase(LPCWSTR fileName, UString &res); -bool GetLongPath(LPCWSTR fileName, UString &res); -#endif - -namespace NDirectory { - -#ifndef _UNICODE -static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } -static UString GetUnicodePath(const CSysString &sysPath) - { return MultiByteToUnicodeString(sysPath, GetCurrentCodePage()); } -static CSysString GetSysPath(LPCWSTR sysPath) - { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } -#endif +namespace NDir { #ifndef UNDER_CE -bool MyGetWindowsDirectory(CSysString &path) -{ - UINT needLength = ::GetWindowsDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); - path.ReleaseBuffer(); - return (needLength > 0 && needLength <= MAX_PATH); -} - -bool MyGetSystemDirectory(CSysString &path) +bool GetWindowsDir(FString &path) { - UINT needLength = ::GetSystemDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); - path.ReleaseBuffer(); + UINT needLength; + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetWindowsDirectory(s, MAX_PATH + 1); + path = fas2fs(s); + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetWindowsDirectoryW(s, MAX_PATH + 1); + path = us2fs(s); + } return (needLength > 0 && needLength <= MAX_PATH); } -#endif - -#ifndef _UNICODE -bool MyGetWindowsDirectory(UString &path) +bool GetSystemDir(FString &path) { - if (g_IsNT) + UINT needLength; + #ifndef _UNICODE + if (!g_IsNT) { - UINT needLength = ::GetWindowsDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); - path.ReleaseBuffer(); - return (needLength > 0 && needLength <= MAX_PATH); + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetSystemDirectory(s, MAX_PATH + 1); + path = fas2fs(s); } - CSysString sysPath; - if (!MyGetWindowsDirectory(sysPath)) - return false; - path = GetUnicodePath(sysPath); - return true; -} - -bool MyGetSystemDirectory(UString &path) -{ - if (g_IsNT) + else + #endif { - UINT needLength = ::GetSystemDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); - path.ReleaseBuffer(); - return (needLength > 0 && needLength <= MAX_PATH); + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetSystemDirectoryW(s, MAX_PATH + 1); + path = us2fs(s); } - CSysString sysPath; - if (!MyGetSystemDirectory(sysPath)) - return false; - path = GetUnicodePath(sysPath); - return true; + return (needLength > 0 && needLength <= MAX_PATH); } #endif -bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) +bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { #ifndef _UNICODE if (!g_IsNT) @@ -97,17 +78,18 @@ bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, return false; } #endif - HANDLE hDir = ::CreateFileW(fileName, GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + + HANDLE hDir = INVALID_HANDLE_VALUE; + IF_USE_MAIN_PATH + hDir = ::CreateFileW(fs2us(path), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); #ifdef WIN_LONG_PATH - if (hDir == INVALID_HANDLE_VALUE) + if (hDir == INVALID_HANDLE_VALUE && USE_SUPER_PATH) { UString longPath; - if (GetLongPath(fileName, longPath)) - hDir = ::CreateFileW(longPath, GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) + hDir = ::CreateFileW(longPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } #endif @@ -120,790 +102,482 @@ bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, return res; } -bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes) -{ - if (::SetFileAttributes(fileName, fileAttributes)) - return true; - #ifdef WIN_LONG_PATH2 - UString longPath; - if (GetLongPath(fileName, longPath)) - return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); - #endif - return false; -} - -bool MyRemoveDirectory(LPCTSTR pathName) -{ - if (::RemoveDirectory(pathName)) - return true; - #ifdef WIN_LONG_PATH2 - UString longPath; - if (GetLongPath(pathName, longPath)) - return BOOLToBool(::RemoveDirectoryW(longPath)); - #endif - return false; -} - -#ifdef WIN_LONG_PATH -bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2) -{ - if (!GetLongPathBase(s1, d1) || !GetLongPathBase(s2, d2)) - return false; - if (d1.IsEmpty() && d2.IsEmpty()) return false; - if (d1.IsEmpty()) d1 = s1; - if (d2.IsEmpty()) d2 = s2; - return true; -} -#endif - -bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName) -{ - if (::MoveFile(existFileName, newFileName)) - return true; - #ifdef WIN_LONG_PATH2 - UString d1, d2; - if (GetLongPaths(existFileName, newFileName, d1, d2)) - return BOOLToBool(::MoveFileW(d1, d2)); - #endif - return false; -} - -#ifndef _UNICODE -bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes) +bool SetFileAttrib(CFSTR path, DWORD attrib) { + #ifndef _UNICODE if (!g_IsNT) - return MySetFileAttributes(GetSysPath(fileName), fileAttributes); - if (::SetFileAttributesW(fileName, fileAttributes)) - return true; - #ifdef WIN_LONG_PATH - UString longPath; - if (GetLongPath(fileName, longPath)) - return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); + { + if (::SetFileAttributes(fs2fas(path), attrib)) + return true; + } + else #endif + { + IF_USE_MAIN_PATH + if (::SetFileAttributesW(fs2us(path), attrib)) + return true; + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH) + { + UString longPath; + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) + return BOOLToBool(::SetFileAttributesW(longPath, attrib)); + } + #endif + } return false; } - -bool MyRemoveDirectory(LPCWSTR pathName) +bool RemoveDir(CFSTR path) { + #ifndef _UNICODE if (!g_IsNT) - return MyRemoveDirectory(GetSysPath(pathName)); - if (::RemoveDirectoryW(pathName)) - return true; - #ifdef WIN_LONG_PATH - UString longPath; - if (GetLongPath(pathName, longPath)) - return BOOLToBool(::RemoveDirectoryW(longPath)); + { + if (::RemoveDirectory(fs2fas(path))) + return true; + } + else #endif + { + IF_USE_MAIN_PATH + if (::RemoveDirectoryW(fs2us(path))) + return true; + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH) + { + UString longPath; + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) + return BOOLToBool(::RemoveDirectoryW(longPath)); + } + #endif + } return false; } -bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName) +bool MyMoveFile(CFSTR oldFile, CFSTR newFile) { + #ifndef _UNICODE if (!g_IsNT) - return MyMoveFile(GetSysPath(existFileName), GetSysPath(newFileName)); - if (::MoveFileW(existFileName, newFileName)) - return true; - #ifdef WIN_LONG_PATH - UString d1, d2; - if (GetLongPaths(existFileName, newFileName, d1, d2)) - return BOOLToBool(::MoveFileW(d1, d2)); - #endif - return false; -} -#endif - -bool MyCreateDirectory(LPCTSTR pathName) -{ - if (::CreateDirectory(pathName, NULL)) - return true; - #ifdef WIN_LONG_PATH2 - if (::GetLastError() != ERROR_ALREADY_EXISTS) { - UString longPath; - if (GetLongPath(pathName, longPath)) - return BOOLToBool(::CreateDirectoryW(longPath, NULL)); + if (::MoveFile(fs2fas(oldFile), fs2fas(newFile))) + return true; } + else #endif + { + IF_USE_MAIN_PATH_2(oldFile, newFile) + if (::MoveFileW(fs2us(oldFile), fs2us(newFile))) + return true; + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH_2) + { + UString d1, d2; + if (GetSuperPaths(oldFile, newFile, d1, d2, USE_MAIN_PATH_2)) + return BOOLToBool(::MoveFileW(d1, d2)); + } + #endif + } return false; } -#ifndef _UNICODE -bool MyCreateDirectory(LPCWSTR pathName) +#ifndef UNDER_CE + +EXTERN_C_BEGIN +typedef BOOL (WINAPI *Func_CreateHardLinkW)( + LPCWSTR lpFileName, + LPCWSTR lpExistingFileName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes + ); +EXTERN_C_END + +bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName) { + #ifndef _UNICODE if (!g_IsNT) - return MyCreateDirectory(GetSysPath(pathName)); - if (::CreateDirectoryW(pathName, NULL)) - return true; - #ifdef WIN_LONG_PATH - if (::GetLastError() != ERROR_ALREADY_EXISTS) { - UString longPath; - if (GetLongPath(pathName, longPath)) - return BOOLToBool(::CreateDirectoryW(longPath, NULL)); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return false; + /* + if (::CreateHardLink(fs2fas(newFileName), fs2fas(existFileName), NULL)) + return true; + */ } + else #endif - return false; -} -#endif - -/* -bool CreateComplexDirectory(LPCTSTR pathName) -{ - NName::CParsedPath path; - path.ParsePath(pathName); - CSysString fullPath = path.Prefix; - DWORD errorCode = ERROR_SUCCESS; - for (int i = 0; i < path.PathParts.Size(); i++) { - const CSysString &string = path.PathParts[i]; - if (string.IsEmpty()) - { - if (i != path.PathParts.Size() - 1) - return false; - return true; - } - fullPath += path.PathParts[i]; - if (!MyCreateDirectory(fullPath)) + Func_CreateHardLinkW my_CreateHardLinkW = (Func_CreateHardLinkW) + ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW"); + if (!my_CreateHardLinkW) + return false; + IF_USE_MAIN_PATH_2(newFileName, existFileName) + if (my_CreateHardLinkW(fs2us(newFileName), fs2us(existFileName), NULL)) + return true; + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH_2) { - DWORD errorCode = GetLastError(); - if (errorCode != ERROR_ALREADY_EXISTS) - return false; + UString d1, d2; + if (GetSuperPaths(newFileName, existFileName, d1, d2, USE_MAIN_PATH_2)) + return BOOLToBool(my_CreateHardLinkW(d1, d2, NULL)); } - fullPath += NName::kDirDelimiter; + #endif } - return true; + return false; } -*/ -bool CreateComplexDirectory(LPCTSTR _aPathName) +#endif + +bool CreateDir(CFSTR path) { - CSysString pathName = _aPathName; - int pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); - if (pos > 0 && pos == pathName.Length() - 1) + #ifndef _UNICODE + if (!g_IsNT) { - if (pathName.Length() == 3 && pathName[1] == ':') - return true; // Disk folder; - pathName.Delete(pos); + if (::CreateDirectory(fs2fas(path), NULL)) + return true; } - CSysString pathName2 = pathName; - pos = pathName.Length(); - for (;;) + else + #endif { - if (MyCreateDirectory(pathName)) - break; - if (::GetLastError() == ERROR_ALREADY_EXISTS) - { - NFind::CFileInfo fileInfo; - if (!fileInfo.Find(pathName)) // For network folders + IF_USE_MAIN_PATH + if (::CreateDirectoryW(fs2us(path), NULL)) return true; - if (!fileInfo.IsDir()) - return false; - break; + #ifdef WIN_LONG_PATH + if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH) + { + UString longPath; + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) + return BOOLToBool(::CreateDirectoryW(longPath, NULL)); } - pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); - if (pos < 0 || pos == 0) - return false; - if (pathName[pos - 1] == ':') - return false; - pathName = pathName.Left(pos); - } - pathName = pathName2; - while (pos < pathName.Length()) - { - pos = pathName.Find(TEXT(CHAR_PATH_SEPARATOR), pos + 1); - if (pos < 0) - pos = pathName.Length(); - if (!MyCreateDirectory(pathName.Left(pos))) - return false; + #endif } - return true; + return false; } -#ifndef _UNICODE - -bool CreateComplexDirectory(LPCWSTR _aPathName) +bool CreateComplexDir(CFSTR _aPathName) { - UString pathName = _aPathName; - int pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); - if (pos > 0 && pos == pathName.Length() - 1) + FString pathName = _aPathName; + int pos = pathName.ReverseFind(FCHAR_PATH_SEPARATOR); + if (pos > 0 && (unsigned)pos == pathName.Len() - 1) { - if (pathName.Length() == 3 && pathName[1] == L':') + if (pathName.Len() == 3 && pathName[1] == L':') return true; // Disk folder; pathName.Delete(pos); } - UString pathName2 = pathName; - pos = pathName.Length(); + const FString pathName2 = pathName; + pos = pathName.Len(); + for (;;) { - if (MyCreateDirectory(pathName)) + if (CreateDir(pathName)) break; if (::GetLastError() == ERROR_ALREADY_EXISTS) { - NFind::CFileInfoW fileInfo; + NFind::CFileInfo fileInfo; if (!fileInfo.Find(pathName)) // For network folders return true; if (!fileInfo.IsDir()) return false; break; } - pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); + pos = pathName.ReverseFind(FCHAR_PATH_SEPARATOR); if (pos < 0 || pos == 0) return false; if (pathName[pos - 1] == L':') return false; - pathName = pathName.Left(pos); + pathName.DeleteFrom(pos); } - pathName = pathName2; - while (pos < pathName.Length()) + + while (pos < (int)pathName2.Len()) { - pos = pathName.Find(WCHAR_PATH_SEPARATOR, pos + 1); + pos = pathName2.Find(FCHAR_PATH_SEPARATOR, pos + 1); if (pos < 0) - pos = pathName.Length(); - if (!MyCreateDirectory(pathName.Left(pos))) + pos = pathName2.Len(); + pathName.SetFrom(pathName2, pos); + if (!CreateDir(pathName)) return false; } + return true; } -#endif - -bool DeleteFileAlways(LPCTSTR name) +bool DeleteFileAlways(CFSTR path) { - if (!MySetFileAttributes(name, 0)) + if (!SetFileAttrib(path, 0)) return false; - if (::DeleteFile(name)) - return true; - #ifdef WIN_LONG_PATH2 - UString longPath; - if (GetLongPath(name, longPath)) - return BOOLToBool(::DeleteFileW(longPath)); - #endif - return false; -} - -#ifndef _UNICODE -bool DeleteFileAlways(LPCWSTR name) -{ + #ifndef _UNICODE if (!g_IsNT) - return DeleteFileAlways(GetSysPath(name)); - if (!MySetFileAttributes(name, 0)) - return false; - if (::DeleteFileW(name)) - return true; - #ifdef WIN_LONG_PATH - UString longPath; - if (GetLongPath(name, longPath)) - return BOOLToBool(::DeleteFileW(longPath)); + { + if (::DeleteFile(fs2fas(path))) + return true; + } + else #endif + { + IF_USE_MAIN_PATH + if (::DeleteFileW(fs2us(path))) + return true; + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH) + { + UString longPath; + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) + return BOOLToBool(::DeleteFileW(longPath)); + } + #endif + } return false; } -#endif - -static bool RemoveDirectorySubItems2(const CSysString pathPrefix, const NFind::CFileInfo &fileInfo) -{ - if (fileInfo.IsDir()) - return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); - return DeleteFileAlways(pathPrefix + fileInfo.Name); -} -bool RemoveDirectoryWithSubItems(const CSysString &path) +bool RemoveDirWithSubItems(const FString &path) { - NFind::CFileInfo fileInfo; - CSysString pathPrefix = path + NName::kDirDelimiter; + bool needRemoveSubItems = true; { - NFind::CEnumerator enumerator(pathPrefix + TCHAR(NName::kAnyStringWildcard)); - while (enumerator.Next(fileInfo)) - if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) - return false; + NFind::CFileInfo fi; + if (!fi.Find(path)) + return false; + if (!fi.IsDir()) + { + ::SetLastError(ERROR_DIRECTORY); + return false; + } + if (fi.HasReparsePoint()) + needRemoveSubItems = false; } - if (!MySetFileAttributes(path, 0)) - return false; - return MyRemoveDirectory(path); -} -#ifndef _UNICODE -static bool RemoveDirectorySubItems2(const UString pathPrefix, const NFind::CFileInfoW &fileInfo) -{ - if (fileInfo.IsDir()) - return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); - return DeleteFileAlways(pathPrefix + fileInfo.Name); -} -bool RemoveDirectoryWithSubItems(const UString &path) -{ - NFind::CFileInfoW fileInfo; - UString pathPrefix = path + UString(NName::kDirDelimiter); + if (needRemoveSubItems) { - NFind::CEnumeratorW enumerator(pathPrefix + UString(NName::kAnyStringWildcard)); - while (enumerator.Next(fileInfo)) - if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) + FString s = path; + s += FCHAR_PATH_SEPARATOR; + unsigned prefixSize = s.Len(); + s += FCHAR_ANY_MASK; + NFind::CEnumerator enumerator(s); + NFind::CFileInfo fi; + while (enumerator.Next(fi)) + { + s.DeleteFrom(prefixSize); + s += fi.Name; + if (fi.IsDir()) + { + if (!RemoveDirWithSubItems(s)) + return false; + } + else if (!DeleteFileAlways(s)) return false; + } } - if (!MySetFileAttributes(path, 0)) - return false; - return MyRemoveDirectory(path); -} -#endif -bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName) -{ - int index; - if (!MyGetFullPathName(fileName, resultName, index)) + if (!SetFileAttrib(path, 0)) return false; - resultName = resultName.Left(index); - return true; -} - -bool GetOnlyName(LPCTSTR fileName, CSysString &resultName) -{ - int index; - if (!MyGetFullPathName(fileName, resultName, index)) - return false; - resultName = resultName.Mid(index); - return true; + return RemoveDir(path); } #ifdef UNDER_CE -bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath) -{ - resultPath = fileName; - return true; -} -bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex) +bool MyGetFullPathName(CFSTR path, FString &resFullPath) { - resultPath = fileName; - // change it - fileNamePartStartIndex = resultPath.ReverseFind(WCHAR_PATH_SEPARATOR); - fileNamePartStartIndex++; + resFullPath = path; return true; } #else -bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath) +bool MyGetFullPathName(CFSTR path, FString &resFullPath) { - DWORD needLength = ::GetShortPathName(longPath, shortPath.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); - shortPath.ReleaseBuffer(); - return (needLength > 0 && needLength < MAX_PATH); + return GetFullPath(path, resFullPath); } -#ifdef WIN_LONG_PATH - -static UString GetLastPart(LPCWSTR path) +bool SetCurrentDir(CFSTR path) { - int i = (int)wcslen(path); - for (; i > 0; i--) - { - WCHAR c = path[i - 1]; - if (c == WCHAR_PATH_SEPARATOR || c == '/') - break; - } - return path + i; -} - -static void AddTrailingDots(LPCWSTR oldPath, UString &newPath) -{ - int len = (int)wcslen(oldPath); - int i; - for (i = len; i > 0 && oldPath[i - 1] == '.'; i--); - if (i == 0 || i == len) - return; - UString oldName = GetLastPart(oldPath); - UString newName = GetLastPart(newPath); - int nonDotsLen = oldName.Length() - (len - i); - if (nonDotsLen == 0 || newName.CompareNoCase(oldName.Left(nonDotsLen)) != 0) - return; - for (; i != len; i++) - newPath += '.'; -} - -#endif - -bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex) -{ - resultPath.Empty(); - LPTSTR fileNamePointer = 0; - LPTSTR buffer = resultPath.GetBuffer(MAX_PATH); - DWORD needLength = ::GetFullPathName(fileName, MAX_PATH + 1, buffer, &fileNamePointer); - resultPath.ReleaseBuffer(); - if (needLength == 0) - return false; - if (needLength >= MAX_PATH) + // SetCurrentDirectory doesn't support \\?\ prefix + #ifndef _UNICODE + if (!g_IsNT) { - #ifdef WIN_LONG_PATH2 - needLength++; - buffer = resultPath.GetBuffer(needLength + 1); - DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); - resultPath.ReleaseBuffer(); - if (needLength2 == 0 || needLength2 > needLength) - #endif - return false; + return BOOLToBool(::SetCurrentDirectory(fs2fas(path))); } - if (fileNamePointer == 0) - fileNamePartStartIndex = lstrlen(fileName); else - fileNamePartStartIndex = (int)(fileNamePointer - buffer); - #ifdef _UNICODE - #ifdef WIN_LONG_PATH - AddTrailingDots(fileName, resultPath); #endif - #endif - return true; + { + return BOOLToBool(::SetCurrentDirectoryW(fs2us(path))); + } } -#ifndef _UNICODE -bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex) +bool GetCurrentDir(FString &path) { - resultPath.Empty(); - if (g_IsNT) + path.Empty(); + DWORD needLength; + #ifndef _UNICODE + if (!g_IsNT) { - LPWSTR fileNamePointer = 0; - LPWSTR buffer = resultPath.GetBuffer(MAX_PATH); - DWORD needLength = ::GetFullPathNameW(fileName, MAX_PATH + 1, buffer, &fileNamePointer); - resultPath.ReleaseBuffer(); - if (needLength == 0) - return false; - if (needLength >= MAX_PATH) - { - #ifdef WIN_LONG_PATH - needLength++; - buffer = resultPath.GetBuffer(needLength + 1); - DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); - resultPath.ReleaseBuffer(); - if (needLength2 == 0 || needLength2 > needLength) - #endif - return false; - } - if (fileNamePointer == 0) - fileNamePartStartIndex = MyStringLen(fileName); - else - fileNamePartStartIndex = (int)(fileNamePointer - buffer); - #ifdef WIN_LONG_PATH - AddTrailingDots(fileName, resultPath); - #endif + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetCurrentDirectory(MAX_PATH + 1, s); + path = fas2fs(s); } else + #endif { - CSysString sysPath; - if (!MyGetFullPathName(GetSysPath(fileName), sysPath, fileNamePartStartIndex)) - return false; - UString resultPath1 = GetUnicodePath(sysPath.Left(fileNamePartStartIndex)); - UString resultPath2 = GetUnicodePath(sysPath.Mid(fileNamePartStartIndex)); - fileNamePartStartIndex = resultPath1.Length(); - resultPath = resultPath1 + resultPath2; + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, s); + path = us2fs(s); } - return true; -} -#endif - - -bool MyGetFullPathName(LPCTSTR fileName, CSysString &path) -{ - int index; - return MyGetFullPathName(fileName, path, index); + return (needLength > 0 && needLength <= MAX_PATH); } -#ifndef _UNICODE -bool MyGetFullPathName(LPCWSTR fileName, UString &path) -{ - int index; - return MyGetFullPathName(fileName, path, index); -} #endif -#ifndef _UNICODE -bool GetOnlyName(LPCWSTR fileName, UString &resultName) +bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName) { - int index; - if (!MyGetFullPathName(fileName, resultName, index)) - return false; - resultName = resultName.Mid(index); - return true; -} -#endif - -#ifndef _UNICODE -bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName) -{ - int index; - if (!MyGetFullPathName(fileName, resultName, index)) - return false; - resultName = resultName.Left(index); - return true; + bool res = MyGetFullPathName(path, resDirPrefix); + if (!res) + resDirPrefix = path; + int pos = resDirPrefix.ReverseFind(FCHAR_PATH_SEPARATOR); + resFileName = resDirPrefix.Ptr(pos + 1); + resDirPrefix.DeleteFrom(pos + 1); + return res; } -#endif -bool MyGetCurrentDirectory(CSysString &path) +bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix) { - DWORD needLength = ::GetCurrentDirectory(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); - path.ReleaseBuffer(); - return (needLength > 0 && needLength <= MAX_PATH); + FString resFileName; + return GetFullPathAndSplit(path, resDirPrefix, resFileName); } -#ifndef _UNICODE -bool MySetCurrentDirectory(LPCWSTR path) +bool MyGetTempPath(FString &path) { - if (g_IsNT) - return BOOLToBool(::SetCurrentDirectoryW(path)); - return MySetCurrentDirectory(GetSysPath(path)); -} -bool MyGetCurrentDirectory(UString &path) -{ - if (g_IsNT) + path.Empty(); + DWORD needLength; + #ifndef _UNICODE + if (!g_IsNT) { - DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); - path.ReleaseBuffer(); - return (needLength > 0 && needLength <= MAX_PATH); + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetTempPath(MAX_PATH + 1, s); + path = fas2fs(s); } - CSysString sysPath; - if (!MyGetCurrentDirectory(sysPath)) - return false; - path = GetUnicodePath(sysPath); - return true; -} -#endif - -bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, - CSysString &resultPath, UINT32 &filePart) -{ - LPTSTR filePartPointer; - DWORD value = ::SearchPath(path, fileName, extension, - MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); - filePart = (UINT32)(filePartPointer - (LPCTSTR)resultPath); - resultPath.ReleaseBuffer(); - return (value > 0 && value <= MAX_PATH); -} -#endif - -#ifndef _UNICODE -bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, - UString &resultPath, UINT32 &filePart) -{ - if (g_IsNT) + else + #endif { - LPWSTR filePartPointer = 0; - DWORD value = ::SearchPathW(path, fileName, extension, - MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); - filePart = (UINT32)(filePartPointer - (LPCWSTR)resultPath); - resultPath.ReleaseBuffer(); - return (value > 0 && value <= MAX_PATH); + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetTempPathW(MAX_PATH + 1, s);; + path = us2fs(s); } - - CSysString sysPath; - if (!MySearchPath( - path != 0 ? (LPCTSTR)GetSysPath(path): 0, - fileName != 0 ? (LPCTSTR)GetSysPath(fileName): 0, - extension != 0 ? (LPCTSTR)GetSysPath(extension): 0, - sysPath, filePart)) - return false; - UString resultPath1 = GetUnicodePath(sysPath.Left(filePart)); - UString resultPath2 = GetUnicodePath(sysPath.Mid(filePart)); - filePart = resultPath1.Length(); - resultPath = resultPath1 + resultPath2; - return true; -} -#endif - -bool MyGetTempPath(CSysString &path) -{ - DWORD needLength = ::GetTempPath(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); - path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } -#ifndef _UNICODE -bool MyGetTempPath(UString &path) -{ - path.Empty(); - if (g_IsNT) - { - DWORD needLength = ::GetTempPathW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); - path.ReleaseBuffer(); - return (needLength > 0 && needLength <= MAX_PATH); - } - CSysString sysPath; - if (!MyGetTempPath(sysPath)) - return false; - path = GetUnicodePath(sysPath); - return true; -} -#endif - -UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &path) -{ - UINT number = ::GetTempFileName(dirPath, prefix, 0, path.GetBuffer(MAX_PATH + 1)); - path.ReleaseBuffer(); - return number; -} - -#ifndef _UNICODE -UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &path) +static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COutFile *outFile) { - if (g_IsNT) + UInt32 d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId(); + for (unsigned i = 0; i < 100; i++) { - UINT number = ::GetTempFileNameW(dirPath, prefix, 0, path.GetBuffer(MAX_PATH)); - path.ReleaseBuffer(); - return number; + path = prefix; + if (addRandom) + { + FChar s[16]; + UInt32 value = d; + unsigned k; + for (k = 0; k < 8; k++) + { + unsigned t = value & 0xF; + value >>= 4; + s[k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } + s[k] = '\0'; + if (outFile) + path += FChar('.'); + path += s; + UInt32 step = GetTickCount() + 2; + if (step == 0) + step = 1; + d += step; + } + addRandom = true; + if (outFile) + path += FTEXT(".tmp"); + if (NFind::DoesFileOrDirExist(path)) + { + SetLastError(ERROR_ALREADY_EXISTS); + continue; + } + if (outFile) + { + if (outFile->Create(path, false)) + return true; + } + else + { + if (CreateDir(path)) + return true; + } + DWORD error = GetLastError(); + if (error != ERROR_FILE_EXISTS && + error != ERROR_ALREADY_EXISTS) + break; } - CSysString sysPath; - UINT number = MyGetTempFileName( - dirPath ? (LPCTSTR)GetSysPath(dirPath): 0, - prefix ? (LPCTSTR)GetSysPath(prefix): 0, - sysPath); - path = GetUnicodePath(sysPath); - return number; + path.Empty(); + return false; } -#endif -UINT CTempFile::Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath) +bool CTempFile::Create(CFSTR prefix, NIO::COutFile *outFile) { - Remove(); - UINT number = MyGetTempFileName(dirPath, prefix, resultPath); - if (number != 0) - { - _fileName = resultPath; - _mustBeDeleted = true; - } - return number; + if (!Remove()) + return false; + if (!CreateTempFile(prefix, false, _path, outFile)) + return false; + _mustBeDeleted = true; + return true; } -bool CTempFile::Create(LPCTSTR prefix, CSysString &resultPath) +bool CTempFile::CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile) { - CSysString tempPath; + if (!Remove()) + return false; + FString tempPath; if (!MyGetTempPath(tempPath)) return false; - if (Create(tempPath, prefix, resultPath) != 0) - return true; - #ifdef UNDER_CE - return false; - #else - if (!MyGetWindowsDirectory(tempPath)) + if (!CreateTempFile(tempPath + namePrefix, true, _path, outFile)) return false; - return (Create(tempPath, prefix, resultPath) != 0); - #endif + _mustBeDeleted = true; + return true; } bool CTempFile::Remove() { if (!_mustBeDeleted) return true; - _mustBeDeleted = !DeleteFileAlways(_fileName); + _mustBeDeleted = !DeleteFileAlways(_path); return !_mustBeDeleted; } -#ifndef _UNICODE - -UINT CTempFileW::Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath) +bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore) { - Remove(); - UINT number = MyGetTempFileName(dirPath, prefix, resultPath); - if (number != 0) - { - _fileName = resultPath; - _mustBeDeleted = true; - } - return number; + if (deleteDestBefore) + if (NFind::DoesFileExist(name)) + if (!DeleteFileAlways(name)) + return false; + DisableDeleting(); + return MyMoveFile(_path, name); } -bool CTempFileW::Create(LPCWSTR prefix, UString &resultPath) +bool CTempDir::Create(CFSTR prefix) { - UString tempPath; + if (!Remove()) + return false; + FString tempPath; if (!MyGetTempPath(tempPath)) return false; - if (Create(tempPath, prefix, resultPath) != 0) - return true; - if (!MyGetWindowsDirectory(tempPath)) + if (!CreateTempFile(tempPath + prefix, true, _path, NULL)) return false; - return (Create(tempPath, prefix, resultPath) != 0); + _mustBeDeleted = true; + return true; } -bool CTempFileW::Remove() +bool CTempDir::Remove() { if (!_mustBeDeleted) return true; - _mustBeDeleted = !DeleteFileAlways(_fileName); + _mustBeDeleted = !RemoveDirWithSubItems(_path); return !_mustBeDeleted; } -#endif - -bool CreateTempDirectory(LPCTSTR prefix, CSysString &dirName) -{ - /* - CSysString prefix = tempPath + prefixChars; - CRandom random; - random.Init(); - */ - for (;;) - { - { - CTempFile tempFile; - if (!tempFile.Create(prefix, dirName)) - return false; - if (!tempFile.Remove()) - return false; - } - /* - UINT32 randomNumber = random.Generate(); - TCHAR randomNumberString[32]; - _stprintf(randomNumberString, _T("%04X"), randomNumber); - dirName = prefix + randomNumberString; - */ - if (NFind::DoesFileOrDirExist(dirName)) - continue; - if (MyCreateDirectory(dirName)) - return true; - if (::GetLastError() != ERROR_ALREADY_EXISTS) - return false; - } -} - -bool CTempDirectory::Create(LPCTSTR prefix) -{ - Remove(); - return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); -} - -#ifndef _UNICODE - -bool CreateTempDirectory(LPCWSTR prefix, UString &dirName) -{ - /* - CSysString prefix = tempPath + prefixChars; - CRandom random; - random.Init(); - */ - for (;;) - { - { - CTempFileW tempFile; - if (!tempFile.Create(prefix, dirName)) - return false; - if (!tempFile.Remove()) - return false; - } - /* - UINT32 randomNumber = random.Generate(); - TCHAR randomNumberString[32]; - _stprintf(randomNumberString, _T("%04X"), randomNumber); - dirName = prefix + randomNumberString; - */ - if (NFind::DoesFileOrDirExist(dirName)) - continue; - if (MyCreateDirectory(dirName)) - return true; - if (::GetLastError() != ERROR_ALREADY_EXISTS) - return false; - } -} - -bool CTempDirectoryW::Create(LPCWSTR prefix) -{ - Remove(); - return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); -} - -#endif - }}} diff --git a/src/libs/7zip/win/CPP/Windows/FileDir.h b/src/libs/7zip/win/CPP/Windows/FileDir.h index 04542d872..02d3e5a57 100644 --- a/src/libs/7zip/win/CPP/Windows/FileDir.h +++ b/src/libs/7zip/win/CPP/Windows/FileDir.h @@ -1,174 +1,94 @@ // Windows/FileDir.h -#ifndef __WINDOWS_FILEDIR_H -#define __WINDOWS_FILEDIR_H +#ifndef __WINDOWS_FILE_DIR_H +#define __WINDOWS_FILE_DIR_H #include "../Common/MyString.h" -#include "Defs.h" + +#include "FileIO.h" namespace NWindows { namespace NFile { -namespace NDirectory { +namespace NDir { -#ifdef WIN_LONG_PATH -bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2); -#endif +bool GetWindowsDir(FString &path); +bool GetSystemDir(FString &path); -bool MyGetWindowsDirectory(CSysString &path); -bool MyGetSystemDirectory(CSysString &path); -#ifndef _UNICODE -bool MyGetWindowsDirectory(UString &path); -bool MyGetSystemDirectory(UString &path); -#endif +bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); +bool SetFileAttrib(CFSTR path, DWORD attrib); +bool MyMoveFile(CFSTR existFileName, CFSTR newFileName); -bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); - -bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes); -bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName); -bool MyRemoveDirectory(LPCTSTR pathName); -bool MyCreateDirectory(LPCTSTR pathName); -bool CreateComplexDirectory(LPCTSTR pathName); -bool DeleteFileAlways(LPCTSTR name); -bool RemoveDirectoryWithSubItems(const CSysString &path); - -#ifndef _UNICODE -bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes); -bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName); -bool MyRemoveDirectory(LPCWSTR pathName); -bool MyCreateDirectory(LPCWSTR pathName); -bool CreateComplexDirectory(LPCWSTR pathName); -bool DeleteFileAlways(LPCWSTR name); -bool RemoveDirectoryWithSubItems(const UString &path); +#ifndef UNDER_CE +bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName); #endif -bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName); -bool GetOnlyName(LPCTSTR fileName, CSysString &resultName); -#ifdef UNDER_CE -bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath); -bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex); -#else -bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath); - -bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex); -bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath); -#ifndef _UNICODE -bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, - int &fileNamePartStartIndex); -bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath); -bool GetOnlyName(LPCWSTR fileName, UString &resultName); -bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName); -#endif +bool RemoveDir(CFSTR path); +bool CreateDir(CFSTR path); +bool CreateComplexDir(CFSTR path); +bool DeleteFileAlways(CFSTR name); +bool RemoveDirWithSubItems(const FString &path); -inline bool MySetCurrentDirectory(LPCTSTR path) - { return BOOLToBool(::SetCurrentDirectory(path)); } -bool MyGetCurrentDirectory(CSysString &resultPath); -#ifndef _UNICODE -bool MySetCurrentDirectory(LPCWSTR path); -bool MyGetCurrentDirectory(UString &resultPath); -#endif +bool MyGetFullPathName(CFSTR path, FString &resFullPath); +bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName); +bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix); -bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart); -#ifndef _UNICODE -bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart); -#endif +#ifndef UNDER_CE -inline bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath) -{ - UINT32 value; - return MySearchPath(path, fileName, extension, resultPath, value); -} - -#ifndef _UNICODE -inline bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath) -{ - UINT32 value; - return MySearchPath(path, fileName, extension, resultPath, value); -} -#endif +bool SetCurrentDir(CFSTR path); +bool GetCurrentDir(FString &resultPath); #endif -bool MyGetTempPath(CSysString &resultPath); -#ifndef _UNICODE -bool MyGetTempPath(UString &resultPath); -#endif - -UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); -#ifndef _UNICODE -UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); -#endif +bool MyGetTempPath(FString &resultPath); class CTempFile { bool _mustBeDeleted; - CSysString _fileName; + FString _path; + void DisableDeleting() { _mustBeDeleted = false; } public: CTempFile(): _mustBeDeleted(false) {} ~CTempFile() { Remove(); } - void DisableDeleting() { _mustBeDeleted = false; } - UINT Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); - bool Create(LPCTSTR prefix, CSysString &resultPath); + const FString &GetPath() const { return _path; } + bool Create(CFSTR pathPrefix, NIO::COutFile *outFile); // pathPrefix is not folder prefix + bool CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile); bool Remove(); + bool MoveTo(CFSTR name, bool deleteDestBefore); }; -#ifdef _UNICODE -typedef CTempFile CTempFileW; -#else -class CTempFileW +class CTempDir { bool _mustBeDeleted; - UString _fileName; + FString _path; public: - CTempFileW(): _mustBeDeleted(false) {} - ~CTempFileW() { Remove(); } + CTempDir(): _mustBeDeleted(false) {} + ~CTempDir() { Remove(); } + const FString &GetPath() const { return _path; } void DisableDeleting() { _mustBeDeleted = false; } - UINT Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); - bool Create(LPCWSTR prefix, UString &resultPath); + bool Create(CFSTR namePrefix) ; bool Remove(); }; -#endif - -bool CreateTempDirectory(LPCTSTR prefixChars, CSysString &dirName); -class CTempDirectory +#if !defined(UNDER_CE) +class CCurrentDirRestorer { - bool _mustBeDeleted; - CSysString _tempDir; + FString _path; public: - const CSysString &GetPath() const { return _tempDir; } - CTempDirectory(): _mustBeDeleted(false) {} - ~CTempDirectory() { Remove(); } - bool Create(LPCTSTR prefix) ; - bool Remove() + bool NeedRestore; + + CCurrentDirRestorer(): NeedRestore(true) { - if (!_mustBeDeleted) - return true; - _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); - return (!_mustBeDeleted); + GetCurrentDir(_path); } - void DisableDeleting() { _mustBeDeleted = false; } -}; - -#ifdef _UNICODE -typedef CTempDirectory CTempDirectoryW; -#else -class CTempDirectoryW -{ - bool _mustBeDeleted; - UString _tempDir; -public: - const UString &GetPath() const { return _tempDir; } - CTempDirectoryW(): _mustBeDeleted(false) {} - ~CTempDirectoryW() { Remove(); } - bool Create(LPCWSTR prefix) ; - bool Remove() + ~CCurrentDirRestorer() { - if (!_mustBeDeleted) - return true; - _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); - return (!_mustBeDeleted); + if (!NeedRestore) + return; + FString s; + if (GetCurrentDir(s)) + if (s != _path) + SetCurrentDir(_path); } - void DisableDeleting() { _mustBeDeleted = false; } }; #endif diff --git a/src/libs/7zip/win/CPP/Windows/FileFind.cpp b/src/libs/7zip/win/CPP/Windows/FileFind.cpp index e3358f905..7f58288fe 100644 --- a/src/libs/7zip/win/CPP/Windows/FileFind.cpp +++ b/src/libs/7zip/win/CPP/Windows/FileFind.cpp @@ -4,6 +4,7 @@ #include "FileFind.h" #include "FileIO.h" +#include "FileName.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif @@ -12,45 +13,55 @@ extern bool g_IsNT; #endif -namespace NWindows { -namespace NFile { +using namespace NWindows; +using namespace NFile; +using namespace NName; -#ifdef SUPPORT_DEVICE_FILE -bool IsDeviceName(LPCTSTR n); -#ifndef _UNICODE -bool IsDeviceName(LPCWSTR n); -#endif -#endif +#if defined(_WIN32) && !defined(UNDER_CE) -#if defined(WIN_LONG_PATH) && defined(_UNICODE) -#define WIN_LONG_PATH2 -#endif +EXTERN_C_BEGIN + +typedef enum +{ + My_FindStreamInfoStandard, + My_FindStreamInfoMaxInfoLevel +} MY_STREAM_INFO_LEVELS; + +typedef struct +{ + LARGE_INTEGER StreamSize; + WCHAR cStreamName[MAX_PATH + 36]; +} MY_WIN32_FIND_STREAM_DATA, *MY_PWIN32_FIND_STREAM_DATA; -bool GetLongPath(LPCWSTR fileName, UString &res); +typedef WINBASEAPI HANDLE (WINAPI *FindFirstStreamW_Ptr)(LPCWSTR fileName, MY_STREAM_INFO_LEVELS infoLevel, + LPVOID findStreamData, DWORD flags); -namespace NFind { +typedef WINBASEAPI BOOL (APIENTRY *FindNextStreamW_Ptr)(HANDLE findStream, LPVOID findStreamData); -static const TCHAR kDot = TEXT('.'); +EXTERN_C_END -bool CFileInfo::IsDots() const +#endif + +namespace NWindows { +namespace NFile { + +#ifdef SUPPORT_DEVICE_FILE +namespace NSystem { - if (!IsDir() || Name.IsEmpty()) - return false; - if (Name[0] != kDot) - return false; - return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); +bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); } +#endif -#ifndef _UNICODE -bool CFileInfoW::IsDots() const +namespace NFind { + +bool CFileInfo::IsDots() const throw() { if (!IsDir() || Name.IsEmpty()) return false; - if (Name[0] != kDot) + if (Name[0] != FTEXT('.')) return false; - return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); + return Name.Len() == 1 || (Name.Len() == 2 && Name[1] == FTEXT('.')); } -#endif #define WIN_FD_TO_MY_FI(fi, fd) \ fi.Attrib = fd.dwFileAttributes; \ @@ -58,6 +69,7 @@ bool CFileInfoW::IsDots() const fi.ATime = fd.ftLastAccessTime; \ fi.MTime = fd.ftLastWriteTime; \ fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; \ + fi.IsAltStream = false; \ fi.IsDevice = false; /* @@ -68,33 +80,31 @@ bool CFileInfoW::IsDots() const #endif */ -static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi) +static void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfo &fi) { WIN_FD_TO_MY_FI(fi, fd); - fi.Name = fd.cFileName; + fi.Name = us2fs(fd.cFileName); + #if defined(_WIN32) && !defined(UNDER_CE) + // fi.ShortName = us2fs(fd.cAlternateFileName); + #endif } #ifndef _UNICODE -static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } - -static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfoW &fi) -{ - WIN_FD_TO_MY_FI(fi, fd); - fi.Name = fd.cFileName; -} - -static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfoW &fi) +static void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi) { WIN_FD_TO_MY_FI(fi, fd); - fi.Name = GetUnicodeString(fd.cFileName, GetCurrentCodePage()); + fi.Name = fas2fs(fd.cFileName); + #if defined(_WIN32) && !defined(UNDER_CE) + // fi.ShortName = fas2fs(fd.cAlternateFileName); + #endif } #endif - + //////////////////////////////// // CFindFile -bool CFindFile::Close() +bool CFindFileBase::Close() throw() { if (_handle == INVALID_HANDLE_VALUE) return true; @@ -104,183 +114,344 @@ bool CFindFile::Close() return true; } - -bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fi) +bool CFindFile::FindFirst(CFSTR path, CFileInfo &fi) { if (!Close()) return false; - WIN32_FIND_DATA fd; - _handle = ::FindFirstFile(wildcard, &fd); - #ifdef WIN_LONG_PATH2 - if (_handle == INVALID_HANDLE_VALUE) + #ifndef _UNICODE + if (!g_IsNT) { - UString longPath; - if (GetLongPath(wildcard, longPath)) - _handle = ::FindFirstFileW(longPath, &fd); + WIN32_FIND_DATAA fd; + _handle = ::FindFirstFileA(fs2fas(path), &fd); + if (_handle == INVALID_HANDLE_VALUE) + return false; + Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); } + else #endif - if (_handle == INVALID_HANDLE_VALUE) - return false; - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); - return true; -} - -#ifndef _UNICODE -bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fi) -{ - if (!Close()) - return false; - if (g_IsNT) { WIN32_FIND_DATAW fd; - _handle = ::FindFirstFileW(wildcard, &fd); + + IF_USE_MAIN_PATH + _handle = ::FindFirstFileW(fs2us(path), &fd); #ifdef WIN_LONG_PATH - if (_handle == INVALID_HANDLE_VALUE) + if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH) { UString longPath; - if (GetLongPath(wildcard, longPath)) + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) _handle = ::FindFirstFileW(longPath, &fd); } #endif - if (_handle != INVALID_HANDLE_VALUE) - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); + if (_handle == INVALID_HANDLE_VALUE) + return false; + Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); } - else + return true; +} + +bool CFindFile::FindNext(CFileInfo &fi) +{ + #ifndef _UNICODE + if (!g_IsNT) { WIN32_FIND_DATAA fd; - _handle = ::FindFirstFileA(UnicodeStringToMultiByte(wildcard, - GetCurrentCodePage()), &fd); - if (_handle != INVALID_HANDLE_VALUE) - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); + if (!::FindNextFileA(_handle, &fd)) + return false; + Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); } - return (_handle != INVALID_HANDLE_VALUE); + else + #endif + { + WIN32_FIND_DATAW fd; + if (!::FindNextFileW(_handle, &fd)) + return false; + Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); + } + return true; } -#endif -bool CFindFile::FindNext(CFileInfo &fi) +#if defined(_WIN32) && !defined(UNDER_CE) + +//////////////////////////////// +// AltStreams + +static FindFirstStreamW_Ptr g_FindFirstStreamW; +static FindNextStreamW_Ptr g_FindNextStreamW; + +struct CFindStreamLoader { - WIN32_FIND_DATA fd; - bool result = BOOLToBool(::FindNextFile(_handle, &fd)); - if (result) - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); - return result; + CFindStreamLoader() + { + g_FindFirstStreamW = (FindFirstStreamW_Ptr)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "FindFirstStreamW"); + g_FindNextStreamW = (FindNextStreamW_Ptr)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "FindNextStreamW"); + } +} g_FindStreamLoader; + +bool CStreamInfo::IsMainStream() const throw() +{ + return Name == L"::$DATA"; +}; + +UString CStreamInfo::GetReducedName() const +{ + UString s = Name; + if (s.Len() >= 6) + if (wcscmp(s.RightPtr(6), L":$DATA") == 0) + s.DeleteFrom(s.Len() - 6); + return s; } -#ifndef _UNICODE -bool CFindFile::FindNext(CFileInfoW &fi) +static void Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(const MY_WIN32_FIND_STREAM_DATA &sd, CStreamInfo &si) +{ + si.Size = sd.StreamSize.QuadPart; + si.Name = sd.cStreamName; +} + +bool CFindStream::FindFirst(CFSTR path, CStreamInfo &si) { - if (g_IsNT) + if (!Close()) + return false; + if (!g_FindFirstStreamW) { - WIN32_FIND_DATAW fd; - if (!::FindNextFileW(_handle, &fd)) + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return false; + } + { + MY_WIN32_FIND_STREAM_DATA sd; + IF_USE_MAIN_PATH + _handle = g_FindFirstStreamW(fs2us(path), My_FindStreamInfoStandard, &sd, 0); + if (_handle == INVALID_HANDLE_VALUE) + { + if (::GetLastError() == ERROR_HANDLE_EOF) + return false; + // long name can be tricky for path like ".\dirName". + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH) + { + UString longPath; + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) + _handle = g_FindFirstStreamW(longPath, My_FindStreamInfoStandard, &sd, 0); + } + #endif + } + if (_handle == INVALID_HANDLE_VALUE) return false; - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); + Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(sd, si); } - else + return true; +} + +bool CFindStream::FindNext(CStreamInfo &si) +{ + if (!g_FindNextStreamW) { - WIN32_FIND_DATAA fd; - if (!::FindNextFileA(_handle, &fd)) + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return false; + } + { + MY_WIN32_FIND_STREAM_DATA sd; + if (!g_FindNextStreamW(_handle, &sd)) return false; - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); + Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(sd, si); } return true; } + +bool CStreamEnumerator::Next(CStreamInfo &si, bool &found) +{ + bool res; + if (_find.IsHandleAllocated()) + res = _find.FindNext(si); + else + res = _find.FindFirst(_filePath, si); + if (res) + { + found = true; + return true; + } + found = false; + return (::GetLastError() == ERROR_HANDLE_EOF); +} + #endif + #define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0; -void CFileInfoBase::Clear() +void CFileInfoBase::Clear() throw() { Size = 0; MY_CLEAR_FILETIME(CTime); MY_CLEAR_FILETIME(ATime); MY_CLEAR_FILETIME(MTime); Attrib = 0; + IsAltStream = false; + IsDevice = false; } - -bool CFileInfo::Find(LPCTSTR wildcard) + +#if defined(_WIN32) && !defined(UNDER_CE) + +static int FindAltStreamColon(CFSTR path) { - #ifdef SUPPORT_DEVICE_FILE - if (IsDeviceName(wildcard)) + for (int i = 0;; i++) { - Clear(); - IsDevice = true; - NIO::CInFile inFile; - if (!inFile.Open(wildcard)) - return false; - Name = wildcard + 4; - if (inFile.LengthDefined) - Size = inFile.Length; - return true; + FChar c = path[i]; + if (c == 0) + return -1; + if (c == ':') + { + if (path[i + 1] == '\\') + if (i == 1 || (i > 1 && path[i - 2] == '\\')) + { + wchar_t c0 = path[i - 1]; + if (c0 >= 'a' && c0 <= 'z' || + c0 >= 'A' && c0 <= 'Z') + continue; + } + return i; + } } - #endif - CFindFile finder; - return finder.FindFirst(wildcard, *this); } +#endif -#ifndef _UNICODE -bool CFileInfoW::Find(LPCWSTR wildcard) +bool CFileInfo::Find(CFSTR path) { #ifdef SUPPORT_DEVICE_FILE - if (IsDeviceName(wildcard)) + if (IsDevicePath(path)) { Clear(); + Name = path + 4; + IsDevice = true; + if (/* path[0] == '\\' && path[1] == '\\' && path[2] == '.' && path[3] == '\\' && */ + path[5] == ':' && path[6] == 0) + { + FChar drive[4] = { path[4], ':', '\\', 0 }; + UInt64 clusterSize, totalSize, freeSize; + if (NSystem::MyGetDiskFreeSpace(drive, clusterSize, totalSize, freeSize)) + { + Size = totalSize; + return true; + } + } + NIO::CInFile inFile; - if (!inFile.Open(wildcard)) + // ::OutputDebugStringW(path); + if (!inFile.Open(path)) return false; - Name = wildcard + 4; - if (inFile.LengthDefined) - Size = inFile.Length; + // ::OutputDebugStringW(L"---"); + if (inFile.SizeDefined) + Size = inFile.Size; return true; } #endif + + #if defined(_WIN32) && !defined(UNDER_CE) + + int colonPos = FindAltStreamColon(path); + if (colonPos >= 0) + { + UString streamName = fs2us(path + (unsigned)colonPos); + FString filePath = path; + filePath.DeleteFrom(colonPos); + streamName += L":$DATA"; // change it!!!! + if (Find(filePath)) + { + // if (IsDir()) + Attrib &= ~FILE_ATTRIBUTE_DIRECTORY; + Size = 0; + CStreamEnumerator enumerator(filePath); + for (;;) + { + CStreamInfo si; + bool found; + if (!enumerator.Next(si, found)) + return false; + if (!found) + { + ::SetLastError(ERROR_FILE_NOT_FOUND); + return false; + } + if (si.Name.IsEqualToNoCase(streamName)) + { + Name += us2fs(si.Name); + Name.DeleteFrom(Name.Len() - 6); + Size = si.Size; + IsAltStream = true; + return true; + } + } + } + } + + #endif + CFindFile finder; - return finder.FindFirst(wildcard, *this); + if (finder.FindFirst(path, *this)) + return true; + #ifdef _WIN32 + { + DWORD lastError = GetLastError(); + if (lastError == ERROR_BAD_NETPATH || + lastError == ERROR_FILE_NOT_FOUND || + lastError == ERROR_INVALID_NAME // for "\\SERVER\shared" paths that are translated to "\\?\UNC\SERVER\shared" + ) + { + unsigned len = MyStringLen(path); + if (len > 2 && path[0] == '\\' && path[1] == '\\') + { + int startPos = 2; + if (len > kSuperUncPathPrefixSize && IsSuperUncPath(path)) + startPos = kSuperUncPathPrefixSize; + int pos = FindCharPosInString(path + startPos, FTEXT('\\')); + if (pos >= 0) + { + pos += startPos + 1; + len -= pos; + int pos2 = FindCharPosInString(path + pos, FTEXT('\\')); + if (pos2 < 0 || pos2 == (int)len - 1) + { + FString s = path; + if (pos2 < 0) + { + pos2 = len; + s += FTEXT('\\'); + } + s += FCHAR_ANY_MASK; + if (finder.FindFirst(s, *this)) + if (Name == FTEXT(".")) + { + Name.SetFrom(s.Ptr(pos), pos2); + return true; + } + ::SetLastError(lastError); + } + } + } + } + } + #endif + return false; } -#endif -bool DoesFileExist(LPCTSTR name) +bool DoesFileExist(CFSTR name) { CFileInfo fi; return fi.Find(name) && !fi.IsDir(); } -bool DoesDirExist(LPCTSTR name) +bool DoesDirExist(CFSTR name) { CFileInfo fi; return fi.Find(name) && fi.IsDir(); } - -bool DoesFileOrDirExist(LPCTSTR name) +bool DoesFileOrDirExist(CFSTR name) { CFileInfo fi; return fi.Find(name); } -#ifndef _UNICODE -bool DoesFileExist(LPCWSTR name) -{ - CFileInfoW fi; - return fi.Find(name) && !fi.IsDir(); -} - -bool DoesDirExist(LPCWSTR name) -{ - CFileInfoW fi; - return fi.Find(name) && fi.IsDir(); -} -bool DoesFileOrDirExist(LPCWSTR name) -{ - CFileInfoW fi; - return fi.Find(name); -} -#endif - -///////////////////////////////////// -// CEnumerator - bool CEnumerator::NextAny(CFileInfo &fi) { if (_findFile.IsHandleAllocated()) @@ -311,44 +482,11 @@ bool CEnumerator::Next(CFileInfo &fi, bool &found) return (::GetLastError() == ERROR_NO_MORE_FILES); } -#ifndef _UNICODE -bool CEnumeratorW::NextAny(CFileInfoW &fi) -{ - if (_findFile.IsHandleAllocated()) - return _findFile.FindNext(fi); - else - return _findFile.FindFirst(_wildcard, fi); -} - -bool CEnumeratorW::Next(CFileInfoW &fi) -{ - for (;;) - { - if (!NextAny(fi)) - return false; - if (!fi.IsDots()) - return true; - } -} - -bool CEnumeratorW::Next(CFileInfoW &fi, bool &found) -{ - if (Next(fi)) - { - found = true; - return true; - } - found = false; - return (::GetLastError() == ERROR_NO_MORE_FILES); -} - -#endif - //////////////////////////////// // CFindChangeNotification // FindFirstChangeNotification can return 0. MSDN doesn't tell about it. -bool CFindChangeNotification::Close() +bool CFindChangeNotification::Close() throw() { if (!IsHandleAllocated()) return true; @@ -357,105 +495,84 @@ bool CFindChangeNotification::Close() _handle = INVALID_HANDLE_VALUE; return true; } - -HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter) -{ - _handle = ::FindFirstChangeNotification(pathName, BoolToBOOL(watchSubtree), notifyFilter); - #ifdef WIN_LONG_PATH2 - if (!IsHandleAllocated()) - { - UString longPath; - if (GetLongPath(pathName, longPath)) - _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); - } - #endif - return _handle; -} -#ifndef _UNICODE -HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter) +HANDLE CFindChangeNotification::FindFirst(CFSTR path, bool watchSubtree, DWORD notifyFilter) { + #ifndef _UNICODE if (!g_IsNT) - return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), watchSubtree, notifyFilter); - _handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), notifyFilter); - #ifdef WIN_LONG_PATH - if (!IsHandleAllocated()) + _handle = ::FindFirstChangeNotification(fs2fas(path), BoolToBOOL(watchSubtree), notifyFilter); + else + #endif { - UString longPath; - if (GetLongPath(pathName, longPath)) - _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); + IF_USE_MAIN_PATH + _handle = ::FindFirstChangeNotificationW(fs2us(path), BoolToBOOL(watchSubtree), notifyFilter); + #ifdef WIN_LONG_PATH + if (!IsHandleAllocated()) + { + UString longPath; + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) + _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); + } + #endif } - #endif return _handle; } -#endif #ifndef UNDER_CE -bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings) + +bool MyGetLogicalDriveStrings(CObjectVector &driveStrings) { driveStrings.Clear(); - UINT32 size = GetLogicalDriveStrings(0, NULL); - if (size == 0) - return false; - CSysString buffer; - UINT32 newSize = GetLogicalDriveStrings(size, buffer.GetBuffer(size)); - if (newSize == 0) - return false; - if (newSize > size) - return false; - CSysString string; - for (UINT32 i = 0; i < newSize; i++) + #ifndef _UNICODE + if (!g_IsNT) { - TCHAR c = buffer[i]; - if (c == TEXT('\0')) + driveStrings.Clear(); + UINT32 size = GetLogicalDriveStrings(0, NULL); + if (size == 0) + return false; + AString buf; + UINT32 newSize = GetLogicalDriveStrings(size, buf.GetBuffer(size)); + if (newSize == 0 || newSize > size) + return false; + AString s; + for (UINT32 i = 0; i < newSize; i++) { - driveStrings.Add(string); - string.Empty(); + char c = buf[i]; + if (c == '\0') + { + driveStrings.Add(fas2fs(s)); + s.Empty(); + } + else + s += c; } - else - string += c; + return s.IsEmpty(); } - if (!string.IsEmpty()) - return false; - return true; -} - -#ifndef _UNICODE -bool MyGetLogicalDriveStrings(UStringVector &driveStrings) -{ - driveStrings.Clear(); - if (g_IsNT) + else + #endif { UINT32 size = GetLogicalDriveStringsW(0, NULL); if (size == 0) return false; - UString buffer; - UINT32 newSize = GetLogicalDriveStringsW(size, buffer.GetBuffer(size)); - if (newSize == 0) - return false; - if (newSize > size) + UString buf; + UINT32 newSize = GetLogicalDriveStringsW(size, buf.GetBuffer(size)); + if (newSize == 0 || newSize > size) return false; - UString string; + UString s; for (UINT32 i = 0; i < newSize; i++) { - WCHAR c = buffer[i]; + WCHAR c = buf[i]; if (c == L'\0') { - driveStrings.Add(string); - string.Empty(); + driveStrings.Add(us2fs(s)); + s.Empty(); } else - string += c; + s += c; } - return string.IsEmpty(); + return s.IsEmpty(); } - CSysStringVector driveStringsA; - bool res = MyGetLogicalDriveStrings(driveStringsA); - for (int i = 0; i < driveStringsA.Size(); i++) - driveStrings.Add(GetUnicodeString(driveStringsA[i])); - return res; } -#endif #endif diff --git a/src/libs/7zip/win/CPP/Windows/FileFind.h b/src/libs/7zip/win/CPP/Windows/FileFind.h index 63631f66b..aaa7499bd 100644 --- a/src/libs/7zip/win/CPP/Windows/FileFind.h +++ b/src/libs/7zip/win/CPP/Windows/FileFind.h @@ -1,12 +1,10 @@ // Windows/FileFind.h -#ifndef __WINDOWS_FILEFIND_H -#define __WINDOWS_FILEFIND_H +#ifndef __WINDOWS_FILE_FIND_H +#define __WINDOWS_FILE_FIND_H #include "../Common/MyString.h" -#include "../Common/Types.h" #include "Defs.h" -#include "FileName.h" namespace NWindows { namespace NFile { @@ -26,14 +24,13 @@ namespace NAttributes class CFileInfoBase { bool MatchesMask(UINT32 mask) const { return ((Attrib & mask) != 0); } -protected: - void Clear(); public: UInt64 Size; FILETIME CTime; FILETIME ATime; FILETIME MTime; DWORD Attrib; + bool IsAltStream; bool IsDevice; /* @@ -44,6 +41,11 @@ public: #endif */ + CFileInfoBase() { Clear(); } + void Clear() throw(); + + void SetAsDir() { Attrib = FILE_ATTRIBUTE_DIRECTORY; } + bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); } bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); } bool IsDir() const { return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); } @@ -60,78 +62,80 @@ public: struct CFileInfo: public CFileInfoBase { - CSysString Name; + FString Name; + #if defined(_WIN32) && !defined(UNDER_CE) + // FString ShortName; + #endif + + bool IsDots() const throw(); + bool Find(CFSTR wildcard); +}; + +class CFindFileBase +{ +protected: + HANDLE _handle; +public: + bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; } + CFindFileBase(): _handle(INVALID_HANDLE_VALUE) {} + ~CFindFileBase() { Close(); } + bool Close() throw(); +}; - bool IsDots() const; - bool Find(LPCTSTR wildcard); +class CFindFile: public CFindFileBase +{ +public: + bool FindFirst(CFSTR wildcard, CFileInfo &fileInfo); + bool FindNext(CFileInfo &fileInfo); }; -#ifdef _UNICODE -typedef CFileInfo CFileInfoW; -#else -struct CFileInfoW: public CFileInfoBase +#if defined(_WIN32) && !defined(UNDER_CE) + +struct CStreamInfo { UString Name; + UInt64 Size; - bool IsDots() const; - bool Find(LPCWSTR wildcard); + UString GetReducedName() const; + bool IsMainStream() const throw(); }; -#endif -class CFindFile +class CFindStream: public CFindFileBase { - friend class CEnumerator; - HANDLE _handle; public: - bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; } - CFindFile(): _handle(INVALID_HANDLE_VALUE) {} - ~CFindFile() { Close(); } - bool FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo); - bool FindNext(CFileInfo &fileInfo); - #ifndef _UNICODE - bool FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo); - bool FindNext(CFileInfoW &fileInfo); - #endif - bool Close(); + bool FindFirst(CFSTR filePath, CStreamInfo &streamInfo); + bool FindNext(CStreamInfo &streamInfo); +}; + +class CStreamEnumerator +{ + CFindStream _find; + FString _filePath; + + bool NextAny(CFileInfo &fileInfo); +public: + CStreamEnumerator(const FString &filePath): _filePath(filePath) {} + bool Next(CStreamInfo &streamInfo, bool &found); }; -bool DoesFileExist(LPCTSTR name); -bool DoesDirExist(LPCTSTR name); -bool DoesFileOrDirExist(LPCTSTR name); -#ifndef _UNICODE -bool DoesFileExist(LPCWSTR name); -bool DoesDirExist(LPCWSTR name); -bool DoesFileOrDirExist(LPCWSTR name); #endif +bool DoesFileExist(CFSTR name); +bool DoesDirExist(CFSTR name); +bool DoesFileOrDirExist(CFSTR name); + class CEnumerator { CFindFile _findFile; - CSysString _wildcard; + FString _wildcard; + bool NextAny(CFileInfo &fileInfo); public: - CEnumerator(): _wildcard(NName::kAnyStringWildcard) {} - CEnumerator(const CSysString &wildcard): _wildcard(wildcard) {} + CEnumerator(const FString &wildcard): _wildcard(wildcard) {} bool Next(CFileInfo &fileInfo); bool Next(CFileInfo &fileInfo, bool &found); }; -#ifdef _UNICODE -typedef CEnumerator CEnumeratorW; -#else -class CEnumeratorW -{ - CFindFile _findFile; - UString _wildcard; - bool NextAny(CFileInfoW &fileInfo); -public: - CEnumeratorW(): _wildcard(NName::kAnyStringWildcard) {} - CEnumeratorW(const UString &wildcard): _wildcard(wildcard) {} - bool Next(CFileInfoW &fileInfo); - bool Next(CFileInfoW &fileInfo, bool &found); -}; -#endif - class CFindChangeNotification { HANDLE _handle; @@ -140,22 +144,15 @@ public: bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE && _handle != 0; } CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {} ~CFindChangeNotification() { Close(); } - bool Close(); - HANDLE FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter); - #ifndef _UNICODE - HANDLE FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter); - #endif + bool Close() throw(); + HANDLE FindFirst(CFSTR pathName, bool watchSubtree, DWORD notifyFilter); bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); } }; #ifndef UNDER_CE -bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings); -#ifndef _UNICODE -bool MyGetLogicalDriveStrings(UStringVector &driveStrings); -#endif +bool MyGetLogicalDriveStrings(CObjectVector &driveStrings); #endif }}} #endif - diff --git a/src/libs/7zip/win/CPP/Windows/FileIO.cpp b/src/libs/7zip/win/CPP/Windows/FileIO.cpp index 938e6c701..fec859ed3 100644 --- a/src/libs/7zip/win/CPP/Windows/FileIO.cpp +++ b/src/libs/7zip/win/CPP/Windows/FileIO.cpp @@ -2,161 +2,86 @@ #include "StdAfx.h" -#include "FileIO.h" - -#if defined(WIN_LONG_PATH) || defined(SUPPORT_DEVICE_FILE) -#include "../Common/MyString.h" -#endif -#ifndef _UNICODE -#include "../Common/StringConvert.h" +#ifdef SUPPORT_DEVICE_FILE +#include "../../C/Alloc.h" #endif +#include "FileIO.h" +#include "FileName.h" + #ifndef _UNICODE extern bool g_IsNT; #endif +using namespace NWindows; +using namespace NFile; +using namespace NName; + namespace NWindows { namespace NFile { #ifdef SUPPORT_DEVICE_FILE -bool IsDeviceName(LPCTSTR n) -{ - #ifdef UNDER_CE - int len = (int)MyStringLen(n); - if (len < 5 || len > 5 || memcmp(n, TEXT("DSK"), 3 * sizeof(TCHAR)) != 0) - return false; - if (n[4] != ':') - return false; - // for reading use SG_REQ sg; if (DeviceIoControl(dsk, IOCTL_DISK_READ)); - #else - if (n[0] != '\\' || n[1] != '\\' || n[2] != '.' || n[3] != '\\') - return false; - int len = (int)MyStringLen(n); - if (len == 6 && n[5] == ':') - return true; - if (len < 18 || len > 22 || memcmp(n + 4, TEXT("PhysicalDrive"), 13 * sizeof(TCHAR)) != 0) - return false; - for (int i = 17; i < len; i++) - if (n[i] < '0' || n[i] > '9') - return false; - #endif - return true; -} -#ifndef _UNICODE -bool IsDeviceName(LPCWSTR n) +namespace NSystem { - if (n[0] != '\\' || n[1] != '\\' || n[2] != '.' || n[3] != '\\') - return false; - int len = (int)wcslen(n); - if (len == 6 && n[5] == ':') - return true; - if (len < 18 || len > 22 || wcsncmp(n + 4, L"PhysicalDrive", 13) != 0) - return false; - for (int i = 17; i < len; i++) - if (n[i] < '0' || n[i] > '9') - return false; - return true; +bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); } #endif -#endif -#if defined(WIN_LONG_PATH) && defined(_UNICODE) -#define WIN_LONG_PATH2 -#endif - -#ifdef WIN_LONG_PATH -bool GetLongPathBase(LPCWSTR s, UString &res) -{ - res.Empty(); - int len = MyStringLen(s); - wchar_t c = s[0]; - if (len < 1 || c == L'\\' || c == L'.' && (len == 1 || len == 2 && s[1] == L'.')) - return true; - UString curDir; - bool isAbs = false; - if (len > 3) - isAbs = (s[1] == L':' && s[2] == L'\\' && (c >= L'a' && c <= L'z' || c >= L'A' && c <= L'Z')); +namespace NIO { - if (!isAbs) - { - DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, curDir.GetBuffer(MAX_PATH + 1)); - curDir.ReleaseBuffer(); - if (needLength == 0 || needLength > MAX_PATH) - return false; - if (curDir[curDir.Length() - 1] != L'\\') - curDir += L'\\'; - } - res = UString(L"\\\\?\\") + curDir + s; - return true; -} +/* +WinXP-64 CreateFile(): + "" - ERROR_PATH_NOT_FOUND + :stream - OK + .:stream - ERROR_PATH_NOT_FOUND + .\:stream - OK -bool GetLongPath(LPCWSTR path, UString &longPath) -{ - if (GetLongPathBase(path, longPath)) - return !longPath.IsEmpty(); - return false; -} -#endif + folder\:stream - ERROR_INVALID_NAME + folder:stream - OK -namespace NIO { + c:\:stream - OK -CFileBase::~CFileBase() { Close(); } + c::stream - ERROR_INVALID_NAME, if current dir is NOT ROOT ( c:\dir1 ) + c::stream - OK, if current dir is ROOT ( c:\ ) +*/ -bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess, +bool CFileBase::Create(CFSTR path, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (!Close()) return false; - _handle = ::CreateFile(fileName, desiredAccess, shareMode, - (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, - flagsAndAttributes, (HANDLE)NULL); - #ifdef WIN_LONG_PATH2 - if (_handle == INVALID_HANDLE_VALUE) - { - UString longPath; - if (GetLongPath(fileName, longPath)) - _handle = ::CreateFileW(longPath, desiredAccess, shareMode, - (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, - flagsAndAttributes, (HANDLE)NULL); - } - #endif + #ifdef SUPPORT_DEVICE_FILE IsDeviceFile = false; #endif - return (_handle != INVALID_HANDLE_VALUE); -} -#ifndef _UNICODE -bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess, - DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) -{ + #ifndef _UNICODE if (!g_IsNT) - return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP), - desiredAccess, shareMode, creationDisposition, flagsAndAttributes); - if (!Close()) - return false; - _handle = ::CreateFileW(fileName, desiredAccess, shareMode, - (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, - flagsAndAttributes, (HANDLE)NULL); - #ifdef WIN_LONG_PATH - if (_handle == INVALID_HANDLE_VALUE) { - UString longPath; - if (GetLongPath(fileName, longPath)) - _handle = ::CreateFileW(longPath, desiredAccess, shareMode, - (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, - flagsAndAttributes, (HANDLE)NULL); + _handle = ::CreateFile(fs2fas(path), desiredAccess, shareMode, + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } + else #endif - #ifdef SUPPORT_DEVICE_FILE - IsDeviceFile = false; - #endif + { + IF_USE_MAIN_PATH + _handle = ::CreateFileW(fs2us(path), desiredAccess, shareMode, + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); + #ifdef WIN_LONG_PATH + if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + _handle = ::CreateFileW(superPath, desiredAccess, shareMode, + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); + } + #endif + } return (_handle != INVALID_HANDLE_VALUE); } -#endif -bool CFileBase::Close() +bool CFileBase::Close() throw() { if (_handle == INVALID_HANDLE_VALUE) return true; @@ -166,17 +91,17 @@ bool CFileBase::Close() return true; } -bool CFileBase::GetPosition(UInt64 &position) const +bool CFileBase::GetPosition(UInt64 &position) const throw() { return Seek(0, FILE_CURRENT, position); } -bool CFileBase::GetLength(UInt64 &length) const +bool CFileBase::GetLength(UInt64 &length) const throw() { #ifdef SUPPORT_DEVICE_FILE - if (IsDeviceFile && LengthDefined) + if (IsDeviceFile && SizeDefined) { - length = Length; + length = Size; return true; } #endif @@ -190,127 +115,211 @@ bool CFileBase::GetLength(UInt64 &length) const return true; } -bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const +bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw() { #ifdef SUPPORT_DEVICE_FILE - if (IsDeviceFile && LengthDefined && moveMethod == FILE_END) + if (IsDeviceFile && SizeDefined && moveMethod == FILE_END) { - distanceToMove += Length; + distanceToMove += Size; moveMethod = FILE_BEGIN; } #endif - LARGE_INTEGER value; - value.QuadPart = distanceToMove; - value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod); - if (value.LowPart == 0xFFFFFFFF) + LONG high = (LONG)(distanceToMove >> 32); + DWORD low = ::SetFilePointer(_handle, (LONG)(distanceToMove & 0xFFFFFFFF), &high, moveMethod); + if (low == 0xFFFFFFFF) if (::GetLastError() != NO_ERROR) return false; - newPosition = value.QuadPart; + newPosition = (((UInt64)high) << 32) + low; return true; } -bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) +bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) const throw() { return Seek(position, FILE_BEGIN, newPosition); } -bool CFileBase::SeekToBegin() +bool CFileBase::SeekToBegin() const throw() { UInt64 newPosition; return Seek(0, newPosition); } -bool CFileBase::SeekToEnd(UInt64 &newPosition) +bool CFileBase::SeekToEnd(UInt64 &newPosition) const throw() { return Seek(0, FILE_END, newPosition); } -bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const +// ---------- CInFile --------- + +#ifdef SUPPORT_DEVICE_FILE + +void CInFile::CorrectDeviceSize() { - BY_HANDLE_FILE_INFORMATION winFileInfo; - if (!::GetFileInformationByHandle(_handle, &winFileInfo)) - return false; - fileInfo.Attrib = winFileInfo.dwFileAttributes; - fileInfo.CTime = winFileInfo.ftCreationTime; - fileInfo.ATime = winFileInfo.ftLastAccessTime; - fileInfo.MTime = winFileInfo.ftLastWriteTime; - fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes; - fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) + winFileInfo.nFileSizeLow; - fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks; - fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow; - return true; + // maybe we must decrease kClusterSize to 1 << 12, if we want correct size at tail + static const UInt32 kClusterSize = 1 << 14; + UInt64 pos = Size & ~(UInt64)(kClusterSize - 1); + UInt64 realNewPosition; + if (!Seek(pos, realNewPosition)) + return; + Byte *buf = (Byte *)MidAlloc(kClusterSize); + + bool needbackward = true; + + for (;;) + { + UInt32 processed = 0; + // up test is slow for "PhysicalDrive". + // processed size for latest block for "PhysicalDrive0" is 0. + if (!Read1(buf, kClusterSize, processed)) + break; + if (processed == 0) + break; + needbackward = false; + Size = pos + processed; + if (processed != kClusterSize) + break; + pos += kClusterSize; + } + + if (needbackward && pos != 0) + { + pos -= kClusterSize; + for (;;) + { + // break; + if (!Seek(pos, realNewPosition)) + break; + if (!buf) + { + buf = (Byte *)MidAlloc(kClusterSize); + if (!buf) + break; + } + UInt32 processed = 0; + // that code doesn't work for "PhysicalDrive0" + if (!Read1(buf, kClusterSize, processed)) + break; + if (processed != 0) + { + Size = pos + processed; + break; + } + if (pos == 0) + break; + pos -= kClusterSize; + } + } + MidFree(buf); } -///////////////////////// -// CInFile -#ifdef SUPPORT_DEVICE_FILE -void CInFile::GetDeviceLength() +void CInFile::CalcDeviceSize(CFSTR s) { - if (_handle != INVALID_HANDLE_VALUE && IsDeviceFile) - { - #ifdef UNDER_CE - LengthDefined = true; - Length = 128 << 20; + SizeDefined = false; + Size = 0; + if (_handle == INVALID_HANDLE_VALUE || !IsDeviceFile) + return; + #ifdef UNDER_CE + + SizeDefined = true; + Size = 128 << 20; + + #else + + PARTITION_INFORMATION partInfo; + bool needCorrectSize = true; - #else - PARTITION_INFORMATION partInfo; - LengthDefined = true; - Length = 0; + /* + WinXP 64-bit: + + HDD \\.\PhysicalDrive0 (MBR): + GetPartitionInfo == GeometryEx : corrrect size? (includes tail) + Geometry : smaller than GeometryEx (no tail, maybe correct too?) + MyGetDiskFreeSpace : FAIL + Size correction is slow and block size (kClusterSize) must be small? + + HDD partition \\.\N: (NTFS): + MyGetDiskFreeSpace : Size of NTFS clusters. Same size can be calculated after correction + GetPartitionInfo : size of partition data: NTFS clusters + TAIL; TAIL contains extra empty sectors and copy of first sector of NTFS + Geometry / CdRomGeometry / GeometryEx : size of HDD (not that partition) + + CD-ROM drive (ISO): + MyGetDiskFreeSpace : correct size. Same size can be calculated after correction + Geometry == CdRomGeometry : smaller than corrrect size + GetPartitionInfo == GeometryEx : larger than corrrect size + + Floppy \\.\a: (FAT): + Geometry : correct size. + CdRomGeometry / GeometryEx / GetPartitionInfo / MyGetDiskFreeSpace - FAIL + correction works OK for FAT. + correction works OK for non-FAT, if kClusterSize = 512. + */ + + if (GetPartitionInfo(&partInfo)) + { + Size = partInfo.PartitionLength.QuadPart; + SizeDefined = true; + needCorrectSize = false; + if ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '.' && (s)[3] == '\\' && (s)[5] == ':' && (s)[6] == 0) + { + FChar path[4] = { s[4], ':', '\\', 0 }; + UInt64 clusterSize, totalSize, freeSize; + if (NSystem::MyGetDiskFreeSpace(path, clusterSize, totalSize, freeSize)) + Size = totalSize; + else + needCorrectSize = true; + } + } - if (GetPartitionInfo(&partInfo)) - Length = partInfo.PartitionLength.QuadPart; + if (!SizeDefined) + { + my_DISK_GEOMETRY_EX geomEx; + SizeDefined = GetGeometryEx(&geomEx); + if (SizeDefined) + Size = geomEx.DiskSize.QuadPart; else { DISK_GEOMETRY geom; - if (!GetGeometry(&geom)) - if (!GetCdRomGeometry(&geom)) - LengthDefined = false; - if (LengthDefined) - Length = geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector; + SizeDefined = GetGeometry(&geom); + if (!SizeDefined) + SizeDefined = GetCdRomGeometry(&geom); + if (SizeDefined) + Size = geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector; } - // SeekToBegin(); - #endif } + + if (needCorrectSize && SizeDefined && Size != 0) + { + CorrectDeviceSize(); + SeekToBegin(); + } + + // SeekToBegin(); + #endif } // ((desiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE)) == 0 && #define MY_DEVICE_EXTRA_CODE \ - IsDeviceFile = IsDeviceName(fileName); \ - GetDeviceLength(); + IsDeviceFile = IsDevicePath(fileName); \ + CalcDeviceSize(fileName); #else #define MY_DEVICE_EXTRA_CODE #endif -bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) -{ - bool res = Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); - MY_DEVICE_EXTRA_CODE - return res; -} - -bool CInFile::OpenShared(LPCTSTR fileName, bool shareForWrite) -{ return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } - -bool CInFile::Open(LPCTSTR fileName) - { return OpenShared(fileName, false); } - -#ifndef _UNICODE -bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) +bool CInFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { bool res = Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); MY_DEVICE_EXTRA_CODE return res; } -bool CInFile::OpenShared(LPCWSTR fileName, bool shareForWrite) +bool CInFile::OpenShared(CFSTR fileName, bool shareForWrite) { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } -bool CInFile::Open(LPCWSTR fileName) +bool CInFile::Open(CFSTR fileName) { return OpenShared(fileName, false); } -#endif // ReadFile and WriteFile functions in Windows have BUG: // If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) @@ -323,7 +332,7 @@ bool CInFile::Open(LPCWSTR fileName) static UInt32 kChunkSizeMax = (1 << 22); -bool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize) +bool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize) throw() { DWORD processedLoc = 0; bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); @@ -331,14 +340,14 @@ bool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize) return res; } -bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) +bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw() { if (size > kChunkSizeMax) size = kChunkSizeMax; return Read1(data, size, processedSize); } -bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) +bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) throw() { processedSize = 0; do @@ -357,40 +366,29 @@ bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) return true; } -///////////////////////// -// COutFile - -bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) - { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } +// ---------- COutFile --------- static inline DWORD GetCreationDisposition(bool createAlways) { return createAlways? CREATE_ALWAYS: CREATE_NEW; } -bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition) - { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } - -bool COutFile::Create(LPCTSTR fileName, bool createAlways) - { return Open(fileName, GetCreationDisposition(createAlways)); } - -#ifndef _UNICODE - -bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) +bool COutFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } -bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition) +bool COutFile::Open(CFSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } -bool COutFile::Create(LPCWSTR fileName, bool createAlways) +bool COutFile::Create(CFSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } -#endif +bool COutFile::CreateAlways(CFSTR fileName, DWORD flagsAndAttributes) + { return Open(fileName, FILE_SHARE_READ, GetCreationDisposition(true), flagsAndAttributes); } -bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) +bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw() { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); } -bool COutFile::SetMTime(const FILETIME *mTime) { return SetTime(NULL, NULL, mTime); } +bool COutFile::SetMTime(const FILETIME *mTime) throw() { return SetTime(NULL, NULL, mTime); } -bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) +bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw() { if (size > kChunkSizeMax) size = kChunkSizeMax; @@ -400,7 +398,7 @@ bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) return res; } -bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) +bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) throw() { processedSize = 0; do @@ -419,9 +417,9 @@ bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) return true; } -bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); } +bool COutFile::SetEndOfFile() throw() { return BOOLToBool(::SetEndOfFile(_handle)); } -bool COutFile::SetLength(UInt64 length) +bool COutFile::SetLength(UInt64 length) throw() { UInt64 newPosition; if (!Seek(length, newPosition)) diff --git a/src/libs/7zip/win/CPP/Windows/FileIO.h b/src/libs/7zip/win/CPP/Windows/FileIO.h index dce692fed..f595121ef 100644 --- a/src/libs/7zip/win/CPP/Windows/FileIO.h +++ b/src/libs/7zip/win/CPP/Windows/FileIO.h @@ -1,134 +1,199 @@ // Windows/FileIO.h -#ifndef __WINDOWS_FILEIO_H -#define __WINDOWS_FILEIO_H +#ifndef __WINDOWS_FILE_IO_H +#define __WINDOWS_FILE_IO_H -#include "../Common/Types.h" +#if defined(_WIN32) && !defined(UNDER_CE) +#include +#endif + +#include "../Common/MyString.h" +#include "../Common/MyBuffer.h" #include "Defs.h" +#define _my_IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) +#define _my_IO_REPARSE_TAG_SYMLINK (0xA000000CL) + +#define _my_SYMLINK_FLAG_RELATIVE 1 + +#define my_FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER +#define my_FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) // REPARSE_DATA_BUFFER + namespace NWindows { namespace NFile { -namespace NIO { -struct CByHandleFileInfo +#if defined(_WIN32) && !defined(UNDER_CE) +bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink); +#endif + +struct CReparseShortInfo +{ + unsigned Offset; + unsigned Size; + + bool Parse(const Byte *p, size_t size); +}; + +struct CReparseAttr { - DWORD Attrib; - FILETIME CTime; - FILETIME ATime; - FILETIME MTime; - DWORD VolumeSerialNumber; - UInt64 Size; - DWORD NumberOfLinks; - UInt64 FileIndex; + UInt32 Tag; + UInt32 Flags; + UString SubsName; + UString PrintName; + + CReparseAttr(): Tag(0), Flags(0) {} + bool Parse(const Byte *p, size_t size); + + bool IsMountPoint() const { return Tag == _my_IO_REPARSE_TAG_MOUNT_POINT; } // it's Junction + bool IsSymLink() const { return Tag == _my_IO_REPARSE_TAG_SYMLINK; } + bool IsRelative() const { return Flags == _my_SYMLINK_FLAG_RELATIVE; } + // bool IsVolume() const; + + bool IsOkNamePair() const; + UString GetPath() const; }; +namespace NIO { + +bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo = NULL); +bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size); + class CFileBase { protected: HANDLE _handle; - - bool Create(LPCTSTR fileName, DWORD desiredAccess, - DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); - #ifndef _UNICODE - bool Create(LPCWSTR fileName, DWORD desiredAccess, + + bool Create(CFSTR path, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); - #endif + +public: + + bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, DWORD inSize, + LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned, LPOVERLAPPED overlapped = NULL) const + { + return BOOLToBool(::DeviceIoControl(_handle, controlCode, inBuffer, inSize, + outBuffer, outSize, bytesReturned, overlapped)); + } + + bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned) const + { + return DeviceIoControl(controlCode, NULL, 0, outBuffer, outSize, bytesReturned); + } + + bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize) const + { + DWORD bytesReturned; + return DeviceIoControlOut(controlCode, outBuffer, outSize, &bytesReturned); + } public: #ifdef SUPPORT_DEVICE_FILE bool IsDeviceFile; - bool LengthDefined; - UInt64 Length; + bool SizeDefined; + UInt64 Size; // it can be larger than real available size #endif CFileBase(): _handle(INVALID_HANDLE_VALUE) {}; - ~CFileBase(); + ~CFileBase() { Close(); } + + bool Close() throw(); + + bool GetPosition(UInt64 &position) const throw(); + bool GetLength(UInt64 &length) const throw(); - bool Close(); + bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw(); + bool Seek(UInt64 position, UInt64 &newPosition) const throw(); + bool SeekToBegin() const throw(); + bool SeekToEnd(UInt64 &newPosition) const throw(); - bool GetPosition(UInt64 &position) const; - bool GetLength(UInt64 &length) const; + bool GetFileInformation(BY_HANDLE_FILE_INFORMATION *info) const + { return BOOLToBool(GetFileInformationByHandle(_handle, info)); } - bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const; - bool Seek(UInt64 position, UInt64 &newPosition); - bool SeekToBegin(); - bool SeekToEnd(UInt64 &newPosition); - - bool GetFileInformation(CByHandleFileInfo &fileInfo) const; + static bool GetFileInformation(CFSTR path, BY_HANDLE_FILE_INFORMATION *info) + { + NIO::CFileBase file; + if (!file.Create(path, 0, FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS)) + return false; + return file.GetFileInformation(info); + } }; +#ifndef UNDER_CE #define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM #define IOCTL_CDROM_GET_DRIVE_GEOMETRY CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_MEDIA_REMOVAL CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS) +// #define IOCTL_CDROM_MEDIA_REMOVAL CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS) + +// IOCTL_DISK_GET_DRIVE_GEOMETRY_EX works since WinXP +#define my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX CTL_CODE(IOCTL_DISK_BASE, 0x0028, METHOD_BUFFERED, FILE_ANY_ACCESS) + +struct my_DISK_GEOMETRY_EX +{ + DISK_GEOMETRY Geometry; + LARGE_INTEGER DiskSize; + BYTE Data[1]; +}; +#endif class CInFile: public CFileBase { #ifdef SUPPORT_DEVICE_FILE - bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, DWORD inSize, - LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned, LPOVERLAPPED overlapped) const - { - return BOOLToBool(::DeviceIoControl(_handle, controlCode, inBuffer, inSize, - outBuffer, outSize, bytesReturned, overlapped)); - } - - bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, - DWORD inSize, LPVOID outBuffer, DWORD outSize) const - { - DWORD ret; - return DeviceIoControl(controlCode, inBuffer, inSize, outBuffer, outSize, &ret, 0); - } - - bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize) const - { return DeviceIoControl(controlCode, NULL, 0, outBuffer, outSize); } #ifndef UNDER_CE + bool GetGeometry(DISK_GEOMETRY *res) const { return DeviceIoControlOut(IOCTL_DISK_GET_DRIVE_GEOMETRY, res, sizeof(*res)); } + bool GetGeometryEx(my_DISK_GEOMETRY_EX *res) const + { return DeviceIoControlOut(my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, res, sizeof(*res)); } + bool GetCdRomGeometry(DISK_GEOMETRY *res) const { return DeviceIoControlOut(IOCTL_CDROM_GET_DRIVE_GEOMETRY, res, sizeof(*res)); } - + bool GetPartitionInfo(PARTITION_INFORMATION *res) { return DeviceIoControlOut(IOCTL_DISK_GET_PARTITION_INFO, LPVOID(res), sizeof(*res)); } + #endif - void GetDeviceLength(); + void CorrectDeviceSize(); + void CalcDeviceSize(CFSTR name); + #endif public: - bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); - bool OpenShared(LPCTSTR fileName, bool shareForWrite); - bool Open(LPCTSTR fileName); - #ifndef _UNICODE - bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); - bool OpenShared(LPCWSTR fileName, bool shareForWrite); - bool Open(LPCWSTR fileName); + bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + bool OpenShared(CFSTR fileName, bool shareForWrite); + bool Open(CFSTR fileName); + + #ifndef UNDER_CE + + bool OpenReparse(CFSTR fileName) + { + return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS); + } + #endif - bool Read1(void *data, UInt32 size, UInt32 &processedSize); - bool ReadPart(void *data, UInt32 size, UInt32 &processedSize); - bool Read(void *data, UInt32 size, UInt32 &processedSize); + + bool Read1(void *data, UInt32 size, UInt32 &processedSize) throw(); + bool ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw(); + bool Read(void *data, UInt32 size, UInt32 &processedSize) throw(); }; class COutFile: public CFileBase { public: - bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); - bool Open(LPCTSTR fileName, DWORD creationDisposition); - bool Create(LPCTSTR fileName, bool createAlways); - - #ifndef _UNICODE - bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); - bool Open(LPCWSTR fileName, DWORD creationDisposition); - bool Create(LPCWSTR fileName, bool createAlways); - #endif - - bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); - bool SetMTime(const FILETIME *mTime); - bool WritePart(const void *data, UInt32 size, UInt32 &processedSize); - bool Write(const void *data, UInt32 size, UInt32 &processedSize); - bool SetEndOfFile(); - bool SetLength(UInt64 length); + bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + bool Open(CFSTR fileName, DWORD creationDisposition); + bool Create(CFSTR fileName, bool createAlways); + bool CreateAlways(CFSTR fileName, DWORD flagsAndAttributes); + + bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw(); + bool SetMTime(const FILETIME *mTime) throw(); + bool WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw(); + bool Write(const void *data, UInt32 size, UInt32 &processedSize) throw(); + bool SetEndOfFile() throw(); + bool SetLength(UInt64 length) throw(); }; }}} diff --git a/src/libs/7zip/win/CPP/Windows/FileLink.cpp b/src/libs/7zip/win/CPP/Windows/FileLink.cpp new file mode 100644 index 000000000..dc524700d --- /dev/null +++ b/src/libs/7zip/win/CPP/Windows/FileLink.cpp @@ -0,0 +1,426 @@ +// Windows/FileLink.cpp + +#include "StdAfx.h" + +#include "../../C/CpuArch.h" + +#ifdef SUPPORT_DEVICE_FILE +#include "../../C/Alloc.h" +#endif + +#include "FileDir.h" +#include "FileFind.h" +#include "FileIO.h" +#include "FileName.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NFile { + +using namespace NName; + +/* + Reparse Points (Junctions and Symbolic Links): + struct + { + UInt32 Tag; + UInt16 Size; // not including starting 8 bytes + UInt16 Reserved; // = 0 + + UInt16 SubstituteOffset; // offset in bytes from start of namesChars + UInt16 SubstituteLen; // size in bytes, it doesn't include tailed NUL + UInt16 PrintOffset; // offset in bytes from start of namesChars + UInt16 PrintLen; // size in bytes, it doesn't include tailed NUL + + [UInt32] Flags; // for Symbolic Links only. + + UInt16 namesChars[] + } + + MOUNT_POINT (Junction point): + 1) there is NUL wchar after path + 2) Default Order in table: + Substitute Path + Print Path + 3) pathnames can not contain dot directory names + + SYMLINK: + 1) there is no NUL wchar after path + 2) Default Order in table: + Print Path + Substitute Path +*/ + +/* +static const UInt32 kReparseFlags_Alias = (1 << 29); +static const UInt32 kReparseFlags_HighLatency = (1 << 30); +static const UInt32 kReparseFlags_Microsoft = ((UInt32)1 << 31); + +#define _my_IO_REPARSE_TAG_HSM (0xC0000004L) +#define _my_IO_REPARSE_TAG_HSM2 (0x80000006L) +#define _my_IO_REPARSE_TAG_SIS (0x80000007L) +#define _my_IO_REPARSE_TAG_WIM (0x80000008L) +#define _my_IO_REPARSE_TAG_CSV (0x80000009L) +#define _my_IO_REPARSE_TAG_DFS (0x8000000AL) +#define _my_IO_REPARSE_TAG_DFSR (0x80000012L) +*/ + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) + +#define Set16(p, v) SetUi16(p, v) +#define Set32(p, v) SetUi32(p, v) + +static const wchar_t *k_LinkPrefix = L"\\??\\"; +static const unsigned k_LinkPrefix_Size = 4; + +static const bool IsLinkPrefix(const wchar_t *s) +{ + return IsString1PrefixedByString2(s, k_LinkPrefix); +} + +/* +static const wchar_t *k_VolumePrefix = L"Volume{"; +static const bool IsVolumeName(const wchar_t *s) +{ + return IsString1PrefixedByString2(s, k_VolumePrefix); +} +*/ + +void WriteString(Byte *dest, const wchar_t *path) +{ + for (;;) + { + wchar_t c = *path++; + if (c == 0) + return; + Set16(dest, (UInt16)c); + dest += 2; + } +} + +bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink) +{ + bool isAbs = IsAbsolutePath(path); + if (!isAbs && !isSymLink) + return false; + + bool needPrintName = true; + + if (IsSuperPath(path)) + { + path += kSuperPathPrefixSize; + if (!IsDrivePath(path)) + needPrintName = false; + } + + const unsigned add_Prefix_Len = isAbs ? k_LinkPrefix_Size : 0; + + unsigned len2 = MyStringLen(path) * 2; + const unsigned len1 = len2 + add_Prefix_Len * 2; + if (!needPrintName) + len2 = 0; + + unsigned totalNamesSize = (len1 + len2); + + /* some WIM imagex software uses old scheme for symbolic links. + so we can old scheme for byte to byte compatibility */ + + bool newOrderScheme = isSymLink; + // newOrderScheme = false; + + if (!newOrderScheme) + totalNamesSize += 2 * 2; + + const size_t size = 8 + 8 + (isSymLink ? 4 : 0) + totalNamesSize; + dest.Alloc(size); + memset(dest, 0, size); + const UInt32 tag = isSymLink ? + _my_IO_REPARSE_TAG_SYMLINK : + _my_IO_REPARSE_TAG_MOUNT_POINT; + Byte *p = dest; + Set32(p, tag); + Set16(p + 4, (UInt16)(size - 8)); + Set16(p + 6, 0); + p += 8; + + unsigned subOffs = 0; + unsigned printOffs = 0; + if (newOrderScheme) + subOffs = len2; + else + printOffs = len1 + 2; + + Set16(p + 0, (UInt16)subOffs); + Set16(p + 2, (UInt16)len1); + Set16(p + 4, (UInt16)printOffs); + Set16(p + 6, (UInt16)len2); + + p += 8; + if (isSymLink) + { + UInt32 flags = isAbs ? 0 : _my_SYMLINK_FLAG_RELATIVE; + Set32(p, flags); + p += 4; + } + + if (add_Prefix_Len != 0) + WriteString(p + subOffs, k_LinkPrefix); + WriteString(p + subOffs + add_Prefix_Len * 2, path); + if (needPrintName) + WriteString(p + printOffs, path); + return true; +} + +static void GetString(const Byte *p, unsigned len, UString &res) +{ + wchar_t *s = res.GetBuffer(len); + for (unsigned i = 0; i < len; i++) + s[i] = Get16(p + i * 2); + s[len] = 0; + res.ReleaseBuffer(); +} + +bool CReparseAttr::Parse(const Byte *p, size_t size) +{ + if (size < 8) + return false; + Tag = Get32(p); + UInt32 len = Get16(p + 4); + if (len + 8 > size) + return false; + /* + if ((type & kReparseFlags_Alias) == 0 || + (type & kReparseFlags_Microsoft) == 0 || + (type & 0xFFFF) != 3) + */ + if (Tag != _my_IO_REPARSE_TAG_MOUNT_POINT && + Tag != _my_IO_REPARSE_TAG_SYMLINK) + // return true; + return false; + + if (Get16(p + 6) != 0) // padding + return false; + + p += 8; + size -= 8; + + if (len != size) // do we need that check? + return false; + + if (len < 8) + return false; + unsigned subOffs = Get16(p); + unsigned subLen = Get16(p + 2); + unsigned printOffs = Get16(p + 4); + unsigned printLen = Get16(p + 6); + len -= 8; + p += 8; + + Flags = 0; + if (Tag == _my_IO_REPARSE_TAG_SYMLINK) + { + if (len < 4) + return false; + Flags = Get32(p); + len -= 4; + p += 4; + } + + if ((subOffs & 1) != 0 || subOffs > len || len - subOffs < subLen) + return false; + if ((printOffs & 1) != 0 || printOffs > len || len - printOffs < printLen) + return false; + GetString(p + subOffs, subLen >> 1, SubsName); + GetString(p + printOffs, printLen >> 1, PrintName); + + return true; +} + +bool CReparseShortInfo::Parse(const Byte *p, size_t size) +{ + const Byte *start = p; + Offset= 0; + Size = 0; + if (size < 8) + return false; + UInt32 Tag = Get32(p); + UInt32 len = Get16(p + 4); + if (len + 8 > size) + return false; + /* + if ((type & kReparseFlags_Alias) == 0 || + (type & kReparseFlags_Microsoft) == 0 || + (type & 0xFFFF) != 3) + */ + if (Tag != _my_IO_REPARSE_TAG_MOUNT_POINT && + Tag != _my_IO_REPARSE_TAG_SYMLINK) + // return true; + return false; + + if (Get16(p + 6) != 0) // padding + return false; + + p += 8; + size -= 8; + + if (len != size) // do we need that check? + return false; + + if (len < 8) + return false; + unsigned subOffs = Get16(p); + unsigned subLen = Get16(p + 2); + unsigned printOffs = Get16(p + 4); + unsigned printLen = Get16(p + 6); + len -= 8; + p += 8; + + // UInt32 Flags = 0; + if (Tag == _my_IO_REPARSE_TAG_SYMLINK) + { + if (len < 4) + return false; + // Flags = Get32(p); + len -= 4; + p += 4; + } + + if ((subOffs & 1) != 0 || subOffs > len || len - subOffs < subLen) + return false; + if ((printOffs & 1) != 0 || printOffs > len || len - printOffs < printLen) + return false; + + Offset = (unsigned)(p - start) + subOffs; + Size = subLen; + return true; +} + +bool CReparseAttr::IsOkNamePair() const +{ + if (IsLinkPrefix(SubsName)) + { + if (!IsDrivePath(SubsName.Ptr(k_LinkPrefix_Size))) + return PrintName.IsEmpty(); + if (wcscmp(SubsName.Ptr(k_LinkPrefix_Size), PrintName) == 0) + return true; + } + return wcscmp(SubsName, PrintName) == 0; +} + +/* +bool CReparseAttr::IsVolume() const +{ + if (!IsLinkPrefix(SubsName)) + return false; + return IsVolumeName(SubsName.Ptr(k_LinkPrefix_Size)); +} +*/ + +UString CReparseAttr::GetPath() const +{ + UString s = SubsName; + if (IsLinkPrefix(s)) + { + s.ReplaceOneCharAtPos(1, '\\'); + if (IsDrivePath(s.Ptr(k_LinkPrefix_Size))) + s.DeleteFrontal(k_LinkPrefix_Size); + } + return s; +} + + +#ifdef SUPPORT_DEVICE_FILE + +namespace NSystem +{ +bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); +} +#endif + +#ifndef UNDER_CE + +namespace NIO { + +bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo) +{ + reparseData.Free(); + CInFile file; + if (!file.OpenReparse(path)) + return false; + + if (fileInfo) + file.GetFileInformation(fileInfo); + + const unsigned kBufSize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE; + CByteArr buf(kBufSize); + DWORD returnedSize; + if (!file.DeviceIoControlOut(my_FSCTL_GET_REPARSE_POINT, buf, kBufSize, &returnedSize)) + return false; + reparseData.CopyFrom(buf, returnedSize); + return true; +} + +static bool CreatePrefixDirOfFile(CFSTR path) +{ + FString path2 = path; + int pos = path2.ReverseFind(FCHAR_PATH_SEPARATOR); + if (pos < 0) + return true; + #ifdef _WIN32 + if (pos == 2 && path2[1] == L':') + return true; // we don't create Disk folder; + #endif + path2.DeleteFrom(pos); + return NDir::CreateComplexDir(path2); +} + +// If there is Reprase data already, it still writes new Reparse data +bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size) +{ + NFile::NFind::CFileInfo fi; + if (fi.Find(path)) + { + if (fi.IsDir() != isDir) + { + ::SetLastError(ERROR_DIRECTORY); + return false; + } + } + else + { + if (isDir) + { + if (!NDir::CreateComplexDir(path)) + return false; + } + else + { + CreatePrefixDirOfFile(path); + COutFile file; + if (!file.Create(path, CREATE_NEW)) + return false; + } + } + + COutFile file; + if (!file.Open(path, + FILE_SHARE_WRITE, + OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS)) + return false; + + DWORD returnedSize; + if (!file.DeviceIoControl(my_FSCTL_SET_REPARSE_POINT, (void *)data, size, NULL, 0, &returnedSize)) + return false; + return true; +} + +} + +#endif + +}} diff --git a/src/libs/7zip/win/CPP/Windows/FileMapping.cpp b/src/libs/7zip/win/CPP/Windows/FileMapping.cpp deleted file mode 100644 index 55048fdb2..000000000 --- a/src/libs/7zip/win/CPP/Windows/FileMapping.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// Windows/FileMapping.cpp - -#include "StdAfx.h" - -#include "Windows/FileMapping.h" - -namespace NWindows { -namespace NFile { -namespace NMapping { - - -}}} diff --git a/src/libs/7zip/win/CPP/Windows/FileMapping.h b/src/libs/7zip/win/CPP/Windows/FileMapping.h index 3f0ebd74c..f90c429f1 100644 --- a/src/libs/7zip/win/CPP/Windows/FileMapping.h +++ b/src/libs/7zip/win/CPP/Windows/FileMapping.h @@ -3,7 +3,7 @@ #ifndef __WINDOWS_FILEMAPPING_H #define __WINDOWS_FILEMAPPING_H -#include "Common/Types.h" +#include "../Common/MyTypes.h" #include "Handle.h" @@ -18,7 +18,11 @@ public: return ::GetLastError(); } - WRes Open(DWORD desiredAccess, LPCTSTR name) + WRes Open(DWORD + #ifndef UNDER_CE + desiredAccess + #endif + , LPCTSTR name) { #ifdef UNDER_CE WRes res = Create(PAGE_READONLY, 0, name); diff --git a/src/libs/7zip/win/CPP/Windows/FileName.cpp b/src/libs/7zip/win/CPP/Windows/FileName.cpp index 8443a4af9..0a6aee100 100644 --- a/src/libs/7zip/win/CPP/Windows/FileName.cpp +++ b/src/libs/7zip/win/CPP/Windows/FileName.cpp @@ -2,49 +2,686 @@ #include "StdAfx.h" -#include "Windows/FileName.h" -#include "Common/Wildcard.h" +#include "FileName.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif namespace NWindows { namespace NFile { namespace NName { -void NormalizeDirPathPrefix(CSysString &dirPath) +#ifndef USE_UNICODE_FSTRING +void NormalizeDirPathPrefix(FString &dirPath) { if (dirPath.IsEmpty()) return; - if (dirPath.ReverseFind(kDirDelimiter) != dirPath.Length() - 1) - dirPath += kDirDelimiter; + if (dirPath.Back() != FCHAR_PATH_SEPARATOR) + dirPath += FCHAR_PATH_SEPARATOR; } +#endif -#ifndef _UNICODE void NormalizeDirPathPrefix(UString &dirPath) { if (dirPath.IsEmpty()) return; - if (dirPath.ReverseFind(wchar_t(kDirDelimiter)) != dirPath.Length() - 1) - dirPath += wchar_t(kDirDelimiter); + if (dirPath.Back() != WCHAR_PATH_SEPARATOR) + dirPath += WCHAR_PATH_SEPARATOR; +} + + +#ifdef _WIN32 + +const wchar_t *kSuperPathPrefix = L"\\\\?\\"; +static const wchar_t *kSuperUncPrefix = L"\\\\?\\UNC\\"; + +#define IS_DEVICE_PATH(s) ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '.' && (s)[3] == '\\') +#define IS_SUPER_PREFIX(s) ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '?' && (s)[3] == '\\') +#define IS_SUPER_OR_DEVICE_PATH(s) ((s)[0] == '\\' && (s)[1] == '\\' && ((s)[2] == '?' || (s)[2] == '.') && (s)[3] == '\\') +#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z') + +#define IS_UNC_WITH_SLASH(s) ( \ + ((s)[0] == 'U' || (s)[0] == 'u') && \ + ((s)[1] == 'N' || (s)[1] == 'n') && \ + ((s)[2] == 'C' || (s)[2] == 'c') && \ + (s)[3] == '\\') + +bool IsDevicePath(CFSTR s) throw() +{ + #ifdef UNDER_CE + + s = s; + return false; + /* + // actually we don't know the way to open device file in WinCE. + unsigned len = MyStringLen(s); + if (len < 5 || len > 5 || memcmp(s, FTEXT("DSK"), 3 * sizeof(FChar)) != 0) + return false; + if (s[4] != ':') + return false; + // for reading use SG_REQ sg; if (DeviceIoControl(dsk, IOCTL_DISK_READ)); + */ + + #else + + if (!IS_DEVICE_PATH(s)) + return false; + unsigned len = MyStringLen(s); + if (len == 6 && s[5] == ':') + return true; + if (len < 18 || len > 22 || memcmp(s + kDevicePathPrefixSize, FTEXT("PhysicalDrive"), 13 * sizeof(FChar)) != 0) + return false; + for (unsigned i = 17; i < len; i++) + if (s[i] < '0' || s[i] > '9') + return false; + return true; + + #endif +} + +bool IsSuperUncPath(CFSTR s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); } + +bool IsDrivePath(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == '\\'; } +bool IsSuperPath(const wchar_t *s) throw() { return IS_SUPER_PREFIX(s); } +bool IsSuperOrDevicePath(const wchar_t *s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); } +// bool IsSuperUncPath(const wchar_t *s) { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); } + +#ifndef USE_UNICODE_FSTRING +bool IsDrivePath(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == '\\'; } +bool IsSuperPath(CFSTR s) throw() { return IS_SUPER_PREFIX(s); } +bool IsSuperOrDevicePath(CFSTR s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); } +#endif // USE_UNICODE_FSTRING + +bool IsAbsolutePath(const wchar_t *s) throw() +{ + return s[0] == WCHAR_PATH_SEPARATOR || IsDrivePath(s); +} + +static const unsigned kDrivePrefixSize = 3; /* c:\ */ + +#ifndef USE_UNICODE_FSTRING + +static unsigned GetRootPrefixSize_Of_NetworkPath(CFSTR s) throw() +{ + // Network path: we look "server\path\" as root prefix + int pos = FindCharPosInString(s, '\\'); + if (pos < 0) + return 0; + int pos2 = FindCharPosInString(s + pos + 1, '\\'); + if (pos2 < 0) + return 0; + return pos + pos2 + 2; +} + +static unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s) throw() +{ + if (IsDrivePath(s)) + return kDrivePrefixSize; + if (s[0] != '\\' || s[1] != '\\') + return 0; + unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2); + return (size == 0) ? 0 : 2 + size; +} + +static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s) throw() +{ + if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)) + { + unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize); + return (size == 0) ? 0 : kSuperUncPathPrefixSize + size; + } + // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\" + int pos = FindCharPosInString(s + kSuperPathPrefixSize, FCHAR_PATH_SEPARATOR); + if (pos < 0) + return 0; + return kSuperPathPrefixSize + pos + 1; +} + +unsigned GetRootPrefixSize(CFSTR s) throw() +{ + if (IS_DEVICE_PATH(s)) + return kDevicePathPrefixSize; + if (IsSuperPath(s)) + return GetRootPrefixSize_Of_SuperPath(s); + return GetRootPrefixSize_Of_SimplePath(s); +} + +#endif // USE_UNICODE_FSTRING + +static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) throw() +{ + // Network path: we look "server\path\" as root prefix + int pos = FindCharPosInString(s, L'\\'); + if (pos < 0) + return 0; + int pos2 = FindCharPosInString(s + pos + 1, L'\\'); + if (pos2 < 0) + return 0; + return pos + pos2 + 2; +} + +static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s) throw() +{ + if (IsDrivePath(s)) + return kDrivePrefixSize; + if (s[0] != '\\' || s[1] != '\\') + return 0; + unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2); + return (size == 0) ? 0 : 2 + size; +} + +static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) throw() +{ + if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)) + { + unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize); + return (size == 0) ? 0 : kSuperUncPathPrefixSize + size; + } + // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\" + int pos = FindCharPosInString(s + kSuperPathPrefixSize, L'\\'); + if (pos < 0) + return 0; + return kSuperPathPrefixSize + pos + 1; +} + +unsigned GetRootPrefixSize(const wchar_t *s) throw() +{ + if (IS_DEVICE_PATH(s)) + return kDevicePathPrefixSize; + if (IsSuperPath(s)) + return GetRootPrefixSize_Of_SuperPath(s); + return GetRootPrefixSize_Of_SimplePath(s); +} + +#else // _WIN32 + +bool IsAbsolutePath(const wchar_t *s) throw() { return s[0] == WCHAR_PATH_SEPARATOR } + +#ifndef USE_UNICODE_FSTRING +unsigned GetRootPrefixSize(CFSTR s) throw() { return s[0] == CHAR_PATH_SEPRATOR ? 1 : 0; } +#endif +unsigned GetRootPrefixSize(const wchar_t *s) throw() { return s[0] == CHAR_PATH_SEPRATOR ? 1 : 0; } + +#endif // _WIN32 + + +#ifndef UNDER_CE + +static bool GetCurDir(UString &path) +{ + path.Empty(); + DWORD needLength; + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetCurrentDirectory(MAX_PATH + 1, s); + path = fs2us(fas2fs(s)); + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, s); + path = s; + } + return (needLength > 0 && needLength <= MAX_PATH); +} + +static bool ResolveDotsFolders(UString &s) +{ + #ifdef _WIN32 + s.Replace(L'/', WCHAR_PATH_SEPARATOR); + #endif + for (int i = 0;;) + { + wchar_t c = s[i]; + if (c == 0) + return true; + if (c == '.' && (i == 0 || s[i - 1] == WCHAR_PATH_SEPARATOR)) + { + wchar_t c1 = s[i + 1]; + if (c1 == '.') + { + wchar_t c2 = s[i + 2]; + if (c2 == WCHAR_PATH_SEPARATOR || c2 == 0) + { + if (i == 0) + return false; + int k = i - 2; + for (; k >= 0; k--) + if (s[k] == WCHAR_PATH_SEPARATOR) + break; + unsigned num; + if (k >= 0) + { + num = i + 2 - k; + i = k; + } + else + { + num = (c2 == 0 ? (i + 2) : (i + 3)); + i = 0; + } + s.Delete(i, num); + continue; + } + } + else + { + if (c1 == WCHAR_PATH_SEPARATOR || c1 == 0) + { + unsigned num = 2; + if (i != 0) + i--; + else if (c1 == 0) + num = 1; + s.Delete(i, num); + continue; + } + } + } + i++; + } +} + +#endif // UNDER_CE + +#define LONG_PATH_DOTS_FOLDERS_PARSING + + +/* +Windows (at least 64-bit XP) can't resolve "." or ".." in paths that start with SuperPrefix \\?\ +To solve that problem we check such path: + - super path contains "." or ".." - we use kSuperPathType_UseOnlySuper + - super path doesn't contain "." or ".." - we use kSuperPathType_UseOnlyMain +*/ +#ifdef LONG_PATH_DOTS_FOLDERS_PARSING +#ifndef UNDER_CE +static bool AreThereDotsFolders(CFSTR s) +{ + for (unsigned i = 0;; i++) + { + FChar c = s[i]; + if (c == 0) + return false; + if (c == '.' && (i == 0 || s[i - 1] == CHAR_PATH_SEPARATOR)) + { + FChar c1 = s[i + 1]; + if (c1 == 0 || c1 == CHAR_PATH_SEPARATOR || + (c1 == '.' && (s[i + 2] == 0 || s[i + 2] == CHAR_PATH_SEPARATOR))) + return true; + } + } } #endif +#endif // LONG_PATH_DOTS_FOLDERS_PARSING + +#ifdef WIN_LONG_PATH + +/* +Most of Windows versions have problems, if some file or dir name +contains '.' or ' ' at the end of name (Bad Path). +To solve that problem, we always use Super Path ("\\?\" prefix and full path) +in such cases. Note that "." and ".." are not bad names. + +There are 3 cases: + 1) If the path is already Super Path, we use that path + 2) If the path is not Super Path : + 2.1) Bad Path; we use only Super Path. + 2.2) Good Path; we use Main Path. If it fails, we use Super Path. + + NeedToUseOriginalPath returns: + kSuperPathType_UseOnlyMain : Super already + kSuperPathType_UseOnlySuper : not Super, Bad Path + kSuperPathType_UseMainAndSuper : not Super, Good Path +*/ + +int GetUseSuperPathType(CFSTR s) throw() +{ + if (IsSuperOrDevicePath(s)) + { + #ifdef LONG_PATH_DOTS_FOLDERS_PARSING + if ((s)[2] != '.') + if (AreThereDotsFolders(s + kSuperPathPrefixSize)) + return kSuperPathType_UseOnlySuper; + #endif + return kSuperPathType_UseOnlyMain; + } + + for (unsigned i = 0;; i++) + { + FChar c = s[i]; + if (c == 0) + return kSuperPathType_UseMainAndSuper; + if (c == '.' || c == ' ') + { + FChar c2 = s[i + 1]; + if (c2 == 0 || c2 == CHAR_PATH_SEPARATOR) + { + // if it's "." or "..", it's not bad name. + if (c == '.') + { + if (i == 0 || s[i - 1] == CHAR_PATH_SEPARATOR) + continue; + if (s[i - 1] == '.') + { + if (i - 1 == 0 || s[i - 2] == CHAR_PATH_SEPARATOR) + continue; + } + } + return kSuperPathType_UseOnlySuper; + } + } + } +} + + +/* + returns false in two cases: + - if GetCurDir was used, and GetCurDir returned error. + - if we can't resolve ".." name. + if path is ".", "..", res is empty. + if it's Super Path already, res is empty. + for \**** , and if GetCurDir is not drive (c:\), res is empty + for absolute paths, returns true, res is Super path. +*/ + + +static bool GetSuperPathBase(CFSTR s, UString &res) +{ + res.Empty(); + + FChar c = s[0]; + if (c == 0) + return true; + if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0))) + return true; + + if (IsSuperOrDevicePath(s)) + { + #ifdef LONG_PATH_DOTS_FOLDERS_PARSING + + if ((s)[2] == '.') + return true; + + // we will return true here, so we will try to use these problem paths. + + if (!AreThereDotsFolders(s + kSuperPathPrefixSize)) + return true; + + UString temp = fs2us(s); + unsigned fixedSize = GetRootPrefixSize_Of_SuperPath(temp); + if (fixedSize == 0) + return true; + + UString rem = &temp[fixedSize]; + if (!ResolveDotsFolders(rem)) + return true; + + temp.DeleteFrom(fixedSize); + res += temp; + res += rem; + + #endif + + return true; + } + + if (c == CHAR_PATH_SEPARATOR) + { + if (s[1] == CHAR_PATH_SEPARATOR) + { + UString temp = fs2us(s + 2); + unsigned fixedSize = GetRootPrefixSize_Of_NetworkPath(temp); + if (fixedSize == 0) // maybe we must ignore that error to allow short network paths? + return false; + UString rem = &temp[fixedSize]; + if (!ResolveDotsFolders(rem)) + return false; + res += kSuperUncPrefix; + temp.DeleteFrom(fixedSize); + res += temp; + res += rem; + return true; + } + } + else + { + if (IsDrivePath(s)) + { + UString temp = fs2us(s); + UString rem = &temp[kDrivePrefixSize]; + if (!ResolveDotsFolders(rem)) + return true; + res += kSuperPathPrefix; + temp.DeleteFrom(kDrivePrefixSize); + res += temp; + res += rem; + return true; + } + } + + UString curDir; + if (!GetCurDir(curDir)) + return false; + if (curDir.Back() != WCHAR_PATH_SEPARATOR) + curDir += WCHAR_PATH_SEPARATOR; + + unsigned fixedSizeStart = 0; + unsigned fixedSize = 0; + const wchar_t *superMarker = NULL; + if (IsSuperPath(curDir)) + { + fixedSize = GetRootPrefixSize_Of_SuperPath(curDir); + if (fixedSize == 0) + return false; + } + else + { + if (IsDrivePath(curDir)) + { + superMarker = kSuperPathPrefix; + fixedSize = kDrivePrefixSize; + } + else + { + if (curDir[0] != CHAR_PATH_SEPARATOR || curDir[1] != CHAR_PATH_SEPARATOR) + return false; + fixedSizeStart = 2; + fixedSize = GetRootPrefixSize_Of_NetworkPath(&curDir[2]); + if (fixedSize == 0) + return false; + superMarker = kSuperUncPrefix; + } + } + + UString temp; + if (c == CHAR_PATH_SEPARATOR) + { + temp = fs2us(s + 1); + } + else + { + temp += &curDir[fixedSizeStart + fixedSize]; + temp += fs2us(s); + } + if (!ResolveDotsFolders(temp)) + return false; + if (superMarker) + res += superMarker; + res += curDir.Mid(fixedSizeStart, fixedSize); + res += temp; + return true; +} + -const wchar_t kExtensionDelimiter = L'.'; +/* + In that case if GetSuperPathBase doesn't return new path, we don't need + to use same path that was used as main path -void SplitNameToPureNameAndExtension(const UString &fullName, - UString &pureName, UString &extensionDelimiter, UString &extension) + GetSuperPathBase superPath.IsEmpty() onlyIfNew + false * * GetCurDir Error + true false * use Super path + true true true don't use any path, we already used mainPath + true true false use main path as Super Path, we don't try mainMath + That case is possible now if GetCurDir returns unknow + type of path (not drive and not network) + + We can change that code if we want to try mainPath, if GetSuperPathBase returns error, + and we didn't try mainPath still. + If we want to work that way, we don't need to use GetSuperPathBase return code. +*/ + +bool GetSuperPath(CFSTR path, UString &superPath, bool onlyIfNew) +{ + if (GetSuperPathBase(path, superPath)) + { + if (superPath.IsEmpty()) + { + // actually the only possible when onlyIfNew == true and superPath is empty + // is case when + + if (onlyIfNew) + return false; + superPath = fs2us(path); + } + return true; + } + return false; +} + +bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew) +{ + if (!GetSuperPathBase(s1, d1) || + !GetSuperPathBase(s2, d2)) + return false; + if (d1.IsEmpty() && d2.IsEmpty() && onlyIfNew) + return false; + if (d1.IsEmpty()) d1 = fs2us(s1); + if (d2.IsEmpty()) d2 = fs2us(s2); + return true; +} + + +/* +// returns true, if we need additional use with New Super path. +bool GetSuperPath(CFSTR path, UString &superPath) +{ + if (GetSuperPathBase(path, superPath)) + return !superPath.IsEmpty(); + return false; +} +*/ +#endif // WIN_LONG_PATH + +bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res) { - int index = fullName.ReverseFind(kExtensionDelimiter); - if (index < 0) + res = s; + + #ifdef UNDER_CE + + if (s[0] != CHAR_PATH_SEPARATOR) + { + if (!dirPrefix) + return false; + res = dirPrefix; + res += s; + } + + #else + + unsigned prefixSize = GetRootPrefixSize(s); + if (prefixSize != 0) + { + if (!AreThereDotsFolders(s + prefixSize)) + return true; + + UString rem = fs2us(s + prefixSize); + if (!ResolveDotsFolders(rem)) + return true; // maybe false; + res.DeleteFrom(prefixSize); + res += us2fs(rem); + return true; + } + + /* + FChar c = s[0]; + if (c == 0) + return true; + if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0))) + return true; + if (c == CHAR_PATH_SEPARATOR && s[1] == CHAR_PATH_SEPARATOR) + return true; + if (IsDrivePath(s)) + return true; + */ + + UString curDir; + if (dirPrefix) + curDir = fs2us(dirPrefix); + else + { + if (!GetCurDir(curDir)) + return false; + } + if (!curDir.IsEmpty() && curDir.Back() != WCHAR_PATH_SEPARATOR) + curDir += WCHAR_PATH_SEPARATOR; + + unsigned fixedSize = 0; + + #ifdef _WIN32 + + if (IsSuperPath(curDir)) + { + fixedSize = GetRootPrefixSize_Of_SuperPath(curDir); + if (fixedSize == 0) + return false; + } + else + { + if (IsDrivePath(curDir)) + fixedSize = kDrivePrefixSize; + else + { + if (curDir[0] != WCHAR_PATH_SEPARATOR || curDir[1] != WCHAR_PATH_SEPARATOR) + return false; + fixedSize = GetRootPrefixSize_Of_NetworkPath(&curDir[2]); + if (fixedSize == 0) + return false; + fixedSize += 2; + } + } + + #endif // _WIN32 + + UString temp; + if (s[0] == CHAR_PATH_SEPARATOR) { - pureName = fullName; - extensionDelimiter.Empty(); - extension.Empty(); + temp = fs2us(s + 1); } else { - pureName = fullName.Left(index); - extensionDelimiter = kExtensionDelimiter; - extension = fullName.Mid(index + 1); + temp += curDir.Ptr(fixedSize); + temp += fs2us(s); } + if (!ResolveDotsFolders(temp)) + return false; + curDir.DeleteFrom(fixedSize); + res = us2fs(curDir); + res += us2fs(temp); + + #endif // UNDER_CE + + return true; +} + +bool GetFullPath(CFSTR path, FString &fullPath) +{ + return GetFullPath(NULL, path, fullPath); } }}} diff --git a/src/libs/7zip/win/CPP/Windows/FileName.h b/src/libs/7zip/win/CPP/Windows/FileName.h index d98079026..04fc79b2d 100644 --- a/src/libs/7zip/win/CPP/Windows/FileName.h +++ b/src/libs/7zip/win/CPP/Windows/FileName.h @@ -1,9 +1,7 @@ // Windows/FileName.h -#ifndef __WINDOWS_FILENAME_H -#define __WINDOWS_FILENAME_H - -#include "../../C/Types.h" +#ifndef __WINDOWS_FILE_NAME_H +#define __WINDOWS_FILE_NAME_H #include "../Common/MyString.h" @@ -11,16 +9,65 @@ namespace NWindows { namespace NFile { namespace NName { -const TCHAR kDirDelimiter = CHAR_PATH_SEPARATOR; -const TCHAR kAnyStringWildcard = '*'; +void NormalizeDirPathPrefix(FString &dirPath); // ensures that it ended with '\\', if dirPath is not epmty +void NormalizeDirPathPrefix(UString &dirPath); + +#ifdef _WIN32 + +extern const wchar_t *kSuperPathPrefix; /* \\?\ */ +const unsigned kDevicePathPrefixSize = 4; +const unsigned kSuperPathPrefixSize = 4; +const unsigned kSuperUncPathPrefixSize = kSuperPathPrefixSize + 4; + +bool IsDevicePath(CFSTR s) throw(); /* \\.\ */ +bool IsSuperUncPath(CFSTR s) throw(); -void NormalizeDirPathPrefix(CSysString &dirPath); // ensures that it ended with '\\' -#ifndef _UNICODE -void NormalizeDirPathPrefix(UString &dirPath); // ensures that it ended with '\\' +bool IsDrivePath(const wchar_t *s) throw(); +bool IsSuperPath(const wchar_t *s) throw(); +bool IsSuperOrDevicePath(const wchar_t *s) throw(); + +#ifndef USE_UNICODE_FSTRING +bool IsDrivePath(CFSTR s) throw(); +bool IsSuperPath(CFSTR s) throw(); +bool IsSuperOrDevicePath(CFSTR s) throw(); #endif -void SplitNameToPureNameAndExtension(const UString &fullName, - UString &pureName, UString &extensionDelimiter, UString &extension); +#endif // _WIN32 + +bool IsAbsolutePath(const wchar_t *s) throw(); +unsigned GetRootPrefixSize(const wchar_t *s) throw(); + +#ifdef WIN_LONG_PATH + +const int kSuperPathType_UseOnlyMain = 0; +const int kSuperPathType_UseOnlySuper = 1; +const int kSuperPathType_UseMainAndSuper = 2; + +int GetUseSuperPathType(CFSTR s) throw(); +bool GetSuperPath(CFSTR path, UString &longPath, bool onlyIfNew); +bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew); + +#define USE_MAIN_PATH (__useSuperPathType != kSuperPathType_UseOnlySuper) +#define USE_MAIN_PATH_2 (__useSuperPathType1 != kSuperPathType_UseOnlySuper && __useSuperPathType2 != kSuperPathType_UseOnlySuper) + +#define USE_SUPER_PATH (__useSuperPathType != kSuperPathType_UseOnlyMain) +#define USE_SUPER_PATH_2 (__useSuperPathType1 != kSuperPathType_UseOnlyMain || __useSuperPathType2 != kSuperPathType_UseOnlyMain) + +#define IF_USE_MAIN_PATH int __useSuperPathType = GetUseSuperPathType(path); if (USE_MAIN_PATH) +#define IF_USE_MAIN_PATH_2(x1, x2) \ + int __useSuperPathType1 = GetUseSuperPathType(x1); \ + int __useSuperPathType2 = GetUseSuperPathType(x2); \ + if (USE_MAIN_PATH_2) + +#else + +#define IF_USE_MAIN_PATH +#define IF_USE_MAIN_PATH_2(x1, x2) + +#endif // WIN_LONG_PATH + +bool GetFullPath(CFSTR dirPrefix, CFSTR path, FString &fullPath); +bool GetFullPath(CFSTR path, FString &fullPath); }}} diff --git a/src/libs/7zip/win/CPP/Windows/MemoryLock.cpp b/src/libs/7zip/win/CPP/Windows/MemoryLock.cpp deleted file mode 100644 index e0f430996..000000000 --- a/src/libs/7zip/win/CPP/Windows/MemoryLock.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// Common/MemoryLock.cpp - -#include "StdAfx.h" - -namespace NWindows { -namespace NSecurity { - -#ifndef UNDER_CE - -#ifndef _UNICODE -typedef BOOL (WINAPI * OpenProcessTokenP)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle); -typedef BOOL (WINAPI * LookupPrivilegeValueP)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID lpLuid); -typedef BOOL (WINAPI * AdjustTokenPrivilegesP)(HANDLE TokenHandle, BOOL DisableAllPrivileges, - PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState,PDWORD ReturnLength); -#endif - -#ifdef _UNICODE -bool EnableLockMemoryPrivilege( -#else -static bool EnableLockMemoryPrivilege2(HMODULE hModule, -#endif -bool enable) -{ - #ifndef _UNICODE - if (hModule == NULL) - return false; - OpenProcessTokenP openProcessToken = (OpenProcessTokenP)GetProcAddress(hModule, "OpenProcessToken"); - LookupPrivilegeValueP lookupPrivilegeValue = (LookupPrivilegeValueP)GetProcAddress(hModule, "LookupPrivilegeValueA" ); - AdjustTokenPrivilegesP adjustTokenPrivileges = (AdjustTokenPrivilegesP)GetProcAddress(hModule, "AdjustTokenPrivileges"); - if (openProcessToken == NULL || adjustTokenPrivileges == NULL || lookupPrivilegeValue == NULL) - return false; - #endif - - HANDLE token; - if (! - #ifdef _UNICODE - ::OpenProcessToken - #else - openProcessToken - #endif - (::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) - return false; - TOKEN_PRIVILEGES tp; - bool res = false; - if ( - #ifdef _UNICODE - ::LookupPrivilegeValue - #else - lookupPrivilegeValue - #endif - (NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid))) - { - tp.PrivilegeCount = 1; - tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED: 0; - if ( - #ifdef _UNICODE - ::AdjustTokenPrivileges - #else - adjustTokenPrivileges - #endif - (token, FALSE, &tp, 0, NULL, NULL)) - res = (GetLastError() == ERROR_SUCCESS); - } - ::CloseHandle(token); - return res; -} - -#ifndef _UNICODE -bool EnableLockMemoryPrivilege(bool enable) -{ - HMODULE hModule = LoadLibrary(TEXT("Advapi32.dll")); - if (hModule == NULL) - return false; - bool res = EnableLockMemoryPrivilege2(hModule, enable); - ::FreeLibrary(hModule); - return res; -} -#endif - -#endif - -}} diff --git a/src/libs/7zip/win/CPP/Windows/MemoryLock.h b/src/libs/7zip/win/CPP/Windows/MemoryLock.h deleted file mode 100644 index 5fe619de0..000000000 --- a/src/libs/7zip/win/CPP/Windows/MemoryLock.h +++ /dev/null @@ -1,15 +0,0 @@ -// Windows/MemoryLock.h - -#ifndef __WINDOWS_MEMORYLOCK_H -#define __WINDOWS_MEMORYLOCK_H - -namespace NWindows { -namespace NSecurity { - -#ifndef UNDER_CE -bool EnableLockMemoryPrivilege(bool enable = true); -#endif - -}} - -#endif diff --git a/src/libs/7zip/win/CPP/Windows/NtCheck.h b/src/libs/7zip/win/CPP/Windows/NtCheck.h deleted file mode 100644 index e56318f00..000000000 --- a/src/libs/7zip/win/CPP/Windows/NtCheck.h +++ /dev/null @@ -1,44 +0,0 @@ -// Windows/NtCheck.h - -#ifndef __WINDOWS_NT_CHECK_H -#define __WINDOWS_NT_CHECK_H - -#ifdef _WIN32 - -#if !defined(_WIN64) && !defined(UNDER_CE) -static inline bool IsItWindowsNT() -{ - OSVERSIONINFO vi; - vi.dwOSVersionInfoSize = sizeof(vi); - return (::GetVersionEx(&vi) && vi.dwPlatformId == VER_PLATFORM_WIN32_NT); -} -#endif - -#ifndef _UNICODE - #if defined(_WIN64) || defined(UNDER_CE) - bool g_IsNT = true; - #define SET_IS_NT - #else - bool g_IsNT = false; - #define SET_IS_NT g_IsNT = IsItWindowsNT(); - #endif - #define NT_CHECK_ACTION - // #define NT_CHECK_ACTION { NT_CHECK_FAIL_ACTION } -#else - #if !defined(_WIN64) && !defined(UNDER_CE) - #define NT_CHECK_ACTION if (!IsItWindowsNT()) { NT_CHECK_FAIL_ACTION } - #else - #define NT_CHECK_ACTION - #endif - #define SET_IS_NT -#endif - -#define NT_CHECK NT_CHECK_ACTION SET_IS_NT - -#else - -#define NT_CHECK - -#endif - -#endif diff --git a/src/libs/7zip/win/CPP/Windows/PropVariant.cpp b/src/libs/7zip/win/CPP/Windows/PropVariant.cpp index 90212e08f..d16f576cc 100644 --- a/src/libs/7zip/win/CPP/Windows/PropVariant.cpp +++ b/src/libs/7zip/win/CPP/Windows/PropVariant.cpp @@ -2,13 +2,43 @@ #include "StdAfx.h" -#include "PropVariant.h" - #include "../Common/Defs.h" +#include "PropVariant.h" + namespace NWindows { namespace NCOM { +HRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw() +{ + p->bstrVal = ::SysAllocStringLen(0, numChars); + if (!p->bstrVal) + { + p->vt = VT_ERROR; + p->scode = E_OUTOFMEMORY; + return E_OUTOFMEMORY; + } + p->vt = VT_BSTR; + return S_OK; +} + +HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw() +{ + UINT len = (UINT)strlen(s); + p->bstrVal = ::SysAllocStringLen(0, len); + if (!p->bstrVal) + { + p->vt = VT_ERROR; + p->scode = E_OUTOFMEMORY; + return E_OUTOFMEMORY; + } + p->vt = VT_BSTR; + BSTR dest = p->bstrVal; + for (UINT i = 0; i <= len; i++) + dest[i] = s[i]; + return S_OK; +} + CPropVariant::CPropVariant(const PROPVARIANT &varSrc) { vt = VT_EMPTY; @@ -58,7 +88,7 @@ CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) vt = VT_BSTR; wReserved1 = 0; bstrVal = ::SysAllocString(lpszSrc); - if (bstrVal == NULL && lpszSrc != NULL) + if (!bstrVal && lpszSrc) { throw kMemException; // vt = VT_ERROR; @@ -67,15 +97,14 @@ CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) return *this; } - CPropVariant& CPropVariant::operator=(const char *s) { InternalClear(); vt = VT_BSTR; wReserved1 = 0; UINT len = (UINT)strlen(s); - bstrVal = ::SysAllocStringByteLen(0, (UINT)len * sizeof(OLECHAR)); - if (bstrVal == NULL) + bstrVal = ::SysAllocStringLen(0, len); + if (!bstrVal) { throw kMemException; // vt = VT_ERROR; @@ -89,7 +118,7 @@ CPropVariant& CPropVariant::operator=(const char *s) return *this; } -CPropVariant& CPropVariant::operator=(bool bSrc) +CPropVariant& CPropVariant::operator=(bool bSrc) throw() { if (vt != VT_BOOL) { @@ -100,22 +129,40 @@ CPropVariant& CPropVariant::operator=(bool bSrc) return *this; } +BSTR CPropVariant::AllocBstr(unsigned numChars) +{ + if (vt != VT_EMPTY) + InternalClear(); + vt = VT_BSTR; + wReserved1 = 0; + bstrVal = ::SysAllocStringLen(0, numChars); + if (!bstrVal) + { + throw kMemException; + // vt = VT_ERROR; + // scode = E_OUTOFMEMORY; + } + return bstrVal; +} + #define SET_PROP_FUNC(type, id, dest) \ - CPropVariant& CPropVariant::operator=(type value) \ + CPropVariant& CPropVariant::operator=(type value) throw() \ { if (vt != id) { InternalClear(); vt = id; } \ dest = value; return *this; } SET_PROP_FUNC(Byte, VT_UI1, bVal) -SET_PROP_FUNC(Int16, VT_I2, iVal) +// SET_PROP_FUNC(Int16, VT_I2, iVal) SET_PROP_FUNC(Int32, VT_I4, lVal) SET_PROP_FUNC(UInt32, VT_UI4, ulVal) SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart) +SET_PROP_FUNC(Int64, VT_I8, hVal.QuadPart) SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime) -static HRESULT MyPropVariantClear(PROPVARIANT *prop) +HRESULT PropVariant_Clear(PROPVARIANT *prop) throw() { - switch(prop->vt) + switch (prop->vt) { + case VT_EMPTY: case VT_UI1: case VT_I1: case VT_I2: @@ -134,17 +181,24 @@ static HRESULT MyPropVariantClear(PROPVARIANT *prop) case VT_DATE: prop->vt = VT_EMPTY; prop->wReserved1 = 0; + prop->wReserved2 = 0; + prop->wReserved3 = 0; + prop->uhVal.QuadPart = 0; return S_OK; } return ::VariantClear((VARIANTARG *)prop); + // return ::PropVariantClear(prop); + // PropVariantClear can clear VT_BLOB. } -HRESULT CPropVariant::Clear() +HRESULT CPropVariant::Clear() throw() { - return MyPropVariantClear(this); + if (vt == VT_EMPTY) + return S_OK; + return PropVariant_Clear(this); } -HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) +HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) throw() { ::VariantClear((tagVARIANT *)this); switch(pSrc->vt) @@ -172,7 +226,7 @@ HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) } -HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) +HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) throw() { HRESULT hr = Clear(); if (FAILED(hr)) @@ -182,18 +236,23 @@ HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) return S_OK; } -HRESULT CPropVariant::Detach(PROPVARIANT *pDest) +HRESULT CPropVariant::Detach(PROPVARIANT *pDest) throw() { - HRESULT hr = MyPropVariantClear(pDest); - if (FAILED(hr)) - return hr; + if (pDest->vt != VT_EMPTY) + { + HRESULT hr = PropVariant_Clear(pDest); + if (FAILED(hr)) + return hr; + } memcpy(pDest, this, sizeof(PROPVARIANT)); vt = VT_EMPTY; return S_OK; } -HRESULT CPropVariant::InternalClear() +HRESULT CPropVariant::InternalClear() throw() { + if (vt == VT_EMPTY) + return S_OK; HRESULT hr = Clear(); if (FAILED(hr)) { @@ -215,7 +274,7 @@ void CPropVariant::InternalCopy(const PROPVARIANT *pSrc) } } -int CPropVariant::Compare(const CPropVariant &a) +int CPropVariant::Compare(const CPropVariant &a) throw() { if (vt != a.vt) return MyCompare(vt, a.vt); @@ -233,9 +292,7 @@ int CPropVariant::Compare(const CPropVariant &a) case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart); case VT_BOOL: return -MyCompare(boolVal, a.boolVal); case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime); - case VT_BSTR: - return 0; // Not implemented - // return MyCompare(aPropVarint.cVal); + case VT_BSTR: return 0; // Not implemented default: return 0; } } diff --git a/src/libs/7zip/win/CPP/Windows/PropVariant.h b/src/libs/7zip/win/CPP/Windows/PropVariant.h index d018034eb..d71b85e1d 100644 --- a/src/libs/7zip/win/CPP/Windows/PropVariant.h +++ b/src/libs/7zip/win/CPP/Windows/PropVariant.h @@ -1,29 +1,73 @@ // Windows/PropVariant.h -#ifndef __WINDOWS_PROPVARIANT_H -#define __WINDOWS_PROPVARIANT_H +#ifndef __WINDOWS_PROP_VARIANT_H +#define __WINDOWS_PROP_VARIANT_H +#include "../Common/MyTypes.h" #include "../Common/MyWindows.h" -#include "../Common/Types.h" namespace NWindows { namespace NCOM { +HRESULT PropVariant_Clear(PROPVARIANT *p) throw(); + +HRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw(); +HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw(); + +inline void PropVarEm_Set_UInt32(PROPVARIANT *p, UInt32 v) throw() +{ + p->vt = VT_UI4; + p->ulVal = v; +} + +inline void PropVarEm_Set_UInt64(PROPVARIANT *p, UInt64 v) throw() +{ + p->vt = VT_UI8; + p->uhVal.QuadPart = v; +} + +inline void PropVarEm_Set_FileTime64(PROPVARIANT *p, UInt64 v) throw() +{ + p->vt = VT_FILETIME; + p->filetime.dwLowDateTime = (DWORD)v; + p->filetime.dwHighDateTime = (DWORD)(v >> 32); +} + +inline void PropVarEm_Set_Bool(PROPVARIANT *p, bool b) throw() +{ + p->vt = VT_BOOL; + p->boolVal = (b ? VARIANT_TRUE : VARIANT_FALSE); +} + + class CPropVariant : public tagPROPVARIANT { public: - CPropVariant() { vt = VT_EMPTY; wReserved1 = 0; } - ~CPropVariant() { Clear(); } + CPropVariant() + { + vt = VT_EMPTY; + wReserved1 = 0; + // wReserved2 = 0; + // wReserved3 = 0; + // uhVal.QuadPart = 0; + bstrVal = 0; + } + ~CPropVariant() throw() { Clear(); } CPropVariant(const PROPVARIANT &varSrc); CPropVariant(const CPropVariant &varSrc); CPropVariant(BSTR bstrSrc); CPropVariant(LPCOLESTR lpszSrc); CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); }; CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; } - CPropVariant(Int16 value) { vt = VT_I2; wReserved1 = 0; iVal = value; } - CPropVariant(Int32 value) { vt = VT_I4; wReserved1 = 0; lVal = value; } + +private: + CPropVariant(Int16 value); // { vt = VT_I2; wReserved1 = 0; iVal = value; } + CPropVariant(Int32 value); // { vt = VT_I4; wReserved1 = 0; lVal = value; } + +public: CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; } CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal.QuadPart = value; } + CPropVariant(Int64 value) { vt = VT_I8; wReserved1 = 0; hVal.QuadPart = value; } CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; } CPropVariant& operator=(const CPropVariant &varSrc); @@ -31,24 +75,31 @@ public: CPropVariant& operator=(BSTR bstrSrc); CPropVariant& operator=(LPCOLESTR lpszSrc); CPropVariant& operator=(const char *s); - CPropVariant& operator=(bool bSrc); - CPropVariant& operator=(Byte value); - CPropVariant& operator=(Int16 value); - CPropVariant& operator=(Int32 value); - CPropVariant& operator=(UInt32 value); - CPropVariant& operator=(Int64 value); - CPropVariant& operator=(UInt64 value); - CPropVariant& operator=(const FILETIME &value); - - HRESULT Clear(); - HRESULT Copy(const PROPVARIANT *pSrc); - HRESULT Attach(PROPVARIANT *pSrc); - HRESULT Detach(PROPVARIANT *pDest); - - HRESULT InternalClear(); + + CPropVariant& operator=(bool bSrc) throw(); + CPropVariant& operator=(Byte value) throw(); + +private: + CPropVariant& operator=(Int16 value) throw(); + +public: + CPropVariant& operator=(Int32 value) throw(); + CPropVariant& operator=(UInt32 value) throw(); + CPropVariant& operator=(UInt64 value) throw(); + CPropVariant& operator=(Int64 value) throw(); + CPropVariant& operator=(const FILETIME &value) throw(); + + BSTR AllocBstr(unsigned numChars); + + HRESULT Clear() throw(); + HRESULT Copy(const PROPVARIANT *pSrc) throw(); + HRESULT Attach(PROPVARIANT *pSrc) throw(); + HRESULT Detach(PROPVARIANT *pDest) throw(); + + HRESULT InternalClear() throw(); void InternalCopy(const PROPVARIANT *pSrc); - int Compare(const CPropVariant &a1); + int Compare(const CPropVariant &a) throw(); }; }} diff --git a/src/libs/7zip/win/CPP/Windows/PropVariantConv.cpp b/src/libs/7zip/win/CPP/Windows/PropVariantConv.cpp new file mode 100644 index 000000000..dfb93d6d6 --- /dev/null +++ b/src/libs/7zip/win/CPP/Windows/PropVariantConv.cpp @@ -0,0 +1,99 @@ +// PropVariantConvert.cpp + +#include "StdAfx.h" + +#include "../Common/IntToString.h" + +#include "Defs.h" +#include "PropVariantConv.h" + +#define UINT_TO_STR_2(c, val) { s[0] = (c); s[1] = (char)('0' + (val) / 10); s[2] = (char)('0' + (val) % 10); s += 3; } + +bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool includeSeconds) throw() +{ + SYSTEMTIME st; + if (!BOOLToBool(FileTimeToSystemTime(&ft, &st))) + { + *s = 0; + return false; + } + unsigned val = st.wYear; + if (val >= 10000) + { + *s++ = (char)('0' + val / 10000); + val %= 10000; + } + { + s[3] = (char)('0' + val % 10); val /= 10; + s[2] = (char)('0' + val % 10); val /= 10; + s[1] = (char)('0' + val % 10); + s[0] = (char)('0' + val / 10); + s += 4; + } + UINT_TO_STR_2('-', st.wMonth); + UINT_TO_STR_2('-', st.wDay); + if (includeTime) + { + UINT_TO_STR_2(' ', st.wHour); + UINT_TO_STR_2(':', st.wMinute); + if (includeSeconds) + UINT_TO_STR_2(':', st.wSecond); + } + *s = 0; + return true; +} + +void ConvertFileTimeToString(const FILETIME &ft, wchar_t *dest, bool includeTime, bool includeSeconds) throw() +{ + char s[32]; + ConvertFileTimeToString(ft, s, includeTime, includeSeconds); + for (unsigned i = 0;; i++) + { + unsigned char c = s[i]; + dest[i] = c; + if (c == 0) + return; + } +} + +void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw() +{ + *dest = 0; + switch (prop.vt) + { + case VT_EMPTY: return; + case VT_BSTR: dest[0] = '?'; dest[1] = 0; return; + case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return; + case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return; + case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return; + case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return; + case VT_FILETIME: ConvertFileTimeToString(prop.filetime, dest, true, true); return; + // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return; + case VT_I2: ConvertInt64ToString(prop.iVal, dest); return; + case VT_I4: ConvertInt64ToString(prop.lVal, dest); return; + case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return; + case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? '+' : '-'; dest[1] = 0; return; + default: dest[0] = '?'; dest[1] = ':'; ConvertUInt64ToString(prop.vt, dest + 2); + } +} + +void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) throw() +{ + *dest = 0; + switch (prop.vt) + { + case VT_EMPTY: return; + case VT_BSTR: dest[0] = '?'; dest[1] = 0; return; + case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return; + case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return; + case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return; + case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return; + case VT_FILETIME: ConvertFileTimeToString(prop.filetime, dest, true, true); return; + // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return; + case VT_I2: ConvertInt64ToString(prop.iVal, dest); return; + case VT_I4: ConvertInt64ToString(prop.lVal, dest); return; + case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return; + case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? '+' : '-'; dest[1] = 0; return; + default: dest[0] = '?'; dest[1] = ':'; ConvertUInt32ToString(prop.vt, dest + 2); + } +} diff --git a/src/libs/7zip/win/CPP/Windows/PropVariantConv.h b/src/libs/7zip/win/CPP/Windows/PropVariantConv.h new file mode 100644 index 000000000..5d26357f0 --- /dev/null +++ b/src/libs/7zip/win/CPP/Windows/PropVariantConv.h @@ -0,0 +1,30 @@ +// Windows/PropVariantConv.h + +#ifndef __PROP_VARIANT_CONV_H +#define __PROP_VARIANT_CONV_H + +#include "../Common/MyTypes.h" + +// provide at least 32 bytes for buffer including zero-end +bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime = true, bool includeSeconds = true) throw(); +void ConvertFileTimeToString(const FILETIME &ft, wchar_t *s, bool includeTime = true, bool includeSeconds = true) throw(); + +// provide at least 32 bytes for buffer including zero-end +// don't send VT_BSTR to these functions +void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw(); +void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) throw(); + +inline bool ConvertPropVariantToUInt64(const PROPVARIANT &prop, UInt64 &value) +{ + switch (prop.vt) + { + case VT_UI8: value = (UInt64)prop.uhVal.QuadPart; return true; + case VT_UI4: value = prop.ulVal; return true; + case VT_UI2: value = prop.uiVal; return true; + case VT_UI1: value = prop.bVal; return true; + case VT_EMPTY: return false; + default: throw 151199; + } +} + +#endif diff --git a/src/libs/7zip/win/CPP/Windows/PropVariantConversions.cpp b/src/libs/7zip/win/CPP/Windows/PropVariantConversions.cpp deleted file mode 100644 index 2d8456cd6..000000000 --- a/src/libs/7zip/win/CPP/Windows/PropVariantConversions.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// PropVariantConversions.cpp - -#include "StdAfx.h" - -#include "Common/IntToString.h" -#include "Common/StringConvert.h" - -#include "Windows/Defs.h" - -#include "PropVariantConversions.h" - -static UString ConvertUInt64ToString(UInt64 value) -{ - wchar_t buffer[32]; - ConvertUInt64ToString(value, buffer); - return buffer; -} - -static UString ConvertInt64ToString(Int64 value) -{ - wchar_t buffer[32]; - ConvertInt64ToString(value, buffer); - return buffer; -} - -static char *UIntToStringSpec(char c, UInt32 value, char *s, int numPos) -{ - if (c != 0) - *s++ = c; - char temp[16]; - int pos = 0; - do - { - temp[pos++] = (char)('0' + value % 10); - value /= 10; - } - while (value != 0); - int i; - for (i = 0; i < numPos - pos; i++) - *s++ = '0'; - do - *s++ = temp[--pos]; - while (pos > 0); - *s = '\0'; - return s; -} - -bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool includeSeconds) -{ - s[0] = '\0'; - SYSTEMTIME st; - if (!BOOLToBool(FileTimeToSystemTime(&ft, &st))) - return false; - s = UIntToStringSpec(0, st.wYear, s, 4); - s = UIntToStringSpec('-', st.wMonth, s, 2); - s = UIntToStringSpec('-', st.wDay, s, 2); - if (includeTime) - { - s = UIntToStringSpec(' ', st.wHour, s, 2); - s = UIntToStringSpec(':', st.wMinute, s, 2); - if (includeSeconds) - UIntToStringSpec(':', st.wSecond, s, 2); - } - return true; -} - -UString ConvertFileTimeToString(const FILETIME &ft, bool includeTime, bool includeSeconds) -{ - char s[32]; - ConvertFileTimeToString(ft, s, includeTime, includeSeconds); - return GetUnicodeString(s); -} - - -UString ConvertPropVariantToString(const PROPVARIANT &prop) -{ - switch (prop.vt) - { - case VT_EMPTY: return UString(); - case VT_BSTR: return prop.bstrVal; - case VT_UI1: return ConvertUInt64ToString(prop.bVal); - case VT_UI2: return ConvertUInt64ToString(prop.uiVal); - case VT_UI4: return ConvertUInt64ToString(prop.ulVal); - case VT_UI8: return ConvertUInt64ToString(prop.uhVal.QuadPart); - case VT_FILETIME: return ConvertFileTimeToString(prop.filetime, true, true); - // case VT_I1: return ConvertInt64ToString(prop.cVal); - case VT_I2: return ConvertInt64ToString(prop.iVal); - case VT_I4: return ConvertInt64ToString(prop.lVal); - case VT_I8: return ConvertInt64ToString(prop.hVal.QuadPart); - case VT_BOOL: return VARIANT_BOOLToBool(prop.boolVal) ? L"+" : L"-"; - default: throw 150245; - } -} - -UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &prop) -{ - switch (prop.vt) - { - case VT_UI1: return prop.bVal; - case VT_UI2: return prop.uiVal; - case VT_UI4: return prop.ulVal; - case VT_UI8: return (UInt64)prop.uhVal.QuadPart; - default: throw 151199; - } -} diff --git a/src/libs/7zip/win/CPP/Windows/PropVariantConversions.h b/src/libs/7zip/win/CPP/Windows/PropVariantConversions.h deleted file mode 100644 index 3de4dedb3..000000000 --- a/src/libs/7zip/win/CPP/Windows/PropVariantConversions.h +++ /dev/null @@ -1,14 +0,0 @@ -// Windows/PropVariantConversions.h - -#ifndef __PROP_VARIANT_CONVERSIONS_H -#define __PROP_VARIANT_CONVERSIONS_H - -#include "Common/MyString.h" -#include "Common/Types.h" - -bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime = true, bool includeSeconds = true); -UString ConvertFileTimeToString(const FILETIME &ft, bool includeTime = true, bool includeSeconds = true); -UString ConvertPropVariantToString(const PROPVARIANT &prop); -UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &prop); - -#endif diff --git a/src/libs/7zip/win/CPP/Windows/Registry.cpp b/src/libs/7zip/win/CPP/Windows/Registry.cpp deleted file mode 100644 index 8b25375d9..000000000 --- a/src/libs/7zip/win/CPP/Windows/Registry.cpp +++ /dev/null @@ -1,369 +0,0 @@ -// Windows/Registry.cpp - -#include "StdAfx.h" - -#ifndef _UNICODE -#include "Common/StringConvert.h" -#endif -#include "Windows/Registry.h" - -#ifndef _UNICODE -extern bool g_IsNT; -#endif - -namespace NWindows { -namespace NRegistry { - -#define MYASSERT(expr) // _ASSERTE(expr) - -LONG CKey::Create(HKEY parentKey, LPCTSTR keyName, - LPTSTR keyClass, DWORD options, REGSAM accessMask, - LPSECURITY_ATTRIBUTES securityAttributes, LPDWORD disposition) -{ - MYASSERT(parentKey != NULL); - DWORD dispositionReal; - HKEY key = NULL; - LONG res = RegCreateKeyEx(parentKey, keyName, 0, keyClass, - options, accessMask, securityAttributes, &key, &dispositionReal); - if (disposition != NULL) - *disposition = dispositionReal; - if (res == ERROR_SUCCESS) - { - res = Close(); - _object = key; - } - return res; -} - -LONG CKey::Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask) -{ - MYASSERT(parentKey != NULL); - HKEY key = NULL; - LONG res = RegOpenKeyEx(parentKey, keyName, 0, accessMask, &key); - if (res == ERROR_SUCCESS) - { - res = Close(); - MYASSERT(res == ERROR_SUCCESS); - _object = key; - } - return res; -} - -LONG CKey::Close() -{ - LONG res = ERROR_SUCCESS; - if (_object != NULL) - { - res = RegCloseKey(_object); - _object = NULL; - } - return res; -} - -// win95, win98: deletes sunkey and all its subkeys -// winNT to be deleted must not have subkeys -LONG CKey::DeleteSubKey(LPCTSTR subKeyName) -{ - MYASSERT(_object != NULL); - return RegDeleteKey(_object, subKeyName); -} - -LONG CKey::RecurseDeleteKey(LPCTSTR subKeyName) -{ - CKey key; - LONG res = key.Open(_object, subKeyName, KEY_READ | KEY_WRITE); - if (res != ERROR_SUCCESS) - return res; - FILETIME fileTime; - const UInt32 kBufferSize = MAX_PATH + 1; // 256 in ATL - DWORD size = kBufferSize; - TCHAR buffer[kBufferSize]; - while (RegEnumKeyEx(key._object, 0, buffer, &size, NULL, NULL, NULL, &fileTime) == ERROR_SUCCESS) - { - res = key.RecurseDeleteKey(buffer); - if (res != ERROR_SUCCESS) - return res; - size = kBufferSize; - } - key.Close(); - return DeleteSubKey(subKeyName); -} - - -///////////////////////// -// Value Functions - -static inline UInt32 BoolToUINT32(bool value) { return (value ? 1: 0); } -static inline bool UINT32ToBool(UInt32 value) { return (value != 0); } - - -LONG CKey::DeleteValue(LPCTSTR name) -{ - MYASSERT(_object != NULL); - return ::RegDeleteValue(_object, name); -} - -#ifndef _UNICODE -LONG CKey::DeleteValue(LPCWSTR name) -{ - MYASSERT(_object != NULL); - if (g_IsNT) - return ::RegDeleteValueW(_object, name); - return DeleteValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name)); -} -#endif - -LONG CKey::SetValue(LPCTSTR name, UInt32 value) -{ - MYASSERT(_object != NULL); - return RegSetValueEx(_object, name, NULL, REG_DWORD, - (BYTE * const)&value, sizeof(UInt32)); -} - -LONG CKey::SetValue(LPCTSTR name, bool value) -{ - return SetValue(name, BoolToUINT32(value)); -} - -LONG CKey::SetValue(LPCTSTR name, LPCTSTR value) -{ - MYASSERT(value != NULL); - MYASSERT(_object != NULL); - return RegSetValueEx(_object, name, NULL, REG_SZ, - (const BYTE * )value, (lstrlen(value) + 1) * sizeof(TCHAR)); -} - -/* -LONG CKey::SetValue(LPCTSTR name, const CSysString &value) -{ - MYASSERT(value != NULL); - MYASSERT(_object != NULL); - return RegSetValueEx(_object, name, NULL, REG_SZ, - (const BYTE *)(const TCHAR *)value, (value.Length() + 1) * sizeof(TCHAR)); -} -*/ - -#ifndef _UNICODE - -LONG CKey::SetValue(LPCWSTR name, LPCWSTR value) -{ - MYASSERT(value != NULL); - MYASSERT(_object != NULL); - if (g_IsNT) - return RegSetValueExW(_object, name, NULL, REG_SZ, - (const BYTE * )value, (DWORD)((wcslen(value) + 1) * sizeof(wchar_t))); - return SetValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), - value == 0 ? 0 : (LPCSTR)GetSystemString(value)); -} - -#endif - - -LONG CKey::SetValue(LPCTSTR name, const void *value, UInt32 size) -{ - MYASSERT(value != NULL); - MYASSERT(_object != NULL); - return RegSetValueEx(_object, name, NULL, REG_BINARY, - (const BYTE *)value, size); -} - -LONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) -{ - MYASSERT(value != NULL); - CKey key; - LONG res = key.Create(parentKey, keyName); - if (res == ERROR_SUCCESS) - res = key.SetValue(valueName, value); - return res; -} - -LONG CKey::SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) -{ - MYASSERT(value != NULL); - CKey key; - LONG res = key.Create(_object, keyName); - if (res == ERROR_SUCCESS) - res = key.SetValue(valueName, value); - return res; -} - -LONG CKey::QueryValue(LPCTSTR name, UInt32 &value) -{ - DWORD type = NULL; - DWORD count = sizeof(DWORD); - LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, - (LPBYTE)&value, &count); - MYASSERT((res!=ERROR_SUCCESS) || (type == REG_DWORD)); - MYASSERT((res!=ERROR_SUCCESS) || (count == sizeof(UInt32))); - return res; -} - -LONG CKey::QueryValue(LPCTSTR name, bool &value) -{ - UInt32 uintValue = BoolToUINT32(value); - LONG res = QueryValue(name, uintValue); - value = UINT32ToBool(uintValue); - return res; -} - -LONG CKey::GetValue_IfOk(LPCTSTR name, UInt32 &value) -{ - UInt32 newVal; - LONG res = QueryValue(name, newVal); - if (res == ERROR_SUCCESS) - value = newVal; - return res; -} - -LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value) -{ - bool newVal; - LONG res = QueryValue(name, newVal); - if (res == ERROR_SUCCESS) - value = newVal; - return res; -} - -LONG CKey::QueryValue(LPCTSTR name, LPTSTR value, UInt32 &count) -{ - MYASSERT(count != NULL); - DWORD type = NULL; - LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count); - MYASSERT((res!=ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ)); - return res; -} - -LONG CKey::QueryValue(LPCTSTR name, CSysString &value) -{ - value.Empty(); - DWORD type = NULL; - UInt32 currentSize = 0; - LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)¤tSize); - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) - return res; - res = QueryValue(name, value.GetBuffer(currentSize), currentSize); - value.ReleaseBuffer(); - return res; -} - -#ifndef _UNICODE -LONG CKey::QueryValue(LPCWSTR name, LPWSTR value, UInt32 &count) -{ - MYASSERT(count != NULL); - DWORD type = NULL; - LONG res = RegQueryValueExW(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count); - MYASSERT((res!=ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ)); - return res; -} -LONG CKey::QueryValue(LPCWSTR name, UString &value) -{ - value.Empty(); - DWORD type = NULL; - UInt32 currentSize = 0; - - LONG res; - if (g_IsNT) - { - res = RegQueryValueExW(_object, name, NULL, &type, NULL, (DWORD *)¤tSize); - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) - return res; - res = QueryValue(name, value.GetBuffer(currentSize), currentSize); - value.ReleaseBuffer(); - } - else - { - AString vTemp; - res = QueryValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), vTemp); - value = GetUnicodeString(vTemp); - } - return res; -} -#endif - -LONG CKey::QueryValue(LPCTSTR name, void *value, UInt32 &count) -{ - DWORD type = NULL; - LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count); - MYASSERT((res!=ERROR_SUCCESS) || (type == REG_BINARY)); - return res; -} - - -LONG CKey::QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize) -{ - DWORD type = NULL; - dataSize = 0; - LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&dataSize); - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) - return res; - value.SetCapacity(dataSize); - return QueryValue(name, (BYTE *)value, dataSize); -} - -LONG CKey::EnumKeys(CSysStringVector &keyNames) -{ - keyNames.Clear(); - CSysString keyName; - for (UInt32 index = 0; ; index++) - { - const UInt32 kBufferSize = MAX_PATH + 1; // 256 in ATL - FILETIME lastWriteTime; - UInt32 nameSize = kBufferSize; - LONG result = ::RegEnumKeyEx(_object, index, keyName.GetBuffer(kBufferSize), - (DWORD *)&nameSize, NULL, NULL, NULL, &lastWriteTime); - keyName.ReleaseBuffer(); - if (result == ERROR_NO_MORE_ITEMS) - break; - if (result != ERROR_SUCCESS) - return result; - keyNames.Add(keyName); - } - return ERROR_SUCCESS; -} - -LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) -{ - UInt32 numChars = 0; - int i; - for (i = 0; i < strings.Size(); i++) - numChars += strings[i].Length() + 1; - CBuffer buffer; - buffer.SetCapacity(numChars); - int pos = 0; - for (i = 0; i < strings.Size(); i++) - { - const UString &s = strings[i]; - MyStringCopy((wchar_t *)buffer + pos, (const wchar_t *)s); - pos += s.Length() + 1; - } - return SetValue(valueName, buffer, numChars * sizeof(wchar_t)); -} - -LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings) -{ - strings.Clear(); - CByteBuffer buffer; - UInt32 dataSize; - LONG res = QueryValue(valueName, buffer, dataSize); - if (res != ERROR_SUCCESS) - return res; - if (dataSize % sizeof(wchar_t) != 0) - return E_FAIL; - const wchar_t *data = (const wchar_t *)(const Byte *)buffer; - int numChars = dataSize / sizeof(wchar_t); - UString s; - for (int i = 0; i < numChars; i++) - { - wchar_t c = data[i]; - if (c == 0) - { - strings.Add(s); - s.Empty(); - } - else - s += c; - } - return res; -} - -}} diff --git a/src/libs/7zip/win/CPP/Windows/Registry.h b/src/libs/7zip/win/CPP/Windows/Registry.h deleted file mode 100644 index f0561e688..000000000 --- a/src/libs/7zip/win/CPP/Windows/Registry.h +++ /dev/null @@ -1,85 +0,0 @@ -// Windows/Registry.h - -#ifndef __WINDOWS_REGISTRY_H -#define __WINDOWS_REGISTRY_H - -#include "Common/Buffer.h" -#include "Common/MyString.h" -#include "Common/Types.h" - -namespace NWindows { -namespace NRegistry { - -LONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value); - -class CKey -{ - HKEY _object; -public: - CKey(): _object(NULL) {} - ~CKey() { Close(); } - - operator HKEY() const { return _object; } - void Attach(HKEY key) { _object = key; } - HKEY Detach() - { - HKEY key = _object; - _object = NULL; - return key; - } - - LONG Create(HKEY parentKey, LPCTSTR keyName, - LPTSTR keyClass = REG_NONE, DWORD options = REG_OPTION_NON_VOLATILE, - REGSAM accessMask = KEY_ALL_ACCESS, - LPSECURITY_ATTRIBUTES securityAttributes = NULL, - LPDWORD disposition = NULL); - LONG Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask = KEY_ALL_ACCESS); - - LONG Close(); - - LONG DeleteSubKey(LPCTSTR subKeyName); - LONG RecurseDeleteKey(LPCTSTR subKeyName); - - LONG DeleteValue(LPCTSTR name); - #ifndef _UNICODE - LONG DeleteValue(LPCWSTR name); - #endif - - LONG SetValue(LPCTSTR valueName, UInt32 value); - LONG SetValue(LPCTSTR valueName, bool value); - LONG SetValue(LPCTSTR valueName, LPCTSTR value); - // LONG SetValue(LPCTSTR valueName, const CSysString &value); - #ifndef _UNICODE - LONG SetValue(LPCWSTR name, LPCWSTR value); - // LONG SetValue(LPCWSTR name, const UString &value); - #endif - - LONG SetValue(LPCTSTR name, const void *value, UInt32 size); - - LONG SetValue_Strings(LPCTSTR valueName, const UStringVector &strings); - LONG GetValue_Strings(LPCTSTR valueName, UStringVector &strings); - - LONG SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value); - - LONG QueryValue(LPCTSTR name, UInt32 &value); - LONG QueryValue(LPCTSTR name, bool &value); - LONG QueryValue(LPCTSTR name, LPTSTR value, UInt32 &dataSize); - LONG QueryValue(LPCTSTR name, CSysString &value); - - LONG GetValue_IfOk(LPCTSTR name, UInt32 &value); - LONG GetValue_IfOk(LPCTSTR name, bool &value); - - #ifndef _UNICODE - LONG QueryValue(LPCWSTR name, LPWSTR value, UInt32 &dataSize); - LONG QueryValue(LPCWSTR name, UString &value); - #endif - - LONG QueryValue(LPCTSTR name, void *value, UInt32 &dataSize); - LONG QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize); - - LONG EnumKeys(CSysStringVector &keyNames); -}; - -}} - -#endif diff --git a/src/libs/7zip/win/CPP/Windows/SecurityUtils.cpp b/src/libs/7zip/win/CPP/Windows/SecurityUtils.cpp new file mode 100644 index 000000000..f997738ce --- /dev/null +++ b/src/libs/7zip/win/CPP/Windows/SecurityUtils.cpp @@ -0,0 +1,179 @@ +// Windows/SecurityUtils.cpp + +#include "StdAfx.h" + +#include "SecurityUtils.h" + +namespace NWindows { +namespace NSecurity { + +/* +bool MyLookupAccountSid(LPCTSTR systemName, PSID sid, + CSysString &accountName, CSysString &domainName, PSID_NAME_USE sidNameUse) +{ + DWORD accountNameSize = 0, domainNameSize = 0; + + if (!::LookupAccountSid(systemName, sid, + accountName.GetBuffer(0), &accountNameSize, + domainName.GetBuffer(0), &domainNameSize, sidNameUse)) + { + if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) + return false; + } + bool result = BOOLToBool(::LookupAccountSid(systemName, sid, + accountName.GetBuffer(accountNameSize), &accountNameSize, + domainName.GetBuffer(domainNameSize), &domainNameSize, sidNameUse)); + accountName.ReleaseBuffer(); + domainName.ReleaseBuffer(); + return result; +} +*/ + +static void SetLsaString(LPWSTR src, PLSA_UNICODE_STRING dest) +{ + int len = (int)wcslen(src); + dest->Length = (USHORT)(len * sizeof(WCHAR)); + dest->MaximumLength = (USHORT)((len + 1) * sizeof(WCHAR)); + dest->Buffer = src; +} + +/* +static void MyLookupSids(CPolicy &policy, PSID ps) +{ + LSA_REFERENCED_DOMAIN_LIST *referencedDomains = NULL; + LSA_TRANSLATED_NAME *names = NULL; + NTSTATUS nts = policy.LookupSids(1, &ps, &referencedDomains, &names); + int res = LsaNtStatusToWinError(nts); + LsaFreeMemory(referencedDomains); + LsaFreeMemory(names); +} +*/ + +#ifndef _UNICODE +typedef BOOL (WINAPI * LookupAccountNameWP)( + LPCWSTR lpSystemName, + LPCWSTR lpAccountName, + PSID Sid, + LPDWORD cbSid, + LPWSTR ReferencedDomainName, + LPDWORD cchReferencedDomainName, + PSID_NAME_USE peUse + ); +#endif + +static PSID GetSid(LPWSTR accountName) +{ + #ifndef _UNICODE + HMODULE hModule = GetModuleHandle(TEXT("Advapi32.dll")); + if (hModule == NULL) + return NULL; + LookupAccountNameWP lookupAccountNameW = (LookupAccountNameWP)GetProcAddress(hModule, "LookupAccountNameW"); + if (lookupAccountNameW == NULL) + return NULL; + #endif + + DWORD sidLen = 0, domainLen = 0; + SID_NAME_USE sidNameUse; + if (! + #ifdef _UNICODE + ::LookupAccountNameW + #else + lookupAccountNameW + #endif + (NULL, accountName, NULL, &sidLen, NULL, &domainLen, &sidNameUse)) + { + if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + PSID pSid = ::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sidLen); + LPWSTR domainName = (LPWSTR)::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (domainLen + 1) * sizeof(WCHAR)); + BOOL res = + #ifdef _UNICODE + ::LookupAccountNameW + #else + lookupAccountNameW + #endif + (NULL, accountName, pSid, &sidLen, domainName, &domainLen, &sidNameUse); + ::HeapFree(GetProcessHeap(), 0, domainName); + if (res) + return pSid; + } + } + return NULL; +} + +#define MY__SE_LOCK_MEMORY_NAME L"SeLockMemoryPrivilege" + +bool AddLockMemoryPrivilege() +{ + CPolicy policy; + LSA_OBJECT_ATTRIBUTES attr; + attr.Length = sizeof(attr); + attr.RootDirectory = NULL; + attr.ObjectName = NULL; + attr.Attributes = 0; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + if (policy.Open(NULL, &attr, + // GENERIC_WRITE) + POLICY_ALL_ACCESS) + // STANDARD_RIGHTS_REQUIRED, + // GENERIC_READ | GENERIC_EXECUTE | POLICY_VIEW_LOCAL_INFORMATION | POLICY_LOOKUP_NAMES) + != 0) + return false; + LSA_UNICODE_STRING userRights; + wchar_t s[128] = MY__SE_LOCK_MEMORY_NAME; + SetLsaString(s, &userRights); + WCHAR userName[256 + 2]; + DWORD size = 256; + if (!GetUserNameW(userName, &size)) + return false; + PSID psid = GetSid(userName); + if (psid == NULL) + return false; + bool res = false; + + /* + PLSA_UNICODE_STRING userRightsArray; + ULONG countOfRights; + NTSTATUS status = policy.EnumerateAccountRights(psid, &userRightsArray, &countOfRights); + if (status != 0) + return false; + bool finded = false; + for (ULONG i = 0; i < countOfRights; i++) + { + LSA_UNICODE_STRING &ur = userRightsArray[i]; + if (ur.Length != s.Length() * sizeof(WCHAR)) + continue; + if (wcsncmp(ur.Buffer, s, s.Length()) != 0) + continue; + finded = true; + res = true; + break; + } + if (!finded) + */ + { + /* + LSA_ENUMERATION_INFORMATION *enums; + ULONG countReturned; + NTSTATUS status = policy.EnumerateAccountsWithUserRight(&userRights, &enums, &countReturned); + if (status == 0) + { + for (ULONG i = 0; i < countReturned; i++) + MyLookupSids(policy, enums[i].Sid); + if (enums) + ::LsaFreeMemory(enums); + res = true; + } + */ + NTSTATUS status = policy.AddAccountRights(psid, &userRights); + if (status == 0) + res = true; + // ULONG res = LsaNtStatusToWinError(status); + } + HeapFree(GetProcessHeap(), 0, psid); + return res; +} + +}} + diff --git a/src/libs/7zip/win/CPP/Windows/SecurityUtils.h b/src/libs/7zip/win/CPP/Windows/SecurityUtils.h new file mode 100644 index 000000000..715de2505 --- /dev/null +++ b/src/libs/7zip/win/CPP/Windows/SecurityUtils.h @@ -0,0 +1,167 @@ +// Windows/SecurityUtils.h + +#ifndef __WINDOWS_SECURITY_UTILS_H +#define __WINDOWS_SECURITY_UTILS_H + +#include + +#include "Defs.h" + +namespace NWindows { +namespace NSecurity { + +class CAccessToken +{ + HANDLE _handle; +public: + CAccessToken(): _handle(NULL) {}; + ~CAccessToken() { Close(); } + bool Close() + { + if (_handle == NULL) + return true; + bool res = BOOLToBool(::CloseHandle(_handle)); + if (res) + _handle = NULL; + return res; + } + + bool OpenProcessToken(HANDLE processHandle, DWORD desiredAccess) + { + Close(); + return BOOLToBool(::OpenProcessToken(processHandle, desiredAccess, &_handle)); + } + + /* + bool OpenThreadToken(HANDLE threadHandle, DWORD desiredAccess, bool openAsSelf) + { + Close(); + return BOOLToBool(::OpenTreadToken(threadHandle, desiredAccess, BoolToBOOL(anOpenAsSelf), &_handle)); + } + */ + + bool AdjustPrivileges(bool disableAllPrivileges, PTOKEN_PRIVILEGES newState, + DWORD bufferLength, PTOKEN_PRIVILEGES previousState, PDWORD returnLength) + { return BOOLToBool(::AdjustTokenPrivileges(_handle, BoolToBOOL(disableAllPrivileges), + newState, bufferLength, previousState, returnLength)); } + + bool AdjustPrivileges(bool disableAllPrivileges, PTOKEN_PRIVILEGES newState) + { return AdjustPrivileges(disableAllPrivileges, newState, 0, NULL, NULL); } + + bool AdjustPrivileges(PTOKEN_PRIVILEGES newState) + { return AdjustPrivileges(false, newState); } + +}; + +#ifndef _UNICODE +typedef NTSTATUS (NTAPI *LsaOpenPolicyP)(PLSA_UNICODE_STRING SystemName, + PLSA_OBJECT_ATTRIBUTES ObjectAttributes, ACCESS_MASK DesiredAccess, PLSA_HANDLE PolicyHandle); +typedef NTSTATUS (NTAPI *LsaCloseP)(LSA_HANDLE ObjectHandle); +typedef NTSTATUS (NTAPI *LsaAddAccountRightsP)(LSA_HANDLE PolicyHandle, + PSID AccountSid, PLSA_UNICODE_STRING UserRights, ULONG CountOfRights ); +#define MY_STATUS_NOT_IMPLEMENTED ((NTSTATUS)0xC0000002L) +#endif + +struct CPolicy +{ +protected: + LSA_HANDLE _handle; + #ifndef _UNICODE + HMODULE hModule; + #endif +public: + operator LSA_HANDLE() const { return _handle; } + CPolicy(): _handle(NULL) + { + #ifndef _UNICODE + hModule = GetModuleHandle(TEXT("Advapi32.dll")); + #endif + }; + ~CPolicy() { Close(); } + + NTSTATUS Open(PLSA_UNICODE_STRING systemName, PLSA_OBJECT_ATTRIBUTES objectAttributes, + ACCESS_MASK desiredAccess) + { + #ifndef _UNICODE + if (hModule == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + LsaOpenPolicyP lsaOpenPolicy = (LsaOpenPolicyP)GetProcAddress(hModule, "LsaOpenPolicy"); + if (lsaOpenPolicy == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + #endif + + Close(); + return + #ifdef _UNICODE + ::LsaOpenPolicy + #else + lsaOpenPolicy + #endif + (systemName, objectAttributes, desiredAccess, &_handle); + } + + NTSTATUS Close() + { + if (_handle == NULL) + return 0; + + #ifndef _UNICODE + if (hModule == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + LsaCloseP lsaClose = (LsaCloseP)GetProcAddress(hModule, "LsaClose"); + if (lsaClose == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + #endif + + NTSTATUS res = + #ifdef _UNICODE + ::LsaClose + #else + lsaClose + #endif + (_handle); + _handle = NULL; + return res; + } + + NTSTATUS EnumerateAccountsWithUserRight(PLSA_UNICODE_STRING userRights, + PLSA_ENUMERATION_INFORMATION *enumerationBuffer, PULONG countReturned) + { return LsaEnumerateAccountsWithUserRight(_handle, userRights, (void **)enumerationBuffer, countReturned); } + + NTSTATUS EnumerateAccountRights(PSID sid, PLSA_UNICODE_STRING* userRights, PULONG countOfRights) + { return ::LsaEnumerateAccountRights(_handle, sid, userRights, countOfRights); } + + NTSTATUS LookupSids(ULONG count, PSID* sids, + PLSA_REFERENCED_DOMAIN_LIST* referencedDomains, PLSA_TRANSLATED_NAME* names) + { return LsaLookupSids(_handle, count, sids, referencedDomains, names); } + + NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights, ULONG countOfRights) + { + #ifndef _UNICODE + if (hModule == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + LsaAddAccountRightsP lsaAddAccountRights = (LsaAddAccountRightsP)GetProcAddress(hModule, "LsaAddAccountRights"); + if (lsaAddAccountRights == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + #endif + + return + #ifdef _UNICODE + ::LsaAddAccountRights + #else + lsaAddAccountRights + #endif + (_handle, accountSid, userRights, countOfRights); + } + NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights) + { return AddAccountRights(accountSid, userRights, 1); } + + NTSTATUS RemoveAccountRights(PSID accountSid, bool allRights, PLSA_UNICODE_STRING userRights, ULONG countOfRights) + { return LsaRemoveAccountRights(_handle, accountSid, (BOOLEAN)(allRights ? TRUE : FALSE), userRights, countOfRights); } +}; + +bool AddLockMemoryPrivilege(); + +}} + +#endif diff --git a/src/libs/7zip/win/CPP/Windows/StdAfx.h b/src/libs/7zip/win/CPP/Windows/StdAfx.h index 8b383c5ba..1766dfa86 100644 --- a/src/libs/7zip/win/CPP/Windows/StdAfx.h +++ b/src/libs/7zip/win/CPP/Windows/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../Common/MyWindows.h" -#include "../Common/NewHandler.h" +#include "../Common/Common.h" #endif diff --git a/src/libs/7zip/win/CPP/Windows/System.h b/src/libs/7zip/win/CPP/Windows/System.h index e0067158f..4133a7b30 100644 --- a/src/libs/7zip/win/CPP/Windows/System.h +++ b/src/libs/7zip/win/CPP/Windows/System.h @@ -3,7 +3,7 @@ #ifndef __WINDOWS_SYSTEM_H #define __WINDOWS_SYSTEM_H -#include "../Common/Types.h" +#include "../Common/MyTypes.h" namespace NWindows { namespace NSystem { diff --git a/src/libs/7zip/win/CPP/Windows/Thread.h b/src/libs/7zip/win/CPP/Windows/Thread.h index 16a509d47..f9ecaed85 100644 --- a/src/libs/7zip/win/CPP/Windows/Thread.h +++ b/src/libs/7zip/win/CPP/Windows/Thread.h @@ -20,7 +20,7 @@ public: WRes Create(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) { return Thread_Create(&thread, startAddress, parameter); } WRes Wait() { return Thread_Wait(&thread); } - + #ifdef _WIN32 operator HANDLE() { return thread; } void Attach(HANDLE handle) { thread = handle; } diff --git a/src/libs/7zip/win/CPP/Windows/Time.cpp b/src/libs/7zip/win/CPP/Windows/Time.cpp deleted file mode 100644 index ec9ca47d9..000000000 --- a/src/libs/7zip/win/CPP/Windows/Time.cpp +++ /dev/null @@ -1,170 +0,0 @@ -// Windows/Time.cpp - -#include "StdAfx.h" - -#include "Windows/Defs.h" - -#include "Time.h" - -namespace NWindows { -namespace NTime { - -static const UInt32 kNumTimeQuantumsInSecond = 10000000; -static const UInt32 kFileTimeStartYear = 1601; -static const UInt32 kDosTimeStartYear = 1980; -static const UInt32 kUnixTimeStartYear = 1970; -static const UInt64 kUnixTimeStartValue = ((UInt64)kNumTimeQuantumsInSecond) * - 60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); - -bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft) -{ - #if defined(_WIN32) && !defined(UNDER_CE) - return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &ft)); - #else - ft.dwLowDateTime = 0; - ft.dwHighDateTime = 0; - UInt64 res; - if (!GetSecondsSince1601(kDosTimeStartYear + (dosTime >> 25), (dosTime >> 21) & 0xF, (dosTime >> 16) & 0x1F, - (dosTime >> 11) & 0x1F, (dosTime >> 5) & 0x3F, (dosTime & 0x1F) * 2, res)) - return false; - res *= kNumTimeQuantumsInSecond; - ft.dwLowDateTime = (UInt32)res; - ft.dwHighDateTime = (UInt32)(res >> 32); - return true; - #endif -} - -static const UInt32 kHighDosTime = 0xFF9FBF7D; -static const UInt32 kLowDosTime = 0x210000; - -#define PERIOD_4 (4 * 365 + 1) -#define PERIOD_100 (PERIOD_4 * 25 - 1) -#define PERIOD_400 (PERIOD_100 * 4 + 1) - -bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime) -{ - #if defined(_WIN32) && !defined(UNDER_CE) - - WORD datePart, timePart; - if (!::FileTimeToDosDateTime(&ft, &datePart, &timePart)) - { - dosTime = (ft.dwHighDateTime >= 0x01C00000) ? kHighDosTime : kLowDosTime; - return false; - } - dosTime = (((UInt32)datePart) << 16) + timePart; - - #else - - unsigned year, mon, day, hour, min, sec; - UInt64 v64 = ft.dwLowDateTime | ((UInt64)ft.dwHighDateTime << 32); - Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - unsigned temp; - UInt32 v; - v64 += (kNumTimeQuantumsInSecond * 2 - 1); - v64 /= kNumTimeQuantumsInSecond; - sec = (unsigned)(v64 % 60); - v64 /= 60; - min = (unsigned)(v64 % 60); - v64 /= 60; - hour = (unsigned)(v64 % 24); - v64 /= 24; - - v = (UInt32)v64; - - year = (unsigned)(kFileTimeStartYear + v / PERIOD_400 * 400); - v %= PERIOD_400; - - temp = (unsigned)(v / PERIOD_100); - if (temp == 4) - temp = 3; - year += temp * 100; - v -= temp * PERIOD_100; - - temp = v / PERIOD_4; - if (temp == 25) - temp = 24; - year += temp * 4; - v -= temp * PERIOD_4; - - temp = v / 365; - if (temp == 4) - temp = 3; - year += temp; - v -= temp * 365; - - if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) - ms[1] = 29; - for (mon = 1; mon <= 12; mon++) - { - unsigned s = ms[mon - 1]; - if (v < s) - break; - v -= s; - } - day = (unsigned)v + 1; - - dosTime = kLowDosTime; - if (year < kDosTimeStartYear) - return false; - year -= kDosTimeStartYear; - dosTime = kHighDosTime; - if (year >= 128) - return false; - dosTime = (year << 25) | (mon << 21) | (day << 16) | (hour << 11) | (min << 5) | (sec >> 1); - #endif - return true; -} - -void UnixTimeToFileTime(UInt32 unixTime, FILETIME &ft) -{ - UInt64 v = kUnixTimeStartValue + ((UInt64)unixTime) * kNumTimeQuantumsInSecond; - ft.dwLowDateTime = (DWORD)v; - ft.dwHighDateTime = (DWORD)(v >> 32); -} - -bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime) -{ - UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; - if (winTime < kUnixTimeStartValue) - { - unixTime = 0; - return false; - } - winTime = (winTime - kUnixTimeStartValue) / kNumTimeQuantumsInSecond; - if (winTime > 0xFFFFFFFF) - { - unixTime = 0xFFFFFFFF; - return false; - } - unixTime = (UInt32)winTime; - return true; -} - -bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, - unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) -{ - resSeconds = 0; - if (year < kFileTimeStartYear || year >= 10000 || month < 1 || month > 12 || - day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59) - return false; - UInt32 numYears = year - kFileTimeStartYear; - UInt32 numDays = numYears * 365 + numYears / 4 - numYears / 100 + numYears / 400; - Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) - ms[1] = 29; - month--; - for (unsigned i = 0; i < month; i++) - numDays += ms[i]; - numDays += day - 1; - resSeconds = ((UInt64)(numDays * 24 + hour) * 60 + min) * 60 + sec; - return true; -} - -void GetCurUtcFileTime(FILETIME &ft) -{ - SYSTEMTIME st; - GetSystemTime(&st); - SystemTimeToFileTime(&st, &ft); -} - -}} diff --git a/src/libs/7zip/win/CPP/Windows/Time.h b/src/libs/7zip/win/CPP/Windows/Time.h deleted file mode 100644 index 6f510b22b..000000000 --- a/src/libs/7zip/win/CPP/Windows/Time.h +++ /dev/null @@ -1,21 +0,0 @@ -// Windows/Time.h - -#ifndef __WINDOWS_TIME_H -#define __WINDOWS_TIME_H - -#include "Common/Types.h" - -namespace NWindows { -namespace NTime { - -bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime); -bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime); -void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime); -bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime); -bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, - unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds); -void GetCurUtcFileTime(FILETIME &ft); - -}} - -#endif diff --git a/src/libs/7zip/win/CPP/Windows/TimeUtils.cpp b/src/libs/7zip/win/CPP/Windows/TimeUtils.cpp new file mode 100644 index 000000000..7ef44d9cc --- /dev/null +++ b/src/libs/7zip/win/CPP/Windows/TimeUtils.cpp @@ -0,0 +1,203 @@ +// Windows/TimeUtils.cpp + +#include "StdAfx.h" + +#include "Defs.h" +#include "TimeUtils.h" + +namespace NWindows { +namespace NTime { + +static const UInt32 kNumTimeQuantumsInSecond = 10000000; +static const UInt32 kFileTimeStartYear = 1601; +static const UInt32 kDosTimeStartYear = 1980; +static const UInt32 kUnixTimeStartYear = 1970; +static const UInt64 kUnixTimeOffset = + (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); +static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond; + +bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft) throw() +{ + #if defined(_WIN32) && !defined(UNDER_CE) + return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &ft)); + #else + ft.dwLowDateTime = 0; + ft.dwHighDateTime = 0; + UInt64 res; + if (!GetSecondsSince1601(kDosTimeStartYear + (dosTime >> 25), (dosTime >> 21) & 0xF, (dosTime >> 16) & 0x1F, + (dosTime >> 11) & 0x1F, (dosTime >> 5) & 0x3F, (dosTime & 0x1F) * 2, res)) + return false; + res *= kNumTimeQuantumsInSecond; + ft.dwLowDateTime = (UInt32)res; + ft.dwHighDateTime = (UInt32)(res >> 32); + return true; + #endif +} + +static const UInt32 kHighDosTime = 0xFF9FBF7D; +static const UInt32 kLowDosTime = 0x210000; + +#define PERIOD_4 (4 * 365 + 1) +#define PERIOD_100 (PERIOD_4 * 25 - 1) +#define PERIOD_400 (PERIOD_100 * 4 + 1) + +bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime) throw() +{ + #if defined(_WIN32) && !defined(UNDER_CE) + + WORD datePart, timePart; + if (!::FileTimeToDosDateTime(&ft, &datePart, &timePart)) + { + dosTime = (ft.dwHighDateTime >= 0x01C00000) ? kHighDosTime : kLowDosTime; + return false; + } + dosTime = (((UInt32)datePart) << 16) + timePart; + + #else + + unsigned year, mon, day, hour, min, sec; + UInt64 v64 = ft.dwLowDateTime | ((UInt64)ft.dwHighDateTime << 32); + Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + unsigned temp; + UInt32 v; + v64 += (kNumTimeQuantumsInSecond * 2 - 1); + v64 /= kNumTimeQuantumsInSecond; + sec = (unsigned)(v64 % 60); + v64 /= 60; + min = (unsigned)(v64 % 60); + v64 /= 60; + hour = (unsigned)(v64 % 24); + v64 /= 24; + + v = (UInt32)v64; + + year = (unsigned)(kFileTimeStartYear + v / PERIOD_400 * 400); + v %= PERIOD_400; + + temp = (unsigned)(v / PERIOD_100); + if (temp == 4) + temp = 3; + year += temp * 100; + v -= temp * PERIOD_100; + + temp = v / PERIOD_4; + if (temp == 25) + temp = 24; + year += temp * 4; + v -= temp * PERIOD_4; + + temp = v / 365; + if (temp == 4) + temp = 3; + year += temp; + v -= temp * 365; + + if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) + ms[1] = 29; + for (mon = 1; mon <= 12; mon++) + { + unsigned s = ms[mon - 1]; + if (v < s) + break; + v -= s; + } + day = (unsigned)v + 1; + + dosTime = kLowDosTime; + if (year < kDosTimeStartYear) + return false; + year -= kDosTimeStartYear; + dosTime = kHighDosTime; + if (year >= 128) + return false; + dosTime = (year << 25) | (mon << 21) | (day << 16) | (hour << 11) | (min << 5) | (sec >> 1); + #endif + return true; +} + +void UnixTimeToFileTime(UInt32 unixTime, FILETIME &ft) throw() +{ + UInt64 v = (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond; + ft.dwLowDateTime = (DWORD)v; + ft.dwHighDateTime = (DWORD)(v >> 32); +} + +bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &ft) throw() +{ + if (unixTime > kNumSecondsInFileTime - kUnixTimeOffset) + { + ft.dwLowDateTime = ft.dwHighDateTime = (UInt32)(Int32)-1; + return false; + } + Int64 v = (Int64)kUnixTimeOffset + unixTime; + if (v < 0) + { + ft.dwLowDateTime = ft.dwHighDateTime = 0; + return false; + } + UInt64 v2 = (UInt64)v * kNumTimeQuantumsInSecond; + ft.dwLowDateTime = (DWORD)v2; + ft.dwHighDateTime = (DWORD)(v2 >> 32); + return true; +} + +Int64 FileTimeToUnixTime64(const FILETIME &ft) throw() +{ + UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; + return (Int64)(winTime / kNumTimeQuantumsInSecond) - kUnixTimeOffset; +} + +bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime) throw() +{ + UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; + winTime /= kNumTimeQuantumsInSecond; + if (winTime < kUnixTimeOffset) + { + unixTime = 0; + return false; + } + winTime -= kUnixTimeOffset; + if (winTime > 0xFFFFFFFF) + { + unixTime = 0xFFFFFFFF; + return false; + } + unixTime = (UInt32)winTime; + return true; +} + +bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, + unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw() +{ + resSeconds = 0; + if (year < kFileTimeStartYear || year >= 10000 || month < 1 || month > 12 || + day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59) + return false; + UInt32 numYears = year - kFileTimeStartYear; + UInt32 numDays = numYears * 365 + numYears / 4 - numYears / 100 + numYears / 400; + Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) + ms[1] = 29; + month--; + for (unsigned i = 0; i < month; i++) + numDays += ms[i]; + numDays += day - 1; + resSeconds = ((UInt64)(numDays * 24 + hour) * 60 + min) * 60 + sec; + return true; +} + +void GetCurUtcFileTime(FILETIME &ft) throw() +{ + // Both variants provide same low resolution on WinXP: about 15 ms. + // But GetSystemTimeAsFileTime is much faster. + + #ifdef UNDER_CE + SYSTEMTIME st; + GetSystemTime(&st); + SystemTimeToFileTime(&st, &ft); + #else + GetSystemTimeAsFileTime(&ft); + #endif +} + +}} diff --git a/src/libs/7zip/win/CPP/Windows/TimeUtils.h b/src/libs/7zip/win/CPP/Windows/TimeUtils.h new file mode 100644 index 000000000..2967214e6 --- /dev/null +++ b/src/libs/7zip/win/CPP/Windows/TimeUtils.h @@ -0,0 +1,23 @@ +// Windows/TimeUtils.h + +#ifndef __WINDOWS_TIME_UTILS_H +#define __WINDOWS_TIME_UTILS_H + +#include "../Common/MyTypes.h" + +namespace NWindows { +namespace NTime { + +bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime) throw(); +bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime) throw(); +void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime) throw(); +bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &fileTime) throw(); +bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime) throw(); +Int64 FileTimeToUnixTime64(const FILETIME &ft) throw(); +bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, + unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw(); +void GetCurUtcFileTime(FILETIME &ft) throw(); + +}} + +#endif diff --git a/src/libs/7zip/win/CPP/Windows/Windows.pri b/src/libs/7zip/win/CPP/Windows/Windows.pri new file mode 100644 index 000000000..a69279060 --- /dev/null +++ b/src/libs/7zip/win/CPP/Windows/Windows.pri @@ -0,0 +1,29 @@ +HEADERS += $$7ZIP_BASE/CPP/Windows/DLL.h \ + $$7ZIP_BASE/CPP/Windows/Defs.h \ + $$7ZIP_BASE/CPP/Windows/FileDir.h \ + $$7ZIP_BASE/CPP/Windows/FileFind.h \ + $$7ZIP_BASE/CPP/Windows/FileIO.h \ + $$7ZIP_BASE/CPP/Windows/FileMapping.h \ + $$7ZIP_BASE/CPP/Windows/FileName.h \ + $$7ZIP_BASE/CPP/Windows/Handle.h \ + $$7ZIP_BASE/CPP/Windows/PropVariant.h \ + $$7ZIP_BASE/CPP/Windows/PropVariantConv.h \ + $$7ZIP_BASE/CPP/Windows/SecurityUtils.h \ + $$7ZIP_BASE/CPP/Windows/StdAfx.h \ + $$7ZIP_BASE/CPP/Windows/Synchronization.h \ + $$7ZIP_BASE/CPP/Windows/System.h \ + $$7ZIP_BASE/CPP/Windows/Thread.h \ + $$7ZIP_BASE/CPP/Windows/TimeUtils.h + +SOURCES += $$7ZIP_BASE/CPP/Windows/DLL.cpp \ + $$7ZIP_BASE/CPP/Windows/FileDir.cpp \ + $$7ZIP_BASE/CPP/Windows/FileFind.cpp \ + $$7ZIP_BASE/CPP/Windows/FileIO.cpp \ + $$7ZIP_BASE/CPP/Windows/FileLink.cpp \ + $$7ZIP_BASE/CPP/Windows/FileName.cpp \ + $$7ZIP_BASE/CPP/Windows/PropVariant.cpp \ + $$7ZIP_BASE/CPP/Windows/PropVariantConv.cpp \ + $$7ZIP_BASE/CPP/Windows/SecurityUtils.cpp \ + $$7ZIP_BASE/CPP/Windows/Synchronization.cpp \ + $$7ZIP_BASE/CPP/Windows/System.cpp \ + $$7ZIP_BASE/CPP/Windows/TimeUtils.cpp diff --git a/src/libs/7zip/win/Methods.txt b/src/libs/7zip/win/Methods.txt deleted file mode 100644 index f52e7c315..000000000 --- a/src/libs/7zip/win/Methods.txt +++ /dev/null @@ -1,152 +0,0 @@ -7-Zip method IDs (9.18) ------------------------ - -Each compression or crypto method in 7z has unique binary value (ID). -The length of ID in bytes is arbitrary but it can not exceed 63 bits (8 bytes). - -If you want to add some new ID, you have two ways: -1) Write request for allocating IDs to 7-zip developers. -2) Generate 8-bytes ID: - - 3F ZZ ZZ ZZ ZZ ZZ MM MM - - 3F - Prefix for random IDs (1 byte) - ZZ ZZ ZZ ZZ ZZ - Developer ID (5 bytes). Use real random bytes. - - MM MM - Method ID (2 bytes) - - You can notify 7-Zip developers about your Developer ID / Method ID. - - Note: Use new ID only if old codec can not decode data encoded with new version. - - -List of defined IDs -------------------- - -00 - Copy - -03 - Delta -04 - x86 (BCJ) -05 - PPC (Big Endian) -06 - IA64 -07 - ARM (little endian) -08 - ARM Thumb (little endian) -09 - SPARC -21 - LZMA2 - -02.. - Common - 03 Swap - - 2 Swap2 - - 4 Swap4 - -03.. - 7z - 01 - LZMA - 01 - Version - - 03 - Branch - 01 - x86 - 03 - BCJ - 1B - BCJ2 - 02 - PPC - 05 - PPC (Big Endian) - 03 - Alpha - 01 - Alpha - 04 - IA64 - 01 - IA64 - 05 - ARM - 01 - ARM - 06 - M68 - 05 - M68 (Big Endian) - 07 - ARM Thumb - 01 - ARMT - 08 - SPARC - 05 - SPARC - - 04 - PPMD - 01 - Version - - 7F - - 01 - experimental methods. - - -04.. - Misc - 00 - Reserved - 01 - Zip - 00 - Copy (not used). Use {00} instead - 01 - Shrink - 06 - Implode - 08 - Deflate - 09 - Deflate64 - 10 - Imploding - 12 - BZip2 (not used). Use {04 02 02} instead - 14 - LZMA - 60 - Jpeg - 61 - WavPack - 62 - PPMd - 63 - wzAES - 02 - BZip - 02 - BZip2 - 03 - Rar - 01 - Rar15 - 02 - Rar20 - 03 - Rar29 - 04 - Arj - 01 - Arj (1,2,3) - 02 - Arj 4 - 05 - Z - 06 - Lzh - 07 - Reserved for 7z - 08 - Cab - 09 - NSIS - 01 - DeflateNSIS - 02 - BZip2NSIS - - -06.. - Crypto - 00 - - 01 - AES - 0x - AES-128 - 4x - AES-192 - 8x - AES-256 - Cx - AES - - x0 - ECB - x1 - CBC - x2 - CFB - x3 - OFB - - 07 - Reserved - 0F - Reserved - - F0 - Misc Ciphers (Real Ciphers without hashing algo) - - F1 - Misc Ciphers (Combine) - 01 - Zip - 01 - Main Zip crypto algo - 03 - RAR - 02 - - 03 - Rar29 AES-128 + (modified SHA-1) - 07 - 7z - 01 - AES-256 + SHA-256 - -07.. - Hash (subject to change) - 00 - - 01 - CRC - 02 - SHA-1 - 03 - SHA-256 - 04 - SHA-384 - 05 - SHA-512 - - F0 - Misc Hash - - F1 - Misc - 03 - RAR - 03 - Rar29 Password Hashing (modified SHA1) - 07 - 7z - 01 - SHA-256 Password Hashing - - - - ---- -End of document diff --git a/src/libs/7zip/win/history.txt b/src/libs/7zip/win/history.txt deleted file mode 100644 index 79abd9cea..000000000 --- a/src/libs/7zip/win/history.txt +++ /dev/null @@ -1,271 +0,0 @@ -HISTORY of the LZMA SDK ------------------------ - -9.18 beta 2010-11-02 -------------------------- -- New small SFX module for installers (SfxSetup). - - -9.12 beta 2010-03-24 -------------------------- -- The BUG in LZMA SDK 9.* was fixed: LZMA2 codec didn't work, - if more than 10 threads were used (or more than 20 threads in some modes). - - -9.11 beta 2010-03-15 -------------------------- -- PPMd compression method support - - -9.09 2009-12-12 -------------------------- -- The bug was fixed: - Utf16_To_Utf8 funstions in UTFConvert.cpp and 7zMain.c - incorrectly converted surrogate characters (the code >= 0x10000) to UTF-8. -- Some bugs were fixed - - -9.06 2009-08-17 -------------------------- -- Some changes in ANSI-C 7z Decoder interfaces. - - -9.04 2009-05-30 -------------------------- -- LZMA2 compression method support -- xz format support - - -4.65 2009-02-03 -------------------------- -- Some minor fixes - - -4.63 2008-12-31 -------------------------- -- Some minor fixes - - -4.61 beta 2008-11-23 -------------------------- -- The bug in ANSI-C LZMA Decoder was fixed: - If encoded stream was corrupted, decoder could access memory - outside of allocated range. -- Some changes in ANSI-C 7z Decoder interfaces. -- LZMA SDK is placed in the public domain. - - -4.60 beta 2008-08-19 -------------------------- -- Some minor fixes. - - -4.59 beta 2008-08-13 -------------------------- -- The bug was fixed: - LZMA Encoder in fast compression mode could access memory outside of - allocated range in some rare cases. - - -4.58 beta 2008-05-05 -------------------------- -- ANSI-C LZMA Decoder was rewritten for speed optimizations. -- ANSI-C LZMA Encoder was included to LZMA SDK. -- C++ LZMA code now is just wrapper over ANSI-C code. - - -4.57 2007-12-12 -------------------------- -- Speed optimizations in Ñ++ LZMA Decoder. -- Small changes for more compatibility with some C/C++ compilers. - - -4.49 beta 2007-07-05 -------------------------- -- .7z ANSI-C Decoder: - - now it supports BCJ and BCJ2 filters - - now it supports files larger than 4 GB. - - now it supports "Last Write Time" field for files. -- C++ code for .7z archives compressing/decompressing from 7-zip - was included to LZMA SDK. - - -4.43 2006-06-04 -------------------------- -- Small changes for more compatibility with some C/C++ compilers. - - -4.42 2006-05-15 -------------------------- -- Small changes in .h files in ANSI-C version. - - -4.39 beta 2006-04-14 -------------------------- -- The bug in versions 4.33b:4.38b was fixed: - C++ version of LZMA encoder could not correctly compress - files larger than 2 GB with HC4 match finder (-mfhc4). - - -4.37 beta 2005-04-06 -------------------------- -- Fixes in C++ code: code could no be compiled if _NO_EXCEPTIONS was defined. - - -4.35 beta 2005-03-02 -------------------------- -- The bug was fixed in C++ version of LZMA Decoder: - If encoded stream was corrupted, decoder could access memory - outside of allocated range. - - -4.34 beta 2006-02-27 -------------------------- -- Compressing speed and memory requirements for compressing were increased -- LZMA now can use only these match finders: HC4, BT2, BT3, BT4 - - -4.32 2005-12-09 -------------------------- -- Java version of LZMA SDK was included - - -4.30 2005-11-20 -------------------------- -- Compression ratio was improved in -a2 mode -- Speed optimizations for compressing in -a2 mode -- -fb switch now supports values up to 273 -- The bug in 7z_C (7zIn.c) was fixed: - It used Alloc/Free functions from different memory pools. - So if program used two memory pools, it worked incorrectly. -- 7z_C: .7z format supporting was improved -- LZMA# SDK (C#.NET version) was included - - -4.27 (Updated) 2005-09-21 -------------------------- -- Some GUIDs/interfaces in C++ were changed. - IStream.h: - ISequentialInStream::Read now works as old ReadPart - ISequentialOutStream::Write now works as old WritePart - - -4.27 2005-08-07 -------------------------- -- The bug in LzmaDecodeSize.c was fixed: - if _LZMA_IN_CB and _LZMA_OUT_READ were defined, - decompressing worked incorrectly. - - -4.26 2005-08-05 -------------------------- -- Fixes in 7z_C code and LzmaTest.c: - previous versions could work incorrectly, - if malloc(0) returns 0 - - -4.23 2005-06-29 -------------------------- -- Small fixes in C++ code - - -4.22 2005-06-10 -------------------------- -- Small fixes - - -4.21 2005-06-08 -------------------------- -- Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed -- New additional version of ANSI-C LZMA Decoder with zlib-like interface: - - LzmaStateDecode.h - - LzmaStateDecode.c - - LzmaStateTest.c -- ANSI-C LZMA Decoder now can decompress files larger than 4 GB - - -4.17 2005-04-18 -------------------------- -- New example for RAM->RAM compressing/decompressing: - LZMA + BCJ (filter for x86 code): - - LzmaRam.h - - LzmaRam.cpp - - LzmaRamDecode.h - - LzmaRamDecode.c - - -f86 switch for lzma.exe - - -4.16 2005-03-29 -------------------------- -- The bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder): - If _LZMA_OUT_READ was defined, and if encoded stream was corrupted, - decoder could access memory outside of allocated range. -- Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster). - Old version of LZMA Decoder now is in file LzmaDecodeSize.c. - LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c -- Small speed optimization in LZMA C++ code -- filter for SPARC's code was added -- Simplified version of .7z ANSI-C Decoder was included - - -4.06 2004-09-05 -------------------------- -- The bug in v4.05 was fixed: - LZMA-Encoder didn't release output stream in some cases. - - -4.05 2004-08-25 -------------------------- -- Source code of filters for x86, IA-64, ARM, ARM-Thumb - and PowerPC code was included to SDK -- Some internal minor changes - - -4.04 2004-07-28 -------------------------- -- More compatibility with some C++ compilers - - -4.03 2004-06-18 -------------------------- -- "Benchmark" command was added. It measures compressing - and decompressing speed and shows rating values. - Also it checks hardware errors. - - -4.02 2004-06-10 -------------------------- -- C++ LZMA Encoder/Decoder code now is more portable - and it can be compiled by GCC on Linux. - - -4.01 2004-02-15 -------------------------- -- Some detection of data corruption was enabled. - LzmaDecode.c / RangeDecoderReadByte - ..... - { - rd->ExtraBytes = 1; - return 0xFF; - } - - -4.00 2004-02-13 -------------------------- -- Original version of LZMA SDK - - - -HISTORY of the LZMA -------------------- - 2001-2008: Improvements to LZMA compressing/decompressing code, - keeping compatibility with original LZMA format - 1996-2001: Development of LZMA compression format - - Some milestones: - - 2001-08-30: LZMA compression was added to 7-Zip - 1999-01-02: First version of 7-Zip was released - - -End of document diff --git a/src/libs/7zip/win/lzma.txt b/src/libs/7zip/win/lzma.txt deleted file mode 100644 index 659323237..000000000 --- a/src/libs/7zip/win/lzma.txt +++ /dev/null @@ -1,598 +0,0 @@ -LZMA SDK 9.20 -------------- - -LZMA SDK provides the documentation, samples, header files, libraries, -and tools you need to develop applications that use LZMA compression. - -LZMA is default and general compression method of 7z format -in 7-Zip compression program (www.7-zip.org). LZMA provides high -compression ratio and very fast decompression. - -LZMA is an improved version of famous LZ77 compression algorithm. -It was improved in way of maximum increasing of compression ratio, -keeping high decompression speed and low memory requirements for -decompressing. - - - -LICENSE -------- - -LZMA SDK is written and placed in the public domain by Igor Pavlov. - -Some code in LZMA SDK is based on public domain code from another developers: - 1) PPMd var.H (2001): Dmitry Shkarin - 2) SHA-256: Wei Dai (Crypto++ library) - - -LZMA SDK Contents ------------------ - -LZMA SDK includes: - - - ANSI-C/C++/C#/Java source code for LZMA compressing and decompressing - - Compiled file->file LZMA compressing/decompressing program for Windows system - - -UNIX/Linux version ------------------- -To compile C++ version of file->file LZMA encoding, go to directory -CPP/7zip/Bundles/LzmaCon -and call make to recompile it: - make -f makefile.gcc clean all - -In some UNIX/Linux versions you must compile LZMA with static libraries. -To compile with static libraries, you can use -LIB = -lm -static - - -Files ---------------------- -lzma.txt - LZMA SDK description (this file) -7zFormat.txt - 7z Format description -7zC.txt - 7z ANSI-C Decoder description -methods.txt - Compression method IDs for .7z -lzma.exe - Compiled file->file LZMA encoder/decoder for Windows -7zr.exe - 7-Zip with 7z/lzma/xz support. -history.txt - history of the LZMA SDK - - -Source code structure ---------------------- - -C/ - C files - 7zCrc*.* - CRC code - Alloc.* - Memory allocation functions - Bra*.* - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code - LzFind.* - Match finder for LZ (LZMA) encoders - LzFindMt.* - Match finder for LZ (LZMA) encoders for multithreading encoding - LzHash.h - Additional file for LZ match finder - LzmaDec.* - LZMA decoding - LzmaEnc.* - LZMA encoding - LzmaLib.* - LZMA Library for DLL calling - Types.h - Basic types for another .c files - Threads.* - The code for multithreading. - - LzmaLib - LZMA Library (.DLL for Windows) - - LzmaUtil - LZMA Utility (file->file LZMA encoder/decoder). - - Archive - files related to archiving - 7z - 7z ANSI-C Decoder - -CPP/ -- CPP files - - Common - common files for C++ projects - Windows - common files for Windows related code - - 7zip - files related to 7-Zip Project - - Common - common files for 7-Zip - - Compress - files related to compression/decompression - - Archive - files related to archiving - - Common - common files for archive handling - 7z - 7z C++ Encoder/Decoder - - Bundles - Modules that are bundles of other modules - - Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2 - LzmaCon - lzma.exe: LZMA compression/decompression - Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2 - Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2. - - UI - User Interface files - - Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll - Common - Common UI files - Console - Code for console archiver - - - -CS/ - C# files - 7zip - Common - some common files for 7-Zip - Compress - files related to compression/decompression - LZ - files related to LZ (Lempel-Ziv) compression algorithm - LZMA - LZMA compression/decompression - LzmaAlone - file->file LZMA compression/decompression - RangeCoder - Range Coder (special code of compression/decompression) - -Java/ - Java files - SevenZip - Compression - files related to compression/decompression - LZ - files related to LZ (Lempel-Ziv) compression algorithm - LZMA - LZMA compression/decompression - RangeCoder - Range Coder (special code of compression/decompression) - - -C/C++ source code of LZMA SDK is part of 7-Zip project. -7-Zip source code can be downloaded from 7-Zip's SourceForge page: - - http://sourceforge.net/projects/sevenzip/ - - - -LZMA features -------------- - - Variable dictionary size (up to 1 GB) - - Estimated compressing speed: about 2 MB/s on 2 GHz CPU - - Estimated decompressing speed: - - 20-30 MB/s on 2 GHz Core 2 or AMD Athlon 64 - - 1-2 MB/s on 200 MHz ARM, MIPS, PowerPC or other simple RISC - - Small memory requirements for decompressing (16 KB + DictionarySize) - - Small code size for decompressing: 5-8 KB - -LZMA decoder uses only integer operations and can be -implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions). - -Some critical operations that affect the speed of LZMA decompression: - 1) 32*16 bit integer multiply - 2) Misspredicted branches (penalty mostly depends from pipeline length) - 3) 32-bit shift and arithmetic operations - -The speed of LZMA decompressing mostly depends from CPU speed. -Memory speed has no big meaning. But if your CPU has small data cache, -overall weight of memory speed will slightly increase. - - -How To Use ----------- - -Using LZMA encoder/decoder executable --------------------------------------- - -Usage: LZMA inputFile outputFile [...] - - e: encode file - - d: decode file - - b: Benchmark. There are two tests: compressing and decompressing - with LZMA method. Benchmark shows rating in MIPS (million - instructions per second). Rating value is calculated from - measured speed and it is normalized with Intel's Core 2 results. - Also Benchmark checks possible hardware errors (RAM - errors in most cases). Benchmark uses these settings: - (-a1, -d21, -fb32, -mfbt4). You can change only -d parameter. - Also you can change the number of iterations. Example for 30 iterations: - LZMA b 30 - Default number of iterations is 10. - - - - - -a{N}: set compression mode 0 = fast, 1 = normal - default: 1 (normal) - - d{N}: Sets Dictionary size - [0, 30], default: 23 (8MB) - The maximum value for dictionary size is 1 GB = 2^30 bytes. - Dictionary size is calculated as DictionarySize = 2^N bytes. - For decompressing file compressed by LZMA method with dictionary - size D = 2^N you need about D bytes of memory (RAM). - - -fb{N}: set number of fast bytes - [5, 273], default: 128 - Usually big number gives a little bit better compression ratio - and slower compression process. - - -lc{N}: set number of literal context bits - [0, 8], default: 3 - Sometimes lc=4 gives gain for big files. - - -lp{N}: set number of literal pos bits - [0, 4], default: 0 - lp switch is intended for periodical data when period is - equal 2^N. For example, for 32-bit (4 bytes) - periodical data you can use lp=2. Often it's better to set lc0, - if you change lp switch. - - -pb{N}: set number of pos bits - [0, 4], default: 2 - pb switch is intended for periodical data - when period is equal 2^N. - - -mf{MF_ID}: set Match Finder. Default: bt4. - Algorithms from hc* group doesn't provide good compression - ratio, but they often works pretty fast in combination with - fast mode (-a0). - - Memory requirements depend from dictionary size - (parameter "d" in table below). - - MF_ID Memory Description - - bt2 d * 9.5 + 4MB Binary Tree with 2 bytes hashing. - bt3 d * 11.5 + 4MB Binary Tree with 3 bytes hashing. - bt4 d * 11.5 + 4MB Binary Tree with 4 bytes hashing. - hc4 d * 7.5 + 4MB Hash Chain with 4 bytes hashing. - - -eos: write End Of Stream marker. By default LZMA doesn't write - eos marker, since LZMA decoder knows uncompressed size - stored in .lzma file header. - - -si: Read data from stdin (it will write End Of Stream marker). - -so: Write data to stdout - - -Examples: - -1) LZMA e file.bin file.lzma -d16 -lc0 - -compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K) -and 0 literal context bits. -lc0 allows to reduce memory requirements -for decompression. - - -2) LZMA e file.bin file.lzma -lc0 -lp2 - -compresses file.bin to file.lzma with settings suitable -for 32-bit periodical data (for example, ARM or MIPS code). - -3) LZMA d file.lzma file.bin - -decompresses file.lzma to file.bin. - - -Compression ratio hints ------------------------ - -Recommendations ---------------- - -To increase the compression ratio for LZMA compressing it's desirable -to have aligned data (if it's possible) and also it's desirable to locate -data in such order, where code is grouped in one place and data is -grouped in other place (it's better than such mixing: code, data, code, -data, ...). - - -Filters -------- -You can increase the compression ratio for some data types, using -special filters before compressing. For example, it's possible to -increase the compression ratio on 5-10% for code for those CPU ISAs: -x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC. - -You can find C source code of such filters in C/Bra*.* files - -You can check the compression ratio gain of these filters with such -7-Zip commands (example for ARM code): -No filter: - 7z a a1.7z a.bin -m0=lzma - -With filter for little-endian ARM code: - 7z a a2.7z a.bin -m0=arm -m1=lzma - -It works in such manner: -Compressing = Filter_encoding + LZMA_encoding -Decompressing = LZMA_decoding + Filter_decoding - -Compressing and decompressing speed of such filters is very high, -so it will not increase decompressing time too much. -Moreover, it reduces decompression time for LZMA_decoding, -since compression ratio with filtering is higher. - -These filters convert CALL (calling procedure) instructions -from relative offsets to absolute addresses, so such data becomes more -compressible. - -For some ISAs (for example, for MIPS) it's impossible to get gain from such filter. - - -LZMA compressed file format ---------------------------- -Offset Size Description - 0 1 Special LZMA properties (lc,lp, pb in encoded form) - 1 4 Dictionary size (little endian) - 5 8 Uncompressed size (little endian). -1 means unknown size - 13 Compressed data - - -ANSI-C LZMA Decoder -~~~~~~~~~~~~~~~~~~~ - -Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58. -If you want to use old interfaces you can download previous version of LZMA SDK -from sourceforge.net site. - -To use ANSI-C LZMA Decoder you need the following files: -1) LzmaDec.h + LzmaDec.c + Types.h -LzmaUtil/LzmaUtil.c is example application that uses these files. - - -Memory requirements for LZMA decoding -------------------------------------- - -Stack usage of LZMA decoding function for local variables is not -larger than 200-400 bytes. - -LZMA Decoder uses dictionary buffer and internal state structure. -Internal state structure consumes - state_size = (4 + (1.5 << (lc + lp))) KB -by default (lc=3, lp=0), state_size = 16 KB. - - -How To decompress data ----------------------- - -LZMA Decoder (ANSI-C version) now supports 2 interfaces: -1) Single-call Decompressing -2) Multi-call State Decompressing (zlib-like interface) - -You must use external allocator: -Example: -void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } -void SzFree(void *p, void *address) { p = p; free(address); } -ISzAlloc alloc = { SzAlloc, SzFree }; - -You can use p = p; operator to disable compiler warnings. - - -Single-call Decompressing -------------------------- -When to use: RAM->RAM decompressing -Compile files: LzmaDec.h + LzmaDec.c + Types.h -Compile defines: no defines -Memory Requirements: - - Input buffer: compressed size - - Output buffer: uncompressed size - - LZMA Internal Structures: state_size (16 KB for default settings) - -Interface: - int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, - const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, - ELzmaStatus *status, ISzAlloc *alloc); - In: - dest - output data - destLen - output data size - src - input data - srcLen - input data size - propData - LZMA properties (5 bytes) - propSize - size of propData buffer (5 bytes) - finishMode - It has meaning only if the decoding reaches output limit (*destLen). - LZMA_FINISH_ANY - Decode just destLen bytes. - LZMA_FINISH_END - Stream must be finished after (*destLen). - You can use LZMA_FINISH_END, when you know that - current output buffer covers last bytes of stream. - alloc - Memory allocator. - - Out: - destLen - processed output size - srcLen - processed input size - - Output: - SZ_OK - status: - LZMA_STATUS_FINISHED_WITH_MARK - LZMA_STATUS_NOT_FINISHED - LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK - SZ_ERROR_DATA - Data error - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_UNSUPPORTED - Unsupported properties - SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). - - If LZMA decoder sees end_marker before reaching output limit, it returns OK result, - and output value of destLen will be less than output buffer size limit. - - You can use multiple checks to test data integrity after full decompression: - 1) Check Result and "status" variable. - 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. - 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. - You must use correct finish mode in that case. */ - - -Multi-call State Decompressing (zlib-like interface) ----------------------------------------------------- - -When to use: file->file decompressing -Compile files: LzmaDec.h + LzmaDec.c + Types.h - -Memory Requirements: - - Buffer for input stream: any size (for example, 16 KB) - - Buffer for output stream: any size (for example, 16 KB) - - LZMA Internal Structures: state_size (16 KB for default settings) - - LZMA dictionary (dictionary size is encoded in LZMA properties header) - -1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header: - unsigned char header[LZMA_PROPS_SIZE + 8]; - ReadFile(inFile, header, sizeof(header) - -2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties - - CLzmaDec state; - LzmaDec_Constr(&state); - res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc); - if (res != SZ_OK) - return res; - -3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop - - LzmaDec_Init(&state); - for (;;) - { - ... - int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, - const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode); - ... - } - - -4) Free all allocated structures - LzmaDec_Free(&state, &g_Alloc); - -For full code example, look at C/LzmaUtil/LzmaUtil.c code. - - -How To compress data --------------------- - -Compile files: LzmaEnc.h + LzmaEnc.c + Types.h + -LzFind.c + LzFind.h + LzFindMt.c + LzFindMt.h + LzHash.h - -Memory Requirements: - - (dictSize * 11.5 + 6 MB) + state_size - -Lzma Encoder can use two memory allocators: -1) alloc - for small arrays. -2) allocBig - for big arrays. - -For example, you can use Large RAM Pages (2 MB) in allocBig allocator for -better compression speed. Note that Windows has bad implementation for -Large RAM Pages. -It's OK to use same allocator for alloc and allocBig. - - -Single-call Compression with callbacks --------------------------------------- - -Check C/LzmaUtil/LzmaUtil.c as example, - -When to use: file->file decompressing - -1) you must implement callback structures for interfaces: -ISeqInStream -ISeqOutStream -ICompressProgress -ISzAlloc - -static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } -static void SzFree(void *p, void *address) { p = p; MyFree(address); } -static ISzAlloc g_Alloc = { SzAlloc, SzFree }; - - CFileSeqInStream inStream; - CFileSeqOutStream outStream; - - inStream.funcTable.Read = MyRead; - inStream.file = inFile; - outStream.funcTable.Write = MyWrite; - outStream.file = outFile; - - -2) Create CLzmaEncHandle object; - - CLzmaEncHandle enc; - - enc = LzmaEnc_Create(&g_Alloc); - if (enc == 0) - return SZ_ERROR_MEM; - - -3) initialize CLzmaEncProps properties; - - LzmaEncProps_Init(&props); - - Then you can change some properties in that structure. - -4) Send LZMA properties to LZMA Encoder - - res = LzmaEnc_SetProps(enc, &props); - -5) Write encoded properties to header - - Byte header[LZMA_PROPS_SIZE + 8]; - size_t headerSize = LZMA_PROPS_SIZE; - UInt64 fileSize; - int i; - - res = LzmaEnc_WriteProperties(enc, header, &headerSize); - fileSize = MyGetFileLength(inFile); - for (i = 0; i < 8; i++) - header[headerSize++] = (Byte)(fileSize >> (8 * i)); - MyWriteFileAndCheck(outFile, header, headerSize) - -6) Call encoding function: - res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable, - NULL, &g_Alloc, &g_Alloc); - -7) Destroy LZMA Encoder Object - LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); - - -If callback function return some error code, LzmaEnc_Encode also returns that code -or it can return the code like SZ_ERROR_READ, SZ_ERROR_WRITE or SZ_ERROR_PROGRESS. - - -Single-call RAM->RAM Compression --------------------------------- - -Single-call RAM->RAM Compression is similar to Compression with callbacks, -but you provide pointers to buffers instead of pointers to stream callbacks: - -HRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, - CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, - ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); - -Return code: - SZ_OK - OK - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_PARAM - Incorrect paramater - SZ_ERROR_OUTPUT_EOF - output buffer overflow - SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) - - - -Defines -------- - -_LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code. - -_LZMA_PROB32 - It can increase the speed on some 32-bit CPUs, but memory usage for - some structures will be doubled in that case. - -_LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is 32-bit. - -_LZMA_NO_SYSTEM_SIZE_T - Define it if you don't want to use size_t type. - - -_7ZIP_PPMD_SUPPPORT - Define it if you don't want to support PPMD method in AMSI-C .7z decoder. - - -C++ LZMA Encoder/Decoder -~~~~~~~~~~~~~~~~~~~~~~~~ -C++ LZMA code use COM-like interfaces. So if you want to use it, -you can study basics of COM/OLE. -C++ LZMA code is just wrapper over ANSI-C code. - - -C++ Notes -~~~~~~~~~~~~~~~~~~~~~~~~ -If you use some C++ code folders in 7-Zip (for example, C++ code for .7z handling), -you must check that you correctly work with "new" operator. -7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator. -So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator: -operator new(size_t size) -{ - void *p = ::malloc(size); - if (p == 0) - throw CNewException(); - return p; -} -If you use MSCV that throws exception for "new" operator, you can compile without -"NewHandler.cpp". So standard exception will be used. Actually some code of -7-Zip catches any exception in internal code and converts it to HRESULT code. -So you don't need to catch CNewException, if you call COM interfaces of 7-Zip. - ---- - -http://www.7-zip.org -http://www.7-zip.org/sdk.html -http://www.7-zip.org/support.html diff --git a/src/libs/7zip/win/win.pri b/src/libs/7zip/win/win.pri index 932c567fa..d29553cbd 100644 --- a/src/libs/7zip/win/win.pri +++ b/src/libs/7zip/win/win.pri @@ -1,131 +1,11 @@ -#$(COMMON_OBJS): ../../../Common/$(*B).cpp -SOURCES += $$7ZIP_BASE/CPP/Common/IntToString.cpp -SOURCES += $$7ZIP_BASE/CPP/Common/MyString.cpp -SOURCES += $$7ZIP_BASE/CPP/Common/StringConvert.cpp -SOURCES += $$7ZIP_BASE/CPP/Common/StringToInt.cpp -SOURCES += $$7ZIP_BASE/CPP/Common/MyVector.cpp -SOURCES += $$7ZIP_BASE/CPP/Common/Wildcard.cpp - -#$(WIN_OBJS): ../../../Windows/$(*B).cpp -SOURCES += $$7ZIP_BASE/CPP/Windows/DLL.cpp -SOURCES += $$7ZIP_BASE/CPP/Windows/FileDir.cpp -SOURCES += $$7ZIP_BASE/CPP/Windows/FileFind.cpp -SOURCES += $$7ZIP_BASE/CPP/Windows/FileName.cpp -SOURCES += $$7ZIP_BASE/CPP/Windows/FileIO.cpp -SOURCES += $$7ZIP_BASE/CPP/Windows/PropVariant.cpp -SOURCES += $$7ZIP_BASE/CPP/Windows/PropVariantConversions.cpp -SOURCES += $$7ZIP_BASE/CPP/Windows/System.cpp -SOURCES += $$7ZIP_BASE/CPP/Windows/Time.cpp - -#$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Common/CreateCoder.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Common/CWrappers.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Common/InBuffer.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Common/InOutTempBuffer.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Common/FileStreams.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Common/FilterCoder.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Common/LimitedStreams.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Common/LockedStream.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Common/MethodId.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Common/MethodProps.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Common/OutBuffer.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Common/ProgressUtils.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Common/StreamBinder.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Common/StreamObjects.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Common/StreamUtils.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Common/VirtThread.cpp - -#$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/UI/Common/DefaultName.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/UI/Common/EnumDirItems.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/UI/Common/LoadCodecs.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/UI/Common/OpenArchive.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/UI/Common/SetProperties.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/UI/Common/SortUtils.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/UI/Common/TempFiles.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/UI/Common/Update.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/UI/Common/UpdateAction.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/UI/Common/UpdateCallback.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/UI/Common/UpdatePair.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/UI/Common/UpdateProduce.cpp - -#$(AR_OBJS): ../../Archive/$(*B).cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/LzmaHandler.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/SplitHandler.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/XzHandler.cpp - -!static:DEF_FILE += $$7ZIP_BASE/CPP/7zip/Archive/Archive.def -!static:DEF_FILE += $$7ZIP_BASE/CPP/7zip/Archive/Archive2.def - -#$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/Common/CoderMixer2.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/Common/CoderMixer2MT.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/Common/HandlerOut.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/Common/ItemNameUtils.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/Common/ParseProperties.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/Common/InStreamWithCRC.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/Common/MultiStream.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/Common/DummyOutStream.cpp - -#$(7Z_OBJS): ../../Archive/7z/$(*B).cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/7z/7zCompressionMode.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/7z/7zDecode.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/7z/7zEncode.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/7z/7zExtract.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/7z/7zFolderInStream.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/7z/7zFolderOutStream.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/7z/7zHandler.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/7z/7zHandlerOut.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/7z/7zHeader.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/7z/7zIn.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/7z/7zOut.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/7z/7zProperties.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/7z/7zSpecStream.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/7z/7zUpdate.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/7z/7zRegister.cpp - -#$(COMPRESS_OBJS): ../../Compress/$(*B).cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Compress/Bcj2Coder.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Compress/Bcj2Register.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Compress/BcjCoder.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Compress/BcjRegister.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Compress/BranchCoder.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Compress/BranchMisc.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Compress/BranchRegister.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Compress/ByteSwap.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Compress/CopyCoder.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Compress/CopyRegister.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Compress/DeltaFilter.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Compress/Lzma2Decoder.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Compress/Lzma2Encoder.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Compress/Lzma2Register.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Compress/LzmaDecoder.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Compress/LzmaEncoder.cpp -SOURCES += $$7ZIP_BASE/CPP/7zip/Compress/LzmaRegister.cpp - -#$(C_OBJS): ../../../../C/$(*B).c -SOURCES += $$7ZIP_BASE/C/Alloc.c -SOURCES += $$7ZIP_BASE/C/Bra.c -SOURCES += $$7ZIP_BASE/C/Bra86.c -SOURCES += $$7ZIP_BASE/C/BraIA64.c -SOURCES += $$7ZIP_BASE/C/CpuArch.c -SOURCES += $$7ZIP_BASE/C/Delta.c -SOURCES += $$7ZIP_BASE/C/LzFind.c -SOURCES += $$7ZIP_BASE/C/LzFindMt.c -SOURCES += $$7ZIP_BASE/C/Lzma2Dec.c -SOURCES += $$7ZIP_BASE/C/Lzma2Enc.c -SOURCES += $$7ZIP_BASE/C/LzmaDec.c -SOURCES += $$7ZIP_BASE/C/LzmaEnc.c -SOURCES += $$7ZIP_BASE/C/MtCoder.c -SOURCES += $$7ZIP_BASE/C/Threads.c -SOURCES += $$7ZIP_BASE/C/7zCrc.c -SOURCES += $$7ZIP_BASE/C/7zCrcOpt.c -SOURCES += $$7ZIP_BASE/C/7zStream.c -SOURCES += $$7ZIP_BASE/C/Xz.c -SOURCES += $$7ZIP_BASE/C/XzIn.c -SOURCES += $$7ZIP_BASE/C/XzCrc64.c -SOURCES += $$7ZIP_BASE/C/XzDec.c -SOURCES += $$7ZIP_BASE/C/XzEnc.c -SOURCES += $$7ZIP_BASE/C/Sha256.c +include(C/C.pri) +include(CPP/7zip/7zip.pri) +include(CPP/7zip/Archive/7z/7z.pri) +include(CPP/7zip/Archive/Archive.pri) +include(CPP/7zip/Archive/Common/Common.pri) +include(CPP/7zip/Common/Common.pri) +include(CPP/7zip/Compress/Compress.pri) +include(CPP/7zip/UI/Common/Common.pri) +include(CPP/7zip/UI/Console/Console.pri) +include(CPP/Common/Common.pri) +include(CPP/Windows/Windows.pri) -- cgit v1.2.3