aboutsummaryrefslogtreecommitdiff
path: root/CPP/7zip/UI/Common
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--CPP/7zip/UI/Common/ArchiveCommandLine.cpp36
-rw-r--r--CPP/7zip/UI/Common/ArchiveCommandLine.h7
-rw-r--r--CPP/7zip/UI/Common/ArchiveExtractCallback.cpp315
-rw-r--r--CPP/7zip/UI/Common/ArchiveExtractCallback.h97
-rw-r--r--CPP/7zip/UI/Common/ArchiveOpenCallback.cpp12
-rw-r--r--CPP/7zip/UI/Common/CompressCall.cpp7
-rw-r--r--CPP/7zip/UI/Common/CompressCall.h2
-rw-r--r--CPP/7zip/UI/Common/CompressCall2.cpp28
-rw-r--r--CPP/7zip/UI/Common/DirItem.h249
-rw-r--r--CPP/7zip/UI/Common/EnumDirItems.cpp242
-rw-r--r--CPP/7zip/UI/Common/Extract.cpp55
-rw-r--r--CPP/7zip/UI/Common/Extract.h4
-rw-r--r--CPP/7zip/UI/Common/ExtractMode.h10
-rw-r--r--CPP/7zip/UI/Common/ExtractingFilePath.cpp11
-rw-r--r--CPP/7zip/UI/Common/HashCalc.cpp85
-rw-r--r--CPP/7zip/UI/Common/HashCalc.h6
-rw-r--r--CPP/7zip/UI/Common/LoadCodecs.cpp48
-rw-r--r--CPP/7zip/UI/Common/LoadCodecs.h40
-rw-r--r--CPP/7zip/UI/Common/OpenArchive.cpp166
-rw-r--r--CPP/7zip/UI/Common/OpenArchive.h42
-rw-r--r--CPP/7zip/UI/Common/PropIDUtils.cpp51
-rw-r--r--CPP/7zip/UI/Common/Update.cpp205
-rw-r--r--CPP/7zip/UI/Common/Update.h3
-rw-r--r--CPP/7zip/UI/Common/UpdateCallback.cpp205
-rw-r--r--CPP/7zip/UI/Common/UpdateCallback.h27
-rw-r--r--CPP/7zip/UI/Common/UpdatePair.cpp125
-rw-r--r--CPP/7zip/UI/Common/UpdateProduce.cpp2
-rw-r--r--CPP/7zip/UI/Common/UpdateProduce.h4
-rw-r--r--CPP/7zip/UI/Common/ZipRegistry.cpp105
-rw-r--r--CPP/7zip/UI/Common/ZipRegistry.h47
30 files changed, 1796 insertions, 440 deletions
diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
index 91ef038..d88c851 100644
--- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
+++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
@@ -160,7 +160,11 @@ enum Enum
160 kSymLinks_AllowDangerous, 160 kSymLinks_AllowDangerous,
161 kSymLinks, 161 kSymLinks,
162 kNtSecurity, 162 kNtSecurity,
163
164 kStoreOwnerId,
165 kStoreOwnerName,
163 166
167 kZoneFile,
164 kAltStreams, 168 kAltStreams,
165 kReplaceColonForAltStream, 169 kReplaceColonForAltStream,
166 kWriteToAltStreamIfColon, 170 kWriteToAltStreamIfColon,
@@ -304,7 +308,11 @@ static const CSwitchForm kSwitchForms[] =
304 { "snld", SWFRM_MINUS }, 308 { "snld", SWFRM_MINUS },
305 { "snl", SWFRM_MINUS }, 309 { "snl", SWFRM_MINUS },
306 { "sni", SWFRM_SIMPLE }, 310 { "sni", SWFRM_SIMPLE },
311
312 { "snoi", SWFRM_MINUS },
313 { "snon", SWFRM_MINUS },
307 314
315 { "snz", SWFRM_STRING_SINGL(0) },
308 { "sns", SWFRM_MINUS }, 316 { "sns", SWFRM_MINUS },
309 { "snr", SWFRM_SIMPLE }, 317 { "snr", SWFRM_SIMPLE },
310 { "snc", SWFRM_SIMPLE }, 318 { "snc", SWFRM_SIMPLE },
@@ -1032,9 +1040,9 @@ void CArcCmdLineParser::Parse1(const UStringVector &commandStrings,
1032 1040
1033 if (parser[NKey::kCaseSensitive].ThereIs) 1041 if (parser[NKey::kCaseSensitive].ThereIs)
1034 { 1042 {
1043 options.CaseSensitive =
1035 g_CaseSensitive = !parser[NKey::kCaseSensitive].WithMinus; 1044 g_CaseSensitive = !parser[NKey::kCaseSensitive].WithMinus;
1036 options.CaseSensitiveChange = true; 1045 options.CaseSensitive_Change = true;
1037 options.CaseSensitive = g_CaseSensitive;
1038 } 1046 }
1039 1047
1040 1048
@@ -1367,6 +1375,9 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
1367 SetBoolPair(parser, NKey::kAltStreams, options.AltStreams); 1375 SetBoolPair(parser, NKey::kAltStreams, options.AltStreams);
1368 SetBoolPair(parser, NKey::kHardLinks, options.HardLinks); 1376 SetBoolPair(parser, NKey::kHardLinks, options.HardLinks);
1369 SetBoolPair(parser, NKey::kSymLinks, options.SymLinks); 1377 SetBoolPair(parser, NKey::kSymLinks, options.SymLinks);
1378
1379 SetBoolPair(parser, NKey::kStoreOwnerId, options.StoreOwnerId);
1380 SetBoolPair(parser, NKey::kStoreOwnerName, options.StoreOwnerName);
1370 1381
1371 CBoolPair symLinks_AllowDangerous; 1382 CBoolPair symLinks_AllowDangerous;
1372 SetBoolPair(parser, NKey::kSymLinks_AllowDangerous, symLinks_AllowDangerous); 1383 SetBoolPair(parser, NKey::kSymLinks_AllowDangerous, symLinks_AllowDangerous);
@@ -1420,12 +1431,28 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
1420 nt.ReplaceColonForAltStream = parser[NKey::kReplaceColonForAltStream].ThereIs; 1431 nt.ReplaceColonForAltStream = parser[NKey::kReplaceColonForAltStream].ThereIs;
1421 nt.WriteToAltStreamIfColon = parser[NKey::kWriteToAltStreamIfColon].ThereIs; 1432 nt.WriteToAltStreamIfColon = parser[NKey::kWriteToAltStreamIfColon].ThereIs;
1422 1433
1434 nt.ExtractOwner = options.StoreOwnerId.Val; // StoreOwnerName
1435
1423 if (parser[NKey::kPreserveATime].ThereIs) 1436 if (parser[NKey::kPreserveATime].ThereIs)
1424 nt.PreserveATime = true; 1437 nt.PreserveATime = true;
1425 if (parser[NKey::kShareForWrite].ThereIs) 1438 if (parser[NKey::kShareForWrite].ThereIs)
1426 nt.OpenShareForWrite = true; 1439 nt.OpenShareForWrite = true;
1427 } 1440 }
1428 1441
1442 if (parser[NKey::kZoneFile].ThereIs)
1443 {
1444 eo.ZoneMode = NExtract::NZoneIdMode::kAll;
1445 const UString &s = parser[NKey::kZoneFile].PostStrings[0];
1446 if (!s.IsEmpty())
1447 {
1448 if (s == L"0") eo.ZoneMode = NExtract::NZoneIdMode::kNone;
1449 else if (s == L"1") eo.ZoneMode = NExtract::NZoneIdMode::kAll;
1450 else if (s == L"2") eo.ZoneMode = NExtract::NZoneIdMode::kOffice;
1451 else
1452 throw CArcCmdLineException("Unsupported -snz:", s);
1453 }
1454 }
1455
1429 options.Censor.AddPathsToCensor(NWildcard::k_AbsPath); 1456 options.Censor.AddPathsToCensor(NWildcard::k_AbsPath);
1430 options.Censor.ExtendExclude(); 1457 options.Censor.ExtendExclude();
1431 1458
@@ -1549,6 +1576,9 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
1549 updateOptions.NtSecurity = options.NtSecurity; 1576 updateOptions.NtSecurity = options.NtSecurity;
1550 updateOptions.HardLinks = options.HardLinks; 1577 updateOptions.HardLinks = options.HardLinks;
1551 updateOptions.SymLinks = options.SymLinks; 1578 updateOptions.SymLinks = options.SymLinks;
1579
1580 updateOptions.StoreOwnerId = options.StoreOwnerId;
1581 updateOptions.StoreOwnerName = options.StoreOwnerName;
1552 1582
1553 updateOptions.EMailMode = parser[NKey::kEmail].ThereIs; 1583 updateOptions.EMailMode = parser[NKey::kEmail].ThereIs;
1554 if (updateOptions.EMailMode) 1584 if (updateOptions.EMailMode)
diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.h b/CPP/7zip/UI/Common/ArchiveCommandLine.h
index ff4f28c..745f999 100644
--- a/CPP/7zip/UI/Common/ArchiveCommandLine.h
+++ b/CPP/7zip/UI/Common/ArchiveCommandLine.h
@@ -51,7 +51,7 @@ struct CArcCmdLineOptions
51 bool HelpMode; 51 bool HelpMode;
52 52
53 // bool LargePages; 53 // bool LargePages;
54 bool CaseSensitiveChange; 54 bool CaseSensitive_Change;
55 bool CaseSensitive; 55 bool CaseSensitive;
56 56
57 bool IsInTerminal; 57 bool IsInTerminal;
@@ -97,6 +97,9 @@ struct CArcCmdLineOptions
97 CBoolPair AltStreams; 97 CBoolPair AltStreams;
98 CBoolPair HardLinks; 98 CBoolPair HardLinks;
99 CBoolPair SymLinks; 99 CBoolPair SymLinks;
100
101 CBoolPair StoreOwnerId;
102 CBoolPair StoreOwnerName;
100 103
101 CUpdateOptions UpdateOptions; 104 CUpdateOptions UpdateOptions;
102 CHashOptions HashOptions; 105 CHashOptions HashOptions;
@@ -117,7 +120,7 @@ struct CArcCmdLineOptions
117 CArcCmdLineOptions(): 120 CArcCmdLineOptions():
118 HelpMode(false), 121 HelpMode(false),
119 // LargePages(false), 122 // LargePages(false),
120 CaseSensitiveChange(false), 123 CaseSensitive_Change(false),
121 CaseSensitive(false), 124 CaseSensitive(false),
122 125
123 IsInTerminal(false), 126 IsInTerminal(false),
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
index 73c191e..a574f13 100644
--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
@@ -95,6 +95,83 @@ bool InitLocalPrivileges()
95#endif // _USE_SECURITY_CODE 95#endif // _USE_SECURITY_CODE
96 96
97 97
98
99#if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX)
100
101static const char * const kOfficeExtensions =
102 " doc dot wbk"
103 " docx docm dotx dotm docb wll wwl"
104 " xls xlt xlm"
105 " xlsx xlsm xltx xltm xlsb xla xlam"
106 " ppt pot pps ppa ppam"
107 " pptx pptm potx potm ppam ppsx ppsm sldx sldm"
108 " ";
109
110static bool FindExt2(const char *p, const UString &name)
111{
112 const int pathPos = name.ReverseFind_PathSepar();
113 const int dotPos = name.ReverseFind_Dot();
114 if (dotPos < 0
115 || dotPos < pathPos
116 || dotPos == (int)name.Len() - 1)
117 return false;
118
119 AString s;
120 for (unsigned pos = dotPos + 1;; pos++)
121 {
122 const wchar_t c = name[pos];
123 if (c <= 0)
124 break;
125 if (c >= 0x80)
126 return false;
127 s += (char)MyCharLower_Ascii((char)c);
128 }
129 for (unsigned i = 0; p[i] != 0;)
130 {
131 unsigned j;
132 for (j = i; p[j] != ' '; j++);
133 if (s.Len() == j - i && memcmp(p + i, (const char *)s, s.Len()) == 0)
134 return true;
135 i = j + 1;
136 }
137 return false;
138}
139
140
141static const FChar * const k_ZoneId_StreamName = FTEXT(":Zone.Identifier");
142
143void ReadZoneFile_Of_BaseFile(CFSTR fileName2, CByteBuffer &buf)
144{
145 FString fileName = fileName2;
146 fileName += k_ZoneId_StreamName;
147
148 buf.Free();
149 NIO::CInFile file;
150 if (!file.Open(fileName))
151 return;
152 UInt64 fileSize;
153 if (!file.GetLength(fileSize))
154 return;
155 if (fileSize == 0 || fileSize >= ((UInt32)1 << 16))
156 return;
157 buf.Alloc((size_t)fileSize);
158 size_t processed;
159 if (file.ReadFull(buf, (size_t)fileSize, processed) && processed == fileSize)
160 return;
161 buf.Free();
162}
163
164static bool WriteZoneFile(CFSTR fileName, const CByteBuffer &buf)
165{
166 NIO::COutFile file;
167 if (!file.Create(fileName, true))
168 return false;
169 return file.WriteFull(buf, buf.Size());
170}
171
172#endif
173
174
98#ifdef SUPPORT_LINKS 175#ifdef SUPPORT_LINKS
99 176
100int CHardLinkNode::Compare(const CHardLinkNode &a) const 177int CHardLinkNode::Compare(const CHardLinkNode &a) const
@@ -190,9 +267,9 @@ HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector<UInt32> *r
190 267
191CArchiveExtractCallback::CArchiveExtractCallback(): 268CArchiveExtractCallback::CArchiveExtractCallback():
192 _arc(NULL), 269 _arc(NULL),
193 WriteCTime(true), 270 Write_CTime(true),
194 WriteATime(true), 271 Write_ATime(true),
195 WriteMTime(true), 272 Write_MTime(true),
196 _multiArchives(false) 273 _multiArchives(false)
197{ 274{
198 LocalProgressSpec = new CLocalProgress(); 275 LocalProgressSpec = new CLocalProgress();
@@ -204,6 +281,13 @@ CArchiveExtractCallback::CArchiveExtractCallback():
204} 281}
205 282
206 283
284void CArchiveExtractCallback::InitBeforeNewArchive()
285{
286 #if defined(_WIN32) && !defined(UNDER_CE)
287 ZoneBuf.Free();
288 #endif
289}
290
207void CArchiveExtractCallback::Init( 291void CArchiveExtractCallback::Init(
208 const CExtractNtOptions &ntOptions, 292 const CExtractNtOptions &ntOptions,
209 const NWildcard::CCensorNode *wildcardCensor, 293 const NWildcard::CCensorNode *wildcardCensor,
@@ -240,13 +324,19 @@ void CArchiveExtractCallback::Init(
240 _progressTotal_Defined = true; 324 _progressTotal_Defined = true;
241 325
242 _extractCallback2 = extractCallback2; 326 _extractCallback2 = extractCallback2;
327
243 _compressProgress.Release(); 328 _compressProgress.Release();
244 _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress); 329 _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress);
330
331 _callbackMessage.Release();
245 _extractCallback2.QueryInterface(IID_IArchiveExtractCallbackMessage, &_callbackMessage); 332 _extractCallback2.QueryInterface(IID_IArchiveExtractCallbackMessage, &_callbackMessage);
333
334 _folderArchiveExtractCallback2.Release();
246 _extractCallback2.QueryInterface(IID_IFolderArchiveExtractCallback2, &_folderArchiveExtractCallback2); 335 _extractCallback2.QueryInterface(IID_IFolderArchiveExtractCallback2, &_folderArchiveExtractCallback2);
247 336
248 #ifndef _SFX 337 #ifndef _SFX
249 338
339 ExtractToStreamCallback.Release();
250 _extractCallback2.QueryInterface(IID_IFolderExtractToStreamCallback, &ExtractToStreamCallback); 340 _extractCallback2.QueryInterface(IID_IFolderExtractToStreamCallback, &ExtractToStreamCallback);
251 if (ExtractToStreamCallback) 341 if (ExtractToStreamCallback)
252 { 342 {
@@ -416,26 +506,22 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat
416} 506}
417 507
418 508
419HRESULT CArchiveExtractCallback::GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined) 509HRESULT CArchiveExtractCallback::GetTime(UInt32 index, PROPID propID, CArcTime &ft)
420{ 510{
421 filetimeIsDefined = false; 511 ft.Clear();
422 filetime.dwLowDateTime = 0;
423 filetime.dwHighDateTime = 0;
424 NCOM::CPropVariant prop; 512 NCOM::CPropVariant prop;
425 RINOK(_arc->Archive->GetProperty(index, propID, &prop)); 513 RINOK(_arc->Archive->GetProperty(index, propID, &prop));
426 if (prop.vt == VT_FILETIME) 514 if (prop.vt == VT_FILETIME)
427 { 515 ft.Set_From_Prop(prop);
428 filetime = prop.filetime;
429 filetimeIsDefined = (filetime.dwHighDateTime != 0 || filetime.dwLowDateTime != 0);
430 }
431 else if (prop.vt != VT_EMPTY) 516 else if (prop.vt != VT_EMPTY)
432 return E_FAIL; 517 return E_FAIL;
433 return S_OK; 518 return S_OK;
434} 519}
435 520
521
436HRESULT CArchiveExtractCallback::GetUnpackSize() 522HRESULT CArchiveExtractCallback::GetUnpackSize()
437{ 523{
438 return _arc->GetItemSize(_index, _curSize, _curSizeDefined); 524 return _arc->GetItem_Size(_index, _curSize, _curSizeDefined);
439} 525}
440 526
441static void AddPathToMessage(UString &s, const FString &path) 527static void AddPathToMessage(UString &s, const FString &path)
@@ -454,8 +540,9 @@ HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FSt
454HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *message, const FString &path) 540HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *message, const FString &path)
455{ 541{
456 DWORD errorCode = GetLastError(); 542 DWORD errorCode = GetLastError();
543 if (errorCode == 0)
544 errorCode = (DWORD)E_FAIL;
457 UString s (message); 545 UString s (message);
458 if (errorCode != 0)
459 { 546 {
460 s += " : "; 547 s += " : ";
461 s += NError::MyFormatMessage(errorCode); 548 s += NError::MyFormatMessage(errorCode);
@@ -843,13 +930,58 @@ HRESULT CArchiveExtractCallback::ReadLink()
843#endif // SUPPORT_LINKS 930#endif // SUPPORT_LINKS
844 931
845 932
933#ifndef _WIN32
934
935static HRESULT GetOwner(IInArchive *archive,
936 UInt32 index, UInt32 pidName, UInt32 pidId, COwnerInfo &res)
937{
938 {
939 NWindows::NCOM::CPropVariant prop;
940 RINOK(archive->GetProperty(index, pidId, &prop));
941 if (prop.vt == VT_UI4)
942 {
943 res.Id_Defined = true;
944 res.Id = prop.ulVal; // for debug
945 // res.Id++; // for debug
946 // if (pidId == kpidGroupId) res.Id += 7; // for debug
947 // res.Id = 0; // for debug
948 }
949 else if (prop.vt != VT_EMPTY)
950 return E_INVALIDARG;
951 }
952 {
953 NWindows::NCOM::CPropVariant prop;
954 RINOK(archive->GetProperty(index, pidName, &prop));
955 if (prop.vt == VT_BSTR)
956 {
957 const UString s = prop.bstrVal;
958 ConvertUnicodeToUTF8(s, res.Name);
959 }
960 else if (prop.vt == VT_UI4)
961 {
962 res.Id_Defined = true;
963 res.Id = prop.ulVal;
964 }
965 else if (prop.vt != VT_EMPTY)
966 return E_INVALIDARG;
967 }
968 return S_OK;
969}
970
971#endif
972
846 973
847HRESULT CArchiveExtractCallback::Read_fi_Props() 974HRESULT CArchiveExtractCallback::Read_fi_Props()
848{ 975{
849 IInArchive *archive = _arc->Archive; 976 IInArchive *archive = _arc->Archive;
850 const UInt32 index = _index; 977 const UInt32 index = _index;
851 978
852 _fi.AttribDefined = false; 979 _fi.Attrib_Defined = false;
980
981 #ifndef _WIN32
982 _fi.Owner.Clear();
983 _fi.Group.Clear();
984 #endif
853 985
854 { 986 {
855 NCOM::CPropVariant prop; 987 NCOM::CPropVariant prop;
@@ -868,15 +1000,25 @@ HRESULT CArchiveExtractCallback::Read_fi_Props()
868 if (prop.vt == VT_UI4) 1000 if (prop.vt == VT_UI4)
869 { 1001 {
870 _fi.Attrib = prop.ulVal; 1002 _fi.Attrib = prop.ulVal;
871 _fi.AttribDefined = true; 1003 _fi.Attrib_Defined = true;
872 } 1004 }
873 else if (prop.vt != VT_EMPTY) 1005 else if (prop.vt != VT_EMPTY)
874 return E_FAIL; 1006 return E_FAIL;
875 } 1007 }
876 1008
877 RINOK(GetTime(index, kpidCTime, _fi.CTime, _fi.CTimeDefined)); 1009 RINOK(GetTime(index, kpidCTime, _fi.CTime));
878 RINOK(GetTime(index, kpidATime, _fi.ATime, _fi.ATimeDefined)); 1010 RINOK(GetTime(index, kpidATime, _fi.ATime));
879 RINOK(GetTime(index, kpidMTime, _fi.MTime, _fi.MTimeDefined)); 1011 RINOK(GetTime(index, kpidMTime, _fi.MTime));
1012
1013 #ifndef _WIN32
1014 if (_ntOptions.ExtractOwner)
1015 {
1016 // SendMessageError_with_LastError("_ntOptions.ExtractOwner", _diskFilePath);
1017 GetOwner(archive, index, kpidUser, kpidUserId, _fi.Owner);
1018 GetOwner(archive, index, kpidGroup, kpidGroupId, _fi.Group);
1019 }
1020 #endif
1021
880 return S_OK; 1022 return S_OK;
881} 1023}
882 1024
@@ -923,6 +1065,39 @@ void CArchiveExtractCallback::CorrectPathParts()
923} 1065}
924 1066
925 1067
1068void CArchiveExtractCallback::GetFiTimesCAM(CFiTimesCAM &pt)
1069{
1070 pt.CTime_Defined = false;
1071 pt.ATime_Defined = false;
1072 pt.MTime_Defined = false;
1073
1074 if (Write_MTime)
1075 {
1076 if (_fi.MTime.Def)
1077 {
1078 _fi.MTime.Write_To_FiTime(pt.MTime);
1079 pt.MTime_Defined = true;
1080 }
1081 else if (_arc->MTime.Def)
1082 {
1083 _arc->MTime.Write_To_FiTime(pt.MTime);
1084 pt.MTime_Defined = true;
1085 }
1086 }
1087
1088 if (Write_CTime && _fi.CTime.Def)
1089 {
1090 _fi.CTime.Write_To_FiTime(pt.CTime);
1091 pt.CTime_Defined = true;
1092 }
1093
1094 if (Write_ATime && _fi.ATime.Def)
1095 {
1096 _fi.ATime.Write_To_FiTime(pt.ATime);
1097 pt.ATime_Defined = true;
1098 }
1099}
1100
926 1101
927void CArchiveExtractCallback::CreateFolders() 1102void CArchiveExtractCallback::CreateFolders()
928{ 1103{
@@ -948,30 +1123,9 @@ void CArchiveExtractCallback::CreateFolders()
948 return; 1123 return;
949 1124
950 CDirPathTime pt; 1125 CDirPathTime pt;
951 1126 GetFiTimesCAM(pt);
952 pt.CTime = _fi.CTime; 1127
953 pt.CTimeDefined = (WriteCTime && _fi.CTimeDefined); 1128 if (pt.IsSomeTimeDefined())
954
955 pt.ATime = _fi.ATime;
956 pt.ATimeDefined = (WriteATime && _fi.ATimeDefined);
957
958 pt.MTimeDefined = false;
959
960 if (WriteMTime)
961 {
962 if (_fi.MTimeDefined)
963 {
964 pt.MTime = _fi.MTime;
965 pt.MTimeDefined = true;
966 }
967 else if (_arc->MTimeDefined)
968 {
969 pt.MTime = _arc->MTime;
970 pt.MTimeDefined = true;
971 }
972 }
973
974 if (pt.MTimeDefined || pt.ATimeDefined || pt.CTimeDefined)
975 { 1129 {
976 pt.Path = fullPathNew; 1130 pt.Path = fullPathNew;
977 pt.SetDirTime(); 1131 pt.SetDirTime();
@@ -1006,10 +1160,13 @@ HRESULT CArchiveExtractCallback::CheckExistFile(FString &fullProcessedPath, bool
1006 /* (fileInfo) can be symbolic link. 1160 /* (fileInfo) can be symbolic link.
1007 we can show final file properties here. */ 1161 we can show final file properties here. */
1008 1162
1163 FILETIME ft1;
1164 FiTime_To_FILETIME(fileInfo.MTime, ft1);
1165
1009 Int32 overwriteResult; 1166 Int32 overwriteResult;
1010 RINOK(_extractCallback2->AskOverwrite( 1167 RINOK(_extractCallback2->AskOverwrite(
1011 fs2us(realFullProcessedPath), &fileInfo.MTime, &fileInfo.Size, _item.Path, 1168 fs2us(realFullProcessedPath), &ft1, &fileInfo.Size, _item.Path,
1012 _fi.MTimeDefined ? &_fi.MTime : NULL, 1169 _fi.MTime.Def ? &_fi.MTime.FT : NULL,
1013 _curSizeDefined ? &_curSize : NULL, 1170 _curSizeDefined ? &_curSize : NULL,
1014 &overwriteResult)) 1171 &overwriteResult))
1015 1172
@@ -1126,7 +1283,7 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream
1126 const UInt32 index = _index; 1283 const UInt32 index = _index;
1127 1284
1128 bool isAnti = false; 1285 bool isAnti = false;
1129 RINOK(_arc->IsItemAnti(index, isAnti)); 1286 RINOK(_arc->IsItem_Anti(index, isAnti));
1130 1287
1131 CorrectPathParts(); 1288 CorrectPathParts();
1132 UString processedPath (MakePathFromParts(_item.PathParts)); 1289 UString processedPath (MakePathFromParts(_item.PathParts));
@@ -1147,8 +1304,8 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream
1147 #ifdef SUPPORT_ALT_STREAMS 1304 #ifdef SUPPORT_ALT_STREAMS
1148 if (_item.IsAltStream && _item.ParentIndex != (UInt32)(Int32)-1) 1305 if (_item.IsAltStream && _item.ParentIndex != (UInt32)(Int32)-1)
1149 { 1306 {
1150 int renIndex = _renamedFiles.FindInSorted(CIndexToPathPair(_item.ParentIndex)); 1307 const int renIndex = _renamedFiles.FindInSorted(CIndexToPathPair(_item.ParentIndex));
1151 if (renIndex >= 0) 1308 if (renIndex != -1)
1152 { 1309 {
1153 const CIndexToPathPair &pair = _renamedFiles[(unsigned)renIndex]; 1310 const CIndexToPathPair &pair = _renamedFiles[(unsigned)renIndex];
1154 fullProcessedPath = pair.Path; 1311 fullProcessedPath = pair.Path;
@@ -1224,8 +1381,8 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream
1224 RINOK(Archive_Get_HardLinkNode(archive, index, h, defined)); 1381 RINOK(Archive_Get_HardLinkNode(archive, index, h, defined));
1225 if (defined) 1382 if (defined)
1226 { 1383 {
1227 int linkIndex = _hardLinks.IDs.FindInSorted2(h); 1384 const int linkIndex = _hardLinks.IDs.FindInSorted2(h);
1228 if (linkIndex >= 0) 1385 if (linkIndex != -1)
1229 { 1386 {
1230 FString &hl = _hardLinks.Links[(unsigned)linkIndex]; 1387 FString &hl = _hardLinks.Links[(unsigned)linkIndex];
1231 if (hl.IsEmpty()) 1388 if (hl.IsEmpty())
@@ -1733,11 +1890,34 @@ HRESULT CArchiveExtractCallback::CloseFile()
1733 _curSize = processedSize; 1890 _curSize = processedSize;
1734 _curSizeDefined = true; 1891 _curSizeDefined = true;
1735 1892
1893 #if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX)
1894 if (ZoneBuf.Size() != 0
1895 && !_item.IsAltStream)
1896 {
1897 // if (NFind::DoesFileExist_Raw(tempFilePath))
1898 if (ZoneMode != NExtract::NZoneIdMode::kOffice ||
1899 FindExt2(kOfficeExtensions, _diskFilePath))
1900 {
1901 // we must write zone file before setting of timestamps
1902 const FString path = _diskFilePath + k_ZoneId_StreamName;
1903 if (!WriteZoneFile(path, ZoneBuf))
1904 {
1905 // we can't write it in FAT
1906 // SendMessageError_with_LastError("Can't write Zone.Identifier stream", path);
1907 }
1908 }
1909 }
1910 #endif
1911
1912 CFiTimesCAM t;
1913 GetFiTimesCAM(t);
1914
1736 // #ifdef _WIN32 1915 // #ifdef _WIN32
1737 _outFileStreamSpec->SetTime( 1916 if (t.IsSomeTimeDefined())
1738 (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL, 1917 _outFileStreamSpec->SetTime(
1739 (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL, 1918 t.CTime_Defined ? &t.CTime : NULL,
1740 (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL)); 1919 t.ATime_Defined ? &t.ATime : NULL,
1920 t.MTime_Defined ? &t.MTime : NULL);
1741 // #endif 1921 // #endif
1742 1922
1743 RINOK(_outFileStreamSpec->Close()); 1923 RINOK(_outFileStreamSpec->Close());
@@ -2065,19 +2245,30 @@ HRESULT CArchiveExtractCallback::CloseReparseAndFile()
2065 2245
2066void CArchiveExtractCallback::SetAttrib() 2246void CArchiveExtractCallback::SetAttrib()
2067{ 2247{
2068 #ifndef _WIN32 2248 #ifndef _WIN32
2069 // Linux now doesn't support permissions for symlinks 2249 // Linux now doesn't support permissions for symlinks
2070 if (_isSymLinkCreated) 2250 if (_isSymLinkCreated)
2071 return; 2251 return;
2072 #endif 2252 #endif
2073 2253
2074 if (_itemFailure 2254 if (_itemFailure
2075 || _diskFilePath.IsEmpty() 2255 || _diskFilePath.IsEmpty()
2076 || _stdOutMode 2256 || _stdOutMode
2077 || !_extractMode 2257 || !_extractMode)
2078 || !_fi.AttribDefined)
2079 return; 2258 return;
2080 2259
2260 #ifndef _WIN32
2261 if (_fi.Owner.Id_Defined &&
2262 _fi.Group.Id_Defined)
2263 {
2264 if (my_chown(_diskFilePath, _fi.Owner.Id, _fi.Group.Id) != 0)
2265 {
2266 SendMessageError_with_LastError("Cannot set owner", _diskFilePath);
2267 }
2268 }
2269 #endif
2270
2271 if (_fi.Attrib_Defined)
2081 { 2272 {
2082 // const AString s = GetAnsiString(_diskFilePath); 2273 // const AString s = GetAnsiString(_diskFilePath);
2083 // printf("\nSetFileAttrib_PosixHighDetect: %s: hex:%x\n", s.Ptr(), _fi.Attrib); 2274 // printf("\nSetFileAttrib_PosixHighDetect: %s: hex:%x\n", s.Ptr(), _fi.Attrib);
@@ -2276,7 +2467,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream2(UInt32 index, ISequentialInStre
2276 2467
2277 CInFileStream *inStreamSpec = new CInFileStream; 2468 CInFileStream *inStreamSpec = new CInFileStream;
2278 CMyComPtr<ISequentialInStream> inStreamRef = inStreamSpec; 2469 CMyComPtr<ISequentialInStream> inStreamRef = inStreamSpec;
2279 inStreamSpec->File.PreserveATime = _ntOptions.PreserveATime; 2470 inStreamSpec->Set_PreserveATime(_ntOptions.PreserveATime);
2280 if (!inStreamSpec->OpenShared(fullProcessedPath, _ntOptions.OpenShareForWrite)) 2471 if (!inStreamSpec->OpenShared(fullProcessedPath, _ntOptions.OpenShareForWrite))
2281 { 2472 {
2282 RINOK(SendMessageError_with_LastError(kCantOpenInFile, fullProcessedPath)); 2473 RINOK(SendMessageError_with_LastError(kCantOpenInFile, fullProcessedPath));
@@ -2318,9 +2509,9 @@ void CDirPathSortPair::SetNumSlashes(const FChar *s)
2318bool CDirPathTime::SetDirTime() const 2509bool CDirPathTime::SetDirTime() const
2319{ 2510{
2320 return NDir::SetDirTime(Path, 2511 return NDir::SetDirTime(Path,
2321 CTimeDefined ? &CTime : NULL, 2512 CTime_Defined ? &CTime : NULL,
2322 ATimeDefined ? &ATime : NULL, 2513 ATime_Defined ? &ATime : NULL,
2323 MTimeDefined ? &MTime : NULL); 2514 MTime_Defined ? &MTime : NULL);
2324} 2515}
2325 2516
2326 2517
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
index fe9cb32..fe70bc9 100644
--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
@@ -60,6 +60,8 @@ struct CExtractNtOptions
60 bool ReplaceColonForAltStream; 60 bool ReplaceColonForAltStream;
61 bool WriteToAltStreamIfColon; 61 bool WriteToAltStreamIfColon;
62 62
63 bool ExtractOwner;
64
63 bool PreAllocateOutFile; 65 bool PreAllocateOutFile;
64 66
65 // used for hash arcs only, when we open external files 67 // used for hash arcs only, when we open external files
@@ -69,6 +71,7 @@ struct CExtractNtOptions
69 CExtractNtOptions(): 71 CExtractNtOptions():
70 ReplaceColonForAltStream(false), 72 ReplaceColonForAltStream(false),
71 WriteToAltStreamIfColon(false), 73 WriteToAltStreamIfColon(false),
74 ExtractOwner(false),
72 PreserveATime(false), 75 PreserveATime(false),
73 OpenShareForWrite(false) 76 OpenShareForWrite(false)
74 { 77 {
@@ -163,16 +166,27 @@ struct CIndexToPathPair
163 166
164 167
165 168
166struct CDirPathTime 169struct CFiTimesCAM
167{ 170{
168 FILETIME CTime; 171 CFiTime CTime;
169 FILETIME ATime; 172 CFiTime ATime;
170 FILETIME MTime; 173 CFiTime MTime;
174
175 bool CTime_Defined;
176 bool ATime_Defined;
177 bool MTime_Defined;
171 178
172 bool CTimeDefined; 179 bool IsSomeTimeDefined() const
173 bool ATimeDefined; 180 {
174 bool MTimeDefined; 181 return
182 CTime_Defined |
183 ATime_Defined |
184 MTime_Defined;
185 }
186};
175 187
188struct CDirPathTime: public CFiTimesCAM
189{
176 FString Path; 190 FString Path;
177 191
178 bool SetDirTime() const; 192 bool SetDirTime() const;
@@ -216,6 +230,25 @@ struct CLinkInfo
216#endif // SUPPORT_LINKS 230#endif // SUPPORT_LINKS
217 231
218 232
233#ifndef _WIN32
234
235struct COwnerInfo
236{
237 bool Id_Defined;
238 UInt32 Id;
239 AString Name;
240
241 void Clear()
242 {
243 Id_Defined = false;
244 Id = 0;
245 Name.Empty();
246 }
247};
248
249#endif
250
251
219class CArchiveExtractCallback: 252class CArchiveExtractCallback:
220 public IArchiveExtractCallback, 253 public IArchiveExtractCallback,
221 public IArchiveExtractCallbackMessage, 254 public IArchiveExtractCallbackMessage,
@@ -256,32 +289,33 @@ class CArchiveExtractCallback:
256 289
257 bool _extractMode; 290 bool _extractMode;
258 291
259 bool WriteCTime; 292 bool Write_CTime;
260 bool WriteATime; 293 bool Write_ATime;
261 bool WriteMTime; 294 bool Write_MTime;
262 295
263 bool _encrypted; 296 bool _encrypted;
264 297
265 struct CProcessedFileInfo 298 struct CProcessedFileInfo
266 { 299 {
267 FILETIME CTime; 300 CArcTime CTime;
268 FILETIME ATime; 301 CArcTime ATime;
269 FILETIME MTime; 302 CArcTime MTime;
270 UInt32 Attrib; 303 UInt32 Attrib;
271 304 bool Attrib_Defined;
272 bool CTimeDefined; 305
273 bool ATimeDefined; 306 #ifndef _WIN32
274 bool MTimeDefined; 307 COwnerInfo Owner;
275 bool AttribDefined; 308 COwnerInfo Group;
309 #endif
276 310
277 bool IsReparse() const 311 bool IsReparse() const
278 { 312 {
279 return (AttribDefined && (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0); 313 return (Attrib_Defined && (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0);
280 } 314 }
281 315
282 bool IsLinuxSymLink() const 316 bool IsLinuxSymLink() const
283 { 317 {
284 return (AttribDefined && MY_LIN_S_ISLNK(Attrib >> 16)); 318 return (Attrib_Defined && MY_LIN_S_ISLNK(Attrib >> 16));
285 } 319 }
286 320
287 void SetFromPosixAttrib(UInt32 a) 321 void SetFromPosixAttrib(UInt32 a)
@@ -294,10 +328,14 @@ class CArchiveExtractCallback:
294 FILE_ATTRIBUTE_ARCHIVE; 328 FILE_ATTRIBUTE_ARCHIVE;
295 if ((a & 0222) == 0) // (& S_IWUSR) in p7zip 329 if ((a & 0222) == 0) // (& S_IWUSR) in p7zip
296 Attrib |= FILE_ATTRIBUTE_READONLY; 330 Attrib |= FILE_ATTRIBUTE_READONLY;
331 // 22.00 : we need type bits for (MY_LIN_S_IFLNK) for IsLinuxSymLink()
332 a &= MY_LIN_S_IFMT;
333 if (a == MY_LIN_S_IFLNK)
334 Attrib |= (a << 16);
297 #else 335 #else
298 Attrib = (a << 16) | FILE_ATTRIBUTE_UNIX_EXTENSION; 336 Attrib = (a << 16) | FILE_ATTRIBUTE_UNIX_EXTENSION;
299 #endif 337 #endif
300 AttribDefined = true; 338 Attrib_Defined = true;
301 } 339 }
302 } _fi; 340 } _fi;
303 341
@@ -359,7 +397,7 @@ class CArchiveExtractCallback:
359 #endif 397 #endif
360 398
361 void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath); 399 void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath);
362 HRESULT GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined); 400 HRESULT GetTime(UInt32 index, PROPID propID, CArcTime &ft);
363 HRESULT GetUnpackSize(); 401 HRESULT GetUnpackSize();
364 402
365 FString Hash_GetFullFilePath(); 403 FString Hash_GetFullFilePath();
@@ -372,6 +410,10 @@ public:
372 HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2); 410 HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2);
373 411
374public: 412public:
413 #if defined(_WIN32) && !defined(UNDER_CE)
414 NExtract::NZoneIdMode::EEnum ZoneMode;
415 CByteBuffer ZoneBuf;
416 #endif
375 417
376 CLocalProgress *LocalProgressSpec; 418 CLocalProgress *LocalProgressSpec;
377 419
@@ -405,11 +447,17 @@ public:
405 void InitForMulti(bool multiArchives, 447 void InitForMulti(bool multiArchives,
406 NExtract::NPathMode::EEnum pathMode, 448 NExtract::NPathMode::EEnum pathMode,
407 NExtract::NOverwriteMode::EEnum overwriteMode, 449 NExtract::NOverwriteMode::EEnum overwriteMode,
450 NExtract::NZoneIdMode::EEnum zoneMode,
408 bool keepAndReplaceEmptyDirPrefixes) 451 bool keepAndReplaceEmptyDirPrefixes)
409 { 452 {
410 _multiArchives = multiArchives; 453 _multiArchives = multiArchives;
411 _pathMode = pathMode; 454 _pathMode = pathMode;
412 _overwriteMode = overwriteMode; 455 _overwriteMode = overwriteMode;
456 #if defined(_WIN32) && !defined(UNDER_CE)
457 ZoneMode = zoneMode;
458 #else
459 UNUSED_VAR(zoneMode)
460 #endif
413 _keepAndReplaceEmptyDirPrefixes = keepAndReplaceEmptyDirPrefixes; 461 _keepAndReplaceEmptyDirPrefixes = keepAndReplaceEmptyDirPrefixes;
414 NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0; 462 NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0;
415 } 463 }
@@ -427,6 +475,8 @@ public:
427 475
428 #endif 476 #endif
429 477
478 void InitBeforeNewArchive();
479
430 void Init( 480 void Init(
431 const CExtractNtOptions &ntOptions, 481 const CExtractNtOptions &ntOptions,
432 const NWildcard::CCensorNode *wildcardCensor, 482 const NWildcard::CCensorNode *wildcardCensor,
@@ -483,6 +533,7 @@ private:
483 533
484 HRESULT Read_fi_Props(); 534 HRESULT Read_fi_Props();
485 void CorrectPathParts(); 535 void CorrectPathParts();
536 void GetFiTimesCAM(CFiTimesCAM &pt);
486 void CreateFolders(); 537 void CreateFolders();
487 538
488 bool _isRenamed; 539 bool _isRenamed;
@@ -533,4 +584,6 @@ struct CArchiveExtractCallback_Closer
533 584
534bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item); 585bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item);
535 586
587void ReadZoneFile_Of_BaseFile(CFSTR fileName2, CByteBuffer &buf);
588
536#endif 589#endif
diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
index d5926f8..64aa987 100644
--- a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
+++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
@@ -34,7 +34,8 @@ STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *b
34 return Callback->Open_SetCompleted(files, bytes); 34 return Callback->Open_SetCompleted(files, bytes);
35 COM_TRY_END 35 COM_TRY_END
36} 36}
37 37
38
38STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value) 39STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)
39{ 40{
40 COM_TRY_BEGIN 41 COM_TRY_BEGIN
@@ -51,10 +52,11 @@ STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)
51 case kpidName: prop = fs2us(_fileInfo.Name); break; 52 case kpidName: prop = fs2us(_fileInfo.Name); break;
52 case kpidIsDir: prop = _fileInfo.IsDir(); break; 53 case kpidIsDir: prop = _fileInfo.IsDir(); break;
53 case kpidSize: prop = _fileInfo.Size; break; 54 case kpidSize: prop = _fileInfo.Size; break;
54 case kpidAttrib: prop = (UInt32)_fileInfo.Attrib; break; 55 case kpidAttrib: prop = (UInt32)_fileInfo.GetWinAttrib(); break;
55 case kpidCTime: prop = _fileInfo.CTime; break; 56 case kpidPosixAttrib: prop = (UInt32)_fileInfo.GetPosixAttrib(); break;
56 case kpidATime: prop = _fileInfo.ATime; break; 57 case kpidCTime: PropVariant_SetFrom_FiTime(prop, _fileInfo.CTime); break;
57 case kpidMTime: prop = _fileInfo.MTime; break; 58 case kpidATime: PropVariant_SetFrom_FiTime(prop, _fileInfo.ATime); break;
59 case kpidMTime: PropVariant_SetFrom_FiTime(prop, _fileInfo.MTime); break;
58 } 60 }
59 prop.Detach(value); 61 prop.Detach(value);
60 return S_OK; 62 return S_OK;
diff --git a/CPP/7zip/UI/Common/CompressCall.cpp b/CPP/7zip/UI/Common/CompressCall.cpp
index c7efa99..3ef047f 100644
--- a/CPP/7zip/UI/Common/CompressCall.cpp
+++ b/CPP/7zip/UI/Common/CompressCall.cpp
@@ -252,7 +252,7 @@ static void ExtractGroupCommand(const UStringVector &arcPaths, UString &params,
252 ErrorMessageHRESULT(result); 252 ErrorMessageHRESULT(result);
253} 253}
254 254
255void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup) 255void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup, UInt32 writeZone)
256{ 256{
257 MY_TRY_BEGIN 257 MY_TRY_BEGIN
258 UString params ('x'); 258 UString params ('x');
@@ -263,6 +263,11 @@ void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bo
263 } 263 }
264 if (elimDup) 264 if (elimDup)
265 params += " -spe"; 265 params += " -spe";
266 if (writeZone != (UInt32)(Int32)-1)
267 {
268 params += " -snz";
269 params.Add_UInt32(writeZone);
270 }
266 if (showDialog) 271 if (showDialog)
267 params += kShowDialogSwitch; 272 params += kShowDialogSwitch;
268 ExtractGroupCommand(arcPaths, params, false); 273 ExtractGroupCommand(arcPaths, params, false);
diff --git a/CPP/7zip/UI/Common/CompressCall.h b/CPP/7zip/UI/Common/CompressCall.h
index b817df0..2697fda 100644
--- a/CPP/7zip/UI/Common/CompressCall.h
+++ b/CPP/7zip/UI/Common/CompressCall.h
@@ -15,7 +15,7 @@ HRESULT CompressFiles(
15 const UStringVector &names, 15 const UStringVector &names,
16 bool email, bool showDialog, bool waitFinish); 16 bool email, bool showDialog, bool waitFinish);
17 17
18void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup); 18void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup, UInt32 writeZone);
19void TestArchives(const UStringVector &arcPaths, bool hashMode = false); 19void TestArchives(const UStringVector &arcPaths, bool hashMode = false);
20 20
21void CalcChecksum(const UStringVector &paths, 21void CalcChecksum(const UStringVector &paths,
diff --git a/CPP/7zip/UI/Common/CompressCall2.cpp b/CPP/7zip/UI/Common/CompressCall2.cpp
index 762342d..5d617e1 100644
--- a/CPP/7zip/UI/Common/CompressCall2.cpp
+++ b/CPP/7zip/UI/Common/CompressCall2.cpp
@@ -152,19 +152,12 @@ HRESULT CompressFiles(
152 152
153 153
154static HRESULT ExtractGroupCommand(const UStringVector &arcPaths, 154static HRESULT ExtractGroupCommand(const UStringVector &arcPaths,
155 bool showDialog, const UString &outFolder, bool testMode, bool elimDup = false, 155 bool showDialog, CExtractOptions &eo, const char *kType = NULL)
156 const char *kType = NULL)
157{ 156{
158 MY_TRY_BEGIN 157 MY_TRY_BEGIN
159 158
160 CREATE_CODECS 159 CREATE_CODECS
161 160
162 CExtractOptions eo;
163 eo.OutputDir = us2fs(outFolder);
164 eo.TestMode = testMode;
165 eo.ElimDup.Val = elimDup;
166 eo.ElimDup.Def = elimDup;
167
168 CExtractCallbackImp *ecs = new CExtractCallbackImp; 161 CExtractCallbackImp *ecs = new CExtractCallbackImp;
169 CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; 162 CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;
170 163
@@ -228,15 +221,26 @@ static HRESULT ExtractGroupCommand(const UStringVector &arcPaths,
228 return result; 221 return result;
229} 222}
230 223
231void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup) 224void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder,
225 bool showDialog, bool elimDup, UInt32 writeZone)
232{ 226{
233 ExtractGroupCommand(arcPaths, showDialog, outFolder, false, elimDup); 227 CExtractOptions eo;
228 eo.OutputDir = us2fs(outFolder);
229 eo.TestMode = false;
230 eo.ElimDup.Val = elimDup;
231 eo.ElimDup.Def = elimDup;
232 if (writeZone != (UInt32)(Int32)-1)
233 eo.ZoneMode = (NExtract::NZoneIdMode::EEnum)writeZone;
234 ExtractGroupCommand(arcPaths, showDialog, eo);
234} 235}
235 236
236void TestArchives(const UStringVector &arcPaths, bool hashMode) 237void TestArchives(const UStringVector &arcPaths, bool hashMode)
237{ 238{
238 ExtractGroupCommand(arcPaths, true, UString(), true, 239 CExtractOptions eo;
239 false, // elimDup 240 eo.TestMode = true;
241 ExtractGroupCommand(arcPaths,
242 true, // showDialog
243 eo,
240 hashMode ? "hash" : NULL); 244 hashMode ? "hash" : NULL);
241} 245}
242 246
diff --git a/CPP/7zip/UI/Common/DirItem.h b/CPP/7zip/UI/Common/DirItem.h
index e5f578d..86e385f 100644
--- a/CPP/7zip/UI/Common/DirItem.h
+++ b/CPP/7zip/UI/Common/DirItem.h
@@ -10,6 +10,8 @@
10#include "../../../Common/MyString.h" 10#include "../../../Common/MyString.h"
11 11
12#include "../../../Windows/FileFind.h" 12#include "../../../Windows/FileFind.h"
13#include "../../../Windows/PropVariant.h"
14#include "../../../Windows/TimeUtils.h"
13 15
14#include "../../Common/UniqBlocks.h" 16#include "../../Common/UniqBlocks.h"
15 17
@@ -80,50 +82,213 @@ struct IDirItemsCallback
80 INTERFACE_IDirItemsCallback(=0) 82 INTERFACE_IDirItemsCallback(=0)
81}; 83};
82 84
83struct CDirItem 85
86struct CArcTime
87{
88 FILETIME FT;
89 UInt16 Prec;
90 Byte Ns100;
91 bool Def;
92
93 CArcTime()
94 {
95 Clear();
96 }
97
98 void Clear()
99 {
100 FT.dwHighDateTime = FT.dwLowDateTime = 0;
101 Prec = 0;
102 Ns100 = 0;
103 Def = false;
104 }
105
106 bool IsZero() const
107 {
108 return FT.dwLowDateTime == 0 && FT.dwHighDateTime == 0 && Ns100 == 0;
109 }
110
111 int CompareWith(const CArcTime &a) const
112 {
113 const int res = CompareFileTime(&FT, &a.FT);
114 if (res != 0)
115 return res;
116 if (Ns100 < a.Ns100) return -1;
117 if (Ns100 > a.Ns100) return 1;
118 return 0;
119 }
120
121 UInt64 Get_FILETIME_as_UInt64() const
122 {
123 return (((UInt64)FT.dwHighDateTime) << 32) + FT.dwLowDateTime;
124 }
125
126 UInt32 Get_DosTime() const
127 {
128 FILETIME ft2 = FT;
129 if ((Prec == k_PropVar_TimePrec_Base + 8 ||
130 Prec == k_PropVar_TimePrec_Base + 9)
131 && Ns100 != 0)
132 {
133 UInt64 u64 = Get_FILETIME_as_UInt64();
134 // we round up even small (ns < 100ns) as FileTimeToDosTime()
135 if (u64 % 20000000 == 0)
136 {
137 u64++;
138 ft2.dwHighDateTime = (DWORD)(u64 >> 32);
139 ft2.dwHighDateTime = (DWORD)u64;
140 }
141 }
142 // FileTimeToDosTime() is expected to round up in Windows
143 UInt32 dosTime;
144 // we use simplified code with utctime->dos.
145 // do we need local time instead here?
146 NWindows::NTime::FileTime_To_DosTime(ft2, dosTime);
147 return dosTime;
148 }
149
150 int GetNumDigits() const
151 {
152 if (Prec == k_PropVar_TimePrec_Unix ||
153 Prec == k_PropVar_TimePrec_DOS)
154 return 0;
155 if (Prec == k_PropVar_TimePrec_HighPrec)
156 return 9;
157 if (Prec == k_PropVar_TimePrec_0)
158 return 7;
159 int digits = (int)Prec - (int)k_PropVar_TimePrec_Base;
160 if (digits < 0)
161 digits = 0;
162 return digits;
163 }
164
165 void Write_To_FiTime(CFiTime &dest) const
166 {
167 #ifdef _WIN32
168 dest = FT;
169 #else
170 if (FILETIME_To_timespec(FT, dest))
171 if ((Prec == k_PropVar_TimePrec_Base + 8 ||
172 Prec == k_PropVar_TimePrec_Base + 9)
173 && Ns100 != 0)
174 {
175 dest.tv_nsec += Ns100;
176 }
177 #endif
178 }
179
180 // (Def) is not set
181 void Set_From_FILETIME(const FILETIME &ft)
182 {
183 FT = ft;
184 // Prec = k_PropVar_TimePrec_CompatNTFS;
185 Prec = k_PropVar_TimePrec_Base + 7;
186 Ns100 = 0;
187 }
188
189 // (Def) is not set
190 // it set full form precision: k_PropVar_TimePrec_Base + numDigits
191 void Set_From_FiTime(const CFiTime &ts)
192 {
193 #ifdef _WIN32
194 FT = ts;
195 Prec = k_PropVar_TimePrec_Base + 7;
196 // Prec = k_PropVar_TimePrec_Base; // for debug
197 // Prec = 0; // for debug
198 Ns100 = 0;
199 #else
200 unsigned ns100;
201 FiTime_To_FILETIME_ns100(ts, FT, ns100);
202 Ns100 = (Byte)ns100;
203 Prec = k_PropVar_TimePrec_Base + 9;
204 #endif
205 }
206
207 void Set_From_Prop(const PROPVARIANT &prop)
208 {
209 FT = prop.filetime;
210 unsigned prec = 0;
211 unsigned ns100 = 0;
212 const unsigned prec_Temp = prop.wReserved1;
213 if (prec_Temp != 0
214 && prec_Temp <= k_PropVar_TimePrec_1ns
215 && prop.wReserved3 == 0)
216 {
217 const unsigned ns100_Temp = prop.wReserved2;
218 if (ns100_Temp < 100)
219 {
220 ns100 = ns100_Temp;
221 prec = prec_Temp;
222 }
223 }
224 Prec = (UInt16)prec;
225 Ns100 = (Byte)ns100;
226 Def = true;
227 }
228};
229
230
231struct CDirItem: public NWindows::NFile::NFind::CFileInfoBase
84{ 232{
85 UInt64 Size;
86 FILETIME CTime;
87 FILETIME ATime;
88 FILETIME MTime;
89 UString Name; 233 UString Name;
90 234
91 #ifndef UNDER_CE 235 #ifndef UNDER_CE
92 CByteBuffer ReparseData; 236 CByteBuffer ReparseData;
93 237
94 #ifdef _WIN32 238 #ifdef _WIN32
95 // UString ShortName; 239 // UString ShortName;
96 CByteBuffer ReparseData2; // fixed (reduced) absolute links for WIM format 240 CByteBuffer ReparseData2; // fixed (reduced) absolute links for WIM format
97 bool AreReparseData() const { return ReparseData.Size() != 0 || ReparseData2.Size() != 0; } 241 bool AreReparseData() const { return ReparseData.Size() != 0 || ReparseData2.Size() != 0; }
98 #else 242 #else
99 bool AreReparseData() const { return ReparseData.Size() != 0; } 243 bool AreReparseData() const { return ReparseData.Size() != 0; }
100 #endif // _WIN32 244 #endif // _WIN32
101 245
102 #endif // !UNDER_CE 246 #endif // !UNDER_CE
103 247
104 UInt32 Attrib; 248 void Copy_From_FileInfoBase(const NWindows::NFile::NFind::CFileInfoBase &fi)
249 {
250 (NWindows::NFile::NFind::CFileInfoBase &)*this = fi;
251 }
252
105 int PhyParent; 253 int PhyParent;
106 int LogParent; 254 int LogParent;
107 int SecureIndex; 255 int SecureIndex;
108 256
109 bool IsAltStream; 257 #ifdef _WIN32
110 258 #else
111 CDirItem(): PhyParent(-1), LogParent(-1), SecureIndex(-1), IsAltStream(false) {} 259 int OwnerNameIndex;
112 260 int OwnerGroupIndex;
113 bool IsDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; } 261 #endif
114 bool IsReadOnly() const { return (Attrib & FILE_ATTRIBUTE_READONLY) != 0; } 262
115 bool Has_Attrib_ReparsePoint() const { return (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0; } 263 CDirItem():
116 264 PhyParent(-1)
117 #ifdef _WIN32 265 , LogParent(-1)
118 UInt32 GetPosixAttrib() const 266 , SecureIndex(-1)
267 #ifdef _WIN32
268 #else
269 , OwnerNameIndex(-1)
270 , OwnerGroupIndex(-1)
271 #endif
119 { 272 {
120 UInt32 v = IsDir() ? MY_LIN_S_IFDIR : MY_LIN_S_IFREG;
121 /* 21.06: as WSL we allow write permissions (0222) for directories even for (FILE_ATTRIBUTE_READONLY).
122 So extracting at Linux will be allowed to write files inside (0777) directories. */
123 v |= ((IsReadOnly() && !IsDir()) ? 0555 : 0777);
124 return v;
125 } 273 }
126 #endif 274
275
276 CDirItem(const NWindows::NFile::NFind::CFileInfo &fi,
277 int phyParent, int logParent, int secureIndex):
278 CFileInfoBase(fi)
279 , Name(fs2us(fi.Name))
280 #if defined(_WIN32) && !defined(UNDER_CE)
281 // , ShortName(fs2us(fi.ShortName))
282 #endif
283 , PhyParent(phyParent)
284 , LogParent(logParent)
285 , SecureIndex(secureIndex)
286 #ifdef _WIN32
287 #else
288 , OwnerNameIndex(-1)
289 , OwnerGroupIndex(-1)
290 #endif
291 {}
127}; 292};
128 293
129 294
@@ -145,6 +310,7 @@ public:
145 bool ScanAltStreams; 310 bool ScanAltStreams;
146 bool ExcludeDirItems; 311 bool ExcludeDirItems;
147 bool ExcludeFileItems; 312 bool ExcludeFileItems;
313 bool ShareForWrite;
148 314
149 /* it must be called after anotrher checks */ 315 /* it must be called after anotrher checks */
150 bool CanIncludeItem(bool isDir) const 316 bool CanIncludeItem(bool isDir) const
@@ -160,7 +326,7 @@ public:
160 const FString &phyPrefix); 326 const FString &phyPrefix);
161 #endif 327 #endif
162 328
163 #if defined(_WIN32) && !defined(UNDER_CE) 329 #if defined(_WIN32) && !defined(UNDER_CE)
164 330
165 CUniqBlocks SecureBlocks; 331 CUniqBlocks SecureBlocks;
166 CByteBuffer TempSecureBuf; 332 CByteBuffer TempSecureBuf;
@@ -170,7 +336,17 @@ public:
170 HRESULT AddSecurityItem(const FString &path, int &secureIndex); 336 HRESULT AddSecurityItem(const FString &path, int &secureIndex);
171 HRESULT FillFixedReparse(); 337 HRESULT FillFixedReparse();
172 338
173 #endif 339 #endif
340
341 #ifndef _WIN32
342
343 C_UInt32_UString_Map OwnerNameMap;
344 C_UInt32_UString_Map OwnerGroupMap;
345 bool StoreOwnerName;
346
347 HRESULT FillDeviceSizes();
348
349 #endif
174 350
175 IDirItemsCallback *Callback; 351 IDirItemsCallback *Callback;
176 352
@@ -204,20 +380,25 @@ public:
204}; 380};
205 381
206 382
383
384
207struct CArcItem 385struct CArcItem
208{ 386{
209 UInt64 Size; 387 UInt64 Size;
210 FILETIME MTime;
211 UString Name; 388 UString Name;
389 CArcTime MTime; // it can be mtime of archive file, if MTime is not defined for item in archive
212 bool IsDir; 390 bool IsDir;
213 bool IsAltStream; 391 bool IsAltStream;
214 bool SizeDefined; 392 bool Size_Defined;
215 bool MTimeDefined;
216 bool Censored; 393 bool Censored;
217 UInt32 IndexInServer; 394 UInt32 IndexInServer;
218 int TimeType;
219 395
220 CArcItem(): IsDir(false), IsAltStream(false), SizeDefined(false), MTimeDefined(false), Censored(false), TimeType(-1) {} 396 CArcItem():
397 IsDir(false),
398 IsAltStream(false),
399 Size_Defined(false),
400 Censored(false)
401 {}
221}; 402};
222 403
223#endif 404#endif
diff --git a/CPP/7zip/UI/Common/EnumDirItems.cpp b/CPP/7zip/UI/Common/EnumDirItems.cpp
index 89cce2b..a4ac413 100644
--- a/CPP/7zip/UI/Common/EnumDirItems.cpp
+++ b/CPP/7zip/UI/Common/EnumDirItems.cpp
@@ -5,6 +5,12 @@
5#include <wchar.h> 5#include <wchar.h>
6// #include <stdio.h> 6// #include <stdio.h>
7 7
8#ifndef _WIN32
9#include <grp.h>
10#include <pwd.h>
11#include "../../../Common/UTFConvert.h"
12#endif
13
8#include "../../../Common/Wildcard.h" 14#include "../../../Common/Wildcard.h"
9 15
10#include "../../../Windows/FileDir.h" 16#include "../../../Windows/FileDir.h"
@@ -23,32 +29,60 @@ using namespace NWindows;
23using namespace NFile; 29using namespace NFile;
24using namespace NName; 30using namespace NName;
25 31
32
33static bool FindFile_KeepDots(NFile::NFind::CFileInfo &fi, const FString &path, bool followLink)
34{
35 const bool res = fi.Find(path, followLink);
36 if (!res)
37 return res;
38 if (path.IsEmpty())
39 return res;
40 // we keep name "." and "..", if it's without tail slash
41 const FChar *p = path.RightPtr(1);
42 if (*p != '.')
43 return res;
44 if (p != path.Ptr())
45 {
46 FChar c = p[-1];
47 if (!IS_PATH_SEPAR(c))
48 {
49 if (c != '.')
50 return res;
51 p--;
52 if (p != path.Ptr())
53 {
54 c = p[-1];
55 if (!IS_PATH_SEPAR(c))
56 return res;
57 }
58 }
59 }
60 fi.Name = p;
61 return res;
62}
63
64
26void CDirItems::AddDirFileInfo(int phyParent, int logParent, int secureIndex, 65void CDirItems::AddDirFileInfo(int phyParent, int logParent, int secureIndex,
27 const NFind::CFileInfo &fi) 66 const NFind::CFileInfo &fi)
28{ 67{
29 CDirItem di; 68 /*
30 di.Size = fi.Size; 69 CDirItem di(fi);
31 di.CTime = fi.CTime;
32 di.ATime = fi.ATime;
33 di.MTime = fi.MTime;
34 di.Attrib = fi.Attrib;
35 di.IsAltStream = fi.IsAltStream;
36 di.PhyParent = phyParent; 70 di.PhyParent = phyParent;
37 di.LogParent = logParent; 71 di.LogParent = logParent;
38 di.SecureIndex = secureIndex; 72 di.SecureIndex = secureIndex;
39 di.Name = fs2us(fi.Name);
40 #if defined(_WIN32) && !defined(UNDER_CE)
41 // di.ShortName = fs2us(fi.ShortName);
42 #endif
43 Items.Add(di); 73 Items.Add(di);
74 */
75 VECTOR_ADD_NEW_OBJECT (Items, CDirItem(fi, phyParent, logParent, secureIndex))
44 76
45 if (fi.IsDir()) 77 if (fi.IsDir())
46 Stat.NumDirs++; 78 Stat.NumDirs++;
79 #ifdef _WIN32
47 else if (fi.IsAltStream) 80 else if (fi.IsAltStream)
48 { 81 {
49 Stat.NumAltStreams++; 82 Stat.NumAltStreams++;
50 Stat.AltStreamsSize += fi.Size; 83 Stat.AltStreamsSize += fi.Size;
51 } 84 }
85 #endif
52 else 86 else
53 { 87 {
54 Stat.NumFiles++; 88 Stat.NumFiles++;
@@ -148,9 +182,13 @@ CDirItems::CDirItems():
148 ScanAltStreams(false) 182 ScanAltStreams(false)
149 , ExcludeDirItems(false) 183 , ExcludeDirItems(false)
150 , ExcludeFileItems(false) 184 , ExcludeFileItems(false)
151 #ifdef _USE_SECURITY_CODE 185 , ShareForWrite(false)
186 #ifdef _USE_SECURITY_CODE
152 , ReadSecure(false) 187 , ReadSecure(false)
153 #endif 188 #endif
189 #ifndef _WIN32
190 , StoreOwnerName(true)
191 #endif
154 , Callback(NULL) 192 , Callback(NULL)
155{ 193{
156 #ifdef _USE_SECURITY_CODE 194 #ifdef _USE_SECURITY_CODE
@@ -379,7 +417,7 @@ HRESULT CDirItems::EnumerateItems2(
379 const FString &filePath = filePaths[i]; 417 const FString &filePath = filePaths[i];
380 NFind::CFileInfo fi; 418 NFind::CFileInfo fi;
381 const FString phyPath = phyPrefix + filePath; 419 const FString phyPath = phyPrefix + filePath;
382 if (!fi.Find(phyPath FOLLOW_LINK_PARAM)) 420 if (!FindFile_KeepDots(fi, phyPath FOLLOW_LINK_PARAM))
383 { 421 {
384 RINOK(AddError(phyPath)); 422 RINOK(AddError(phyPath));
385 continue; 423 continue;
@@ -658,15 +696,14 @@ static HRESULT EnumerateForItem(
658 if (!enterToSubFolders) 696 if (!enterToSubFolders)
659 return S_OK; 697 return S_OK;
660 698
661 #ifndef _WIN32 699 #ifndef _WIN32
662 if (fi.IsPosixLink()) 700 if (fi.IsPosixLink())
663 { 701 {
664 // here we can try to resolve posix link 702 // here we can try to resolve posix link
665 // if the link to dir, then can we follow it 703 // if the link to dir, then can we follow it
666 return S_OK; // we don't follow posix link 704 return S_OK; // we don't follow posix link
667 } 705 }
668 #endif 706 #else
669
670 if (dirItems.SymLinks && fi.HasReparsePoint()) 707 if (dirItems.SymLinks && fi.HasReparsePoint())
671 { 708 {
672 /* 20.03: in SymLinks mode: we don't enter to directory that 709 /* 20.03: in SymLinks mode: we don't enter to directory that
@@ -677,6 +714,7 @@ static HRESULT EnumerateForItem(
677 */ 714 */
678 return S_OK; 715 return S_OK;
679 } 716 }
717 #endif
680 nextNode = &curNode; 718 nextNode = &curNode;
681 } 719 }
682 720
@@ -826,7 +864,7 @@ static HRESULT EnumerateDirItems(
826 } 864 }
827 else 865 else
828 #endif 866 #endif
829 if (!fi.Find(fullPath FOLLOW_LINK_PARAM2)) 867 if (!FindFile_KeepDots(fi, fullPath FOLLOW_LINK_PARAM2))
830 { 868 {
831 RINOK(dirItems.AddError(fullPath)); 869 RINOK(dirItems.AddError(fullPath));
832 continue; 870 continue;
@@ -914,15 +952,14 @@ static HRESULT EnumerateDirItems(
914 } 952 }
915 else 953 else
916 { 954 {
917 #ifndef _WIN32 955 #ifndef _WIN32
918 if (fi.IsPosixLink()) 956 if (fi.IsPosixLink())
919 { 957 {
920 // here we can try to resolve posix link 958 // here we can try to resolve posix link
921 // if the link to dir, then can we follow it 959 // if the link to dir, then can we follow it
922 continue; // we don't follow posix link 960 continue; // we don't follow posix link
923 } 961 }
924 #endif 962 #else
925
926 if (dirItems.SymLinks) 963 if (dirItems.SymLinks)
927 { 964 {
928 if (fi.HasReparsePoint()) 965 if (fi.HasReparsePoint())
@@ -932,6 +969,7 @@ static HRESULT EnumerateDirItems(
932 continue; 969 continue;
933 } 970 }
934 } 971 }
972 #endif
935 nextNode = &curNode; 973 nextNode = &curNode;
936 newParts.Add(name); // don't change it to fi.Name. It's for shortnames support 974 newParts.Add(name); // don't change it to fi.Name. It's for shortnames support
937 } 975 }
@@ -973,7 +1011,7 @@ static HRESULT EnumerateDirItems(
973 } 1011 }
974 else 1012 else
975 { 1013 {
976 if (!fi.Find(fullPath FOLLOW_LINK_PARAM2)) 1014 if (!FindFile_KeepDots(fi, fullPath FOLLOW_LINK_PARAM2))
977 { 1015 {
978 if (!nextNode.AreThereIncludeItems()) 1016 if (!nextNode.AreThereIncludeItems())
979 continue; 1017 continue;
@@ -1136,15 +1174,18 @@ HRESULT EnumerateItems(
1136 } 1174 }
1137 dirItems.ReserveDown(); 1175 dirItems.ReserveDown();
1138 1176
1139 #if defined(_WIN32) && !defined(UNDER_CE) 1177 #if defined(_WIN32) && !defined(UNDER_CE)
1140 RINOK(dirItems.FillFixedReparse()); 1178 RINOK(dirItems.FillFixedReparse());
1141 #endif 1179 #endif
1180
1181 #ifndef _WIN32
1182 RINOK(dirItems.FillDeviceSizes());
1183 #endif
1142 1184
1143 return S_OK; 1185 return S_OK;
1144} 1186}
1145 1187
1146 1188
1147
1148#if defined(_WIN32) && !defined(UNDER_CE) 1189#if defined(_WIN32) && !defined(UNDER_CE)
1149 1190
1150HRESULT CDirItems::FillFixedReparse() 1191HRESULT CDirItems::FillFixedReparse()
@@ -1281,6 +1322,148 @@ HRESULT CDirItems::FillFixedReparse()
1281#endif 1322#endif
1282 1323
1283 1324
1325#ifndef _WIN32
1326
1327HRESULT CDirItems::FillDeviceSizes()
1328{
1329 {
1330 FOR_VECTOR (i, Items)
1331 {
1332 CDirItem &item = Items[i];
1333
1334 if (S_ISBLK(item.mode) && item.Size == 0)
1335 {
1336 const FString phyPath = GetPhyPath(i);
1337 NIO::CInFile inFile;
1338 inFile.PreserveATime = true;
1339 if (inFile.OpenShared(phyPath, ShareForWrite)) // fixme: OpenShared ??
1340 {
1341 UInt64 size = 0;
1342 if (inFile.GetLength(size))
1343 item.Size = size;
1344 }
1345 }
1346 if (StoreOwnerName)
1347 {
1348 OwnerNameMap.Add_UInt32(item.uid);
1349 OwnerGroupMap.Add_UInt32(item.gid);
1350 }
1351 }
1352 }
1353
1354 if (StoreOwnerName)
1355 {
1356 UString u;
1357 AString a;
1358 {
1359 FOR_VECTOR (i, OwnerNameMap.Numbers)
1360 {
1361 // 200K/sec speed
1362 u.Empty();
1363 const passwd *pw = getpwuid(OwnerNameMap.Numbers[i]);
1364 if (pw)
1365 {
1366 a = pw->pw_name;
1367 ConvertUTF8ToUnicode(a, u);
1368 }
1369 OwnerNameMap.Strings.Add(u);
1370 }
1371 }
1372 {
1373 FOR_VECTOR (i, OwnerGroupMap.Numbers)
1374 {
1375 u.Empty();
1376 const group *gr = getgrgid(OwnerGroupMap.Numbers[i]);
1377 if (gr)
1378 {
1379 // printf("\ngetgrgid %d %s\n", OwnerGroupMap.Numbers[i], gr->gr_name);
1380 a = gr->gr_name;
1381 ConvertUTF8ToUnicode(a, u);
1382 }
1383 OwnerGroupMap.Strings.Add(u);
1384 }
1385 }
1386
1387 FOR_VECTOR (i, Items)
1388 {
1389 CDirItem &item = Items[i];
1390 {
1391 const int index = OwnerNameMap.Find(item.uid);
1392 if (index < 0) throw 1;
1393 item.OwnerNameIndex = index;
1394 }
1395 {
1396 const int index = OwnerGroupMap.Find(item.gid);
1397 if (index < 0) throw 1;
1398 item.OwnerGroupIndex = index;
1399 }
1400 }
1401 }
1402
1403
1404 // if (NeedOwnerNames)
1405 {
1406 /*
1407 {
1408 for (unsigned i = 0 ; i < 10000; i++)
1409 {
1410 const passwd *pw = getpwuid(i);
1411 if (pw)
1412 {
1413 UString u;
1414 ConvertUTF8ToUnicode(AString(pw->pw_name), u);
1415 OwnerNameMap.Add(i, u);
1416 OwnerNameMap.Add(i, u);
1417 OwnerNameMap.Add(i, u);
1418 }
1419 const group *gr = getgrgid(i);
1420 if (gr)
1421 {
1422 // we can use utf-8 here.
1423 UString u;
1424 ConvertUTF8ToUnicode(AString(gr->gr_name), u);
1425 OwnerGroupMap.Add(i, u);
1426 }
1427 }
1428 }
1429 */
1430 /*
1431 {
1432 FOR_VECTOR (i, OwnerNameMap.Strings)
1433 {
1434 AString s;
1435 ConvertUnicodeToUTF8(OwnerNameMap.Strings[i], s);
1436 printf("\n%5d %s", (unsigned)OwnerNameMap.Numbers[i], s.Ptr());
1437 }
1438 }
1439 {
1440 printf("\n\n=========Groups\n");
1441 FOR_VECTOR (i, OwnerGroupMap.Strings)
1442 {
1443 AString s;
1444 ConvertUnicodeToUTF8(OwnerGroupMap.Strings[i], s);
1445 printf("\n%5d %s", (unsigned)OwnerGroupMap.Numbers[i], s.Ptr());
1446 }
1447 }
1448 */
1449 }
1450 /*
1451 for (unsigned i = 0 ; i < 100000000; i++)
1452 {
1453 // const passwd *pw = getpwuid(1000);
1454 // pw = pw;
1455 int pos = OwnerNameMap.Find(1000);
1456 if (pos < 0 - (int)i)
1457 throw 1;
1458 }
1459 */
1460
1461 return S_OK;
1462}
1463
1464#endif
1465
1466
1284 1467
1285static const char * const kCannotFindArchive = "Cannot find archive"; 1468static const char * const kCannotFindArchive = "Cannot find archive";
1286 1469
@@ -1351,11 +1534,18 @@ HRESULT EnumerateDirItemsAndSort(
1351 1534
1352#ifdef _WIN32 1535#ifdef _WIN32
1353 1536
1537static bool IsDotsName(const wchar_t *s)
1538{
1539 return s[0] == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0));
1540}
1541
1354// This code converts all short file names to long file names. 1542// This code converts all short file names to long file names.
1355 1543
1356static void ConvertToLongName(const UString &prefix, UString &name) 1544static void ConvertToLongName(const UString &prefix, UString &name)
1357{ 1545{
1358 if (name.IsEmpty() || DoesNameContainWildcard(name)) 1546 if (name.IsEmpty()
1547 || DoesNameContainWildcard(name)
1548 || IsDotsName(name))
1359 return; 1549 return;
1360 NFind::CFileInfo fi; 1550 NFind::CFileInfo fi;
1361 const FString path (us2fs(prefix + name)); 1551 const FString path (us2fs(prefix + name));
diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp
index de2aeb2..58f5218 100644
--- a/CPP/7zip/UI/Common/Extract.cpp
+++ b/CPP/7zip/UI/Common/Extract.cpp
@@ -239,18 +239,18 @@ static HRESULT DecompressArchive(
239 Sorted list for file paths was sorted with case insensitive compare function. 239 Sorted list for file paths was sorted with case insensitive compare function.
240 But FindInSorted function did binary search via case sensitive compare function */ 240 But FindInSorted function did binary search via case sensitive compare function */
241 241
242int Find_FileName_InSortedVector(const UStringVector &fileName, const UString &name); 242int Find_FileName_InSortedVector(const UStringVector &fileNames, const UString &name);
243int Find_FileName_InSortedVector(const UStringVector &fileName, const UString &name) 243int Find_FileName_InSortedVector(const UStringVector &fileNames, const UString &name)
244{ 244{
245 unsigned left = 0, right = fileName.Size(); 245 unsigned left = 0, right = fileNames.Size();
246 while (left != right) 246 while (left != right)
247 { 247 {
248 unsigned mid = (left + right) / 2; 248 const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
249 const UString &midValue = fileName[mid]; 249 const UString &midVal = fileNames[mid];
250 int compare = CompareFileNames(name, midValue); 250 const int comp = CompareFileNames(name, midVal);
251 if (compare == 0) 251 if (comp == 0)
252 return (int)mid; 252 return (int)mid;
253 if (compare < 0) 253 if (comp < 0)
254 right = mid; 254 right = mid;
255 else 255 else
256 left = mid + 1; 256 left = mid + 1;
@@ -314,8 +314,13 @@ HRESULT Extract(
314 314
315 CArchiveExtractCallback *ecs = new CArchiveExtractCallback; 315 CArchiveExtractCallback *ecs = new CArchiveExtractCallback;
316 CMyComPtr<IArchiveExtractCallback> ec(ecs); 316 CMyComPtr<IArchiveExtractCallback> ec(ecs);
317 bool multi = (numArcs > 1); 317
318 ecs->InitForMulti(multi, options.PathMode, options.OverwriteMode, 318 const bool multi = (numArcs > 1);
319
320 ecs->InitForMulti(multi,
321 options.PathMode,
322 options.OverwriteMode,
323 options.ZoneMode,
319 false // keepEmptyDirParts 324 false // keepEmptyDirParts
320 ); 325 );
321 #ifndef _SFX 326 #ifndef _SFX
@@ -335,12 +340,18 @@ HRESULT Extract(
335 if (skipArcs[i]) 340 if (skipArcs[i])
336 continue; 341 continue;
337 342
343 ecs->InitBeforeNewArchive();
344
338 const UString &arcPath = arcPaths[i]; 345 const UString &arcPath = arcPaths[i];
339 NFind::CFileInfo fi; 346 NFind::CFileInfo fi;
340 if (options.StdInMode) 347 if (options.StdInMode)
341 { 348 {
342 fi.Size = 0; 349 // do we need ctime and mtime?
343 fi.Attrib = 0; 350 fi.ClearBase();
351 fi.Size = 0; // (UInt64)(Int64)-1;
352 fi.SetAsFile();
353 // NTime::GetCurUtc_FiTime(fi.MTime);
354 // fi.CTime = fi.ATime = fi.MTime;
344 } 355 }
345 else 356 else
346 { 357 {
@@ -417,6 +428,15 @@ HRESULT Extract(
417 continue; 428 continue;
418 } 429 }
419 430
431 #if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX)
432 if (options.ZoneMode != NExtract::NZoneIdMode::kNone
433 && !options.StdInMode)
434 {
435 ReadZoneFile_Of_BaseFile(us2fs(arcPath), ecs->ZoneBuf);
436 }
437 #endif
438
439
420 if (arcLink.Arcs.Size() != 0) 440 if (arcLink.Arcs.Size() != 0)
421 { 441 {
422 if (arcLink.GetArc()->IsHashHandler(op)) 442 if (arcLink.GetArc()->IsHashHandler(op))
@@ -490,11 +510,16 @@ HRESULT Extract(
490 */ 510 */
491 511
492 CArc &arc = arcLink.Arcs.Back(); 512 CArc &arc = arcLink.Arcs.Back();
493 arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice); 513 arc.MTime.Def = !options.StdInMode
494 arc.MTime = fi.MTime; 514 #ifdef _WIN32
515 && !fi.IsDevice
516 #endif
517 ;
518 if (arc.MTime.Def)
519 arc.MTime.Set_From_FiTime(fi.MTime);
495 520
496 UInt64 packProcessed; 521 UInt64 packProcessed;
497 bool calcCrc = 522 const bool calcCrc =
498 #ifndef _SFX 523 #ifndef _SFX
499 (hash != NULL); 524 (hash != NULL);
500 #else 525 #else
diff --git a/CPP/7zip/UI/Common/Extract.h b/CPP/7zip/UI/Common/Extract.h
index 10e06da..f3d1126 100644
--- a/CPP/7zip/UI/Common/Extract.h
+++ b/CPP/7zip/UI/Common/Extract.h
@@ -25,6 +25,7 @@ struct CExtractOptionsBase
25 bool OverwriteMode_Force; 25 bool OverwriteMode_Force;
26 NExtract::NPathMode::EEnum PathMode; 26 NExtract::NPathMode::EEnum PathMode;
27 NExtract::NOverwriteMode::EEnum OverwriteMode; 27 NExtract::NOverwriteMode::EEnum OverwriteMode;
28 NExtract::NZoneIdMode::EEnum ZoneMode;
28 29
29 FString OutputDir; 30 FString OutputDir;
30 CExtractNtOptions NtOptions; 31 CExtractNtOptions NtOptions;
@@ -36,7 +37,8 @@ struct CExtractOptionsBase
36 PathMode_Force(false), 37 PathMode_Force(false),
37 OverwriteMode_Force(false), 38 OverwriteMode_Force(false),
38 PathMode(NExtract::NPathMode::kFullPaths), 39 PathMode(NExtract::NPathMode::kFullPaths),
39 OverwriteMode(NExtract::NOverwriteMode::kAsk) 40 OverwriteMode(NExtract::NOverwriteMode::kAsk),
41 ZoneMode(NExtract::NZoneIdMode::kNone)
40 {} 42 {}
41}; 43};
42 44
diff --git a/CPP/7zip/UI/Common/ExtractMode.h b/CPP/7zip/UI/Common/ExtractMode.h
index 3b2b9a0..9ad831e 100644
--- a/CPP/7zip/UI/Common/ExtractMode.h
+++ b/CPP/7zip/UI/Common/ExtractMode.h
@@ -29,6 +29,16 @@ namespace NOverwriteMode
29 }; 29 };
30} 30}
31 31
32namespace NZoneIdMode
33{
34 enum EEnum
35 {
36 kNone,
37 kAll,
38 kOffice
39 };
40}
41
32} 42}
33 43
34#endif 44#endif
diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/CPP/7zip/UI/Common/ExtractingFilePath.cpp
index 21a306d..a1282b7 100644
--- a/CPP/7zip/UI/Common/ExtractingFilePath.cpp
+++ b/CPP/7zip/UI/Common/ExtractingFilePath.cpp
@@ -34,10 +34,19 @@ static void ReplaceIncorrectChars(UString &s)
34 || 34 ||
35 #endif 35 #endif
36 c == WCHAR_PATH_SEPARATOR) 36 c == WCHAR_PATH_SEPARATOR)
37 {
38 #if WCHAR_PATH_SEPARATOR != L'/'
39 // 22.00 : WSL replacement for backslash
40 if (c == WCHAR_PATH_SEPARATOR)
41 c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT;
42 else
43 #endif
44 c = '_';
37 s.ReplaceOneCharAtPos(i, 45 s.ReplaceOneCharAtPos(i,
38 '_' // default 46 c
39 // (wchar_t)(0xf000 + c) // 21.02 debug: WSL encoding for unsupported characters 47 // (wchar_t)(0xf000 + c) // 21.02 debug: WSL encoding for unsupported characters
40 ); 48 );
49 }
41 } 50 }
42 } 51 }
43 52
diff --git a/CPP/7zip/UI/Common/HashCalc.cpp b/CPP/7zip/UI/Common/HashCalc.cpp
index 2417708..f0aa4bd 100644
--- a/CPP/7zip/UI/Common/HashCalc.cpp
+++ b/CPP/7zip/UI/Common/HashCalc.cpp
@@ -15,6 +15,7 @@
15#include "../../Common/StreamUtils.h" 15#include "../../Common/StreamUtils.h"
16 16
17#include "../../Archive/Common/ItemNameUtils.h" 17#include "../../Archive/Common/ItemNameUtils.h"
18#include "../../Archive/IArchive.h"
18 19
19#include "EnumDirItems.h" 20#include "EnumDirItems.h"
20#include "HashCalc.h" 21#include "HashCalc.h"
@@ -309,8 +310,6 @@ static unsigned GetColumnWidth(unsigned digestSize)
309} 310}
310 311
311 312
312void HashHexToString(char *dest, const Byte *data, UInt32 size);
313
314static void AddHashResultLine( 313static void AddHashResultLine(
315 AString &_s, 314 AString &_s,
316 // bool showHash, 315 // bool showHash,
@@ -463,10 +462,7 @@ HRESULT HashCalc(
463 { 462 {
464 CDirItem di; 463 CDirItem di;
465 di.Size = (UInt64)(Int64)-1; 464 di.Size = (UInt64)(Int64)-1;
466 di.Attrib = 0; 465 di.SetAsFile();
467 di.MTime.dwLowDateTime = 0;
468 di.MTime.dwHighDateTime = 0;
469 di.CTime = di.ATime = di.MTime;
470 dirItems.Items.Add(di); 466 dirItems.Items.Add(di);
471 } 467 }
472 else 468 else
@@ -478,6 +474,8 @@ HRESULT HashCalc(
478 dirItems.ExcludeDirItems = censor.ExcludeDirItems; 474 dirItems.ExcludeDirItems = censor.ExcludeDirItems;
479 dirItems.ExcludeFileItems = censor.ExcludeFileItems; 475 dirItems.ExcludeFileItems = censor.ExcludeFileItems;
480 476
477 dirItems.ShareForWrite = options.OpenShareForWrite;
478
481 HRESULT res = EnumerateItems(censor, 479 HRESULT res = EnumerateItems(censor,
482 options.PathMode, 480 options.PathMode,
483 UString(), 481 UString(),
@@ -498,14 +496,16 @@ HRESULT HashCalc(
498 // hb.Init(); 496 // hb.Init();
499 497
500 hb.NumErrors = dirItems.Stat.NumErrors; 498 hb.NumErrors = dirItems.Stat.NumErrors;
501 499
500 UInt64 totalSize = 0;
502 if (options.StdInMode) 501 if (options.StdInMode)
503 { 502 {
504 RINOK(callback->SetNumFiles(1)); 503 RINOK(callback->SetNumFiles(1));
505 } 504 }
506 else 505 else
507 { 506 {
508 RINOK(callback->SetTotal(dirItems.Stat.GetTotalBytes())); 507 totalSize = dirItems.Stat.GetTotalBytes();
508 RINOK(callback->SetTotal(totalSize));
509 } 509 }
510 510
511 const UInt32 kBufSize = 1 << 15; 511 const UInt32 kBufSize = 1 << 15;
@@ -537,7 +537,9 @@ HRESULT HashCalc(
537 { 537 {
538 path = dirItems.GetLogPath(i); 538 path = dirItems.GetLogPath(i);
539 const CDirItem &di = dirItems.Items[i]; 539 const CDirItem &di = dirItems.Items[i];
540 #ifdef _WIN32
540 isAltStream = di.IsAltStream; 541 isAltStream = di.IsAltStream;
542 #endif
541 543
542 #ifndef UNDER_CE 544 #ifndef UNDER_CE
543 // if (di.AreReparseData()) 545 // if (di.AreReparseData())
@@ -551,7 +553,7 @@ HRESULT HashCalc(
551 #endif 553 #endif
552 { 554 {
553 CInFileStream *inStreamSpec = new CInFileStream; 555 CInFileStream *inStreamSpec = new CInFileStream;
554 inStreamSpec->File.PreserveATime = options.PreserveATime; 556 inStreamSpec->Set_PreserveATime(options.PreserveATime);
555 inStream = inStreamSpec; 557 inStream = inStreamSpec;
556 isDir = di.IsDir(); 558 isDir = di.IsDir();
557 if (!isDir) 559 if (!isDir)
@@ -565,6 +567,20 @@ HRESULT HashCalc(
565 return res; 567 return res;
566 continue; 568 continue;
567 } 569 }
570 if (!options.StdInMode)
571 {
572 UInt64 curSize = 0;
573 if (inStreamSpec->GetSize(&curSize) == S_OK)
574 {
575 if (curSize > di.Size)
576 {
577 totalSize += curSize - di.Size;
578 RINOK(callback->SetTotal(totalSize));
579 // printf("\ntotal = %d MiB\n", (unsigned)(totalSize >> 20));
580 }
581 }
582 }
583 // inStreamSpec->ReloadProps();
568 } 584 }
569 } 585 }
570 } 586 }
@@ -580,6 +596,7 @@ HRESULT HashCalc(
580 { 596 {
581 if ((step & 0xFF) == 0) 597 if ((step & 0xFF) == 0)
582 { 598 {
599 // printf("\ncompl = %d\n", (unsigned)(completeValue >> 20));
583 RINOK(callback->SetCompleted(&completeValue)); 600 RINOK(callback->SetCompleted(&completeValue));
584 } 601 }
585 UInt32 size; 602 UInt32 size;
@@ -1679,8 +1696,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
1679 if (_isArc && !CanUpdate()) 1696 if (_isArc && !CanUpdate())
1680 return E_NOTIMPL; 1697 return E_NOTIMPL;
1681 1698
1682 // const UINT codePage = CP_UTF8; // // (_forceCodePage ? _specifiedCodePage : _openCodePage); 1699 /*
1683 // const unsigned utfFlags = g_Unicode_To_UTF8_Flags; 1700 CMyComPtr<IArchiveUpdateCallbackArcProp> reportArcProp;
1701 callback->QueryInterface(IID_IArchiveUpdateCallbackArcProp, (void **)&reportArcProp);
1702 */
1703
1684 CObjectVector<CUpdateItem> updateItems; 1704 CObjectVector<CUpdateItem> updateItems;
1685 1705
1686 UInt64 complexity = 0; 1706 UInt64 complexity = 0;
@@ -1827,6 +1847,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
1827 if (ui.NewData) 1847 if (ui.NewData)
1828 { 1848 {
1829 UInt64 currentComplexity = ui.Size; 1849 UInt64 currentComplexity = ui.Size;
1850 UInt64 fileSize = 0;
1851
1830 CMyComPtr<ISequentialInStream> fileInStream; 1852 CMyComPtr<ISequentialInStream> fileInStream;
1831 bool needWrite = true; 1853 bool needWrite = true;
1832 { 1854 {
@@ -1840,6 +1862,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
1840 1862
1841 if (fileInStream) 1863 if (fileInStream)
1842 { 1864 {
1865 CMyComPtr<IStreamGetSize> streamGetSize;
1866 fileInStream->QueryInterface(IID_IStreamGetSize, (void **)&streamGetSize);
1867 if (streamGetSize)
1868 {
1869 UInt64 size;
1870 if (streamGetSize->GetSize(&size) == S_OK)
1871 currentComplexity = size;
1872 }
1873 /*
1843 CMyComPtr<IStreamGetProps> getProps; 1874 CMyComPtr<IStreamGetProps> getProps;
1844 fileInStream->QueryInterface(IID_IStreamGetProps, (void **)&getProps); 1875 fileInStream->QueryInterface(IID_IStreamGetProps, (void **)&getProps);
1845 if (getProps) 1876 if (getProps)
@@ -1852,6 +1883,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
1852 // item.MTime = NWindows::NTime::FileTimeToUnixTime64(mTime);; 1883 // item.MTime = NWindows::NTime::FileTimeToUnixTime64(mTime);;
1853 } 1884 }
1854 } 1885 }
1886 */
1855 } 1887 }
1856 else 1888 else
1857 { 1889 {
@@ -1865,7 +1897,6 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
1865 1897
1866 if (needWrite && fileInStream && !isDir) 1898 if (needWrite && fileInStream && !isDir)
1867 { 1899 {
1868 UInt64 fileSize = 0;
1869 for (UInt32 step = 0;; step++) 1900 for (UInt32 step = 0;; step++)
1870 { 1901 {
1871 if ((step & 0xFF) == 0) 1902 if ((step & 0xFF) == 0)
@@ -1901,6 +1932,36 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
1901 } 1932 }
1902 1933
1903 complexity += currentComplexity; 1934 complexity += currentComplexity;
1935
1936 /*
1937 if (reportArcProp)
1938 {
1939 PROPVARIANT prop;
1940 prop.vt = VT_EMPTY;
1941 prop.wReserved1 = 0;
1942
1943 NCOM::PropVarEm_Set_UInt64(&prop, fileSize);
1944 RINOK(reportArcProp->ReportProp(NArchive::NEventIndexType::kOutArcIndex, ui.IndexInClient, kpidSize, &prop));
1945
1946 for (unsigned k = 0; k < hb.Hashers.Size(); k++)
1947 {
1948 const CHasherState &hs = hb.Hashers[k];
1949
1950 if (hs.DigestSize == 4 && hs.Name.IsEqualTo_Ascii_NoCase("crc32"))
1951 {
1952 NCOM::PropVarEm_Set_UInt32(&prop, GetUi32(hs.Digests[k_HashCalc_Index_Current]));
1953 RINOK(reportArcProp->ReportProp(NArchive::NEventIndexType::kOutArcIndex, ui.IndexInClient, kpidCRC, &prop));
1954 }
1955 else
1956 {
1957 RINOK(reportArcProp->ReportRawProp(NArchive::NEventIndexType::kOutArcIndex, ui.IndexInClient,
1958 kpidChecksum, hs.Digests[k_HashCalc_Index_Current],
1959 hs.DigestSize, NPropDataType::kRaw));
1960 }
1961 RINOK(reportArcProp->ReportFinished(NArchive::NEventIndexType::kOutArcIndex, ui.IndexInClient, NArchive::NUpdate::NOperationResult::kOK));
1962 }
1963 }
1964 */
1904 RINOK(callback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); 1965 RINOK(callback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
1905 } 1966 }
1906 else 1967 else
diff --git a/CPP/7zip/UI/Common/HashCalc.h b/CPP/7zip/UI/Common/HashCalc.h
index 80a5565..c566caa 100644
--- a/CPP/7zip/UI/Common/HashCalc.h
+++ b/CPP/7zip/UI/Common/HashCalc.h
@@ -16,6 +16,12 @@ const unsigned k_HashCalc_DigestSize_Max = 64;
16const unsigned k_HashCalc_ExtraSize = 8; 16const unsigned k_HashCalc_ExtraSize = 8;
17const unsigned k_HashCalc_NumGroups = 4; 17const unsigned k_HashCalc_NumGroups = 4;
18 18
19/*
20 if (size <= 8) : upper case : reversed byte order : it shows 32-bit/64-bit number, if data contains little-endian number
21 if (size > 8) : lower case : original byte order (as big-endian byte sequence)
22*/
23void HashHexToString(char *dest, const Byte *data, UInt32 size);
24
19enum 25enum
20{ 26{
21 k_HashCalc_Index_Current, 27 k_HashCalc_Index_Current,
diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp
index 377963a..b6a2073 100644
--- a/CPP/7zip/UI/Common/LoadCodecs.cpp
+++ b/CPP/7zip/UI/Common/LoadCodecs.cpp
@@ -33,8 +33,6 @@ EXPORT_CODECS
33 33
34#include "StdAfx.h" 34#include "StdAfx.h"
35 35
36#include "../../../../C/7zVersion.h"
37
38#include "../../../Common/MyCom.h" 36#include "../../../Common/MyCom.h"
39#include "../../../Common/StringToInt.h" 37#include "../../../Common/StringToInt.h"
40#include "../../../Common/StringConvert.h" 38#include "../../../Common/StringConvert.h"
@@ -275,6 +273,9 @@ static HRESULT GetMethodBoolProp(Func_GetMethodProperty getMethodProperty, UInt3
275#define MY_GET_FUNC(dest, type, func) *(void **)(&dest) = (func); 273#define MY_GET_FUNC(dest, type, func) *(void **)(&dest) = (func);
276// #define MY_GET_FUNC(dest, type, func) dest = (type)(func); 274// #define MY_GET_FUNC(dest, type, func) dest = (type)(func);
277 275
276#define MY_GET_FUNC_LOC(dest, type, func) \
277 type dest; MY_GET_FUNC(dest, type, func)
278
278HRESULT CCodecs::LoadCodecs() 279HRESULT CCodecs::LoadCodecs()
279{ 280{
280 CCodecLib &lib = Libs.Back(); 281 CCodecLib &lib = Libs.Back();
@@ -286,8 +287,7 @@ HRESULT CCodecs::LoadCodecs()
286 if (lib.GetMethodProperty) 287 if (lib.GetMethodProperty)
287 { 288 {
288 UInt32 numMethods = 1; 289 UInt32 numMethods = 1;
289 Func_GetNumberOfMethods getNumberOfMethods; 290 MY_GET_FUNC_LOC (getNumberOfMethods, Func_GetNumberOfMethods, lib.Lib.GetProc("GetNumberOfMethods"));
290 MY_GET_FUNC (getNumberOfMethods, Func_GetNumberOfMethods, lib.Lib.GetProc("GetNumberOfMethods"));
291 if (getNumberOfMethods) 291 if (getNumberOfMethods)
292 { 292 {
293 RINOK(getNumberOfMethods(&numMethods)); 293 RINOK(getNumberOfMethods(&numMethods));
@@ -304,8 +304,7 @@ HRESULT CCodecs::LoadCodecs()
304 } 304 }
305 } 305 }
306 306
307 Func_GetHashers getHashers; 307 MY_GET_FUNC_LOC (getHashers, Func_GetHashers, lib.Lib.GetProc("GetHashers"));
308 MY_GET_FUNC (getHashers, Func_GetHashers, lib.Lib.GetProc("GetHashers"));
309 if (getHashers) 308 if (getHashers)
310 { 309 {
311 RINOK(getHashers(&lib.ComHashers)); 310 RINOK(getHashers(&lib.ComHashers));
@@ -414,17 +413,14 @@ HRESULT CCodecs::LoadFormats()
414 const NDLL::CLibrary &lib = Libs.Back().Lib; 413 const NDLL::CLibrary &lib = Libs.Back().Lib;
415 414
416 Func_GetHandlerProperty getProp = NULL; 415 Func_GetHandlerProperty getProp = NULL;
417 Func_GetHandlerProperty2 getProp2; 416 MY_GET_FUNC_LOC (getProp2, Func_GetHandlerProperty2, lib.GetProc("GetHandlerProperty2"));
418 MY_GET_FUNC (getProp2, Func_GetHandlerProperty2, lib.GetProc("GetHandlerProperty2")); 417 MY_GET_FUNC_LOC (getIsArc, Func_GetIsArc, lib.GetProc("GetIsArc"));
419 Func_GetIsArc getIsArc;
420 MY_GET_FUNC (getIsArc, Func_GetIsArc, lib.GetProc("GetIsArc"));
421 418
422 UInt32 numFormats = 1; 419 UInt32 numFormats = 1;
423 420
424 if (getProp2) 421 if (getProp2)
425 { 422 {
426 Func_GetNumberOfFormats getNumberOfFormats; 423 MY_GET_FUNC_LOC (getNumberOfFormats, Func_GetNumberOfFormats, lib.GetProc("GetNumberOfFormats"));
427 MY_GET_FUNC (getNumberOfFormats, Func_GetNumberOfFormats, lib.GetProc("GetNumberOfFormats"));
428 if (getNumberOfFormats) 424 if (getNumberOfFormats)
429 { 425 {
430 RINOK(getNumberOfFormats(&numFormats)); 426 RINOK(getNumberOfFormats(&numFormats));
@@ -477,6 +473,11 @@ HRESULT CCodecs::LoadFormats()
477 item.Flags |= kArcFlagsPars[j + 1]; 473 item.Flags |= kArcFlagsPars[j + 1];
478 } 474 }
479 } 475 }
476
477 {
478 bool defined = false;
479 RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kTimeFlags, item.TimeFlags, defined));
480 }
480 481
481 CByteBuffer sig; 482 CByteBuffer sig;
482 RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kSignature, sig)); 483 RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kSignature, sig));
@@ -567,8 +568,7 @@ HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll, bool *loaded
567 568
568 /* 569 /*
569 { 570 {
570 Func_LibStartup _LibStartup; 571 MY_GET_FUNC_LOC (_LibStartup, Func_LibStartup, lib.Lib.GetProc("LibStartup"));
571 MY_GET_FUNC (_LibStartup, Func_LibStartup, lib.Lib.GetProc("LibStartup"));
572 if (_LibStartup) 572 if (_LibStartup)
573 { 573 {
574 HRESULT res = _LibStartup(); 574 HRESULT res = _LibStartup();
@@ -585,21 +585,31 @@ HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll, bool *loaded
585 #ifdef _7ZIP_LARGE_PAGES 585 #ifdef _7ZIP_LARGE_PAGES
586 if (g_LargePageSize != 0) 586 if (g_LargePageSize != 0)
587 { 587 {
588 Func_SetLargePageMode setLargePageMode; 588 MY_GET_FUNC_LOC (setLargePageMode, Func_SetLargePageMode, lib.Lib.GetProc("SetLargePageMode"));
589 MY_GET_FUNC (setLargePageMode, Func_SetLargePageMode, lib.Lib.GetProc("SetLargePageMode"));
590 if (setLargePageMode) 589 if (setLargePageMode)
591 setLargePageMode(); 590 setLargePageMode();
592 } 591 }
593 #endif 592 #endif
594 593
595 if (CaseSensitiveChange) 594 if (CaseSensitive_Change)
596 { 595 {
597 Func_SetCaseSensitive setCaseSensitive; 596 MY_GET_FUNC_LOC (setCaseSensitive, Func_SetCaseSensitive, lib.Lib.GetProc("SetCaseSensitive"));
598 MY_GET_FUNC (setCaseSensitive, Func_SetCaseSensitive, lib.Lib.GetProc("SetCaseSensitive"));
599 if (setCaseSensitive) 597 if (setCaseSensitive)
600 setCaseSensitive(CaseSensitive ? 1 : 0); 598 setCaseSensitive(CaseSensitive ? 1 : 0);
601 } 599 }
602 600
601 /*
602 {
603 MY_GET_FUNC_LOC (setClientVersion, Func_SetClientVersion, lib.Lib.GetProc("SetClientVersion"));
604 if (setClientVersion)
605 {
606 // const UInt32 kVersion = (MY_VER_MAJOR << 16) | MY_VER_MINOR;
607 setClientVersion(g_ClientVersion);
608 }
609 }
610 */
611
612
603 MY_GET_FUNC (lib.CreateObject, Func_CreateObject, lib.Lib.GetProc("CreateObject")); 613 MY_GET_FUNC (lib.CreateObject, Func_CreateObject, lib.Lib.GetProc("CreateObject"));
604 { 614 {
605 unsigned startSize = Codecs.Size() + Hashers.Size(); 615 unsigned startSize = Codecs.Size() + Hashers.Size();
diff --git a/CPP/7zip/UI/Common/LoadCodecs.h b/CPP/7zip/UI/Common/LoadCodecs.h
index 829472d..50fb9f8 100644
--- a/CPP/7zip/UI/Common/LoadCodecs.h
+++ b/CPP/7zip/UI/Common/LoadCodecs.h
@@ -96,6 +96,7 @@ struct CArcExtInfo
96struct CArcInfoEx 96struct CArcInfoEx
97{ 97{
98 UInt32 Flags; 98 UInt32 Flags;
99 UInt32 TimeFlags;
99 100
100 Func_CreateInArchive CreateInArchive; 101 Func_CreateInArchive CreateInArchive;
101 Func_IsArc IsArcFunc; 102 Func_IsArc IsArcFunc;
@@ -142,7 +143,7 @@ struct CArcInfoEx
142 bool Flags_FindSignature() const { return (Flags & NArcInfoFlags::kFindSignature) != 0; } 143 bool Flags_FindSignature() const { return (Flags & NArcInfoFlags::kFindSignature) != 0; }
143 144
144 bool Flags_AltStreams() const { return (Flags & NArcInfoFlags::kAltStreams) != 0; } 145 bool Flags_AltStreams() const { return (Flags & NArcInfoFlags::kAltStreams) != 0; }
145 bool Flags_NtSecure() const { return (Flags & NArcInfoFlags::kNtSecure) != 0; } 146 bool Flags_NtSecurity() const { return (Flags & NArcInfoFlags::kNtSecure) != 0; }
146 bool Flags_SymLinks() const { return (Flags & NArcInfoFlags::kSymLinks) != 0; } 147 bool Flags_SymLinks() const { return (Flags & NArcInfoFlags::kSymLinks) != 0; }
147 bool Flags_HardLinks() const { return (Flags & NArcInfoFlags::kHardLinks) != 0; } 148 bool Flags_HardLinks() const { return (Flags & NArcInfoFlags::kHardLinks) != 0; }
148 149
@@ -154,6 +155,27 @@ struct CArcInfoEx
154 bool Flags_ByExtOnlyOpen() const { return (Flags & NArcInfoFlags::kByExtOnlyOpen) != 0; } 155 bool Flags_ByExtOnlyOpen() const { return (Flags & NArcInfoFlags::kByExtOnlyOpen) != 0; }
155 bool Flags_HashHandler() const { return (Flags & NArcInfoFlags::kHashHandler) != 0; } 156 bool Flags_HashHandler() const { return (Flags & NArcInfoFlags::kHashHandler) != 0; }
156 157
158 bool Flags_CTime() const { return (Flags & NArcInfoFlags::kCTime) != 0; }
159 bool Flags_ATime() const { return (Flags & NArcInfoFlags::kATime) != 0; }
160 bool Flags_MTime() const { return (Flags & NArcInfoFlags::kMTime) != 0; }
161
162 bool Flags_CTime_Default() const { return (Flags & NArcInfoFlags::kCTime_Default) != 0; }
163 bool Flags_ATime_Default() const { return (Flags & NArcInfoFlags::kATime_Default) != 0; }
164 bool Flags_MTime_Default() const { return (Flags & NArcInfoFlags::kMTime_Default) != 0; }
165
166 UInt32 Get_TimePrecFlags() const
167 {
168 return (TimeFlags >> NArcInfoTimeFlags::kTime_Prec_Mask_bit_index) &
169 (((UInt32)1 << NArcInfoTimeFlags::kTime_Prec_Mask_num_bits) - 1);
170 }
171
172 UInt32 Get_DefaultTimePrec() const
173 {
174 return (TimeFlags >> NArcInfoTimeFlags::kTime_Prec_Default_bit_index) &
175 (((UInt32)1 << NArcInfoTimeFlags::kTime_Prec_Default_num_bits) - 1);
176 }
177
178
157 UString GetMainExt() const 179 UString GetMainExt() const
158 { 180 {
159 if (Exts.IsEmpty()) 181 if (Exts.IsEmpty())
@@ -162,6 +184,15 @@ struct CArcInfoEx
162 } 184 }
163 int FindExtension(const UString &ext) const; 185 int FindExtension(const UString &ext) const;
164 186
187 bool Is_7z() const { return Name.IsEqualTo_Ascii_NoCase("7z"); }
188 bool Is_Split() const { return Name.IsEqualTo_Ascii_NoCase("Split"); }
189 bool Is_Xz() const { return Name.IsEqualTo_Ascii_NoCase("xz"); }
190 bool Is_BZip2() const { return Name.IsEqualTo_Ascii_NoCase("bzip2"); }
191 bool Is_GZip() const { return Name.IsEqualTo_Ascii_NoCase("gzip"); }
192 bool Is_Tar() const { return Name.IsEqualTo_Ascii_NoCase("tar"); }
193 bool Is_Zip() const { return Name.IsEqualTo_Ascii_NoCase("zip"); }
194 bool Is_Rar() const { return Name.IsEqualTo_Ascii_NoCase("rar"); }
195
165 /* 196 /*
166 UString GetAllExtensions() const 197 UString GetAllExtensions() const
167 { 198 {
@@ -178,11 +209,10 @@ struct CArcInfoEx
178 209
179 void AddExts(const UString &ext, const UString &addExt); 210 void AddExts(const UString &ext, const UString &addExt);
180 211
181 bool IsSplit() const { return StringsAreEqualNoCase_Ascii(Name, "Split"); }
182 // bool IsRar() const { return StringsAreEqualNoCase_Ascii(Name, "Rar"); }
183 212
184 CArcInfoEx(): 213 CArcInfoEx():
185 Flags(0), 214 Flags(0),
215 TimeFlags(0),
186 CreateInArchive(NULL), 216 CreateInArchive(NULL),
187 IsArcFunc(NULL) 217 IsArcFunc(NULL)
188 #ifndef _SFX 218 #ifndef _SFX
@@ -333,14 +363,14 @@ public:
333 CRecordVector<CDllHasherInfo> Hashers; 363 CRecordVector<CDllHasherInfo> Hashers;
334 #endif 364 #endif
335 365
336 bool CaseSensitiveChange; 366 bool CaseSensitive_Change;
337 bool CaseSensitive; 367 bool CaseSensitive;
338 368
339 CCodecs(): 369 CCodecs():
340 #ifdef EXTERNAL_CODECS 370 #ifdef EXTERNAL_CODECS
341 NeedSetLibCodecs(true), 371 NeedSetLibCodecs(true),
342 #endif 372 #endif
343 CaseSensitiveChange(false), 373 CaseSensitive_Change(false),
344 CaseSensitive(false) 374 CaseSensitive(false)
345 {} 375 {}
346 376
diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp
index 331793f..4a91a26 100644
--- a/CPP/7zip/UI/Common/OpenArchive.cpp
+++ b/CPP/7zip/UI/Common/OpenArchive.cpp
@@ -209,8 +209,8 @@ int CHandler::FindInsertPos(const CParseItem &item) const
209 unsigned left = 0, right = _items.Size(); 209 unsigned left = 0, right = _items.Size();
210 while (left != right) 210 while (left != right)
211 { 211 {
212 unsigned mid = (left + right) / 2; 212 const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
213 const CParseItem & midItem = _items[mid]; 213 const CParseItem &midItem = _items[mid];
214 if (item.Offset < midItem.Offset) 214 if (item.Offset < midItem.Offset)
215 right = mid; 215 right = mid;
216 else if (item.Offset > midItem.Offset) 216 else if (item.Offset > midItem.Offset)
@@ -262,8 +262,8 @@ void CHandler::AddUnknownItem(UInt64 next)
262void CHandler::AddItem(const CParseItem &item) 262void CHandler::AddItem(const CParseItem &item)
263{ 263{
264 AddUnknownItem(item.Offset); 264 AddUnknownItem(item.Offset);
265 int pos = FindInsertPos(item); 265 const int pos = FindInsertPos(item);
266 if (pos >= 0) 266 if (pos != -1)
267 { 267 {
268 _items.Insert((unsigned)pos, item); 268 _items.Insert((unsigned)pos, item);
269 UInt64 next = item.Offset + item.Size; 269 UInt64 next = item.Offset + item.Size;
@@ -482,7 +482,7 @@ HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &result) thro
482 return Archive_GetItemBoolProp(arc, index, kpidIsDeleted, result); 482 return Archive_GetItemBoolProp(arc, index, kpidIsDeleted, result);
483} 483}
484 484
485static HRESULT Archive_GetArcBoolProp(IInArchive *arc, PROPID propid, bool &result) throw() 485static HRESULT Archive_GetArcProp_Bool(IInArchive *arc, PROPID propid, bool &result) throw()
486{ 486{
487 NCOM::CPropVariant prop; 487 NCOM::CPropVariant prop;
488 result = false; 488 result = false;
@@ -532,7 +532,7 @@ static HRESULT Archive_GetArcProp_Int(IInArchive *arc, PROPID propid, Int64 &res
532 532
533#ifndef _SFX 533#ifndef _SFX
534 534
535HRESULT CArc::GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const 535HRESULT CArc::GetItem_PathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const
536{ 536{
537 if (!GetRawProps) 537 if (!GetRawProps)
538 return E_FAIL; 538 return E_FAIL;
@@ -616,7 +616,7 @@ HRESULT CArc::GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &pa
616 616
617 617
618 618
619HRESULT CArc::GetItemPath(UInt32 index, UString &result) const 619HRESULT CArc::GetItem_Path(UInt32 index, UString &result) const
620{ 620{
621 #ifdef MY_CPU_LE 621 #ifdef MY_CPU_LE
622 if (GetRawProps) 622 if (GetRawProps)
@@ -752,13 +752,13 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const
752 } 752 }
753 753
754 if (result.IsEmpty()) 754 if (result.IsEmpty())
755 return GetDefaultItemPath(index, result); 755 return GetItem_DefaultPath(index, result);
756 756
757 Convert_UnicodeEsc16_To_UnicodeEscHigh(result); 757 Convert_UnicodeEsc16_To_UnicodeEscHigh(result);
758 return S_OK; 758 return S_OK;
759} 759}
760 760
761HRESULT CArc::GetDefaultItemPath(UInt32 index, UString &result) const 761HRESULT CArc::GetItem_DefaultPath(UInt32 index, UString &result) const
762{ 762{
763 result.Empty(); 763 result.Empty();
764 bool isDir; 764 bool isDir;
@@ -779,9 +779,9 @@ HRESULT CArc::GetDefaultItemPath(UInt32 index, UString &result) const
779 return S_OK; 779 return S_OK;
780} 780}
781 781
782HRESULT CArc::GetItemPath2(UInt32 index, UString &result) const 782HRESULT CArc::GetItem_Path2(UInt32 index, UString &result) const
783{ 783{
784 RINOK(GetItemPath(index, result)); 784 RINOK(GetItem_Path(index, result));
785 if (Ask_Deleted) 785 if (Ask_Deleted)
786 { 786 {
787 bool isDeleted = false; 787 bool isDeleted = false;
@@ -833,7 +833,7 @@ HRESULT CArc::GetItem(UInt32 index, CReadArcItem &item) const
833 RINOK(Archive_IsItem_Dir(Archive, index, item.IsDir)); 833 RINOK(Archive_IsItem_Dir(Archive, index, item.IsDir));
834 item.MainIsDir = item.IsDir; 834 item.MainIsDir = item.IsDir;
835 835
836 RINOK(GetItemPath2(index, item.Path)); 836 RINOK(GetItem_Path2(index, item.Path));
837 837
838 #ifndef _SFX 838 #ifndef _SFX
839 UInt32 mainIndex = index; 839 UInt32 mainIndex = index;
@@ -885,7 +885,7 @@ HRESULT CArc::GetItem(UInt32 index, CReadArcItem &item) const
885 } 885 }
886 else 886 else
887 { 887 {
888 RINOK(GetItemPath2(parentIndex, item.MainPath)); 888 RINOK(GetItem_Path2(parentIndex, item.MainPath));
889 RINOK(Archive_IsItem_Dir(Archive, parentIndex, item.MainIsDir)); 889 RINOK(Archive_IsItem_Dir(Archive, parentIndex, item.MainIsDir));
890 } 890 }
891 } 891 }
@@ -911,7 +911,7 @@ HRESULT CArc::GetItem(UInt32 index, CReadArcItem &item) const
911 #ifndef _SFX 911 #ifndef _SFX
912 if (item._use_baseParentFolder_mode) 912 if (item._use_baseParentFolder_mode)
913 { 913 {
914 RINOK(GetItemPathToParent(mainIndex, (unsigned)item._baseParentFolder, item.PathParts)); 914 RINOK(GetItem_PathToParent(mainIndex, (unsigned)item._baseParentFolder, item.PathParts));
915 915
916 #ifdef SUPPORT_ALT_STREAMS 916 #ifdef SUPPORT_ALT_STREAMS
917 if ((item.WriteToAltStreamIfColon || needFindAltStream) && !item.PathParts.IsEmpty()) 917 if ((item.WriteToAltStreamIfColon || needFindAltStream) && !item.PathParts.IsEmpty())
@@ -970,7 +970,7 @@ static HRESULT Archive_GetItem_Size(IInArchive *archive, UInt32 index, UInt64 &s
970 970
971#endif 971#endif
972 972
973HRESULT CArc::GetItemSize(UInt32 index, UInt64 &size, bool &defined) const 973HRESULT CArc::GetItem_Size(UInt32 index, UInt64 &size, bool &defined) const
974{ 974{
975 NCOM::CPropVariant prop; 975 NCOM::CPropVariant prop;
976 defined = false; 976 defined = false;
@@ -989,24 +989,52 @@ HRESULT CArc::GetItemSize(UInt32 index, UInt64 &size, bool &defined) const
989 return S_OK; 989 return S_OK;
990} 990}
991 991
992HRESULT CArc::GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const 992HRESULT CArc::GetItem_MTime(UInt32 index, CArcTime &at) const
993{ 993{
994 at.Clear();
994 NCOM::CPropVariant prop; 995 NCOM::CPropVariant prop;
995 defined = false;
996 ft.dwHighDateTime = ft.dwLowDateTime = 0;
997 RINOK(Archive->GetProperty(index, kpidMTime, &prop)); 996 RINOK(Archive->GetProperty(index, kpidMTime, &prop));
997
998 if (prop.vt == VT_FILETIME) 998 if (prop.vt == VT_FILETIME)
999 { 999 {
1000 ft = prop.filetime; 1000 /*
1001 defined = true; 1001 // for debug
1002 if (FILETIME_IsZero(prop.at) && MTime.Def)
1003 {
1004 at = MTime;
1005 return S_OK;
1006 }
1007 */
1008 at.Set_From_Prop(prop);
1009 if (at.Prec == 0)
1010 {
1011 // (at.Prec == 0) before version 22.
1012 // so kpidTimeType is required for that code
1013 prop.Clear();
1014 RINOK(Archive->GetProperty(index, kpidTimeType, &prop));
1015 if (prop.vt == VT_UI4)
1016 {
1017 UInt32 val = prop.ulVal;
1018 if (val == NFileTimeType::kWindows)
1019 val = k_PropVar_TimePrec_100ns;
1020 /*
1021 else if (val > k_PropVar_TimePrec_1ns)
1022 {
1023 val = k_PropVar_TimePrec_100ns;
1024 // val = k_PropVar_TimePrec_1ns;
1025 // return E_FAIL; // for debug
1026 }
1027 */
1028 at.Prec = (UInt16)val;
1029 }
1030 }
1031 return S_OK;
1002 } 1032 }
1003 else if (prop.vt != VT_EMPTY) 1033
1034 if (prop.vt != VT_EMPTY)
1004 return E_FAIL; 1035 return E_FAIL;
1005 else if (MTimeDefined) 1036 if (MTime.Def)
1006 { 1037 at = MTime;
1007 ft = MTime;
1008 defined = true;
1009 }
1010 return S_OK; 1038 return S_OK;
1011} 1039}
1012 1040
@@ -1020,6 +1048,7 @@ static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size)
1020 return true; 1048 return true;
1021} 1049}
1022 1050
1051
1023static void MakeCheckOrder(CCodecs *codecs, 1052static void MakeCheckOrder(CCodecs *codecs,
1024 CIntVector &orderIndices, unsigned numTypes, CIntVector &orderIndices2, 1053 CIntVector &orderIndices, unsigned numTypes, CIntVector &orderIndices2,
1025 const Byte *data, size_t dataSize) 1054 const Byte *data, size_t dataSize)
@@ -1034,7 +1063,7 @@ static void MakeCheckOrder(CCodecs *codecs,
1034 { 1063 {
1035 if (ai.Signatures.IsEmpty()) 1064 if (ai.Signatures.IsEmpty())
1036 { 1065 {
1037 if (dataSize != 0) // 21.04: no Sinature means Empty Signature 1066 if (dataSize != 0) // 21.04: no Signature means Empty Signature
1038 continue; 1067 continue;
1039 } 1068 }
1040 else 1069 else
@@ -1229,7 +1258,7 @@ void CArcErrorInfo::ClearErrors()
1229HRESULT CArc::ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes) 1258HRESULT CArc::ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes)
1230{ 1259{
1231 // OkPhySize_Defined = false; 1260 // OkPhySize_Defined = false;
1232 PhySizeDefined = false; 1261 PhySize_Defined = false;
1233 PhySize = 0; 1262 PhySize = 0;
1234 Offset = 0; 1263 Offset = 0;
1235 AvailPhySize = FileSize - startPos; 1264 AvailPhySize = FileSize - startPos;
@@ -1262,12 +1291,12 @@ HRESULT CArc::ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openR
1262 1291
1263 if (openRes == S_OK || ErrorInfo.IsArc_After_NonOpen()) 1292 if (openRes == S_OK || ErrorInfo.IsArc_After_NonOpen())
1264 { 1293 {
1265 RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, PhySize, PhySizeDefined)); 1294 RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, PhySize, PhySize_Defined));
1266 /* 1295 /*
1267 RINOK(Archive_GetArcProp_UInt(archive, kpidOkPhySize, OkPhySize, OkPhySize_Defined)); 1296 RINOK(Archive_GetArcProp_UInt(archive, kpidOkPhySize, OkPhySize, OkPhySize_Defined));
1268 if (!OkPhySize_Defined) 1297 if (!OkPhySize_Defined)
1269 { 1298 {
1270 OkPhySize_Defined = PhySizeDefined; 1299 OkPhySize_Defined = PhySize_Defined;
1271 OkPhySize = PhySize; 1300 OkPhySize = PhySize;
1272 } 1301 }
1273 */ 1302 */
@@ -1277,7 +1306,7 @@ HRESULT CArc::ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openR
1277 1306
1278 Int64 globalOffset = (Int64)startPos + Offset; 1307 Int64 globalOffset = (Int64)startPos + Offset;
1279 AvailPhySize = (UInt64)((Int64)FileSize - globalOffset); 1308 AvailPhySize = (UInt64)((Int64)FileSize - globalOffset);
1280 if (PhySizeDefined) 1309 if (PhySize_Defined)
1281 { 1310 {
1282 UInt64 endPos = (UInt64)(globalOffset + (Int64)PhySize); 1311 UInt64 endPos = (UInt64)(globalOffset + (Int64)PhySize);
1283 if (endPos < FileSize) 1312 if (endPos < FileSize)
@@ -1378,9 +1407,9 @@ static HRESULT ReadParseItemProps(IInArchive *archive, const CArcInfoEx &ai, NAr
1378 pi.FileTime_Defined = false; 1407 pi.FileTime_Defined = false;
1379 pi.ArcType = ai.Name; 1408 pi.ArcType = ai.Name;
1380 1409
1381 RINOK(Archive_GetArcBoolProp(archive, kpidIsNotArcType, pi.IsNotArcType)); 1410 RINOK(Archive_GetArcProp_Bool(archive, kpidIsNotArcType, pi.IsNotArcType));
1382 1411
1383 // RINOK(Archive_GetArcBoolProp(archive, kpidIsSelfExe, pi.IsSelfExe)); 1412 // RINOK(Archive_GetArcProp_Bool(archive, kpidIsSelfExe, pi.IsSelfExe));
1384 pi.IsSelfExe = ai.Flags_PreArc(); 1413 pi.IsSelfExe = ai.Flags_PreArc();
1385 1414
1386 { 1415 {
@@ -1584,7 +1613,7 @@ static HRESULT OpenArchiveSpec(IInArchive *archive, bool needPhySize,
1584 return S_OK; 1613 return S_OK;
1585 1614
1586 bool phySizeCantBeDetected = false; 1615 bool phySizeCantBeDetected = false;
1587 RINOK(Archive_GetArcBoolProp(archive, kpidPhySizeCantBeDetected, phySizeCantBeDetected)); 1616 RINOK(Archive_GetArcProp_Bool(archive, kpidPhySizeCantBeDetected, phySizeCantBeDetected));
1588 1617
1589 if (!phySizeCantBeDetected) 1618 if (!phySizeCantBeDetected)
1590 { 1619 {
@@ -1724,7 +1753,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
1724 const CArcInfoEx &ai = op.codecs->Formats[i]; 1753 const CArcInfoEx &ai = op.codecs->Formats[i];
1725 1754
1726 if (IgnoreSplit || !op.openType.CanReturnArc) 1755 if (IgnoreSplit || !op.openType.CanReturnArc)
1727 if (ai.IsSplit()) 1756 if (ai.Is_Split())
1728 continue; 1757 continue;
1729 if (op.excludedFormats->FindInSorted((int)i) >= 0) 1758 if (op.excludedFormats->FindInSorted((int)i) >= 0)
1730 continue; 1759 continue;
@@ -1736,8 +1765,8 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
1736 1765
1737 if (ai.FindExtension(extension) >= 0 1766 if (ai.FindExtension(extension) >= 0
1738 #ifndef _SFX 1767 #ifndef _SFX
1739 || (isZip && StringsAreEqualNoCase_Ascii(ai.Name, "zip")) 1768 || (isZip && ai.Is_Zip())
1740 || (isRar && StringsAreEqualNoCase_Ascii(ai.Name, "rar")) 1769 || (isRar && ai.Is_Rar())
1741 #endif 1770 #endif
1742 ) 1771 )
1743 { 1772 {
@@ -1811,11 +1840,27 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
1811 1840
1812 /* 1841 /*
1813 check type order: 1842 check type order:
1814 1) matched extension, no signuature 1843 0) matched_extension && Backward
1815 2) matched extension, matched signuature 1844 1) matched_extension && (no_signuature || SignatureOffset != 0)
1845 2) matched_extension && (matched_signature)
1816 // 3) no signuature 1846 // 3) no signuature
1817 // 4) matched signuature 1847 // 4) matched signuature
1818 */ 1848 */
1849 // we move index from orderIndices to orderIndices2 for priority handlers.
1850
1851 for (unsigned i = 0; i < numFinded; i++)
1852 {
1853 const int index = orderIndices[i];
1854 if (index < 0)
1855 continue;
1856 const CArcInfoEx &ai = op.codecs->Formats[(unsigned)index];
1857 if (ai.Flags_BackwardOpen())
1858 {
1859 // backward doesn't need start signatures
1860 orderIndices2.Add(index);
1861 orderIndices[i] = -1;
1862 }
1863 }
1819 1864
1820 MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, NULL, 0); 1865 MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, NULL, 0);
1821 MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, byteBuffer, processedSize); 1866 MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, byteBuffer, processedSize);
@@ -1906,6 +1951,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
1906 // OutputDebugStringW(ai.Name); 1951 // OutputDebugStringW(ai.Name);
1907 if (i >= numMainTypes) 1952 if (i >= numMainTypes)
1908 { 1953 {
1954 // here we allow mismatched extension only for backward handlers
1909 if (!ai.Flags_BackwardOpen() 1955 if (!ai.Flags_BackwardOpen()
1910 // && !ai.Flags_PureStartOpen() 1956 // && !ai.Flags_PureStartOpen()
1911 ) 1957 )
@@ -2125,7 +2171,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
2125 2171
2126 const CArcInfoEx &ai = op.codecs->Formats[form]; 2172 const CArcInfoEx &ai = op.codecs->Formats[form];
2127 2173
2128 if (ai.IsSplit()) 2174 if (ai.Is_Split())
2129 { 2175 {
2130 splitIndex = (int)form; 2176 splitIndex = (int)form;
2131 continue; 2177 continue;
@@ -2234,7 +2280,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
2234 2280
2235 // bool needScan = false; 2281 // bool needScan = false;
2236 2282
2237 if (!PhySizeDefined) 2283 if (!PhySize_Defined)
2238 { 2284 {
2239 // it's for Z format 2285 // it's for Z format
2240 pi.LenIsUnknown = true; 2286 pi.LenIsUnknown = true;
@@ -2726,14 +2772,14 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
2726 } 2772 }
2727 continue; 2773 continue;
2728 } 2774 }
2729 if (!ErrorInfo.IsArc_After_NonOpen() || !PhySizeDefined || PhySize == 0) 2775 if (!ErrorInfo.IsArc_After_NonOpen() || !PhySize_Defined || PhySize == 0)
2730 continue; 2776 continue;
2731 } 2777 }
2732 else 2778 else
2733 { 2779 {
2734 if (PhySizeDefined && PhySize == 0) 2780 if (PhySize_Defined && PhySize == 0)
2735 { 2781 {
2736 PRF(printf(" phySizeDefined && PhySize == 0 ")); 2782 PRF(printf(" phySize_Defined && PhySize == 0 "));
2737 // we skip that epmty archive case with unusual unexpected (PhySize == 0) from Code function. 2783 // we skip that epmty archive case with unusual unexpected (PhySize == 0) from Code function.
2738 continue; 2784 continue;
2739 } 2785 }
@@ -2754,10 +2800,10 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
2754 else if (Offset != 0) 2800 else if (Offset != 0)
2755 return E_FAIL; 2801 return E_FAIL;
2756 2802
2757 UInt64 arcRem = FileSize - pi.Offset; 2803 const UInt64 arcRem = FileSize - pi.Offset;
2758 UInt64 phySize = arcRem; 2804 UInt64 phySize = arcRem;
2759 bool phySizeDefined = PhySizeDefined; 2805 const bool phySize_Defined = PhySize_Defined;
2760 if (phySizeDefined) 2806 if (phySize_Defined)
2761 { 2807 {
2762 if (pi.Offset + PhySize > FileSize) 2808 if (pi.Offset + PhySize > FileSize)
2763 { 2809 {
@@ -2783,7 +2829,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
2783 bool needScan = false; 2829 bool needScan = false;
2784 2830
2785 2831
2786 if (isOpen && !phySizeDefined) 2832 if (isOpen && !phySize_Defined)
2787 { 2833 {
2788 // it's for Z format, or bzip2,gz,xz with phySize that was not detected 2834 // it's for Z format, or bzip2,gz,xz with phySize that was not detected
2789 pi.LenIsUnknown = true; 2835 pi.LenIsUnknown = true;
@@ -2802,7 +2848,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
2802 2848
2803 /* 2849 /*
2804 if (needSkipFullArc) 2850 if (needSkipFullArc)
2805 if (pi.Offset == 0 && phySizeDefined && pi.Size >= fileSize) 2851 if (pi.Offset == 0 && phySize_Defined && pi.Size >= fileSize)
2806 continue; 2852 continue;
2807 */ 2853 */
2808 if (pi.Offset == 0 && !pi.LenIsUnknown && pi.Size >= FileSize) 2854 if (pi.Offset == 0 && !pi.LenIsUnknown && pi.Size >= FileSize)
@@ -2830,7 +2876,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
2830 2876
2831 RINOK(ReadParseItemProps(archive, ai, pi)); 2877 RINOK(ReadParseItemProps(archive, ai, pi));
2832 2878
2833 if (pi.Offset < startArcPos && !mode.EachPos /* && phySizeDefined */) 2879 if (pi.Offset < startArcPos && !mode.EachPos /* && phySize_Defined */)
2834 { 2880 {
2835 /* It's for DMG format. 2881 /* It's for DMG format.
2836 This code deletes all previous items that are included to current item */ 2882 This code deletes all previous items that are included to current item */
@@ -2849,7 +2895,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
2849 } 2895 }
2850 2896
2851 2897
2852 if (isOpen && mode.CanReturnArc && phySizeDefined) 2898 if (isOpen && mode.CanReturnArc && phySize_Defined)
2853 { 2899 {
2854 // if (pi.Offset + pi.Size >= fileSize) 2900 // if (pi.Offset + pi.Size >= fileSize)
2855 bool openCur = false; 2901 bool openCur = false;
@@ -2993,12 +3039,12 @@ HRESULT CArc::OpenStream(const COpenOptions &op)
2993 Archive->QueryInterface(IID_IArchiveGetRawProps, (void **)&GetRawProps); 3039 Archive->QueryInterface(IID_IArchiveGetRawProps, (void **)&GetRawProps);
2994 Archive->QueryInterface(IID_IArchiveGetRootProps, (void **)&GetRootProps); 3040 Archive->QueryInterface(IID_IArchiveGetRootProps, (void **)&GetRootProps);
2995 3041
2996 RINOK(Archive_GetArcBoolProp(Archive, kpidIsTree, IsTree)); 3042 RINOK(Archive_GetArcProp_Bool(Archive, kpidIsTree, IsTree));
2997 RINOK(Archive_GetArcBoolProp(Archive, kpidIsDeleted, Ask_Deleted)); 3043 RINOK(Archive_GetArcProp_Bool(Archive, kpidIsDeleted, Ask_Deleted));
2998 RINOK(Archive_GetArcBoolProp(Archive, kpidIsAltStream, Ask_AltStream)); 3044 RINOK(Archive_GetArcProp_Bool(Archive, kpidIsAltStream, Ask_AltStream));
2999 RINOK(Archive_GetArcBoolProp(Archive, kpidIsAux, Ask_Aux)); 3045 RINOK(Archive_GetArcProp_Bool(Archive, kpidIsAux, Ask_Aux));
3000 RINOK(Archive_GetArcBoolProp(Archive, kpidINode, Ask_INode)); 3046 RINOK(Archive_GetArcProp_Bool(Archive, kpidINode, Ask_INode));
3001 RINOK(Archive_GetArcBoolProp(Archive, kpidReadOnly, IsReadOnly)); 3047 RINOK(Archive_GetArcProp_Bool(Archive, kpidReadOnly, IsReadOnly));
3002 3048
3003 const UString fileName = ExtractFileNameFromPath(Path); 3049 const UString fileName = ExtractFileNameFromPath(Path);
3004 UString extension; 3050 UString extension;
@@ -3092,7 +3138,7 @@ HRESULT CArc::OpenStreamOrFile(COpenOptions &op)
3092 FOR_VECTOR (i, op.codecs->Formats) 3138 FOR_VECTOR (i, op.codecs->Formats)
3093 { 3139 {
3094 const CArcInfoEx &ai = op.codecs->Formats[i]; 3140 const CArcInfoEx &ai = op.codecs->Formats[i];
3095 if (ai.IsSplit()) 3141 if (ai.Is_Split())
3096 continue; 3142 continue;
3097 UString path3 = path2; 3143 UString path3 = path2;
3098 path3 += '.'; 3144 path3 += '.';
@@ -3299,7 +3345,7 @@ HRESULT CArchiveLink::Open(COpenOptions &op)
3299 break; 3345 break;
3300 3346
3301 CArc arc2; 3347 CArc arc2;
3302 RINOK(arc.GetItemPath(mainSubfile, arc2.Path)); 3348 RINOK(arc.GetItem_Path(mainSubfile, arc2.Path));
3303 3349
3304 bool zerosTailIsAllowed; 3350 bool zerosTailIsAllowed;
3305 RINOK(Archive_GetItemBoolProp(arc.Archive, mainSubfile, kpidZerosTailIsAllowed, zerosTailIsAllowed)); 3351 RINOK(Archive_GetItemBoolProp(arc.Archive, mainSubfile, kpidZerosTailIsAllowed, zerosTailIsAllowed));
@@ -3343,7 +3389,7 @@ HRESULT CArchiveLink::Open(COpenOptions &op)
3343 break; 3389 break;
3344 } 3390 }
3345 RINOK(result); 3391 RINOK(result);
3346 RINOK(arc.GetItemMTime(mainSubfile, arc2.MTime, arc2.MTimeDefined)); 3392 RINOK(arc.GetItem_MTime(mainSubfile, arc2.MTime));
3347 Arcs.Add(arc2); 3393 Arcs.Add(arc2);
3348 } 3394 }
3349 IsOpen = !Arcs.IsEmpty(); 3395 IsOpen = !Arcs.IsEmpty();
diff --git a/CPP/7zip/UI/Common/OpenArchive.h b/CPP/7zip/UI/Common/OpenArchive.h
index 4e1192c..e3220b9 100644
--- a/CPP/7zip/UI/Common/OpenArchive.h
+++ b/CPP/7zip/UI/Common/OpenArchive.h
@@ -8,6 +8,7 @@
8#include "ArchiveOpenCallback.h" 8#include "ArchiveOpenCallback.h"
9#include "LoadCodecs.h" 9#include "LoadCodecs.h"
10#include "Property.h" 10#include "Property.h"
11#include "DirItem.h"
11 12
12#ifndef _SFX 13#ifndef _SFX
13 14
@@ -260,6 +261,9 @@ struct CReadArcItem
260 } 261 }
261}; 262};
262 263
264
265
266
263class CArc 267class CArc
264{ 268{
265 HRESULT PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive); 269 HRESULT PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive);
@@ -268,7 +272,7 @@ class CArc
268 272
269 #ifndef _SFX 273 #ifndef _SFX
270 // parts.Back() can contain alt stream name "nams:AltName" 274 // parts.Back() can contain alt stream name "nams:AltName"
271 HRESULT GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const; 275 HRESULT GetItem_PathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const;
272 #endif 276 #endif
273 277
274public: 278public:
@@ -289,19 +293,21 @@ public:
289 UString DefaultName; 293 UString DefaultName;
290 int FormatIndex; // -1 means Parser 294 int FormatIndex; // -1 means Parser
291 UInt32 SubfileIndex; // (UInt32)(Int32)-1; means no subfile 295 UInt32 SubfileIndex; // (UInt32)(Int32)-1; means no subfile
292 FILETIME MTime; 296
293 bool MTimeDefined; 297 // CFiTime MTime;
298 // bool MTime_Defined;
299 CArcTime MTime;
294 300
295 Int64 Offset; // it's offset of start of archive inside stream that is open by Archive Handler 301 Int64 Offset; // it's offset of start of archive inside stream that is open by Archive Handler
296 UInt64 PhySize; 302 UInt64 PhySize;
297 // UInt64 OkPhySize; 303 // UInt64 OkPhySize;
298 bool PhySizeDefined; 304 bool PhySize_Defined;
299 // bool OkPhySize_Defined; 305 // bool OkPhySize_Defined;
300 UInt64 FileSize; 306 UInt64 FileSize;
301 UInt64 AvailPhySize; // PhySize, but it's reduced if exceed end of file 307 UInt64 AvailPhySize; // PhySize, but it's reduced if exceed end of file
302 // bool offsetDefined; 308 // bool offsetDefined;
303 309
304 UInt64 GetEstmatedPhySize() const { return PhySizeDefined ? PhySize : FileSize; } 310 UInt64 GetEstmatedPhySize() const { return PhySize_Defined ? PhySize : FileSize; }
305 311
306 UInt64 ArcStreamOffset; // offset of stream that is open by Archive Handler 312 UInt64 ArcStreamOffset; // offset of stream that is open by Archive Handler
307 Int64 GetGlobalOffset() const { return (Int64)ArcStreamOffset + Offset; } // it's global offset of archive 313 Int64 GetGlobalOffset() const { return (Int64)ArcStreamOffset + Offset; } // it's global offset of archive
@@ -323,7 +329,7 @@ public:
323 // void Set_ErrorFlagsText(); 329 // void Set_ErrorFlagsText();
324 330
325 CArc(): 331 CArc():
326 MTimeDefined(false), 332 // MTime_Defined(false),
327 IsTree(false), 333 IsTree(false),
328 IsReadOnly(false), 334 IsReadOnly(false),
329 Ask_Deleted(false), 335 Ask_Deleted(false),
@@ -343,17 +349,29 @@ public:
343 return Archive->Close(); 349 return Archive->Close();
344 } 350 }
345 351
346 HRESULT GetItemPath(UInt32 index, UString &result) const; 352 HRESULT GetItem_Path(UInt32 index, UString &result) const;
347 HRESULT GetDefaultItemPath(UInt32 index, UString &result) const; 353 HRESULT GetItem_DefaultPath(UInt32 index, UString &result) const;
348 354
349 // GetItemPath2 adds [DELETED] dir prefix for deleted items. 355 // GetItemPath2 adds [DELETED] dir prefix for deleted items.
350 HRESULT GetItemPath2(UInt32 index, UString &result) const; 356 HRESULT GetItem_Path2(UInt32 index, UString &result) const;
351 357
352 HRESULT GetItem(UInt32 index, CReadArcItem &item) const; 358 HRESULT GetItem(UInt32 index, CReadArcItem &item) const;
353 359
354 HRESULT GetItemSize(UInt32 index, UInt64 &size, bool &defined) const; 360 HRESULT GetItem_Size(UInt32 index, UInt64 &size, bool &defined) const;
355 HRESULT GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const; 361
356 HRESULT IsItemAnti(UInt32 index, bool &result) const 362 /* if (GetProperty() returns vt==VT_EMPTY), this function sets
363 timestamp from archive file timestamp (MTime).
364 So (at) will be set in most cases (at.Def == true)
365 if (at.Prec == 0)
366 {
367 it means that (Prec == 0) was returned for (kpidMTime),
368 and no value was returned for (kpidTimeType).
369 it can mean Windows precision or unknown precision.
370 }
371 */
372 HRESULT GetItem_MTime(UInt32 index, CArcTime &at) const;
373
374 HRESULT IsItem_Anti(UInt32 index, bool &result) const
357 { return Archive_GetItemBoolProp(Archive, index, kpidIsAnti, result); } 375 { return Archive_GetItemBoolProp(Archive, index, kpidIsAnti, result); }
358 376
359 377
diff --git a/CPP/7zip/UI/Common/PropIDUtils.cpp b/CPP/7zip/UI/Common/PropIDUtils.cpp
index 30efd53..72384b3 100644
--- a/CPP/7zip/UI/Common/PropIDUtils.cpp
+++ b/CPP/7zip/UI/Common/PropIDUtils.cpp
@@ -136,10 +136,37 @@ void ConvertPropertyToShortString2(char *dest, const PROPVARIANT &prop, PROPID p
136 if (prop.vt == VT_FILETIME) 136 if (prop.vt == VT_FILETIME)
137 { 137 {
138 const FILETIME &ft = prop.filetime; 138 const FILETIME &ft = prop.filetime;
139 if ((ft.dwHighDateTime == 0 && 139 unsigned ns100 = 0;
140 ft.dwLowDateTime == 0)) 140 int numDigits = kTimestampPrintLevel_NTFS;
141 const unsigned prec = prop.wReserved1;
142 const unsigned ns100_Temp = prop.wReserved2;
143 if (prec != 0
144 && prec <= k_PropVar_TimePrec_1ns
145 && ns100_Temp < 100
146 && prop.wReserved3 == 0)
147 {
148 ns100 = ns100_Temp;
149 if (prec == k_PropVar_TimePrec_Unix ||
150 prec == k_PropVar_TimePrec_DOS)
151 numDigits = 0;
152 else if (prec == k_PropVar_TimePrec_HighPrec)
153 numDigits = 9;
154 else
155 {
156 numDigits = (int)prec - (int)k_PropVar_TimePrec_Base;
157 if (
158 // numDigits < kTimestampPrintLevel_DAY // for debuf
159 numDigits < kTimestampPrintLevel_SEC
160 )
161
162 numDigits = kTimestampPrintLevel_NTFS;
163 }
164 }
165 if (ft.dwHighDateTime == 0 && ft.dwLowDateTime == 0 && ns100 == 0)
141 return; 166 return;
142 ConvertUtcFileTimeToString(prop.filetime, dest, level); 167 if (level > numDigits)
168 level = numDigits;
169 ConvertUtcFileTimeToString2(ft, ns100, dest, level);
143 return; 170 return;
144 } 171 }
145 172
@@ -198,6 +225,24 @@ void ConvertPropertyToShortString2(char *dest, const PROPVARIANT &prop, PROPID p
198 ConvertUInt64ToHex(v, dest + 2); 225 ConvertUInt64ToHex(v, dest + 2);
199 return; 226 return;
200 } 227 }
228
229 /*
230 case kpidDevice:
231 {
232 UInt64 v = 0;
233 if (prop.vt == VT_UI4)
234 v = prop.ulVal;
235 else if (prop.vt == VT_UI8)
236 v = (UInt64)prop.uhVal.QuadPart;
237 else
238 break;
239 ConvertUInt32ToString(MY_dev_major(v), dest);
240 dest += strlen(dest);
241 *dest++ = ',';
242 ConvertUInt32ToString(MY_dev_minor(v), dest);
243 return;
244 }
245 */
201 } 246 }
202 247
203 ConvertPropVariantToShortString(prop, dest); 248 ConvertPropVariantToShortString(prop, dest);
diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp
index 032a876..042991d 100644
--- a/CPP/7zip/UI/Common/Update.cpp
+++ b/CPP/7zip/UI/Common/Update.cpp
@@ -2,6 +2,8 @@
2 2
3#include "StdAfx.h" 3#include "StdAfx.h"
4 4
5// #include <stdio.h>
6
5#include "Update.h" 7#include "Update.h"
6 8
7#include "../../../Common/StringConvert.h" 9#include "../../../Common/StringConvert.h"
@@ -101,7 +103,7 @@ public:
101 _length = 0; 103 _length = 0;
102 } 104 }
103 105
104 bool SetMTime(const FILETIME *mTime); 106 bool SetMTime(const CFiTime *mTime);
105 HRESULT Close(); 107 HRESULT Close();
106 108
107 UInt64 GetSize() const { return _length; } 109 UInt64 GetSize() const { return _length; }
@@ -131,7 +133,7 @@ HRESULT COutMultiVolStream::Close()
131 return res; 133 return res;
132} 134}
133 135
134bool COutMultiVolStream::SetMTime(const FILETIME *mTime) 136bool COutMultiVolStream::SetMTime(const CFiTime *mTime)
135{ 137{
136 bool res = true; 138 bool res = true;
137 FOR_VECTOR (i, Streams) 139 FOR_VECTOR (i, Streams)
@@ -545,11 +547,46 @@ static HRESULT Compress(
545 if (!outArchive) 547 if (!outArchive)
546 throw kUpdateIsNotSupoorted; 548 throw kUpdateIsNotSupoorted;
547 549
550 // we need to set properties to get fileTimeType.
551 RINOK(SetProperties(outArchive, options.MethodMode.Properties));
552
548 NFileTimeType::EEnum fileTimeType; 553 NFileTimeType::EEnum fileTimeType;
549 { 554 {
555 /*
556 how we compare file_in_archive::MTime with dirItem.MTime
557 for GetUpdatePairInfoList():
558
559 if (kpidMTime is not defined), external MTime of archive is used.
560
561 before 22.00:
562 if (kpidTimeType is defined)
563 {
564 kpidTimeType is used as precision.
565 (kpidTimeType > kDOS) is not allowed.
566 }
567 else GetFileTimeType() value is used as precision.
568
569 22.00:
570 if (kpidMTime is defined)
571 {
572 if (kpidMTime::precision != 0), then kpidMTime::precision is used as precision.
573 else
574 {
575 if (kpidTimeType is defined), kpidTimeType is used as precision.
576 else GetFileTimeType() value is used as precision.
577 }
578 }
579 else external MTime of archive is used as precision.
580 */
581
550 UInt32 value; 582 UInt32 value;
551 RINOK(outArchive->GetFileTimeType(&value)); 583 RINOK(outArchive->GetFileTimeType(&value));
584
585 // we support any future fileType here.
586 fileTimeType = (NFileTimeType::EEnum)value;
552 587
588 /*
589 old 21.07 code:
553 switch (value) 590 switch (value)
554 { 591 {
555 case NFileTimeType::kWindows: 592 case NFileTimeType::kWindows:
@@ -560,13 +597,26 @@ static HRESULT Compress(
560 default: 597 default:
561 return E_FAIL; 598 return E_FAIL;
562 } 599 }
600 */
563 } 601 }
564 602
603 // bool noTimestampExpected = false;
565 { 604 {
566 const CArcInfoEx &arcInfo = codecs->Formats[(unsigned)formatIndex]; 605 const CArcInfoEx &arcInfo = codecs->Formats[(unsigned)formatIndex];
606
607 // if (arcInfo.Flags_KeepName()) noTimestampExpected = true;
608 if (arcInfo.Is_Xz() ||
609 arcInfo.Is_BZip2())
610 {
611 /* 7-zip before 22.00 returns NFileTimeType::kUnix for xz and bzip2,
612 but we want to set timestamp without reduction to unix. */
613 // noTimestampExpected = true;
614 fileTimeType = NFileTimeType::kNotDefined; // it means not defined
615 }
616
567 if (options.AltStreams.Val && !arcInfo.Flags_AltStreams()) 617 if (options.AltStreams.Val && !arcInfo.Flags_AltStreams())
568 return E_NOTIMPL; 618 return E_NOTIMPL;
569 if (options.NtSecurity.Val && !arcInfo.Flags_NtSecure()) 619 if (options.NtSecurity.Val && !arcInfo.Flags_NtSecurity())
570 return E_NOTIMPL; 620 return E_NOTIMPL;
571 if (options.DeleteAfterCompressing && arcInfo.Flags_HashHandler()) 621 if (options.DeleteAfterCompressing && arcInfo.Flags_HashHandler())
572 return E_NOTIMPL; 622 return E_NOTIMPL;
@@ -626,7 +676,7 @@ static HRESULT Compress(
626 if (needRename) 676 if (needRename)
627 { 677 {
628 up2.NewProps = true; 678 up2.NewProps = true;
629 RINOK(arc->IsItemAnti(i, up2.IsAnti)); 679 RINOK(arc->IsItem_Anti(i, up2.IsAnti));
630 up2.NewNameIndex = (int)newNames.Add(dest); 680 up2.NewNameIndex = (int)newNames.Add(dest);
631 } 681 }
632 updatePairs2.Add(up2); 682 updatePairs2.Add(up2);
@@ -661,6 +711,7 @@ static HRESULT Compress(
661 else 711 else
662 stat.NumDirs++; 712 stat.NumDirs++;
663 } 713 }
714 #ifdef _WIN32
664 else if (di.IsAltStream) 715 else if (di.IsAltStream)
665 { 716 {
666 if (up.IsAnti) 717 if (up.IsAnti)
@@ -671,6 +722,7 @@ static HRESULT Compress(
671 stat.AltStreamsSize += di.Size; 722 stat.AltStreamsSize += di.Size;
672 } 723 }
673 } 724 }
725 #endif
674 else 726 else
675 { 727 {
676 if (up.IsAnti) 728 if (up.IsAnti)
@@ -740,6 +792,8 @@ static HRESULT Compress(
740 updateCallbackSpec->StoreNtSecurity = options.NtSecurity.Val; 792 updateCallbackSpec->StoreNtSecurity = options.NtSecurity.Val;
741 updateCallbackSpec->StoreHardLinks = options.HardLinks.Val; 793 updateCallbackSpec->StoreHardLinks = options.HardLinks.Val;
742 updateCallbackSpec->StoreSymLinks = options.SymLinks.Val; 794 updateCallbackSpec->StoreSymLinks = options.SymLinks.Val;
795 updateCallbackSpec->StoreOwnerName = options.StoreOwnerName.Val;
796 updateCallbackSpec->StoreOwnerId = options.StoreOwnerId.Val;
743 797
744 updateCallbackSpec->Arc = arc; 798 updateCallbackSpec->Arc = arc;
745 updateCallbackSpec->ArcItems = &arcItems; 799 updateCallbackSpec->ArcItems = &arcItems;
@@ -755,6 +809,12 @@ static HRESULT Compress(
755 if (options.RenamePairs.Size() != 0) 809 if (options.RenamePairs.Size() != 0)
756 updateCallbackSpec->NewNames = &newNames; 810 updateCallbackSpec->NewNames = &newNames;
757 811
812 if (options.SetArcMTime)
813 {
814 // updateCallbackSpec->Need_ArcMTime_Report = true;
815 updateCallbackSpec->Need_LatestMTime = true;
816 }
817
758 CMyComPtr<IOutStream> outSeekStream; 818 CMyComPtr<IOutStream> outSeekStream;
759 CMyComPtr<ISequentialOutStream> outStream; 819 CMyComPtr<ISequentialOutStream> outStream;
760 820
@@ -838,8 +898,6 @@ static HRESULT Compress(
838 */ 898 */
839 } 899 }
840 900
841 RINOK(SetProperties(outArchive, options.MethodMode.Properties));
842
843 if (options.SfxMode) 901 if (options.SfxMode)
844 { 902 {
845 CInFileStream *sfxStreamSpec = new CInFileStream; 903 CInFileStream *sfxStreamSpec = new CInFileStream;
@@ -909,24 +967,71 @@ static HRESULT Compress(
909 967
910 if (options.SetArcMTime) 968 if (options.SetArcMTime)
911 { 969 {
912 FILETIME ft; 970 CFiTime ft;
913 ft.dwLowDateTime = 0; 971 FiTime_Clear(ft);
914 ft.dwHighDateTime = 0; 972 bool isDefined = false;
915 FOR_VECTOR (i, updatePairs2) 973
974 // bool needNormalizeAfterStream;
975 // needParse;
976 /*
977 if (updateCallbackSpec->ArcMTime_WasReported)
916 { 978 {
917 const CUpdatePair2 &pair2 = updatePairs2[i]; 979 isDefined = updateCallbackSpec->Reported_ArcMTime.Def;
918 const FILETIME *ft2 = NULL; 980 if (isDefined)
919 if (pair2.NewProps && pair2.DirIndex >= 0) 981 updateCallbackSpec->Reported_ArcMTime.Write_To_FiTime(ft);
920 ft2 = &dirItems.Items[(unsigned)pair2.DirIndex].MTime; 982 else
921 else if (pair2.UseArcProps && pair2.ArcIndex >= 0) 983 fileTimeType = NFileTimeType::kNotDefined;
922 ft2 = &arcItems[(unsigned)pair2.ArcIndex].MTime; 984 }
923 if (ft2) 985 if (!isDefined)
986 */
987 {
988 if (updateCallbackSpec->LatestMTime_Defined)
924 { 989 {
925 if (::CompareFileTime(&ft, ft2) < 0) 990 // CArcTime at = StreamCallback_ArcMTime;
926 ft = *ft2; 991 // updateCallbackSpec->StreamCallback_ArcMTime.Write_To_FiTime(ft);
992 // we must normalize with precision from archive;
993 ft = updateCallbackSpec->LatestMTime;
994 isDefined = true;
927 } 995 }
996
997 FOR_VECTOR (i, updatePairs2)
998 {
999 const CUpdatePair2 &pair2 = updatePairs2[i];
1000 CFiTime ft2;
1001 bool ft2_Defined = false;
1002 /* we use full precision of dirItem, if dirItem is defined
1003 and (dirItem will be used or dirItem is sameTime in dir and arc */
1004 if (pair2.DirIndex >= 0 &&
1005 (pair2.NewProps || pair2.IsSameTime))
1006 {
1007 ft2 = dirItems.Items[(unsigned)pair2.DirIndex].MTime;
1008 ft2_Defined = true;
1009 }
1010 else if (pair2.UseArcProps && pair2.ArcIndex >= 0)
1011 {
1012 const CArcItem &arcItem = arcItems[(unsigned)pair2.ArcIndex];
1013 if (arcItem.MTime.Def)
1014 {
1015 arcItem.MTime.Write_To_FiTime(ft2);
1016 ft2_Defined = true;
1017 }
1018 }
1019 if (ft2_Defined)
1020 {
1021 if (Compare_FiTime(&ft, &ft2) < 0)
1022 {
1023 ft = ft2;
1024 isDefined = true;
1025 }
1026 }
1027 }
1028 /*
1029 if (fileTimeType != NFileTimeType::kNotDefined)
1030 FiTime_Normalize_With_Prec(ft, fileTimeType);
1031 */
928 } 1032 }
929 if (ft.dwLowDateTime != 0 || ft.dwHighDateTime != 0) 1033 // if (ft.dwLowDateTime != 0 || ft.dwHighDateTime != 0)
1034 if (isDefined)
930 { 1035 {
931 if (outStreamSpec) 1036 if (outStreamSpec)
932 outStreamSpec->SetMTime(&ft); 1037 outStreamSpec->SetMTime(&ft);
@@ -1046,26 +1151,9 @@ static HRESULT EnumerateInArchiveItems(
1046 else 1151 else
1047 ai.Censored = Censor_CheckPath(censor, item); 1152 ai.Censored = Censor_CheckPath(censor, item);
1048 1153
1049 RINOK(arc.GetItemMTime(i, ai.MTime, ai.MTimeDefined)); 1154 // ai.MTime will be set to archive MTime, if not present in archive item
1050 RINOK(arc.GetItemSize(i, ai.Size, ai.SizeDefined)); 1155 RINOK(arc.GetItem_MTime(i, ai.MTime));
1051 1156 RINOK(arc.GetItem_Size(i, ai.Size, ai.Size_Defined));
1052 {
1053 CPropVariant prop;
1054 RINOK(archive->GetProperty(i, kpidTimeType, &prop));
1055 if (prop.vt == VT_UI4)
1056 {
1057 ai.TimeType = (int)(NFileTimeType::EEnum)prop.ulVal;
1058 switch (ai.TimeType)
1059 {
1060 case NFileTimeType::kWindows:
1061 case NFileTimeType::kUnix:
1062 case NFileTimeType::kDOS:
1063 break;
1064 default:
1065 return E_FAIL;
1066 }
1067 }
1068 }
1069 1157
1070 ai.IndexInServer = i; 1158 ai.IndexInServer = i;
1071 arcItems.AddInReserved(ai); 1159 arcItems.AddInReserved(ai);
@@ -1198,8 +1286,10 @@ HRESULT UpdateArchive(
1198 EISDIR 1286 EISDIR
1199 #endif 1287 #endif
1200 ); 1288 );
1289 #ifdef _WIN32
1201 if (fi.IsDevice) 1290 if (fi.IsDevice)
1202 return E_NOTIMPL; 1291 return E_NOTIMPL;
1292 #endif
1203 1293
1204 if (!options.StdOutMode && options.UpdateArchiveItself) 1294 if (!options.StdOutMode && options.UpdateArchiveItself)
1205 if (fi.IsReadOnly()) 1295 if (fi.IsReadOnly())
@@ -1262,8 +1352,14 @@ HRESULT UpdateArchive(
1262 } 1352 }
1263 1353
1264 CArc &arc = arcLink.Arcs.Back(); 1354 CArc &arc = arcLink.Arcs.Back();
1265 arc.MTimeDefined = !fi.IsDevice; 1355 arc.MTime.Def =
1266 arc.MTime = fi.MTime; 1356 #ifdef _WIN32
1357 !fi.IsDevice;
1358 #else
1359 true;
1360 #endif
1361 if (arc.MTime.Def)
1362 arc.MTime.Set_From_FiTime(fi.MTime);
1267 1363
1268 if (arc.ErrorInfo.ThereIsTail) 1364 if (arc.ErrorInfo.ThereIsTail)
1269 { 1365 {
@@ -1307,10 +1403,11 @@ HRESULT UpdateArchive(
1307 if (options.StdInMode) 1403 if (options.StdInMode)
1308 { 1404 {
1309 CDirItem di; 1405 CDirItem di;
1406 di.ClearBase();
1310 di.Name = options.StdInFileName; 1407 di.Name = options.StdInFileName;
1311 di.Size = (UInt64)(Int64)-1; 1408 di.Size = (UInt64)(Int64)-1;
1312 di.Attrib = 0; 1409 di.SetAsFile();
1313 NTime::GetCurUtcFileTime(di.MTime); 1410 NTime::GetCurUtc_FiTime(di.MTime);
1314 di.CTime = di.ATime = di.MTime; 1411 di.CTime = di.ATime = di.MTime;
1315 dirItems.Items.Add(di); 1412 dirItems.Items.Add(di);
1316 } 1413 }
@@ -1336,8 +1433,14 @@ HRESULT UpdateArchive(
1336 dirItems.ScanAltStreams = options.AltStreams.Val; 1433 dirItems.ScanAltStreams = options.AltStreams.Val;
1337 dirItems.ExcludeDirItems = censor.ExcludeDirItems; 1434 dirItems.ExcludeDirItems = censor.ExcludeDirItems;
1338 dirItems.ExcludeFileItems = censor.ExcludeFileItems; 1435 dirItems.ExcludeFileItems = censor.ExcludeFileItems;
1436
1437 dirItems.ShareForWrite = options.OpenShareForWrite;
1438
1439 #ifndef _WIN32
1440 dirItems.StoreOwnerName = options.StoreOwnerName.Val;
1441 #endif
1339 1442
1340 HRESULT res = EnumerateItems(censor, 1443 const HRESULT res = EnumerateItems(censor,
1341 options.PathMode, 1444 options.PathMode,
1342 UString(), // options.AddPathPrefix, 1445 UString(), // options.AddPathPrefix,
1343 dirItems); 1446 dirItems);
@@ -1351,6 +1454,8 @@ HRESULT UpdateArchive(
1351 1454
1352 RINOK(callback->FinishScanning(dirItems.Stat)); 1455 RINOK(callback->FinishScanning(dirItems.Stat));
1353 1456
1457 // 22.00: we don't need parent folder, if absolute path mode
1458 if (options.PathMode != NWildcard::k_AbsPath)
1354 if (censor.Pairs.Size() == 1) 1459 if (censor.Pairs.Size() == 1)
1355 { 1460 {
1356 NFind::CFileInfo fi; 1461 NFind::CFileInfo fi;
@@ -1366,11 +1471,7 @@ HRESULT UpdateArchive(
1366 if (fi.Find(prefix)) 1471 if (fi.Find(prefix))
1367 if (fi.IsDir()) 1472 if (fi.IsDir())
1368 { 1473 {
1369 parentDirItem.Size = fi.Size; 1474 parentDirItem.Copy_From_FileInfoBase(fi);
1370 parentDirItem.CTime = fi.CTime;
1371 parentDirItem.ATime = fi.ATime;
1372 parentDirItem.MTime = fi.MTime;
1373 parentDirItem.Attrib = fi.Attrib;
1374 parentDirItem_Ptr = &parentDirItem; 1475 parentDirItem_Ptr = &parentDirItem;
1375 1476
1376 int secureIndex = -1; 1477 int secureIndex = -1;
@@ -1723,8 +1824,8 @@ HRESULT UpdateArchive(
1723 is_SameSize = (fileInfo.Size == dirItem.Size); 1824 is_SameSize = (fileInfo.Size == dirItem.Size);
1724 1825
1725 if (is_SameSize 1826 if (is_SameSize
1726 && CompareFileTime(&fileInfo.MTime, &dirItem.MTime) == 0 1827 && Compare_FiTime(&fileInfo.MTime, &dirItem.MTime) == 0
1727 && CompareFileTime(&fileInfo.CTime, &dirItem.CTime) == 0) 1828 && Compare_FiTime(&fileInfo.CTime, &dirItem.CTime) == 0)
1728 { 1829 {
1729 RINOK(callback->DeletingAfterArchiving(phyPath, false)); 1830 RINOK(callback->DeletingAfterArchiving(phyPath, false));
1730 DeleteFileAlways(phyPath); 1831 DeleteFileAlways(phyPath);
diff --git a/CPP/7zip/UI/Common/Update.h b/CPP/7zip/UI/Common/Update.h
index 06d1387..01fc43e 100644
--- a/CPP/7zip/UI/Common/Update.h
+++ b/CPP/7zip/UI/Common/Update.h
@@ -112,6 +112,9 @@ struct CUpdateOptions
112 CBoolPair HardLinks; 112 CBoolPair HardLinks;
113 CBoolPair SymLinks; 113 CBoolPair SymLinks;
114 114
115 CBoolPair StoreOwnerId;
116 CBoolPair StoreOwnerName;
117
115 bool DeleteAfterCompressing; 118 bool DeleteAfterCompressing;
116 119
117 bool SetArcMTime; 120 bool SetArcMTime;
diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp
index 7b705ba..926a275 100644
--- a/CPP/7zip/UI/Common/UpdateCallback.cpp
+++ b/CPP/7zip/UI/Common/UpdateCallback.cpp
@@ -4,6 +4,15 @@
4 4
5// #include <stdio.h> 5// #include <stdio.h>
6 6
7#ifndef _WIN32
8// #include <grp.h>
9// #include <pwd.h>
10
11// for major minor:
12// BSD: <sys/types.h>
13#include <sys/sysmacros.h>
14#endif
15
7#ifndef _7ZIP_ST 16#ifndef _7ZIP_ST
8#include "../../../Windows/Synchronization.h" 17#include "../../../Windows/Synchronization.h"
9#endif 18#endif
@@ -66,6 +75,18 @@ CArchiveUpdateCallback::CArchiveUpdateCallback():
66 StoreNtSecurity(false), 75 StoreNtSecurity(false),
67 StoreHardLinks(false), 76 StoreHardLinks(false),
68 StoreSymLinks(false), 77 StoreSymLinks(false),
78
79 #ifndef _WIN32
80 StoreOwnerId(false),
81 StoreOwnerName(false),
82 #endif
83
84 /*
85 , Need_ArcMTime_Report(false),
86 , ArcMTime_WasReported(false),
87 */
88 Need_LatestMTime(false),
89 LatestMTime_Defined(false),
69 90
70 ProcessedItemsStatuses(NULL) 91 ProcessedItemsStatuses(NULL)
71{ 92{
@@ -134,16 +155,17 @@ STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index,
134 COM_TRY_END 155 COM_TRY_END
135} 156}
136 157
158
137STDMETHODIMP CArchiveUpdateCallback::GetRootProp(PROPID propID, PROPVARIANT *value) 159STDMETHODIMP CArchiveUpdateCallback::GetRootProp(PROPID propID, PROPVARIANT *value)
138{ 160{
139 NCOM::CPropVariant prop; 161 NCOM::CPropVariant prop;
140 switch (propID) 162 switch (propID)
141 { 163 {
142 case kpidIsDir: prop = true; break; 164 case kpidIsDir: prop = true; break;
143 case kpidAttrib: if (ParentDirItem) prop = ParentDirItem->Attrib; break; 165 case kpidAttrib: if (ParentDirItem) prop = ParentDirItem->GetWinAttrib(); break;
144 case kpidCTime: if (ParentDirItem) prop = ParentDirItem->CTime; break; 166 case kpidCTime: if (ParentDirItem) PropVariant_SetFrom_FiTime(prop, ParentDirItem->CTime); break;
145 case kpidATime: if (ParentDirItem) prop = ParentDirItem->ATime; break; 167 case kpidATime: if (ParentDirItem) PropVariant_SetFrom_FiTime(prop, ParentDirItem->ATime); break;
146 case kpidMTime: if (ParentDirItem) prop = ParentDirItem->MTime; break; 168 case kpidMTime: if (ParentDirItem) PropVariant_SetFrom_FiTime(prop, ParentDirItem->MTime); break;
147 case kpidArcFileName: if (!ArcFileName.IsEmpty()) prop = ArcFileName; break; 169 case kpidArcFileName: if (!ArcFileName.IsEmpty()) prop = ArcFileName; break;
148 } 170 }
149 prop.Detach(value); 171 prop.Detach(value);
@@ -446,25 +468,46 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR
446 { 468 {
447 case kpidPath: prop = DirItems->GetLogPath((unsigned)up.DirIndex); break; 469 case kpidPath: prop = DirItems->GetLogPath((unsigned)up.DirIndex); break;
448 case kpidIsDir: prop = di.IsDir(); break; 470 case kpidIsDir: prop = di.IsDir(); break;
449 case kpidSize: prop = di.IsDir() ? (UInt64)0 : di.Size; break; 471 case kpidSize: prop = (UInt64)(di.IsDir() ? (UInt64)0 : di.Size); break;
450 case kpidAttrib: prop = di.Attrib; break; 472 case kpidCTime: PropVariant_SetFrom_FiTime(prop, di.CTime); break;
451 case kpidCTime: prop = di.CTime; break; 473 case kpidATime: PropVariant_SetFrom_FiTime(prop, di.ATime); break;
452 case kpidATime: prop = di.ATime; break; 474 case kpidMTime: PropVariant_SetFrom_FiTime(prop, di.MTime); break;
453 case kpidMTime: prop = di.MTime; break; 475 case kpidAttrib: prop = (UInt32)di.GetWinAttrib(); break;
476 case kpidPosixAttrib: prop = (UInt32)di.GetPosixAttrib(); break;
477
478 #if defined(_WIN32)
454 case kpidIsAltStream: prop = di.IsAltStream; break; 479 case kpidIsAltStream: prop = di.IsAltStream; break;
455 #if defined(_WIN32) && !defined(UNDER_CE)
456 // case kpidShortName: prop = di.ShortName; break; 480 // case kpidShortName: prop = di.ShortName; break;
457 #endif 481 #else
458 case kpidPosixAttrib: 482
459 { 483 case kpidDeviceMajor:
460 #ifdef _WIN32 484 /*
461 prop = di.GetPosixAttrib(); 485 printf("\ndi.mode = %o\n", di.mode);
462 #else 486 printf("\nst.st_rdev major = %d\n", (unsigned)major(di.rdev));
463 if (di.Attrib & FILE_ATTRIBUTE_UNIX_EXTENSION) 487 printf("\nst.st_rdev minor = %d\n", (unsigned)minor(di.rdev));
464 prop = (UInt32)(di.Attrib >> 16); 488 */
465 #endif 489 if (S_ISCHR(di.mode) || S_ISBLK(di.mode))
490 prop = (UInt32)major(di.rdev);
466 break; 491 break;
467 } 492
493 case kpidDeviceMinor:
494 if (S_ISCHR(di.mode) || S_ISBLK(di.mode))
495 prop = (UInt32)minor(di.rdev);
496 break;
497
498 // case kpidDevice: if (S_ISCHR(di.mode) || S_ISBLK(di.mode)) prop = (UInt64)(di.rdev); break;
499
500 case kpidUserId: if (StoreOwnerId) prop = (UInt32)di.uid; break;
501 case kpidGroupId: if (StoreOwnerId) prop = (UInt32)di.gid; break;
502 case kpidUser:
503 if (di.OwnerNameIndex >= 0)
504 prop = DirItems->OwnerNameMap.Strings[(unsigned)di.OwnerNameIndex];
505 break;
506 case kpidGroup:
507 if (di.OwnerGroupIndex >= 0)
508 prop = DirItems->OwnerGroupMap.Strings[(unsigned)di.OwnerGroupIndex];
509 break;
510 #endif
468 } 511 }
469 } 512 }
470 prop.Detach(value); 513 prop.Detach(value);
@@ -565,12 +608,41 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStrea
565 CInFileStream *inStreamSpec = new CInFileStream; 608 CInFileStream *inStreamSpec = new CInFileStream;
566 CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); 609 CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
567 610
611 /*
612 // for debug:
613 #ifdef _WIN32
614 inStreamSpec->StoreOwnerName = true;
615 inStreamSpec->OwnerName = "user_name";
616 inStreamSpec->OwnerName += di.Name;
617 inStreamSpec->OwnerName += "11111111112222222222222333333333333";
618 inStreamSpec->OwnerGroup = "gname_";
619 inStreamSpec->OwnerGroup += inStreamSpec->OwnerName;
620 #endif
621 */
622
623 #ifndef _WIN32
624 inStreamSpec->StoreOwnerId = StoreOwnerId;
625 inStreamSpec->StoreOwnerName = StoreOwnerName;
626
627 // if (StoreOwner)
628 {
629 inStreamSpec->_uid = di.uid;
630 inStreamSpec->_gid = di.gid;
631 if (di.OwnerNameIndex >= 0)
632 inStreamSpec->OwnerName = DirItems->OwnerNameMap.Strings[(unsigned)di.OwnerNameIndex];
633 if (di.OwnerGroupIndex >= 0)
634 inStreamSpec->OwnerGroup = DirItems->OwnerGroupMap.Strings[(unsigned)di.OwnerGroupIndex];
635 }
636 #endif
637
568 inStreamSpec->SupportHardLinks = StoreHardLinks; 638 inStreamSpec->SupportHardLinks = StoreHardLinks;
569 inStreamSpec->File.PreserveATime = PreserveATime; 639 inStreamSpec->Set_PreserveATime(PreserveATime
640 || mode == NUpdateNotifyOp::kAnalyze); // 22.00 : we don't change access time in Analyze pass.
570 641
571 const FString path = DirItems->GetPhyPath((unsigned)up.DirIndex); 642 const FString path = DirItems->GetPhyPath((unsigned)up.DirIndex);
572 _openFiles_Indexes.Add(index); 643 _openFiles_Indexes.Add(index);
573 _openFiles_Paths.Add(path); 644 _openFiles_Paths.Add(path);
645 // _openFiles_Streams.Add(inStreamSpec);
574 646
575 /* 21.02 : we set Callback/CallbackRef after _openFiles_Indexes adding 647 /* 21.02 : we set Callback/CallbackRef after _openFiles_Indexes adding
576 for correct working if exception was raised in GetPhyPath */ 648 for correct working if exception was raised in GetPhyPath */
@@ -579,14 +651,30 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStrea
579 651
580 if (!inStreamSpec->OpenShared(path, ShareForWrite)) 652 if (!inStreamSpec->OpenShared(path, ShareForWrite))
581 { 653 {
582 DWORD error = ::GetLastError(); 654 const DWORD error = ::GetLastError();
583 HRESULT hres = Callback->OpenFileError(path, error); 655 const HRESULT hres = Callback->OpenFileError(path, error);
584 if (StopAfterOpenError) 656 if (StopAfterOpenError)
585 if (hres == S_OK || hres == S_FALSE) 657 if (hres == S_OK || hres == S_FALSE)
586 return HRESULT_FROM_WIN32(error); 658 return HRESULT_FROM_WIN32(error);
587 return hres; 659 return hres;
588 } 660 }
589 661
662 /*
663 {
664 // for debug:
665 Byte b = 0;
666 UInt32 processedSize = 0;
667 if (inStreamSpec->Read(&b, 1, &processedSize) != S_OK ||
668 processedSize != 1)
669 return E_FAIL;
670 }
671 */
672
673 if (Need_LatestMTime)
674 {
675 inStreamSpec->ReloadProps();
676 }
677
590 // #if defined(USE_WIN_FILE) || !defined(_WIN32) 678 // #if defined(USE_WIN_FILE) || !defined(_WIN32)
591 if (StoreHardLinks) 679 if (StoreHardLinks)
592 { 680 {
@@ -643,6 +731,8 @@ STDMETHODIMP CArchiveUpdateCallback::ReportOperation(UInt32 indexType, UInt32 in
643{ 731{
644 COM_TRY_BEGIN 732 COM_TRY_BEGIN
645 733
734 // if (op == NUpdateNotifyOp::kOpFinished) return Callback->ReportFinished(indexType, index);
735
646 bool isDir = false; 736 bool isDir = false;
647 737
648 if (indexType == NArchive::NEventIndexType::kOutArcIndex) 738 if (indexType == NArchive::NEventIndexType::kOutArcIndex)
@@ -676,7 +766,7 @@ STDMETHODIMP CArchiveUpdateCallback::ReportOperation(UInt32 indexType, UInt32 in
676 } 766 }
677 else if (Arc) 767 else if (Arc)
678 { 768 {
679 RINOK(Arc->GetItemPath(index, s2)); 769 RINOK(Arc->GetItem_Path(index, s2));
680 s = s2; 770 s = s2;
681 RINOK(Archive_IsItem_Dir(Arc->Archive, index, isDir)); 771 RINOK(Archive_IsItem_Dir(Arc->Archive, index, isDir));
682 } 772 }
@@ -731,7 +821,7 @@ STDMETHODIMP CArchiveUpdateCallback::ReportExtractResult(UInt32 indexType, UInt3
731 s = (*ArcItems)[index].Name; 821 s = (*ArcItems)[index].Name;
732 else if (Arc) 822 else if (Arc)
733 { 823 {
734 RINOK(Arc->GetItemPath(index, s2)); 824 RINOK(Arc->GetItem_Path(index, s2));
735 s = s2; 825 s = s2;
736 } 826 }
737 if (Archive) 827 if (Archive)
@@ -752,6 +842,51 @@ STDMETHODIMP CArchiveUpdateCallback::ReportExtractResult(UInt32 indexType, UInt3
752 COM_TRY_END 842 COM_TRY_END
753} 843}
754 844
845
846/*
847STDMETHODIMP CArchiveUpdateCallback::DoNeedArcProp(PROPID propID, Int32 *answer)
848{
849 *answer = 0;
850 if (Need_ArcMTime_Report && propID == kpidComboMTime)
851 *answer = 1;
852 return S_OK;
853}
854
855STDMETHODIMP CArchiveUpdateCallback::ReportProp(UInt32 indexType, UInt32 index, PROPID propID, const PROPVARIANT *value)
856{
857 if (indexType == NArchive::NEventIndexType::kArcProp)
858 {
859 if (propID == kpidComboMTime)
860 {
861 ArcMTime_WasReported = true;
862 if (value->vt == VT_FILETIME)
863 {
864 Reported_ArcMTime.Set_From_Prop(*value);
865 Reported_ArcMTime.Def = true;
866 }
867 else
868 {
869 Reported_ArcMTime.Clear();
870 if (value->vt != VT_EMPTY)
871 return E_FAIL; // for debug
872 }
873 }
874 }
875 return Callback->ReportProp(indexType, index, propID, value);
876}
877
878STDMETHODIMP CArchiveUpdateCallback::ReportRawProp(UInt32 indexType, UInt32 index,
879 PROPID propID, const void *data, UInt32 dataSize, UInt32 propType)
880{
881 return Callback->ReportRawProp(indexType, index, propID, data, dataSize, propType);
882}
883
884STDMETHODIMP CArchiveUpdateCallback::ReportFinished(UInt32 indexType, UInt32 index, Int32 opRes)
885{
886 return Callback->ReportFinished(indexType, index, opRes);
887}
888*/
889
755STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) 890STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)
756{ 891{
757 if (VolumesSizes.Size() == 0) 892 if (VolumesSizes.Size() == 0)
@@ -805,7 +940,7 @@ HRESULT CArchiveUpdateCallback::InFileStream_On_Error(UINT_PTR val, DWORD error)
805 #endif 940 #endif
806 { 941 {
807 MT_LOCK 942 MT_LOCK
808 UInt32 index = (UInt32)val; 943 const UInt32 index = (UInt32)val;
809 FOR_VECTOR(i, _openFiles_Indexes) 944 FOR_VECTOR(i, _openFiles_Indexes)
810 { 945 {
811 if (_openFiles_Indexes[i] == index) 946 if (_openFiles_Indexes[i] == index)
@@ -818,21 +953,31 @@ HRESULT CArchiveUpdateCallback::InFileStream_On_Error(UINT_PTR val, DWORD error)
818 return HRESULT_FROM_WIN32(error); 953 return HRESULT_FROM_WIN32(error);
819} 954}
820 955
821void CArchiveUpdateCallback::InFileStream_On_Destroy(UINT_PTR val) 956void CArchiveUpdateCallback::InFileStream_On_Destroy(CInFileStream *stream, UINT_PTR val)
822{ 957{
823 {
824 MT_LOCK 958 MT_LOCK
825 UInt32 index = (UInt32)val; 959 if (Need_LatestMTime)
960 {
961 if (stream->_info_WasLoaded)
962 {
963 const CFiTime &ft = ST_MTIME(stream->_info);
964 if (!LatestMTime_Defined
965 || Compare_FiTime(&LatestMTime, &ft) < 0)
966 LatestMTime = ft;
967 LatestMTime_Defined = true;
968 }
969 }
970 const UInt32 index = (UInt32)val;
826 FOR_VECTOR(i, _openFiles_Indexes) 971 FOR_VECTOR(i, _openFiles_Indexes)
827 { 972 {
828 if (_openFiles_Indexes[i] == index) 973 if (_openFiles_Indexes[i] == index)
829 { 974 {
830 _openFiles_Indexes.Delete(i); 975 _openFiles_Indexes.Delete(i);
831 _openFiles_Paths.Delete(i); 976 _openFiles_Paths.Delete(i);
977 // _openFiles_Streams.Delete(i);
832 return; 978 return;
833 } 979 }
834 } 980 }
835 }
836 /* 21.02 : this function can be called in destructor. 981 /* 21.02 : this function can be called in destructor.
837 And destructor can be called after some exception. 982 And destructor can be called after some exception.
838 If we don't want to throw exception in desctructors or after another exceptions, 983 If we don't want to throw exception in desctructors or after another exceptions,
diff --git a/CPP/7zip/UI/Common/UpdateCallback.h b/CPP/7zip/UI/Common/UpdateCallback.h
index d27776e..3719c1e 100644
--- a/CPP/7zip/UI/Common/UpdateCallback.h
+++ b/CPP/7zip/UI/Common/UpdateCallback.h
@@ -45,6 +45,13 @@ struct CArcToDoStat
45 virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \ 45 virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \
46 virtual HRESULT CryptoGetTextPassword(BSTR *password) x; \ 46 virtual HRESULT CryptoGetTextPassword(BSTR *password) x; \
47 virtual HRESULT ShowDeleteFile(const wchar_t *name, bool isDir) x; \ 47 virtual HRESULT ShowDeleteFile(const wchar_t *name, bool isDir) x; \
48
49 /*
50 virtual HRESULT ReportProp(UInt32 indexType, UInt32 index, PROPID propID, const PROPVARIANT *value) x; \
51 virtual HRESULT ReportRawProp(UInt32 indexType, UInt32 index, PROPID propID, const void *data, UInt32 dataSize, UInt32 propType) x; \
52 virtual HRESULT ReportFinished(UInt32 indexType, UInt32 index, Int32 opRes) x; \
53 */
54
48 /* virtual HRESULT CloseProgress() { return S_OK; } */ 55 /* virtual HRESULT CloseProgress() { return S_OK; } */
49 56
50struct IUpdateCallbackUI 57struct IUpdateCallbackUI
@@ -70,6 +77,7 @@ struct CKeyKeyValPair
70class CArchiveUpdateCallback: 77class CArchiveUpdateCallback:
71 public IArchiveUpdateCallback2, 78 public IArchiveUpdateCallback2,
72 public IArchiveUpdateCallbackFile, 79 public IArchiveUpdateCallbackFile,
80 // public IArchiveUpdateCallbackArcProp,
73 public IArchiveExtractCallbackMessage, 81 public IArchiveExtractCallbackMessage,
74 public IArchiveGetRawProps, 82 public IArchiveGetRawProps,
75 public IArchiveGetRootProps, 83 public IArchiveGetRootProps,
@@ -92,6 +100,7 @@ class CArchiveUpdateCallback:
92public: 100public:
93 MY_QUERYINTERFACE_BEGIN2(IArchiveUpdateCallback2) 101 MY_QUERYINTERFACE_BEGIN2(IArchiveUpdateCallback2)
94 MY_QUERYINTERFACE_ENTRY(IArchiveUpdateCallbackFile) 102 MY_QUERYINTERFACE_ENTRY(IArchiveUpdateCallbackFile)
103 // MY_QUERYINTERFACE_ENTRY(IArchiveUpdateCallbackArcProp)
95 MY_QUERYINTERFACE_ENTRY(IArchiveExtractCallbackMessage) 104 MY_QUERYINTERFACE_ENTRY(IArchiveExtractCallbackMessage)
96 MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps) 105 MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
97 MY_QUERYINTERFACE_ENTRY(IArchiveGetRootProps) 106 MY_QUERYINTERFACE_ENTRY(IArchiveGetRootProps)
@@ -106,6 +115,7 @@ public:
106 115
107 INTERFACE_IArchiveUpdateCallback2(;) 116 INTERFACE_IArchiveUpdateCallback2(;)
108 INTERFACE_IArchiveUpdateCallbackFile(;) 117 INTERFACE_IArchiveUpdateCallbackFile(;)
118 // INTERFACE_IArchiveUpdateCallbackArcProp(;)
109 INTERFACE_IArchiveExtractCallbackMessage(;) 119 INTERFACE_IArchiveExtractCallbackMessage(;)
110 INTERFACE_IArchiveGetRawProps(;) 120 INTERFACE_IArchiveGetRawProps(;)
111 INTERFACE_IArchiveGetRootProps(;) 121 INTERFACE_IArchiveGetRootProps(;)
@@ -115,10 +125,11 @@ public:
115 125
116 CRecordVector<UInt32> _openFiles_Indexes; 126 CRecordVector<UInt32> _openFiles_Indexes;
117 FStringVector _openFiles_Paths; 127 FStringVector _openFiles_Paths;
128 // CRecordVector< CInFileStream* > _openFiles_Streams;
118 129
119 bool AreAllFilesClosed() const { return _openFiles_Indexes.IsEmpty(); } 130 bool AreAllFilesClosed() const { return _openFiles_Indexes.IsEmpty(); }
120 virtual HRESULT InFileStream_On_Error(UINT_PTR val, DWORD error); 131 virtual HRESULT InFileStream_On_Error(UINT_PTR val, DWORD error);
121 virtual void InFileStream_On_Destroy(UINT_PTR val); 132 virtual void InFileStream_On_Destroy(CInFileStream *stream, UINT_PTR val);
122 133
123 CRecordVector<UInt64> VolumesSizes; 134 CRecordVector<UInt64> VolumesSizes;
124 FString VolName; 135 FString VolName;
@@ -148,8 +159,22 @@ public:
148 bool StoreHardLinks; 159 bool StoreHardLinks;
149 bool StoreSymLinks; 160 bool StoreSymLinks;
150 161
162 bool StoreOwnerId;
163 bool StoreOwnerName;
164
165 /*
166 bool Need_ArcMTime_Report;
167 bool ArcMTime_WasReported;
168 CArcTime Reported_ArcMTime;
169 */
170 bool Need_LatestMTime;
171 bool LatestMTime_Defined;
172 CFiTime LatestMTime;
173
151 Byte *ProcessedItemsStatuses; 174 Byte *ProcessedItemsStatuses;
152 175
176
177
153 CArchiveUpdateCallback(); 178 CArchiveUpdateCallback();
154 179
155 bool IsDir(const CUpdatePair2 &up) const 180 bool IsDir(const CUpdatePair2 &up) const
diff --git a/CPP/7zip/UI/Common/UpdatePair.cpp b/CPP/7zip/UI/Common/UpdatePair.cpp
index 31d73f9..e9a1644 100644
--- a/CPP/7zip/UI/Common/UpdatePair.cpp
+++ b/CPP/7zip/UI/Common/UpdatePair.cpp
@@ -3,6 +3,7 @@
3#include "StdAfx.h" 3#include "StdAfx.h"
4 4
5#include <time.h> 5#include <time.h>
6// #include <stdio.h>
6 7
7#include "../../../Common/Wildcard.h" 8#include "../../../Common/Wildcard.h"
8 9
@@ -14,30 +15,90 @@
14using namespace NWindows; 15using namespace NWindows;
15using namespace NTime; 16using namespace NTime;
16 17
17static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2) 18
19/*
20 a2.Prec =
21 {
22 0 (k_PropVar_TimePrec_0):
23 if GetProperty(kpidMTime) returned 0 and
24 GetProperty(kpidTimeType) did not returned VT_UI4.
25 7z, wim, tar in 7-Zip before v21)
26 in that case we use
27 (prec) that is set by IOutArchive::GetFileTimeType()
28 }
29*/
30
31static int MyCompareTime(unsigned prec, const CFiTime &f1, const CArcTime &a2)
18{ 32{
19 switch (fileTimeType) 33 // except of precision, we also have limitation, when timestamp is out of range
34
35 /* if (Prec) in archive item is defined, then use global (prec) */
36 if (a2.Prec != k_PropVar_TimePrec_0)
37 prec = a2.Prec;
38
39 CArcTime a1;
40 a1.Set_From_FiTime(f1);
41 /* Set_From_FiTime() must set full form precision:
42 k_PropVar_TimePrec_Base + numDigits
43 windows: 7 digits, non-windows: 9 digits */
44
45 if (prec == k_PropVar_TimePrec_DOS)
20 { 46 {
21 case NFileTimeType::kWindows: 47 const UInt32 dosTime1 = a1.Get_DosTime();
22 return ::CompareFileTime(&time1, &time2); 48 const UInt32 dosTime2 = a2.Get_DosTime();
23 case NFileTimeType::kUnix: 49 return MyCompare(dosTime1, dosTime2);
24 {
25 UInt32 unixTime1, unixTime2;
26 FileTimeToUnixTime(time1, unixTime1);
27 FileTimeToUnixTime(time2, unixTime2);
28 return MyCompare(unixTime1, unixTime2);
29 }
30 case NFileTimeType::kDOS:
31 {
32 UInt32 dosTime1, dosTime2;
33 FileTimeToDosTime(time1, dosTime1);
34 FileTimeToDosTime(time2, dosTime2);
35 return MyCompare(dosTime1, dosTime2);
36 }
37 } 50 }
38 throw 4191618; 51
52 if (prec == k_PropVar_TimePrec_Unix)
53 {
54 const Int64 u2 = FileTime_To_UnixTime64(a2.FT);
55 if (u2 == 0 || u2 == (UInt32)0xFFFFFFFF)
56 {
57 // timestamp probably was saturated in archive to 32-bit
58 // so we use saturated 32-bit value for disk file too.
59 UInt32 u1;
60 FileTime_To_UnixTime(a1.FT, u1);
61 const UInt32 u2_32 = (UInt32)u2;
62 return MyCompare(u1, u2_32);
63 }
64
65 const Int64 u1 = FileTime_To_UnixTime64(a1.FT);
66 return MyCompare(u1, u2);
67 // prec = k_PropVar_TimePrec_Base; // for debug
68 }
69
70 if (prec == k_PropVar_TimePrec_0)
71 prec = k_PropVar_TimePrec_Base + 7;
72 else if (prec == k_PropVar_TimePrec_HighPrec)
73 prec = k_PropVar_TimePrec_Base + 9;
74 else if (prec < k_PropVar_TimePrec_Base)
75 prec = k_PropVar_TimePrec_Base;
76 else if (prec > k_PropVar_TimePrec_Base + 9)
77 prec = k_PropVar_TimePrec_Base + 7;
78
79 // prec now is full form: k_PropVar_TimePrec_Base + numDigits;
80 if (prec > a1.Prec && a1.Prec >= k_PropVar_TimePrec_Base)
81 prec = a1.Prec;
82
83 const unsigned numDigits = prec - k_PropVar_TimePrec_Base;
84 if (numDigits >= 7)
85 {
86 const int comp = CompareFileTime(&a1.FT, &a2.FT);
87 if (comp != 0 || numDigits == 7)
88 return comp;
89 return MyCompare(a1.Ns100, a2.Ns100);
90 }
91 UInt32 d = 1;
92 for (unsigned k = numDigits; k < 7; k++)
93 d *= 10;
94 const UInt64 v1 = a1.Get_FILETIME_as_UInt64() / d * d;
95 const UInt64 v2 = a2.Get_FILETIME_as_UInt64() / d * d;
96 // printf("\ndelta=%d numDigits=%d\n", (unsigned)(v1- v2), numDigits);
97 return MyCompare(v1, v2);
39} 98}
40 99
100
101
41static const char * const k_Duplicate_inArc_Message = "Duplicate filename in archive:"; 102static const char * const k_Duplicate_inArc_Message = "Duplicate filename in archive:";
42static const char * const k_Duplicate_inDir_Message = "Duplicate filename on disk:"; 103static const char * const k_Duplicate_inDir_Message = "Duplicate filename on disk:";
43static const char * const k_NotCensoredCollision_Message = "Internal file name collision (file on disk, file in archive):"; 104static const char * const k_NotCensoredCollision_Message = "Internal file name collision (file on disk, file in archive):";
@@ -64,8 +125,8 @@ static int CompareArcItemsBase(const CArcItem &ai1, const CArcItem &ai2)
64 125
65static int CompareArcItems(const unsigned *p1, const unsigned *p2, void *param) 126static int CompareArcItems(const unsigned *p1, const unsigned *p2, void *param)
66{ 127{
67 unsigned i1 = *p1; 128 const unsigned i1 = *p1;
68 unsigned i2 = *p2; 129 const unsigned i2 = *p2;
69 const CObjectVector<CArcItem> &arcItems = *(const CObjectVector<CArcItem> *)param; 130 const CObjectVector<CArcItem> &arcItems = *(const CObjectVector<CArcItem> *)param;
70 int res = CompareArcItemsBase(arcItems[i1], arcItems[i2]); 131 int res = CompareArcItemsBase(arcItems[i1], arcItems[i2]);
71 if (res != 0) 132 if (res != 0)
@@ -81,8 +142,8 @@ void GetUpdatePairInfoList(
81{ 142{
82 CUIntVector dirIndices, arcIndices; 143 CUIntVector dirIndices, arcIndices;
83 144
84 unsigned numDirItems = dirItems.Items.Size(); 145 const unsigned numDirItems = dirItems.Items.Size();
85 unsigned numArcItems = arcItems.Size(); 146 const unsigned numArcItems = arcItems.Size();
86 147
87 CIntArr duplicatedArcItem(numArcItems); 148 CIntArr duplicatedArcItem(numArcItems);
88 { 149 {
@@ -184,7 +245,7 @@ void GetUpdatePairInfoList(
184 } 245 }
185 else 246 else
186 { 247 {
187 int dupl = duplicatedArcItem[arcIndex]; 248 const int dupl = duplicatedArcItem[arcIndex];
188 if (dupl != 0) 249 if (dupl != 0)
189 ThrowError(k_Duplicate_inArc_Message, ai->Name, arcItems[arcIndices[(unsigned)((int)arcIndex + dupl)]].Name); 250 ThrowError(k_Duplicate_inArc_Message, ai->Name, arcItems[arcIndices[(unsigned)((int)arcIndex + dupl)]].Name);
190 251
@@ -195,14 +256,17 @@ void GetUpdatePairInfoList(
195 pair.DirIndex = dirIndex2; 256 pair.DirIndex = dirIndex2;
196 pair.ArcIndex = arcIndex2; 257 pair.ArcIndex = arcIndex2;
197 258
198 switch (ai->MTimeDefined ? MyCompareTime( 259 int compResult = 0;
199 ai->TimeType != - 1 ? (NFileTimeType::EEnum)ai->TimeType : fileTimeType, 260 if (ai->MTime.Def)
200 di->MTime, ai->MTime): 0) 261 {
262 compResult = MyCompareTime(fileTimeType, di->MTime, ai->MTime);
263 }
264 switch (compResult)
201 { 265 {
202 case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break; 266 case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break;
203 case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break; 267 case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break;
204 default: 268 default:
205 pair.State = (ai->SizeDefined && di->Size == ai->Size) ? 269 pair.State = (ai->Size_Defined && di->Size == ai->Size) ?
206 NUpdateArchive::NPairState::kSameFiles : 270 NUpdateArchive::NPairState::kSameFiles :
207 NUpdateArchive::NPairState::kUnknowNewerFiles; 271 NUpdateArchive::NPairState::kUnknowNewerFiles;
208 } 272 }
@@ -211,7 +275,10 @@ void GetUpdatePairInfoList(
211 arcIndex++; 275 arcIndex++;
212 } 276 }
213 277
214 if ((di && di->IsAltStream) || 278 if (
279 #ifdef _WIN32
280 (di && di->IsAltStream) ||
281 #endif
215 (ai && ai->IsAltStream)) 282 (ai && ai->IsAltStream))
216 { 283 {
217 if (prevHostName) 284 if (prevHostName)
diff --git a/CPP/7zip/UI/Common/UpdateProduce.cpp b/CPP/7zip/UI/Common/UpdateProduce.cpp
index fa4bd69..e921dc3 100644
--- a/CPP/7zip/UI/Common/UpdateProduce.cpp
+++ b/CPP/7zip/UI/Common/UpdateProduce.cpp
@@ -63,6 +63,8 @@ void UpdateProduce(
63 break; 63 break;
64 } 64 }
65 65
66 up2.IsSameTime = ((unsigned)pair.State == NUpdateArchive::NPairState::kSameFiles);
67
66 operationChain.Add(up2); 68 operationChain.Add(up2);
67 } 69 }
68 70
diff --git a/CPP/7zip/UI/Common/UpdateProduce.h b/CPP/7zip/UI/Common/UpdateProduce.h
index 595370f..24bb32e 100644
--- a/CPP/7zip/UI/Common/UpdateProduce.h
+++ b/CPP/7zip/UI/Common/UpdateProduce.h
@@ -17,6 +17,7 @@ struct CUpdatePair2
17 int NewNameIndex; 17 int NewNameIndex;
18 18
19 bool IsMainRenameItem; 19 bool IsMainRenameItem;
20 bool IsSameTime;
20 21
21 void SetAs_NoChangeArcItem(unsigned arcIndex) // int 22 void SetAs_NoChangeArcItem(unsigned arcIndex) // int
22 { 23 {
@@ -37,7 +38,8 @@ struct CUpdatePair2
37 DirIndex(-1), 38 DirIndex(-1),
38 ArcIndex(-1), 39 ArcIndex(-1),
39 NewNameIndex(-1), 40 NewNameIndex(-1),
40 IsMainRenameItem(false) 41 IsMainRenameItem(false),
42 IsSameTime(false)
41 {} 43 {}
42}; 44};
43 45
diff --git a/CPP/7zip/UI/Common/ZipRegistry.cpp b/CPP/7zip/UI/Common/ZipRegistry.cpp
index ab4871f..a67a99b 100644
--- a/CPP/7zip/UI/Common/ZipRegistry.cpp
+++ b/CPP/7zip/UI/Common/ZipRegistry.cpp
@@ -33,12 +33,45 @@ static LONG CreateMainKey(CKey &key, LPCTSTR keyName)
33 return key.Create(HKEY_CURRENT_USER, GetKeyPath(keyName)); 33 return key.Create(HKEY_CURRENT_USER, GetKeyPath(keyName));
34} 34}
35 35
36static void Key_Set_UInt32(CKey &key, LPCTSTR name, UInt32 value)
37{
38 if (value == (UInt32)(Int32)-1)
39 key.DeleteValue(name);
40 else
41 key.SetValue(name, value);
42}
43
44
45static void Key_Get_UInt32(CKey &key, LPCTSTR name, UInt32 &value)
46{
47 if (key.QueryValue(name, value) != ERROR_SUCCESS)
48 value = (UInt32)(Int32)-1;
49}
50
51
36static void Key_Set_BoolPair(CKey &key, LPCTSTR name, const CBoolPair &b) 52static void Key_Set_BoolPair(CKey &key, LPCTSTR name, const CBoolPair &b)
37{ 53{
38 if (b.Def) 54 if (b.Def)
39 key.SetValue(name, b.Val); 55 key.SetValue(name, b.Val);
40} 56}
41 57
58static void Key_Set_bool_if_Changed(CKey &key, LPCTSTR name, bool val)
59{
60 bool oldVal = false;
61 if (key.GetValue_IfOk(name, oldVal) == ERROR_SUCCESS)
62 if (val == oldVal)
63 return;
64 key.SetValue(name, val);
65}
66
67static void Key_Set_BoolPair_Delete_IfNotDef(CKey &key, LPCTSTR name, const CBoolPair &b)
68{
69 if (b.Def)
70 Key_Set_bool_if_Changed(key, name, b.Val);
71 else
72 key.DeleteValue(name);
73}
74
42static void Key_Get_BoolPair(CKey &key, LPCTSTR name, CBoolPair &b) 75static void Key_Get_BoolPair(CKey &key, LPCTSTR name, CBoolPair &b)
43{ 76{
44 b.Val = false; 77 b.Val = false;
@@ -169,6 +202,13 @@ static LPCTSTR const kNtSecur = TEXT("Security");
169static LPCTSTR const kAltStreams = TEXT("AltStreams"); 202static LPCTSTR const kAltStreams = TEXT("AltStreams");
170static LPCTSTR const kHardLinks = TEXT("HardLinks"); 203static LPCTSTR const kHardLinks = TEXT("HardLinks");
171static LPCTSTR const kSymLinks = TEXT("SymLinks"); 204static LPCTSTR const kSymLinks = TEXT("SymLinks");
205static LPCTSTR const kPreserveATime = TEXT("PreserveATime");
206
207static LPCTSTR const kTimePrec = TEXT("TimePrec");
208static LPCTSTR const kMTime = TEXT("MTime");
209static LPCTSTR const kATime = TEXT("ATime");
210static LPCTSTR const kCTime = TEXT("CTime");
211static LPCTSTR const kSetArcMTime = TEXT("SetArcMTime");
172 212
173static void SetRegString(CKey &key, LPCWSTR name, const UString &value) 213static void SetRegString(CKey &key, LPCWSTR name, const UString &value)
174{ 214{
@@ -178,26 +218,12 @@ static void SetRegString(CKey &key, LPCWSTR name, const UString &value)
178 key.SetValue(name, value); 218 key.SetValue(name, value);
179} 219}
180 220
181static void SetRegUInt32(CKey &key, LPCTSTR name, UInt32 value)
182{
183 if (value == (UInt32)(Int32)-1)
184 key.DeleteValue(name);
185 else
186 key.SetValue(name, value);
187}
188
189static void GetRegString(CKey &key, LPCWSTR name, UString &value) 221static void GetRegString(CKey &key, LPCWSTR name, UString &value)
190{ 222{
191 if (key.QueryValue(name, value) != ERROR_SUCCESS) 223 if (key.QueryValue(name, value) != ERROR_SUCCESS)
192 value.Empty(); 224 value.Empty();
193} 225}
194 226
195static void GetRegUInt32(CKey &key, LPCTSTR name, UInt32 &value)
196{
197 if (key.QueryValue(name, value) != ERROR_SUCCESS)
198 value = (UInt32)(Int32)-1;
199}
200
201static LPCWSTR const kMemUse = L"MemUse" 227static LPCWSTR const kMemUse = L"MemUse"
202 #if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4) 228 #if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4)
203 L"32"; 229 L"32";
@@ -212,10 +238,11 @@ void CInfo::Save() const
212 CKey key; 238 CKey key;
213 CreateMainKey(key, kKeyName); 239 CreateMainKey(key, kKeyName);
214 240
215 Key_Set_BoolPair(key, kNtSecur, NtSecurity); 241 Key_Set_BoolPair_Delete_IfNotDef (key, kNtSecur, NtSecurity);
216 Key_Set_BoolPair(key, kAltStreams, AltStreams); 242 Key_Set_BoolPair_Delete_IfNotDef (key, kAltStreams, AltStreams);
217 Key_Set_BoolPair(key, kHardLinks, HardLinks); 243 Key_Set_BoolPair_Delete_IfNotDef (key, kHardLinks, HardLinks);
218 Key_Set_BoolPair(key, kSymLinks, SymLinks); 244 Key_Set_BoolPair_Delete_IfNotDef (key, kSymLinks, SymLinks);
245 Key_Set_BoolPair_Delete_IfNotDef (key, kPreserveATime, PreserveATime);
219 246
220 key.SetValue(kShowPassword, ShowPassword); 247 key.SetValue(kShowPassword, ShowPassword);
221 key.SetValue(kLevel, (UInt32)Level); 248 key.SetValue(kLevel, (UInt32)Level);
@@ -235,16 +262,22 @@ void CInfo::Save() const
235 CKey fk; 262 CKey fk;
236 fk.Create(optionsKey, fo.FormatID); 263 fk.Create(optionsKey, fo.FormatID);
237 264
238 SetRegUInt32(fk, kLevel, fo.Level);
239 SetRegUInt32(fk, kDictionary, fo.Dictionary);
240 SetRegUInt32(fk, kOrder, fo.Order);
241 SetRegUInt32(fk, kBlockSize, fo.BlockLogSize);
242 SetRegUInt32(fk, kNumThreads, fo.NumThreads);
243
244 SetRegString(fk, kMethod, fo.Method); 265 SetRegString(fk, kMethod, fo.Method);
245 SetRegString(fk, kOptions, fo.Options); 266 SetRegString(fk, kOptions, fo.Options);
246 SetRegString(fk, kEncryptionMethod, fo.EncryptionMethod); 267 SetRegString(fk, kEncryptionMethod, fo.EncryptionMethod);
247 SetRegString(fk, kMemUse, fo.MemUse); 268 SetRegString(fk, kMemUse, fo.MemUse);
269
270 Key_Set_UInt32(fk, kLevel, fo.Level);
271 Key_Set_UInt32(fk, kDictionary, fo.Dictionary);
272 Key_Set_UInt32(fk, kOrder, fo.Order);
273 Key_Set_UInt32(fk, kBlockSize, fo.BlockLogSize);
274 Key_Set_UInt32(fk, kNumThreads, fo.NumThreads);
275
276 Key_Set_UInt32(fk, kTimePrec, fo.TimePrec);
277 Key_Set_BoolPair_Delete_IfNotDef (fk, kMTime, fo.MTime);
278 Key_Set_BoolPair_Delete_IfNotDef (fk, kATime, fo.ATime);
279 Key_Set_BoolPair_Delete_IfNotDef (fk, kCTime, fo.CTime);
280 Key_Set_BoolPair_Delete_IfNotDef (fk, kSetArcMTime, fo.SetArcMTime);
248 } 281 }
249 } 282 }
250} 283}
@@ -269,6 +302,7 @@ void CInfo::Load()
269 Key_Get_BoolPair(key, kAltStreams, AltStreams); 302 Key_Get_BoolPair(key, kAltStreams, AltStreams);
270 Key_Get_BoolPair(key, kHardLinks, HardLinks); 303 Key_Get_BoolPair(key, kHardLinks, HardLinks);
271 Key_Get_BoolPair(key, kSymLinks, SymLinks); 304 Key_Get_BoolPair(key, kSymLinks, SymLinks);
305 Key_Get_BoolPair(key, kPreserveATime, PreserveATime);
272 306
273 key.GetValue_Strings(kArcHistory, ArcPaths); 307 key.GetValue_Strings(kArcHistory, ArcPaths);
274 308
@@ -290,11 +324,17 @@ void CInfo::Load()
290 GetRegString(fk, kEncryptionMethod, fo.EncryptionMethod); 324 GetRegString(fk, kEncryptionMethod, fo.EncryptionMethod);
291 GetRegString(fk, kMemUse, fo.MemUse); 325 GetRegString(fk, kMemUse, fo.MemUse);
292 326
293 GetRegUInt32(fk, kLevel, fo.Level); 327 Key_Get_UInt32(fk, kLevel, fo.Level);
294 GetRegUInt32(fk, kDictionary, fo.Dictionary); 328 Key_Get_UInt32(fk, kDictionary, fo.Dictionary);
295 GetRegUInt32(fk, kOrder, fo.Order); 329 Key_Get_UInt32(fk, kOrder, fo.Order);
296 GetRegUInt32(fk, kBlockSize, fo.BlockLogSize); 330 Key_Get_UInt32(fk, kBlockSize, fo.BlockLogSize);
297 GetRegUInt32(fk, kNumThreads, fo.NumThreads); 331 Key_Get_UInt32(fk, kNumThreads, fo.NumThreads);
332
333 Key_Get_UInt32(fk, kTimePrec, fo.TimePrec);
334 Key_Get_BoolPair(fk, kMTime, fo.MTime);
335 Key_Get_BoolPair(fk, kATime, fo.ATime);
336 Key_Get_BoolPair(fk, kCTime, fo.CTime);
337 Key_Get_BoolPair(fk, kSetArcMTime, fo.SetArcMTime);
298 338
299 Formats.Add(fo); 339 Formats.Add(fo);
300 } 340 }
@@ -478,6 +518,7 @@ static LPCTSTR const kCascadedMenu = TEXT("CascadedMenu");
478static LPCTSTR const kContextMenu = TEXT("ContextMenu"); 518static LPCTSTR const kContextMenu = TEXT("ContextMenu");
479static LPCTSTR const kMenuIcons = TEXT("MenuIcons"); 519static LPCTSTR const kMenuIcons = TEXT("MenuIcons");
480static LPCTSTR const kElimDup = TEXT("ElimDupExtract"); 520static LPCTSTR const kElimDup = TEXT("ElimDupExtract");
521static LPCTSTR const kWriteZoneId = TEXT("WriteZoneIdExtract");
481 522
482void CContextMenuInfo::Save() const 523void CContextMenuInfo::Save() const
483{ 524{
@@ -488,6 +529,8 @@ void CContextMenuInfo::Save() const
488 Key_Set_BoolPair(key, kCascadedMenu, Cascaded); 529 Key_Set_BoolPair(key, kCascadedMenu, Cascaded);
489 Key_Set_BoolPair(key, kMenuIcons, MenuIcons); 530 Key_Set_BoolPair(key, kMenuIcons, MenuIcons);
490 Key_Set_BoolPair(key, kElimDup, ElimDup); 531 Key_Set_BoolPair(key, kElimDup, ElimDup);
532
533 Key_Set_UInt32(key, kWriteZoneId, WriteZone);
491 534
492 if (Flags_Def) 535 if (Flags_Def)
493 key.SetValue(kContextMenu, Flags); 536 key.SetValue(kContextMenu, Flags);
@@ -504,6 +547,8 @@ void CContextMenuInfo::Load()
504 ElimDup.Val = true; 547 ElimDup.Val = true;
505 ElimDup.Def = false; 548 ElimDup.Def = false;
506 549
550 WriteZone = (UInt32)(Int32)-1;
551
507 Flags = (UInt32)(Int32)-1; 552 Flags = (UInt32)(Int32)-1;
508 Flags_Def = false; 553 Flags_Def = false;
509 554
@@ -517,5 +562,7 @@ void CContextMenuInfo::Load()
517 Key_Get_BoolPair_true(key, kElimDup, ElimDup); 562 Key_Get_BoolPair_true(key, kElimDup, ElimDup);
518 Key_Get_BoolPair(key, kMenuIcons, MenuIcons); 563 Key_Get_BoolPair(key, kMenuIcons, MenuIcons);
519 564
565 Key_Get_UInt32(key, kWriteZoneId, WriteZone);
566
520 Flags_Def = (key.GetValue_IfOk(kContextMenu, Flags) == ERROR_SUCCESS); 567 Flags_Def = (key.GetValue_IfOk(kContextMenu, Flags) == ERROR_SUCCESS);
521} 568}
diff --git a/CPP/7zip/UI/Common/ZipRegistry.h b/CPP/7zip/UI/Common/ZipRegistry.h
index 3d2e4b9..b7075e6 100644
--- a/CPP/7zip/UI/Common/ZipRegistry.h
+++ b/CPP/7zip/UI/Common/ZipRegistry.h
@@ -10,6 +10,16 @@
10 10
11#include "ExtractMode.h" 11#include "ExtractMode.h"
12 12
13/*
14CBoolPair::Def in writing functions means:
15 if ( CBoolPair::Def ), we write CBoolPair::Val
16 if ( !CBoolPair::Def )
17 {
18 in NCompression functions we delete registry value
19 in another functions we do nothing
20 }
21*/
22
13namespace NExtract 23namespace NExtract
14{ 24{
15 struct CInfo 25 struct CInfo
@@ -75,12 +85,29 @@ namespace NCompression
75 UInt32 BlockLogSize; 85 UInt32 BlockLogSize;
76 UInt32 NumThreads; 86 UInt32 NumThreads;
77 87
88 UInt32 TimePrec;
89 CBoolPair MTime;
90 CBoolPair ATime;
91 CBoolPair CTime;
92 CBoolPair SetArcMTime;
93
78 CSysString FormatID; 94 CSysString FormatID;
79 UString Method; 95 UString Method;
80 UString Options; 96 UString Options;
81 UString EncryptionMethod; 97 UString EncryptionMethod;
82 UString MemUse; 98 UString MemUse;
83 99
100 void Reset_TimePrec()
101 {
102 TimePrec = (UInt32)(Int32)-1;
103 }
104
105 bool IsSet_TimePrec() const
106 {
107 return TimePrec != (UInt32)(Int32)-1;
108 }
109
110
84 void Reset_BlockLogSize() 111 void Reset_BlockLogSize()
85 { 112 {
86 BlockLogSize = (UInt32)(Int32)-1; 113 BlockLogSize = (UInt32)(Int32)-1;
@@ -93,7 +120,12 @@ namespace NCompression
93 // Options.Empty(); 120 // Options.Empty();
94 // EncryptionMethod.Empty(); 121 // EncryptionMethod.Empty();
95 } 122 }
96 CFormatOptions() { ResetForLevelChange(); } 123 CFormatOptions()
124 {
125 // TimePrec = 0;
126 Reset_TimePrec();
127 ResetForLevelChange();
128 }
97 }; 129 };
98 130
99 struct CInfo 131 struct CInfo
@@ -111,6 +143,8 @@ namespace NCompression
111 CBoolPair HardLinks; 143 CBoolPair HardLinks;
112 CBoolPair SymLinks; 144 CBoolPair SymLinks;
113 145
146 CBoolPair PreserveATime;
147
114 void Save() const; 148 void Save() const;
115 void Load(); 149 void Load();
116 }; 150 };
@@ -152,9 +186,18 @@ struct CContextMenuInfo
152 CBoolPair Cascaded; 186 CBoolPair Cascaded;
153 CBoolPair MenuIcons; 187 CBoolPair MenuIcons;
154 CBoolPair ElimDup; 188 CBoolPair ElimDup;
155 189
156 bool Flags_Def; 190 bool Flags_Def;
157 UInt32 Flags; 191 UInt32 Flags;
192 UInt32 WriteZone;
193
194 /*
195 CContextMenuInfo():
196 Flags_Def(0),
197 WriteZone((UInt32)(Int32)-1),
198 Flags((UInt32)(Int32)-1)
199 {}
200 */
158 201
159 void Save() const; 202 void Save() const;
160 void Load(); 203 void Load();