mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-07 09:15:00 -06:00
18.01
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
#define MY_VER_MAJOR 18
|
#define MY_VER_MAJOR 18
|
||||||
#define MY_VER_MINOR 00
|
#define MY_VER_MINOR 01
|
||||||
#define MY_VER_BUILD 0
|
#define MY_VER_BUILD 0
|
||||||
#define MY_VERSION_NUMBERS "18.00 beta"
|
#define MY_VERSION_NUMBERS "18.01"
|
||||||
#define MY_VERSION MY_VERSION_NUMBERS
|
#define MY_VERSION MY_VERSION_NUMBERS
|
||||||
|
|
||||||
#ifdef MY_CPU_NAME
|
#ifdef MY_CPU_NAME
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
#define MY_VERSION_CPU MY_VERSION
|
#define MY_VERSION_CPU MY_VERSION
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MY_DATE "2018-01-10"
|
#define MY_DATE "2018-01-28"
|
||||||
#undef MY_COPYRIGHT
|
#undef MY_COPYRIGHT
|
||||||
#undef MY_VERSION_COPYRIGHT_DATE
|
#undef MY_VERSION_COPYRIGHT_DATE
|
||||||
#define MY_AUTHOR_NAME "Igor Pavlov"
|
#define MY_AUTHOR_NAME "Igor Pavlov"
|
||||||
|
|||||||
17
C/XzDec.c
17
C/XzDec.c
@@ -1,5 +1,5 @@
|
|||||||
/* XzDec.c -- Xz Decode
|
/* XzDec.c -- Xz Decode
|
||||||
2017-07-27 : Igor Pavlov : Public domain */
|
2018-01-21 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include "Precomp.h"
|
#include "Precomp.h"
|
||||||
|
|
||||||
@@ -742,7 +742,8 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
|
|||||||
|
|
||||||
srcRem = srcLenOrig - *srcLen;
|
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;
|
*status = CODER_STATUS_NEEDS_MORE_INPUT;
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
@@ -820,8 +821,13 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
|
|||||||
|
|
||||||
case XZ_STATE_BLOCK_FOOTER:
|
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)++;
|
(*srcLen)++;
|
||||||
p->alignPos++;
|
p->alignPos++;
|
||||||
if (*src++ != 0)
|
if (*src++ != 0)
|
||||||
@@ -833,6 +839,11 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
|
|||||||
UInt32 cur = checkSize - p->pos;
|
UInt32 cur = checkSize - p->pos;
|
||||||
if (cur != 0)
|
if (cur != 0)
|
||||||
{
|
{
|
||||||
|
if (srcRem == 0)
|
||||||
|
{
|
||||||
|
*status = CODER_STATUS_NEEDS_MORE_INPUT;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
if (cur > srcRem)
|
if (cur > srcRem)
|
||||||
cur = (UInt32)srcRem;
|
cur = (UInt32)srcRem;
|
||||||
memcpy(p->buf + p->pos, src, cur);
|
memcpy(p->buf + p->pos, src, cur);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "../Compress/BZip2Decoder.h"
|
#include "../Compress/BZip2Decoder.h"
|
||||||
#include "../Compress/CopyCoder.h"
|
#include "../Compress/CopyCoder.h"
|
||||||
|
#include "../Compress/LzfseDecoder.h"
|
||||||
#include "../Compress/ZlibDecoder.h"
|
#include "../Compress/ZlibDecoder.h"
|
||||||
|
|
||||||
#include "Common/OutStreamWithCRC.h"
|
#include "Common/OutStreamWithCRC.h"
|
||||||
@@ -121,6 +122,7 @@ enum
|
|||||||
METHOD_ADC = 0x80000004,
|
METHOD_ADC = 0x80000004,
|
||||||
METHOD_ZLIB = 0x80000005,
|
METHOD_ZLIB = 0x80000005,
|
||||||
METHOD_BZIP2 = 0x80000006,
|
METHOD_BZIP2 = 0x80000006,
|
||||||
|
METHOD_LZFSE = 0x80000007,
|
||||||
METHOD_COMMENT = 0x7FFFFFFE, // is used to comment "+beg" and "+end" in extra field.
|
METHOD_COMMENT = 0x7FFFFFFE, // is used to comment "+beg" and "+end" in extra field.
|
||||||
METHOD_END = 0xFFFFFFFF
|
METHOD_END = 0xFFFFFFFF
|
||||||
};
|
};
|
||||||
@@ -276,6 +278,7 @@ void CMethods::GetString(AString &res) const
|
|||||||
case METHOD_ADC: s = "ADC"; break;
|
case METHOD_ADC: s = "ADC"; break;
|
||||||
case METHOD_ZLIB: s = "ZLIB"; break;
|
case METHOD_ZLIB: s = "ZLIB"; break;
|
||||||
case METHOD_BZIP2: s = "BZip2"; break;
|
case METHOD_BZIP2: s = "BZip2"; break;
|
||||||
|
case METHOD_LZFSE: s = "LZFSE"; break;
|
||||||
default: ConvertUInt32ToString(type, buf); s = buf;
|
default: ConvertUInt32ToString(type, buf); s = buf;
|
||||||
}
|
}
|
||||||
res.Add_OptSpaced(s);
|
res.Add_OptSpaced(s);
|
||||||
@@ -307,6 +310,10 @@ static const CAppleName k_Names[] =
|
|||||||
{ true, "hfs", "Apple_HFS" },
|
{ true, "hfs", "Apple_HFS" },
|
||||||
{ true, "hfsx", "Apple_HFSX" },
|
{ true, "hfsx", "Apple_HFSX" },
|
||||||
{ true, "ufs", "Apple_UFS" },
|
{ 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, "free", "Apple_Free" },
|
||||||
{ false, "ddm", "DDM" },
|
{ false, "ddm", "DDM" },
|
||||||
{ false, NULL, "Apple_partition_map" },
|
{ false, NULL, "Apple_partition_map" },
|
||||||
@@ -1247,6 +1254,11 @@ STDMETHODIMP CAdcDecoder::Code(ISequentialInStream *inStream,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||||
Int32 testMode, IArchiveExtractCallback *extractCallback)
|
Int32 testMode, IArchiveExtractCallback *extractCallback)
|
||||||
{
|
{
|
||||||
@@ -1292,6 +1304,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
|||||||
CAdcDecoder *adcCoderSpec = new CAdcDecoder();
|
CAdcDecoder *adcCoderSpec = new CAdcDecoder();
|
||||||
CMyComPtr<ICompressCoder> adcCoder = adcCoderSpec;
|
CMyComPtr<ICompressCoder> adcCoder = adcCoderSpec;
|
||||||
|
|
||||||
|
NCompress::NLzfse::CDecoder *lzfseCoderSpec = new NCompress::NLzfse::CDecoder();
|
||||||
|
CMyComPtr<ICompressCoder> lzfseCoder = lzfseCoderSpec;
|
||||||
|
|
||||||
CLocalProgress *lps = new CLocalProgress;
|
CLocalProgress *lps = new CLocalProgress;
|
||||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||||
lps->Init(extractCallback, false);
|
lps->Init(extractCallback, false);
|
||||||
@@ -1420,6 +1435,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case METHOD_LZFSE:
|
||||||
|
{
|
||||||
|
res = lzfseCoder->Code(inStream, outStream, &block.PackSize, &block.UnpSize, progress);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
opRes = NExtract::NOperationResult::kUnsupportedMethod;
|
opRes = NExtract::NOperationResult::kUnsupportedMethod;
|
||||||
break;
|
break;
|
||||||
@@ -1490,6 +1511,9 @@ class CInStream:
|
|||||||
CAdcDecoder *adcCoderSpec;
|
CAdcDecoder *adcCoderSpec;
|
||||||
CMyComPtr<ICompressCoder> adcCoder;
|
CMyComPtr<ICompressCoder> adcCoder;
|
||||||
|
|
||||||
|
NCompress::NLzfse::CDecoder *lzfseCoderSpec;
|
||||||
|
CMyComPtr<ICompressCoder> lzfseCoder;
|
||||||
|
|
||||||
CBufPtrSeqOutStream *outStreamSpec;
|
CBufPtrSeqOutStream *outStreamSpec;
|
||||||
CMyComPtr<ISequentialOutStream> outStream;
|
CMyComPtr<ISequentialOutStream> outStream;
|
||||||
|
|
||||||
@@ -1652,6 +1676,15 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
|||||||
res = S_FALSE;
|
res = S_FALSE;
|
||||||
break;
|
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:
|
default:
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
@@ -1738,6 +1771,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
|||||||
case METHOD_ADC:
|
case METHOD_ADC:
|
||||||
case METHOD_ZLIB:
|
case METHOD_ZLIB:
|
||||||
case METHOD_BZIP2:
|
case METHOD_BZIP2:
|
||||||
|
case METHOD_LZFSE:
|
||||||
case METHOD_END:
|
case METHOD_END:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -387,6 +387,10 @@ void CSection::Parse(const Byte *p)
|
|||||||
G32(36, Flags);
|
G32(36, Flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// IMAGE_FILE_*
|
||||||
|
|
||||||
static const CUInt32PCharPair g_HeaderCharacts[] =
|
static const CUInt32PCharPair g_HeaderCharacts[] =
|
||||||
{
|
{
|
||||||
{ 1, "Executable" },
|
{ 1, "Executable" },
|
||||||
@@ -406,9 +410,7 @@ static const CUInt32PCharPair g_HeaderCharacts[] =
|
|||||||
{ 15, "Big-Endian" }
|
{ 15, "Big-Endian" }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// IMAGE_DLLCHARACTERISTICS_*
|
||||||
|
|
||||||
// IMAGE_DLLCHARACTERISTICS_* constants
|
|
||||||
|
|
||||||
static const char * const g_DllCharacts[] =
|
static const char * const g_DllCharacts[] =
|
||||||
{
|
{
|
||||||
@@ -930,7 +932,9 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
|||||||
|
|
||||||
case kpidExtension:
|
case kpidExtension:
|
||||||
if (_header.IsDll())
|
if (_header.IsDll())
|
||||||
prop = _optHeader.IsSybSystem_EFI() ? "efi" : "dll";
|
prop = "dll";
|
||||||
|
else if (_optHeader.IsSybSystem_EFI())
|
||||||
|
prop = "efi";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kpidBit64: if (_optHeader.Is64Bit()) prop = true; break;
|
case kpidBit64: if (_optHeader.Is64Bit()) prop = true; break;
|
||||||
@@ -1137,9 +1141,18 @@ HRESULT CHandler::LoadDebugSections(IInStream *stream, bool &thereIsSection)
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
const unsigned kEntrySize = 28;
|
const unsigned kEntrySize = 28;
|
||||||
UInt32 numItems = debugLink.Size / kEntrySize;
|
UInt32 numItems = debugLink.Size / kEntrySize;
|
||||||
if (numItems * kEntrySize != debugLink.Size || numItems > 16)
|
if (numItems > 16)
|
||||||
return S_FALSE;
|
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;
|
UInt64 pa = 0;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
for (i = 0; i < _sections.Size(); i++)
|
for (i = 0; i < _sections.Size(); i++)
|
||||||
@@ -2191,6 +2204,9 @@ bool CHeader::ParseCoff(const Byte *p)
|
|||||||
for (unsigned i = 0; i < ARRAY_SIZE(g_MachinePairs); i++)
|
for (unsigned i = 0; i < ARRAY_SIZE(g_MachinePairs); i++)
|
||||||
if (Machine == g_MachinePairs[i].Value)
|
if (Machine == g_MachinePairs[i].Value)
|
||||||
return true;
|
return true;
|
||||||
|
if (Machine == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
|||||||
thereAreAesUpdates = true;
|
thereAreAesUpdates = true;
|
||||||
if (!IntToBool(newProps))
|
if (!IntToBool(newProps))
|
||||||
ui.IsDir = inputItem.IsDir();
|
ui.IsDir = inputItem.IsDir();
|
||||||
|
// ui.IsAltStream = inputItem.IsAltStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IntToBool(newProps))
|
if (IntToBool(newProps))
|
||||||
@@ -175,6 +176,33 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
|||||||
ui.IsDir = (prop.boolVal != VARIANT_FALSE);
|
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;
|
CPropVariant prop;
|
||||||
RINOK(callback->GetProperty(i, kpidTimeType, &prop));
|
RINOK(callback->GetProperty(i, kpidTimeType, &prop));
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ namespace NFileHeader
|
|||||||
const unsigned kDescriptorUsedMask = 1 << 3;
|
const unsigned kDescriptorUsedMask = 1 << 3;
|
||||||
const unsigned kStrongEncrypted = 1 << 6;
|
const unsigned kStrongEncrypted = 1 << 6;
|
||||||
const unsigned kUtf8 = 1 << 11;
|
const unsigned kUtf8 = 1 << 11;
|
||||||
|
const unsigned kAltStream = 1 << 14;
|
||||||
|
|
||||||
const unsigned kImplodeDictionarySizeMask = 1 << 1;
|
const unsigned kImplodeDictionarySizeMask = 1 << 1;
|
||||||
const unsigned kImplodeLiteralsOnMask = 1 << 2;
|
const unsigned kImplodeLiteralsOnMask = 1 << 2;
|
||||||
|
|||||||
@@ -20,10 +20,13 @@ class CItemEx: public CItem
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
UInt32 LocalFullHeaderSize; // including Name and Extra
|
UInt32 LocalFullHeaderSize; // including Name and Extra
|
||||||
|
// int ParentOfAltStream; // -1, if not AltStream
|
||||||
|
|
||||||
bool DescriptorWasRead;
|
bool DescriptorWasRead;
|
||||||
|
|
||||||
CItemEx(): DescriptorWasRead(false) {}
|
CItemEx():
|
||||||
|
// ParentOfAltStream(-1),
|
||||||
|
DescriptorWasRead(false) {}
|
||||||
|
|
||||||
UInt64 GetLocalFullSize() const
|
UInt64 GetLocalFullSize() const
|
||||||
{ return LocalFullHeaderSize + GetPackSizeWithDescriptor(); }
|
{ return LocalFullHeaderSize + GetPackSizeWithDescriptor(); }
|
||||||
|
|||||||
@@ -20,6 +20,12 @@ namespace NZip {
|
|||||||
|
|
||||||
using namespace NFileHeader;
|
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[] =
|
static const CUInt32PCharPair g_ExtraTypes[] =
|
||||||
{
|
{
|
||||||
{ NExtraID::kZip64, "Zip64" },
|
{ NExtraID::kZip64, "Zip64" },
|
||||||
|
|||||||
@@ -14,6 +14,11 @@
|
|||||||
namespace NArchive {
|
namespace NArchive {
|
||||||
namespace NZip {
|
namespace NZip {
|
||||||
|
|
||||||
|
/*
|
||||||
|
extern const char *k_SpecName_NTFS_STREAM;
|
||||||
|
extern const char *k_SpecName_MAC_RESOURCE_FORK;
|
||||||
|
*/
|
||||||
|
|
||||||
struct CVersion
|
struct CVersion
|
||||||
{
|
{
|
||||||
Byte Version;
|
Byte Version;
|
||||||
@@ -233,6 +238,7 @@ public:
|
|||||||
bool IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || Method == NFileHeader::NCompressionMethod::kWzAES); }
|
bool IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || Method == NFileHeader::NCompressionMethod::kWzAES); }
|
||||||
bool IsLzmaEOS() const { return (Flags & NFileHeader::NFlags::kLzmaEOS) != 0; }
|
bool IsLzmaEOS() const { return (Flags & NFileHeader::NFlags::kLzmaEOS) != 0; }
|
||||||
bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 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; }
|
unsigned GetDeflateLevel() const { return (Flags >> 1) & 3; }
|
||||||
|
|
||||||
@@ -264,6 +270,7 @@ public:
|
|||||||
void ClearFlags() { Flags = 0; }
|
void ClearFlags() { Flags = 0; }
|
||||||
void SetEncrypted(bool encrypted) { SetFlag(NFileHeader::NFlags::kEncrypted, encrypted); }
|
void SetEncrypted(bool encrypted) { SetFlag(NFileHeader::NFlags::kEncrypted, encrypted); }
|
||||||
void SetUtf8(bool isUtf8) { SetFlag(NFileHeader::NFlags::kUtf8, isUtf8); }
|
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); }
|
void SetDescriptorMode(bool useDescriptor) { SetFlag(NFileHeader::NFlags::kDescriptorUsedMask, useDescriptor); }
|
||||||
|
|
||||||
UINT GetCodePage() const { return CP_OEMCP; }
|
UINT GetCodePage() const { return CP_OEMCP; }
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ static void SetFileHeader(
|
|||||||
item.Name = ui.Name;
|
item.Name = ui.Name;
|
||||||
item.Comment = ui.Comment;
|
item.Comment = ui.Comment;
|
||||||
item.SetUtf8(ui.IsUtf8);
|
item.SetUtf8(ui.IsUtf8);
|
||||||
|
// item.SetFlag_AltStream(ui.IsAltStream);
|
||||||
item.ExternalAttrib = ui.Attrib;
|
item.ExternalAttrib = ui.Attrib;
|
||||||
item.Time = ui.Time;
|
item.Time = ui.Time;
|
||||||
item.Ntfs_MTime = ui.Ntfs_MTime;
|
item.Ntfs_MTime = ui.Ntfs_MTime;
|
||||||
@@ -280,6 +281,7 @@ public:
|
|||||||
MY_UNKNOWN_IMP
|
MY_UNKNOWN_IMP
|
||||||
void Create(IProgress *progress, bool inSizeIsMain);
|
void Create(IProgress *progress, bool inSizeIsMain);
|
||||||
void SetProgressOffset(UInt64 progressOffset);
|
void SetProgressOffset(UInt64 progressOffset);
|
||||||
|
void SetProgressOffset_NoLock(UInt64 progressOffset);
|
||||||
HRESULT SetRatioInfo(unsigned index, const UInt64 *inSize, const UInt64 *outSize);
|
HRESULT SetRatioInfo(unsigned index, const UInt64 *inSize, const UInt64 *outSize);
|
||||||
STDMETHOD(SetRatioInfo)(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;
|
ProgressOffset = InSizes[0] = InSizes[1] = OutSizes[0] = OutSizes[1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMtProgressMixer2::SetProgressOffset_NoLock(UInt64 progressOffset)
|
||||||
|
{
|
||||||
|
InSizes[1] = OutSizes[1] = 0;
|
||||||
|
ProgressOffset = progressOffset;
|
||||||
|
}
|
||||||
|
|
||||||
void CMtProgressMixer2::SetProgressOffset(UInt64 progressOffset)
|
void CMtProgressMixer2::SetProgressOffset(UInt64 progressOffset)
|
||||||
{
|
{
|
||||||
CriticalSection.Enter();
|
CriticalSection.Enter();
|
||||||
InSizes[1] = OutSizes[1] = 0;
|
SetProgressOffset_NoLock(progressOffset);
|
||||||
ProgressOffset = progressOffset;
|
|
||||||
CriticalSection.Leave();
|
CriticalSection.Leave();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,6 +391,7 @@ static HRESULT UpdateItemOldData(
|
|||||||
item.Comment = ui.Comment;
|
item.Comment = ui.Comment;
|
||||||
item.Name = ui.Name;
|
item.Name = ui.Name;
|
||||||
item.SetUtf8(ui.IsUtf8);
|
item.SetUtf8(ui.IsUtf8);
|
||||||
|
// item.SetFlag_AltStream(ui.IsAltStream);
|
||||||
item.Time = ui.Time;
|
item.Time = ui.Time;
|
||||||
item.Ntfs_MTime = ui.Ntfs_MTime;
|
item.Ntfs_MTime = ui.Ntfs_MTime;
|
||||||
item.Ntfs_ATime = ui.Ntfs_ATime;
|
item.Ntfs_ATime = ui.Ntfs_ATime;
|
||||||
@@ -602,8 +610,11 @@ static HRESULT Update2St(
|
|||||||
lps->InSize = unpackSizeTotal;
|
lps->InSize = unpackSizeTotal;
|
||||||
lps->OutSize = packSizeTotal;
|
lps->OutSize = packSizeTotal;
|
||||||
RINOK(lps->SetCur());
|
RINOK(lps->SetCur());
|
||||||
|
|
||||||
archive.WriteCentralDir(items, comment);
|
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 += ui.Size;
|
||||||
complexity += kLocalHeaderSize;
|
complexity += kLocalHeaderSize;
|
||||||
mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity);
|
mtProgressMixerSpec->Mixer2->SetProgressOffset_NoLock(complexity);
|
||||||
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
||||||
memRef2.Skip = true;
|
memRef2.Skip = true;
|
||||||
continue;
|
continue;
|
||||||
@@ -1107,8 +1118,13 @@ static HRESULT Update2(
|
|||||||
}
|
}
|
||||||
|
|
||||||
RINOK(mtCompressProgressMixer.SetRatioInfo(0, NULL, NULL));
|
RINOK(mtCompressProgressMixer.SetRatioInfo(0, NULL, NULL));
|
||||||
|
|
||||||
archive.WriteCentralDir(items, comment);
|
archive.WriteCentralDir(items, comment);
|
||||||
return S_OK;
|
|
||||||
|
complexity += kCentralHeaderSize * updateItems.Size() + 1;
|
||||||
|
mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity);
|
||||||
|
return mtCompressProgressMixer.SetRatioInfo(0, NULL, NULL);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ struct CUpdateItem
|
|||||||
bool IsDir;
|
bool IsDir;
|
||||||
bool NtfsTimeIsDefined;
|
bool NtfsTimeIsDefined;
|
||||||
bool IsUtf8;
|
bool IsUtf8;
|
||||||
|
// bool IsAltStream;
|
||||||
int IndexInArc;
|
int IndexInArc;
|
||||||
int IndexInClient;
|
int IndexInClient;
|
||||||
UInt32 Attrib;
|
UInt32 Attrib;
|
||||||
@@ -50,12 +51,19 @@ struct CUpdateItem
|
|||||||
IsDir = false;
|
IsDir = false;
|
||||||
NtfsTimeIsDefined = false;
|
NtfsTimeIsDefined = false;
|
||||||
IsUtf8 = false;
|
IsUtf8 = false;
|
||||||
|
// IsAltStream = false;
|
||||||
Size = 0;
|
Size = 0;
|
||||||
Name.Empty();
|
Name.Empty();
|
||||||
Comment.Free();
|
Comment.Free();
|
||||||
}
|
}
|
||||||
|
|
||||||
CUpdateItem(): NtfsTimeIsDefined(false), IsUtf8(false), Size(0) {}
|
CUpdateItem():
|
||||||
|
IsDir(false),
|
||||||
|
NtfsTimeIsDefined(false),
|
||||||
|
IsUtf8(false),
|
||||||
|
// IsAltStream(false),
|
||||||
|
Size(0)
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
HRESULT Update(
|
HRESULT Update(
|
||||||
|
|||||||
@@ -198,6 +198,7 @@ COMPRESS_OBJS = \
|
|||||||
$O\DeflateRegister.obj \
|
$O\DeflateRegister.obj \
|
||||||
$O\DeltaFilter.obj \
|
$O\DeltaFilter.obj \
|
||||||
$O\ImplodeDecoder.obj \
|
$O\ImplodeDecoder.obj \
|
||||||
|
$O\LzfseDecoder.obj \
|
||||||
$O\LzhDecoder.obj \
|
$O\LzhDecoder.obj \
|
||||||
$O\Lzma2Decoder.obj \
|
$O\Lzma2Decoder.obj \
|
||||||
$O\Lzma2Encoder.obj \
|
$O\Lzma2Encoder.obj \
|
||||||
|
|||||||
@@ -961,6 +961,24 @@ SOURCE=..\..\Compress\HuffmanDecoder.h
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin 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
|
SOURCE=..\..\Compress\LzhDecoder.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|||||||
@@ -97,6 +97,33 @@ Byte CInBufferBase::ReadByte_FromNewBlock()
|
|||||||
|
|
||||||
size_t CInBufferBase::ReadBytes(Byte *buf, size_t size)
|
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)
|
if ((size_t)(_bufLim - _buf) >= size)
|
||||||
{
|
{
|
||||||
const Byte *src = _buf;
|
const Byte *src = _buf;
|
||||||
@@ -113,6 +140,7 @@ size_t CInBufferBase::ReadBytes(Byte *buf, size_t size)
|
|||||||
buf[i] = *_buf++;
|
buf[i] = *_buf++;
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t CInBufferBase::Skip(size_t size)
|
size_t CInBufferBase::Skip(size_t size)
|
||||||
|
|||||||
@@ -57,6 +57,39 @@ public:
|
|||||||
FlushWithCheck();
|
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
|
Byte GetByte(UInt32 distance) const
|
||||||
{
|
{
|
||||||
UInt32 pos = _pos - distance - 1;
|
UInt32 pos = _pos - distance - 1;
|
||||||
|
|||||||
925
CPP/7zip/Compress/LzfseDecoder.cpp
Normal file
925
CPP/7zip/Compress/LzfseDecoder.cpp
Normal file
@@ -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 <stdio.h>
|
||||||
|
#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 <LITERALS>
|
||||||
|
small L - 1110LLLL <LITERALS>
|
||||||
|
|
||||||
|
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 <LITERALS>
|
||||||
|
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 <LITERALS>
|
||||||
|
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 <LITERALS>
|
||||||
|
// small - LLMMMDDD DDDDDDDD <LITERALS>
|
||||||
|
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) < numStates * 2
|
||||||
|
// 0 < j0 <= f
|
||||||
|
// (f + j0) = next_power_of_2 for f
|
||||||
|
unsigned k = CountZeroBits(f, NUM_LIT_STATES);
|
||||||
|
unsigned j0 = (((unsigned)NUM_LIT_STATES * 2) >> 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; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}}
|
||||||
58
CPP/7zip/Compress/LzfseDecoder.h
Normal file
58
CPP/7zip/Compress/LzfseDecoder.h
Normal file
@@ -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
|
||||||
@@ -1217,7 +1217,12 @@ STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
|
|||||||
NWindows::NCOM::CPropVariant prop;
|
NWindows::NCOM::CPropVariant prop;
|
||||||
|
|
||||||
if (propID == kpidReadOnly)
|
if (propID == kpidReadOnly)
|
||||||
prop = _agentSpec->IsThereReadOnlyArc();
|
{
|
||||||
|
if (_agentSpec->Is_Attrib_ReadOnly())
|
||||||
|
prop = true;
|
||||||
|
else
|
||||||
|
prop = _agentSpec->IsThereReadOnlyArc();
|
||||||
|
}
|
||||||
else if (_proxy2)
|
else if (_proxy2)
|
||||||
{
|
{
|
||||||
const CProxyDir2 &dir = _proxy2->Dirs[_proxyDirIndex];
|
const CProxyDir2 &dir = _proxy2->Dirs[_proxyDirIndex];
|
||||||
@@ -1564,6 +1569,7 @@ STDMETHODIMP CAgent::Open(
|
|||||||
{
|
{
|
||||||
COM_TRY_BEGIN
|
COM_TRY_BEGIN
|
||||||
_archiveFilePath = filePath;
|
_archiveFilePath = filePath;
|
||||||
|
_attrib = 0;
|
||||||
NFile::NFind::CFileInfo fi;
|
NFile::NFind::CFileInfo fi;
|
||||||
_isDeviceFile = false;
|
_isDeviceFile = false;
|
||||||
if (!inStream)
|
if (!inStream)
|
||||||
@@ -1572,6 +1578,7 @@ STDMETHODIMP CAgent::Open(
|
|||||||
return ::GetLastError();
|
return ::GetLastError();
|
||||||
if (fi.IsDir())
|
if (fi.IsDir())
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
_attrib = fi.Attrib;
|
||||||
_isDeviceFile = fi.IsDevice;
|
_isDeviceFile = fi.IsDevice;
|
||||||
}
|
}
|
||||||
CArcInfoEx archiverInfo0, archiverInfo1;
|
CArcInfoEx archiverInfo0, archiverInfo1;
|
||||||
|
|||||||
@@ -241,6 +241,7 @@ public:
|
|||||||
CAgentFolder *_agentFolder;
|
CAgentFolder *_agentFolder;
|
||||||
|
|
||||||
UString _archiveFilePath;
|
UString _archiveFilePath;
|
||||||
|
DWORD _attrib;
|
||||||
bool _isDeviceFile;
|
bool _isDeviceFile;
|
||||||
|
|
||||||
#ifndef EXTRACT_ONLY
|
#ifndef EXTRACT_ONLY
|
||||||
@@ -252,6 +253,11 @@ public:
|
|||||||
IInArchive *GetArchive() const { if ( _archiveLink.Arcs.IsEmpty()) return 0; return GetArc().Archive; }
|
IInArchive *GetArchive() const { if ( _archiveLink.Arcs.IsEmpty()) return 0; return GetArc().Archive; }
|
||||||
bool CanUpdate() const;
|
bool CanUpdate() const;
|
||||||
|
|
||||||
|
bool Is_Attrib_ReadOnly() const
|
||||||
|
{
|
||||||
|
return _attrib != INVALID_FILE_ATTRIBUTES && (_attrib & FILE_ATTRIBUTE_READONLY);
|
||||||
|
}
|
||||||
|
|
||||||
bool IsThereReadOnlyArc() const
|
bool IsThereReadOnlyArc() const
|
||||||
{
|
{
|
||||||
FOR_VECTOR (i, _archiveLink.Arcs)
|
FOR_VECTOR (i, _archiveLink.Arcs)
|
||||||
|
|||||||
@@ -372,6 +372,8 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat
|
|||||||
HRESULT CArchiveExtractCallback::GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined)
|
HRESULT CArchiveExtractCallback::GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined)
|
||||||
{
|
{
|
||||||
filetimeIsDefined = false;
|
filetimeIsDefined = false;
|
||||||
|
filetime.dwLowDateTime = 0;
|
||||||
|
filetime.dwHighDateTime = 0;
|
||||||
NCOM::CPropVariant prop;
|
NCOM::CPropVariant prop;
|
||||||
RINOK(_arc->Archive->GetProperty(index, propID, &prop));
|
RINOK(_arc->Archive->GetProperty(index, propID, &prop));
|
||||||
if (prop.vt == VT_FILETIME)
|
if (prop.vt == VT_FILETIME)
|
||||||
@@ -1032,14 +1034,36 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
|
|||||||
{
|
{
|
||||||
FString fullPathNew;
|
FString fullPathNew;
|
||||||
CreateComplexDirectory(pathParts, fullPathNew);
|
CreateComplexDirectory(pathParts, fullPathNew);
|
||||||
|
|
||||||
if (_item.IsDir)
|
if (_item.IsDir)
|
||||||
{
|
{
|
||||||
_extractedFolderPaths.Add(fullPathNew);
|
CDirPathTime &pt = _extractedFolders.AddNew();
|
||||||
_extractedFolderIndices.Add(index);
|
|
||||||
SetDirTime(fullPathNew,
|
pt.CTime = _fi.CTime;
|
||||||
(WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL,
|
pt.CTimeDefined = (WriteCTime && _fi.CTimeDefined);
|
||||||
(WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL,
|
|
||||||
(WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
|
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
|
void CDirPathSortPair::SetNumSlashes(const FChar *s)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
for (unsigned numSlashes = 0;;)
|
for (unsigned numSlashes = 0;;)
|
||||||
{
|
{
|
||||||
FChar c = *s++;
|
FChar c = *s++;
|
||||||
if (c == 0)
|
if (c == 0)
|
||||||
return numSlashes;
|
{
|
||||||
|
Len = numSlashes;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (IS_PATH_SEPAR(c))
|
if (IS_PATH_SEPAR(c))
|
||||||
numSlashes++;
|
numSlashes++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CDirPathTime::SetDirTime()
|
||||||
|
{
|
||||||
|
return NDir::SetDirTime(Path,
|
||||||
|
CTimeDefined ? &CTime : NULL,
|
||||||
|
ATimeDefined ? &ATime : NULL,
|
||||||
|
MTimeDefined ? &MTime : NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
HRESULT CArchiveExtractCallback::SetDirsTimes()
|
HRESULT CArchiveExtractCallback::SetDirsTimes()
|
||||||
{
|
{
|
||||||
if (!_arc)
|
if (!_arc)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
CRecordVector<CExtrRefSortPair> pairs;
|
CRecordVector<CDirPathSortPair> pairs;
|
||||||
pairs.ClearAndSetSize(_extractedFolderPaths.Size());
|
pairs.ClearAndSetSize(_extractedFolders.Size());
|
||||||
unsigned i;
|
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.Index = i;
|
||||||
pair.Len = GetNumSlashes(_extractedFolderPaths[i]);
|
pair.SetNumSlashes(_extractedFolders[i].Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
pairs.Sort2();
|
pairs.Sort2();
|
||||||
|
|
||||||
for (i = 0; i < pairs.Size(); i++)
|
for (i = 0; i < pairs.Size(); i++)
|
||||||
{
|
{
|
||||||
unsigned pairIndex = pairs[i].Index;
|
_extractedFolders[pairs[i].Index].SetDirTime();
|
||||||
UInt32 index = _extractedFolderIndices[pairIndex];
|
// if (!) return GetLastError();
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ClearExtractedDirsInfo();
|
ClearExtractedDirsInfo();
|
||||||
|
|||||||
@@ -151,6 +151,25 @@ struct CIndexToPathPair
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct CDirPathTime
|
||||||
|
{
|
||||||
|
FILETIME CTime;
|
||||||
|
FILETIME ATime;
|
||||||
|
FILETIME MTime;
|
||||||
|
|
||||||
|
bool CTimeDefined;
|
||||||
|
bool ATimeDefined;
|
||||||
|
bool MTimeDefined;
|
||||||
|
|
||||||
|
FString Path;
|
||||||
|
|
||||||
|
bool SetDirTime();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CArchiveExtractCallback:
|
class CArchiveExtractCallback:
|
||||||
public IArchiveExtractCallback,
|
public IArchiveExtractCallback,
|
||||||
public IArchiveExtractCallbackMessage,
|
public IArchiveExtractCallbackMessage,
|
||||||
@@ -241,8 +260,7 @@ class CArchiveExtractCallback:
|
|||||||
UInt64 _progressTotal;
|
UInt64 _progressTotal;
|
||||||
bool _progressTotal_Defined;
|
bool _progressTotal_Defined;
|
||||||
|
|
||||||
FStringVector _extractedFolderPaths;
|
CObjectVector<CDirPathTime> _extractedFolders;
|
||||||
CRecordVector<UInt32> _extractedFolderIndices;
|
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX)
|
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX)
|
||||||
bool _saclEnabled;
|
bool _saclEnabled;
|
||||||
@@ -348,8 +366,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
void ClearExtractedDirsInfo()
|
void ClearExtractedDirsInfo()
|
||||||
{
|
{
|
||||||
_extractedFolderPaths.Clear();
|
_extractedFolders.Clear();
|
||||||
_extractedFolderIndices.Clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CloseFile();
|
HRESULT CloseFile();
|
||||||
|
|||||||
@@ -857,7 +857,7 @@ HRESULT CArc::GetItem(UInt32 index, CReadArcItem &item) const
|
|||||||
|
|
||||||
if (item.WriteToAltStreamIfColon || needFindAltStream)
|
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 */
|
So the following code currently is not used */
|
||||||
int colon = FindAltStreamColon_in_Path(item.Path);
|
int colon = FindAltStreamColon_in_Path(item.Path);
|
||||||
if (colon >= 0)
|
if (colon >= 0)
|
||||||
|
|||||||
@@ -414,4 +414,23 @@ struct CArchiveLink
|
|||||||
|
|
||||||
bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types);
|
bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &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
|
#endif
|
||||||
|
|||||||
@@ -1046,32 +1046,6 @@ static HRESULT EnumerateInArchiveItems(
|
|||||||
|
|
||||||
#endif
|
#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
|
#ifdef _WIN32
|
||||||
void ConvertToLongNames(NWildcard::CCensor &censor);
|
void ConvertToLongNames(NWildcard::CCensor &censor);
|
||||||
#endif
|
#endif
|
||||||
@@ -1190,6 +1164,16 @@ HRESULT UpdateArchive(
|
|||||||
throw "there is no such archive";
|
throw "there is no such archive";
|
||||||
if (fi.IsDevice)
|
if (fi.IsDevice)
|
||||||
return E_NOTIMPL;
|
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)
|
if (options.VolumesSizes.Size() > 0)
|
||||||
{
|
{
|
||||||
errorInfo.FileNames.Add(us2fs(arcPath));
|
errorInfo.FileNames.Add(us2fs(arcPath));
|
||||||
@@ -1510,9 +1494,13 @@ HRESULT UpdateArchive(
|
|||||||
CArchivePath &ap = options.Commands[0].ArchivePath;
|
CArchivePath &ap = options.Commands[0].ArchivePath;
|
||||||
const FString &tempPath = ap.GetTempPath();
|
const FString &tempPath = ap.GetTempPath();
|
||||||
|
|
||||||
|
// DWORD attrib = 0;
|
||||||
if (thereIsInArchive)
|
if (thereIsInArchive)
|
||||||
|
{
|
||||||
|
// attrib = NFind::GetFileAttrib(us2fs(arcPath));
|
||||||
if (!DeleteFileAlways(us2fs(arcPath)))
|
if (!DeleteFileAlways(us2fs(arcPath)))
|
||||||
return errorInfo.SetFromLastError("cannot delete the file", us2fs(arcPath));
|
return errorInfo.SetFromLastError("cannot delete the file", us2fs(arcPath));
|
||||||
|
}
|
||||||
|
|
||||||
if (!MyMoveFile(tempPath, us2fs(arcPath)))
|
if (!MyMoveFile(tempPath, us2fs(arcPath)))
|
||||||
{
|
{
|
||||||
@@ -1520,6 +1508,15 @@ HRESULT UpdateArchive(
|
|||||||
errorInfo.FileNames.Add(us2fs(arcPath));
|
errorInfo.FileNames.Add(us2fs(arcPath));
|
||||||
return errorInfo.Get_HRESULT_Error();
|
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(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
@@ -1609,7 +1606,7 @@ HRESULT UpdateArchive(
|
|||||||
|
|
||||||
if (options.DeleteAfterCompressing)
|
if (options.DeleteAfterCompressing)
|
||||||
{
|
{
|
||||||
CRecordVector<CRefSortPair> pairs;
|
CRecordVector<CDirPathSortPair> pairs;
|
||||||
FStringVector foldersNames;
|
FStringVector foldersNames;
|
||||||
|
|
||||||
unsigned i;
|
unsigned i;
|
||||||
@@ -1617,12 +1614,12 @@ HRESULT UpdateArchive(
|
|||||||
for (i = 0; i < dirItems.Items.Size(); i++)
|
for (i = 0; i < dirItems.Items.Size(); i++)
|
||||||
{
|
{
|
||||||
const CDirItem &dirItem = dirItems.Items[i];
|
const CDirItem &dirItem = dirItems.Items[i];
|
||||||
FString phyPath = dirItems.GetPhyPath(i);
|
const FString phyPath = dirItems.GetPhyPath(i);
|
||||||
if (dirItem.IsDir())
|
if (dirItem.IsDir())
|
||||||
{
|
{
|
||||||
CRefSortPair pair;
|
CDirPathSortPair pair;
|
||||||
pair.Index = i;
|
pair.Index = i;
|
||||||
pair.Len = GetNumSlashes(phyPath);
|
pair.SetNumSlashes(phyPath);
|
||||||
pairs.Add(pair);
|
pairs.Add(pair);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1655,11 +1652,11 @@ HRESULT UpdateArchive(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pairs.Sort(CompareRefSortPair, NULL);
|
pairs.Sort2();
|
||||||
|
|
||||||
for (i = 0; i < pairs.Size(); i++)
|
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))
|
if (NFind::DoesDirExist(phyPath))
|
||||||
{
|
{
|
||||||
RINOK(callback->DeletingAfterArchiving(phyPath, true));
|
RINOK(callback->DeletingAfterArchiving(phyPath, true));
|
||||||
|
|||||||
@@ -667,12 +667,27 @@ bool CTempFile::Remove()
|
|||||||
|
|
||||||
bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore)
|
bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore)
|
||||||
{
|
{
|
||||||
|
// DWORD attrib = 0;
|
||||||
if (deleteDestBefore)
|
if (deleteDestBefore)
|
||||||
|
{
|
||||||
if (NFind::DoesFileExist(name))
|
if (NFind::DoesFileExist(name))
|
||||||
|
{
|
||||||
|
// attrib = NFind::GetFileAttrib(name);
|
||||||
if (!DeleteFileAlways(name))
|
if (!DeleteFileAlways(name))
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
DisableDeleting();
|
DisableDeleting();
|
||||||
return MyMoveFile(_path, name);
|
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)
|
bool CTempDir::Create(CFSTR prefix)
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ AppName = "7-Zip"
|
|||||||
InstallDir = %CE1%\%AppName%
|
InstallDir = %CE1%\%AppName%
|
||||||
|
|
||||||
[Strings]
|
[Strings]
|
||||||
AppVer = "18.00"
|
AppVer = "18.01"
|
||||||
AppDate = "2018-01-10"
|
AppDate = "2018-01-28"
|
||||||
|
|
||||||
[CEDevice]
|
[CEDevice]
|
||||||
; ProcessorType = 2577 ; ARM
|
; ProcessorType = 2577 ; ARM
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
;Defines
|
;Defines
|
||||||
|
|
||||||
!define VERSION_MAJOR 18
|
!define VERSION_MAJOR 18
|
||||||
!define VERSION_MINOR 00
|
!define VERSION_MINOR 01
|
||||||
!define VERSION_POSTFIX_FULL " beta"
|
!define VERSION_POSTFIX_FULL ""
|
||||||
!ifdef WIN64
|
!ifdef WIN64
|
||||||
!ifdef IA64
|
!ifdef IA64
|
||||||
!define VERSION_SYS_POSTFIX_FULL " for Windows IA-64"
|
!define VERSION_SYS_POSTFIX_FULL " for Windows IA-64"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
<?define VerMajor = "18" ?>
|
<?define VerMajor = "18" ?>
|
||||||
<?define VerMinor = "00" ?>
|
<?define VerMinor = "01" ?>
|
||||||
<?define VerBuild = "00" ?>
|
<?define VerBuild = "00" ?>
|
||||||
<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>
|
<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>
|
||||||
<?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?>
|
<?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?>
|
||||||
|
|||||||
@@ -5,13 +5,18 @@
|
|||||||
|
|
||||||
7-Zip Copyright (C) 1999-2018 Igor Pavlov.
|
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
|
GNU LGPL information
|
||||||
@@ -32,8 +37,41 @@
|
|||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
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
|
The decompression engine for RAR archives was developed using source
|
||||||
code of unRAR program.
|
code of unRAR program.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
7-Zip 18.00 beta Sources
|
7-Zip 18.01 Sources
|
||||||
------------------------
|
-------------------
|
||||||
|
|
||||||
7-Zip is a file archiver for Windows.
|
7-Zip is a file archiver for Windows.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user