From 866a06f5a0c0ede11979504a318e150030aa7a11 Mon Sep 17 00:00:00 2001 From: Igor Pavlov Date: Tue, 30 Jan 2018 00:15:34 +0000 Subject: 18.01 --- C/7zVersion.h | 6 +- C/XzDec.c | 17 +- CPP/7zip/Archive/DmgHandler.cpp | 34 + CPP/7zip/Archive/PeHandler.cpp | 26 +- CPP/7zip/Archive/Zip/ZipHandlerOut.cpp | 28 + CPP/7zip/Archive/Zip/ZipHeader.h | 1 + CPP/7zip/Archive/Zip/ZipIn.h | 5 +- CPP/7zip/Archive/Zip/ZipItem.cpp | 6 + CPP/7zip/Archive/Zip/ZipItem.h | 7 + CPP/7zip/Archive/Zip/ZipUpdate.cpp | 26 +- CPP/7zip/Archive/Zip/ZipUpdate.h | 10 +- CPP/7zip/Bundles/Format7zF/Arc.mak | 1 + CPP/7zip/Bundles/Format7zF/Format7z.dsp | 18 + CPP/7zip/Common/InBuffer.cpp | 28 + CPP/7zip/Compress/LzOutWindow.h | 33 + CPP/7zip/Compress/LzfseDecoder.cpp | 925 ++++++++++++++++++++++++++ CPP/7zip/Compress/LzfseDecoder.h | 58 ++ CPP/7zip/UI/Agent/Agent.cpp | 9 +- CPP/7zip/UI/Agent/Agent.h | 6 + CPP/7zip/UI/Common/ArchiveExtractCallback.cpp | 100 +-- CPP/7zip/UI/Common/ArchiveExtractCallback.h | 25 +- CPP/7zip/UI/Common/OpenArchive.cpp | 2 +- CPP/7zip/UI/Common/OpenArchive.h | 19 + CPP/7zip/UI/Common/Update.cpp | 61 +- CPP/Windows/FileDir.cpp | 15 + DOC/7zip.inf | 4 +- DOC/7zip.nsi | 4 +- DOC/7zip.wxs | 2 +- DOC/License.txt | 52 +- DOC/readme.txt | 4 +- 30 files changed, 1413 insertions(+), 119 deletions(-) create mode 100644 CPP/7zip/Compress/LzfseDecoder.cpp create mode 100644 CPP/7zip/Compress/LzfseDecoder.h diff --git a/C/7zVersion.h b/C/7zVersion.h index 5e17019a..69ef6985 100644 --- a/C/7zVersion.h +++ b/C/7zVersion.h @@ -1,7 +1,7 @@ #define MY_VER_MAJOR 18 -#define MY_VER_MINOR 00 +#define MY_VER_MINOR 01 #define MY_VER_BUILD 0 -#define MY_VERSION_NUMBERS "18.00 beta" +#define MY_VERSION_NUMBERS "18.01" #define MY_VERSION MY_VERSION_NUMBERS #ifdef MY_CPU_NAME @@ -10,7 +10,7 @@ #define MY_VERSION_CPU MY_VERSION #endif -#define MY_DATE "2018-01-10" +#define MY_DATE "2018-01-28" #undef MY_COPYRIGHT #undef MY_VERSION_COPYRIGHT_DATE #define MY_AUTHOR_NAME "Igor Pavlov" diff --git a/C/XzDec.c b/C/XzDec.c index 67216a57..4c5c93ae 100644 --- a/C/XzDec.c +++ b/C/XzDec.c @@ -1,5 +1,5 @@ /* XzDec.c -- Xz Decode -2017-07-27 : Igor Pavlov : Public domain */ +2018-01-21 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -742,7 +742,8 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, srcRem = srcLenOrig - *srcLen; - if (srcRem == 0) + // XZ_STATE_BLOCK_FOOTER can transit to XZ_STATE_BLOCK_HEADER without input bytes + if (srcRem == 0 && p->state != XZ_STATE_BLOCK_FOOTER) { *status = CODER_STATUS_NEEDS_MORE_INPUT; return SZ_OK; @@ -820,8 +821,13 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, case XZ_STATE_BLOCK_FOOTER: { - if (((p->packSize + p->alignPos) & 3) != 0) + if ((((unsigned)p->packSize + p->alignPos) & 3) != 0) { + if (srcRem == 0) + { + *status = CODER_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } (*srcLen)++; p->alignPos++; if (*src++ != 0) @@ -833,6 +839,11 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, UInt32 cur = checkSize - p->pos; if (cur != 0) { + if (srcRem == 0) + { + *status = CODER_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } if (cur > srcRem) cur = (UInt32)srcRem; memcpy(p->buf + p->pos, src, cur); diff --git a/CPP/7zip/Archive/DmgHandler.cpp b/CPP/7zip/Archive/DmgHandler.cpp index 8acbcea6..608ad4c4 100644 --- a/CPP/7zip/Archive/DmgHandler.cpp +++ b/CPP/7zip/Archive/DmgHandler.cpp @@ -19,6 +19,7 @@ #include "../Compress/BZip2Decoder.h" #include "../Compress/CopyCoder.h" +#include "../Compress/LzfseDecoder.h" #include "../Compress/ZlibDecoder.h" #include "Common/OutStreamWithCRC.h" @@ -121,6 +122,7 @@ enum METHOD_ADC = 0x80000004, METHOD_ZLIB = 0x80000005, METHOD_BZIP2 = 0x80000006, + METHOD_LZFSE = 0x80000007, METHOD_COMMENT = 0x7FFFFFFE, // is used to comment "+beg" and "+end" in extra field. METHOD_END = 0xFFFFFFFF }; @@ -276,6 +278,7 @@ void CMethods::GetString(AString &res) const case METHOD_ADC: s = "ADC"; break; case METHOD_ZLIB: s = "ZLIB"; break; case METHOD_BZIP2: s = "BZip2"; break; + case METHOD_LZFSE: s = "LZFSE"; break; default: ConvertUInt32ToString(type, buf); s = buf; } res.Add_OptSpaced(s); @@ -307,6 +310,10 @@ static const CAppleName k_Names[] = { true, "hfs", "Apple_HFS" }, { true, "hfsx", "Apple_HFSX" }, { true, "ufs", "Apple_UFS" }, + + // efi_sys partition is FAT32, but it's not main file. So we use (IsFs = false) + { false, "efi_sys", "C12A7328-F81F-11D2-BA4B-00A0C93EC93B" }, + { false, "free", "Apple_Free" }, { false, "ddm", "DDM" }, { false, NULL, "Apple_partition_map" }, @@ -1247,6 +1254,11 @@ STDMETHODIMP CAdcDecoder::Code(ISequentialInStream *inStream, } + + + + + STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { @@ -1292,6 +1304,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CAdcDecoder *adcCoderSpec = new CAdcDecoder(); CMyComPtr adcCoder = adcCoderSpec; + NCompress::NLzfse::CDecoder *lzfseCoderSpec = new NCompress::NLzfse::CDecoder(); + CMyComPtr lzfseCoder = lzfseCoderSpec; + CLocalProgress *lps = new CLocalProgress; CMyComPtr progress = lps; lps->Init(extractCallback, false); @@ -1419,6 +1434,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, opRes = NExtract::NOperationResult::kDataError; break; } + + case METHOD_LZFSE: + { + res = lzfseCoder->Code(inStream, outStream, &block.PackSize, &block.UnpSize, progress); + break; + } default: opRes = NExtract::NOperationResult::kUnsupportedMethod; @@ -1490,6 +1511,9 @@ class CInStream: CAdcDecoder *adcCoderSpec; CMyComPtr adcCoder; + NCompress::NLzfse::CDecoder *lzfseCoderSpec; + CMyComPtr lzfseCoder; + CBufPtrSeqOutStream *outStreamSpec; CMyComPtr outStream; @@ -1651,6 +1675,15 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) if (res == S_OK && bzip2CoderSpec->GetInputProcessedSize() != block.PackSize) res = S_FALSE; break; + + case METHOD_LZFSE: + if (!lzfseCoder) + { + lzfseCoderSpec = new NCompress::NLzfse::CDecoder(); + lzfseCoder = lzfseCoderSpec; + } + res = lzfseCoder->Code(inStream, outStream, &block.PackSize, &block.UnpSize, NULL); + break; default: return E_FAIL; @@ -1738,6 +1771,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) case METHOD_ADC: case METHOD_ZLIB: case METHOD_BZIP2: + case METHOD_LZFSE: case METHOD_END: break; default: diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp index 4edaa918..cb0836cc 100644 --- a/CPP/7zip/Archive/PeHandler.cpp +++ b/CPP/7zip/Archive/PeHandler.cpp @@ -387,6 +387,10 @@ void CSection::Parse(const Byte *p) G32(36, Flags); } + + +// IMAGE_FILE_* + static const CUInt32PCharPair g_HeaderCharacts[] = { { 1, "Executable" }, @@ -406,9 +410,7 @@ static const CUInt32PCharPair g_HeaderCharacts[] = { 15, "Big-Endian" } }; - - -// IMAGE_DLLCHARACTERISTICS_* constants +// IMAGE_DLLCHARACTERISTICS_* static const char * const g_DllCharacts[] = { @@ -930,7 +932,9 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidExtension: if (_header.IsDll()) - prop = _optHeader.IsSybSystem_EFI() ? "efi" : "dll"; + prop = "dll"; + else if (_optHeader.IsSybSystem_EFI()) + prop = "efi"; break; case kpidBit64: if (_optHeader.Is64Bit()) prop = true; break; @@ -1137,8 +1141,17 @@ HRESULT CHandler::LoadDebugSections(IInStream *stream, bool &thereIsSection) return S_OK; const unsigned kEntrySize = 28; UInt32 numItems = debugLink.Size / kEntrySize; - if (numItems * kEntrySize != debugLink.Size || numItems > 16) + if (numItems > 16) return S_FALSE; + + // MAC's EFI file: numItems can be incorrect. Only first CDebugEntry entry is correct. + // debugLink.Size = kEntrySize + some_data, pointed by entry[0]. + if (numItems * kEntrySize != debugLink.Size) + { + // return S_FALSE; + if (numItems > 1) + numItems = 1; + } UInt64 pa = 0; unsigned i; @@ -2191,6 +2204,9 @@ bool CHeader::ParseCoff(const Byte *p) for (unsigned i = 0; i < ARRAY_SIZE(g_MachinePairs); i++) if (Machine == g_MachinePairs[i].Value) return true; + if (Machine == 0) + return true; + return false; } diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp index 8ecf7942..5acbb6d4 100644 --- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp @@ -136,6 +136,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt thereAreAesUpdates = true; if (!IntToBool(newProps)) ui.IsDir = inputItem.IsDir(); + // ui.IsAltStream = inputItem.IsAltStream(); } if (IntToBool(newProps)) @@ -175,6 +176,33 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt ui.IsDir = (prop.boolVal != VARIANT_FALSE); } + /* + { + bool isAltStream = false; + { + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(i, kpidIsAltStream, &prop)); + if (prop.vt == VT_BOOL) + isAltStream = (prop.boolVal != VARIANT_FALSE); + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + } + + if (isAltStream) + { + if (ui.IsDir) + return E_INVALIDARG; + int delim = name.ReverseFind(L':'); + if (delim >= 0) + { + name.Delete(delim, 1); + name.Insert(delim, UString(k_SpecName_NTFS_STREAM)); + ui.IsAltStream = true; + } + } + } + */ + { CPropVariant prop; RINOK(callback->GetProperty(i, kpidTimeType, &prop)); diff --git a/CPP/7zip/Archive/Zip/ZipHeader.h b/CPP/7zip/Archive/Zip/ZipHeader.h index 61b4ea4b..5e6f00e4 100644 --- a/CPP/7zip/Archive/Zip/ZipHeader.h +++ b/CPP/7zip/Archive/Zip/ZipHeader.h @@ -131,6 +131,7 @@ namespace NFileHeader const unsigned kDescriptorUsedMask = 1 << 3; const unsigned kStrongEncrypted = 1 << 6; const unsigned kUtf8 = 1 << 11; + const unsigned kAltStream = 1 << 14; const unsigned kImplodeDictionarySizeMask = 1 << 1; const unsigned kImplodeLiteralsOnMask = 1 << 2; diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h index a312c36a..e67bce42 100644 --- a/CPP/7zip/Archive/Zip/ZipIn.h +++ b/CPP/7zip/Archive/Zip/ZipIn.h @@ -20,10 +20,13 @@ class CItemEx: public CItem { public: UInt32 LocalFullHeaderSize; // including Name and Extra + // int ParentOfAltStream; // -1, if not AltStream bool DescriptorWasRead; - CItemEx(): DescriptorWasRead(false) {} + CItemEx(): + // ParentOfAltStream(-1), + DescriptorWasRead(false) {} UInt64 GetLocalFullSize() const { return LocalFullHeaderSize + GetPackSizeWithDescriptor(); } diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp index 885a43cd..5cff1735 100644 --- a/CPP/7zip/Archive/Zip/ZipItem.cpp +++ b/CPP/7zip/Archive/Zip/ZipItem.cpp @@ -20,6 +20,12 @@ namespace NZip { using namespace NFileHeader; + +/* +const char *k_SpecName_NTFS_STREAM = "@@NTFS@STREAM@"; +const char *k_SpecName_MAC_RESOURCE_FORK = "@@MAC@RESOURCE-FORK@"; +*/ + static const CUInt32PCharPair g_ExtraTypes[] = { { NExtraID::kZip64, "Zip64" }, diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h index 0cf9bd09..78e3e01c 100644 --- a/CPP/7zip/Archive/Zip/ZipItem.h +++ b/CPP/7zip/Archive/Zip/ZipItem.h @@ -14,6 +14,11 @@ namespace NArchive { namespace NZip { +/* +extern const char *k_SpecName_NTFS_STREAM; +extern const char *k_SpecName_MAC_RESOURCE_FORK; +*/ + struct CVersion { Byte Version; @@ -233,6 +238,7 @@ public: bool IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || Method == NFileHeader::NCompressionMethod::kWzAES); } bool IsLzmaEOS() const { return (Flags & NFileHeader::NFlags::kLzmaEOS) != 0; } bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; } + // bool IsAltStream() const { return (Flags & NFileHeader::NFlags::kAltStream) != 0; } unsigned GetDeflateLevel() const { return (Flags >> 1) & 3; } @@ -264,6 +270,7 @@ public: void ClearFlags() { Flags = 0; } void SetEncrypted(bool encrypted) { SetFlag(NFileHeader::NFlags::kEncrypted, encrypted); } void SetUtf8(bool isUtf8) { SetFlag(NFileHeader::NFlags::kUtf8, isUtf8); } + // void SetFlag_AltStream(bool isAltStream) { SetFlag(NFileHeader::NFlags::kAltStream, isAltStream); } void SetDescriptorMode(bool useDescriptor) { SetFlag(NFileHeader::NFlags::kDescriptorUsedMask, useDescriptor); } UINT GetCodePage() const { return CP_OEMCP; } diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp index 606f7829..2289203b 100644 --- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp +++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp @@ -75,6 +75,7 @@ static void SetFileHeader( item.Name = ui.Name; item.Comment = ui.Comment; item.SetUtf8(ui.IsUtf8); + // item.SetFlag_AltStream(ui.IsAltStream); item.ExternalAttrib = ui.Attrib; item.Time = ui.Time; item.Ntfs_MTime = ui.Ntfs_MTime; @@ -280,6 +281,7 @@ public: MY_UNKNOWN_IMP void Create(IProgress *progress, bool inSizeIsMain); void SetProgressOffset(UInt64 progressOffset); + void SetProgressOffset_NoLock(UInt64 progressOffset); HRESULT SetRatioInfo(unsigned index, const UInt64 *inSize, const UInt64 *outSize); STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; @@ -292,11 +294,16 @@ void CMtProgressMixer2::Create(IProgress *progress, bool inSizeIsMain) ProgressOffset = InSizes[0] = InSizes[1] = OutSizes[0] = OutSizes[1] = 0; } -void CMtProgressMixer2::SetProgressOffset(UInt64 progressOffset) +void CMtProgressMixer2::SetProgressOffset_NoLock(UInt64 progressOffset) { - CriticalSection.Enter(); InSizes[1] = OutSizes[1] = 0; ProgressOffset = progressOffset; +} + +void CMtProgressMixer2::SetProgressOffset(UInt64 progressOffset) +{ + CriticalSection.Enter(); + SetProgressOffset_NoLock(progressOffset); CriticalSection.Leave(); } @@ -384,6 +391,7 @@ static HRESULT UpdateItemOldData( item.Comment = ui.Comment; item.Name = ui.Name; item.SetUtf8(ui.IsUtf8); + // item.SetFlag_AltStream(ui.IsAltStream); item.Time = ui.Time; item.Ntfs_MTime = ui.Ntfs_MTime; item.Ntfs_ATime = ui.Ntfs_ATime; @@ -602,8 +610,11 @@ static HRESULT Update2St( lps->InSize = unpackSizeTotal; lps->OutSize = packSizeTotal; RINOK(lps->SetCur()); + archive.WriteCentralDir(items, comment); - return S_OK; + + lps->ProgressOffset += kCentralHeaderSize * updateItems.Size() + 1; + return lps->SetCur(); } @@ -897,7 +908,7 @@ static HRESULT Update2( { complexity += ui.Size; complexity += kLocalHeaderSize; - mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity); + mtProgressMixerSpec->Mixer2->SetProgressOffset_NoLock(complexity); RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); memRef2.Skip = true; continue; @@ -1107,8 +1118,13 @@ static HRESULT Update2( } RINOK(mtCompressProgressMixer.SetRatioInfo(0, NULL, NULL)); + archive.WriteCentralDir(items, comment); - return S_OK; + + complexity += kCentralHeaderSize * updateItems.Size() + 1; + mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity); + return mtCompressProgressMixer.SetRatioInfo(0, NULL, NULL); + #endif } diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.h b/CPP/7zip/Archive/Zip/ZipUpdate.h index d5fda855..8785ae60 100644 --- a/CPP/7zip/Archive/Zip/ZipUpdate.h +++ b/CPP/7zip/Archive/Zip/ZipUpdate.h @@ -32,6 +32,7 @@ struct CUpdateItem bool IsDir; bool NtfsTimeIsDefined; bool IsUtf8; + // bool IsAltStream; int IndexInArc; int IndexInClient; UInt32 Attrib; @@ -50,12 +51,19 @@ struct CUpdateItem IsDir = false; NtfsTimeIsDefined = false; IsUtf8 = false; + // IsAltStream = false; Size = 0; Name.Empty(); Comment.Free(); } - CUpdateItem(): NtfsTimeIsDefined(false), IsUtf8(false), Size(0) {} + CUpdateItem(): + IsDir(false), + NtfsTimeIsDefined(false), + IsUtf8(false), + // IsAltStream(false), + Size(0) + {} }; HRESULT Update( diff --git a/CPP/7zip/Bundles/Format7zF/Arc.mak b/CPP/7zip/Bundles/Format7zF/Arc.mak index 97f6596e..28dce218 100644 --- a/CPP/7zip/Bundles/Format7zF/Arc.mak +++ b/CPP/7zip/Bundles/Format7zF/Arc.mak @@ -198,6 +198,7 @@ COMPRESS_OBJS = \ $O\DeflateRegister.obj \ $O\DeltaFilter.obj \ $O\ImplodeDecoder.obj \ + $O\LzfseDecoder.obj \ $O\LzhDecoder.obj \ $O\Lzma2Decoder.obj \ $O\Lzma2Encoder.obj \ diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsp b/CPP/7zip/Bundles/Format7zF/Format7z.dsp index f2a8fcc8..7b1b233e 100644 --- a/CPP/7zip/Bundles/Format7zF/Format7z.dsp +++ b/CPP/7zip/Bundles/Format7zF/Format7z.dsp @@ -961,6 +961,24 @@ SOURCE=..\..\Compress\HuffmanDecoder.h # End Source File # Begin Source File +SOURCE=..\..\Compress\LzfseDecoder.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzfseDecoder.h +# End Source File +# Begin Source File + SOURCE=..\..\Compress\LzhDecoder.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/Common/InBuffer.cpp b/CPP/7zip/Common/InBuffer.cpp index 133d95b3..d1bc9b9a 100644 --- a/CPP/7zip/Common/InBuffer.cpp +++ b/CPP/7zip/Common/InBuffer.cpp @@ -97,6 +97,33 @@ Byte CInBufferBase::ReadByte_FromNewBlock() size_t CInBufferBase::ReadBytes(Byte *buf, size_t size) { + size_t num = 0; + for (;;) + { + const size_t rem = _bufLim - _buf; + if (size <= rem) + { + if (size != 0) + { + memcpy(buf, _buf, size); + _buf += size; + num += size; + } + return num; + } + if (rem != 0) + { + memcpy(buf, _buf, rem); + _buf += rem; + buf += rem; + num += rem; + size -= rem; + } + if (!ReadBlock()) + return num; + } + + /* if ((size_t)(_bufLim - _buf) >= size) { const Byte *src = _buf; @@ -113,6 +140,7 @@ size_t CInBufferBase::ReadBytes(Byte *buf, size_t size) buf[i] = *_buf++; } return size; + */ } size_t CInBufferBase::Skip(size_t size) diff --git a/CPP/7zip/Compress/LzOutWindow.h b/CPP/7zip/Compress/LzOutWindow.h index 5591744d..30ac334f 100644 --- a/CPP/7zip/Compress/LzOutWindow.h +++ b/CPP/7zip/Compress/LzOutWindow.h @@ -56,6 +56,39 @@ public: if (pos == _limitPos) FlushWithCheck(); } + + void PutBytes(const Byte *data, UInt32 size) + { + if (size == 0) + return; + UInt32 pos = _pos; + Byte *buf = _buf; + buf[pos++] = *data++; + size--; + for (;;) + { + UInt32 limitPos = _limitPos; + UInt32 rem = limitPos - pos; + if (rem == 0) + { + _pos = pos; + FlushWithCheck(); + pos = _pos; + continue; + } + + if (size == 0) + break; + + if (rem > size) + rem = size; + size -= rem; + do + buf[pos++] = *data++; + while (--rem); + } + _pos = pos; + } Byte GetByte(UInt32 distance) const { diff --git a/CPP/7zip/Compress/LzfseDecoder.cpp b/CPP/7zip/Compress/LzfseDecoder.cpp new file mode 100644 index 00000000..41c7445a --- /dev/null +++ b/CPP/7zip/Compress/LzfseDecoder.cpp @@ -0,0 +1,925 @@ +// LzfseDecoder.cpp + +/* +This code implements LZFSE data decompressing. +The code from "LZFSE compression library" was used. + +2018 : Igor Pavlov : BSD 3-clause License : the code in this file +2015-2017 : Apple Inc : BSD 3-clause License : original "LZFSE compression library" code + +The code in the "LZFSE compression library" is licensed under the "BSD 3-clause License": +---- +Copyright (c) 2015-2016, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +---- +*/ + +#include "StdAfx.h" + +// #define SHOW_DEBUG_INFO + +#ifdef SHOW_DEBUG_INFO +#include +#endif + +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + +#include "../../../C/CpuArch.h" + +#include "LzfseDecoder.h" + +namespace NCompress { +namespace NLzfse { + +static const Byte kSignature_LZFSE_V1 = 0x31; // '1' +static const Byte kSignature_LZFSE_V2 = 0x32; // '2' + + +HRESULT CDecoder::GetUInt32(UInt32 &val) +{ + Byte b[4]; + for (unsigned i = 0; i < 4; i++) + if (!m_InStream.ReadByte(b[i])) + return S_FALSE; + val = GetUi32(b); + return S_OK; +} + + + +HRESULT CDecoder::DecodeUncompressed(UInt32 unpackSize) +{ + PRF(printf("\nUncompressed %7u\n", unpackSize)); + + const unsigned kBufSize = 1 << 8; + Byte buf[kBufSize]; + for (;;) + { + if (unpackSize == 0) + return S_OK; + UInt32 cur = unpackSize; + if (cur > kBufSize) + cur = kBufSize; + UInt32 cur2 = (UInt32)m_InStream.ReadBytes(buf, cur); + m_OutWindowStream.PutBytes(buf, cur2); + if (cur != cur2) + return S_FALSE; + } +} + + + +HRESULT CDecoder::DecodeLzvn(UInt32 unpackSize) +{ + UInt32 packSize; + RINOK(GetUInt32(packSize)); + + PRF(printf("\nLZVN %7u %7u", unpackSize, packSize)); + + UInt32 D = 0; + + for (;;) + { + if (packSize == 0) + return S_FALSE; + Byte b; + if (!m_InStream.ReadByte(b)) + return S_FALSE; + packSize--; + + UInt32 M; + UInt32 L; + + if (b >= 0xE0) + { + /* + large L - 11100000 LLLLLLLL + small L - 1110LLLL + + large Rep - 11110000 MMMMMMMM + small Rep - 1111MMMM + */ + + M = b & 0xF; + if (M == 0) + { + if (packSize == 0) + return S_FALSE; + Byte b1; + if (!m_InStream.ReadByte(b1)) + return S_FALSE; + packSize--; + M = (UInt32)b1 + 16; + } + L = 0; + if ((b & 0x10) == 0) + { + // Literals only + L = M; + M = 0; + } + } + + // ERROR codes + else if ((b & 0xF0) == 0x70) // 0111xxxx + return S_FALSE; + else if ((b & 0xF0) == 0xD0) // 1101xxxx + return S_FALSE; + + else + { + if ((b & 0xE0) == 0xA0) + { + // medium - 101LLMMM DDDDDDMM DDDDDDDD + if (packSize < 2) + return S_FALSE; + Byte b1; + if (!m_InStream.ReadByte(b1)) + return S_FALSE; + packSize--; + + Byte b2; + if (!m_InStream.ReadByte(b2)) + return S_FALSE; + packSize--; + L = (((UInt32)b >> 3) & 3); + M = (((UInt32)b & 7) << 2) + (b1 & 3); + D = ((UInt32)b1 >> 2) + ((UInt32)b2 << 6); + } + else + { + L = (UInt32)b >> 6; + M = ((UInt32)b >> 3) & 7; + if ((b & 0x7) == 6) + { + // REP - LLMMM110 + if (L == 0) + { + // spec + if (M == 0) + break; // EOS + if (M <= 2) + continue; // NOP + return S_FALSE; // UNDEFINED + } + } + else + { + if (packSize == 0) + return S_FALSE; + Byte b1; + if (!m_InStream.ReadByte(b1)) + return S_FALSE; + packSize--; + + // large - LLMMM111 DDDDDDDD DDDDDDDD + // small - LLMMMDDD DDDDDDDD + D = ((UInt32)b & 7); + if (D == 7) + { + if (packSize == 0) + return S_FALSE; + Byte b2; + if (!m_InStream.ReadByte(b2)) + return S_FALSE; + packSize--; + D = b2; + } + D = (D << 8) + b1; + } + } + + M += 3; + } + { + for (unsigned i = 0; i < L; i++) + { + if (packSize == 0 || unpackSize == 0) + return S_FALSE; + Byte b1; + if (!m_InStream.ReadByte(b1)) + return S_FALSE; + packSize--; + m_OutWindowStream.PutByte(b1); + unpackSize--; + } + } + + if (M != 0) + { + if (unpackSize == 0 || D == 0) + return S_FALSE; + unsigned cur = M; + if (cur > unpackSize) + cur = (unsigned)unpackSize; + if (!m_OutWindowStream.CopyBlock(D - 1, cur)) + return S_FALSE; + unpackSize -= cur; + if (cur != M) + return S_FALSE; + } + } + + if (unpackSize != 0) + return S_FALSE; + + // LZVN encoder writes 7 additional zero bytes + if (packSize != 7) + return S_FALSE; + do + { + Byte b; + if (!m_InStream.ReadByte(b)) + return S_FALSE; + packSize--; + if (b != 0) + return S_FALSE; + } + while (packSize != 0); + + return S_OK; +} + + + +// ---------- LZFSE ---------- + +#define MATCHES_PER_BLOCK 10000 +#define LITERALS_PER_BLOCK (4 * MATCHES_PER_BLOCK) + +#define NUM_L_SYMBOLS 20 +#define NUM_M_SYMBOLS 20 +#define NUM_D_SYMBOLS 64 +#define NUM_LIT_SYMBOLS 256 + +#define NUM_SYMBOLS ( \ + NUM_L_SYMBOLS + \ + NUM_M_SYMBOLS + \ + NUM_D_SYMBOLS + \ + NUM_LIT_SYMBOLS) + +#define NUM_L_STATES (1 << 6) +#define NUM_M_STATES (1 << 6) +#define NUM_D_STATES (1 << 8) +#define NUM_LIT_STATES (1 << 10) + + +typedef UInt32 CFseState; + + +static UInt32 SumFreqs(const UInt16 *freqs, unsigned num) +{ + UInt32 sum = 0; + for (unsigned i = 0; i < num; i++) + sum += (UInt32)freqs[i]; + return sum; +} + + +static MY_FORCE_INLINE unsigned CountZeroBits(UInt32 val, UInt32 mask) +{ + for (unsigned i = 0;;) + { + if (val & mask) + return i; + i++; + mask >>= 1; + } +} + + +static MY_FORCE_INLINE void InitLitTable(const UInt16 *freqs, UInt32 *table) +{ + for (unsigned i = 0; i < NUM_LIT_SYMBOLS; i++) + { + unsigned f = freqs[i]; + if (f == 0) + continue; + + // 0 < f <= numStates + // 0 <= k <= numStatesLog + // numStates <= (f<> k) - f; + + /* + CEntry + { + Byte k; + Byte symbol; + UInt16 delta; + }; + */ + + UInt32 e = ((UInt32)i << 8) + k; + k += 16; + UInt32 d = e + ((UInt32)f << k) - ((UInt32)NUM_LIT_STATES << 16); + UInt32 step = (UInt32)1 << k; + + unsigned j = 0; + do + { + *table++ = d; + d += step; + } + while (++j < j0); + + e--; + step >>= 1; + + for (j = j0; j < f; j++) + { + *table++ = e; + e += step; + } + } +} + + +typedef struct +{ + Byte totalBits; + Byte extraBits; + UInt16 delta; + UInt32 vbase; +} CExtraEntry; + + +static void InitExtraDecoderTable(unsigned numStates, + unsigned numSymbols, + const UInt16 *freqs, + const Byte *vbits, + CExtraEntry *table) +{ + UInt32 vbase = 0; + + for (unsigned i = 0; i < numSymbols; i++) + { + unsigned f = freqs[i]; + unsigned extraBits = vbits[i]; + + if (f != 0) + { + unsigned k = CountZeroBits(f, numStates); + unsigned j0 = ((2 * numStates) >> k) - f; + + unsigned j = 0; + do + { + CExtraEntry *e = table++; + e->totalBits = (Byte)(k + extraBits); + e->extraBits = (Byte)extraBits; + e->delta = (UInt16)(((f + j) << k) - numStates); + e->vbase = vbase; + } + while (++j < j0); + + f -= j0; + k--; + + for (j = 0; j < f; j++) + { + CExtraEntry *e = table++; + e->totalBits = (Byte)(k + extraBits); + e->extraBits = (Byte)extraBits; + e->delta = (UInt16)(j << k); + e->vbase = vbase; + } + } + + vbase += ((UInt32)1 << extraBits); + } +} + + +static const Byte k_L_extra[NUM_L_SYMBOLS] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 5, 8 +}; + +static const Byte k_M_extra[NUM_M_SYMBOLS] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11 +}; + +static const Byte k_D_extra[NUM_D_SYMBOLS] = +{ + 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, + 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, + 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15 +}; + + + +// ---------- CBitStream ---------- + +typedef struct +{ + UInt32 accum; + unsigned numBits; // [0, 31] - Number of valid bits in (accum), other bits are 0 +} CBitStream; + + +static MY_FORCE_INLINE int FseInStream_Init(CBitStream *s, + int n, // [-7, 0], (-n == number_of_unused_bits) in last byte + const Byte **pbuf) +{ + *pbuf -= 4; + s->accum = GetUi32(*pbuf); + if (n) + { + s->numBits = n + 32; + if ((s->accum >> s->numBits) != 0) + return -1; // ERROR, encoder should have zeroed the upper bits + } + else + { + *pbuf += 1; + s->accum >>= 8; + s->numBits = 24; + } + return 0; // OK +} + + +// 0 <= numBits < 32 +#define mask31(x, numBits) ((x) & (((UInt32)1 << (numBits)) - 1)) + +#define FseInStream_FLUSH \ + { unsigned nbits = (31 - in.numBits) & -8; \ + if (nbits) { \ + buf -= (nbits >> 3); \ + if (buf < buf_check) return S_FALSE; \ + UInt32 v = GetUi32(buf); \ + in.accum = (in.accum << nbits) | mask31(v, nbits); \ + in.numBits += nbits; }} + + + +static MY_FORCE_INLINE UInt32 BitStream_Pull(CBitStream *s, unsigned numBits) +{ + s->numBits -= numBits; + UInt32 v = s->accum >> s->numBits; + s->accum = mask31(s->accum, s->numBits); + return v; +} + + +#define DECODE_LIT(dest, pstate) { \ + UInt32 e = lit_decoder[pstate]; \ + pstate = (CFseState)((e >> 16) + BitStream_Pull(&in, e & 0xff)); \ + dest = (Byte)(e >> 8); } + + +static MY_FORCE_INLINE UInt32 FseDecodeExtra(CFseState *pstate, + const CExtraEntry *table, + CBitStream *s) +{ + const CExtraEntry *e = &table[*pstate]; + UInt32 v = BitStream_Pull(s, e->totalBits); + unsigned extraBits = e->extraBits; + *pstate = (CFseState)(e->delta + (v >> extraBits)); + return e->vbase + mask31(v, extraBits); +} + + +#define freqs_L (freqs) +#define freqs_M (freqs_L + NUM_L_SYMBOLS) +#define freqs_D (freqs_M + NUM_M_SYMBOLS) +#define freqs_LIT (freqs_D + NUM_D_SYMBOLS) + +#define GET_BITS_64(v, offset, num, dest) dest = (UInt32) ((v >> (offset)) & ((1 << (num)) - 1)); +#define GET_BITS_32(v, offset, num, dest) dest = (CFseState)((v >> (offset)) & ((1 << (num)) - 1)); + + +HRESULT CDecoder::DecodeLzfse(UInt32 unpackSize, Byte version) +{ + PRF(printf("\nLZFSE-%d %7u", version - '0', unpackSize)); + + UInt32 numLiterals; + UInt32 litPayloadSize; + Int32 literal_bits; + + UInt32 lit_state_0; + UInt32 lit_state_1; + UInt32 lit_state_2; + UInt32 lit_state_3; + + UInt32 numMatches; + UInt32 lmdPayloadSize; + Int32 lmd_bits; + + CFseState l_state; + CFseState m_state; + CFseState d_state; + + UInt16 freqs[NUM_SYMBOLS]; + + if (version == kSignature_LZFSE_V1) + { + return E_NOTIMPL; + // we need examples to test LZFSE-V1 code + /* + const unsigned k_v1_SubHeaderSize = 7 * 4 + 7 * 2; + const unsigned k_v1_HeaderSize = k_v1_SubHeaderSize + NUM_SYMBOLS * 2; + _buffer.AllocAtLeast(k_v1_HeaderSize); + if (m_InStream.ReadBytes(_buffer, k_v1_HeaderSize) != k_v1_HeaderSize) + return S_FALSE; + + const Byte *buf = _buffer; + #define GET_32(offs, dest) dest = GetUi32(buf + offs) + #define GET_16(offs, dest) dest = GetUi16(buf + offs) + + UInt32 payload_bytes; + GET_32(0, payload_bytes); + GET_32(4, numLiterals); + GET_32(8, numMatches); + GET_32(12, litPayloadSize); + GET_32(16, lmdPayloadSize); + if (litPayloadSize > (1 << 20) || lmdPayloadSize > (1 << 20)) + return S_FALSE; + GET_32(20, literal_bits); + if (literal_bits < -7 || literal_bits > 0) + return S_FALSE; + + GET_16(24, lit_state_0); + GET_16(26, lit_state_1); + GET_16(28, lit_state_2); + GET_16(30, lit_state_3); + + GET_32(32, lmd_bits); + if (lmd_bits < -7 || lmd_bits > 0) + return S_FALSE; + + GET_16(36, l_state); + GET_16(38, m_state); + GET_16(40, d_state); + + for (unsigned i = 0; i < NUM_SYMBOLS; i++) + freqs[i] = GetUi16(buf + k_v1_SubHeaderSize + i * 2); + */ + } + else + { + UInt32 headerSize; + { + const unsigned kPreHeaderSize = 4 * 2; // signature and upackSize + const unsigned kHeaderSize = 8 * 3; + Byte temp[kHeaderSize]; + if (m_InStream.ReadBytes(temp, kHeaderSize) != kHeaderSize) + return S_FALSE; + + UInt64 v; + + v = GetUi64(temp); + GET_BITS_64(v, 0, 20, numLiterals); + GET_BITS_64(v, 20, 20, litPayloadSize); + GET_BITS_64(v, 40, 20, numMatches); + GET_BITS_64(v, 60, 3 + 1, literal_bits); // (NumberOfUsedBits - 1) + literal_bits -= 7; // (-NumberOfUnusedBits) + if (literal_bits > 0) + return S_FALSE; + // GET_BITS_64(v, 63, 1, unused); + + v = GetUi64(temp + 8); + GET_BITS_64(v, 0, 10, lit_state_0); + GET_BITS_64(v, 10, 10, lit_state_1); + GET_BITS_64(v, 20, 10, lit_state_2); + GET_BITS_64(v, 30, 10, lit_state_3); + GET_BITS_64(v, 40, 20, lmdPayloadSize); + GET_BITS_64(v, 60, 3 + 1, lmd_bits); + lmd_bits -= 7; + if (lmd_bits > 0) + return S_FALSE; + // GET_BITS_64(v, 63, 1, unused) + + UInt32 v32 = GetUi32(temp + 20); + // (total header size in bytes; this does not + // correspond to a field in the uncompressed header version, + // but is required; we wouldn't know the size of the + // compresssed header otherwise. + GET_BITS_32(v32, 0, 10, l_state); + GET_BITS_32(v32, 10, 10, m_state); + GET_BITS_32(v32, 20, 10 + 2, d_state); + // GET_BITS_64(v, 62, 2, unused); + + headerSize = GetUi32(temp + 16); + if (headerSize <= kPreHeaderSize + kHeaderSize) + return S_FALSE; + headerSize -= kPreHeaderSize + kHeaderSize; + } + + // no freqs case is not allowed ? + // memset(freqs, 0, sizeof(freqs)); + // if (headerSize != 0) + { + static const Byte numBitsTable[32] = + { + 2, 3, 2, 5, 2, 3, 2, 8, 2, 3, 2, 5, 2, 3, 2, 14, + 2, 3, 2, 5, 2, 3, 2, 8, 2, 3, 2, 5, 2, 3, 2, 14 + }; + + static const Byte valueTable[32] = + { + 0, 2, 1, 4, 0, 3, 1, 8, 0, 2, 1, 5, 0, 3, 1, 24, + 0, 2, 1, 6, 0, 3, 1, 8, 0, 2, 1, 7, 0, 3, 1, 24 + }; + + UInt32 accum = 0; + unsigned numBits = 0; + + for (unsigned i = 0; i < NUM_SYMBOLS; i++) + { + while (numBits <= 14 && headerSize != 0) + { + Byte b; + if (!m_InStream.ReadByte(b)) + return S_FALSE; + accum |= (UInt32)b << numBits; + numBits += 8; + headerSize--; + } + + unsigned b = (unsigned)accum & 31; + unsigned n = numBitsTable[b]; + if (numBits < n) + return S_FALSE; + numBits -= n; + UInt32 f = valueTable[b]; + if (n >= 8) + f += ((accum >> 4) & (0x3ff >> (14 - n))); + accum >>= n; + freqs[i] = (UInt16)f; + } + + if (numBits >= 8 || headerSize != 0) + return S_FALSE; + } + } + + PRF(printf(" Literals=%6u Matches=%6u", numLiterals, numMatches)); + + if (numLiterals > LITERALS_PER_BLOCK + || (numLiterals & 3) != 0 + || numMatches > MATCHES_PER_BLOCK + || lit_state_0 >= NUM_LIT_STATES + || lit_state_1 >= NUM_LIT_STATES + || lit_state_2 >= NUM_LIT_STATES + || lit_state_3 >= NUM_LIT_STATES + || l_state >= NUM_L_STATES + || m_state >= NUM_M_STATES + || d_state >= NUM_D_STATES) + return S_FALSE; + + // only full table is allowed ? + if ( SumFreqs(freqs_L, NUM_L_SYMBOLS) != NUM_L_STATES + || SumFreqs(freqs_M, NUM_M_SYMBOLS) != NUM_M_STATES + || SumFreqs(freqs_D, NUM_D_SYMBOLS) != NUM_D_STATES + || SumFreqs(freqs_LIT, NUM_LIT_SYMBOLS) != NUM_LIT_STATES) + return S_FALSE; + + + const unsigned kPad = 16; + + // ---------- Decode literals ---------- + + { + _literals.AllocAtLeast(LITERALS_PER_BLOCK + 16); + _buffer.AllocAtLeast(kPad + litPayloadSize); + memset(_buffer, 0, kPad); + + if (m_InStream.ReadBytes(_buffer + kPad, litPayloadSize) != litPayloadSize) + return S_FALSE; + + UInt32 lit_decoder[NUM_LIT_STATES]; + InitLitTable(freqs_LIT, lit_decoder); + + const Byte *buf_start = _buffer + kPad; + const Byte *buf_check = buf_start - 4; + const Byte *buf = buf_start + litPayloadSize; + CBitStream in; + if (FseInStream_Init(&in, literal_bits, &buf) != 0) + return S_FALSE; + + Byte *lit = _literals; + const Byte *lit_limit = lit + numLiterals; + for (; lit < lit_limit; lit += 4) + { + FseInStream_FLUSH + DECODE_LIT (lit[0], lit_state_0); + DECODE_LIT (lit[1], lit_state_1); + FseInStream_FLUSH + DECODE_LIT (lit[2], lit_state_2); + DECODE_LIT (lit[3], lit_state_3); + } + + if ((buf_start - buf) * 8 != (int)in.numBits) + return S_FALSE; + } + + + // ---------- Decode LMD ---------- + + _buffer.AllocAtLeast(kPad + lmdPayloadSize); + memset(_buffer, 0, kPad); + if (m_InStream.ReadBytes(_buffer + kPad, lmdPayloadSize) != lmdPayloadSize) + return S_FALSE; + + CExtraEntry l_decoder[NUM_L_STATES]; + CExtraEntry m_decoder[NUM_M_STATES]; + CExtraEntry d_decoder[NUM_D_STATES]; + + InitExtraDecoderTable(NUM_L_STATES, NUM_L_SYMBOLS, freqs_L, k_L_extra, l_decoder); + InitExtraDecoderTable(NUM_M_STATES, NUM_M_SYMBOLS, freqs_M, k_M_extra, m_decoder); + InitExtraDecoderTable(NUM_D_STATES, NUM_D_SYMBOLS, freqs_D, k_D_extra, d_decoder); + + const Byte *buf_start = _buffer + kPad; + const Byte *buf_check = buf_start - 4; + const Byte *buf = buf_start + lmdPayloadSize; + CBitStream in; + if (FseInStream_Init(&in, lmd_bits, &buf)) + return S_FALSE; + + const Byte *lit = _literals; + const Byte *lit_limit = lit + numLiterals; + + UInt32 D = 0; + + for (;;) + { + if (numMatches == 0) + break; + numMatches--; + + FseInStream_FLUSH + + unsigned L = (unsigned)FseDecodeExtra(&l_state, l_decoder, &in); + + FseInStream_FLUSH + + unsigned M = (unsigned)FseDecodeExtra(&m_state, m_decoder, &in); + + FseInStream_FLUSH + + { + UInt32 new_D = FseDecodeExtra(&d_state, d_decoder, &in); + if (new_D) + D = new_D; + } + + if (L != 0) + { + if (L > (size_t)(lit_limit - lit)) + return S_FALSE; + unsigned cur = L; + if (cur > unpackSize) + cur = (unsigned)unpackSize; + m_OutWindowStream.PutBytes(lit, cur); + unpackSize -= cur; + lit += cur; + if (cur != L) + return S_FALSE; + } + + if (M != 0) + { + if (unpackSize == 0 || D == 0) + return S_FALSE; + unsigned cur = M; + if (cur > unpackSize) + cur = (unsigned)unpackSize; + if (!m_OutWindowStream.CopyBlock(D - 1, cur)) + return S_FALSE; + unpackSize -= cur; + if (cur != M) + return S_FALSE; + } + } + + if (unpackSize != 0) + return S_FALSE; + + // LZFSE encoder writes 8 additional zero bytes before LMD payload + // We test it: + if ((buf - buf_start) * 8 + in.numBits != 64) + return S_FALSE; + if (GetUi64(buf_start) != 0) + return S_FALSE; + + return S_OK; +} + + +STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + PRF(printf("\n\nLzfseDecoder %7u %7u\n", (unsigned)*outSize, (unsigned)*inSize)); + + const UInt32 kLzfseDictSize = 1 << 18; + if (!m_OutWindowStream.Create(kLzfseDictSize)) + return E_OUTOFMEMORY; + if (!m_InStream.Create(1 << 18)) + return E_OUTOFMEMORY; + + m_OutWindowStream.SetStream(outStream); + m_OutWindowStream.Init(false); + m_InStream.SetStream(inStream); + m_InStream.Init(); + + CCoderReleaser coderReleaser(this); + + UInt64 prevOut = 0; + UInt64 prevIn = 0; + + for (;;) + { + const UInt64 pos = m_OutWindowStream.GetProcessedSize(); + const UInt64 packPos = m_InStream.GetProcessedSize(); + + if (progress && ((pos - prevOut) >= (1 << 22) || (packPos - prevIn) >= (1 << 22))) + { + RINOK(progress->SetRatioInfo(&packPos, &pos)); + prevIn = packPos; + prevOut = pos; + } + + const UInt64 rem = *outSize - pos; + UInt32 v; + RINOK(GetUInt32(v)) + if ((v & 0xFFFFFF) != 0x787662) // bvx + return S_FALSE; + v >>= 24; + + if (v == 0x24) // '$', end of stream + break; + + UInt32 unpackSize; + RINOK(GetUInt32(unpackSize)); + + UInt32 cur = unpackSize; + if (cur > rem) + cur = (UInt32)rem; + + unpackSize -= cur; + + HRESULT res; + if (v == kSignature_LZFSE_V1 || v == kSignature_LZFSE_V2) + res = DecodeLzfse(cur, (Byte)v); + else if (v == 0x6E) // 'n' + res = DecodeLzvn(cur); + else if (v == 0x2D) // '-' + res = DecodeUncompressed(cur); + else + return E_NOTIMPL; + + if (res != S_OK) + return res; + + if (unpackSize != 0) + return S_FALSE; + } + + coderReleaser.NeedFlush = false; + HRESULT res = m_OutWindowStream.Flush(); + if (res == S_OK) + if (*inSize != m_InStream.GetProcessedSize() + || *outSize != m_OutWindowStream.GetProcessedSize()) + res = S_FALSE; + return res; +} + + +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + try { return CodeReal(inStream, outStream, inSize, outSize, progress); } + catch(const CInBufferException &e) { return e.ErrorCode; } + catch(const CLzOutWindowException &e) { return e.ErrorCode; } + catch(...) { return E_OUTOFMEMORY; } + // catch(...) { return S_FALSE; } +} + +}} diff --git a/CPP/7zip/Compress/LzfseDecoder.h b/CPP/7zip/Compress/LzfseDecoder.h new file mode 100644 index 00000000..0156a087 --- /dev/null +++ b/CPP/7zip/Compress/LzfseDecoder.h @@ -0,0 +1,58 @@ +// LzfseDecoder.h + +#ifndef __LZFSE_DECODER_H +#define __LZFSE_DECODER_H + +#include "../../Common/MyBuffer.h" +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +#include "../Common/InBuffer.h" + +#include "LzOutWindow.h" + +namespace NCompress { +namespace NLzfse { + +class CDecoder: + public ICompressCoder, + public CMyUnknownImp +{ + CLzOutWindow m_OutWindowStream; + CInBuffer m_InStream; + CByteBuffer _literals; + CByteBuffer _buffer; + + class CCoderReleaser + { + CDecoder *m_Coder; + public: + bool NeedFlush; + CCoderReleaser(CDecoder *coder): m_Coder(coder), NeedFlush(true) {} + ~CCoderReleaser() + { + if (NeedFlush) + m_Coder->m_OutWindowStream.Flush(); + } + }; + friend class CCoderReleaser; + + HRESULT GetUInt32(UInt32 &val); + + HRESULT DecodeUncompressed(UInt32 unpackSize); + HRESULT DecodeLzvn(UInt32 unpackSize); + HRESULT DecodeLzfse(UInt32 unpackSize, Byte version); + + STDMETHOD(CodeReal)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); +public: + MY_UNKNOWN_IMP + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, + const UInt64 *outSize, ICompressProgressInfo *progress); +}; + +}} + +#endif diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp index e52e47d0..1c2e3397 100644 --- a/CPP/7zip/UI/Agent/Agent.cpp +++ b/CPP/7zip/UI/Agent/Agent.cpp @@ -1217,7 +1217,12 @@ STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) NWindows::NCOM::CPropVariant prop; if (propID == kpidReadOnly) - prop = _agentSpec->IsThereReadOnlyArc(); + { + if (_agentSpec->Is_Attrib_ReadOnly()) + prop = true; + else + prop = _agentSpec->IsThereReadOnlyArc(); + } else if (_proxy2) { const CProxyDir2 &dir = _proxy2->Dirs[_proxyDirIndex]; @@ -1564,6 +1569,7 @@ STDMETHODIMP CAgent::Open( { COM_TRY_BEGIN _archiveFilePath = filePath; + _attrib = 0; NFile::NFind::CFileInfo fi; _isDeviceFile = false; if (!inStream) @@ -1572,6 +1578,7 @@ STDMETHODIMP CAgent::Open( return ::GetLastError(); if (fi.IsDir()) return E_FAIL; + _attrib = fi.Attrib; _isDeviceFile = fi.IsDevice; } CArcInfoEx archiverInfo0, archiverInfo1; diff --git a/CPP/7zip/UI/Agent/Agent.h b/CPP/7zip/UI/Agent/Agent.h index ae4026d6..7ba96f4a 100644 --- a/CPP/7zip/UI/Agent/Agent.h +++ b/CPP/7zip/UI/Agent/Agent.h @@ -241,6 +241,7 @@ public: CAgentFolder *_agentFolder; UString _archiveFilePath; + DWORD _attrib; bool _isDeviceFile; #ifndef EXTRACT_ONLY @@ -252,6 +253,11 @@ public: IInArchive *GetArchive() const { if ( _archiveLink.Arcs.IsEmpty()) return 0; return GetArc().Archive; } bool CanUpdate() const; + bool Is_Attrib_ReadOnly() const + { + return _attrib != INVALID_FILE_ATTRIBUTES && (_attrib & FILE_ATTRIBUTE_READONLY); + } + bool IsThereReadOnlyArc() const { FOR_VECTOR (i, _archiveLink.Arcs) diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp index 0571a452..083e7c84 100644 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp @@ -372,6 +372,8 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat HRESULT CArchiveExtractCallback::GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined) { filetimeIsDefined = false; + filetime.dwLowDateTime = 0; + filetime.dwHighDateTime = 0; NCOM::CPropVariant prop; RINOK(_arc->Archive->GetProperty(index, propID, &prop)); if (prop.vt == VT_FILETIME) @@ -1032,14 +1034,36 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) { FString fullPathNew; CreateComplexDirectory(pathParts, fullPathNew); + if (_item.IsDir) { - _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)); + CDirPathTime &pt = _extractedFolders.AddNew(); + + pt.CTime = _fi.CTime; + pt.CTimeDefined = (WriteCTime && _fi.CTimeDefined); + + pt.ATime = _fi.ATime; + pt.ATimeDefined = (WriteATime && _fi.ATimeDefined); + + pt.MTimeDefined = false; + + if (WriteMTime) + { + if (_fi.MTimeDefined) + { + pt.MTime = _fi.MTime; + pt.MTimeDefined = true; + } + else if (_arc->MTimeDefined) + { + pt.MTime = _arc->MTime; + pt.MTimeDefined = true; + } + } + + pt.Path = fullPathNew; + + pt.SetDirTime(); } } } @@ -1602,75 +1626,53 @@ STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) } -struct CExtrRefSortPair -{ - unsigned Len; - unsigned 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 unsigned GetNumSlashes(const FChar *s) +void CDirPathSortPair::SetNumSlashes(const FChar *s) { for (unsigned numSlashes = 0;;) { FChar c = *s++; if (c == 0) - return numSlashes; + { + Len = numSlashes; + return; + } if (IS_PATH_SEPAR(c)) numSlashes++; } } +bool CDirPathTime::SetDirTime() +{ + return NDir::SetDirTime(Path, + CTimeDefined ? &CTime : NULL, + ATimeDefined ? &ATime : NULL, + MTimeDefined ? &MTime : NULL); +} + + HRESULT CArchiveExtractCallback::SetDirsTimes() { if (!_arc) return S_OK; - CRecordVector pairs; - pairs.ClearAndSetSize(_extractedFolderPaths.Size()); + CRecordVector pairs; + pairs.ClearAndSetSize(_extractedFolders.Size()); unsigned i; - for (i = 0; i < _extractedFolderPaths.Size(); i++) + for (i = 0; i < _extractedFolders.Size(); i++) { - CExtrRefSortPair &pair = pairs[i]; + CDirPathSortPair &pair = pairs[i]; pair.Index = i; - pair.Len = GetNumSlashes(_extractedFolderPaths[i]); + pair.SetNumSlashes(_extractedFolders[i].Path); } pairs.Sort2(); for (i = 0; i < pairs.Size(); i++) { - unsigned pairIndex = pairs[i].Index; - UInt32 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)); + _extractedFolders[pairs[i].Index].SetDirTime(); + // if (!) return GetLastError(); } ClearExtractedDirsInfo(); diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h index 4b96b523..dd5c98c0 100644 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h @@ -151,6 +151,25 @@ struct CIndexToPathPair #endif + + +struct CDirPathTime +{ + FILETIME CTime; + FILETIME ATime; + FILETIME MTime; + + bool CTimeDefined; + bool ATimeDefined; + bool MTimeDefined; + + FString Path; + + bool SetDirTime(); +}; + + + class CArchiveExtractCallback: public IArchiveExtractCallback, public IArchiveExtractCallbackMessage, @@ -241,8 +260,7 @@ class CArchiveExtractCallback: UInt64 _progressTotal; bool _progressTotal_Defined; - FStringVector _extractedFolderPaths; - CRecordVector _extractedFolderIndices; + CObjectVector _extractedFolders; #if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX) bool _saclEnabled; @@ -348,8 +366,7 @@ public: private: void ClearExtractedDirsInfo() { - _extractedFolderPaths.Clear(); - _extractedFolderIndices.Clear(); + _extractedFolders.Clear(); } HRESULT CloseFile(); diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp index 69817179..b9b4abd9 100644 --- a/CPP/7zip/UI/Common/OpenArchive.cpp +++ b/CPP/7zip/UI/Common/OpenArchive.cpp @@ -857,7 +857,7 @@ HRESULT CArc::GetItem(UInt32 index, CReadArcItem &item) const if (item.WriteToAltStreamIfColon || needFindAltStream) { - /* Good handler must support GetRawProps::GetParent for alt streams./ + /* Good handler must support GetRawProps::GetParent for alt streams. So the following code currently is not used */ int colon = FindAltStreamColon_in_Path(item.Path); if (colon >= 0) diff --git a/CPP/7zip/UI/Common/OpenArchive.h b/CPP/7zip/UI/Common/OpenArchive.h index d46d69e8..6eb0d395 100644 --- a/CPP/7zip/UI/Common/OpenArchive.h +++ b/CPP/7zip/UI/Common/OpenArchive.h @@ -414,4 +414,23 @@ struct CArchiveLink bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector &types); + +struct CDirPathSortPair +{ + unsigned Len; + unsigned Index; + + void SetNumSlashes(const FChar *s); + + int Compare(const CDirPathSortPair &a) const + { + // We need sorting order where parent items will be after child items + if (Len < a.Len) return 1; + if (Len > a.Len) return -1; + if (Index < a.Index) return -1; + if (Index > a.Index) return 1; + return 0; + } +}; + #endif diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp index f1826957..5d3c4484 100644 --- a/CPP/7zip/UI/Common/Update.cpp +++ b/CPP/7zip/UI/Common/Update.cpp @@ -1046,32 +1046,6 @@ static HRESULT EnumerateInArchiveItems( #endif -struct CRefSortPair -{ - unsigned Len; - unsigned Index; -}; - -#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } - -static int CompareRefSortPair(const CRefSortPair *a1, const CRefSortPair *a2, void *) -{ - RINOZ(-MyCompare(a1->Len, a2->Len)); - return MyCompare(a1->Index, a2->Index); -} - -static unsigned GetNumSlashes(const FChar *s) -{ - for (unsigned numSlashes = 0;;) - { - FChar c = *s++; - if (c == 0) - return numSlashes; - if (IS_PATH_SEPAR(c)) - numSlashes++; - } -} - #ifdef _WIN32 void ConvertToLongNames(NWildcard::CCensor &censor); #endif @@ -1190,6 +1164,16 @@ HRESULT UpdateArchive( throw "there is no such archive"; if (fi.IsDevice) return E_NOTIMPL; + + if (!options.StdOutMode && options.UpdateArchiveItself) + if (fi.IsReadOnly()) + { + errorInfo.SystemError = ERROR_ACCESS_DENIED; + errorInfo.Message = "The file is read-only"; + errorInfo.FileNames.Add(arcPath); + return errorInfo.Get_HRESULT_Error(); + } + if (options.VolumesSizes.Size() > 0) { errorInfo.FileNames.Add(us2fs(arcPath)); @@ -1510,9 +1494,13 @@ HRESULT UpdateArchive( CArchivePath &ap = options.Commands[0].ArchivePath; const FString &tempPath = ap.GetTempPath(); + // DWORD attrib = 0; if (thereIsInArchive) + { + // attrib = NFind::GetFileAttrib(us2fs(arcPath)); if (!DeleteFileAlways(us2fs(arcPath))) return errorInfo.SetFromLastError("cannot delete the file", us2fs(arcPath)); + } if (!MyMoveFile(tempPath, us2fs(arcPath))) { @@ -1520,6 +1508,15 @@ HRESULT UpdateArchive( errorInfo.FileNames.Add(us2fs(arcPath)); return errorInfo.Get_HRESULT_Error(); } + + /* + if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY)) + { + DWORD attrib2 = NFind::GetFileAttrib(us2fs(arcPath)); + if (attrib2 != INVALID_FILE_ATTRIBUTES) + NDir::SetFileAttrib(us2fs(arcPath), attrib2 | FILE_ATTRIBUTE_READONLY); + } + */ } catch(...) { @@ -1609,7 +1606,7 @@ HRESULT UpdateArchive( if (options.DeleteAfterCompressing) { - CRecordVector pairs; + CRecordVector pairs; FStringVector foldersNames; unsigned i; @@ -1617,12 +1614,12 @@ HRESULT UpdateArchive( for (i = 0; i < dirItems.Items.Size(); i++) { const CDirItem &dirItem = dirItems.Items[i]; - FString phyPath = dirItems.GetPhyPath(i); + const FString phyPath = dirItems.GetPhyPath(i); if (dirItem.IsDir()) { - CRefSortPair pair; + CDirPathSortPair pair; pair.Index = i; - pair.Len = GetNumSlashes(phyPath); + pair.SetNumSlashes(phyPath); pairs.Add(pair); } else @@ -1655,11 +1652,11 @@ HRESULT UpdateArchive( } } - pairs.Sort(CompareRefSortPair, NULL); + pairs.Sort2(); for (i = 0; i < pairs.Size(); i++) { - FString phyPath = dirItems.GetPhyPath(pairs[i].Index); + const FString phyPath = dirItems.GetPhyPath(pairs[i].Index); if (NFind::DoesDirExist(phyPath)) { RINOK(callback->DeletingAfterArchiving(phyPath, true)); diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp index 72e0b7f7..62b11c10 100644 --- a/CPP/Windows/FileDir.cpp +++ b/CPP/Windows/FileDir.cpp @@ -667,12 +667,27 @@ bool CTempFile::Remove() bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore) { + // DWORD attrib = 0; if (deleteDestBefore) + { if (NFind::DoesFileExist(name)) + { + // attrib = NFind::GetFileAttrib(name); if (!DeleteFileAlways(name)) return false; + } + } DisableDeleting(); return MyMoveFile(_path, name); + + /* + if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY)) + { + DWORD attrib2 = NFind::GetFileAttrib(name); + if (attrib2 != INVALID_FILE_ATTRIBUTES) + SetFileAttrib(name, attrib2 | FILE_ATTRIBUTE_READONLY); + } + */ } bool CTempDir::Create(CFSTR prefix) diff --git a/DOC/7zip.inf b/DOC/7zip.inf index b7bcfa3d..9bd74d52 100644 --- a/DOC/7zip.inf +++ b/DOC/7zip.inf @@ -10,8 +10,8 @@ AppName = "7-Zip" InstallDir = %CE1%\%AppName% [Strings] -AppVer = "18.00" -AppDate = "2018-01-10" +AppVer = "18.01" +AppDate = "2018-01-28" [CEDevice] ; ProcessorType = 2577 ; ARM diff --git a/DOC/7zip.nsi b/DOC/7zip.nsi index 56b134b7..5483e5fb 100644 --- a/DOC/7zip.nsi +++ b/DOC/7zip.nsi @@ -2,8 +2,8 @@ ;Defines !define VERSION_MAJOR 18 -!define VERSION_MINOR 00 -!define VERSION_POSTFIX_FULL " beta" +!define VERSION_MINOR 01 +!define VERSION_POSTFIX_FULL "" !ifdef WIN64 !ifdef IA64 !define VERSION_SYS_POSTFIX_FULL " for Windows IA-64" diff --git a/DOC/7zip.wxs b/DOC/7zip.wxs index cdd40015..96969d93 100644 --- a/DOC/7zip.wxs +++ b/DOC/7zip.wxs @@ -1,7 +1,7 @@ - + diff --git a/DOC/License.txt b/DOC/License.txt index bcd31d65..cf3741b6 100644 --- a/DOC/License.txt +++ b/DOC/License.txt @@ -5,13 +5,18 @@ 7-Zip Copyright (C) 1999-2018 Igor Pavlov. - Licenses for files are: + The licenses for files are: + + 1) CPP/7zip/Compress/Rar* files: the "GNU LGPL" with "unRAR license restriction" + 2) CPP/7zip/Compress/LzfseDecoder.cpp: the "BSD 3-clause License" + 3) Some files are "public domain" files, if "public domain" status is stated in source file. + 4) the "GNU LGPL" for all other files. If there is no license information in + some source file, that file is under the "GNU LGPL". + + The "GNU LGPL" with "unRAR license restriction" means that you must follow both + "GNU LGPL" rules and "unRAR license restriction" rules. - 1) CPP/7zip/Compress/Rar* files: GNU LGPL + unRAR restriction - 2) All other files: GNU LGPL - The GNU LGPL + unRAR restriction means that you must follow both - GNU LGPL rules and unRAR restriction rules. GNU LGPL information @@ -32,8 +37,41 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - unRAR restriction - ----------------- + + + BSD 3-clause License + -------------------- + + The "BSD 3-clause License" is used for the code in LzfseDecoder.cpp that implements LZFSE data decompression. + That code was derived from the code in the "LZFSE compression library" developed by Apple Inc, + that also uses the "BSD 3-clause License": + + ---- + Copyright (c) 2015-2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---- + + + + + unRAR license restriction + ------------------------- The decompression engine for RAR archives was developed using source code of unRAR program. diff --git a/DOC/readme.txt b/DOC/readme.txt index 4979093a..9907ff83 100644 --- a/DOC/readme.txt +++ b/DOC/readme.txt @@ -1,5 +1,5 @@ -7-Zip 18.00 beta Sources ------------------------- +7-Zip 18.01 Sources +------------------- 7-Zip is a file archiver for Windows. -- cgit v1.2.3