mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-08 16:07:04 -06:00
Update to 7-Zip Version 22.00
See: https://sourceforge.net/p/sevenzip/discussion/45797/thread/9c2d9061ce/
This commit is contained in:
@@ -191,6 +191,8 @@ static const Byte kProps[] =
|
||||
kpidVolumeIndex,
|
||||
kpidOffset
|
||||
// kpidIsAltStream
|
||||
// , kpidChangeTime // for debug
|
||||
// , 255 // for debug
|
||||
};
|
||||
|
||||
static const Byte kArcProps[] =
|
||||
@@ -348,6 +350,34 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
static bool NtfsUnixTimeToProp(bool fromCentral,
|
||||
const CExtraBlock &extra,
|
||||
unsigned ntfsIndex, unsigned unixIndex, NWindows::NCOM::CPropVariant &prop)
|
||||
{
|
||||
{
|
||||
FILETIME ft;
|
||||
if (extra.GetNtfsTime(ntfsIndex, ft))
|
||||
{
|
||||
PropVariant_SetFrom_NtfsTime(prop, ft);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
{
|
||||
UInt32 unixTime = 0;
|
||||
if (!extra.GetUnixTime(fromCentral, unixIndex, unixTime))
|
||||
return false;
|
||||
/*
|
||||
// we allow unixTime == 0
|
||||
if (unixTime == 0)
|
||||
return false;
|
||||
*/
|
||||
PropVariant_SetFrom_UnixTime(prop, unixTime);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
@@ -393,6 +423,30 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
|
||||
case kpidPackSize: prop = item.PackSize; break;
|
||||
|
||||
case kpidCTime:
|
||||
NtfsUnixTimeToProp(item.FromCentral, extra,
|
||||
NFileHeader::NNtfsExtra::kCTime,
|
||||
NFileHeader::NUnixTime::kCTime, prop);
|
||||
break;
|
||||
|
||||
case kpidATime:
|
||||
NtfsUnixTimeToProp(item.FromCentral, extra,
|
||||
NFileHeader::NNtfsExtra::kATime,
|
||||
NFileHeader::NUnixTime::kATime, prop);
|
||||
break;
|
||||
|
||||
case kpidMTime:
|
||||
{
|
||||
if (!NtfsUnixTimeToProp(item.FromCentral, extra,
|
||||
NFileHeader::NNtfsExtra::kMTime,
|
||||
NFileHeader::NUnixTime::kMTime, prop))
|
||||
{
|
||||
if (item.Time != 0)
|
||||
PropVariant_SetFrom_DosTime(prop, item.Time);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidTimeType:
|
||||
{
|
||||
FILETIME ft;
|
||||
@@ -400,7 +454,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
UInt32 type;
|
||||
if (extra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, ft))
|
||||
type = NFileTimeType::kWindows;
|
||||
else if (extra.GetUnixTime(true, NFileHeader::NUnixTime::kMTime, unixTime))
|
||||
else if (extra.GetUnixTime(item.FromCentral, NFileHeader::NUnixTime::kMTime, unixTime))
|
||||
type = NFileTimeType::kUnix;
|
||||
else
|
||||
type = NFileTimeType::kDOS;
|
||||
@@ -408,64 +462,28 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidCTime:
|
||||
/*
|
||||
// for debug to get Dos time values:
|
||||
case kpidChangeTime: if (item.Time != 0) PropVariant_SetFrom_DosTime(prop, item.Time); break;
|
||||
// for debug
|
||||
// time difference (dos - utc)
|
||||
case 255:
|
||||
{
|
||||
FILETIME utc;
|
||||
bool defined = true;
|
||||
if (!extra.GetNtfsTime(NFileHeader::NNtfsExtra::kCTime, utc))
|
||||
if (NtfsUnixTimeToProp(item.FromCentral, extra,
|
||||
NFileHeader::NNtfsExtra::kMTime,
|
||||
NFileHeader::NUnixTime::kMTime, prop))
|
||||
{
|
||||
UInt32 unixTime = 0;
|
||||
if (extra.GetUnixTime(true, NFileHeader::NUnixTime::kCTime, unixTime))
|
||||
NTime::UnixTimeToFileTime(unixTime, utc);
|
||||
else
|
||||
defined = false;
|
||||
}
|
||||
if (defined)
|
||||
prop = utc;
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidATime:
|
||||
{
|
||||
FILETIME utc;
|
||||
bool defined = true;
|
||||
if (!extra.GetNtfsTime(NFileHeader::NNtfsExtra::kATime, utc))
|
||||
{
|
||||
UInt32 unixTime = 0;
|
||||
if (extra.GetUnixTime(true, NFileHeader::NUnixTime::kATime, unixTime))
|
||||
NTime::UnixTimeToFileTime(unixTime, utc);
|
||||
else
|
||||
defined = false;
|
||||
}
|
||||
if (defined)
|
||||
prop = utc;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidMTime:
|
||||
{
|
||||
FILETIME utc;
|
||||
bool defined = true;
|
||||
if (!extra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, utc))
|
||||
{
|
||||
UInt32 unixTime = 0;
|
||||
if (extra.GetUnixTime(true, NFileHeader::NUnixTime::kMTime, unixTime))
|
||||
NTime::UnixTimeToFileTime(unixTime, utc);
|
||||
else
|
||||
FILETIME localFileTime;
|
||||
if (item.Time != 0 && NTime::DosTime_To_FileTime(item.Time, localFileTime))
|
||||
{
|
||||
FILETIME localFileTime;
|
||||
if (item.Time == 0)
|
||||
defined = false;
|
||||
else if (!NTime::DosTimeToFileTime(item.Time, localFileTime) ||
|
||||
!LocalFileTimeToFileTime(&localFileTime, &utc))
|
||||
utc.dwHighDateTime = utc.dwLowDateTime = 0;
|
||||
UInt64 t1 = FILETIME_To_UInt64(prop.filetime);
|
||||
UInt64 t2 = FILETIME_To_UInt64(localFileTime);
|
||||
prop.Set_Int64(t2 - t1);
|
||||
}
|
||||
}
|
||||
if (defined)
|
||||
prop = utc;
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
||||
case kpidAttrib: prop = item.GetWinAttrib(); break;
|
||||
|
||||
@@ -1149,7 +1167,18 @@ HRESULT CZipDecoder::Decode(
|
||||
AString_Wipe charPassword;
|
||||
if (password)
|
||||
{
|
||||
UnicodeStringToMultiByte2(charPassword, (LPCOLESTR)password, CP_ACP);
|
||||
/*
|
||||
// 22.00: do we need UTF-8 passwords here ?
|
||||
if (item.IsUtf8()) // 22.00
|
||||
{
|
||||
// throw 1;
|
||||
ConvertUnicodeToUTF8((LPCOLESTR)password, charPassword);
|
||||
}
|
||||
else
|
||||
*/
|
||||
{
|
||||
UnicodeStringToMultiByte2(charPassword, (LPCOLESTR)password, CP_ACP);
|
||||
}
|
||||
/*
|
||||
if (wzAesMode || pkAesMode)
|
||||
{
|
||||
@@ -1372,6 +1401,8 @@ HRESULT CZipDecoder::Decode(
|
||||
|
||||
if (id == NFileHeader::NCompressionMethod::kStore && item.IsEncrypted())
|
||||
{
|
||||
// for debug : we can disable this code (kStore + 50), if we want to test CopyCoder+Filter
|
||||
// here we use filter without CopyCoder
|
||||
readFromFilter = false;
|
||||
|
||||
COutStreamWithPadPKCS7 *padStreamSpec = NULL;
|
||||
@@ -1456,33 +1487,44 @@ HRESULT CZipDecoder::Decode(
|
||||
const UInt32 padSize = _pkAesDecoderSpec->GetPadSize((UInt32)processed);
|
||||
if (processed + padSize > coderPackSize)
|
||||
truncatedError = true;
|
||||
else if (processed + padSize < coderPackSize)
|
||||
dataAfterEnd = true;
|
||||
else
|
||||
{
|
||||
if (processed + padSize < coderPackSize)
|
||||
dataAfterEnd = true;
|
||||
else
|
||||
{
|
||||
// here we can PKCS7 padding data from reminder (it can be inside stream buffer in coder).
|
||||
// here we check PKCS7 padding data from reminder (it can be inside stream buffer in coder).
|
||||
CMyComPtr<ICompressReadUnusedFromInBuf> readInStream;
|
||||
coder->QueryInterface(IID_ICompressReadUnusedFromInBuf, (void **)&readInStream);
|
||||
if (readInStream)
|
||||
// CCopyCoder() for kStore doesn't read data outside of (item.Size)
|
||||
if (readInStream || id == NFileHeader::NCompressionMethod::kStore)
|
||||
{
|
||||
// change pad size, it we support another block size in ZipStron
|
||||
// here we request more to detect error with data after end.
|
||||
// change pad size, if we support another block size in ZipStrong.
|
||||
// here we request more data to detect error with data after end.
|
||||
const UInt32 kBufSize = NCrypto::NZipStrong::kAesPadAllign + 16;
|
||||
Byte buf[kBufSize];
|
||||
UInt32 processedSize;
|
||||
RINOK(readInStream->ReadUnusedFromInBuf(buf, kBufSize, &processedSize));
|
||||
UInt32 processedSize = 0;
|
||||
if (readInStream)
|
||||
{
|
||||
RINOK(readInStream->ReadUnusedFromInBuf(buf, kBufSize, &processedSize));
|
||||
}
|
||||
if (processedSize > padSize)
|
||||
dataAfterEnd = true;
|
||||
else
|
||||
{
|
||||
if (ReadStream_FALSE(filterStream, buf + processedSize, padSize - processedSize) != S_OK)
|
||||
padError = true;
|
||||
else
|
||||
for (unsigned i = 0; i < padSize; i++)
|
||||
if (buf[i] != padSize)
|
||||
padError = true;
|
||||
size_t processedSize2 = kBufSize - processedSize;
|
||||
result = ReadStream(filterStream, buf + processedSize, &processedSize2);
|
||||
if (result == S_OK)
|
||||
{
|
||||
processedSize2 += processedSize;
|
||||
if (processedSize2 > padSize)
|
||||
dataAfterEnd = true;
|
||||
else if (processedSize2 < padSize)
|
||||
truncatedError = true;
|
||||
else
|
||||
for (unsigned i = 0; i < padSize; i++)
|
||||
if (buf[i] != padSize)
|
||||
padError = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,9 @@ private:
|
||||
|
||||
int m_MainMethod;
|
||||
bool m_ForceAesMode;
|
||||
bool m_WriteNtfsTimeExtra;
|
||||
|
||||
CHandlerTimeOptions TimeOptions;
|
||||
|
||||
bool _removeSfxBlock;
|
||||
bool m_ForceLocal;
|
||||
bool m_ForceUtf8;
|
||||
@@ -71,7 +73,8 @@ private:
|
||||
_props.Init();
|
||||
m_MainMethod = -1;
|
||||
m_ForceAesMode = false;
|
||||
m_WriteNtfsTimeExtra = true;
|
||||
TimeOptions.Init();
|
||||
TimeOptions.Prec = k_PropVar_TimePrec_0;
|
||||
_removeSfxBlock = false;
|
||||
m_ForceLocal = false;
|
||||
m_ForceUtf8 = true;
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace NZip {
|
||||
|
||||
STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
|
||||
{
|
||||
*timeType = NFileTimeType::kDOS;
|
||||
*timeType = TimeOptions.Prec;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -207,27 +207,58 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
}
|
||||
*/
|
||||
|
||||
// 22.00 : kpidTimeType is useless here : the code was disabled
|
||||
/*
|
||||
{
|
||||
CPropVariant prop;
|
||||
RINOK(callback->GetProperty(i, kpidTimeType, &prop));
|
||||
if (prop.vt == VT_UI4)
|
||||
ui.NtfsTimeIsDefined = (prop.ulVal == NFileTimeType::kWindows);
|
||||
ui.NtfsTime_IsDefined = (prop.ulVal == NFileTimeType::kWindows);
|
||||
else
|
||||
ui.NtfsTimeIsDefined = m_WriteNtfsTimeExtra;
|
||||
ui.NtfsTime_IsDefined = _Write_NtfsTime;
|
||||
}
|
||||
RINOK(GetTime(callback, i, kpidMTime, ui.Ntfs_MTime));
|
||||
RINOK(GetTime(callback, i, kpidATime, ui.Ntfs_ATime));
|
||||
RINOK(GetTime(callback, i, kpidCTime, ui.Ntfs_CTime));
|
||||
*/
|
||||
|
||||
if (TimeOptions.Write_MTime.Val) RINOK (GetTime (callback, i, kpidMTime, ui.Ntfs_MTime));
|
||||
if (TimeOptions.Write_ATime.Val) RINOK (GetTime (callback, i, kpidATime, ui.Ntfs_ATime));
|
||||
if (TimeOptions.Write_CTime.Val) RINOK (GetTime (callback, i, kpidCTime, ui.Ntfs_CTime));
|
||||
|
||||
if (TimeOptions.Prec != k_PropVar_TimePrec_DOS)
|
||||
{
|
||||
FILETIME localFileTime = { 0, 0 };
|
||||
if (ui.Ntfs_MTime.dwHighDateTime != 0 ||
|
||||
ui.Ntfs_MTime.dwLowDateTime != 0)
|
||||
if (!FileTimeToLocalFileTime(&ui.Ntfs_MTime, &localFileTime))
|
||||
return E_INVALIDARG;
|
||||
FileTimeToDosTime(localFileTime, ui.Time);
|
||||
if (TimeOptions.Prec == k_PropVar_TimePrec_Unix ||
|
||||
TimeOptions.Prec == k_PropVar_TimePrec_Base)
|
||||
ui.Write_UnixTime = ! FILETIME_IsZero (ui.Ntfs_MTime);
|
||||
else
|
||||
{
|
||||
/*
|
||||
// if we want to store zero timestamps as zero timestamp, use the following:
|
||||
ui.Write_NtfsTime =
|
||||
_Write_MTime ||
|
||||
_Write_ATime ||
|
||||
_Write_CTime;
|
||||
*/
|
||||
|
||||
// We treat zero timestamp as no timestamp
|
||||
ui.Write_NtfsTime =
|
||||
! FILETIME_IsZero (ui.Ntfs_MTime) ||
|
||||
! FILETIME_IsZero (ui.Ntfs_ATime) ||
|
||||
! FILETIME_IsZero (ui.Ntfs_CTime);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
how 0 in dos time works:
|
||||
win10 explorer extract : some random date 1601-04-25.
|
||||
winrar 6.10 : write time.
|
||||
7zip : MTime of archive is used
|
||||
how 0 in tar works:
|
||||
winrar 6.10 : 1970
|
||||
0 in dos field can show that there is no timestamp.
|
||||
we write correct 1970-01-01 in dos field, to support correct extraction in Win10.
|
||||
*/
|
||||
|
||||
UtcFileTime_To_LocalDosTime(ui.Ntfs_MTime, ui.Time);
|
||||
|
||||
NItemName::ReplaceSlashes_OsToUnix(name);
|
||||
|
||||
bool needSlash = ui.IsDir;
|
||||
@@ -441,11 +472,21 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
if (mainMethod != NFileHeader::NCompressionMethod::kStore)
|
||||
options.MethodSequence.Add(NFileHeader::NCompressionMethod::kStore);
|
||||
|
||||
CUpdateOptions uo;
|
||||
uo.Write_MTime = TimeOptions.Write_MTime.Val;
|
||||
uo.Write_ATime = TimeOptions.Write_ATime.Val;
|
||||
uo.Write_CTime = TimeOptions.Write_CTime.Val;
|
||||
/*
|
||||
uo.Write_NtfsTime = _Write_NtfsTime &&
|
||||
(_Write_MTime || _Write_ATime || _Write_CTime);
|
||||
uo.Write_UnixTime = _Write_UnixTime;
|
||||
*/
|
||||
|
||||
return Update(
|
||||
EXTERNAL_CODECS_VARS
|
||||
m_Items, updateItems, outStream,
|
||||
m_Archive.IsOpen() ? &m_Archive : NULL, _removeSfxBlock,
|
||||
options, callback);
|
||||
uo, options, callback);
|
||||
|
||||
COM_TRY_END2
|
||||
}
|
||||
@@ -494,10 +535,9 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
else if (name.IsEqualTo("tc"))
|
||||
{
|
||||
RINOK(PROPVARIANT_to_bool(prop, m_WriteNtfsTimeExtra));
|
||||
}
|
||||
|
||||
|
||||
|
||||
else if (name.IsEqualTo("cl"))
|
||||
{
|
||||
RINOK(PROPVARIANT_to_bool(prop, m_ForceLocal));
|
||||
@@ -532,7 +572,12 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(_props.SetProperty(name, prop));
|
||||
bool processed = false;
|
||||
RINOK(TimeOptions.Parse(name, prop, processed));
|
||||
if (!processed)
|
||||
{
|
||||
RINOK(_props.SetProperty(name, prop));
|
||||
}
|
||||
}
|
||||
// RINOK(_props.MethodInfo.ParseParamsFromPROPVARIANT(name, prop));
|
||||
}
|
||||
|
||||
@@ -88,14 +88,15 @@ namespace NFileHeader
|
||||
{
|
||||
kZip64 = 0x01,
|
||||
kNTFS = 0x0A,
|
||||
kUnix0 = 0x0D, // Info-ZIP : (UNIX) PK
|
||||
kStrongEncrypt = 0x17,
|
||||
kIzNtSecurityDescriptor = 0x4453,
|
||||
kUnixTime = 0x5455,
|
||||
kUnixExtra = 0x5855,
|
||||
kUnixTime = 0x5455, // "UT" (time) Info-ZIP
|
||||
kUnix1 = 0x5855, // Info-ZIP
|
||||
kIzUnicodeComment = 0x6375,
|
||||
kIzUnicodeName = 0x7075,
|
||||
kUnix2Extra = 0x7855,
|
||||
kUnix3Extra = 0x7875,
|
||||
kUnix2 = 0x7855, // Info-ZIP
|
||||
kUnixN = 0x7875, // Info-ZIP
|
||||
kWzAES = 0x9901,
|
||||
kApkAlign = 0xD935
|
||||
};
|
||||
|
||||
@@ -1045,9 +1045,24 @@ bool CInArchive::ReadExtra(const CLocalItem &item, unsigned extraSize, CExtraBlo
|
||||
|
||||
if (cdItem)
|
||||
{
|
||||
if (isOK && ZIP64_IS_32_MAX(cdItem->LocalHeaderPos))
|
||||
{ if (size < 8) isOK = false; else { size -= 8; cdItem->LocalHeaderPos = ReadUInt64(); }}
|
||||
|
||||
if (isOK)
|
||||
{
|
||||
if (ZIP64_IS_32_MAX(cdItem->LocalHeaderPos))
|
||||
{ if (size < 8) isOK = false; else { size -= 8; cdItem->LocalHeaderPos = ReadUInt64(); }}
|
||||
/*
|
||||
else if (size == 8)
|
||||
{
|
||||
size -= 8;
|
||||
const UInt64 v = ReadUInt64();
|
||||
// soong_zip, an AOSP tool (written in the Go) writes incorrect value.
|
||||
// we can ignore that minor error here
|
||||
if (v != cdItem->LocalHeaderPos)
|
||||
isOK = false; // ignore error
|
||||
// isOK = false; // force error
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if (isOK && ZIP64_IS_16_MAX(cdItem->Disk))
|
||||
{ if (size < 4) isOK = false; else { size -= 4; cdItem->Disk = ReadUInt32(); }}
|
||||
}
|
||||
@@ -1926,7 +1941,7 @@ static int FindItem(const CObjectVector<CItemEx> &items, const CItemEx &item)
|
||||
{
|
||||
if (left >= right)
|
||||
return -1;
|
||||
const unsigned index = (left + right) / 2;
|
||||
const unsigned index = (unsigned)(((size_t)left + (size_t)right) / 2);
|
||||
const CItemEx &item2 = items[index];
|
||||
if (item.Disk < item2.Disk)
|
||||
right = index;
|
||||
|
||||
@@ -30,11 +30,12 @@ static const CUInt32PCharPair g_ExtraTypes[] =
|
||||
{
|
||||
{ NExtraID::kZip64, "Zip64" },
|
||||
{ NExtraID::kNTFS, "NTFS" },
|
||||
{ NExtraID::kUnix0, "UNIX" },
|
||||
{ NExtraID::kStrongEncrypt, "StrongCrypto" },
|
||||
{ NExtraID::kUnixTime, "UT" },
|
||||
{ NExtraID::kUnixExtra, "UX" },
|
||||
{ NExtraID::kUnix2Extra, "Ux" },
|
||||
{ NExtraID::kUnix3Extra, "ux" },
|
||||
{ NExtraID::kUnix1, "UX" },
|
||||
{ NExtraID::kUnix2, "Ux" },
|
||||
{ NExtraID::kUnixN, "ux" },
|
||||
{ NExtraID::kIzUnicodeComment, "uc" },
|
||||
{ NExtraID::kIzUnicodeName, "up" },
|
||||
{ NExtraID::kIzNtSecurityDescriptor, "SD" },
|
||||
@@ -50,6 +51,23 @@ void CExtraSubBlock::PrintInfo(AString &s) const
|
||||
if (pair.Value == ID)
|
||||
{
|
||||
s += pair.Name;
|
||||
if (ID == NExtraID::kUnixTime)
|
||||
{
|
||||
if (Data.Size() >= 1)
|
||||
{
|
||||
s += ':';
|
||||
const Byte flags = Data[0];
|
||||
if (flags & 1) s += 'M';
|
||||
if (flags & 2) s += 'A';
|
||||
if (flags & 4) s += 'C';
|
||||
const UInt32 size = (UInt32)(Data.Size()) - 1;
|
||||
if (size % 4 == 0)
|
||||
{
|
||||
s += ':';
|
||||
s.Add_UInt32(size / 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
if (ID == NExtraID::kApkAlign && Data.Size() >= 2)
|
||||
{
|
||||
@@ -133,14 +151,22 @@ bool CExtraSubBlock::ExtractNtfsTime(unsigned index, FILETIME &ft) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CExtraSubBlock::ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res) const
|
||||
bool CExtraSubBlock::Extract_UnixTime(bool isCentral, unsigned index, UInt32 &res) const
|
||||
{
|
||||
/* Info-Zip :
|
||||
The central-header extra field contains the modification
|
||||
time only, or no timestamp at all.
|
||||
Size of Data is used to flag its presence or absence
|
||||
If "Flags" indicates that Modtime is present in the local header
|
||||
field, it MUST be present in the central header field, too
|
||||
*/
|
||||
|
||||
res = 0;
|
||||
UInt32 size = (UInt32)Data.Size();
|
||||
if (ID != NExtraID::kUnixTime || size < 5)
|
||||
return false;
|
||||
const Byte *p = (const Byte *)Data;
|
||||
Byte flags = *p++;
|
||||
const Byte flags = *p++;
|
||||
size--;
|
||||
if (isCentral)
|
||||
{
|
||||
@@ -168,18 +194,35 @@ bool CExtraSubBlock::ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res
|
||||
}
|
||||
|
||||
|
||||
bool CExtraSubBlock::ExtractUnixExtraTime(unsigned index, UInt32 &res) const
|
||||
// Info-ZIP's abandoned "Unix1 timestamps & owner ID info"
|
||||
|
||||
bool CExtraSubBlock::Extract_Unix01_Time(unsigned index, UInt32 &res) const
|
||||
{
|
||||
res = 0;
|
||||
const size_t size = Data.Size();
|
||||
unsigned offset = index * 4;
|
||||
if (ID != NExtraID::kUnixExtra || size < offset + 4)
|
||||
const unsigned offset = index * 4;
|
||||
if (Data.Size() < offset + 4)
|
||||
return false;
|
||||
if (ID != NExtraID::kUnix0 &&
|
||||
ID != NExtraID::kUnix1)
|
||||
return false;
|
||||
const Byte *p = (const Byte *)Data + offset;
|
||||
res = GetUi32(p);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
// PKWARE's Unix "extra" is similar to Info-ZIP's abandoned "Unix1 timestamps"
|
||||
bool CExtraSubBlock::Extract_Unix_Time(unsigned index, UInt32 &res) const
|
||||
{
|
||||
res = 0;
|
||||
const unsigned offset = index * 4;
|
||||
if (ID != NExtraID::kUnix0 || Data.Size() < offset)
|
||||
return false;
|
||||
const Byte *p = (const Byte *)Data + offset;
|
||||
res = GetUi32(p);
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
bool CExtraBlock::GetNtfsTime(unsigned index, FILETIME &ft) const
|
||||
{
|
||||
@@ -199,7 +242,7 @@ bool CExtraBlock::GetUnixTime(bool isCentral, unsigned index, UInt32 &res) const
|
||||
{
|
||||
const CExtraSubBlock &sb = SubBlocks[i];
|
||||
if (sb.ID == NFileHeader::NExtraID::kUnixTime)
|
||||
return sb.ExtractUnixTime(isCentral, index, res);
|
||||
return sb.Extract_UnixTime(isCentral, index, res);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,8 +257,9 @@ bool CExtraBlock::GetUnixTime(bool isCentral, unsigned index, UInt32 &res) const
|
||||
FOR_VECTOR (i, SubBlocks)
|
||||
{
|
||||
const CExtraSubBlock &sb = SubBlocks[i];
|
||||
if (sb.ID == NFileHeader::NExtraID::kUnixExtra)
|
||||
return sb.ExtractUnixExtraTime(index, res);
|
||||
if (sb.ID == NFileHeader::NExtraID::kUnix0 ||
|
||||
sb.ID == NFileHeader::NExtraID::kUnix1)
|
||||
return sb.Extract_Unix01_Time(index, res);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -31,8 +31,9 @@ struct CExtraSubBlock
|
||||
CByteBuffer Data;
|
||||
|
||||
bool ExtractNtfsTime(unsigned index, FILETIME &ft) const;
|
||||
bool ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res) const;
|
||||
bool ExtractUnixExtraTime(unsigned index, UInt32 &res) const;
|
||||
bool Extract_UnixTime(bool isCentral, unsigned index, UInt32 &res) const;
|
||||
bool Extract_Unix01_Time(unsigned index, UInt32 &res) const;
|
||||
// bool Extract_Unix_Time(unsigned index, UInt32 &res) const;
|
||||
|
||||
bool CheckIzUnicode(const AString &s) const;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "../../../../C/7zCrc.h"
|
||||
|
||||
#include "../../../Windows/TimeUtils.h"
|
||||
#include "../../Common/OffsetStream.h"
|
||||
|
||||
#include "ZipOut.h"
|
||||
@@ -110,6 +111,40 @@ void COutArchive::WriteUtfName(const CItemOut &item)
|
||||
WriteBytes(item.Name_Utf, (UInt16)item.Name_Utf.Size());
|
||||
}
|
||||
|
||||
|
||||
static const unsigned k_Ntfs_ExtraSize = 4 + 2 + 2 + (3 * 8);
|
||||
static const unsigned k_UnixTime_ExtraSize = 1 + (1 * 4);
|
||||
|
||||
void COutArchive::WriteTimeExtra(const CItemOut &item, bool writeNtfs)
|
||||
{
|
||||
if (writeNtfs)
|
||||
{
|
||||
// windows explorer ignores that extra
|
||||
Write16(NFileHeader::NExtraID::kNTFS);
|
||||
Write16(k_Ntfs_ExtraSize);
|
||||
Write32(0); // reserved
|
||||
Write16(NFileHeader::NNtfsExtra::kTagTime);
|
||||
Write16(8 * 3);
|
||||
WriteNtfsTime(item.Ntfs_MTime);
|
||||
WriteNtfsTime(item.Ntfs_ATime);
|
||||
WriteNtfsTime(item.Ntfs_CTime);
|
||||
}
|
||||
|
||||
if (item.Write_UnixTime)
|
||||
{
|
||||
// windows explorer ignores that extra
|
||||
// by specification : should we write to local header also?
|
||||
Write16(NFileHeader::NExtraID::kUnixTime);
|
||||
Write16(k_UnixTime_ExtraSize);
|
||||
const Byte flags = (Byte)((unsigned)1 << NFileHeader::NUnixTime::kMTime);
|
||||
Write8(flags);
|
||||
UInt32 unixTime;
|
||||
NWindows::NTime::FileTime_To_UnixTime(item.Ntfs_MTime, unixTime);
|
||||
Write32(unixTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void COutArchive::WriteLocalHeader(CItemOut &item, bool needCheck)
|
||||
{
|
||||
m_LocalHeaderPos = m_CurPos;
|
||||
@@ -122,8 +157,14 @@ void COutArchive::WriteLocalHeader(CItemOut &item, bool needCheck)
|
||||
if (needCheck && m_IsZip64)
|
||||
isZip64 = true;
|
||||
|
||||
// Why don't we write NTFS timestamps to local header?
|
||||
// Probably we want to reduce size of archive?
|
||||
const bool writeNtfs = false; // do not write NTFS timestamp to local header
|
||||
// const bool writeNtfs = item.Write_NtfsTime; // write NTFS time to local header
|
||||
const UInt32 localExtraSize = (UInt32)(
|
||||
(isZip64 ? (4 + 8 + 8): 0)
|
||||
+ (writeNtfs ? 4 + k_Ntfs_ExtraSize : 0)
|
||||
+ (item.Write_UnixTime ? 4 + k_UnixTime_ExtraSize : 0)
|
||||
+ item.Get_UtfName_ExtraSize()
|
||||
+ item.LocalExtra.GetSize());
|
||||
if ((UInt16)localExtraSize != localExtraSize)
|
||||
@@ -168,13 +209,12 @@ void COutArchive::WriteLocalHeader(CItemOut &item, bool needCheck)
|
||||
Write64(packSize);
|
||||
}
|
||||
|
||||
WriteTimeExtra(item, writeNtfs);
|
||||
|
||||
WriteUtfName(item);
|
||||
|
||||
WriteExtra(item.LocalExtra);
|
||||
|
||||
// Why don't we write NTFS timestamps to local header?
|
||||
// Probably we want to reduce size of archive?
|
||||
|
||||
const UInt32 localFileHeaderSize = (UInt32)(m_CurPos - m_LocalHeaderPos);
|
||||
if (needCheck && m_LocalFileHeaderSize != localFileHeaderSize)
|
||||
throw CSystemException(E_FAIL);
|
||||
@@ -231,10 +271,10 @@ void COutArchive::WriteDescriptor(const CItemOut &item)
|
||||
|
||||
void COutArchive::WriteCentralHeader(const CItemOut &item)
|
||||
{
|
||||
bool isUnPack64 = DOES_NEED_ZIP64(item.Size);
|
||||
bool isPack64 = DOES_NEED_ZIP64(item.PackSize);
|
||||
bool isPosition64 = DOES_NEED_ZIP64(item.LocalHeaderPos);
|
||||
bool isZip64 = isPack64 || isUnPack64 || isPosition64;
|
||||
const bool isUnPack64 = DOES_NEED_ZIP64(item.Size);
|
||||
const bool isPack64 = DOES_NEED_ZIP64(item.PackSize);
|
||||
const bool isPosition64 = DOES_NEED_ZIP64(item.LocalHeaderPos);
|
||||
const bool isZip64 = isPack64 || isUnPack64 || isPosition64;
|
||||
|
||||
Write32(NSignature::kCentralFileHeader);
|
||||
Write8(item.MadeByVersion.Version);
|
||||
@@ -249,10 +289,11 @@ void COutArchive::WriteCentralHeader(const CItemOut &item)
|
||||
Write16((UInt16)item.Name.Len());
|
||||
|
||||
const UInt16 zip64ExtraSize = (UInt16)((isUnPack64 ? 8: 0) + (isPack64 ? 8: 0) + (isPosition64 ? 8: 0));
|
||||
const UInt16 kNtfsExtraSize = 4 + 2 + 2 + (3 * 8);
|
||||
const bool writeNtfs = item.Write_NtfsTime;
|
||||
const size_t centralExtraSize =
|
||||
(isZip64 ? 4 + zip64ExtraSize : 0)
|
||||
+ (item.NtfsTimeIsDefined ? 4 + kNtfsExtraSize : 0)
|
||||
+ (writeNtfs ? 4 + k_Ntfs_ExtraSize : 0)
|
||||
+ (item.Write_UnixTime ? 4 + k_UnixTime_ExtraSize : 0)
|
||||
+ item.Get_UtfName_ExtraSize()
|
||||
+ item.CentralExtra.GetSize();
|
||||
|
||||
@@ -283,18 +324,7 @@ void COutArchive::WriteCentralHeader(const CItemOut &item)
|
||||
Write64(item.LocalHeaderPos);
|
||||
}
|
||||
|
||||
if (item.NtfsTimeIsDefined)
|
||||
{
|
||||
Write16(NFileHeader::NExtraID::kNTFS);
|
||||
Write16(kNtfsExtraSize);
|
||||
Write32(0); // reserved
|
||||
Write16(NFileHeader::NNtfsExtra::kTagTime);
|
||||
Write16(8 * 3);
|
||||
WriteNtfsTime(item.Ntfs_MTime);
|
||||
WriteNtfsTime(item.Ntfs_ATime);
|
||||
WriteNtfsTime(item.Ntfs_CTime);
|
||||
}
|
||||
|
||||
WriteTimeExtra(item, writeNtfs);
|
||||
WriteUtfName(item);
|
||||
|
||||
WriteExtra(item.CentralExtra);
|
||||
@@ -304,15 +334,15 @@ void COutArchive::WriteCentralHeader(const CItemOut &item)
|
||||
|
||||
void COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const CByteBuffer *comment)
|
||||
{
|
||||
UInt64 cdOffset = GetCurPos();
|
||||
const UInt64 cdOffset = GetCurPos();
|
||||
FOR_VECTOR (i, items)
|
||||
WriteCentralHeader(items[i]);
|
||||
UInt64 cd64EndOffset = GetCurPos();
|
||||
UInt64 cdSize = cd64EndOffset - cdOffset;
|
||||
bool cdOffset64 = DOES_NEED_ZIP64(cdOffset);
|
||||
bool cdSize64 = DOES_NEED_ZIP64(cdSize);
|
||||
bool items64 = items.Size() >= 0xFFFF;
|
||||
bool isZip64 = (cdOffset64 || cdSize64 || items64);
|
||||
const UInt64 cd64EndOffset = GetCurPos();
|
||||
const UInt64 cdSize = cd64EndOffset - cdOffset;
|
||||
const bool cdOffset64 = DOES_NEED_ZIP64(cdOffset);
|
||||
const bool cdSize64 = DOES_NEED_ZIP64(cdSize);
|
||||
const bool items64 = items.Size() >= 0xFFFF;
|
||||
const bool isZip64 = (cdOffset64 || cdSize64 || items64);
|
||||
|
||||
// isZip64 = true; // to test Zip64
|
||||
|
||||
|
||||
@@ -18,7 +18,8 @@ public:
|
||||
FILETIME Ntfs_MTime;
|
||||
FILETIME Ntfs_ATime;
|
||||
FILETIME Ntfs_CTime;
|
||||
bool NtfsTimeIsDefined;
|
||||
bool Write_NtfsTime;
|
||||
bool Write_UnixTime;
|
||||
|
||||
// It's possible that NtfsTime is not defined, but there is NtfsTime in Extra.
|
||||
|
||||
@@ -32,7 +33,10 @@ public:
|
||||
return 4 + 5 + size;
|
||||
}
|
||||
|
||||
CItemOut(): NtfsTimeIsDefined(false) {}
|
||||
CItemOut():
|
||||
Write_NtfsTime(false),
|
||||
Write_UnixTime(false)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@@ -62,6 +66,7 @@ class COutArchive
|
||||
Write32(ft.dwHighDateTime);
|
||||
}
|
||||
|
||||
void WriteTimeExtra(const CItemOut &item, bool writeNtfs);
|
||||
void WriteUtfName(const CItemOut &item);
|
||||
void WriteExtra(const CExtraBlock &extra);
|
||||
void WriteCommonItemInfo(const CLocalItem &item, bool isZip64);
|
||||
|
||||
@@ -20,9 +20,19 @@ REGISTER_ARC_IO(
|
||||
"zip", "zip z01 zipx jar xpi odt ods docx xlsx epub ipa apk appx", 0, 1,
|
||||
k_Signature,
|
||||
0,
|
||||
NArcInfoFlags::kFindSignature |
|
||||
NArcInfoFlags::kMultiSignature |
|
||||
NArcInfoFlags::kUseGlobalOffset,
|
||||
IsArc_Zip)
|
||||
NArcInfoFlags::kFindSignature
|
||||
| NArcInfoFlags::kMultiSignature
|
||||
| NArcInfoFlags::kUseGlobalOffset
|
||||
| NArcInfoFlags::kCTime
|
||||
// | NArcInfoFlags::kCTime_Default
|
||||
| NArcInfoFlags::kATime
|
||||
// | NArcInfoFlags::kATime_Default
|
||||
| NArcInfoFlags::kMTime
|
||||
| NArcInfoFlags::kMTime_Default
|
||||
, TIME_PREC_TO_ARC_FLAGS_MASK (NFileTimeType::kWindows)
|
||||
| TIME_PREC_TO_ARC_FLAGS_MASK (NFileTimeType::kUnix)
|
||||
| TIME_PREC_TO_ARC_FLAGS_MASK (NFileTimeType::kDOS)
|
||||
| TIME_PREC_TO_ARC_FLAGS_TIME_DEFAULT (NFileTimeType::kWindows)
|
||||
, IsArc_Zip)
|
||||
|
||||
}}
|
||||
|
||||
@@ -74,7 +74,9 @@ static void Copy_From_UpdateItem_To_ItemOut(const CUpdateItem &ui, CItemOut &ite
|
||||
item.Ntfs_MTime = ui.Ntfs_MTime;
|
||||
item.Ntfs_ATime = ui.Ntfs_ATime;
|
||||
item.Ntfs_CTime = ui.Ntfs_CTime;
|
||||
item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined;
|
||||
|
||||
item.Write_UnixTime = ui.Write_UnixTime;
|
||||
item.Write_NtfsTime = ui.Write_NtfsTime;
|
||||
}
|
||||
|
||||
static void SetFileHeader(
|
||||
@@ -476,12 +478,9 @@ static void WriteDirHeader(COutArchive &archive, const CCompressionMethodMode *o
|
||||
}
|
||||
|
||||
|
||||
static inline bool IsZero_FILETIME(const FILETIME &ft)
|
||||
{
|
||||
return (ft.dwHighDateTime == 0 && ft.dwLowDateTime == 0);
|
||||
}
|
||||
|
||||
static void UpdatePropsFromStream(CUpdateItem &item, ISequentialInStream *fileInStream,
|
||||
static void UpdatePropsFromStream(
|
||||
const CUpdateOptions &options,
|
||||
CUpdateItem &item, ISequentialInStream *fileInStream,
|
||||
IArchiveUpdateCallback *updateCallback, UInt64 &totalComplexity)
|
||||
{
|
||||
CMyComPtr<IStreamGetProps> getProps;
|
||||
@@ -505,36 +504,100 @@ static void UpdatePropsFromStream(CUpdateItem &item, ISequentialInStream *fileIn
|
||||
}
|
||||
item.Size = size;
|
||||
}
|
||||
|
||||
if (!IsZero_FILETIME(mTime))
|
||||
{
|
||||
item.Ntfs_MTime = mTime;
|
||||
FILETIME loc = { 0, 0 };
|
||||
if (FileTimeToLocalFileTime(&mTime, &loc))
|
||||
{
|
||||
item.Time = 0;
|
||||
NTime::FileTimeToDosTime(loc, item.Time);
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsZero_FILETIME(cTime)) item.Ntfs_CTime = cTime;
|
||||
if (!IsZero_FILETIME(aTime)) item.Ntfs_ATime = aTime;
|
||||
if (options.Write_MTime)
|
||||
if (!FILETIME_IsZero(mTime))
|
||||
{
|
||||
item.Ntfs_MTime = mTime;
|
||||
NTime::UtcFileTime_To_LocalDosTime(mTime, item.Time);
|
||||
}
|
||||
|
||||
if (options.Write_CTime) if (!FILETIME_IsZero(cTime)) item.Ntfs_CTime = cTime;
|
||||
if (options.Write_ATime) if (!FILETIME_IsZero(aTime)) item.Ntfs_ATime = aTime;
|
||||
|
||||
item.Attrib = attrib;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
static HRESULT ReportProps(
|
||||
IArchiveUpdateCallbackArcProp *reportArcProp,
|
||||
UInt32 index,
|
||||
const CItemOut &item,
|
||||
bool isAesMode)
|
||||
{
|
||||
PROPVARIANT prop;
|
||||
prop.vt = VT_EMPTY;
|
||||
prop.wReserved1 = 0;
|
||||
|
||||
NCOM::PropVarEm_Set_UInt64(&prop, item.Size);
|
||||
RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidSize, &prop));
|
||||
|
||||
NCOM::PropVarEm_Set_UInt64(&prop, item.PackSize);
|
||||
RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidPackSize, &prop));
|
||||
|
||||
if (!isAesMode)
|
||||
{
|
||||
NCOM::PropVarEm_Set_UInt32(&prop, item.Crc);
|
||||
RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidCRC, &prop));
|
||||
}
|
||||
|
||||
RINOK(reportArcProp->ReportFinished(NEventIndexType::kOutArcIndex, index, NUpdate::NOperationResult::kOK));
|
||||
|
||||
// if (opCallback) RINOK(opCallback->ReportOperation(NEventIndexType::kOutArcIndex, index, NUpdateNotifyOp::kOpFinished))
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
struct CTotalStats
|
||||
{
|
||||
UInt64 Size;
|
||||
UInt64 PackSize;
|
||||
|
||||
void UpdateWithItem(const CItemOut &item)
|
||||
{
|
||||
Size += item.Size;
|
||||
PackSize += item.PackSize;
|
||||
}
|
||||
};
|
||||
|
||||
static HRESULT ReportArcProps(IArchiveUpdateCallbackArcProp *reportArcProp,
|
||||
CTotalStats &st)
|
||||
{
|
||||
PROPVARIANT prop;
|
||||
prop.vt = VT_EMPTY;
|
||||
prop.wReserved1 = 0;
|
||||
{
|
||||
NWindows::NCOM::PropVarEm_Set_UInt64(&prop, st.Size);
|
||||
RINOK(reportArcProp->ReportProp(
|
||||
NEventIndexType::kArcProp, 0, kpidSize, &prop));
|
||||
}
|
||||
{
|
||||
NWindows::NCOM::PropVarEm_Set_UInt64(&prop, st.PackSize);
|
||||
RINOK(reportArcProp->ReportProp(
|
||||
NEventIndexType::kArcProp, 0, kpidPackSize, &prop));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
static HRESULT Update2St(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
COutArchive &archive,
|
||||
CInArchive *inArchive,
|
||||
const CObjectVector<CItemEx> &inputItems,
|
||||
CObjectVector<CUpdateItem> &updateItems,
|
||||
const CUpdateOptions &updateOptions,
|
||||
const CCompressionMethodMode *options, bool outSeqMode,
|
||||
const CByteBuffer *comment,
|
||||
IArchiveUpdateCallback *updateCallback,
|
||||
UInt64 &totalComplexity,
|
||||
IArchiveUpdateCallbackFile *opCallback)
|
||||
IArchiveUpdateCallbackFile *opCallback
|
||||
// , IArchiveUpdateCallbackArcProp *reportArcProp
|
||||
)
|
||||
{
|
||||
CLocalProgress *lps = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
@@ -575,7 +638,8 @@ static HRESULT Update2St(
|
||||
}
|
||||
else
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> fileInStream;
|
||||
CMyComPtr<ISequentialInStream> fileInStream;
|
||||
{
|
||||
HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream);
|
||||
if (res == S_FALSE)
|
||||
{
|
||||
@@ -596,7 +660,7 @@ static HRESULT Update2St(
|
||||
}
|
||||
// seqMode = true; // to test seqMode
|
||||
|
||||
UpdatePropsFromStream(ui, fileInStream, updateCallback, totalComplexity);
|
||||
UpdatePropsFromStream(updateOptions, ui, fileInStream, updateCallback, totalComplexity);
|
||||
|
||||
CCompressingResult compressingResult;
|
||||
|
||||
@@ -629,10 +693,11 @@ static HRESULT Update2St(
|
||||
SetItemInfoFromCompressingResult(compressingResult, options->IsRealAesMode(), options->AesKeyMode, item);
|
||||
|
||||
archive.WriteLocalHeader_Replace(item);
|
||||
|
||||
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
||||
unpackSizeTotal += item.Size;
|
||||
packSizeTotal += item.PackSize;
|
||||
}
|
||||
// if (reportArcProp) RINOK(ReportProps(reportArcProp, ui.IndexInClient, item, options->IsRealAesMode()))
|
||||
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
||||
unpackSizeTotal += item.Size;
|
||||
packSizeTotal += item.PackSize;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -656,6 +721,14 @@ static HRESULT Update2St(
|
||||
|
||||
archive.WriteCentralDir(items, comment);
|
||||
|
||||
/*
|
||||
CTotalStats stat;
|
||||
stat.Size = unpackSizeTotal;
|
||||
stat.PackSize = packSizeTotal;
|
||||
if (reportArcProp)
|
||||
RINOK(ReportArcProps(reportArcProp, stat))
|
||||
*/
|
||||
|
||||
lps->ProgressOffset += kCentralHeaderSize * updateItems.Size() + 1;
|
||||
return lps->SetCur();
|
||||
}
|
||||
@@ -667,6 +740,7 @@ static HRESULT Update2(
|
||||
CInArchive *inArchive,
|
||||
const CObjectVector<CItemEx> &inputItems,
|
||||
CObjectVector<CUpdateItem> &updateItems,
|
||||
const CUpdateOptions &updateOptions,
|
||||
const CCompressionMethodMode &options, bool outSeqMode,
|
||||
const CByteBuffer *comment,
|
||||
IArchiveUpdateCallback *updateCallback)
|
||||
@@ -674,6 +748,11 @@ static HRESULT Update2(
|
||||
CMyComPtr<IArchiveUpdateCallbackFile> opCallback;
|
||||
updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);
|
||||
|
||||
/*
|
||||
CMyComPtr<IArchiveUpdateCallbackArcProp> reportArcProp;
|
||||
updateCallback->QueryInterface(IID_IArchiveUpdateCallbackArcProp, (void **)&reportArcProp);
|
||||
*/
|
||||
|
||||
bool unknownComplexity = false;
|
||||
UInt64 complexity = 0;
|
||||
UInt64 numFilesToCompress = 0;
|
||||
@@ -901,11 +980,23 @@ static HRESULT Update2(
|
||||
return Update2St(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
archive, inArchive,
|
||||
inputItems, updateItems, &options2, outSeqMode, comment, updateCallback, totalComplexity, opCallback);
|
||||
inputItems, updateItems,
|
||||
updateOptions,
|
||||
&options2, outSeqMode,
|
||||
comment, updateCallback, totalComplexity,
|
||||
opCallback
|
||||
// , reportArcProp
|
||||
);
|
||||
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
|
||||
/*
|
||||
CTotalStats stat;
|
||||
stat.Size = 0;
|
||||
stat.PackSize = 0;
|
||||
*/
|
||||
|
||||
CObjectVector<CItemOut> items;
|
||||
|
||||
CMtProgressMixer *mtProgressMixerSpec = new CMtProgressMixer;
|
||||
@@ -1021,7 +1112,7 @@ static HRESULT Update2(
|
||||
RINOK(res);
|
||||
if (!fileInStream)
|
||||
return E_INVALIDARG;
|
||||
UpdatePropsFromStream(ui, fileInStream, updateCallback, totalComplexity);
|
||||
UpdatePropsFromStream(updateOptions, ui, fileInStream, updateCallback, totalComplexity);
|
||||
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
||||
}
|
||||
|
||||
@@ -1122,6 +1213,13 @@ static HRESULT Update2(
|
||||
memRef.WriteToStream(memManager.GetBlockSize(), outStream);
|
||||
archive.MoveCurPos(item.PackSize);
|
||||
memRef.FreeOpt(&memManager);
|
||||
/*
|
||||
if (reportArcProp)
|
||||
{
|
||||
stat.UpdateWithItem(item);
|
||||
RINOK(ReportProps(reportArcProp, ui.IndexInClient, item, options.IsRealAesMode()));
|
||||
}
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1202,6 +1300,14 @@ static HRESULT Update2(
|
||||
options.IsRealAesMode(), options.AesKeyMode, item);
|
||||
|
||||
archive.WriteLocalHeader_Replace(item);
|
||||
|
||||
/*
|
||||
if (reportArcProp)
|
||||
{
|
||||
stat.UpdateWithItem(item);
|
||||
RINOK(ReportProps(reportArcProp, ui.IndexInClient, item, options.IsRealAesMode()));
|
||||
}
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1230,7 +1336,14 @@ static HRESULT Update2(
|
||||
RINOK(mtCompressProgressMixer.SetRatioInfo(0, NULL, NULL));
|
||||
|
||||
archive.WriteCentralDir(items, comment);
|
||||
|
||||
|
||||
/*
|
||||
if (reportArcProp)
|
||||
{
|
||||
RINOK(ReportArcProps(reportArcProp, stat));
|
||||
}
|
||||
*/
|
||||
|
||||
complexity += kCentralHeaderSize * updateItems.Size() + 1;
|
||||
mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity);
|
||||
return mtCompressProgressMixer.SetRatioInfo(0, NULL, NULL);
|
||||
@@ -1472,6 +1585,7 @@ HRESULT Update(
|
||||
CObjectVector<CUpdateItem> &updateItems,
|
||||
ISequentialOutStream *seqOutStream,
|
||||
CInArchive *inArchive, bool removeSfx,
|
||||
const CUpdateOptions &updateOptions,
|
||||
const CCompressionMethodMode &compressionMethodMode,
|
||||
IArchiveUpdateCallback *updateCallback)
|
||||
{
|
||||
@@ -1529,6 +1643,7 @@ HRESULT Update(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
outArchive, inArchive,
|
||||
inputItems, updateItems,
|
||||
updateOptions,
|
||||
compressionMethodMode, outSeqMode,
|
||||
inArchive ? &inArchive->ArcInfo.Comment : NULL,
|
||||
updateCallback);
|
||||
|
||||
@@ -30,7 +30,9 @@ struct CUpdateItem
|
||||
bool NewData;
|
||||
bool NewProps;
|
||||
bool IsDir;
|
||||
bool NtfsTimeIsDefined;
|
||||
bool Write_NtfsTime;
|
||||
bool Write_UnixTime;
|
||||
// bool Write_UnixTime_ATime;
|
||||
bool IsUtf8;
|
||||
// bool IsAltStream;
|
||||
int IndexInArc;
|
||||
@@ -50,30 +52,50 @@ struct CUpdateItem
|
||||
void Clear()
|
||||
{
|
||||
IsDir = false;
|
||||
NtfsTimeIsDefined = false;
|
||||
|
||||
Write_NtfsTime = false;
|
||||
Write_UnixTime = false;
|
||||
|
||||
IsUtf8 = false;
|
||||
// IsAltStream = false;
|
||||
Time = 0;
|
||||
Size = 0;
|
||||
Name.Empty();
|
||||
Name_Utf.Free();
|
||||
Comment.Free();
|
||||
|
||||
FILETIME_Clear(Ntfs_MTime);
|
||||
FILETIME_Clear(Ntfs_ATime);
|
||||
FILETIME_Clear(Ntfs_CTime);
|
||||
}
|
||||
|
||||
CUpdateItem():
|
||||
IsDir(false),
|
||||
NtfsTimeIsDefined(false),
|
||||
Write_NtfsTime(false),
|
||||
Write_UnixTime(false),
|
||||
IsUtf8(false),
|
||||
// IsAltStream(false),
|
||||
Time(0),
|
||||
Size(0)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
struct CUpdateOptions
|
||||
{
|
||||
bool Write_MTime;
|
||||
bool Write_ATime;
|
||||
bool Write_CTime;
|
||||
};
|
||||
|
||||
|
||||
HRESULT Update(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
const CObjectVector<CItemEx> &inputItems,
|
||||
CObjectVector<CUpdateItem> &updateItems,
|
||||
ISequentialOutStream *seqOutStream,
|
||||
CInArchive *inArchive, bool removeSfx,
|
||||
const CUpdateOptions &updateOptions,
|
||||
const CCompressionMethodMode &compressionMethodMode,
|
||||
IArchiveUpdateCallback *updateCallback);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user