diff options
Diffstat (limited to 'CPP/7zip/Archive/Zip')
-rwxr-xr-x[-rw-r--r--] | CPP/7zip/Archive/Zip/StdAfx.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | CPP/7zip/Archive/Zip/ZipAddCommon.cpp | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | CPP/7zip/Archive/Zip/ZipAddCommon.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | CPP/7zip/Archive/Zip/ZipCompressionMode.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | CPP/7zip/Archive/Zip/ZipHandler.cpp | 178 | ||||
-rwxr-xr-x[-rw-r--r--] | CPP/7zip/Archive/Zip/ZipHandler.h | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | CPP/7zip/Archive/Zip/ZipHandlerOut.cpp | 81 | ||||
-rwxr-xr-x[-rw-r--r--] | CPP/7zip/Archive/Zip/ZipHeader.h | 9 | ||||
-rwxr-xr-x[-rw-r--r--] | CPP/7zip/Archive/Zip/ZipIn.cpp | 23 | ||||
-rwxr-xr-x[-rw-r--r--] | CPP/7zip/Archive/Zip/ZipIn.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | CPP/7zip/Archive/Zip/ZipItem.cpp | 68 | ||||
-rwxr-xr-x[-rw-r--r--] | CPP/7zip/Archive/Zip/ZipItem.h | 5 | ||||
-rwxr-xr-x[-rw-r--r--] | CPP/7zip/Archive/Zip/ZipOut.cpp | 86 | ||||
-rwxr-xr-x[-rw-r--r--] | CPP/7zip/Archive/Zip/ZipOut.h | 9 | ||||
-rwxr-xr-x[-rw-r--r--] | CPP/7zip/Archive/Zip/ZipRegister.cpp | 18 | ||||
-rwxr-xr-x[-rw-r--r--] | CPP/7zip/Archive/Zip/ZipUpdate.cpp | 171 | ||||
-rwxr-xr-x[-rw-r--r--] | CPP/7zip/Archive/Zip/ZipUpdate.h | 28 |
17 files changed, 508 insertions, 175 deletions
diff --git a/CPP/7zip/Archive/Zip/StdAfx.h b/CPP/7zip/Archive/Zip/StdAfx.h index 2854ff3e..2854ff3e 100644..100755 --- a/CPP/7zip/Archive/Zip/StdAfx.h +++ b/CPP/7zip/Archive/Zip/StdAfx.h diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp index 2bb57d5c..2bb57d5c 100644..100755 --- a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.h b/CPP/7zip/Archive/Zip/ZipAddCommon.h index 0aa44adf..0aa44adf 100644..100755 --- a/CPP/7zip/Archive/Zip/ZipAddCommon.h +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.h diff --git a/CPP/7zip/Archive/Zip/ZipCompressionMode.h b/CPP/7zip/Archive/Zip/ZipCompressionMode.h index 842991c4..842991c4 100644..100755 --- a/CPP/7zip/Archive/Zip/ZipCompressionMode.h +++ b/CPP/7zip/Archive/Zip/ZipCompressionMode.h diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp index d8168bbe..1b3985fd 100644..100755 --- a/CPP/7zip/Archive/Zip/ZipHandler.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp @@ -190,6 +190,8 @@ static const Byte kProps[] = kpidVolumeIndex, kpidOffset // kpidIsAltStream + // , kpidChangeTime // for debug + // , 255 // for debug }; static const Byte kArcProps[] = @@ -347,6 +349,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 @@ -392,6 +422,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; @@ -399,7 +453,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; @@ -407,64 +461,28 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val break; } - case kpidCTime: - { - FILETIME utc; - bool defined = true; - if (!extra.GetNtfsTime(NFileHeader::NNtfsExtra::kCTime, utc)) - { - 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: + /* + // 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::kMTime, utc)) + if (NtfsUnixTimeToProp(item.FromCentral, extra, + NFileHeader::NNtfsExtra::kMTime, + NFileHeader::NUnixTime::kMTime, prop)) { - 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; @@ -1122,7 +1140,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) { @@ -1341,6 +1370,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; @@ -1425,33 +1456,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; + } } } } diff --git a/CPP/7zip/Archive/Zip/ZipHandler.h b/CPP/7zip/Archive/Zip/ZipHandler.h index 3043e41c..a70a1a76 100644..100755 --- a/CPP/7zip/Archive/Zip/ZipHandler.h +++ b/CPP/7zip/Archive/Zip/ZipHandler.h @@ -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 = false; diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp index a9b3eae5..77a71df2 100644..100755 --- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp @@ -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)); } diff --git a/CPP/7zip/Archive/Zip/ZipHeader.h b/CPP/7zip/Archive/Zip/ZipHeader.h index c47659ac..34fa359b 100644..100755 --- a/CPP/7zip/Archive/Zip/ZipHeader.h +++ b/CPP/7zip/Archive/Zip/ZipHeader.h @@ -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 }; diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp index 076d6bb5..f2b69a9c 100644..100755 --- a/CPP/7zip/Archive/Zip/ZipIn.cpp +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp @@ -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; diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h index 1498afed..1498afed 100644..100755 --- a/CPP/7zip/Archive/Zip/ZipIn.h +++ b/CPP/7zip/Archive/Zip/ZipIn.h diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp index be336485..cffbb78a 100644..100755 --- a/CPP/7zip/Archive/Zip/ZipItem.cpp +++ b/CPP/7zip/Archive/Zip/ZipItem.cpp @@ -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; diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h index 6ee87658..934d7ecf 100644..100755 --- a/CPP/7zip/Archive/Zip/ZipItem.h +++ b/CPP/7zip/Archive/Zip/ZipItem.h @@ -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; diff --git a/CPP/7zip/Archive/Zip/ZipOut.cpp b/CPP/7zip/Archive/Zip/ZipOut.cpp index efed0a41..8f3f43bf 100644..100755 --- a/CPP/7zip/Archive/Zip/ZipOut.cpp +++ b/CPP/7zip/Archive/Zip/ZipOut.cpp @@ -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 diff --git a/CPP/7zip/Archive/Zip/ZipOut.h b/CPP/7zip/Archive/Zip/ZipOut.h index 3546411c..a645d67f 100644..100755 --- a/CPP/7zip/Archive/Zip/ZipOut.h +++ b/CPP/7zip/Archive/Zip/ZipOut.h @@ -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); diff --git a/CPP/7zip/Archive/Zip/ZipRegister.cpp b/CPP/7zip/Archive/Zip/ZipRegister.cpp index e6929f1b..3ad47153 100644..100755 --- a/CPP/7zip/Archive/Zip/ZipRegister.cpp +++ b/CPP/7zip/Archive/Zip/ZipRegister.cpp @@ -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) }} diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp index 26636c78..7f13071a 100644..100755 --- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp +++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp @@ -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)) + + if (options.Write_MTime) + if (!FILETIME_IsZero(mTime)) { - item.Time = 0; - NTime::FileTimeToDosTime(loc, item.Time); + item.Ntfs_MTime = mTime; + NTime::UtcFileTime_To_LocalDosTime(mTime, item.Time); } - } - if (!IsZero_FILETIME(cTime)) item.Ntfs_CTime = cTime; - if (!IsZero_FILETIME(aTime)) item.Ntfs_ATime = aTime; + 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); diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.h b/CPP/7zip/Archive/Zip/ZipUpdate.h index 95e72a47..d1e35347 100644..100755 --- a/CPP/7zip/Archive/Zip/ZipUpdate.h +++ b/CPP/7zip/Archive/Zip/ZipUpdate.h @@ -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); |