diff options
author | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2022-06-20 00:00:00 +0000 |
---|---|---|
committer | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2023-12-17 13:35:20 +0500 |
commit | a3e1d227377188734b82f023f96f8e25dc40f3e6 (patch) | |
tree | 23cad8d47eb23d26ea727b4f7f4a65124f724065 | |
parent | f19f813537c7aea1c20749c914e756b54a9c3cf5 (diff) | |
download | 7zip-a3e1d227377188734b82f023f96f8e25dc40f3e6.tar.gz 7zip-a3e1d227377188734b82f023f96f8e25dc40f3e6.tar.bz2 7zip-a3e1d227377188734b82f023f96f8e25dc40f3e6.zip |
22.0022.00
211 files changed, 15196 insertions, 2397 deletions
diff --git a/Asm/x86/7zAsm.asm b/Asm/x86/7zAsm.asm index 6275bb7..19c40da 100644 --- a/Asm/x86/7zAsm.asm +++ b/Asm/x86/7zAsm.asm | |||
@@ -1,7 +1,12 @@ | |||
1 | ; 7zAsm.asm -- ASM macros | 1 | ; 7zAsm.asm -- ASM macros |
2 | ; 2021-12-25 : Igor Pavlov : Public domain | 2 | ; 2022-05-16 : Igor Pavlov : Public domain |
3 | 3 | ||
4 | 4 | ||
5 | ; UASM can require these changes | ||
6 | ; OPTION FRAMEPRESERVEFLAGS:ON | ||
7 | ; OPTION PROLOGUE:NONE | ||
8 | ; OPTION EPILOGUE:NONE | ||
9 | |||
5 | ifdef @wordsize | 10 | ifdef @wordsize |
6 | ; @wordsize is defined only in JWASM and ASMC and is not defined in MASM | 11 | ; @wordsize is defined only in JWASM and ASMC and is not defined in MASM |
7 | ; @wordsize eq 8 for 64-bit x64 | 12 | ; @wordsize eq 8 for 64-bit x64 |
diff --git a/Asm/x86/Sha256Opt.asm b/Asm/x86/Sha256Opt.asm index 5d02c90..3e9f6ed 100644 --- a/Asm/x86/Sha256Opt.asm +++ b/Asm/x86/Sha256Opt.asm | |||
@@ -1,5 +1,5 @@ | |||
1 | ; Sha256Opt.asm -- SHA-256 optimized code for SHA-256 x86 hardware instructions | 1 | ; Sha256Opt.asm -- SHA-256 optimized code for SHA-256 x86 hardware instructions |
2 | ; 2021-03-10 : Igor Pavlov : Public domain | 2 | ; 2022-04-17 : Igor Pavlov : Public domain |
3 | 3 | ||
4 | include 7zAsm.asm | 4 | include 7zAsm.asm |
5 | 5 | ||
@@ -54,14 +54,20 @@ ifndef x64 | |||
54 | .686 | 54 | .686 |
55 | .xmm | 55 | .xmm |
56 | endif | 56 | endif |
57 | 57 | ||
58 | ; jwasm-based assemblers for linux and linker from new versions of binutils | ||
59 | ; can generate incorrect code for load [ARRAY + offset] instructions. | ||
60 | ; 22.00: we load K_CONST offset to (rTable) register to avoid jwasm+binutils problem | ||
61 | rTable equ r0 | ||
62 | ; rTable equ K_CONST | ||
63 | |||
58 | ifdef x64 | 64 | ifdef x64 |
59 | rNum equ REG_ABI_PARAM_2 | 65 | rNum equ REG_ABI_PARAM_2 |
60 | if (IS_LINUX eq 0) | 66 | if (IS_LINUX eq 0) |
61 | LOCAL_SIZE equ (16 * 2) | 67 | LOCAL_SIZE equ (16 * 2) |
62 | endif | 68 | endif |
63 | else | 69 | else |
64 | rNum equ r0 | 70 | rNum equ r3 |
65 | LOCAL_SIZE equ (16 * 1) | 71 | LOCAL_SIZE equ (16 * 1) |
66 | endif | 72 | endif |
67 | 73 | ||
@@ -103,15 +109,18 @@ MY_PROLOG macro | |||
103 | movdqa [r4 + 16], xmm9 | 109 | movdqa [r4 + 16], xmm9 |
104 | endif | 110 | endif |
105 | else ; x86 | 111 | else ; x86 |
112 | push r3 | ||
113 | push r5 | ||
114 | mov r5, r4 | ||
115 | NUM_PUSH_REGS equ 2 | ||
116 | PARAM_OFFSET equ (REG_SIZE * (1 + NUM_PUSH_REGS)) | ||
106 | if (IS_CDECL gt 0) | 117 | if (IS_CDECL gt 0) |
107 | mov rState, [r4 + REG_SIZE * 1] | 118 | mov rState, [r4 + PARAM_OFFSET] |
108 | mov rData, [r4 + REG_SIZE * 2] | 119 | mov rData, [r4 + PARAM_OFFSET + REG_SIZE * 1] |
109 | mov rNum, [r4 + REG_SIZE * 3] | 120 | mov rNum, [r4 + PARAM_OFFSET + REG_SIZE * 2] |
110 | else ; fastcall | 121 | else ; fastcall |
111 | mov rNum, [r4 + REG_SIZE * 1] | 122 | mov rNum, [r4 + PARAM_OFFSET] |
112 | endif | 123 | endif |
113 | push r5 | ||
114 | mov r5, r4 | ||
115 | and r4, -16 | 124 | and r4, -16 |
116 | sub r4, LOCAL_SIZE | 125 | sub r4, LOCAL_SIZE |
117 | endif | 126 | endif |
@@ -129,6 +138,7 @@ MY_EPILOG macro | |||
129 | else ; x86 | 138 | else ; x86 |
130 | mov r4, r5 | 139 | mov r4, r5 |
131 | pop r5 | 140 | pop r5 |
141 | pop r3 | ||
132 | endif | 142 | endif |
133 | MY_ENDP | 143 | MY_ENDP |
134 | endm | 144 | endm |
@@ -171,7 +181,7 @@ pre2 equ 2 | |||
171 | 181 | ||
172 | 182 | ||
173 | RND4 macro k | 183 | RND4 macro k |
174 | movdqa msg, xmmword ptr [K_CONST + (k) * 16] | 184 | movdqa msg, xmmword ptr [rTable + (k) * 16] |
175 | paddd msg, @CatStr(xmm, %(w_regs + ((k + 0) mod 4))) | 185 | paddd msg, @CatStr(xmm, %(w_regs + ((k + 0) mod 4))) |
176 | MY_sha256rnds2 state0_N, state1_N | 186 | MY_sha256rnds2 state0_N, state1_N |
177 | pshufd msg, msg, 0eH | 187 | pshufd msg, msg, 0eH |
@@ -210,6 +220,8 @@ endm | |||
210 | MY_PROC Sha256_UpdateBlocks_HW, 3 | 220 | MY_PROC Sha256_UpdateBlocks_HW, 3 |
211 | MY_PROLOG | 221 | MY_PROLOG |
212 | 222 | ||
223 | lea rTable, [K_CONST] | ||
224 | |||
213 | cmp rNum, 0 | 225 | cmp rNum, 0 |
214 | je end_c | 226 | je end_c |
215 | 227 | ||
diff --git a/C/7zTypes.h b/C/7zTypes.h index fe4fde3..f7d7071 100644 --- a/C/7zTypes.h +++ b/C/7zTypes.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* 7zTypes.h -- Basic types | 1 | /* 7zTypes.h -- Basic types |
2 | 2021-12-25 : Igor Pavlov : Public domain */ | 2 | 2022-04-01 : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #ifndef __7Z_TYPES_H | 4 | #ifndef __7Z_TYPES_H |
5 | #define __7Z_TYPES_H | 5 | #define __7Z_TYPES_H |
@@ -133,10 +133,6 @@ typedef int WRes; | |||
133 | #define MY__E_ERROR_NEGATIVE_SEEK MY_HRESULT_FROM_errno_CONST_ERROR(EINVAL) | 133 | #define MY__E_ERROR_NEGATIVE_SEEK MY_HRESULT_FROM_errno_CONST_ERROR(EINVAL) |
134 | */ | 134 | */ |
135 | 135 | ||
136 | // gcc / clang : (sizeof(long) == sizeof(void*)) in 32/64 bits | ||
137 | typedef long INT_PTR; | ||
138 | typedef unsigned long UINT_PTR; | ||
139 | |||
140 | #define TEXT(quote) quote | 136 | #define TEXT(quote) quote |
141 | 137 | ||
142 | #define FILE_ATTRIBUTE_READONLY 0x0001 | 138 | #define FILE_ATTRIBUTE_READONLY 0x0001 |
@@ -520,6 +516,14 @@ struct ISzAlloc | |||
520 | 516 | ||
521 | #endif | 517 | #endif |
522 | 518 | ||
519 | #define k_PropVar_TimePrec_0 0 | ||
520 | #define k_PropVar_TimePrec_Unix 1 | ||
521 | #define k_PropVar_TimePrec_DOS 2 | ||
522 | #define k_PropVar_TimePrec_HighPrec 3 | ||
523 | #define k_PropVar_TimePrec_Base 16 | ||
524 | #define k_PropVar_TimePrec_100ns (k_PropVar_TimePrec_Base + 7) | ||
525 | #define k_PropVar_TimePrec_1ns (k_PropVar_TimePrec_Base + 9) | ||
526 | |||
523 | EXTERN_C_END | 527 | EXTERN_C_END |
524 | 528 | ||
525 | #endif | 529 | #endif |
diff --git a/C/7zVersion.h b/C/7zVersion.h index e9363d3..89fffd9 100644 --- a/C/7zVersion.h +++ b/C/7zVersion.h | |||
@@ -1,7 +1,7 @@ | |||
1 | #define MY_VER_MAJOR 21 | 1 | #define MY_VER_MAJOR 22 |
2 | #define MY_VER_MINOR 07 | 2 | #define MY_VER_MINOR 00 |
3 | #define MY_VER_BUILD 0 | 3 | #define MY_VER_BUILD 0 |
4 | #define MY_VERSION_NUMBERS "21.07" | 4 | #define MY_VERSION_NUMBERS "22.00" |
5 | #define MY_VERSION MY_VERSION_NUMBERS | 5 | #define MY_VERSION MY_VERSION_NUMBERS |
6 | 6 | ||
7 | #ifdef MY_CPU_NAME | 7 | #ifdef MY_CPU_NAME |
@@ -10,12 +10,12 @@ | |||
10 | #define MY_VERSION_CPU MY_VERSION | 10 | #define MY_VERSION_CPU MY_VERSION |
11 | #endif | 11 | #endif |
12 | 12 | ||
13 | #define MY_DATE "2021-12-26" | 13 | #define MY_DATE "2022-06-15" |
14 | #undef MY_COPYRIGHT | 14 | #undef MY_COPYRIGHT |
15 | #undef MY_VERSION_COPYRIGHT_DATE | 15 | #undef MY_VERSION_COPYRIGHT_DATE |
16 | #define MY_AUTHOR_NAME "Igor Pavlov" | 16 | #define MY_AUTHOR_NAME "Igor Pavlov" |
17 | #define MY_COPYRIGHT_PD "Igor Pavlov : Public domain" | 17 | #define MY_COPYRIGHT_PD "Igor Pavlov : Public domain" |
18 | #define MY_COPYRIGHT_CR "Copyright (c) 1999-2021 Igor Pavlov" | 18 | #define MY_COPYRIGHT_CR "Copyright (c) 1999-2022 Igor Pavlov" |
19 | 19 | ||
20 | #ifdef USE_COPYRIGHT_CR | 20 | #ifdef USE_COPYRIGHT_CR |
21 | #define MY_COPYRIGHT MY_COPYRIGHT_CR | 21 | #define MY_COPYRIGHT MY_COPYRIGHT_CR |
diff --git a/CPP/7zip/7zip_gcc.mak b/CPP/7zip/7zip_gcc.mak index e2698a6..b242459 100644 --- a/CPP/7zip/7zip_gcc.mak +++ b/CPP/7zip/7zip_gcc.mak | |||
@@ -382,6 +382,8 @@ $O/VirtThread.o: ../../Common/VirtThread.cpp | |||
382 | $(CXX) $(CXXFLAGS) $< | 382 | $(CXX) $(CXXFLAGS) $< |
383 | 383 | ||
384 | 384 | ||
385 | $O/ApfsHandler.o: ../../Archive/ApfsHandler.cpp | ||
386 | $(CXX) $(CXXFLAGS) $< | ||
385 | $O/ApmHandler.o: ../../Archive/ApmHandler.cpp | 387 | $O/ApmHandler.o: ../../Archive/ApmHandler.cpp |
386 | $(CXX) $(CXXFLAGS) $< | 388 | $(CXX) $(CXXFLAGS) $< |
387 | $O/ArchiveExports.o: ../../Archive/ArchiveExports.cpp | 389 | $O/ArchiveExports.o: ../../Archive/ArchiveExports.cpp |
@@ -390,6 +392,8 @@ $O/ArHandler.o: ../../Archive/ArHandler.cpp | |||
390 | $(CXX) $(CXXFLAGS) $< | 392 | $(CXX) $(CXXFLAGS) $< |
391 | $O/ArjHandler.o: ../../Archive/ArjHandler.cpp | 393 | $O/ArjHandler.o: ../../Archive/ArjHandler.cpp |
392 | $(CXX) $(CXXFLAGS) $< | 394 | $(CXX) $(CXXFLAGS) $< |
395 | $O/AvbHandler.o: ../../Archive/AvbHandler.cpp | ||
396 | $(CXX) $(CXXFLAGS) $< | ||
393 | $O/Base64Handler.o: ../../Archive/Base64Handler.cpp | 397 | $O/Base64Handler.o: ../../Archive/Base64Handler.cpp |
394 | $(CXX) $(CXXFLAGS) $< | 398 | $(CXX) $(CXXFLAGS) $< |
395 | $O/Bz2Handler.o: ../../Archive/Bz2Handler.cpp | 399 | $O/Bz2Handler.o: ../../Archive/Bz2Handler.cpp |
@@ -426,6 +430,8 @@ $O/HfsHandler.o: ../../Archive/HfsHandler.cpp | |||
426 | $(CXX) $(CXXFLAGS) $< | 430 | $(CXX) $(CXXFLAGS) $< |
427 | $O/IhexHandler.o: ../../Archive/IhexHandler.cpp | 431 | $O/IhexHandler.o: ../../Archive/IhexHandler.cpp |
428 | $(CXX) $(CXXFLAGS) $< | 432 | $(CXX) $(CXXFLAGS) $< |
433 | $O/LpHandler.o: ../../Archive/LpHandler.cpp | ||
434 | $(CXX) $(CXXFLAGS) $< | ||
429 | $O/LzhHandler.o: ../../Archive/LzhHandler.cpp | 435 | $O/LzhHandler.o: ../../Archive/LzhHandler.cpp |
430 | $(CXX) $(CXXFLAGS) $< | 436 | $(CXX) $(CXXFLAGS) $< |
431 | $O/LzmaHandler.o: ../../Archive/LzmaHandler.cpp | 437 | $O/LzmaHandler.o: ../../Archive/LzmaHandler.cpp |
@@ -448,6 +454,8 @@ $O/QcowHandler.o: ../../Archive/QcowHandler.cpp | |||
448 | $(CXX) $(CXXFLAGS) $< | 454 | $(CXX) $(CXXFLAGS) $< |
449 | $O/RpmHandler.o: ../../Archive/RpmHandler.cpp | 455 | $O/RpmHandler.o: ../../Archive/RpmHandler.cpp |
450 | $(CXX) $(CXXFLAGS) $< | 456 | $(CXX) $(CXXFLAGS) $< |
457 | $O/SparseHandler.o: ../../Archive/SparseHandler.cpp | ||
458 | $(CXX) $(CXXFLAGS) $< | ||
451 | $O/SplitHandler.o: ../../Archive/SplitHandler.cpp | 459 | $O/SplitHandler.o: ../../Archive/SplitHandler.cpp |
452 | $(CXX) $(CXXFLAGS) $< | 460 | $(CXX) $(CXXFLAGS) $< |
453 | $O/SquashfsHandler.o: ../../Archive/SquashfsHandler.cpp | 461 | $O/SquashfsHandler.o: ../../Archive/SquashfsHandler.cpp |
diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.cpp b/CPP/7zip/Archive/7z/7zFolderInStream.cpp index a68edf4..cf50e69 100644 --- a/CPP/7zip/Archive/7z/7zFolderInStream.cpp +++ b/CPP/7zip/Archive/7z/7zFolderInStream.cpp | |||
@@ -2,6 +2,8 @@ | |||
2 | 2 | ||
3 | #include "StdAfx.h" | 3 | #include "StdAfx.h" |
4 | 4 | ||
5 | #include "../../../Windows/TimeUtils.h" | ||
6 | |||
5 | #include "7zFolderInStream.h" | 7 | #include "7zFolderInStream.h" |
6 | 8 | ||
7 | namespace NArchive { | 9 | namespace NArchive { |
@@ -13,17 +15,17 @@ void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback, | |||
13 | _updateCallback = updateCallback; | 15 | _updateCallback = updateCallback; |
14 | _indexes = indexes; | 16 | _indexes = indexes; |
15 | _numFiles = numFiles; | 17 | _numFiles = numFiles; |
16 | _index = 0; | ||
17 | 18 | ||
18 | Processed.ClearAndReserve(numFiles); | 19 | Processed.ClearAndReserve(numFiles); |
19 | CRCs.ClearAndReserve(numFiles); | 20 | CRCs.ClearAndReserve(numFiles); |
20 | Sizes.ClearAndReserve(numFiles); | 21 | Sizes.ClearAndReserve(numFiles); |
21 | |||
22 | _pos = 0; | ||
23 | _crc = CRC_INIT_VAL; | ||
24 | _size_Defined = false; | ||
25 | _size = 0; | ||
26 | 22 | ||
23 | if (Need_CTime) CTimes.ClearAndReserve(numFiles); | ||
24 | if (Need_ATime) ATimes.ClearAndReserve(numFiles); | ||
25 | if (Need_MTime) MTimes.ClearAndReserve(numFiles); | ||
26 | if (Need_Attrib) Attribs.ClearAndReserve(numFiles); | ||
27 | TimesDefined.ClearAndReserve(numFiles); | ||
28 | |||
27 | _stream.Release(); | 29 | _stream.Release(); |
28 | } | 30 | } |
29 | 31 | ||
@@ -32,44 +34,101 @@ HRESULT CFolderInStream::OpenStream() | |||
32 | _pos = 0; | 34 | _pos = 0; |
33 | _crc = CRC_INIT_VAL; | 35 | _crc = CRC_INIT_VAL; |
34 | _size_Defined = false; | 36 | _size_Defined = false; |
37 | _times_Defined = false; | ||
35 | _size = 0; | 38 | _size = 0; |
39 | FILETIME_Clear(_cTime); | ||
40 | FILETIME_Clear(_aTime); | ||
41 | FILETIME_Clear(_mTime); | ||
42 | _attrib = 0; | ||
36 | 43 | ||
37 | while (_index < _numFiles) | 44 | while (Processed.Size() < _numFiles) |
38 | { | 45 | { |
39 | CMyComPtr<ISequentialInStream> stream; | 46 | CMyComPtr<ISequentialInStream> stream; |
40 | HRESULT result = _updateCallback->GetStream(_indexes[_index], &stream); | 47 | const HRESULT result = _updateCallback->GetStream(_indexes[Processed.Size()], &stream); |
41 | if (result != S_OK) | 48 | if (result != S_OK && result != S_FALSE) |
42 | { | 49 | return result; |
43 | if (result != S_FALSE) | ||
44 | return result; | ||
45 | } | ||
46 | 50 | ||
47 | _stream = stream; | 51 | _stream = stream; |
48 | 52 | ||
49 | if (stream) | 53 | if (stream) |
50 | { | 54 | { |
51 | CMyComPtr<IStreamGetSize> streamGetSize; | ||
52 | stream.QueryInterface(IID_IStreamGetSize, &streamGetSize); | ||
53 | if (streamGetSize) | ||
54 | { | 55 | { |
55 | if (streamGetSize->GetSize(&_size) == S_OK) | 56 | CMyComPtr<IStreamGetProps> getProps; |
56 | _size_Defined = true; | 57 | stream.QueryInterface(IID_IStreamGetProps, (void **)&getProps); |
58 | if (getProps) | ||
59 | { | ||
60 | // access could be changed in first myx pass | ||
61 | if (getProps->GetProps(&_size, | ||
62 | Need_CTime ? &_cTime : NULL, | ||
63 | Need_ATime ? &_aTime : NULL, | ||
64 | Need_MTime ? &_mTime : NULL, | ||
65 | Need_Attrib ? &_attrib : NULL) | ||
66 | == S_OK) | ||
67 | { | ||
68 | _size_Defined = true; | ||
69 | _times_Defined = true; | ||
70 | } | ||
71 | return S_OK; | ||
72 | } | ||
73 | } | ||
74 | { | ||
75 | CMyComPtr<IStreamGetSize> streamGetSize; | ||
76 | stream.QueryInterface(IID_IStreamGetSize, &streamGetSize); | ||
77 | if (streamGetSize) | ||
78 | { | ||
79 | if (streamGetSize->GetSize(&_size) == S_OK) | ||
80 | _size_Defined = true; | ||
81 | } | ||
82 | return S_OK; | ||
57 | } | 83 | } |
58 | return S_OK; | ||
59 | } | 84 | } |
60 | 85 | ||
61 | _index++; | 86 | RINOK(AddFileInfo(result == S_OK)); |
62 | RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); | ||
63 | AddFileInfo(result == S_OK); | ||
64 | } | 87 | } |
65 | return S_OK; | 88 | return S_OK; |
66 | } | 89 | } |
67 | 90 | ||
68 | void CFolderInStream::AddFileInfo(bool isProcessed) | 91 | static void AddFt(CRecordVector<UInt64> &vec, const FILETIME &ft) |
69 | { | 92 | { |
70 | Processed.Add(isProcessed); | 93 | vec.AddInReserved(FILETIME_To_UInt64(ft)); |
71 | Sizes.Add(_pos); | 94 | } |
72 | CRCs.Add(CRC_GET_DIGEST(_crc)); | 95 | |
96 | /* | ||
97 | HRESULT ReportItemProps(IArchiveUpdateCallbackArcProp *reportArcProp, | ||
98 | UInt32 index, UInt64 size, const UInt32 *crc) | ||
99 | { | ||
100 | PROPVARIANT prop; | ||
101 | prop.vt = VT_EMPTY; | ||
102 | prop.wReserved1 = 0; | ||
103 | |||
104 | NWindows::NCOM::PropVarEm_Set_UInt64(&prop, size); | ||
105 | RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidSize, &prop)); | ||
106 | if (crc) | ||
107 | { | ||
108 | NWindows::NCOM::PropVarEm_Set_UInt32(&prop, *crc); | ||
109 | RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidCRC, &prop)); | ||
110 | } | ||
111 | return reportArcProp->ReportFinished(NEventIndexType::kOutArcIndex, index, NUpdate::NOperationResult::kOK); | ||
112 | } | ||
113 | */ | ||
114 | |||
115 | HRESULT CFolderInStream::AddFileInfo(bool isProcessed) | ||
116 | { | ||
117 | // const UInt32 index = _indexes[Processed.Size()]; | ||
118 | Processed.AddInReserved(isProcessed); | ||
119 | Sizes.AddInReserved(_pos); | ||
120 | const UInt32 crc = CRC_GET_DIGEST(_crc); | ||
121 | CRCs.AddInReserved(crc); | ||
122 | TimesDefined.AddInReserved(_times_Defined); | ||
123 | if (Need_CTime) AddFt(CTimes, _cTime); | ||
124 | if (Need_ATime) AddFt(ATimes, _aTime); | ||
125 | if (Need_MTime) AddFt(MTimes, _mTime); | ||
126 | if (Need_Attrib) Attribs.AddInReserved(_attrib); | ||
127 | /* | ||
128 | if (isProcessed && _reportArcProp) | ||
129 | RINOK(ReportItemProps(_reportArcProp, index, _pos, &crc)) | ||
130 | */ | ||
131 | return _updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); | ||
73 | } | 132 | } |
74 | 133 | ||
75 | STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) | 134 | STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) |
@@ -95,18 +154,10 @@ STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSiz | |||
95 | } | 154 | } |
96 | 155 | ||
97 | _stream.Release(); | 156 | _stream.Release(); |
98 | _index++; | 157 | RINOK(AddFileInfo(true)); |
99 | AddFileInfo(true); | ||
100 | |||
101 | _pos = 0; | ||
102 | _crc = CRC_INIT_VAL; | ||
103 | _size_Defined = false; | ||
104 | _size = 0; | ||
105 | |||
106 | RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); | ||
107 | } | 158 | } |
108 | 159 | ||
109 | if (_index >= _numFiles) | 160 | if (Processed.Size() >= _numFiles) |
110 | break; | 161 | break; |
111 | RINOK(OpenStream()); | 162 | RINOK(OpenStream()); |
112 | } | 163 | } |
diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.h b/CPP/7zip/Archive/7z/7zFolderInStream.h index 805db54..f054e68 100644 --- a/CPP/7zip/Archive/7z/7zFolderInStream.h +++ b/CPP/7zip/Archive/7z/7zFolderInStream.h | |||
@@ -23,21 +23,37 @@ class CFolderInStream: | |||
23 | UInt64 _pos; | 23 | UInt64 _pos; |
24 | UInt32 _crc; | 24 | UInt32 _crc; |
25 | bool _size_Defined; | 25 | bool _size_Defined; |
26 | bool _times_Defined; | ||
26 | UInt64 _size; | 27 | UInt64 _size; |
28 | FILETIME _cTime; | ||
29 | FILETIME _aTime; | ||
30 | FILETIME _mTime; | ||
31 | UInt32 _attrib; | ||
27 | 32 | ||
28 | const UInt32 *_indexes; | ||
29 | unsigned _numFiles; | 33 | unsigned _numFiles; |
30 | unsigned _index; | 34 | const UInt32 *_indexes; |
31 | 35 | ||
32 | CMyComPtr<IArchiveUpdateCallback> _updateCallback; | 36 | CMyComPtr<IArchiveUpdateCallback> _updateCallback; |
33 | 37 | ||
34 | HRESULT OpenStream(); | 38 | HRESULT OpenStream(); |
35 | void AddFileInfo(bool isProcessed); | 39 | HRESULT AddFileInfo(bool isProcessed); |
36 | 40 | ||
37 | public: | 41 | public: |
38 | CRecordVector<bool> Processed; | 42 | CRecordVector<bool> Processed; |
39 | CRecordVector<UInt32> CRCs; | 43 | CRecordVector<UInt32> CRCs; |
40 | CRecordVector<UInt64> Sizes; | 44 | CRecordVector<UInt64> Sizes; |
45 | CRecordVector<UInt64> CTimes; | ||
46 | CRecordVector<UInt64> ATimes; | ||
47 | CRecordVector<UInt64> MTimes; | ||
48 | CRecordVector<UInt32> Attribs; | ||
49 | CRecordVector<bool> TimesDefined; | ||
50 | |||
51 | bool Need_CTime; | ||
52 | bool Need_ATime; | ||
53 | bool Need_MTime; | ||
54 | bool Need_Attrib; | ||
55 | |||
56 | // CMyComPtr<IArchiveUpdateCallbackArcProp> _reportArcProp; | ||
41 | 57 | ||
42 | MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize) | 58 | MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize) |
43 | STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); | 59 | STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); |
@@ -45,7 +61,7 @@ public: | |||
45 | 61 | ||
46 | void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *indexes, unsigned numFiles); | 62 | void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *indexes, unsigned numFiles); |
47 | 63 | ||
48 | bool WasFinished() const { return _index == _numFiles; } | 64 | bool WasFinished() const { return Processed.Size() == _numFiles; } |
49 | 65 | ||
50 | UInt64 GetFullSize() const | 66 | UInt64 GetFullSize() const |
51 | { | 67 | { |
@@ -54,6 +70,13 @@ public: | |||
54 | size += Sizes[i]; | 70 | size += Sizes[i]; |
55 | return size; | 71 | return size; |
56 | } | 72 | } |
73 | |||
74 | CFolderInStream(): | ||
75 | Need_CTime(false), | ||
76 | Need_ATime(false), | ||
77 | Need_MTime(false), | ||
78 | Need_Attrib(false) | ||
79 | {} | ||
57 | }; | 80 | }; |
58 | 81 | ||
59 | }} | 82 | }} |
diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp index 9e344c3..ca22f88 100644 --- a/CPP/7zip/Archive/7z/7zHandler.cpp +++ b/CPP/7zip/Archive/7z/7zHandler.cpp | |||
@@ -278,7 +278,7 @@ static void SetFileTimeProp_From_UInt64Def(PROPVARIANT *prop, const CUInt64DefVe | |||
278 | { | 278 | { |
279 | UInt64 value; | 279 | UInt64 value; |
280 | if (v.GetItem(index, value)) | 280 | if (v.GetItem(index, value)) |
281 | PropVarEm_Set_FileTime64(prop, value); | 281 | PropVarEm_Set_FileTime64_Prec(prop, value, k_PropVar_TimePrec_100ns); |
282 | } | 282 | } |
283 | 283 | ||
284 | bool CHandler::IsFolderEncrypted(CNum folderIndex) const | 284 | bool CHandler::IsFolderEncrypted(CNum folderIndex) const |
diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h index cbc2d02..08bd654 100644 --- a/CPP/7zip/Archive/7z/7zHandler.h +++ b/CPP/7zip/Archive/7z/7zHandler.h | |||
@@ -49,9 +49,8 @@ public: | |||
49 | bool _encryptHeaders; | 49 | bool _encryptHeaders; |
50 | // bool _useParents; 9.26 | 50 | // bool _useParents; 9.26 |
51 | 51 | ||
52 | CBoolPair Write_CTime; | 52 | CHandlerTimeOptions TimeOptions; |
53 | CBoolPair Write_ATime; | 53 | |
54 | CBoolPair Write_MTime; | ||
55 | CBoolPair Write_Attrib; | 54 | CBoolPair Write_Attrib; |
56 | 55 | ||
57 | bool _useMultiThreadMixer; | 56 | bool _useMultiThreadMixer; |
diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp index 8f875ce..bf4e7a6 100644 --- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp +++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp | |||
@@ -384,16 +384,16 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
384 | 384 | ||
385 | CObjectVector<CUpdateItem> updateItems; | 385 | CObjectVector<CUpdateItem> updateItems; |
386 | 386 | ||
387 | bool need_CTime = (Write_CTime.Def && Write_CTime.Val); | 387 | bool need_CTime = (TimeOptions.Write_CTime.Def && TimeOptions.Write_CTime.Val); |
388 | bool need_ATime = (Write_ATime.Def && Write_ATime.Val); | 388 | bool need_ATime = (TimeOptions.Write_ATime.Def && TimeOptions.Write_ATime.Val); |
389 | bool need_MTime = (Write_MTime.Def ? Write_MTime.Val : true); | 389 | bool need_MTime = (TimeOptions.Write_MTime.Def ? TimeOptions.Write_MTime.Val : true); |
390 | bool need_Attrib = (Write_Attrib.Def ? Write_Attrib.Val : true); | 390 | bool need_Attrib = (Write_Attrib.Def ? Write_Attrib.Val : true); |
391 | 391 | ||
392 | if (db && !db->Files.IsEmpty()) | 392 | if (db && !db->Files.IsEmpty()) |
393 | { | 393 | { |
394 | if (!Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty(); | 394 | if (!TimeOptions.Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty(); |
395 | if (!Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty(); | 395 | if (!TimeOptions.Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty(); |
396 | if (!Write_MTime.Def) need_MTime = !db->MTime.Defs.IsEmpty(); | 396 | if (!TimeOptions.Write_MTime.Def) need_MTime = !db->MTime.Defs.IsEmpty(); |
397 | if (!Write_Attrib.Def) need_Attrib = !db->Attrib.Defs.IsEmpty(); | 397 | if (!Write_Attrib.Def) need_Attrib = !db->Attrib.Defs.IsEmpty(); |
398 | } | 398 | } |
399 | 399 | ||
@@ -719,6 +719,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
719 | int level = GetLevel(); | 719 | int level = GetLevel(); |
720 | 720 | ||
721 | CUpdateOptions options; | 721 | CUpdateOptions options; |
722 | options.Need_CTime = need_CTime; | ||
723 | options.Need_ATime = need_ATime; | ||
724 | options.Need_MTime = need_MTime; | ||
725 | options.Need_Attrib = need_Attrib; | ||
726 | |||
722 | options.Method = &methodMode; | 727 | options.Method = &methodMode; |
723 | options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : NULL; | 728 | options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : NULL; |
724 | options.UseFilters = (level != 0 && _autoFilter && !methodMode.Filter_was_Inserted); | 729 | options.UseFilters = (level != 0 && _autoFilter && !methodMode.Filter_was_Inserted); |
@@ -817,9 +822,7 @@ void COutHandler::InitProps7z() | |||
817 | _encryptHeaders = false; | 822 | _encryptHeaders = false; |
818 | // _useParents = false; | 823 | // _useParents = false; |
819 | 824 | ||
820 | Write_CTime.Init(); | 825 | TimeOptions.Init(); |
821 | Write_ATime.Init(); | ||
822 | Write_MTime.Init(); | ||
823 | Write_Attrib.Init(); | 826 | Write_Attrib.Init(); |
824 | 827 | ||
825 | _useMultiThreadMixer = true; | 828 | _useMultiThreadMixer = true; |
@@ -954,10 +957,20 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val | |||
954 | return S_OK; | 957 | return S_OK; |
955 | } | 958 | } |
956 | 959 | ||
957 | if (name.IsEqualTo("tc")) return PROPVARIANT_to_BoolPair(value, Write_CTime); | 960 | { |
958 | if (name.IsEqualTo("ta")) return PROPVARIANT_to_BoolPair(value, Write_ATime); | 961 | bool processed; |
959 | if (name.IsEqualTo("tm")) return PROPVARIANT_to_BoolPair(value, Write_MTime); | 962 | RINOK(TimeOptions.Parse(name, value, processed)); |
960 | 963 | if (processed) | |
964 | { | ||
965 | if ( TimeOptions.Prec != (UInt32)(Int32)-1 | ||
966 | && TimeOptions.Prec != k_PropVar_TimePrec_0 | ||
967 | && TimeOptions.Prec != k_PropVar_TimePrec_HighPrec | ||
968 | && TimeOptions.Prec != k_PropVar_TimePrec_100ns) | ||
969 | return E_INVALIDARG; | ||
970 | return S_OK; | ||
971 | } | ||
972 | } | ||
973 | |||
961 | if (name.IsEqualTo("tr")) return PROPVARIANT_to_BoolPair(value, Write_Attrib); | 974 | if (name.IsEqualTo("tr")) return PROPVARIANT_to_BoolPair(value, Write_Attrib); |
962 | 975 | ||
963 | if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer); | 976 | if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer); |
diff --git a/CPP/7zip/Archive/7z/7zRegister.cpp b/CPP/7zip/Archive/7z/7zRegister.cpp index 389b540..eac8b4f 100644 --- a/CPP/7zip/Archive/7z/7zRegister.cpp +++ b/CPP/7zip/Archive/7z/7zRegister.cpp | |||
@@ -15,7 +15,13 @@ REGISTER_ARC_IO_DECREMENT_SIG( | |||
15 | "7z", "7z", NULL, 7, | 15 | "7z", "7z", NULL, 7, |
16 | k_Signature_Dec, | 16 | k_Signature_Dec, |
17 | 0, | 17 | 0, |
18 | NArcInfoFlags::kFindSignature, | 18 | NArcInfoFlags::kFindSignature |
19 | NULL); | 19 | | NArcInfoFlags::kCTime |
20 | | NArcInfoFlags::kATime | ||
21 | | NArcInfoFlags::kMTime | ||
22 | | NArcInfoFlags::kMTime_Default | ||
23 | , TIME_PREC_TO_ARC_FLAGS_MASK(NFileTimeType::kWindows) | ||
24 | | TIME_PREC_TO_ARC_FLAGS_TIME_DEFAULT(NFileTimeType::kWindows) | ||
25 | , NULL); | ||
20 | 26 | ||
21 | }} | 27 | }} |
diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp index b641d93..b6fd192 100644 --- a/CPP/7zip/Archive/7z/7zUpdate.cpp +++ b/CPP/7zip/Archive/7z/7zUpdate.cpp | |||
@@ -804,10 +804,20 @@ struct CAnalysis | |||
804 | bool ParseExe; | 804 | bool ParseExe; |
805 | bool ParseAll; | 805 | bool ParseAll; |
806 | 806 | ||
807 | /* | ||
808 | bool Need_ATime; | ||
809 | bool ATime_Defined; | ||
810 | FILETIME ATime; | ||
811 | */ | ||
812 | |||
807 | CAnalysis(): | 813 | CAnalysis(): |
808 | ParseWav(true), | 814 | ParseWav(true), |
809 | ParseExe(false), | 815 | ParseExe(false), |
810 | ParseAll(false) | 816 | ParseAll(false) |
817 | /* | ||
818 | , Need_ATime(false) | ||
819 | , ATime_Defined(false) | ||
820 | */ | ||
811 | {} | 821 | {} |
812 | 822 | ||
813 | HRESULT GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMode &filterMode); | 823 | HRESULT GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMode &filterMode); |
@@ -887,6 +897,18 @@ HRESULT CAnalysis::GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMo | |||
887 | HRESULT result = Callback->GetStream2(index, &stream, NUpdateNotifyOp::kAnalyze); | 897 | HRESULT result = Callback->GetStream2(index, &stream, NUpdateNotifyOp::kAnalyze); |
888 | if (result == S_OK && stream) | 898 | if (result == S_OK && stream) |
889 | { | 899 | { |
900 | /* | ||
901 | if (Need_ATime) | ||
902 | { | ||
903 | // access time could be changed in analysis pass | ||
904 | CMyComPtr<IStreamGetProps> getProps; | ||
905 | stream.QueryInterface(IID_IStreamGetProps, (void **)&getProps); | ||
906 | if (getProps) | ||
907 | if (getProps->GetProps(NULL, NULL, &ATime, NULL, NULL) == S_OK) | ||
908 | ATime_Defined = true; | ||
909 | } | ||
910 | */ | ||
911 | |||
890 | size_t size = kAnalysisBufSize; | 912 | size_t size = kAnalysisBufSize; |
891 | result = ReadStream(stream, Buffer, &size); | 913 | result = ReadStream(stream, Buffer, &size); |
892 | stream.Release(); | 914 | stream.Release(); |
@@ -1586,6 +1608,11 @@ HRESULT Update( | |||
1586 | CMyComPtr<IArchiveExtractCallbackMessage> extractCallback; | 1608 | CMyComPtr<IArchiveExtractCallbackMessage> extractCallback; |
1587 | updateCallback->QueryInterface(IID_IArchiveExtractCallbackMessage, (void **)&extractCallback); | 1609 | updateCallback->QueryInterface(IID_IArchiveExtractCallbackMessage, (void **)&extractCallback); |
1588 | 1610 | ||
1611 | /* | ||
1612 | CMyComPtr<IArchiveUpdateCallbackArcProp> reportArcProp; | ||
1613 | updateCallback->QueryInterface(IID_IArchiveUpdateCallbackArcProp, (void **)&reportArcProp); | ||
1614 | */ | ||
1615 | |||
1589 | // size_t totalSecureDataSize = (size_t)secureBlocks.GetTotalSizeInBytes(); | 1616 | // size_t totalSecureDataSize = (size_t)secureBlocks.GetTotalSizeInBytes(); |
1590 | 1617 | ||
1591 | /* | 1618 | /* |
@@ -1756,6 +1783,7 @@ HRESULT Update( | |||
1756 | 1783 | ||
1757 | { | 1784 | { |
1758 | CAnalysis analysis; | 1785 | CAnalysis analysis; |
1786 | // analysis.Need_ATime = options.Need_ATime; | ||
1759 | if (options.AnalysisLevel == 0) | 1787 | if (options.AnalysisLevel == 0) |
1760 | { | 1788 | { |
1761 | analysis.ParseWav = false; | 1789 | analysis.ParseWav = false; |
@@ -1790,7 +1818,15 @@ HRESULT Update( | |||
1790 | CFilterMode2 fm; | 1818 | CFilterMode2 fm; |
1791 | if (useFilters) | 1819 | if (useFilters) |
1792 | { | 1820 | { |
1821 | // analysis.ATime_Defined = false; | ||
1793 | RINOK(analysis.GetFilterGroup(i, ui, fm)); | 1822 | RINOK(analysis.GetFilterGroup(i, ui, fm)); |
1823 | /* | ||
1824 | if (analysis.ATime_Defined) | ||
1825 | { | ||
1826 | ui.ATime = FILETIME_To_UInt64(analysis.ATime); | ||
1827 | ui.ATime_WasReadByAnalysis = true; | ||
1828 | } | ||
1829 | */ | ||
1794 | } | 1830 | } |
1795 | fm.Encrypted = method.PasswordIsDefined; | 1831 | fm.Encrypted = method.PasswordIsDefined; |
1796 | 1832 | ||
@@ -2374,13 +2410,33 @@ HRESULT Update( | |||
2374 | 2410 | ||
2375 | RINOK(lps->SetCur()); | 2411 | RINOK(lps->SetCur()); |
2376 | 2412 | ||
2413 | /* | ||
2414 | const unsigned folderIndex = newDatabase.NumUnpackStreamsVector.Size(); | ||
2415 | |||
2416 | if (opCallback) | ||
2417 | { | ||
2418 | RINOK(opCallback->ReportOperation( | ||
2419 | NEventIndexType::kBlockIndex, (UInt32)folderIndex, | ||
2420 | NUpdateNotifyOp::kAdd)); | ||
2421 | } | ||
2422 | */ | ||
2423 | |||
2424 | |||
2377 | CFolderInStream *inStreamSpec = new CFolderInStream; | 2425 | CFolderInStream *inStreamSpec = new CFolderInStream; |
2378 | CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec); | 2426 | CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec); |
2427 | |||
2428 | // inStreamSpec->_reportArcProp = reportArcProp; | ||
2429 | |||
2430 | inStreamSpec->Need_CTime = options.Need_CTime; | ||
2431 | inStreamSpec->Need_ATime = options.Need_ATime; | ||
2432 | inStreamSpec->Need_MTime = options.Need_MTime; | ||
2433 | inStreamSpec->Need_Attrib = options.Need_Attrib; | ||
2434 | |||
2379 | inStreamSpec->Init(updateCallback, &indices[i], numSubFiles); | 2435 | inStreamSpec->Init(updateCallback, &indices[i], numSubFiles); |
2380 | 2436 | ||
2381 | unsigned startPackIndex = newDatabase.PackSizes.Size(); | 2437 | unsigned startPackIndex = newDatabase.PackSizes.Size(); |
2382 | UInt64 curFolderUnpackSize = totalSize; | 2438 | UInt64 curFolderUnpackSize = totalSize; |
2383 | // curFolderUnpackSize = (UInt64)(Int64)-1; | 2439 | // curFolderUnpackSize = (UInt64)(Int64)-1; // for debug |
2384 | 2440 | ||
2385 | RINOK(encoder.Encode( | 2441 | RINOK(encoder.Encode( |
2386 | EXTERNAL_CODECS_LOC_VARS | 2442 | EXTERNAL_CODECS_LOC_VARS |
@@ -2393,8 +2449,11 @@ HRESULT Update( | |||
2393 | if (!inStreamSpec->WasFinished()) | 2449 | if (!inStreamSpec->WasFinished()) |
2394 | return E_FAIL; | 2450 | return E_FAIL; |
2395 | 2451 | ||
2452 | UInt64 packSize = 0; | ||
2453 | // const UInt32 numStreams = newDatabase.PackSizes.Size() - startPackIndex; | ||
2396 | for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) | 2454 | for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) |
2397 | lps->OutSize += newDatabase.PackSizes[startPackIndex]; | 2455 | packSize += newDatabase.PackSizes[startPackIndex]; |
2456 | lps->OutSize += packSize; | ||
2398 | 2457 | ||
2399 | lps->InSize += curFolderUnpackSize; | 2458 | lps->InSize += curFolderUnpackSize; |
2400 | // for () | 2459 | // for () |
@@ -2403,7 +2462,9 @@ HRESULT Update( | |||
2403 | 2462 | ||
2404 | CNum numUnpackStreams = 0; | 2463 | CNum numUnpackStreams = 0; |
2405 | UInt64 skippedSize = 0; | 2464 | UInt64 skippedSize = 0; |
2406 | 2465 | UInt64 procSize = 0; | |
2466 | // unsigned numProcessedFiles = 0; | ||
2467 | |||
2407 | for (unsigned subIndex = 0; subIndex < numSubFiles; subIndex++) | 2468 | for (unsigned subIndex = 0; subIndex < numSubFiles; subIndex++) |
2408 | { | 2469 | { |
2409 | const CUpdateItem &ui = updateItems[indices[i + subIndex]]; | 2470 | const CUpdateItem &ui = updateItems[indices[i + subIndex]]; |
@@ -2429,14 +2490,16 @@ HRESULT Update( | |||
2429 | */ | 2490 | */ |
2430 | if (!inStreamSpec->Processed[subIndex]) | 2491 | if (!inStreamSpec->Processed[subIndex]) |
2431 | { | 2492 | { |
2493 | // we don't add file here | ||
2432 | skippedSize += ui.Size; | 2494 | skippedSize += ui.Size; |
2433 | continue; | 2495 | continue; // comment it for debug |
2434 | // file.Name += ".locked"; | 2496 | // name += ".locked"; // for debug |
2435 | } | 2497 | } |
2436 | 2498 | ||
2437 | file.Crc = inStreamSpec->CRCs[subIndex]; | 2499 | file.Crc = inStreamSpec->CRCs[subIndex]; |
2438 | file.Size = inStreamSpec->Sizes[subIndex]; | 2500 | file.Size = inStreamSpec->Sizes[subIndex]; |
2439 | 2501 | ||
2502 | procSize += file.Size; | ||
2440 | // if (file.Size >= 0) // test purposes | 2503 | // if (file.Size >= 0) // test purposes |
2441 | if (file.Size != 0) | 2504 | if (file.Size != 0) |
2442 | { | 2505 | { |
@@ -2450,6 +2513,23 @@ HRESULT Update( | |||
2450 | file.HasStream = false; | 2513 | file.HasStream = false; |
2451 | } | 2514 | } |
2452 | 2515 | ||
2516 | if (inStreamSpec->TimesDefined[subIndex]) | ||
2517 | { | ||
2518 | if (inStreamSpec->Need_CTime) | ||
2519 | { file2.CTimeDefined = true; file2.CTime = inStreamSpec->CTimes[subIndex]; } | ||
2520 | if (inStreamSpec->Need_ATime | ||
2521 | // && !ui.ATime_WasReadByAnalysis | ||
2522 | ) | ||
2523 | { file2.ATimeDefined = true; file2.ATime = inStreamSpec->ATimes[subIndex]; } | ||
2524 | if (inStreamSpec->Need_MTime) | ||
2525 | { file2.MTimeDefined = true; file2.MTime = inStreamSpec->MTimes[subIndex]; } | ||
2526 | if (inStreamSpec->Need_Attrib) | ||
2527 | { | ||
2528 | file2.AttribDefined = true; | ||
2529 | file2.Attrib = inStreamSpec->Attribs[subIndex]; | ||
2530 | } | ||
2531 | } | ||
2532 | |||
2453 | /* | 2533 | /* |
2454 | file.Parent = ui.ParentFolderIndex; | 2534 | file.Parent = ui.ParentFolderIndex; |
2455 | if (ui.TreeFolderIndex >= 0) | 2535 | if (ui.TreeFolderIndex >= 0) |
@@ -2457,9 +2537,22 @@ HRESULT Update( | |||
2457 | if (totalSecureDataSize != 0) | 2537 | if (totalSecureDataSize != 0) |
2458 | newDatabase.SecureIDs.Add(ui.SecureIndex); | 2538 | newDatabase.SecureIDs.Add(ui.SecureIndex); |
2459 | */ | 2539 | */ |
2540 | /* | ||
2541 | if (reportArcProp) | ||
2542 | { | ||
2543 | RINOK(ReportItemProps(reportArcProp, ui.IndexInClient, file.Size, | ||
2544 | file.CrcDefined ? &file.Crc : NULL)) | ||
2545 | } | ||
2546 | */ | ||
2547 | |||
2548 | // numProcessedFiles++; | ||
2460 | newDatabase.AddFile(file, file2, name); | 2549 | newDatabase.AddFile(file, file2, name); |
2461 | } | 2550 | } |
2462 | 2551 | ||
2552 | // it's optional check to ensure that sizes are correct | ||
2553 | if (procSize != curFolderUnpackSize) | ||
2554 | return E_FAIL; | ||
2555 | |||
2463 | // numUnpackStreams = 0 is very bad case for locked files | 2556 | // numUnpackStreams = 0 is very bad case for locked files |
2464 | // v3.13 doesn't understand it. | 2557 | // v3.13 doesn't understand it. |
2465 | newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams); | 2558 | newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams); |
@@ -2470,6 +2563,44 @@ HRESULT Update( | |||
2470 | complexity -= skippedSize; | 2563 | complexity -= skippedSize; |
2471 | RINOK(updateCallback->SetTotal(complexity)); | 2564 | RINOK(updateCallback->SetTotal(complexity)); |
2472 | } | 2565 | } |
2566 | |||
2567 | /* | ||
2568 | if (reportArcProp) | ||
2569 | { | ||
2570 | PROPVARIANT prop; | ||
2571 | prop.vt = VT_EMPTY; | ||
2572 | prop.wReserved1 = 0; | ||
2573 | { | ||
2574 | NWindows::NCOM::PropVarEm_Set_UInt32(&prop, numProcessedFiles); | ||
2575 | RINOK(reportArcProp->ReportProp( | ||
2576 | NEventIndexType::kBlockIndex, (UInt32)folderIndex, kpidNumSubFiles, &prop)); | ||
2577 | } | ||
2578 | { | ||
2579 | NWindows::NCOM::PropVarEm_Set_UInt64(&prop, curFolderUnpackSize); | ||
2580 | RINOK(reportArcProp->ReportProp( | ||
2581 | NEventIndexType::kBlockIndex, (UInt32)folderIndex, kpidSize, &prop)); | ||
2582 | } | ||
2583 | { | ||
2584 | NWindows::NCOM::PropVarEm_Set_UInt64(&prop, packSize); | ||
2585 | RINOK(reportArcProp->ReportProp( | ||
2586 | NEventIndexType::kBlockIndex, (UInt32)folderIndex, kpidPackSize, &prop)); | ||
2587 | } | ||
2588 | { | ||
2589 | NWindows::NCOM::PropVarEm_Set_UInt32(&prop, numStreams); | ||
2590 | RINOK(reportArcProp->ReportProp( | ||
2591 | NEventIndexType::kBlockIndex, (UInt32)folderIndex, kpidNumStreams, &prop)); | ||
2592 | } | ||
2593 | RINOK(reportArcProp->ReportFinished(NEventIndexType::kBlockIndex, (UInt32)folderIndex, NUpdate::NOperationResult::kOK)); | ||
2594 | } | ||
2595 | */ | ||
2596 | /* | ||
2597 | if (opCallback) | ||
2598 | { | ||
2599 | RINOK(opCallback->ReportOperation( | ||
2600 | NEventIndexType::kBlockIndex, (UInt32)folderIndex, | ||
2601 | NUpdateNotifyOp::kOpFinished)); | ||
2602 | } | ||
2603 | */ | ||
2473 | } | 2604 | } |
2474 | } | 2605 | } |
2475 | 2606 | ||
diff --git a/CPP/7zip/Archive/7z/7zUpdate.h b/CPP/7zip/Archive/7z/7zUpdate.h index 7c0f78a..e6c48ca 100644 --- a/CPP/7zip/Archive/7z/7zUpdate.h +++ b/CPP/7zip/Archive/7z/7zUpdate.h | |||
@@ -62,6 +62,8 @@ struct CUpdateItem | |||
62 | bool ATimeDefined; | 62 | bool ATimeDefined; |
63 | bool MTimeDefined; | 63 | bool MTimeDefined; |
64 | 64 | ||
65 | // bool ATime_WasReadByAnalysis; | ||
66 | |||
65 | // int SecureIndex; // 0 means (no_security) | 67 | // int SecureIndex; // 0 means (no_security) |
66 | 68 | ||
67 | bool HasStream() const { return !IsDir && !IsAnti && Size != 0; } | 69 | bool HasStream() const { return !IsDir && !IsAnti && Size != 0; } |
@@ -76,6 +78,7 @@ struct CUpdateItem | |||
76 | CTimeDefined(false), | 78 | CTimeDefined(false), |
77 | ATimeDefined(false), | 79 | ATimeDefined(false), |
78 | MTimeDefined(false) | 80 | MTimeDefined(false) |
81 | // , ATime_WasReadByAnalysis(false) | ||
79 | // SecureIndex(0) | 82 | // SecureIndex(0) |
80 | {} | 83 | {} |
81 | void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); } | 84 | void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); } |
@@ -103,6 +106,11 @@ struct CUpdateOptions | |||
103 | bool RemoveSfxBlock; | 106 | bool RemoveSfxBlock; |
104 | bool MultiThreadMixer; | 107 | bool MultiThreadMixer; |
105 | 108 | ||
109 | bool Need_CTime; | ||
110 | bool Need_ATime; | ||
111 | bool Need_MTime; | ||
112 | bool Need_Attrib; | ||
113 | |||
106 | CUpdateOptions(): | 114 | CUpdateOptions(): |
107 | Method(NULL), | 115 | Method(NULL), |
108 | HeaderMethod(NULL), | 116 | HeaderMethod(NULL), |
@@ -114,7 +122,11 @@ struct CUpdateOptions | |||
114 | SolidExtension(false), | 122 | SolidExtension(false), |
115 | UseTypeSorting(true), | 123 | UseTypeSorting(true), |
116 | RemoveSfxBlock(false), | 124 | RemoveSfxBlock(false), |
117 | MultiThreadMixer(true) | 125 | MultiThreadMixer(true), |
126 | Need_CTime(false), | ||
127 | Need_ATime(false), | ||
128 | Need_MTime(false), | ||
129 | Need_Attrib(false) | ||
118 | {} | 130 | {} |
119 | }; | 131 | }; |
120 | 132 | ||
diff --git a/CPP/7zip/Archive/ApfsHandler.cpp b/CPP/7zip/Archive/ApfsHandler.cpp new file mode 100644 index 0000000..8312456 --- /dev/null +++ b/CPP/7zip/Archive/ApfsHandler.cpp | |||
@@ -0,0 +1,3546 @@ | |||
1 | // ApfsHandler.cpp | ||
2 | |||
3 | #include "StdAfx.h" | ||
4 | |||
5 | // #define SHOW_DEBUG_INFO | ||
6 | |||
7 | #ifdef SHOW_DEBUG_INFO | ||
8 | #include <stdio.h> | ||
9 | #define PRF(x) x | ||
10 | #else | ||
11 | #define PRF(x) | ||
12 | #endif | ||
13 | |||
14 | #include "../../../C/CpuArch.h" | ||
15 | |||
16 | #include "../../Common/ComTry.h" | ||
17 | #include "../../Common/IntToString.h" | ||
18 | #include "../../Common/MyLinux.h" | ||
19 | #include "../../Common/UTFConvert.h" | ||
20 | |||
21 | #include "../../Windows/PropVariantConv.h" | ||
22 | #include "../../Windows/PropVariantUtils.h" | ||
23 | #include "../../Windows/TimeUtils.h" | ||
24 | |||
25 | #include "../Common/LimitedStreams.h" | ||
26 | #include "../Common/ProgressUtils.h" | ||
27 | #include "../Common/RegisterArc.h" | ||
28 | #include "../Common/StreamObjects.h" | ||
29 | #include "../Common/StreamUtils.h" | ||
30 | |||
31 | #include "../Compress/CopyCoder.h" | ||
32 | |||
33 | #include "Common/ItemNameUtils.h" | ||
34 | |||
35 | // if APFS_SHOW_ALT_STREAMS is defined, the handler will show attribute files. | ||
36 | #define APFS_SHOW_ALT_STREAMS | ||
37 | |||
38 | #define VI_MINUS1 ((unsigned)(int)-1) | ||
39 | #define IsViDef(x) ((int)(x) != -1) | ||
40 | #define IsViNotDef(x) ((int)(x) == -1) | ||
41 | |||
42 | #define Get16(p) GetUi16(p) | ||
43 | #define Get32(p) GetUi32(p) | ||
44 | #define Get64(p) GetUi64(p) | ||
45 | |||
46 | #define G16(_offs_, dest) dest = Get16(p + (_offs_)); | ||
47 | #define G32(_offs_, dest) dest = Get32(p + (_offs_)); | ||
48 | #define G64(_offs_, dest) dest = Get64(p + (_offs_)); | ||
49 | |||
50 | namespace NArchive { | ||
51 | namespace NApfs { | ||
52 | |||
53 | #define ValToHex(t) ((char)(((t) < 10) ? ('0' + (t)) : ('a' + ((t) - 10)))) | ||
54 | |||
55 | static void ConvertByteToHex(unsigned val, char *s) | ||
56 | { | ||
57 | unsigned t; | ||
58 | t = val >> 4; | ||
59 | s[0] = ValToHex(t); | ||
60 | t = val & 0xF; | ||
61 | s[1] = ValToHex(t); | ||
62 | } | ||
63 | |||
64 | struct CUuid | ||
65 | { | ||
66 | Byte Data[16]; | ||
67 | |||
68 | void SetHex_To_str(char *s) const | ||
69 | { | ||
70 | for (unsigned i = 0; i < 16; i++) | ||
71 | ConvertByteToHex(Data[i], s + i * 2); | ||
72 | s[32] = 0; | ||
73 | } | ||
74 | |||
75 | void AddHexToString(UString &dest) const | ||
76 | { | ||
77 | char temp[32 + 4]; | ||
78 | SetHex_To_str(temp); | ||
79 | dest += temp; | ||
80 | } | ||
81 | |||
82 | void SetFrom(const Byte *p) { memcpy(Data, p, 16); } | ||
83 | }; | ||
84 | |||
85 | |||
86 | typedef UInt64 oid_t; | ||
87 | typedef UInt64 xid_t; | ||
88 | typedef Int64 paddr_t; | ||
89 | |||
90 | #define G64o G64 | ||
91 | #define G64x G64 | ||
92 | // #define G64a G64 | ||
93 | |||
94 | /* | ||
95 | struct prange_t | ||
96 | { | ||
97 | paddr_t start_paddr; | ||
98 | UInt64 block_count; | ||
99 | |||
100 | void Parse(const Byte *p) | ||
101 | { | ||
102 | G64a (0, start_paddr); | ||
103 | G64 (8, block_count); | ||
104 | } | ||
105 | }; | ||
106 | */ | ||
107 | |||
108 | #define OBJECT_TYPE_NX_SUPERBLOCK 0x1 | ||
109 | #define OBJECT_TYPE_BTREE 0x2 | ||
110 | #define OBJECT_TYPE_BTREE_NODE 0x3 | ||
111 | /* | ||
112 | #define OBJECT_TYPE_SPACEMAN 0x5 | ||
113 | #define OBJECT_TYPE_SPACEMAN_CAB 0x6 | ||
114 | #define OBJECT_TYPE_SPACEMAN_CIB 0x7 | ||
115 | #define OBJECT_TYPE_SPACEMAN_BITMAP 0x8 | ||
116 | #define OBJECT_TYPE_SPACEMAN_FREE_QUEUE 0x9 | ||
117 | #define OBJECT_TYPE_EXTENT_LIST_TREE 0xa | ||
118 | */ | ||
119 | #define OBJECT_TYPE_OMAP 0xb | ||
120 | /* | ||
121 | #define OBJECT_TYPE_CHECKPOINT_MAP 0xc | ||
122 | */ | ||
123 | #define OBJECT_TYPE_FS 0xd | ||
124 | #define OBJECT_TYPE_FSTREE 0xe | ||
125 | /* | ||
126 | #define OBJECT_TYPE_BLOCKREFTREE 0xf | ||
127 | #define OBJECT_TYPE_SNAPMETATREE 0x10 | ||
128 | #define OBJECT_TYPE_NX_REAPER 0x11 | ||
129 | #define OBJECT_TYPE_NX_REAP_LIST 0x12 | ||
130 | #define OBJECT_TYPE_OMAP_SNAPSHOT 0x13 | ||
131 | #define OBJECT_TYPE_EFI_JUMPSTART 0x14 | ||
132 | #define OBJECT_TYPE_FUSION_MIDDLE_TREE 0x15 | ||
133 | #define OBJECT_TYPE_NX_FUSION_WBC 0x16 | ||
134 | #define OBJECT_TYPE_NX_FUSION_WBC_LIST 0x17 | ||
135 | #define OBJECT_TYPE_ER_STATE 0x18 | ||
136 | #define OBJECT_TYPE_GBITMAP 0x19 | ||
137 | #define OBJECT_TYPE_GBITMAP_TREE 0x1a | ||
138 | #define OBJECT_TYPE_GBITMAP_BLOCK 0x1b | ||
139 | #define OBJECT_TYPE_ER_RECOVERY_BLOCK 0x1c | ||
140 | #define OBJECT_TYPE_SNAP_META_EXT 0x1d | ||
141 | #define OBJECT_TYPE_INTEGRITY_META 0x1e | ||
142 | #define OBJECT_TYPE_FEXT_TREE 0x1f | ||
143 | #define OBJECT_TYPE_RESERVED_20 0x20 | ||
144 | |||
145 | #define OBJECT_TYPE_INVALID 0x0 | ||
146 | #define OBJECT_TYPE_TEST 0xff | ||
147 | #define OBJECT_TYPE_CONTAINER_KEYBAG 'keys' | ||
148 | #define OBJECT_TYPE_VOLUME_KEYBAG 'recs' | ||
149 | #define OBJECT_TYPE_MEDIA_KEYBAG 'mkey' | ||
150 | |||
151 | #define OBJ_VIRTUAL 0x0 | ||
152 | #define OBJ_EPHEMERAL 0x80000000 | ||
153 | #define OBJ_PHYSICAL 0x40000000 | ||
154 | |||
155 | #define OBJ_NOHEADER 0x20000000 | ||
156 | #define OBJ_ENCRYPTED 0x10000000 | ||
157 | #define OBJ_NONPERSISTENT 0x08000000 | ||
158 | */ | ||
159 | #define OBJECT_TYPE_MASK 0x0000ffff | ||
160 | /* | ||
161 | #define OBJECT_TYPE_FLAGS_MASK 0xffff0000 | ||
162 | #define OBJ_STORAGETYPE_MASK 0xc0000000 | ||
163 | #define OBJECT_TYPE_FLAGS_DEFINED_MASK 0xf8000000 | ||
164 | */ | ||
165 | |||
166 | // #define MAX_CKSUM_SIZE 8 | ||
167 | |||
168 | // obj_phys_t | ||
169 | struct CPhys | ||
170 | { | ||
171 | // Byte cksum[MAX_CKSUM_SIZE]; | ||
172 | oid_t oid; | ||
173 | xid_t xid; | ||
174 | UInt32 type; | ||
175 | UInt32 subtype; | ||
176 | |||
177 | UInt32 GetType() const { return type & OBJECT_TYPE_MASK; } | ||
178 | void Parse(const Byte *p); | ||
179 | }; | ||
180 | |||
181 | void CPhys::Parse(const Byte *p) | ||
182 | { | ||
183 | // memcpy(cksum, p, MAX_CKSUM_SIZE); | ||
184 | G64o (8, oid); | ||
185 | G64x (0x10, xid); | ||
186 | G32 (0x18, type); | ||
187 | G32 (0x1C, subtype); | ||
188 | } | ||
189 | |||
190 | #define NX_MAX_FILE_SYSTEMS 100 | ||
191 | /* | ||
192 | #define NX_EPH_INFO_COUNT 4 | ||
193 | #define NX_EPH_MIN_BLOCK_COUNT 8 | ||
194 | #define NX_MAX_FILE_SYSTEM_EPH_STRUCTS 4 | ||
195 | #define NX_TX_MIN_CHECKPOINT_COUNT 4 | ||
196 | #define NX_EPH_INFO_VERSION_1 1 | ||
197 | */ | ||
198 | |||
199 | /* | ||
200 | typedef enum | ||
201 | { | ||
202 | NX_CNTR_OBJ_CKSUM_SET = 0, | ||
203 | NX_CNTR_OBJ_CKSUM_FAIL = 1, | ||
204 | NX_NUM_COUNTERS = 32 | ||
205 | } counter_id_t; | ||
206 | */ | ||
207 | |||
208 | /* Incompatible volume feature flags */ | ||
209 | #define APFS_INCOMPAT_CASE_INSENSITIVE (1 << 0) | ||
210 | /* | ||
211 | #define APFS_INCOMPAT_DATALESS_SNAPS (1 << 1) | ||
212 | #define APFS_INCOMPAT_ENC_ROLLED (1 << 2) | ||
213 | */ | ||
214 | #define APFS_INCOMPAT_NORMALIZATION_INSENSITIVE (1 << 3) | ||
215 | /* | ||
216 | #define APFS_INCOMPAT_INCOMPLETE_RESTORE (1 << 4) | ||
217 | #define APFS_INCOMPAT_SEALED_VOLUME (1 << 5) | ||
218 | #define APFS_INCOMPAT_RESERVED_40 (1 << 6) | ||
219 | */ | ||
220 | |||
221 | static const char * const g_APFS_INCOMPAT_Flags[] = | ||
222 | { | ||
223 | "CASE_INSENSITIVE" | ||
224 | , "DATALESS_SNAPS" | ||
225 | , "ENC_ROLLED" | ||
226 | , "NORMALIZATION_INSENSITIVE" | ||
227 | , "INCOMPLETE_RESTORE" | ||
228 | , "SEALED_VOLUME" | ||
229 | }; | ||
230 | |||
231 | /* | ||
232 | #define APFS_SUPPORTED_INCOMPAT_MASK \ | ||
233 | ( APFS_INCOMPAT_CASE_INSENSITIVE \ | ||
234 | | APFS_INCOMPAT_DATALESS_SNAPS \ | ||
235 | | APFS_INCOMPAT_ENC_ROLLED \ | ||
236 | | APFS_INCOMPAT_NORMALIZATION_INSENSITIVE \ | ||
237 | | APFS_INCOMPAT_INCOMPLETE_RESTORE \ | ||
238 | | APFS_INCOMPAT_SEALED_VOLUME \ | ||
239 | | APFS_INCOMPAT_RESERVED_40 \ | ||
240 | ) | ||
241 | */ | ||
242 | |||
243 | // superblock_t | ||
244 | struct CSuperBlock | ||
245 | { | ||
246 | // CPhys o; | ||
247 | // UInt32 magic; | ||
248 | UInt32 block_size; | ||
249 | unsigned block_size_Log; | ||
250 | UInt64 block_count; | ||
251 | // UInt64 features; | ||
252 | // UInt64 readonly_compatible_features; | ||
253 | // UInt64 incompatible_features; | ||
254 | CUuid uuid; | ||
255 | /* | ||
256 | oid_t next_oid; | ||
257 | xid_t next_xid; | ||
258 | UInt32 xp_desc_blocks; | ||
259 | UInt32 xp_data_blocks; | ||
260 | paddr_t xp_desc_base; | ||
261 | paddr_t xp_data_base; | ||
262 | UInt32 xp_desc_next; | ||
263 | UInt32 xp_data_next; | ||
264 | UInt32 xp_desc_index; | ||
265 | UInt32 xp_desc_len; | ||
266 | UInt32 xp_data_index; | ||
267 | UInt32 xp_data_len; | ||
268 | oid_t spaceman_oid; | ||
269 | */ | ||
270 | oid_t omap_oid; | ||
271 | // oid_t reaper_oid; | ||
272 | // UInt32 test_type; | ||
273 | UInt32 max_file_systems; | ||
274 | // oid_t fs_oid[NX_MAX_FILE_SYSTEMS]; | ||
275 | /* | ||
276 | UInt64 counters[NX_NUM_COUNTERS]; // counter_id_t | ||
277 | prange_t blocked_out_prange; | ||
278 | oid_t evict_mapping_tree_oid; | ||
279 | UInt64 flags; | ||
280 | paddr_t efi_jumpstart; | ||
281 | CUuid fusion_uuid; | ||
282 | prange_t keylocker; | ||
283 | UInt64 ephemeral_info[NX_EPH_INFO_COUNT]; | ||
284 | oid_t test_oid; | ||
285 | oid_t fusion_mt_oid; | ||
286 | oid_t fusion_wbc_oid; | ||
287 | prange_t fusion_wbc; | ||
288 | UInt64 newest_mounted_version; | ||
289 | prange_t mkb_locker; | ||
290 | */ | ||
291 | |||
292 | bool Parse(const Byte *p); | ||
293 | }; | ||
294 | |||
295 | struct CSuperBlock2 | ||
296 | { | ||
297 | oid_t fs_oid[NX_MAX_FILE_SYSTEMS]; | ||
298 | void Parse(const Byte *p) | ||
299 | { | ||
300 | for (unsigned i = 0; i < NX_MAX_FILE_SYSTEMS; i++) | ||
301 | { | ||
302 | G64o (0xb8 + i * 8, fs_oid[i]); | ||
303 | } | ||
304 | } | ||
305 | }; | ||
306 | |||
307 | |||
308 | // we include one additional byte of next field (block_size) | ||
309 | static const unsigned k_SignatureOffset = 32; | ||
310 | static const Byte k_Signature[] = { 'N', 'X', 'S', 'B', 0 }; | ||
311 | |||
312 | // size must be 4 bytes aligned | ||
313 | static UInt64 Fletcher64(const Byte *data, size_t size) | ||
314 | { | ||
315 | const UInt32 kMax32 = 0xffffffff; | ||
316 | const UInt64 val = 0; // startVal | ||
317 | UInt64 a = val & kMax32; | ||
318 | UInt64 b = (val >> 32) & kMax32; | ||
319 | for (size_t i = 0; i < size; i += 4) | ||
320 | { | ||
321 | a += GetUi32(data + i); | ||
322 | b += a; | ||
323 | } | ||
324 | a %= kMax32; | ||
325 | b %= kMax32; | ||
326 | b = (UInt32)(kMax32 - ((a + b) % kMax32)); | ||
327 | a = (UInt32)(kMax32 - ((a + b) % kMax32)); | ||
328 | return (a << 32) | b; | ||
329 | } | ||
330 | |||
331 | static bool CheckFletcher64(const Byte *p, size_t size) | ||
332 | { | ||
333 | const UInt64 calculated_checksum = Fletcher64(p + 8, size - 8); | ||
334 | const UInt64 stored_checksum = Get64(p); | ||
335 | return (stored_checksum == calculated_checksum); | ||
336 | } | ||
337 | |||
338 | |||
339 | static unsigned GetLogSize(UInt32 size) | ||
340 | { | ||
341 | unsigned k; | ||
342 | for (k = 0; k < 32; k++) | ||
343 | if (((UInt32)1 << k) == size) | ||
344 | return k; | ||
345 | return k; | ||
346 | } | ||
347 | |||
348 | static const unsigned kApfsHeaderSize = 1 << 12; | ||
349 | |||
350 | // #define OID_INVALID 0 | ||
351 | #define OID_NX_SUPERBLOCK 1 | ||
352 | // #define OID_RESERVED_COUNT 1024 | ||
353 | // This range of identifiers is reserved for physical, virtual, and ephemeral objects | ||
354 | |||
355 | bool CSuperBlock::Parse(const Byte *p) | ||
356 | { | ||
357 | CPhys o; | ||
358 | o.Parse(p); | ||
359 | if (o.oid != OID_NX_SUPERBLOCK) | ||
360 | return false; | ||
361 | if (o.GetType() != OBJECT_TYPE_NX_SUPERBLOCK) | ||
362 | return false; | ||
363 | if (o.subtype != 0) | ||
364 | return false; | ||
365 | if (memcmp(p + k_SignatureOffset, k_Signature, 4) != 0) | ||
366 | return false; | ||
367 | if (!CheckFletcher64(p, kApfsHeaderSize)) | ||
368 | return false; | ||
369 | |||
370 | G32 (0x24, block_size); | ||
371 | { | ||
372 | unsigned logSize = GetLogSize(block_size); | ||
373 | if (logSize < 12 || logSize > 16) | ||
374 | return false; | ||
375 | block_size_Log = logSize; | ||
376 | } | ||
377 | |||
378 | G64 (0x28, block_count); | ||
379 | |||
380 | static const UInt64 kArcSize_MAX = (UInt64)1 << 62; | ||
381 | if (block_count > (kArcSize_MAX >> block_size_Log)) | ||
382 | return false; | ||
383 | |||
384 | // G64 (0x30, features); | ||
385 | // G64 (0x38, readonly_compatible_features); | ||
386 | // G64 (0x40, incompatible_features); | ||
387 | uuid.SetFrom(p + 0x48); | ||
388 | /* | ||
389 | G64o (0x58, next_oid); | ||
390 | G64x (0x60, next_xid); | ||
391 | G32 (0x68, xp_desc_blocks); | ||
392 | G32 (0x6c, xp_data_blocks); | ||
393 | G64a (0x70, xp_desc_base); | ||
394 | G64a (0x78, xp_data_base); | ||
395 | G32 (0x80, xp_desc_next); | ||
396 | G32 (0x84, xp_data_next); | ||
397 | G32 (0x88, xp_desc_index); | ||
398 | G32 (0x8c, xp_desc_len); | ||
399 | G32 (0x90, xp_data_index); | ||
400 | G32 (0x94, xp_data_len); | ||
401 | G64o (0x98, spaceman_oid); | ||
402 | */ | ||
403 | G64o (0xa0, omap_oid); | ||
404 | // G64o (0xa8, reaper_oid); | ||
405 | // G32 (0xb0, test_type); | ||
406 | G32 (0xb4, max_file_systems); | ||
407 | if (max_file_systems > NX_MAX_FILE_SYSTEMS) | ||
408 | return false; | ||
409 | /* | ||
410 | { | ||
411 | for (unsigned i = 0; i < NX_MAX_FILE_SYSTEMS; i++) | ||
412 | { | ||
413 | G64o (0xb8 + i * 8, fs_oid[i]); | ||
414 | } | ||
415 | } | ||
416 | */ | ||
417 | /* | ||
418 | { | ||
419 | for (unsigned i = 0; i < NX_NUM_COUNTERS; i++) | ||
420 | { | ||
421 | G64 (0x3d8 + i * 8, counters[i]); | ||
422 | } | ||
423 | } | ||
424 | blocked_out_prange.Parse(p + 0x4d8); | ||
425 | G64o (0x4e8, evict_mapping_tree_oid); | ||
426 | #define NX_CRYPTO_SW 0x00000004LL | ||
427 | G64 (0x4f0, flags); | ||
428 | G64a (0x4f8, efi_jumpstart); | ||
429 | fusion_uuid.SetFrom(p + 0x500); | ||
430 | keylocker.Parse(p + 0x510); | ||
431 | { | ||
432 | for (unsigned i = 0; i < NX_EPH_INFO_COUNT; i++) | ||
433 | { | ||
434 | G64 (0x520 + i * 8, ephemeral_info[i]); | ||
435 | } | ||
436 | } | ||
437 | G64o (0x540, test_oid); | ||
438 | G64o (0x548, fusion_mt_oid); | ||
439 | G64o (0x550, fusion_wbc_oid); | ||
440 | fusion_wbc.Parse(p + 0x558); | ||
441 | G64 (0x568, newest_mounted_version); // decimal 1412141 001 000 000 | ||
442 | mkb_locker.Parse(p + 0x570); | ||
443 | */ | ||
444 | |||
445 | return true; | ||
446 | } | ||
447 | |||
448 | |||
449 | |||
450 | struct C_omap_phys | ||
451 | { | ||
452 | // om_ prefix | ||
453 | // CPhys o; | ||
454 | /* | ||
455 | UInt32 flags; | ||
456 | UInt32 snap_count; | ||
457 | UInt32 tree_type; | ||
458 | UInt32 snapshot_tree_type; | ||
459 | */ | ||
460 | oid_t tree_oid; | ||
461 | /* | ||
462 | oid_t snapshot_tree_oid; | ||
463 | xid_t most_recent_snap; | ||
464 | xid_t pending_revert_min; | ||
465 | xid_t pending_revert_max; | ||
466 | */ | ||
467 | bool Parse(const Byte *p, size_t size, oid_t oid); | ||
468 | }; | ||
469 | |||
470 | bool C_omap_phys::Parse(const Byte *p, size_t size, oid_t oid) | ||
471 | { | ||
472 | CPhys o; | ||
473 | if (!CheckFletcher64(p, size)) | ||
474 | return false; | ||
475 | o.Parse(p); | ||
476 | if (o.GetType() != OBJECT_TYPE_OMAP) | ||
477 | return false; | ||
478 | if (o.oid != oid) | ||
479 | return false; | ||
480 | /* | ||
481 | G32 (0x20, flags); | ||
482 | G32 (0x24, snap_count); | ||
483 | G32 (0x28, tree_type); | ||
484 | G32 (0x2C, snapshot_tree_type); | ||
485 | */ | ||
486 | G64o (0x30, tree_oid); | ||
487 | /* | ||
488 | G64o (0x38, snapshot_tree_oid); | ||
489 | G64x (0x40, most_recent_snap); | ||
490 | G64x (0x48, pending_revert_min); | ||
491 | G64x (0x50, pending_revert_max); | ||
492 | */ | ||
493 | return true; | ||
494 | } | ||
495 | |||
496 | |||
497 | // #define BTOFF_INVALID 0xffff | ||
498 | /* This value is stored in the off field of nloc_t to indicate that | ||
499 | there's no offset. For example, the last entry in a free | ||
500 | list has no entry after it, so it uses this value for its off field. */ | ||
501 | |||
502 | // A location within a B-tree node | ||
503 | struct nloc | ||
504 | { | ||
505 | UInt16 off; | ||
506 | UInt16 len; | ||
507 | |||
508 | void Parse(const Byte *p) | ||
509 | { | ||
510 | G16 (0, off); | ||
511 | G16 (2, len); | ||
512 | } | ||
513 | UInt32 GetEnd() const { return (UInt32)off + len; } | ||
514 | bool CheckOverLimit(UInt32 limit) | ||
515 | { | ||
516 | return off < limit && len <= limit - off; | ||
517 | } | ||
518 | }; | ||
519 | |||
520 | |||
521 | // The location, within a B-tree node, of a key and value | ||
522 | struct kvloc | ||
523 | { | ||
524 | nloc k; | ||
525 | nloc v; | ||
526 | |||
527 | void Parse(const Byte *p) | ||
528 | { | ||
529 | k.Parse(p); | ||
530 | v.Parse(p + 4); | ||
531 | } | ||
532 | }; | ||
533 | |||
534 | |||
535 | // The location, within a B-tree node, of a fixed-size key and value | ||
536 | struct kvoff | ||
537 | { | ||
538 | UInt16 k; | ||
539 | UInt16 v; | ||
540 | |||
541 | void Parse(const Byte *p) | ||
542 | { | ||
543 | G16 (0, k); | ||
544 | G16 (2, v); | ||
545 | } | ||
546 | }; | ||
547 | |||
548 | |||
549 | #define BTNODE_ROOT (1 << 0) | ||
550 | #define BTNODE_LEAF (1 << 1) | ||
551 | #define BTNODE_FIXED_KV_SIZE (1 << 2) | ||
552 | /* | ||
553 | #define BTNODE_HASHED (1 << 3) | ||
554 | #define BTNODE_NOHEADER (1 << 4) | ||
555 | #define BTNODE_CHECK_KOFF_INVAL (1 << 15) | ||
556 | */ | ||
557 | |||
558 | static const unsigned k_Toc_offset = 0x38; | ||
559 | |||
560 | // btree_node_phys | ||
561 | struct CBTreeNodePhys | ||
562 | { | ||
563 | // btn_ prefix | ||
564 | CPhys o; | ||
565 | UInt16 flags; | ||
566 | UInt16 level; // the number of child levels below this node. 0 - for a leaf node, 1 for the immediate parent of a leaf node | ||
567 | UInt32 nkeys; // The number of keys stored in this node. | ||
568 | nloc table_space; | ||
569 | /* | ||
570 | nloc free_space; | ||
571 | nloc key_free_list; | ||
572 | nloc val_free_list; | ||
573 | */ | ||
574 | |||
575 | bool Is_FIXED_KV_SIZE() const { return (flags & BTNODE_FIXED_KV_SIZE) != 0; } | ||
576 | |||
577 | bool Parse(const Byte *p, size_t size) | ||
578 | { | ||
579 | if (!CheckFletcher64(p, size)) | ||
580 | return false; | ||
581 | o.Parse(p); | ||
582 | G16 (0x20, flags); | ||
583 | G16 (0x22, level); | ||
584 | G32 (0x24, nkeys); | ||
585 | table_space.Parse(p + 0x28); | ||
586 | /* | ||
587 | free_space.Parse(p + 0x2C); | ||
588 | key_free_list.Parse(p + 0x30); | ||
589 | val_free_list.Parse(p + 0x34); | ||
590 | */ | ||
591 | return true; | ||
592 | } | ||
593 | }; | ||
594 | |||
595 | /* | ||
596 | #define BTREE_UINT64_KEYS (1 << 0) | ||
597 | #define BTREE_SEQUENTIAL_INSERT (1 << 1) | ||
598 | #define BTREE_ALLOW_GHOSTS (1 << 2) | ||
599 | */ | ||
600 | #define BTREE_EPHEMERAL (1 << 3) | ||
601 | #define BTREE_PHYSICAL (1 << 4) | ||
602 | /* | ||
603 | #define BTREE_NONPERSISTENT (1 << 5) | ||
604 | #define BTREE_KV_NONALIGNED (1 << 6) | ||
605 | #define BTREE_HASHED (1 << 7) | ||
606 | */ | ||
607 | |||
608 | /* | ||
609 | BTREE_EPHEMERAL: The nodes in the B-tree use ephemeral object identifiers to link to child nodes | ||
610 | BTREE_PHYSICAL : The nodes in the B-tree use physical object identifiers to link to child nodes. | ||
611 | If neither flag is set, nodes in the B-tree use virtual object | ||
612 | identifiers to link to their child nodes. | ||
613 | */ | ||
614 | |||
615 | // Static information about a B-tree. | ||
616 | struct btree_info_fixed | ||
617 | { | ||
618 | UInt32 flags; | ||
619 | UInt32 node_size; | ||
620 | UInt32 key_size; | ||
621 | UInt32 val_size; | ||
622 | |||
623 | void Parse(const Byte *p) | ||
624 | { | ||
625 | G32 (0, flags); | ||
626 | G32 (4, node_size); | ||
627 | G32 (8, key_size); | ||
628 | G32 (12, val_size); | ||
629 | } | ||
630 | }; | ||
631 | |||
632 | static const unsigned k_btree_info_Size = 0x28; | ||
633 | |||
634 | struct btree_info | ||
635 | { | ||
636 | btree_info_fixed fixed; | ||
637 | UInt32 longest_key; | ||
638 | UInt32 longest_val; | ||
639 | UInt64 key_count; | ||
640 | UInt64 node_count; | ||
641 | |||
642 | bool Is_EPHEMERAL() const { return (fixed.flags & BTREE_EPHEMERAL) != 0; } | ||
643 | bool Is_PHYSICAL() const { return (fixed.flags & BTREE_PHYSICAL) != 0; } | ||
644 | |||
645 | void Parse(const Byte *p) | ||
646 | { | ||
647 | fixed.Parse(p); | ||
648 | G32 (0x10, longest_key); | ||
649 | G32 (0x14, longest_val); | ||
650 | G64 (0x18, key_count); | ||
651 | G64 (0x20, node_count); | ||
652 | } | ||
653 | }; | ||
654 | |||
655 | |||
656 | /* | ||
657 | typedef UInt32 cp_key_class_t; | ||
658 | typedef UInt32 cp_key_os_version_t; | ||
659 | typedef UInt16 cp_key_revision_t; | ||
660 | typedef UInt32 crypto_flags_t; | ||
661 | |||
662 | struct wrapped_meta_crypto_state | ||
663 | { | ||
664 | UInt16 major_version; | ||
665 | UInt16 minor_version; | ||
666 | crypto_flags_t cpflags; | ||
667 | cp_key_class_t persistent_class; | ||
668 | cp_key_os_version_t key_os_version; | ||
669 | cp_key_revision_t key_revision; | ||
670 | // UInt16 unused; | ||
671 | |||
672 | void Parse(const Byte *p) | ||
673 | { | ||
674 | G16 (0, major_version); | ||
675 | G16 (2, minor_version); | ||
676 | G32 (4, cpflags); | ||
677 | G32 (8, persistent_class); | ||
678 | G32 (12, key_os_version); | ||
679 | G16 (16, key_revision); | ||
680 | } | ||
681 | }; | ||
682 | */ | ||
683 | |||
684 | |||
685 | #define APFS_MODIFIED_NAMELEN 32 | ||
686 | #define sizeof__apfs_modified_by_t (APFS_MODIFIED_NAMELEN + 16); | ||
687 | |||
688 | struct apfs_modified_by_t | ||
689 | { | ||
690 | Byte id[APFS_MODIFIED_NAMELEN]; | ||
691 | UInt64 timestamp; | ||
692 | xid_t last_xid; | ||
693 | |||
694 | void Parse(const Byte *p) | ||
695 | { | ||
696 | memcpy(id, p, APFS_MODIFIED_NAMELEN); | ||
697 | p += APFS_MODIFIED_NAMELEN; | ||
698 | G64 (0, timestamp); | ||
699 | G64x (8, last_xid); | ||
700 | } | ||
701 | }; | ||
702 | |||
703 | |||
704 | #define APFS_MAX_HIST 8 | ||
705 | #define APFS_VOLNAME_LEN 256 | ||
706 | |||
707 | struct CApfs | ||
708 | { | ||
709 | // apfs_ | ||
710 | CPhys o; | ||
711 | // UInt32 magic; | ||
712 | UInt32 fs_index; // e index of the object identifier for this volume's file system in the container's array of file systems. | ||
713 | // UInt64 features; | ||
714 | // UInt64 readonly_compatible_features; | ||
715 | UInt64 incompatible_features; | ||
716 | UInt64 unmount_time; | ||
717 | // UInt64 fs_reserve_block_count; | ||
718 | // UInt64 fs_quota_block_count; | ||
719 | UInt64 fs_alloc_count; | ||
720 | // wrapped_meta_crypto_state meta_crypto; | ||
721 | // UInt32 root_tree_type; | ||
722 | /* The type of the root file-system tree. | ||
723 | The value is typically OBJ_VIRTUAL | OBJECT_TYPE_BTREE, | ||
724 | with a subtype of OBJECT_TYPE_FSTREE */ | ||
725 | |||
726 | // UInt32 extentref_tree_type; | ||
727 | // UInt32 snap_meta_tree_type; | ||
728 | oid_t omap_oid; | ||
729 | oid_t root_tree_oid; | ||
730 | /* | ||
731 | oid_t extentref_tree_oid; | ||
732 | oid_t snap_meta_tree_oid; | ||
733 | xid_t revert_to_xid; | ||
734 | oid_t revert_to_sblock_oid; | ||
735 | UInt64 next_obj_id; | ||
736 | */ | ||
737 | UInt64 num_files; | ||
738 | UInt64 num_directories; | ||
739 | UInt64 num_symlinks; | ||
740 | UInt64 num_other_fsobjects; | ||
741 | UInt64 num_snapshots; | ||
742 | UInt64 total_blocks_alloced; | ||
743 | UInt64 total_blocks_freed; | ||
744 | CUuid vol_uuid; | ||
745 | UInt64 last_mod_time; | ||
746 | UInt64 fs_flags; | ||
747 | apfs_modified_by_t formatted_by; | ||
748 | apfs_modified_by_t modified_by[APFS_MAX_HIST]; | ||
749 | Byte volname[APFS_VOLNAME_LEN]; | ||
750 | /* | ||
751 | UInt32 next_doc_id; | ||
752 | UInt16 role; // APFS_VOL_ROLE_NONE APFS_VOL_ROLE_SYSTEM .... | ||
753 | UInt16 reserved; | ||
754 | xid_t root_to_xid; | ||
755 | oid_t er_state_oid; | ||
756 | UInt64 cloneinfo_id_epoch; | ||
757 | UInt64 cloneinfo_xid; | ||
758 | oid_t snap_meta_ext_oid; | ||
759 | CUuid volume_group_id; | ||
760 | oid_t integrity_meta_oid; | ||
761 | oid_t fext_tree_oid; | ||
762 | UInt32 fext_tree_type; | ||
763 | UInt32 reserved_type; | ||
764 | oid_t reserved_oid; | ||
765 | */ | ||
766 | |||
767 | UInt64 GetTotalItems() const | ||
768 | { | ||
769 | return num_files + num_directories + num_symlinks + num_other_fsobjects; | ||
770 | } | ||
771 | |||
772 | bool IsHashedName() const | ||
773 | { | ||
774 | return | ||
775 | (incompatible_features & APFS_INCOMPAT_CASE_INSENSITIVE) != 0 || | ||
776 | (incompatible_features & APFS_INCOMPAT_NORMALIZATION_INSENSITIVE) != 0; | ||
777 | } | ||
778 | |||
779 | bool Parse(const Byte *p, size_t size); | ||
780 | }; | ||
781 | |||
782 | |||
783 | bool CApfs::Parse(const Byte *p, size_t size) | ||
784 | { | ||
785 | o.Parse(p); | ||
786 | if (Get32(p + 32) != 0x42535041) // { 'A', 'P', 'S', 'B' }; | ||
787 | return false; | ||
788 | if (o.GetType() != OBJECT_TYPE_FS) | ||
789 | return false; | ||
790 | if (!CheckFletcher64(p, size)) | ||
791 | return false; | ||
792 | // if (o.GetType() != OBJECT_TYPE_NX_SUPERBLOCK) return false; | ||
793 | |||
794 | G32 (0x24, fs_index); | ||
795 | // G64 (0x28, features); | ||
796 | // G64 (0x30, readonly_compatible_features); | ||
797 | G64 (0x38, incompatible_features); | ||
798 | G64 (0x40, unmount_time); | ||
799 | // G64 (0x48, fs_reserve_block_count); | ||
800 | // G64 (0x50, fs_quota_block_count); | ||
801 | G64 (0x58, fs_alloc_count); | ||
802 | // meta_crypto.Parse(p + 0x60); | ||
803 | // G32 (0x74, root_tree_type); | ||
804 | // G32 (0x78, extentref_tree_type); | ||
805 | // G32 (0x7C, snap_meta_tree_type); | ||
806 | |||
807 | G64o (0x80, omap_oid); | ||
808 | G64o (0x88, root_tree_oid); | ||
809 | /* | ||
810 | G64o (0x90, extentref_tree_oid); | ||
811 | G64o (0x98, snap_meta_tree_oid); | ||
812 | G64x (0xa0, revert_to_xid); | ||
813 | G64o (0xa8, revert_to_sblock_oid); | ||
814 | G64 (0xb0, next_obj_id); | ||
815 | */ | ||
816 | G64 (0xb8, num_files); | ||
817 | G64 (0xc0, num_directories); | ||
818 | G64 (0xc8, num_symlinks); | ||
819 | G64 (0xd0, num_other_fsobjects); | ||
820 | G64 (0xd8, num_snapshots); | ||
821 | G64 (0xe0, total_blocks_alloced); | ||
822 | G64 (0xe8, total_blocks_freed); | ||
823 | vol_uuid.SetFrom(p + 0xf0); | ||
824 | G64 (0x100, last_mod_time); | ||
825 | G64 (0x108, fs_flags); | ||
826 | p += 0x110; | ||
827 | formatted_by.Parse(p); | ||
828 | p += sizeof__apfs_modified_by_t; | ||
829 | for (unsigned i = 0; i < APFS_MAX_HIST; i++) | ||
830 | { | ||
831 | modified_by[i].Parse(p); | ||
832 | p += sizeof__apfs_modified_by_t; | ||
833 | } | ||
834 | memcpy(volname, p, APFS_VOLNAME_LEN); | ||
835 | p += APFS_VOLNAME_LEN; | ||
836 | /* | ||
837 | G32 (0, next_doc_id); | ||
838 | G16 (4, role); | ||
839 | G16 (6, reserved); | ||
840 | G64x (8, root_to_xid); | ||
841 | G64o (0x10, er_state_oid); | ||
842 | G64 (0x18, cloneinfo_id_epoch); | ||
843 | G64 (0x20, cloneinfo_xid); | ||
844 | G64o (0x28, snap_meta_ext_oid); | ||
845 | volume_group_id.SetFrom(p + 0x30); | ||
846 | G64o (0x40, integrity_meta_oid); | ||
847 | G64o (0x48, fext_tree_oid); | ||
848 | G32 (0x50, fext_tree_type); | ||
849 | G32 (0x54, reserved_type); | ||
850 | G64o (0x58, reserved_oid); | ||
851 | */ | ||
852 | return true; | ||
853 | } | ||
854 | |||
855 | |||
856 | #define OBJ_ID_MASK 0x0fffffffffffffff | ||
857 | /* | ||
858 | #define OBJ_TYPE_MASK 0xf000000000000000 | ||
859 | #define SYSTEM_OBJ_ID_MARK 0x0fffffff00000000 | ||
860 | */ | ||
861 | #define OBJ_TYPE_SHIFT 60 | ||
862 | |||
863 | typedef enum | ||
864 | { | ||
865 | APFS_TYPE_ANY = 0, | ||
866 | APFS_TYPE_SNAP_METADATA = 1, | ||
867 | APFS_TYPE_EXTENT = 2, | ||
868 | APFS_TYPE_INODE = 3, | ||
869 | APFS_TYPE_XATTR = 4, | ||
870 | APFS_TYPE_SIBLING_LINK = 5, | ||
871 | APFS_TYPE_DSTREAM_ID = 6, | ||
872 | APFS_TYPE_CRYPTO_STATE = 7, | ||
873 | APFS_TYPE_FILE_EXTENT = 8, | ||
874 | APFS_TYPE_DIR_REC = 9, | ||
875 | APFS_TYPE_DIR_STATS = 10, | ||
876 | APFS_TYPE_SNAP_NAME = 11, | ||
877 | APFS_TYPE_SIBLING_MAP = 12, | ||
878 | APFS_TYPE_FILE_INFO = 13, | ||
879 | APFS_TYPE_MAX_VALID = 13, | ||
880 | APFS_TYPE_MAX = 15, | ||
881 | APFS_TYPE_INVALID = 15 | ||
882 | } j_obj_types; | ||
883 | |||
884 | |||
885 | struct j_key_t | ||
886 | { | ||
887 | UInt64 obj_id_and_type; | ||
888 | |||
889 | void Parse(const Byte *p) { G64(0, obj_id_and_type); } | ||
890 | unsigned GetType() const { return (unsigned)(obj_id_and_type >> OBJ_TYPE_SHIFT); } | ||
891 | UInt64 GetID() const { return obj_id_and_type & OBJ_ID_MASK; } | ||
892 | }; | ||
893 | |||
894 | |||
895 | |||
896 | #define J_DREC_LEN_MASK 0x000003ff | ||
897 | /* | ||
898 | #define J_DREC_HASH_MASK 0xfffff400 | ||
899 | #define J_DREC_HASH_SHIFT 10 | ||
900 | */ | ||
901 | |||
902 | static const unsigned k_SizeOf_j_drec_val = 0x12; | ||
903 | |||
904 | struct j_drec_val | ||
905 | { | ||
906 | UInt64 file_id; | ||
907 | UInt64 date_added; /* The time that this directory entry was added to the directory. | ||
908 | It's not updated when modifying the directory entry for example, | ||
909 | by renaming a file without moving it to a different directory. */ | ||
910 | UInt16 flags; | ||
911 | |||
912 | // bool IsFlags_File() const { return flags == MY_LIN_DT_REG; } | ||
913 | bool IsFlags_Unknown() const { return flags == MY_LIN_DT_UNKNOWN; } | ||
914 | bool IsFlags_Dir() const { return flags == MY_LIN_DT_DIR; } | ||
915 | |||
916 | // uint8_t xfields[]; | ||
917 | void Parse(const Byte *p) | ||
918 | { | ||
919 | G64 (0, file_id); | ||
920 | G64 (8, date_added); | ||
921 | G16 (0x10, flags); | ||
922 | } | ||
923 | }; | ||
924 | |||
925 | |||
926 | struct CItem | ||
927 | { | ||
928 | // j_key_t hdr; | ||
929 | UInt64 ParentId; | ||
930 | AString Name; | ||
931 | j_drec_val Val; | ||
932 | |||
933 | unsigned ParentItemIndex; | ||
934 | unsigned RefIndex; | ||
935 | // unsigned iNode_Index; | ||
936 | |||
937 | CItem(): | ||
938 | ParentItemIndex(VI_MINUS1), | ||
939 | RefIndex(VI_MINUS1) | ||
940 | // iNode_Index(VI_MINUS1) | ||
941 | {} | ||
942 | }; | ||
943 | |||
944 | |||
945 | /* | ||
946 | #define INVALID_INO_NUM 0 | ||
947 | #define ROOT_DIR_PARENT 1 // parent for "root" and "private-dir", there's no inode on disk with this inode number. | ||
948 | */ | ||
949 | #define ROOT_DIR_INO_NUM 2 // "root" - parent for all main files | ||
950 | #define PRIV_DIR_INO_NUM 3 // "private-dir" | ||
951 | /* | ||
952 | #define SNAP_DIR_INO_NUM 6 // the directory where snapshot metadata is stored. Snapshot inodes are stored in the snapshot metedata tree. | ||
953 | #define PURGEABLE_DIR_INO_NUM 7 | ||
954 | #define MIN_USER_INO_NUM 16 | ||
955 | |||
956 | #define UNIFIED_ID_SPACE_MARK 0x0800000000000000 | ||
957 | */ | ||
958 | |||
959 | /* | ||
960 | typedef enum | ||
961 | { | ||
962 | INODE_IS_APFS_PRIVATE = 0x00000001, | ||
963 | INODE_MAINTAIN_DIR_STATS = 0x00000002, | ||
964 | INODE_DIR_STATS_ORIGIN = 0x00000004, | ||
965 | INODE_PROT_CLASS_EXPLICIT = 0x00000008, | ||
966 | INODE_WAS_CLONED = 0x00000010, | ||
967 | INODE_FLAG_UNUSED = 0x00000020, | ||
968 | INODE_HAS_SECURITY_EA = 0x00000040, | ||
969 | INODE_BEING_TRUNCATED = 0x00000080, | ||
970 | INODE_HAS_FINDER_INFO = 0x00000100, | ||
971 | INODE_IS_SPARSE = 0x00000200, | ||
972 | INODE_WAS_EVER_CLONED = 0x00000400, | ||
973 | INODE_ACTIVE_FILE_TRIMMED = 0x00000800, | ||
974 | INODE_PINNED_TO_MAIN = 0x00001000, | ||
975 | INODE_PINNED_TO_TIER2 = 0x00002000, | ||
976 | INODE_HAS_RSRC_FORK = 0x00004000, | ||
977 | INODE_NO_RSRC_FORK = 0x00008000, | ||
978 | INODE_ALLOCATION_SPILLEDOVER = 0x00010000, | ||
979 | INODE_FAST_PROMOTE = 0x00020000, | ||
980 | INODE_HAS_UNCOMPRESSED_SIZE = 0x00040000, | ||
981 | INODE_IS_PURGEABLE = 0x00080000, | ||
982 | INODE_WANTS_TO_BE_PURGEABLE = 0x00100000, | ||
983 | INODE_IS_SYNC_ROOT = 0x00200000, | ||
984 | INODE_SNAPSHOT_COW_EXEMPTION = 0x00400000, | ||
985 | |||
986 | |||
987 | INODE_INHERITED_INTERNAL_FLAGS = \ | ||
988 | ( INODE_MAINTAIN_DIR_STATS \ | ||
989 | | INODE_SNAPSHOT_COW_EXEMPTION), | ||
990 | |||
991 | INODE_CLONED_INTERNAL_FLAGS = \ | ||
992 | ( INODE_HAS_RSRC_FORK \ | ||
993 | | INODE_NO_RSRC_FORK \ | ||
994 | | INODE_HAS_FINDER_INFO \ | ||
995 | | INODE_SNAPSHOT_COW_EXEMPTION), | ||
996 | } | ||
997 | j_inode_flags; | ||
998 | |||
999 | |||
1000 | #define APFS_VALID_INTERNAL_INODE_FLAGS \ | ||
1001 | ( INODE_IS_APFS_PRIVATE \ | ||
1002 | | INODE_MAINTAIN_DIR_STATS \ | ||
1003 | | INODE_DIR_STATS_ORIGIN \ | ||
1004 | | INODE_PROT_CLASS_EXPLICIT \ | ||
1005 | | INODE_WAS_CLONED \ | ||
1006 | | INODE_HAS_SECURITY_EA \ | ||
1007 | | INODE_BEING_TRUNCATED \ | ||
1008 | | INODE_HAS_FINDER_INFO \ | ||
1009 | | INODE_IS_SPARSE \ | ||
1010 | | INODE_WAS_EVER_CLONED \ | ||
1011 | | INODE_ACTIVE_FILE_TRIMMED \ | ||
1012 | | INODE_PINNED_TO_MAIN \ | ||
1013 | | INODE_PINNED_TO_TIER2 \ | ||
1014 | | INODE_HAS_RSRC_FORK \ | ||
1015 | | INODE_NO_RSRC_FORK \ | ||
1016 | | INODE_ALLOCATION_SPILLEDOVER \ | ||
1017 | | INODE_FAST_PROMOTE \ | ||
1018 | | INODE_HAS_UNCOMPRESSED_SIZE \ | ||
1019 | | INODE_IS_PURGEABLE \ | ||
1020 | | INODE_WANTS_TO_BE_PURGEABLE \ | ||
1021 | | INODE_IS_SYNC_ROOT \ | ||
1022 | | INODE_SNAPSHOT_COW_EXEMPTION) | ||
1023 | |||
1024 | #define APFS_INODE_PINNED_MASK (INODE_PINNED_TO_MAIN | INODE_PINNED_TO_TIER2) | ||
1025 | */ | ||
1026 | |||
1027 | static const char * const g_INODE_Flags[] = | ||
1028 | { | ||
1029 | "IS_APFS_PRIVATE" | ||
1030 | , "MAINTAIN_DIR_STATS" | ||
1031 | , "DIR_STATS_ORIGIN" | ||
1032 | , "PROT_CLASS_EXPLICIT" | ||
1033 | , "WAS_CLONED" | ||
1034 | , "FLAG_UNUSED" | ||
1035 | , "HAS_SECURITY_EA" | ||
1036 | , "BEING_TRUNCATED" | ||
1037 | , "HAS_FINDER_INFO" | ||
1038 | , "IS_SPARSE" | ||
1039 | , "WAS_EVER_CLONED" | ||
1040 | , "ACTIVE_FILE_TRIMMED" | ||
1041 | , "PINNED_TO_MAIN" | ||
1042 | , "PINNED_TO_TIER2" | ||
1043 | , "HAS_RSRC_FORK" | ||
1044 | , "NO_RSRC_FORK" | ||
1045 | , "ALLOCATION_SPILLEDOVER" | ||
1046 | , "FAST_PROMOTE" | ||
1047 | , "HAS_UNCOMPRESSED_SIZE" | ||
1048 | , "IS_PURGEABLE" | ||
1049 | , "WANTS_TO_BE_PURGEABLE" | ||
1050 | , "IS_SYNC_ROOT" | ||
1051 | , "SNAPSHOT_COW_EXEMPTION" | ||
1052 | }; | ||
1053 | |||
1054 | |||
1055 | // bsd stat.h | ||
1056 | /* | ||
1057 | #define MY__UF_SETTABLE 0x0000ffff // mask of owner changeable flags | ||
1058 | #define MY__UF_NODUMP 0x00000001 // do not dump file | ||
1059 | #define MY__UF_IMMUTABLE 0x00000002 // file may not be changed | ||
1060 | #define MY__UF_APPEND 0x00000004 // writes to file may only append | ||
1061 | #define MY__UF_OPAQUE 0x00000008 // directory is opaque wrt. union | ||
1062 | #define MY__UF_NOUNLINK 0x00000010 // file entry may not be removed or renamed Not implement in MacOS | ||
1063 | #define MY__UF_COMPRESSED 0x00000020 // file entry is compressed | ||
1064 | #define MY__UF_TRACKED 0x00000040 // notify about file entry changes | ||
1065 | #define MY__UF_DATAVAULT 0x00000080 // entitlement required for reading and writing | ||
1066 | #define MY__UF_HIDDEN 0x00008000 // file entry is hidden | ||
1067 | |||
1068 | #define MY__SF_SETTABLE 0xffff0000 // mask of superuser changeable flags | ||
1069 | #define MY__SF_ARCHIVED 0x00010000 // file is archived | ||
1070 | #define MY__SF_IMMUTABLE 0x00020000 // file may not be changed | ||
1071 | #define MY__SF_APPEND 0x00040000 // writes to file may only append | ||
1072 | #define MY__SF_RESTRICTED 0x00080000 // entitlement required for writing | ||
1073 | #define MY__SF_NOUNLINK 0x00100000 // file entry may not be removed, renamed or used as mount point | ||
1074 | #define MY__SF_SNAPSHOT 0x00200000 // snapshot inode | ||
1075 | Not implement in MacOS | ||
1076 | */ | ||
1077 | |||
1078 | static const char * const g_INODE_BSD_Flags[] = | ||
1079 | { | ||
1080 | "UF_NODUMP" | ||
1081 | , "UF_IMMUTABLE" | ||
1082 | , "UF_APPEND" | ||
1083 | , "UF_OPAQUE" | ||
1084 | , "UF_NOUNLINK" | ||
1085 | , "UF_COMPRESSED" | ||
1086 | , "UF_TRACKED" | ||
1087 | , "UF_DATAVAULT" | ||
1088 | , NULL, NULL, NULL, NULL | ||
1089 | , NULL, NULL, NULL | ||
1090 | , "UF_HIDDEN" | ||
1091 | |||
1092 | , "SF_ARCHIVE" | ||
1093 | , "SF_IMMUTABLE" | ||
1094 | , "SF_APPEND" | ||
1095 | , "SF_RESTRICTED" | ||
1096 | , "SF_NOUNLINK" | ||
1097 | , "SF_SNAPSHOT" | ||
1098 | }; | ||
1099 | |||
1100 | /* | ||
1101 | #define INO_EXT_TYPE_SNAP_XID 1 | ||
1102 | #define INO_EXT_TYPE_DELTA_TREE_OID 2 | ||
1103 | #define INO_EXT_TYPE_DOCUMENT_ID 3 | ||
1104 | */ | ||
1105 | #define INO_EXT_TYPE_NAME 4 | ||
1106 | /* | ||
1107 | #define INO_EXT_TYPE_PREV_FSIZE 5 | ||
1108 | #define INO_EXT_TYPE_RESERVED_6 6 | ||
1109 | #define INO_EXT_TYPE_FINDER_INFO 7 | ||
1110 | */ | ||
1111 | #define INO_EXT_TYPE_DSTREAM 8 | ||
1112 | /* | ||
1113 | #define INO_EXT_TYPE_RESERVED_9 9 | ||
1114 | #define INO_EXT_TYPE_DIR_STATS_KEY 10 | ||
1115 | #define INO_EXT_TYPE_FS_UUID 11 | ||
1116 | #define INO_EXT_TYPE_RESERVED_12 12 | ||
1117 | #define INO_EXT_TYPE_SPARSE_BYTES 13 | ||
1118 | #define INO_EXT_TYPE_RDEV 14 | ||
1119 | #define INO_EXT_TYPE_PURGEABLE_FLAGS 15 | ||
1120 | #define INO_EXT_TYPE_ORIG_SYNC_ROOT_ID 16 | ||
1121 | */ | ||
1122 | |||
1123 | |||
1124 | static const unsigned k_SizeOf_j_dstream = 8 * 5; | ||
1125 | |||
1126 | struct j_dstream | ||
1127 | { | ||
1128 | UInt64 size; | ||
1129 | UInt64 alloced_size; | ||
1130 | UInt64 default_crypto_id; | ||
1131 | UInt64 total_bytes_written; | ||
1132 | UInt64 total_bytes_read; | ||
1133 | |||
1134 | void Parse(const Byte *p) | ||
1135 | { | ||
1136 | G64 (0, size); | ||
1137 | G64 (0x8, alloced_size); | ||
1138 | G64 (0x10, default_crypto_id); | ||
1139 | G64 (0x18, total_bytes_written); | ||
1140 | G64 (0x20, total_bytes_read); | ||
1141 | } | ||
1142 | }; | ||
1143 | |||
1144 | static const unsigned k_SizeOf_j_file_extent_val = 8 * 3; | ||
1145 | |||
1146 | #define J_FILE_EXTENT_LEN_MASK 0x00ffffffffffffffU | ||
1147 | // #define J_FILE_EXTENT_FLAG_MASK 0xff00000000000000U | ||
1148 | // #define J_FILE_EXTENT_FLAG_SHIFT 56 | ||
1149 | |||
1150 | #define EXTENT_GET_LEN(x) ((x) & J_FILE_EXTENT_LEN_MASK) | ||
1151 | |||
1152 | struct j_file_extent_val | ||
1153 | { | ||
1154 | UInt64 len_and_flags; // The length must be a multiple of the block size defined by the nx_block_size field of nx_superblock_t. | ||
1155 | // There are currently no flags defined | ||
1156 | UInt64 phys_block_num; // The physical block address that the extent starts at | ||
1157 | // UInt64 crypto_id; // The encryption key or the encryption tweak used in this extent. | ||
1158 | |||
1159 | void Parse(const Byte *p) | ||
1160 | { | ||
1161 | G64 (0, len_and_flags); | ||
1162 | G64 (0x8, phys_block_num); | ||
1163 | // G64 (0x10, crypto_id); | ||
1164 | } | ||
1165 | }; | ||
1166 | |||
1167 | |||
1168 | struct CExtent | ||
1169 | { | ||
1170 | UInt64 logical_offset; | ||
1171 | UInt64 len_and_flags; // The length must be a multiple of the block size defined by the nx_block_size field of nx_superblock_t. | ||
1172 | // There are currently no flags defined | ||
1173 | UInt64 phys_block_num; // The physical block address that the extent starts at | ||
1174 | }; | ||
1175 | |||
1176 | |||
1177 | typedef UInt32 MY__uid_t; | ||
1178 | typedef UInt32 MY__gid_t; | ||
1179 | typedef UInt16 MY__mode_t; | ||
1180 | |||
1181 | |||
1182 | typedef enum | ||
1183 | { | ||
1184 | XATTR_DATA_STREAM = 1 << 0, | ||
1185 | XATTR_DATA_EMBEDDED = 1 << 1, | ||
1186 | XATTR_FILE_SYSTEM_OWNED = 1 << 2, | ||
1187 | XATTR_RESERVED_8 = 1 << 3 | ||
1188 | } j_xattr_flags; | ||
1189 | |||
1190 | |||
1191 | struct CAttr | ||
1192 | { | ||
1193 | AString Name; | ||
1194 | UInt32 flags; | ||
1195 | CByteBuffer Data; | ||
1196 | |||
1197 | j_dstream dstream; | ||
1198 | bool dstream_defined; | ||
1199 | UInt64 Id; | ||
1200 | |||
1201 | bool Is_dstream_OK_for_SymLink() const | ||
1202 | { | ||
1203 | return dstream_defined && dstream.size <= (1 << 12) && dstream.size != 0; | ||
1204 | } | ||
1205 | |||
1206 | CAttr(): | ||
1207 | dstream_defined(false) | ||
1208 | {} | ||
1209 | |||
1210 | bool Is_STREAM() const { return (flags & XATTR_DATA_STREAM) != 0; } | ||
1211 | bool Is_EMBEDDED() const { return (flags & XATTR_DATA_EMBEDDED) != 0; } | ||
1212 | }; | ||
1213 | |||
1214 | |||
1215 | // j_inode_val_t | ||
1216 | struct CNode | ||
1217 | { | ||
1218 | unsigned ItemIndex; // index to CItem. We set it only if Node is directory. | ||
1219 | unsigned NumCalcedLinks; // Num links to that node | ||
1220 | // unsigned NumItems; // Num Items in that node | ||
1221 | |||
1222 | UInt64 parent_id; // The identifier of the file system record for the parent directory. | ||
1223 | UInt64 private_id; | ||
1224 | UInt64 create_time; | ||
1225 | UInt64 mod_time; | ||
1226 | UInt64 change_time; | ||
1227 | UInt64 access_time; | ||
1228 | UInt64 internal_flags; | ||
1229 | union | ||
1230 | { | ||
1231 | UInt32 nchildren; /* The number of directory entries. | ||
1232 | is valid only if the inode is a directory */ | ||
1233 | UInt32 nlink; /* The number of hard links whose target is this inode. | ||
1234 | is valid only if the inode isn't a directory. | ||
1235 | Inodes with multiple hard links (nlink > 1) | ||
1236 | - The parent_id field refers to the parent directory of the primary link. | ||
1237 | - The name field contains the name of the primary link. | ||
1238 | - The INO_EXT_TYPE_NAME extended field contains the name of this link. | ||
1239 | */ | ||
1240 | }; | ||
1241 | // cp_key_class_t default_protection_class; | ||
1242 | UInt32 write_generation_counter; | ||
1243 | UInt32 bsd_flags; | ||
1244 | MY__uid_t owner; | ||
1245 | MY__gid_t group; | ||
1246 | MY__mode_t mode; | ||
1247 | UInt16 pad1; | ||
1248 | // UInt64 uncompressed_size; | ||
1249 | |||
1250 | j_dstream dstream; | ||
1251 | AString PrimaryName; | ||
1252 | bool dstream_defined; | ||
1253 | bool refcnt_defined; | ||
1254 | UInt32 refcnt; // j_dstream_id_val_t | ||
1255 | CRecordVector<CExtent> Extents; | ||
1256 | CObjectVector<CAttr> Attrs; | ||
1257 | unsigned SymLinkIndex; // index in Attrs | ||
1258 | |||
1259 | CNode(): | ||
1260 | ItemIndex(VI_MINUS1), | ||
1261 | NumCalcedLinks(0), | ||
1262 | // NumItems(0), | ||
1263 | dstream_defined(false), | ||
1264 | refcnt_defined(false), | ||
1265 | SymLinkIndex(VI_MINUS1) | ||
1266 | {} | ||
1267 | |||
1268 | bool IsDir() const { return MY_LIN_S_ISDIR(mode); } | ||
1269 | bool IsSymLink() const { return MY_LIN_S_ISLNK(mode); } | ||
1270 | unsigned Get_Type_From_mode() const { return mode >> 12; } | ||
1271 | |||
1272 | bool GetSize(unsigned attrIndex, UInt64 &size) const | ||
1273 | { | ||
1274 | if (IsViNotDef(attrIndex)) | ||
1275 | { | ||
1276 | if (dstream_defined) | ||
1277 | { | ||
1278 | size = dstream.size; | ||
1279 | return true; | ||
1280 | } | ||
1281 | if (!IsSymLink()) | ||
1282 | return false; | ||
1283 | attrIndex = SymLinkIndex; | ||
1284 | if (IsViNotDef(attrIndex)) | ||
1285 | return false; | ||
1286 | } | ||
1287 | const CAttr &attr = Attrs[(unsigned)attrIndex]; | ||
1288 | if (attr.dstream_defined) | ||
1289 | size = attr.dstream.size; | ||
1290 | else | ||
1291 | size = attr.Data.Size(); | ||
1292 | return true; | ||
1293 | } | ||
1294 | |||
1295 | bool GetPackSize(unsigned attrIndex, UInt64 &size) const | ||
1296 | { | ||
1297 | if (IsViNotDef(attrIndex)) | ||
1298 | { | ||
1299 | if (dstream_defined) | ||
1300 | { | ||
1301 | size = dstream.alloced_size; | ||
1302 | return true; | ||
1303 | } | ||
1304 | if (!IsSymLink()) | ||
1305 | return false; | ||
1306 | attrIndex = SymLinkIndex; | ||
1307 | if (IsViNotDef(attrIndex)) | ||
1308 | return false; | ||
1309 | } | ||
1310 | const CAttr &attr = Attrs[(unsigned)attrIndex]; | ||
1311 | if (attr.dstream_defined) | ||
1312 | size = attr.dstream.alloced_size; | ||
1313 | else | ||
1314 | size = attr.Data.Size(); | ||
1315 | return true; | ||
1316 | } | ||
1317 | |||
1318 | void Parse(const Byte *p); | ||
1319 | }; | ||
1320 | |||
1321 | |||
1322 | // it's used for Attr streams | ||
1323 | struct CSmallNode | ||
1324 | { | ||
1325 | CRecordVector<CExtent> Extents; | ||
1326 | // UInt32 NumLinks; | ||
1327 | // CSmallNode(): NumLinks(0) {}; | ||
1328 | }; | ||
1329 | |||
1330 | static const unsigned k_SizeOf_j_inode_val = 0x5c; | ||
1331 | |||
1332 | void CNode::Parse(const Byte *p) | ||
1333 | { | ||
1334 | G64 (0, parent_id); | ||
1335 | G64 (0x8, private_id); | ||
1336 | G64 (0x10, create_time); | ||
1337 | G64 (0x18, mod_time); | ||
1338 | G64 (0x20, change_time); | ||
1339 | G64 (0x28, access_time); | ||
1340 | G64 (0x30, internal_flags); | ||
1341 | { | ||
1342 | G32(0x38, nchildren); | ||
1343 | // G32(0x38, nlink); | ||
1344 | } | ||
1345 | // G32(0x3c, default_protection_class); | ||
1346 | G32(0x40, write_generation_counter); | ||
1347 | G32(0x44, bsd_flags); | ||
1348 | G32(0x48, owner); | ||
1349 | G32(0x4c, group); | ||
1350 | G16(0x50, mode); | ||
1351 | // G16(0x52, pad1); | ||
1352 | // G64 (0x54, uncompressed_size); | ||
1353 | } | ||
1354 | |||
1355 | |||
1356 | struct CRef | ||
1357 | { | ||
1358 | unsigned ItemIndex; | ||
1359 | unsigned NodeIndex; | ||
1360 | unsigned ParentRefIndex; | ||
1361 | |||
1362 | #ifdef APFS_SHOW_ALT_STREAMS | ||
1363 | unsigned AttrIndex; | ||
1364 | bool IsAltStream() const { return IsViDef(AttrIndex); } | ||
1365 | unsigned GetAttrIndex() const { return AttrIndex; }; | ||
1366 | #else | ||
1367 | unsigned GetAttrIndex() const { return VI_MINUS1; }; | ||
1368 | #endif | ||
1369 | }; | ||
1370 | |||
1371 | |||
1372 | struct CRef2 | ||
1373 | { | ||
1374 | unsigned VolIndex; | ||
1375 | unsigned RefIndex; | ||
1376 | }; | ||
1377 | |||
1378 | |||
1379 | struct CVol | ||
1380 | { | ||
1381 | CObjectVector<CNode> Nodes; | ||
1382 | CRecordVector<UInt64> NodeIDs; | ||
1383 | CObjectVector<CItem> Items; | ||
1384 | CRecordVector<CRef> Refs; | ||
1385 | |||
1386 | CObjectVector<CSmallNode> SmallNodes; | ||
1387 | CRecordVector<UInt64> SmallNodeIDs; | ||
1388 | |||
1389 | unsigned StartRef2Index; // ref2_Index for Refs[0] item | ||
1390 | unsigned RootRef2Index; // ref2_Index of virtual root folder (Volume1) | ||
1391 | CApfs apfs; | ||
1392 | bool NodeNotFound; | ||
1393 | bool ThereAreUnlinkedNodes; | ||
1394 | bool WrongInodeLink; | ||
1395 | bool UnsupportedFeature; | ||
1396 | |||
1397 | unsigned NumItems_In_PrivateDir; | ||
1398 | unsigned NumAltStreams; | ||
1399 | |||
1400 | UString RootName; | ||
1401 | |||
1402 | bool ThereAreErrors() const | ||
1403 | { | ||
1404 | return NodeNotFound || ThereAreUnlinkedNodes || WrongInodeLink; | ||
1405 | } | ||
1406 | |||
1407 | void AddComment(UString &s) const; | ||
1408 | |||
1409 | HRESULT FillRefs(); | ||
1410 | |||
1411 | CVol(): | ||
1412 | StartRef2Index(0), | ||
1413 | RootRef2Index(VI_MINUS1), | ||
1414 | NodeNotFound(false), | ||
1415 | ThereAreUnlinkedNodes(false), | ||
1416 | WrongInodeLink(false), | ||
1417 | UnsupportedFeature(false), | ||
1418 | NumItems_In_PrivateDir(0), | ||
1419 | NumAltStreams(0) | ||
1420 | {} | ||
1421 | }; | ||
1422 | |||
1423 | |||
1424 | static void ApfsTimeToFileTime(UInt64 apfsTime, FILETIME &ft, UInt32 &ns100) | ||
1425 | { | ||
1426 | const UInt64 s = apfsTime / 1000000000; | ||
1427 | const UInt32 ns = (UInt32)(apfsTime % 1000000000); | ||
1428 | ns100 = (ns % 100); | ||
1429 | const UInt64 v = NWindows::NTime::UnixTime64_To_FileTime64(s) + ns / 100; | ||
1430 | ft.dwLowDateTime = (DWORD)v; | ||
1431 | ft.dwHighDateTime = (DWORD)(v >> 32); | ||
1432 | } | ||
1433 | |||
1434 | static void AddComment_Name(UString &s, const char *name) | ||
1435 | { | ||
1436 | s += name; | ||
1437 | s += ": "; | ||
1438 | } | ||
1439 | |||
1440 | /* | ||
1441 | static void AddComment_Bool(UString &s, const char *name, bool val) | ||
1442 | { | ||
1443 | AddComment_Name(s, name); | ||
1444 | s += val ? "+" : "-"; | ||
1445 | s.Add_LF(); | ||
1446 | } | ||
1447 | */ | ||
1448 | |||
1449 | static void AddComment_UInt64(UString &s, const char *name, UInt64 v) | ||
1450 | { | ||
1451 | AddComment_Name(s, name); | ||
1452 | s.Add_UInt64(v); | ||
1453 | s.Add_LF(); | ||
1454 | } | ||
1455 | |||
1456 | |||
1457 | static void AddComment_Time(UString &s, const char *name, UInt64 v) | ||
1458 | { | ||
1459 | AddComment_Name(s, name); | ||
1460 | |||
1461 | FILETIME ft; | ||
1462 | UInt32 ns100; | ||
1463 | ApfsTimeToFileTime(v, ft, ns100); | ||
1464 | char temp[64]; | ||
1465 | ConvertUtcFileTimeToString2(ft, ns100, temp | ||
1466 | // , kTimestampPrintLevel_SEC); | ||
1467 | , kTimestampPrintLevel_NS); | ||
1468 | s += temp; | ||
1469 | s.Add_LF(); | ||
1470 | } | ||
1471 | |||
1472 | |||
1473 | static void AddComment_modified_by_t(UString &s, const char *name, const apfs_modified_by_t &v) | ||
1474 | { | ||
1475 | AddComment_Name(s, name); | ||
1476 | AString s2; | ||
1477 | s2.SetFrom_CalcLen((const char *)v.id, sizeof(v.id)); | ||
1478 | s += s2; | ||
1479 | s.Add_LF(); | ||
1480 | s += " "; | ||
1481 | AddComment_Time(s, "timestamp", v.timestamp); | ||
1482 | s += " "; | ||
1483 | AddComment_UInt64(s, "last_xid", v.last_xid); | ||
1484 | } | ||
1485 | |||
1486 | |||
1487 | static void AddVolInternalName_toString(UString &s, const CApfs &apfs) | ||
1488 | { | ||
1489 | AString temp; | ||
1490 | temp.SetFrom_CalcLen((const char *)apfs.volname, sizeof(apfs.volname)); | ||
1491 | UString unicode; | ||
1492 | ConvertUTF8ToUnicode(temp, unicode); | ||
1493 | s += unicode; | ||
1494 | } | ||
1495 | |||
1496 | |||
1497 | void CVol::AddComment(UString &s) const | ||
1498 | { | ||
1499 | AddComment_UInt64(s, "fs_index", apfs.fs_index); | ||
1500 | { | ||
1501 | AddComment_Name(s, "volume_name"); | ||
1502 | AddVolInternalName_toString(s, apfs); | ||
1503 | s.Add_LF(); | ||
1504 | } | ||
1505 | AddComment_Name(s, "vol_uuid"); | ||
1506 | apfs.vol_uuid.AddHexToString(s); | ||
1507 | s.Add_LF(); | ||
1508 | |||
1509 | AddComment_Name(s, "incompatible_features"); | ||
1510 | s += FlagsToString(g_APFS_INCOMPAT_Flags, | ||
1511 | ARRAY_SIZE(g_APFS_INCOMPAT_Flags), | ||
1512 | (UInt32)apfs.incompatible_features); | ||
1513 | s.Add_LF(); | ||
1514 | |||
1515 | // AddComment_UInt64(s, "reserve_block_count", apfs.fs_reserve_block_count, false); | ||
1516 | // AddComment_UInt64(s, "quota_block_count", apfs.fs_quota_block_count); | ||
1517 | AddComment_UInt64(s, "fs_alloc_count", apfs.fs_alloc_count); | ||
1518 | |||
1519 | AddComment_UInt64(s, "num_files", apfs.num_files); | ||
1520 | AddComment_UInt64(s, "num_directories", apfs.num_directories); | ||
1521 | AddComment_UInt64(s, "num_symlinks", apfs.num_symlinks); | ||
1522 | AddComment_UInt64(s, "num_other_fsobjects", apfs.num_other_fsobjects); | ||
1523 | |||
1524 | AddComment_UInt64(s, "Num_Attr_Streams", NumAltStreams); | ||
1525 | |||
1526 | AddComment_UInt64(s, "num_snapshots", apfs.num_snapshots); | ||
1527 | AddComment_UInt64(s, "total_blocks_alloced", apfs.total_blocks_alloced); | ||
1528 | AddComment_UInt64(s, "total_blocks_freed", apfs.total_blocks_freed); | ||
1529 | |||
1530 | AddComment_Time(s, "unmounted", apfs.unmount_time); | ||
1531 | AddComment_Time(s, "last_modified", apfs.last_mod_time); | ||
1532 | AddComment_modified_by_t(s, "formatted_by", apfs.formatted_by); | ||
1533 | for (unsigned i = 0; i < ARRAY_SIZE(apfs.modified_by); i++) | ||
1534 | { | ||
1535 | const apfs_modified_by_t &v = apfs.modified_by[i]; | ||
1536 | if (v.last_xid == 0 && v.timestamp == 0 && v.id[0] == 0) | ||
1537 | continue; | ||
1538 | AString name ("modified_by["); | ||
1539 | name.Add_UInt32(i); | ||
1540 | name += ']'; | ||
1541 | AddComment_modified_by_t(s, name.Ptr(), v); | ||
1542 | } | ||
1543 | } | ||
1544 | |||
1545 | |||
1546 | |||
1547 | struct CKeyValPair | ||
1548 | { | ||
1549 | CByteBuffer Key; | ||
1550 | CByteBuffer Val; | ||
1551 | // unsigned ValPos; // for alognment | ||
1552 | }; | ||
1553 | |||
1554 | |||
1555 | struct omap_key | ||
1556 | { | ||
1557 | oid_t oid; // The object identifier | ||
1558 | xid_t xid; // The transaction identifier | ||
1559 | void Parse(const Byte *p) | ||
1560 | { | ||
1561 | G64o (0, oid); | ||
1562 | G64x (8, xid); | ||
1563 | } | ||
1564 | }; | ||
1565 | |||
1566 | /* | ||
1567 | #define OMAP_VAL_DELETED (1 << 0) | ||
1568 | #define OMAP_VAL_SAVED (1 << 1) | ||
1569 | #define OMAP_VAL_ENCRYPTED (1 << 2) | ||
1570 | #define OMAP_VAL_NOHEADER (1 << 3) | ||
1571 | #define OMAP_VAL_CRYPTO_GENERATION (1 << 4) | ||
1572 | */ | ||
1573 | |||
1574 | struct omap_val | ||
1575 | { | ||
1576 | UInt32 flags; | ||
1577 | UInt32 size; | ||
1578 | paddr_t paddr; | ||
1579 | |||
1580 | void Parse(const Byte *p) | ||
1581 | { | ||
1582 | G32 (0, flags); | ||
1583 | G32 (4, size); | ||
1584 | G64 (8, paddr); | ||
1585 | } | ||
1586 | }; | ||
1587 | |||
1588 | |||
1589 | struct CObjectMap | ||
1590 | { | ||
1591 | CRecordVector<UInt64> Keys; | ||
1592 | CRecordVector<omap_val> Vals; | ||
1593 | |||
1594 | bool Parse(const CObjectVector<CKeyValPair> &pairs); | ||
1595 | int FindKey(UInt64 id) const { return Keys.FindInSorted(id); } | ||
1596 | }; | ||
1597 | |||
1598 | bool CObjectMap::Parse(const CObjectVector<CKeyValPair> &pairs) | ||
1599 | { | ||
1600 | omap_key prev; | ||
1601 | prev.oid = 0; | ||
1602 | prev.xid = 0; | ||
1603 | FOR_VECTOR (i, pairs) | ||
1604 | { | ||
1605 | const CKeyValPair &pair = pairs[i]; | ||
1606 | if (pair.Key.Size() != 16 || pair.Val.Size() != 16) | ||
1607 | return false; | ||
1608 | omap_key key; | ||
1609 | key.Parse(pair.Key); | ||
1610 | omap_val val; | ||
1611 | val.Parse(pair.Val); | ||
1612 | /* Object map B-trees are sorted by object identifier and then by transaction identifier | ||
1613 | but it's possible to have identical Ids in map ? | ||
1614 | do we need to look transaction id ? | ||
1615 | and search key with largest transaction id? */ | ||
1616 | if (key.oid <= prev.oid) | ||
1617 | return false; | ||
1618 | prev = key; | ||
1619 | Keys.Add(key.oid); | ||
1620 | Vals.Add(val); | ||
1621 | } | ||
1622 | return true; | ||
1623 | } | ||
1624 | |||
1625 | |||
1626 | struct CMap | ||
1627 | { | ||
1628 | CObjectVector<CKeyValPair> Pairs; | ||
1629 | |||
1630 | CObjectMap Omap; | ||
1631 | btree_info bti; | ||
1632 | UInt64 NumNodes; | ||
1633 | |||
1634 | // we use thnese options to check: | ||
1635 | UInt32 Subtype; | ||
1636 | bool IsPhysical; | ||
1637 | |||
1638 | bool CheckAtFinish() const | ||
1639 | { | ||
1640 | return NumNodes == bti.node_count && Pairs.Size() == bti.key_count; | ||
1641 | } | ||
1642 | |||
1643 | CMap(): | ||
1644 | NumNodes(0), | ||
1645 | Subtype(0), | ||
1646 | IsPhysical(true) | ||
1647 | {} | ||
1648 | }; | ||
1649 | |||
1650 | |||
1651 | |||
1652 | struct CDatabase | ||
1653 | { | ||
1654 | CRecordVector<CRef2> Refs2; | ||
1655 | CObjectVector<CVol> Vols; | ||
1656 | |||
1657 | bool HeadersError; | ||
1658 | bool ThereAreAltStreams; | ||
1659 | bool UnsupportedFeature; | ||
1660 | |||
1661 | CSuperBlock sb; | ||
1662 | |||
1663 | IInStream *OpenInStream; | ||
1664 | IArchiveOpenCallback *OpenCallback; | ||
1665 | UInt64 ProgressVal_Cur; | ||
1666 | UInt64 ProgressVal_Prev; | ||
1667 | UInt64 ProgressVal_NumFilesTotal; | ||
1668 | CObjectVector<CByteBuffer> Buffers; | ||
1669 | |||
1670 | UInt64 GetSize(const UInt32 index) const; | ||
1671 | |||
1672 | void Clear() | ||
1673 | { | ||
1674 | HeadersError = false; | ||
1675 | UnsupportedFeature = false; | ||
1676 | ThereAreAltStreams = false; | ||
1677 | |||
1678 | ProgressVal_Cur = 0; | ||
1679 | ProgressVal_Prev = 0; | ||
1680 | ProgressVal_NumFilesTotal = 0; | ||
1681 | |||
1682 | Vols.Clear(); | ||
1683 | Refs2.Clear(); | ||
1684 | Buffers.Clear(); | ||
1685 | } | ||
1686 | |||
1687 | HRESULT SeekReadBlock_FALSE(UInt64 oid, void *data); | ||
1688 | void GetItemPath(unsigned index, const CNode *inode, NWindows::NCOM::CPropVariant &path) const; | ||
1689 | HRESULT ReadMap(UInt64 oid, CMap &map, unsigned recurseLevel); | ||
1690 | HRESULT ReadObjectMap(UInt64 oid, CObjectMap &map); | ||
1691 | HRESULT OpenVolume(const CObjectMap &omap, const oid_t fs_oid); | ||
1692 | HRESULT Open2(); | ||
1693 | |||
1694 | HRESULT GetStream2( | ||
1695 | IInStream *apfsInStream, | ||
1696 | const CRecordVector<CExtent> *extents, UInt64 rem, | ||
1697 | ISequentialInStream **stream); | ||
1698 | }; | ||
1699 | |||
1700 | |||
1701 | HRESULT CDatabase::SeekReadBlock_FALSE(UInt64 oid, void *data) | ||
1702 | { | ||
1703 | if (OpenCallback) | ||
1704 | { | ||
1705 | if (ProgressVal_Cur - ProgressVal_Prev >= (1 << 22)) | ||
1706 | { | ||
1707 | RINOK(OpenCallback->SetCompleted(NULL, &ProgressVal_Cur)); | ||
1708 | ProgressVal_Prev = ProgressVal_Cur; | ||
1709 | } | ||
1710 | ProgressVal_Cur += sb.block_size; | ||
1711 | } | ||
1712 | if (oid == 0 || oid >= sb.block_count) | ||
1713 | return S_FALSE; | ||
1714 | RINOK(OpenInStream->Seek(oid << sb.block_size_Log, STREAM_SEEK_SET, NULL)); | ||
1715 | return ReadStream_FALSE(OpenInStream, data, sb.block_size); | ||
1716 | } | ||
1717 | |||
1718 | |||
1719 | |||
1720 | API_FUNC_static_IsArc IsArc_APFS(const Byte *p, size_t size) | ||
1721 | { | ||
1722 | if (size < kApfsHeaderSize) | ||
1723 | return k_IsArc_Res_NEED_MORE; | ||
1724 | CSuperBlock sb; | ||
1725 | if (!sb.Parse(p)) | ||
1726 | return k_IsArc_Res_NO; | ||
1727 | return k_IsArc_Res_YES; | ||
1728 | } | ||
1729 | } | ||
1730 | |||
1731 | |||
1732 | |||
1733 | HRESULT CDatabase::ReadMap(UInt64 oid, CMap &map, unsigned recurseLevel) | ||
1734 | { | ||
1735 | // is it allowed to use big number of levels ? | ||
1736 | if (recurseLevel > (1 << 10)) | ||
1737 | return S_FALSE; | ||
1738 | |||
1739 | const UInt32 blockSize = sb.block_size; | ||
1740 | if (Buffers.Size() <= recurseLevel) | ||
1741 | { | ||
1742 | Buffers.AddNew(); | ||
1743 | if (Buffers.Size() <= recurseLevel) | ||
1744 | throw 123; | ||
1745 | Buffers.Back().Alloc(blockSize); | ||
1746 | } | ||
1747 | const Byte *buf; | ||
1748 | { | ||
1749 | CByteBuffer &buf2 = Buffers[recurseLevel]; | ||
1750 | RINOK(SeekReadBlock_FALSE(oid, buf2)); | ||
1751 | buf = buf2; | ||
1752 | } | ||
1753 | |||
1754 | CBTreeNodePhys bt; | ||
1755 | if (!bt.Parse(buf, blockSize)) | ||
1756 | return S_FALSE; | ||
1757 | |||
1758 | map.NumNodes++; | ||
1759 | |||
1760 | /* Specification: All values are stored in leaf nodes, which | ||
1761 | makes these B+ trees, and the values in nonleaf nodes are object | ||
1762 | identifiers of child nodes. | ||
1763 | |||
1764 | The entries in the table of contents are sorted by key. The comparison function used for sorting depends on the keys type | ||
1765 | - Object map B-trees are sorted by object identifier and then by transaction identifier. | ||
1766 | - Free queue B-trees are sorted by transaction identifier and then by physical address. | ||
1767 | - File-system records are sorted according to the rules listed in File-System Objects. | ||
1768 | */ | ||
1769 | |||
1770 | if (bt.o.subtype != map.Subtype) | ||
1771 | return S_FALSE; | ||
1772 | |||
1773 | unsigned endLimit = blockSize; | ||
1774 | |||
1775 | if (recurseLevel == 0) | ||
1776 | { | ||
1777 | if (bt.o.GetType() != OBJECT_TYPE_BTREE) | ||
1778 | return S_FALSE; | ||
1779 | if ((bt.flags & BTNODE_ROOT) == 0) | ||
1780 | return S_FALSE; | ||
1781 | endLimit -= k_btree_info_Size; | ||
1782 | map.bti.Parse(buf + endLimit); | ||
1783 | btree_info &bti = map.bti; | ||
1784 | if (bti.fixed.key_size >= blockSize) | ||
1785 | return S_FALSE; | ||
1786 | if (bti.Is_EPHEMERAL() && | ||
1787 | bti.Is_PHYSICAL()) | ||
1788 | return S_FALSE; | ||
1789 | if (bti.Is_PHYSICAL() != map.IsPhysical) | ||
1790 | return S_FALSE; | ||
1791 | // we don't allow volumes with big number of Keys | ||
1792 | const UInt32 kNumItemsMax = k_VectorSizeMax; | ||
1793 | if (map.bti.node_count > kNumItemsMax) | ||
1794 | return S_FALSE; | ||
1795 | if (map.bti.key_count > kNumItemsMax) | ||
1796 | return S_FALSE; | ||
1797 | } | ||
1798 | else | ||
1799 | { | ||
1800 | if (bt.o.GetType() != OBJECT_TYPE_BTREE_NODE) | ||
1801 | return S_FALSE; | ||
1802 | if ((bt.flags & BTNODE_ROOT) != 0) | ||
1803 | return S_FALSE; | ||
1804 | if (map.NumNodes > map.bti.node_count | ||
1805 | || map.Pairs.Size() > map.bti.key_count) | ||
1806 | return S_FALSE; | ||
1807 | } | ||
1808 | |||
1809 | const bool isLeaf = (bt.flags & BTNODE_LEAF) != 0; | ||
1810 | |||
1811 | if (isLeaf) | ||
1812 | { | ||
1813 | if (bt.level != 0) | ||
1814 | return S_FALSE; | ||
1815 | } | ||
1816 | else | ||
1817 | { | ||
1818 | if (bt.level == 0) | ||
1819 | return S_FALSE; | ||
1820 | } | ||
1821 | |||
1822 | if (!bt.table_space.CheckOverLimit(endLimit - k_Toc_offset)) | ||
1823 | return S_FALSE; | ||
1824 | |||
1825 | const unsigned tableEnd = k_Toc_offset + bt.table_space.GetEnd(); | ||
1826 | const unsigned keyValRange = endLimit - tableEnd; | ||
1827 | const unsigned tocEntrySize = bt.Is_FIXED_KV_SIZE() ? 4 : 8; | ||
1828 | if (bt.table_space.len / tocEntrySize < bt.nkeys) | ||
1829 | return S_FALSE; | ||
1830 | |||
1831 | for (unsigned i = 0; i < bt.nkeys; i++) | ||
1832 | { | ||
1833 | const Byte *p = buf + k_Toc_offset + bt.table_space.off + i * tocEntrySize; | ||
1834 | if (bt.Is_FIXED_KV_SIZE()) | ||
1835 | { | ||
1836 | kvoff a; | ||
1837 | a.Parse(p); | ||
1838 | if (a.k + map.bti.fixed.key_size > keyValRange | ||
1839 | || a.v > keyValRange) | ||
1840 | return S_FALSE; | ||
1841 | { | ||
1842 | CKeyValPair pair; | ||
1843 | |||
1844 | const Byte *p2 = buf + k_Toc_offset + bt.table_space.len; | ||
1845 | p2 += a.k; | ||
1846 | pair.Key.CopyFrom(p2, map.bti.fixed.key_size); | ||
1847 | |||
1848 | p2 = buf + endLimit; | ||
1849 | p2 -= a.v; | ||
1850 | if (isLeaf) | ||
1851 | { | ||
1852 | if (a.v < map.bti.fixed.val_size) | ||
1853 | return S_FALSE; | ||
1854 | pair.Val.CopyFrom(p2, map.bti.fixed.val_size); | ||
1855 | // pair.ValPos = endLimit - a.v; | ||
1856 | map.Pairs.Add(pair); | ||
1857 | continue; | ||
1858 | } | ||
1859 | { | ||
1860 | if (a.v < 8) | ||
1861 | return S_FALSE; | ||
1862 | // value is only 64-bit for non leaf. | ||
1863 | const oid_t oidNext = Get64(p2); | ||
1864 | if (map.bti.Is_PHYSICAL()) | ||
1865 | { | ||
1866 | RINOK(ReadMap(oidNext, map, recurseLevel + 1)); | ||
1867 | continue; | ||
1868 | } | ||
1869 | else | ||
1870 | { | ||
1871 | // fixme | ||
1872 | return S_FALSE; | ||
1873 | } | ||
1874 | } | ||
1875 | } | ||
1876 | } | ||
1877 | else | ||
1878 | { | ||
1879 | kvloc a; | ||
1880 | a.Parse(p); | ||
1881 | if (!a.k.CheckOverLimit(keyValRange) | ||
1882 | || a.v.off > keyValRange | ||
1883 | || a.v.len > a.v.off) | ||
1884 | return S_FALSE; | ||
1885 | { | ||
1886 | CKeyValPair pair; | ||
1887 | const Byte *p2 = buf + k_Toc_offset + bt.table_space.len; | ||
1888 | p2 += a.k.off; | ||
1889 | pair.Key.CopyFrom(p2, a.k.len); | ||
1890 | |||
1891 | p2 = buf + endLimit; | ||
1892 | p2 -= a.v.off; | ||
1893 | if (isLeaf) | ||
1894 | { | ||
1895 | pair.Val.CopyFrom(p2, a.v.len); | ||
1896 | // pair.ValPos = endLimit - a.v.off; | ||
1897 | map.Pairs.Add(pair); | ||
1898 | continue; | ||
1899 | } | ||
1900 | { | ||
1901 | if (a.v.off < 8 || a.v.len != 8) | ||
1902 | return S_FALSE; | ||
1903 | // value is only 64-bit for non leaf. | ||
1904 | const oid_t oidNext = Get64(p2); | ||
1905 | |||
1906 | if (map.bti.Is_PHYSICAL()) | ||
1907 | { | ||
1908 | return S_FALSE; | ||
1909 | // the code was not tested: | ||
1910 | // RINOK(ReadMap(oidNext, map, recurseLevel + 1)); | ||
1911 | // continue; | ||
1912 | } | ||
1913 | else | ||
1914 | { | ||
1915 | const int index = map.Omap.FindKey(oidNext); | ||
1916 | if (index == -1) | ||
1917 | return S_FALSE; | ||
1918 | const omap_val &ov = map.Omap.Vals[(unsigned)index]; | ||
1919 | if (ov.size != blockSize) // change it : it must be multiple of | ||
1920 | return S_FALSE; | ||
1921 | RINOK(ReadMap(ov.paddr, map, recurseLevel + 1)); | ||
1922 | continue; | ||
1923 | } | ||
1924 | } | ||
1925 | } | ||
1926 | } | ||
1927 | } | ||
1928 | |||
1929 | if (recurseLevel == 0) | ||
1930 | if (!map.CheckAtFinish()) | ||
1931 | return S_FALSE; | ||
1932 | return S_OK; | ||
1933 | } | ||
1934 | |||
1935 | |||
1936 | |||
1937 | HRESULT CDatabase::ReadObjectMap(UInt64 oid, CObjectMap &omap) | ||
1938 | { | ||
1939 | CByteBuffer buf; | ||
1940 | const size_t blockSize = sb.block_size; | ||
1941 | buf.Alloc(blockSize); | ||
1942 | RINOK(SeekReadBlock_FALSE(oid, buf)); | ||
1943 | C_omap_phys op; | ||
1944 | if (!op.Parse(buf, blockSize, oid)) | ||
1945 | return S_FALSE; | ||
1946 | CMap map; | ||
1947 | map.Subtype = OBJECT_TYPE_OMAP; | ||
1948 | map.IsPhysical = true; | ||
1949 | RINOK(ReadMap(op.tree_oid, map, 0)); | ||
1950 | if (!omap.Parse(map.Pairs)) | ||
1951 | return S_FALSE; | ||
1952 | return S_OK; | ||
1953 | } | ||
1954 | |||
1955 | |||
1956 | |||
1957 | HRESULT CDatabase::Open2() | ||
1958 | { | ||
1959 | Clear(); | ||
1960 | CSuperBlock2 sb2; | ||
1961 | { | ||
1962 | Byte buf[kApfsHeaderSize]; | ||
1963 | RINOK(ReadStream_FALSE(OpenInStream, buf, kApfsHeaderSize)); | ||
1964 | if (!sb.Parse(buf)) | ||
1965 | return S_FALSE; | ||
1966 | sb2.Parse(buf); | ||
1967 | } | ||
1968 | |||
1969 | { | ||
1970 | CObjectMap omap; | ||
1971 | RINOK(ReadObjectMap(sb.omap_oid, omap)); | ||
1972 | unsigned numRefs = 0; | ||
1973 | for (unsigned i = 0; i < sb.max_file_systems; i++) | ||
1974 | { | ||
1975 | const oid_t oid = sb2.fs_oid[i]; | ||
1976 | if (oid == 0) | ||
1977 | continue; | ||
1978 | // for (unsigned k = 0; k < 1; k++) // for debug | ||
1979 | RINOK(OpenVolume(omap, oid)); | ||
1980 | const unsigned a = Vols.Back().Refs.Size(); | ||
1981 | numRefs += a; | ||
1982 | if (numRefs < a) | ||
1983 | return S_FALSE; // overflow | ||
1984 | } | ||
1985 | } | ||
1986 | |||
1987 | const bool needVolumePrefix = (Vols.Size() > 1); | ||
1988 | // const bool needVolumePrefix = true; // for debug | ||
1989 | { | ||
1990 | unsigned numRefs = 0; | ||
1991 | FOR_VECTOR (i, Vols) | ||
1992 | { | ||
1993 | const unsigned a = Vols[i].Refs.Size(); | ||
1994 | numRefs += a; | ||
1995 | if (numRefs < a) | ||
1996 | return S_FALSE; // overflow | ||
1997 | } | ||
1998 | numRefs += Vols.Size(); | ||
1999 | if (numRefs < Vols.Size()) | ||
2000 | return S_FALSE; // overflow | ||
2001 | Refs2.Reserve(numRefs); | ||
2002 | } | ||
2003 | { | ||
2004 | FOR_VECTOR (i, Vols) | ||
2005 | { | ||
2006 | CVol &vol = Vols[i]; | ||
2007 | |||
2008 | CRef2 ref2; | ||
2009 | ref2.VolIndex = i; | ||
2010 | |||
2011 | if (needVolumePrefix) | ||
2012 | { | ||
2013 | vol.RootName = "Volume"; | ||
2014 | vol.RootName.Add_UInt32(1 + (UInt32)i); | ||
2015 | vol.RootRef2Index = Refs2.Size(); | ||
2016 | ref2.RefIndex = VI_MINUS1; | ||
2017 | Refs2.Add(ref2); | ||
2018 | } | ||
2019 | |||
2020 | vol.StartRef2Index = Refs2.Size(); | ||
2021 | const unsigned numItems = vol.Refs.Size(); | ||
2022 | for (unsigned k = 0; k < numItems; k++) | ||
2023 | { | ||
2024 | ref2.RefIndex = k; | ||
2025 | Refs2.Add(ref2); | ||
2026 | } | ||
2027 | } | ||
2028 | } | ||
2029 | return S_OK; | ||
2030 | } | ||
2031 | |||
2032 | |||
2033 | HRESULT CDatabase::OpenVolume(const CObjectMap &omap, const oid_t fs_oid) | ||
2034 | { | ||
2035 | const size_t blockSize = sb.block_size; | ||
2036 | CByteBuffer buf; | ||
2037 | { | ||
2038 | const int index = omap.FindKey(fs_oid); | ||
2039 | if (index == -1) | ||
2040 | return S_FALSE; | ||
2041 | const omap_val &ov = omap.Vals[(unsigned)index]; | ||
2042 | if (ov.size != blockSize) // change it : it must be multiple of | ||
2043 | return S_FALSE; | ||
2044 | buf.Alloc(blockSize); | ||
2045 | RINOK(SeekReadBlock_FALSE(ov.paddr, buf)); | ||
2046 | } | ||
2047 | |||
2048 | CVol &vol = Vols.AddNew(); | ||
2049 | CApfs &apfs = vol.apfs; | ||
2050 | |||
2051 | if (!apfs.Parse(buf, blockSize)) | ||
2052 | return S_FALSE; | ||
2053 | |||
2054 | /* For each volume, read the root file system tree's virtual object | ||
2055 | identifier from the apfs_root_tree_oid field, | ||
2056 | and then look it up in the volume object map indicated | ||
2057 | by the omap_oid field. */ | ||
2058 | |||
2059 | CMap map; | ||
2060 | { | ||
2061 | ReadObjectMap(apfs.omap_oid, map.Omap); | ||
2062 | const int index = map.Omap.FindKey(apfs.root_tree_oid); | ||
2063 | if (index == -1) | ||
2064 | return S_FALSE; | ||
2065 | const omap_val &ov = map.Omap.Vals[(unsigned)index]; | ||
2066 | if (ov.size != blockSize) // change it : it must be multiple of | ||
2067 | return S_FALSE; | ||
2068 | map.Subtype = OBJECT_TYPE_FSTREE; | ||
2069 | map.IsPhysical = false; | ||
2070 | RINOK(ReadMap(ov.paddr, map, 0)); | ||
2071 | } | ||
2072 | |||
2073 | bool NeedReadSymLink = false; | ||
2074 | |||
2075 | { | ||
2076 | const bool isHashed = apfs.IsHashedName(); | ||
2077 | UInt64 prevId = 1; | ||
2078 | |||
2079 | { | ||
2080 | const UInt64 numApfsItems = vol.apfs.GetTotalItems() | ||
2081 | + 2; // we will have 2 additional hidden directories: root and private-dir | ||
2082 | const UInt64 numApfsItems_Reserve = numApfsItems | ||
2083 | + 16; // we reserve 16 for some possible unexpected items | ||
2084 | if (numApfsItems_Reserve < map.Pairs.Size()) | ||
2085 | { | ||
2086 | vol.Items.ClearAndReserve((unsigned)numApfsItems_Reserve); | ||
2087 | vol.Nodes.ClearAndReserve((unsigned)numApfsItems_Reserve); | ||
2088 | vol.NodeIDs.ClearAndReserve((unsigned)numApfsItems_Reserve); | ||
2089 | } | ||
2090 | if (OpenCallback) | ||
2091 | { | ||
2092 | const UInt64 numFiles = ProgressVal_NumFilesTotal + numApfsItems; | ||
2093 | RINOK(OpenCallback->SetTotal(&numFiles, NULL)); | ||
2094 | } | ||
2095 | } | ||
2096 | |||
2097 | FOR_VECTOR (i, map.Pairs) | ||
2098 | { | ||
2099 | if (OpenCallback && (i & 0xffff) == 1) | ||
2100 | { | ||
2101 | const UInt64 numFiles = ProgressVal_NumFilesTotal + | ||
2102 | (vol.Items.Size() + vol.Nodes.Size()) / 2; | ||
2103 | RINOK(OpenCallback->SetCompleted(&numFiles, &ProgressVal_Cur)); | ||
2104 | } | ||
2105 | |||
2106 | const CKeyValPair &pair = map.Pairs[i]; | ||
2107 | j_key_t jkey; | ||
2108 | if (pair.Key.Size() < 8) | ||
2109 | return S_FALSE; | ||
2110 | const Byte *p = pair.Key; | ||
2111 | jkey.Parse(p); | ||
2112 | const unsigned type = jkey.GetType(); | ||
2113 | const UInt64 id = jkey.GetID(); | ||
2114 | if (id < prevId) | ||
2115 | return S_FALSE; // IDs must be sorted | ||
2116 | prevId = id; | ||
2117 | |||
2118 | PRF(printf("\n%6d: id=%6d type = %2d", i, (unsigned)id, type)); | ||
2119 | |||
2120 | if (type == APFS_TYPE_INODE) | ||
2121 | { | ||
2122 | PRF(printf (" INODE")); | ||
2123 | if (pair.Key.Size() != 8 || | ||
2124 | pair.Val.Size() < k_SizeOf_j_inode_val) | ||
2125 | return S_FALSE; | ||
2126 | |||
2127 | CNode inode; | ||
2128 | inode.Parse(pair.Val); | ||
2129 | |||
2130 | if (inode.private_id != id) | ||
2131 | { | ||
2132 | /* private_id : The unique identifier used by this file's data stream. | ||
2133 | This identifier appears in the owning_obj_id field of j_phys_ext_val_t | ||
2134 | records that describe the extents where the data is stored. | ||
2135 | For an inode that doesn't have data, the value of this | ||
2136 | field is the file-system object's identifier. | ||
2137 | */ | ||
2138 | // APFS_TYPE_EXTENT allow to link physical address extents. | ||
2139 | // we don't support case (private_id != id) | ||
2140 | UnsupportedFeature = true; | ||
2141 | // return S_FALSE; | ||
2142 | } | ||
2143 | const UInt32 extraSize = (UInt32)pair.Val.Size() - k_SizeOf_j_inode_val; | ||
2144 | if (extraSize != 0) | ||
2145 | { | ||
2146 | if (extraSize < 4) | ||
2147 | return S_FALSE; | ||
2148 | /* | ||
2149 | struct xf_blob | ||
2150 | { | ||
2151 | uint16_t xf_num_exts; | ||
2152 | uint16_t xf_used_data; | ||
2153 | uint8_t xf_data[]; | ||
2154 | }; | ||
2155 | */ | ||
2156 | const Byte *p2 = pair.Val + k_SizeOf_j_inode_val; | ||
2157 | const UInt32 xf_num_exts = Get16(p2); | ||
2158 | const UInt32 xf_used_data = Get16(p2 + 2); | ||
2159 | UInt32 offset = 4 + (UInt32)xf_num_exts * 4; | ||
2160 | if (offset + xf_used_data != extraSize) | ||
2161 | return S_FALSE; | ||
2162 | for (unsigned k = 0; k < xf_num_exts; k++) | ||
2163 | { | ||
2164 | // struct x_field | ||
2165 | const Byte *p3 = p2 + 4 + k * 4; | ||
2166 | const Byte x_type = p3[0]; | ||
2167 | // const Byte x_flags = p3[1]; | ||
2168 | const UInt32 x_size = Get16(p3 + 2); | ||
2169 | const UInt32 x_size_ceil = (x_size + 7) & ~(UInt32)7; | ||
2170 | if (offset + x_size_ceil > extraSize) | ||
2171 | return S_FALSE; | ||
2172 | const Byte *p4 = p2 + offset; | ||
2173 | if (x_type == INO_EXT_TYPE_NAME) | ||
2174 | { | ||
2175 | if (x_size < 2) | ||
2176 | return S_FALSE; | ||
2177 | inode.PrimaryName.SetFrom_CalcLen((const char *)p4, x_size); | ||
2178 | PRF(printf(" PrimaryName = %s", inode.PrimaryName.Ptr())); | ||
2179 | if (inode.PrimaryName.Len() != x_size - 1) | ||
2180 | HeadersError = true; | ||
2181 | // return S_FALSE; | ||
2182 | } | ||
2183 | else if (x_type == INO_EXT_TYPE_DSTREAM) | ||
2184 | { | ||
2185 | if (x_size != k_SizeOf_j_dstream) | ||
2186 | return S_FALSE; | ||
2187 | if (inode.dstream_defined) | ||
2188 | return S_FALSE; | ||
2189 | inode.dstream.Parse(p4); | ||
2190 | inode.dstream_defined = true; | ||
2191 | } | ||
2192 | else | ||
2193 | { | ||
2194 | // UnsupportedFeature = true; | ||
2195 | // return S_FALSE; | ||
2196 | } | ||
2197 | offset += x_size_ceil; | ||
2198 | } | ||
2199 | if (offset != extraSize) | ||
2200 | return S_FALSE; | ||
2201 | } | ||
2202 | |||
2203 | if (!vol.NodeIDs.IsEmpty()) | ||
2204 | if (id <= vol.NodeIDs.Back()) | ||
2205 | return S_FALSE; | ||
2206 | vol.Nodes.Add(inode); | ||
2207 | vol.NodeIDs.Add(id); | ||
2208 | continue; | ||
2209 | } | ||
2210 | |||
2211 | if (type == APFS_TYPE_XATTR) | ||
2212 | { | ||
2213 | PRF(printf(" XATTR")); | ||
2214 | |||
2215 | /* | ||
2216 | struct j_xattr_key | ||
2217 | { | ||
2218 | j_key_t hdr; | ||
2219 | uint16_t name_len; | ||
2220 | uint8_t name[0]; | ||
2221 | } | ||
2222 | */ | ||
2223 | |||
2224 | UInt32 len; | ||
2225 | unsigned nameOffset; | ||
2226 | { | ||
2227 | nameOffset = 8 + 2; | ||
2228 | if (pair.Key.Size() < nameOffset + 1) | ||
2229 | return S_FALSE; | ||
2230 | len = Get16(p + 8); | ||
2231 | } | ||
2232 | if (nameOffset + len != pair.Key.Size()) | ||
2233 | return S_FALSE; | ||
2234 | |||
2235 | CAttr attr; | ||
2236 | attr.Name.SetFrom_CalcLen((const char *)p + nameOffset, len); | ||
2237 | if (attr.Name.Len() != len - 1) | ||
2238 | return S_FALSE; | ||
2239 | |||
2240 | PRF(printf(" name=%s", attr.Name.Ptr())); | ||
2241 | |||
2242 | const unsigned k_SizeOf_j_xattr_val = 4; | ||
2243 | if (pair.Val.Size() < k_SizeOf_j_xattr_val) | ||
2244 | return S_FALSE; | ||
2245 | /* | ||
2246 | struct j_xattr_val | ||
2247 | { | ||
2248 | uint16_t flags; | ||
2249 | uint16_t xdata_len; | ||
2250 | uint8_t xdata[0]; | ||
2251 | } | ||
2252 | */ | ||
2253 | attr.flags = Get16(pair.Val); | ||
2254 | const UInt32 xdata_len = Get16(pair.Val + 2); | ||
2255 | |||
2256 | PRF(printf(" flags=%x xdata_len = %d", | ||
2257 | (unsigned)attr.flags, | ||
2258 | (unsigned)xdata_len)); | ||
2259 | |||
2260 | const Byte *p4 = pair.Val + 4; | ||
2261 | |||
2262 | if (k_SizeOf_j_xattr_val + xdata_len != pair.Val.Size()) | ||
2263 | return S_FALSE; | ||
2264 | if (attr.Is_EMBEDDED()) | ||
2265 | attr.Data.CopyFrom(p4, xdata_len); | ||
2266 | else if (attr.Is_STREAM()) | ||
2267 | { | ||
2268 | // why (attr.flags == 0x11) here? (0x11 is undocummented flag) | ||
2269 | if (k_SizeOf_j_xattr_val + 8 + k_SizeOf_j_dstream != pair.Val.Size()) | ||
2270 | return S_FALSE; | ||
2271 | attr.Id = Get64(p4); | ||
2272 | attr.dstream.Parse(p4 + 8); | ||
2273 | attr.dstream_defined = true; | ||
2274 | PRF(printf(" streamID=%d", (unsigned)attr.Id)); | ||
2275 | } | ||
2276 | else | ||
2277 | { | ||
2278 | // unknown attribute | ||
2279 | // UnsupportedFeature = true; | ||
2280 | // return S_FALSE; | ||
2281 | } | ||
2282 | |||
2283 | if (vol.NodeIDs.IsEmpty() || | ||
2284 | vol.NodeIDs.Back() != id) | ||
2285 | { | ||
2286 | return S_FALSE; | ||
2287 | // UnsupportedFeature = true; | ||
2288 | // continue; | ||
2289 | } | ||
2290 | CNode &inode = vol.Nodes.Back(); | ||
2291 | if (attr.Name.IsEqualTo("com.apple.fs.symlink")) | ||
2292 | { | ||
2293 | inode.SymLinkIndex = inode.Attrs.Size(); | ||
2294 | if (attr.Is_dstream_OK_for_SymLink()) | ||
2295 | NeedReadSymLink = true; | ||
2296 | } | ||
2297 | else | ||
2298 | vol.NumAltStreams++; | ||
2299 | inode.Attrs.Add(attr); | ||
2300 | continue; | ||
2301 | } | ||
2302 | |||
2303 | if (type == APFS_TYPE_DSTREAM_ID) | ||
2304 | { | ||
2305 | PRF(printf(" DSTREAM_ID")); | ||
2306 | if (pair.Key.Size() != 8) | ||
2307 | return S_FALSE; | ||
2308 | // j_dstream_id_val_t | ||
2309 | if (pair.Val.Size() != 4) | ||
2310 | return S_FALSE; | ||
2311 | const UInt32 refcnt = Get32(pair.Val); | ||
2312 | |||
2313 | // The data stream record can be deleted when its reference count reaches zero. | ||
2314 | PRF(printf(" refcnt = %8d", (unsigned)refcnt)); | ||
2315 | |||
2316 | if (vol.NodeIDs.IsEmpty()) | ||
2317 | return S_FALSE; | ||
2318 | |||
2319 | if (vol.NodeIDs.Back() != id) | ||
2320 | { | ||
2321 | // is it possible ? | ||
2322 | // continue; | ||
2323 | return S_FALSE; | ||
2324 | } | ||
2325 | |||
2326 | CNode &inode = vol.Nodes.Back(); | ||
2327 | |||
2328 | if (inode.refcnt_defined) | ||
2329 | return S_FALSE; | ||
2330 | |||
2331 | inode.refcnt = refcnt; | ||
2332 | inode.refcnt_defined = true; | ||
2333 | if (inode.refcnt != (UInt32)inode.nlink) | ||
2334 | { | ||
2335 | // is it possible ? | ||
2336 | // return S_FALSE; | ||
2337 | } | ||
2338 | continue; | ||
2339 | } | ||
2340 | |||
2341 | if (type == APFS_TYPE_FILE_EXTENT) | ||
2342 | { | ||
2343 | PRF(printf(" FILE_EXTENT")); | ||
2344 | /* | ||
2345 | struct j_file_extent_key | ||
2346 | { | ||
2347 | j_key_t hdr; | ||
2348 | uint64_t logical_addr; | ||
2349 | } | ||
2350 | */ | ||
2351 | if (pair.Key.Size() != 16) | ||
2352 | return S_FALSE; | ||
2353 | // The offset within the file's data, in bytes, for the data stored in this extent | ||
2354 | const UInt64 logical_addr = Get64(p + 8); | ||
2355 | |||
2356 | j_file_extent_val eval; | ||
2357 | if (pair.Val.Size() != k_SizeOf_j_file_extent_val) | ||
2358 | return S_FALSE; | ||
2359 | eval.Parse(pair.Val); | ||
2360 | |||
2361 | if (logical_addr != 0) | ||
2362 | { | ||
2363 | PRF(printf(" logical_addr = %d", (unsigned)logical_addr)); | ||
2364 | } | ||
2365 | PRF(printf(" len = %8d pos = %8d", | ||
2366 | (unsigned)eval.len_and_flags, | ||
2367 | (unsigned)eval.phys_block_num | ||
2368 | )); | ||
2369 | |||
2370 | CExtent ext; | ||
2371 | ext.logical_offset = logical_addr; | ||
2372 | ext.len_and_flags = eval.len_and_flags; | ||
2373 | ext.phys_block_num = eval.phys_block_num; | ||
2374 | |||
2375 | if (vol.NodeIDs.IsEmpty()) | ||
2376 | return S_FALSE; | ||
2377 | if (vol.NodeIDs.Back() != id) | ||
2378 | { | ||
2379 | // extents for Attributs; | ||
2380 | if (vol.SmallNodeIDs.IsEmpty() || | ||
2381 | vol.SmallNodeIDs.Back() != id) | ||
2382 | { | ||
2383 | vol.SmallNodeIDs.Add(id); | ||
2384 | vol.SmallNodes.AddNew(); | ||
2385 | } | ||
2386 | vol.SmallNodes.Back().Extents.Add(ext); | ||
2387 | continue; | ||
2388 | // return S_FALSE; | ||
2389 | } | ||
2390 | |||
2391 | CNode &inode = vol.Nodes.Back(); | ||
2392 | inode.Extents.Add(ext); | ||
2393 | continue; | ||
2394 | } | ||
2395 | |||
2396 | if (type == APFS_TYPE_DIR_REC) | ||
2397 | { | ||
2398 | UInt32 len; | ||
2399 | unsigned nameOffset; | ||
2400 | |||
2401 | if (isHashed) | ||
2402 | { | ||
2403 | /* | ||
2404 | struct j_drec_hashed_key | ||
2405 | { | ||
2406 | j_key_t hdr; | ||
2407 | UInt32 name_len_and_hash; | ||
2408 | uint8_t name[0]; | ||
2409 | } | ||
2410 | */ | ||
2411 | nameOffset = 8 + 4; | ||
2412 | if (pair.Key.Size() < nameOffset + 1) | ||
2413 | return S_FALSE; | ||
2414 | const UInt32 name_len_and_hash = Get32(p + 8); | ||
2415 | len = name_len_and_hash & J_DREC_LEN_MASK; | ||
2416 | } | ||
2417 | else | ||
2418 | { | ||
2419 | /* | ||
2420 | struct j_drec_key | ||
2421 | { | ||
2422 | j_key_t hdr; | ||
2423 | UInt16 name_len; // The length of the name, including the final null character | ||
2424 | uint8_t name[0]; // The name, represented as a null-terminated UTF-8 string | ||
2425 | } | ||
2426 | */ | ||
2427 | nameOffset = 8 + 2; | ||
2428 | if (pair.Key.Size() < nameOffset + 1) | ||
2429 | return S_FALSE; | ||
2430 | len = Get16(p + 8); | ||
2431 | } | ||
2432 | if (nameOffset + len != pair.Key.Size()) | ||
2433 | return S_FALSE; | ||
2434 | CItem item; | ||
2435 | item.ParentId = id; | ||
2436 | item.Name.SetFrom_CalcLen((const char *)p + nameOffset, len); | ||
2437 | if (item.Name.Len() != len - 1) | ||
2438 | return S_FALSE; | ||
2439 | |||
2440 | if (pair.Val.Size() < k_SizeOf_j_drec_val) | ||
2441 | return S_FALSE; | ||
2442 | |||
2443 | item.Val.Parse(pair.Val); | ||
2444 | |||
2445 | if (pair.Val.Size() > k_SizeOf_j_drec_val) | ||
2446 | { | ||
2447 | // fixme: parse extra fields; | ||
2448 | // UnsupportedFeature = true; | ||
2449 | // return S_FALSE; | ||
2450 | } | ||
2451 | |||
2452 | vol.Items.Add(item); | ||
2453 | |||
2454 | /* | ||
2455 | if (!vol.NodeIDs.IsEmpty() && vol.NodeIDs.Back() == id) | ||
2456 | vol.Nodes.Back().NumItems++; | ||
2457 | */ | ||
2458 | if (id == PRIV_DIR_INO_NUM) | ||
2459 | vol.NumItems_In_PrivateDir++; | ||
2460 | |||
2461 | PRF(printf(" next=%6d flags=%2x %s", | ||
2462 | (unsigned)item.Val.file_id, | ||
2463 | (unsigned)item.Val.flags, | ||
2464 | item.Name.Ptr())); | ||
2465 | continue; | ||
2466 | } | ||
2467 | |||
2468 | UnsupportedFeature = true; | ||
2469 | // return S_FALSE; | ||
2470 | } | ||
2471 | ProgressVal_NumFilesTotal += vol.Items.Size(); | ||
2472 | } | ||
2473 | |||
2474 | if (NeedReadSymLink) | ||
2475 | { | ||
2476 | /* we read external streams for SymLinks to CAttr.Data | ||
2477 | So we can get SymLink for GetProperty(kpidSymLink) later */ | ||
2478 | FOR_VECTOR (i, vol.Nodes) | ||
2479 | { | ||
2480 | CNode &node = vol.Nodes[i]; | ||
2481 | if (IsViNotDef(node.SymLinkIndex)) | ||
2482 | continue; | ||
2483 | CAttr &attr = node.Attrs[(unsigned)node.SymLinkIndex]; | ||
2484 | // FOR_VECTOR (k, node.Attrs) { CAttr &attr = node.Attrs[(unsigned)k]; // for debug | ||
2485 | if (attr.Data.Size() != 0 | ||
2486 | || !attr.Is_dstream_OK_for_SymLink()) | ||
2487 | continue; | ||
2488 | const UInt32 size = (UInt32)attr.dstream.size; | ||
2489 | const int idIndex = vol.SmallNodeIDs.FindInSorted(attr.Id); | ||
2490 | if (idIndex == -1) | ||
2491 | continue; | ||
2492 | CMyComPtr<ISequentialInStream> inStream; | ||
2493 | const HRESULT res = GetStream2( | ||
2494 | OpenInStream, | ||
2495 | &vol.SmallNodes[(unsigned)idIndex].Extents, | ||
2496 | size, &inStream); | ||
2497 | if (res == S_OK && inStream) | ||
2498 | { | ||
2499 | CByteBuffer buf2; | ||
2500 | buf2.Alloc(size); | ||
2501 | if (ReadStream_FAIL(inStream, buf2, size) == S_OK) | ||
2502 | attr.Data = buf2; | ||
2503 | } | ||
2504 | } | ||
2505 | } | ||
2506 | |||
2507 | const HRESULT res = vol.FillRefs(); | ||
2508 | |||
2509 | if (vol.ThereAreErrors()) | ||
2510 | HeadersError = true; | ||
2511 | if (vol.UnsupportedFeature) | ||
2512 | UnsupportedFeature = true; | ||
2513 | if (vol.NumAltStreams != 0) | ||
2514 | ThereAreAltStreams = true; | ||
2515 | |||
2516 | return res; | ||
2517 | } | ||
2518 | |||
2519 | |||
2520 | |||
2521 | HRESULT CVol::FillRefs() | ||
2522 | { | ||
2523 | { | ||
2524 | // we fill Refs[*] | ||
2525 | // we | ||
2526 | // and set Nodes[*].ItemIndex for Nodes that are dictories; | ||
2527 | FOR_VECTOR (i, Items) | ||
2528 | { | ||
2529 | CItem &item = Items[i]; | ||
2530 | const UInt64 id = item.Val.file_id; | ||
2531 | // if (item.Id == ROOT_DIR_PARENT) continue; | ||
2532 | /* for two root folders items | ||
2533 | we don't set Node.ItemIndex; */ | ||
2534 | // so nodes | ||
2535 | if (id == ROOT_DIR_INO_NUM) | ||
2536 | continue; | ||
2537 | if (id == PRIV_DIR_INO_NUM) | ||
2538 | if (NumItems_In_PrivateDir == 0) // if (inode.NumItems == 0) | ||
2539 | continue; | ||
2540 | |||
2541 | CRef ref; | ||
2542 | ref.ItemIndex = i; | ||
2543 | // ref.NodeIndex = VI_MINUS1; | ||
2544 | ref.ParentRefIndex = VI_MINUS1; | ||
2545 | #ifdef APFS_SHOW_ALT_STREAMS | ||
2546 | ref.AttrIndex = VI_MINUS1; | ||
2547 | #endif | ||
2548 | const int index = NodeIDs.FindInSorted(id); | ||
2549 | // const int index = -1; // for debug | ||
2550 | ref.NodeIndex = (unsigned)index; | ||
2551 | item.RefIndex = Refs.Size(); | ||
2552 | Refs.Add(ref); | ||
2553 | |||
2554 | if (index == -1) | ||
2555 | { | ||
2556 | NodeNotFound = true; | ||
2557 | continue; | ||
2558 | // return S_FALSE; | ||
2559 | } | ||
2560 | |||
2561 | // item.iNode_Index = index; | ||
2562 | CNode &inode = Nodes[(unsigned)index]; | ||
2563 | if (!item.Val.IsFlags_Unknown() | ||
2564 | && inode.Get_Type_From_mode() != item.Val.flags) | ||
2565 | { | ||
2566 | Refs.Back().NodeIndex = VI_MINUS1; | ||
2567 | WrongInodeLink = true; | ||
2568 | continue; | ||
2569 | // return S_FALSE; | ||
2570 | } | ||
2571 | |||
2572 | const bool isDir = inode.IsDir(); | ||
2573 | if (isDir) | ||
2574 | { | ||
2575 | if (IsViDef(inode.ItemIndex)) | ||
2576 | { | ||
2577 | // hard links to dirs are not supported | ||
2578 | Refs.Back().NodeIndex = VI_MINUS1; | ||
2579 | WrongInodeLink = true; | ||
2580 | continue; | ||
2581 | } | ||
2582 | inode.ItemIndex = i; | ||
2583 | } | ||
2584 | inode.NumCalcedLinks++; | ||
2585 | |||
2586 | #ifdef APFS_SHOW_ALT_STREAMS | ||
2587 | if (!isDir) | ||
2588 | { | ||
2589 | // we use alt streams only for files | ||
2590 | const unsigned numAttrs = inode.Attrs.Size(); | ||
2591 | if (numAttrs != 0) | ||
2592 | { | ||
2593 | ref.ParentRefIndex = item.RefIndex; | ||
2594 | for (unsigned k = 0; k < numAttrs; k++) | ||
2595 | { | ||
2596 | if (k == inode.SymLinkIndex) | ||
2597 | continue; | ||
2598 | ref.AttrIndex = k; | ||
2599 | Refs.Add(ref); | ||
2600 | /* | ||
2601 | const CAttr &attr = inode.Attrs[k]; | ||
2602 | if (attr.dstream_defined) | ||
2603 | { | ||
2604 | const int idIndex = SmallNodeIDs.FindInSorted(attr.Id); | ||
2605 | if (idIndex != -1) | ||
2606 | SmallNodes[(unsigned)idIndex].NumLinks++; // for debug | ||
2607 | } | ||
2608 | */ | ||
2609 | } | ||
2610 | } | ||
2611 | } | ||
2612 | #endif | ||
2613 | } | ||
2614 | } | ||
2615 | |||
2616 | |||
2617 | { | ||
2618 | // fill ghost nodes | ||
2619 | CRef ref; | ||
2620 | ref.ItemIndex = VI_MINUS1; | ||
2621 | ref.ParentRefIndex = VI_MINUS1; | ||
2622 | #ifdef APFS_SHOW_ALT_STREAMS | ||
2623 | ref.AttrIndex = VI_MINUS1; | ||
2624 | #endif | ||
2625 | FOR_VECTOR (i, Nodes) | ||
2626 | { | ||
2627 | if (Nodes[i].NumCalcedLinks != 0) | ||
2628 | continue; | ||
2629 | const UInt64 id = NodeIDs[i]; | ||
2630 | if (id == ROOT_DIR_INO_NUM || | ||
2631 | id == PRIV_DIR_INO_NUM) | ||
2632 | continue; | ||
2633 | ThereAreUnlinkedNodes = true; | ||
2634 | ref.NodeIndex = i; | ||
2635 | Refs.Add(ref); | ||
2636 | } | ||
2637 | } | ||
2638 | |||
2639 | /* if want to create Refs for ghost data streams, | ||
2640 | we need additional CRef::SmallNodeIndex field */ | ||
2641 | |||
2642 | { | ||
2643 | /* all Nodes[*].ItemIndex were already filled for directory Nodes, | ||
2644 | except of "root" and "private-dir" Nodes. */ | ||
2645 | |||
2646 | // now we fill Items[*].ParentItemIndex and Refs[*].ParentRefIndex | ||
2647 | |||
2648 | UInt64 prev_ID = (UInt64)(Int64)-1; | ||
2649 | unsigned prev_ParentItemIndex = VI_MINUS1; | ||
2650 | |||
2651 | FOR_VECTOR (i, Items) | ||
2652 | { | ||
2653 | CItem &item = Items[i]; | ||
2654 | const UInt64 id = item.ParentId; // it's id of parent NODE | ||
2655 | if (id != prev_ID) | ||
2656 | { | ||
2657 | prev_ID = id; | ||
2658 | prev_ParentItemIndex = VI_MINUS1; | ||
2659 | const int index = NodeIDs.FindInSorted(id); | ||
2660 | if (index == -1) | ||
2661 | continue; | ||
2662 | prev_ParentItemIndex = Nodes[(unsigned)index].ItemIndex; | ||
2663 | } | ||
2664 | |||
2665 | if (IsViNotDef(prev_ParentItemIndex)) | ||
2666 | continue; | ||
2667 | item.ParentItemIndex = prev_ParentItemIndex; | ||
2668 | if (IsViNotDef(item.RefIndex)) | ||
2669 | { | ||
2670 | // RefIndex is not set for 2 Items (root folders) | ||
2671 | // but there is no node for them usually | ||
2672 | continue; | ||
2673 | } | ||
2674 | CRef &ref = Refs[item.RefIndex]; | ||
2675 | |||
2676 | /* | ||
2677 | // it's optional check that parent_id is set correclty | ||
2678 | if (IsViDef(ref.NodeIndex)) | ||
2679 | { | ||
2680 | const CNode &node = Nodes[ref.NodeIndex]; | ||
2681 | if (node.IsDir() && node.parent_id != id) | ||
2682 | return S_FALSE; | ||
2683 | } | ||
2684 | */ | ||
2685 | |||
2686 | /* | ||
2687 | if (id == ROOT_DIR_INO_NUM) | ||
2688 | { | ||
2689 | // ItemIndex in Node for ROOT_DIR_INO_NUM was not set bofere | ||
2690 | // probably unused now. | ||
2691 | ref.ParentRefIndex = VI_MINUS1; | ||
2692 | } | ||
2693 | else | ||
2694 | */ | ||
2695 | ref.ParentRefIndex = Items[prev_ParentItemIndex].RefIndex; | ||
2696 | } | ||
2697 | } | ||
2698 | |||
2699 | { | ||
2700 | // check for loops | ||
2701 | const unsigned numItems = Items.Size(); | ||
2702 | if (numItems + 1 == 0) | ||
2703 | return S_FALSE; | ||
2704 | CUIntArr arr; | ||
2705 | arr.Alloc(numItems); | ||
2706 | { | ||
2707 | for (unsigned i = 0; i < numItems; i++) | ||
2708 | arr[i] = 0; | ||
2709 | } | ||
2710 | for (unsigned i = 0; i < numItems;) | ||
2711 | { | ||
2712 | unsigned k = i++; | ||
2713 | for (;;) | ||
2714 | { | ||
2715 | const unsigned a = arr[k]; | ||
2716 | if (a != 0) | ||
2717 | { | ||
2718 | if (a == i) | ||
2719 | return S_FALSE; | ||
2720 | break; | ||
2721 | } | ||
2722 | arr[k] = i; | ||
2723 | k = Items[k].ParentItemIndex; | ||
2724 | if (IsViNotDef(k)) | ||
2725 | break; | ||
2726 | } | ||
2727 | } | ||
2728 | } | ||
2729 | |||
2730 | return S_OK; | ||
2731 | } | ||
2732 | |||
2733 | |||
2734 | |||
2735 | class CHandler: | ||
2736 | public IInArchive, | ||
2737 | public IArchiveGetRawProps, | ||
2738 | public IInArchiveGetStream, | ||
2739 | public CMyUnknownImp, | ||
2740 | public CDatabase | ||
2741 | { | ||
2742 | CMyComPtr<IInStream> _stream; | ||
2743 | public: | ||
2744 | MY_UNKNOWN_IMP3(IInArchive, IArchiveGetRawProps, IInArchiveGetStream) | ||
2745 | INTERFACE_IInArchive(;) | ||
2746 | INTERFACE_IArchiveGetRawProps(;) | ||
2747 | STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); | ||
2748 | }; | ||
2749 | |||
2750 | |||
2751 | STDMETHODIMP CHandler::Open(IInStream *inStream, | ||
2752 | const UInt64 * /* maxCheckStartPosition */, | ||
2753 | IArchiveOpenCallback *callback) | ||
2754 | { | ||
2755 | COM_TRY_BEGIN | ||
2756 | Close(); | ||
2757 | OpenInStream = inStream; | ||
2758 | OpenCallback = callback; | ||
2759 | RINOK(Open2()); | ||
2760 | _stream = inStream; | ||
2761 | return S_OK; | ||
2762 | COM_TRY_END | ||
2763 | } | ||
2764 | |||
2765 | |||
2766 | STDMETHODIMP CHandler::Close() | ||
2767 | { | ||
2768 | _stream.Release(); | ||
2769 | Clear(); | ||
2770 | return S_OK; | ||
2771 | } | ||
2772 | |||
2773 | |||
2774 | enum | ||
2775 | { | ||
2776 | kpidBytesWritten = kpidUserDefined, | ||
2777 | kpidBytesRead, | ||
2778 | kpidPrimeName, | ||
2779 | kpidParentINode, | ||
2780 | kpidAddTime, | ||
2781 | kpidGeneration, | ||
2782 | kpidBsdFlags | ||
2783 | }; | ||
2784 | |||
2785 | static const CStatProp kProps[] = | ||
2786 | { | ||
2787 | { NULL, kpidPath, VT_BSTR }, | ||
2788 | { NULL, kpidSize, VT_UI8 }, | ||
2789 | { NULL, kpidPackSize, VT_UI8 }, | ||
2790 | { NULL, kpidPosixAttrib, VT_UI4 }, | ||
2791 | { NULL, kpidMTime, VT_FILETIME }, | ||
2792 | { NULL, kpidCTime, VT_FILETIME }, | ||
2793 | { NULL, kpidATime, VT_FILETIME }, | ||
2794 | { NULL, kpidChangeTime, VT_FILETIME }, | ||
2795 | { "Added Time", kpidAddTime, VT_FILETIME }, | ||
2796 | { NULL, kpidINode, VT_UI8 }, | ||
2797 | { NULL, kpidLinks, VT_UI4 }, | ||
2798 | { NULL, kpidSymLink, VT_BSTR }, | ||
2799 | { NULL, kpidUserId, VT_UI4 }, | ||
2800 | { NULL, kpidGroupId, VT_UI4 }, | ||
2801 | #ifdef APFS_SHOW_ALT_STREAMS | ||
2802 | { NULL, kpidIsAltStream, VT_BOOL }, | ||
2803 | #endif | ||
2804 | { "Parent iNode", kpidParentINode, VT_UI8 }, | ||
2805 | { "Primary Name", kpidPrimeName, VT_BSTR }, | ||
2806 | { "Generation", kpidGeneration, VT_UI4 }, | ||
2807 | { "Written Size", kpidBytesWritten, VT_UI8 }, | ||
2808 | { "Read Size", kpidBytesRead, VT_UI8 }, | ||
2809 | { "BSD Flags", kpidBsdFlags, VT_UI4 } | ||
2810 | }; | ||
2811 | |||
2812 | |||
2813 | static const Byte kArcProps[] = | ||
2814 | { | ||
2815 | kpidName, | ||
2816 | kpidId, | ||
2817 | kpidClusterSize, | ||
2818 | kpidCTime, | ||
2819 | kpidMTime, | ||
2820 | kpidComment | ||
2821 | }; | ||
2822 | |||
2823 | IMP_IInArchive_Props_WITH_NAME | ||
2824 | IMP_IInArchive_ArcProps | ||
2825 | |||
2826 | |||
2827 | static void ApfsTimeToProp(UInt64 hfsTime, NWindows::NCOM::CPropVariant &prop) | ||
2828 | { | ||
2829 | if (hfsTime == 0) | ||
2830 | return; | ||
2831 | FILETIME ft; | ||
2832 | UInt32 ns100; | ||
2833 | ApfsTimeToFileTime(hfsTime, ft, ns100); | ||
2834 | prop.SetAsTimeFrom_FT_Prec_Ns100(ft, k_PropVar_TimePrec_1ns, ns100); | ||
2835 | } | ||
2836 | |||
2837 | |||
2838 | STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | ||
2839 | { | ||
2840 | COM_TRY_BEGIN | ||
2841 | NWindows::NCOM::CPropVariant prop; | ||
2842 | const CApfs *apfs = NULL; | ||
2843 | if (Vols.Size() == 1) | ||
2844 | apfs = &Vols[0].apfs; | ||
2845 | switch (propID) | ||
2846 | { | ||
2847 | case kpidPhySize: | ||
2848 | prop = (UInt64)sb.block_count << sb.block_size_Log; | ||
2849 | break; | ||
2850 | case kpidClusterSize: prop = (UInt32)(sb.block_size); break; | ||
2851 | case kpidMTime: | ||
2852 | if (apfs) | ||
2853 | ApfsTimeToProp(apfs->modified_by[0].timestamp, prop); | ||
2854 | break; | ||
2855 | case kpidCTime: | ||
2856 | if (apfs) | ||
2857 | ApfsTimeToProp(apfs->formatted_by.timestamp, prop); | ||
2858 | break; | ||
2859 | case kpidIsTree: prop = true; break; | ||
2860 | case kpidErrorFlags: | ||
2861 | { | ||
2862 | UInt32 flags = 0; | ||
2863 | if (HeadersError) flags |= kpv_ErrorFlags_HeadersError; | ||
2864 | if (flags != 0) | ||
2865 | prop = flags; | ||
2866 | break; | ||
2867 | } | ||
2868 | case kpidWarningFlags: | ||
2869 | { | ||
2870 | UInt32 flags = 0; | ||
2871 | if (UnsupportedFeature) flags |= kpv_ErrorFlags_UnsupportedFeature; | ||
2872 | if (flags != 0) | ||
2873 | prop = flags; | ||
2874 | break; | ||
2875 | } | ||
2876 | |||
2877 | case kpidName: | ||
2878 | { | ||
2879 | if (apfs) | ||
2880 | { | ||
2881 | UString s; | ||
2882 | AddVolInternalName_toString(s, *apfs); | ||
2883 | s += ".apfs"; | ||
2884 | prop = s; | ||
2885 | } | ||
2886 | break; | ||
2887 | } | ||
2888 | |||
2889 | case kpidId: | ||
2890 | { | ||
2891 | char s[32 + 4]; | ||
2892 | sb.uuid.SetHex_To_str(s); | ||
2893 | prop = s; | ||
2894 | break; | ||
2895 | } | ||
2896 | |||
2897 | case kpidComment: | ||
2898 | { | ||
2899 | UString s; | ||
2900 | { | ||
2901 | AddComment_UInt64(s, "block_size", sb.block_size); | ||
2902 | |||
2903 | FOR_VECTOR (i, Vols) | ||
2904 | { | ||
2905 | if (Vols.Size() > 1) | ||
2906 | { | ||
2907 | if (i != 0) | ||
2908 | { | ||
2909 | s += "----"; | ||
2910 | s.Add_LF(); | ||
2911 | } | ||
2912 | AddComment_UInt64(s, "Volume", i + 1); | ||
2913 | } | ||
2914 | Vols[i].AddComment(s); | ||
2915 | } | ||
2916 | } | ||
2917 | prop = s; | ||
2918 | break; | ||
2919 | } | ||
2920 | |||
2921 | #ifdef APFS_SHOW_ALT_STREAMS | ||
2922 | case kpidIsAltStream: | ||
2923 | prop = ThereAreAltStreams; | ||
2924 | // prop = false; // for debug | ||
2925 | break; | ||
2926 | #endif | ||
2927 | } | ||
2928 | prop.Detach(value); | ||
2929 | return S_OK; | ||
2930 | COM_TRY_END | ||
2931 | } | ||
2932 | |||
2933 | |||
2934 | STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps) | ||
2935 | { | ||
2936 | *numProps = 0; | ||
2937 | return S_OK; | ||
2938 | } | ||
2939 | |||
2940 | |||
2941 | STDMETHODIMP CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID) | ||
2942 | { | ||
2943 | *name = NULL; | ||
2944 | *propID = 0; | ||
2945 | return S_OK; | ||
2946 | } | ||
2947 | |||
2948 | |||
2949 | STDMETHODIMP CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType) | ||
2950 | { | ||
2951 | *parentType = NParentType::kDir; | ||
2952 | |||
2953 | const CRef2 &ref2 = Refs2[index]; | ||
2954 | const CVol &vol = Vols[ref2.VolIndex]; | ||
2955 | UInt32 parentIndex = (UInt32)(Int32)-1; | ||
2956 | *parentType = NParentType::kDir; | ||
2957 | |||
2958 | if (IsViDef(ref2.RefIndex)) | ||
2959 | { | ||
2960 | const CRef &ref = vol.Refs[ref2.RefIndex]; | ||
2961 | #ifdef APFS_SHOW_ALT_STREAMS | ||
2962 | if (ref.IsAltStream()) | ||
2963 | *parentType = NParentType::kAltStream; | ||
2964 | #endif | ||
2965 | if (IsViDef(ref.ParentRefIndex)) | ||
2966 | parentIndex = (UInt32)(ref.ParentRefIndex + vol.StartRef2Index); | ||
2967 | else if (index != vol.RootRef2Index && IsViDef(vol.RootRef2Index)) | ||
2968 | parentIndex = (UInt32)vol.RootRef2Index; | ||
2969 | } | ||
2970 | |||
2971 | *parent = parentIndex; | ||
2972 | return S_OK; | ||
2973 | } | ||
2974 | |||
2975 | |||
2976 | STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) | ||
2977 | { | ||
2978 | *data = NULL; | ||
2979 | *dataSize = 0; | ||
2980 | *propType = 0; | ||
2981 | UNUSED_VAR(index); | ||
2982 | UNUSED_VAR(propID); | ||
2983 | return S_OK; | ||
2984 | } | ||
2985 | |||
2986 | |||
2987 | static void Utf8Name_to_InterName(const AString &src, UString &dest) | ||
2988 | { | ||
2989 | ConvertUTF8ToUnicode(src, dest); | ||
2990 | NItemName::NormalizeSlashes_in_FileName_for_OsPath(dest); | ||
2991 | } | ||
2992 | |||
2993 | |||
2994 | static void AddNodeName(UString &s, const CNode &inode, UInt64 id) | ||
2995 | { | ||
2996 | s += "node"; | ||
2997 | s.Add_UInt64(id); | ||
2998 | if (!inode.PrimaryName.IsEmpty()) | ||
2999 | { | ||
3000 | s += '.'; | ||
3001 | UString s2; | ||
3002 | Utf8Name_to_InterName(inode.PrimaryName, s2); | ||
3003 | s += s2; | ||
3004 | } | ||
3005 | } | ||
3006 | |||
3007 | |||
3008 | void CDatabase::GetItemPath(unsigned index, const CNode *inode, NWindows::NCOM::CPropVariant &path) const | ||
3009 | { | ||
3010 | const unsigned kNumLevelsMax = (1 << 10); | ||
3011 | const unsigned kLenMax = (1 << 12); | ||
3012 | UString s; | ||
3013 | const CRef2 &ref2 = Refs2[index]; | ||
3014 | const CVol &vol = Vols[ref2.VolIndex]; | ||
3015 | |||
3016 | if (IsViDef(ref2.RefIndex)) | ||
3017 | { | ||
3018 | const CRef &ref = vol.Refs[ref2.RefIndex]; | ||
3019 | unsigned cur = ref.ItemIndex; | ||
3020 | if (IsViNotDef(cur)) | ||
3021 | { | ||
3022 | if (inode) | ||
3023 | AddNodeName(s, *inode, vol.NodeIDs[ref.NodeIndex]); | ||
3024 | } | ||
3025 | else | ||
3026 | { | ||
3027 | for (unsigned i = 0;; i++) | ||
3028 | { | ||
3029 | if (i >= kNumLevelsMax || s.Len() > kLenMax) | ||
3030 | { | ||
3031 | s.Insert(0, UString("[LONG_PATH]")); | ||
3032 | break; | ||
3033 | } | ||
3034 | const CItem &item = vol.Items[(unsigned)cur]; | ||
3035 | UString s2; | ||
3036 | Utf8Name_to_InterName(item.Name, s2); | ||
3037 | // s2 += "a\\b"; // for debug | ||
3038 | s.Insert(0, s2); | ||
3039 | cur = item.ParentItemIndex; | ||
3040 | if (IsViNotDef(cur)) | ||
3041 | break; | ||
3042 | // ParentItemIndex was not set for sch items | ||
3043 | // if (item.ParentId == ROOT_DIR_INO_NUM) break; | ||
3044 | s.InsertAtFront(WCHAR_PATH_SEPARATOR); | ||
3045 | } | ||
3046 | } | ||
3047 | |||
3048 | #ifdef APFS_SHOW_ALT_STREAMS | ||
3049 | if (IsViDef(ref.AttrIndex) && inode) | ||
3050 | { | ||
3051 | s += ':'; | ||
3052 | UString s2; | ||
3053 | Utf8Name_to_InterName(inode->Attrs[(unsigned)ref.AttrIndex].Name, s2); | ||
3054 | // s2 += "a\\b"; // for debug | ||
3055 | s += s2; | ||
3056 | } | ||
3057 | #endif | ||
3058 | } | ||
3059 | |||
3060 | if (!vol.RootName.IsEmpty()) | ||
3061 | { | ||
3062 | if (IsViDef(ref2.RefIndex)) | ||
3063 | s.InsertAtFront(WCHAR_PATH_SEPARATOR); | ||
3064 | s.Insert(0, vol.RootName); | ||
3065 | } | ||
3066 | |||
3067 | path = s; | ||
3068 | } | ||
3069 | |||
3070 | |||
3071 | |||
3072 | STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) | ||
3073 | { | ||
3074 | COM_TRY_BEGIN | ||
3075 | NWindows::NCOM::CPropVariant prop; | ||
3076 | |||
3077 | const CRef2 &ref2 = Refs2[index]; | ||
3078 | const CVol &vol = Vols[ref2.VolIndex]; | ||
3079 | |||
3080 | if (IsViNotDef(ref2.RefIndex)) | ||
3081 | { | ||
3082 | switch (propID) | ||
3083 | { | ||
3084 | case kpidName: | ||
3085 | case kpidPath: | ||
3086 | GetItemPath(index, NULL, prop); | ||
3087 | break; | ||
3088 | case kpidIsDir: | ||
3089 | prop = true; | ||
3090 | break; | ||
3091 | } | ||
3092 | prop.Detach(value); | ||
3093 | return S_OK; | ||
3094 | } | ||
3095 | |||
3096 | const CRef &ref = vol.Refs[ref2.RefIndex]; | ||
3097 | |||
3098 | const CItem *item = NULL; | ||
3099 | if (IsViDef(ref.ItemIndex)) | ||
3100 | item = &vol.Items[ref.ItemIndex]; | ||
3101 | |||
3102 | const CNode *inode = NULL; | ||
3103 | if (IsViDef(ref.NodeIndex)) | ||
3104 | inode = &vol.Nodes[ref.NodeIndex]; | ||
3105 | |||
3106 | switch (propID) | ||
3107 | { | ||
3108 | case kpidPath: | ||
3109 | GetItemPath(index, inode, prop); | ||
3110 | break; | ||
3111 | case kpidPrimeName: | ||
3112 | { | ||
3113 | if (inode | ||
3114 | #ifdef APFS_SHOW_ALT_STREAMS | ||
3115 | && !ref.IsAltStream() | ||
3116 | #endif | ||
3117 | && !inode->PrimaryName.IsEmpty()) | ||
3118 | { | ||
3119 | UString s; | ||
3120 | ConvertUTF8ToUnicode(inode->PrimaryName, s); | ||
3121 | /* | ||
3122 | // for debug: | ||
3123 | if (inode.PrimaryName != item.Name) throw 123456; | ||
3124 | */ | ||
3125 | prop = s; | ||
3126 | } | ||
3127 | break; | ||
3128 | } | ||
3129 | |||
3130 | case kpidName: | ||
3131 | { | ||
3132 | UString s; | ||
3133 | #ifdef APFS_SHOW_ALT_STREAMS | ||
3134 | if (ref.IsAltStream()) | ||
3135 | { | ||
3136 | // if (inode) | ||
3137 | { | ||
3138 | const CAttr &attr = inode->Attrs[(unsigned)ref.AttrIndex]; | ||
3139 | ConvertUTF8ToUnicode(attr.Name, s); | ||
3140 | } | ||
3141 | } | ||
3142 | else | ||
3143 | #endif | ||
3144 | { | ||
3145 | if (item) | ||
3146 | ConvertUTF8ToUnicode(item->Name, s); | ||
3147 | else if (inode) | ||
3148 | AddNodeName(s, *inode, vol.NodeIDs[ref.NodeIndex]); | ||
3149 | else | ||
3150 | break; | ||
3151 | } | ||
3152 | // s += "s/1bs\\2"; // for debug: | ||
3153 | prop = s; | ||
3154 | break; | ||
3155 | } | ||
3156 | |||
3157 | case kpidSymLink: | ||
3158 | if (inode) | ||
3159 | { | ||
3160 | if (inode->IsSymLink() && IsViDef(inode->SymLinkIndex)) | ||
3161 | { | ||
3162 | const CByteBuffer &buf = inode->Attrs[(unsigned)inode->SymLinkIndex].Data; | ||
3163 | if (buf.Size() != 0) | ||
3164 | { | ||
3165 | AString s; | ||
3166 | s.SetFrom_CalcLen((const char *)(const Byte *)buf, (unsigned)buf.Size()); | ||
3167 | if (s.Len() == buf.Size() - 1) | ||
3168 | { | ||
3169 | UString u; | ||
3170 | ConvertUTF8ToUnicode(s, u); | ||
3171 | prop = u; | ||
3172 | } | ||
3173 | } | ||
3174 | } | ||
3175 | } | ||
3176 | break; | ||
3177 | |||
3178 | case kpidSize: | ||
3179 | if (inode) | ||
3180 | { | ||
3181 | UInt64 size; | ||
3182 | if (inode->GetSize(ref.GetAttrIndex(), size)) | ||
3183 | prop = size; | ||
3184 | } | ||
3185 | break; | ||
3186 | |||
3187 | case kpidPackSize: | ||
3188 | if (inode) | ||
3189 | { | ||
3190 | UInt64 size; | ||
3191 | if (inode->GetPackSize(ref.GetAttrIndex(), size)) | ||
3192 | prop = size; | ||
3193 | } | ||
3194 | break; | ||
3195 | |||
3196 | case kpidIsDir: | ||
3197 | { | ||
3198 | bool isDir = false; | ||
3199 | if (inode) | ||
3200 | isDir = inode->IsDir(); | ||
3201 | else if (item) | ||
3202 | isDir = item->Val.IsFlags_Dir(); | ||
3203 | prop = isDir; | ||
3204 | break; | ||
3205 | } | ||
3206 | |||
3207 | case kpidPosixAttrib: | ||
3208 | { | ||
3209 | if (inode) | ||
3210 | { | ||
3211 | UInt32 mode = inode->mode; | ||
3212 | #ifdef APFS_SHOW_ALT_STREAMS | ||
3213 | if (ref.IsAltStream()) | ||
3214 | { | ||
3215 | mode &= 0666; // we disable execution | ||
3216 | mode |= MY_LIN_S_IFREG; | ||
3217 | } | ||
3218 | #endif | ||
3219 | prop = (UInt32)mode; | ||
3220 | } | ||
3221 | else if (item && !item->Val.IsFlags_Unknown()) | ||
3222 | prop = (UInt32)(item->Val.flags << 12); | ||
3223 | break; | ||
3224 | } | ||
3225 | |||
3226 | case kpidCTime: if (inode) ApfsTimeToProp(inode->create_time, prop); break; | ||
3227 | case kpidMTime: if (inode) ApfsTimeToProp(inode->mod_time, prop); break; | ||
3228 | case kpidATime: if (inode) ApfsTimeToProp(inode->access_time, prop); break; | ||
3229 | case kpidChangeTime: if (inode) ApfsTimeToProp(inode->change_time, prop); break; | ||
3230 | case kpidAddTime: if (item) ApfsTimeToProp(item->Val.date_added, prop); break; | ||
3231 | |||
3232 | case kpidBytesWritten: | ||
3233 | #ifdef APFS_SHOW_ALT_STREAMS | ||
3234 | if (!ref.IsAltStream()) | ||
3235 | #endif | ||
3236 | if (inode && inode->dstream_defined) | ||
3237 | prop = inode->dstream.total_bytes_written; | ||
3238 | break; | ||
3239 | case kpidBytesRead: | ||
3240 | #ifdef APFS_SHOW_ALT_STREAMS | ||
3241 | if (!ref.IsAltStream()) | ||
3242 | #endif | ||
3243 | if (inode && inode->dstream_defined) | ||
3244 | prop = inode->dstream.total_bytes_read; | ||
3245 | break; | ||
3246 | |||
3247 | #ifdef APFS_SHOW_ALT_STREAMS | ||
3248 | case kpidIsAltStream: | ||
3249 | prop = ref.IsAltStream(); | ||
3250 | break; | ||
3251 | #endif | ||
3252 | |||
3253 | case kpidCharacts: | ||
3254 | if (inode) | ||
3255 | { | ||
3256 | FLAGS_TO_PROP(g_INODE_Flags, (UInt32)inode->internal_flags, prop); | ||
3257 | } | ||
3258 | break; | ||
3259 | |||
3260 | case kpidBsdFlags: | ||
3261 | if (inode) | ||
3262 | { | ||
3263 | FLAGS_TO_PROP(g_INODE_BSD_Flags, inode->bsd_flags, prop); | ||
3264 | } | ||
3265 | break; | ||
3266 | |||
3267 | case kpidGeneration: | ||
3268 | if (inode) | ||
3269 | prop = inode->write_generation_counter; | ||
3270 | break; | ||
3271 | |||
3272 | case kpidUserId: | ||
3273 | if (inode) | ||
3274 | prop = (UInt32)inode->owner; | ||
3275 | break; | ||
3276 | |||
3277 | case kpidGroupId: | ||
3278 | if (inode) | ||
3279 | prop = (UInt32)inode->group; | ||
3280 | break; | ||
3281 | |||
3282 | case kpidLinks: | ||
3283 | if (inode && !inode->IsDir()) | ||
3284 | prop = (UInt32)inode->nlink; | ||
3285 | break; | ||
3286 | |||
3287 | case kpidINode: | ||
3288 | #ifdef APFS_SHOW_ALT_STREAMS | ||
3289 | // here we can disable iNode for alt stream. | ||
3290 | // if (!ref.IsAltStream()) | ||
3291 | #endif | ||
3292 | if (IsViDef(ref.NodeIndex)) | ||
3293 | prop = (UInt32)vol.NodeIDs[ref.NodeIndex]; | ||
3294 | break; | ||
3295 | |||
3296 | case kpidParentINode: | ||
3297 | if (inode) | ||
3298 | prop = (UInt32)inode->parent_id; | ||
3299 | break; | ||
3300 | } | ||
3301 | prop.Detach(value); | ||
3302 | return S_OK; | ||
3303 | COM_TRY_END | ||
3304 | } | ||
3305 | |||
3306 | |||
3307 | UInt64 CDatabase::GetSize(const UInt32 index) const | ||
3308 | { | ||
3309 | const CRef2 &ref2 = Refs2[index]; | ||
3310 | const CVol &vol = Vols[ref2.VolIndex]; | ||
3311 | if (IsViNotDef(ref2.RefIndex)) | ||
3312 | return 0; | ||
3313 | const CRef &ref = vol.Refs[ref2.RefIndex]; | ||
3314 | if (IsViNotDef(ref.NodeIndex)) | ||
3315 | return 0; | ||
3316 | const CNode &inode = vol.Nodes[ref.NodeIndex]; | ||
3317 | UInt64 size; | ||
3318 | if (inode.GetSize(ref.GetAttrIndex(), size)) | ||
3319 | return size; | ||
3320 | return 0; | ||
3321 | } | ||
3322 | |||
3323 | |||
3324 | STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, | ||
3325 | Int32 testMode, IArchiveExtractCallback *extractCallback) | ||
3326 | { | ||
3327 | COM_TRY_BEGIN | ||
3328 | const bool allFilesMode = (numItems == (UInt32)(Int32)-1); | ||
3329 | if (allFilesMode) | ||
3330 | numItems = Refs2.Size(); | ||
3331 | if (numItems == 0) | ||
3332 | return S_OK; | ||
3333 | UInt32 i; | ||
3334 | |||
3335 | { | ||
3336 | UInt64 totalSize = 0; | ||
3337 | for (i = 0; i < numItems; i++) | ||
3338 | { | ||
3339 | const UInt32 index = allFilesMode ? i : indices[i]; | ||
3340 | totalSize += GetSize(index); | ||
3341 | } | ||
3342 | RINOK(extractCallback->SetTotal(totalSize)); | ||
3343 | } | ||
3344 | |||
3345 | UInt64 currentTotalSize = 0, currentItemSize = 0; | ||
3346 | |||
3347 | CLocalProgress *lps = new CLocalProgress; | ||
3348 | CMyComPtr<ICompressProgressInfo> progress = lps; | ||
3349 | lps->Init(extractCallback, false); | ||
3350 | |||
3351 | NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); | ||
3352 | CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; | ||
3353 | |||
3354 | for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) | ||
3355 | { | ||
3356 | lps->InSize = currentTotalSize; | ||
3357 | lps->OutSize = currentTotalSize; | ||
3358 | RINOK(lps->SetCur()); | ||
3359 | |||
3360 | const UInt32 index = allFilesMode ? i : indices[i]; | ||
3361 | const CRef2 &ref2 = Refs2[index]; | ||
3362 | const CVol &vol = Vols[ref2.VolIndex]; | ||
3363 | |||
3364 | currentItemSize = GetSize(index); | ||
3365 | |||
3366 | CMyComPtr<ISequentialOutStream> realOutStream; | ||
3367 | |||
3368 | const Int32 askMode = testMode ? | ||
3369 | NExtract::NAskMode::kTest : | ||
3370 | NExtract::NAskMode::kExtract; | ||
3371 | RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); | ||
3372 | |||
3373 | if (IsViNotDef(ref2.RefIndex)) | ||
3374 | { | ||
3375 | RINOK(extractCallback->PrepareOperation(askMode)); | ||
3376 | RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); | ||
3377 | continue; | ||
3378 | } | ||
3379 | |||
3380 | const CRef &ref = vol.Refs[ref2.RefIndex]; | ||
3381 | bool isDir = false; | ||
3382 | if (IsViDef(ref.NodeIndex)) | ||
3383 | isDir = vol.Nodes[ref.NodeIndex].IsDir(); | ||
3384 | else if (IsViDef(ref.ItemIndex)) | ||
3385 | isDir = | ||
3386 | #ifdef APFS_SHOW_ALT_STREAMS | ||
3387 | !ref.IsAltStream() && | ||
3388 | #endif | ||
3389 | vol.Items[ref.ItemIndex].Val.IsFlags_Dir(); | ||
3390 | |||
3391 | if (isDir) | ||
3392 | { | ||
3393 | RINOK(extractCallback->PrepareOperation(askMode)); | ||
3394 | RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); | ||
3395 | continue; | ||
3396 | } | ||
3397 | if (!testMode && !realOutStream) | ||
3398 | continue; | ||
3399 | RINOK(extractCallback->PrepareOperation(askMode)); | ||
3400 | int opRes = NExtract::NOperationResult::kDataError; | ||
3401 | |||
3402 | CMyComPtr<ISequentialInStream> inStream; | ||
3403 | if (GetStream(index, &inStream) == S_OK && inStream) | ||
3404 | { | ||
3405 | RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); | ||
3406 | opRes = NExtract::NOperationResult::kDataError; | ||
3407 | if (copyCoderSpec->TotalSize == currentItemSize) | ||
3408 | opRes = NExtract::NOperationResult::kOK; | ||
3409 | else if (copyCoderSpec->TotalSize < currentItemSize) | ||
3410 | opRes = NExtract::NOperationResult::kUnexpectedEnd; | ||
3411 | } | ||
3412 | |||
3413 | realOutStream.Release(); | ||
3414 | RINOK(extractCallback->SetOperationResult(opRes)); | ||
3415 | } | ||
3416 | return S_OK; | ||
3417 | COM_TRY_END | ||
3418 | } | ||
3419 | |||
3420 | |||
3421 | STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) | ||
3422 | { | ||
3423 | *numItems = Refs2.Size(); | ||
3424 | return S_OK; | ||
3425 | } | ||
3426 | |||
3427 | |||
3428 | STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) | ||
3429 | { | ||
3430 | *stream = NULL; | ||
3431 | |||
3432 | const CRef2 &ref2 = Refs2[index]; | ||
3433 | const CVol &vol = Vols[ref2.VolIndex]; | ||
3434 | if (IsViNotDef(ref2.RefIndex)) | ||
3435 | return S_FALSE; | ||
3436 | |||
3437 | const CRef &ref = vol.Refs[ref2.RefIndex]; | ||
3438 | if (IsViNotDef(ref.NodeIndex)) | ||
3439 | return S_FALSE; | ||
3440 | const CNode &inode = vol.Nodes[ref.NodeIndex]; | ||
3441 | |||
3442 | const CRecordVector<CExtent> *extents; | ||
3443 | UInt64 rem = 0; | ||
3444 | |||
3445 | unsigned attrIndex = ref.GetAttrIndex(); | ||
3446 | |||
3447 | if (IsViNotDef(attrIndex) | ||
3448 | && !inode.dstream_defined | ||
3449 | && inode.IsSymLink()) | ||
3450 | { | ||
3451 | attrIndex = inode.SymLinkIndex; | ||
3452 | if (IsViNotDef(attrIndex)) | ||
3453 | return S_FALSE; | ||
3454 | } | ||
3455 | |||
3456 | if (IsViDef(attrIndex)) | ||
3457 | { | ||
3458 | const CAttr &attr = inode.Attrs[(unsigned)attrIndex]; | ||
3459 | if (!attr.dstream_defined) | ||
3460 | { | ||
3461 | CBufInStream *streamSpec = new CBufInStream; | ||
3462 | CMyComPtr<ISequentialInStream> streamTemp = streamSpec; | ||
3463 | streamSpec->Init(attr.Data, attr.Data.Size(), (IInArchive *)this); | ||
3464 | *stream = streamTemp.Detach(); | ||
3465 | return S_OK; | ||
3466 | } | ||
3467 | const int idIndex = vol.SmallNodeIDs.FindInSorted(attr.Id); | ||
3468 | if (idIndex == -1) | ||
3469 | return S_FALSE; | ||
3470 | extents = &vol.SmallNodes[(unsigned)idIndex].Extents; | ||
3471 | rem = attr.dstream.size; | ||
3472 | } | ||
3473 | else | ||
3474 | { | ||
3475 | if (IsViDef(ref.ItemIndex)) | ||
3476 | if (vol.Items[ref.ItemIndex].Val.IsFlags_Dir()) | ||
3477 | return S_FALSE; | ||
3478 | if (inode.IsDir()) | ||
3479 | return S_FALSE; | ||
3480 | if (inode.dstream_defined) | ||
3481 | rem = inode.dstream.size; | ||
3482 | extents = &inode.Extents; | ||
3483 | } | ||
3484 | return GetStream2(_stream, extents, rem, stream); | ||
3485 | } | ||
3486 | |||
3487 | |||
3488 | |||
3489 | HRESULT CDatabase::GetStream2( | ||
3490 | IInStream *apfsInStream, | ||
3491 | const CRecordVector<CExtent> *extents, UInt64 rem, | ||
3492 | ISequentialInStream **stream) | ||
3493 | { | ||
3494 | CExtentsStream *extentStreamSpec = new CExtentsStream(); | ||
3495 | CMyComPtr<ISequentialInStream> extentStream = extentStreamSpec; | ||
3496 | |||
3497 | UInt64 virt = 0; | ||
3498 | FOR_VECTOR (i, *extents) | ||
3499 | { | ||
3500 | const CExtent &e = (*extents)[i]; | ||
3501 | if (virt != e.logical_offset) | ||
3502 | return S_FALSE; | ||
3503 | const UInt64 len = EXTENT_GET_LEN(e.len_and_flags); | ||
3504 | if (len == 0) | ||
3505 | { | ||
3506 | return S_FALSE; | ||
3507 | // continue; | ||
3508 | } | ||
3509 | if (rem == 0) | ||
3510 | return S_FALSE; | ||
3511 | UInt64 cur = len; | ||
3512 | if (cur > rem) | ||
3513 | cur = rem; | ||
3514 | CSeekExtent se; | ||
3515 | se.Phy = (UInt64)e.phys_block_num << sb.block_size_Log; | ||
3516 | se.Virt = virt; | ||
3517 | virt += cur; | ||
3518 | rem -= cur; | ||
3519 | extentStreamSpec->Extents.Add(se); | ||
3520 | if (rem == 0) | ||
3521 | if (i != extents->Size() - 1) | ||
3522 | return S_FALSE; | ||
3523 | } | ||
3524 | |||
3525 | if (rem != 0) | ||
3526 | return S_FALSE; | ||
3527 | |||
3528 | CSeekExtent se; | ||
3529 | se.Phy = 0; | ||
3530 | se.Virt = virt; | ||
3531 | extentStreamSpec->Extents.Add(se); | ||
3532 | extentStreamSpec->Stream = apfsInStream; | ||
3533 | extentStreamSpec->Init(); | ||
3534 | *stream = extentStream.Detach(); | ||
3535 | return S_OK; | ||
3536 | } | ||
3537 | |||
3538 | |||
3539 | REGISTER_ARC_I( | ||
3540 | "APFS", "apfs img", NULL, 0xc3, | ||
3541 | k_Signature, | ||
3542 | k_SignatureOffset, | ||
3543 | 0, | ||
3544 | IsArc_APFS) | ||
3545 | |||
3546 | }} | ||
diff --git a/CPP/7zip/Archive/ArHandler.cpp b/CPP/7zip/Archive/ArHandler.cpp index 0bea8b4..6cd72bb 100644 --- a/CPP/7zip/Archive/ArHandler.cpp +++ b/CPP/7zip/Archive/ArHandler.cpp | |||
@@ -322,8 +322,8 @@ static const Byte kProps[] = | |||
322 | kpidSize, | 322 | kpidSize, |
323 | kpidMTime, | 323 | kpidMTime, |
324 | kpidPosixAttrib, | 324 | kpidPosixAttrib, |
325 | kpidUser, | 325 | kpidUserId, |
326 | kpidGroup | 326 | kpidGroupId |
327 | }; | 327 | }; |
328 | 328 | ||
329 | IMP_IInArchive_Props | 329 | IMP_IInArchive_Props |
@@ -734,15 +734,11 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
734 | case kpidMTime: | 734 | case kpidMTime: |
735 | { | 735 | { |
736 | if (item.MTime != 0) | 736 | if (item.MTime != 0) |
737 | { | 737 | PropVariant_SetFrom_UnixTime(prop, item.MTime); |
738 | FILETIME fileTime; | ||
739 | NTime::UnixTimeToFileTime(item.MTime, fileTime); | ||
740 | prop = fileTime; | ||
741 | } | ||
742 | break; | 738 | break; |
743 | } | 739 | } |
744 | case kpidUser: if (item.User != 0) prop = item.User; break; | 740 | case kpidUserId: if (item.User != 0) prop = item.User; break; |
745 | case kpidGroup: if (item.Group != 0) prop = item.Group; break; | 741 | case kpidGroupId: if (item.Group != 0) prop = item.Group; break; |
746 | case kpidPosixAttrib: | 742 | case kpidPosixAttrib: |
747 | if (item.TextFileIndex < 0) | 743 | if (item.TextFileIndex < 0) |
748 | prop = item.Mode; | 744 | prop = item.Mode; |
diff --git a/CPP/7zip/Archive/ArchiveExports.cpp b/CPP/7zip/Archive/ArchiveExports.cpp index 6549b3d..8a441bc 100644 --- a/CPP/7zip/Archive/ArchiveExports.cpp +++ b/CPP/7zip/Archive/ArchiveExports.cpp | |||
@@ -115,6 +115,7 @@ STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value | |||
115 | case NArchive::NHandlerPropID::kAltStreams: prop = ((arc.Flags & NArcInfoFlags::kAltStreams) != 0); break; | 115 | case NArchive::NHandlerPropID::kAltStreams: prop = ((arc.Flags & NArcInfoFlags::kAltStreams) != 0); break; |
116 | case NArchive::NHandlerPropID::kNtSecure: prop = ((arc.Flags & NArcInfoFlags::kNtSecure) != 0); break; | 116 | case NArchive::NHandlerPropID::kNtSecure: prop = ((arc.Flags & NArcInfoFlags::kNtSecure) != 0); break; |
117 | case NArchive::NHandlerPropID::kFlags: prop = (UInt32)arc.Flags; break; | 117 | case NArchive::NHandlerPropID::kFlags: prop = (UInt32)arc.Flags; break; |
118 | case NArchive::NHandlerPropID::kTimeFlags: prop = (UInt32)arc.TimeFlags; break; | ||
118 | case NArchive::NHandlerPropID::kSignatureOffset: prop = (UInt32)arc.SignatureOffset; break; | 119 | case NArchive::NHandlerPropID::kSignatureOffset: prop = (UInt32)arc.SignatureOffset; break; |
119 | // case NArchive::NHandlerPropID::kVersion: prop = (UInt32)MY_VER_MIX; break; | 120 | // case NArchive::NHandlerPropID::kVersion: prop = (UInt32)MY_VER_MIX; break; |
120 | 121 | ||
diff --git a/CPP/7zip/Archive/ArjHandler.cpp b/CPP/7zip/Archive/ArjHandler.cpp index 0e353dc..125b9c2 100644 --- a/CPP/7zip/Archive/ArjHandler.cpp +++ b/CPP/7zip/Archive/ArjHandler.cpp | |||
@@ -682,15 +682,7 @@ static void SetTime(UInt32 dosTime, NCOM::CPropVariant &prop) | |||
682 | { | 682 | { |
683 | if (dosTime == 0) | 683 | if (dosTime == 0) |
684 | return; | 684 | return; |
685 | FILETIME localFileTime, utc; | 685 | PropVariant_SetFrom_DosTime(prop, dosTime); |
686 | if (NTime::DosTimeToFileTime(dosTime, localFileTime)) | ||
687 | { | ||
688 | if (!LocalFileTimeToFileTime(&localFileTime, &utc)) | ||
689 | utc.dwHighDateTime = utc.dwLowDateTime = 0; | ||
690 | } | ||
691 | else | ||
692 | utc.dwHighDateTime = utc.dwLowDateTime = 0; | ||
693 | prop = utc; | ||
694 | } | 686 | } |
695 | 687 | ||
696 | static void SetHostOS(Byte hostOS, NCOM::CPropVariant &prop) | 688 | static void SetHostOS(Byte hostOS, NCOM::CPropVariant &prop) |
diff --git a/CPP/7zip/Archive/Bz2Handler.cpp b/CPP/7zip/Archive/Bz2Handler.cpp index b0c2f75..c89a53c 100644 --- a/CPP/7zip/Archive/Bz2Handler.cpp +++ b/CPP/7zip/Archive/Bz2Handler.cpp | |||
@@ -305,29 +305,91 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
305 | } | 305 | } |
306 | 306 | ||
307 | 307 | ||
308 | /* | ||
309 | static HRESULT ReportItemProp(IArchiveUpdateCallbackArcProp *reportArcProp, PROPID propID, const PROPVARIANT *value) | ||
310 | { | ||
311 | return reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, 0, propID, value); | ||
312 | } | ||
313 | |||
314 | static HRESULT ReportArcProp(IArchiveUpdateCallbackArcProp *reportArcProp, PROPID propID, const PROPVARIANT *value) | ||
315 | { | ||
316 | return reportArcProp->ReportProp(NEventIndexType::kArcProp, 0, propID, value); | ||
317 | } | ||
318 | |||
319 | static HRESULT ReportArcProps(IArchiveUpdateCallbackArcProp *reportArcProp, | ||
320 | const UInt64 *unpackSize, | ||
321 | const UInt64 *numBlocks) | ||
322 | { | ||
323 | NCOM::CPropVariant sizeProp; | ||
324 | if (unpackSize) | ||
325 | { | ||
326 | sizeProp = *unpackSize; | ||
327 | RINOK(ReportItemProp(reportArcProp, kpidSize, &sizeProp)); | ||
328 | RINOK(reportArcProp->ReportFinished(NEventIndexType::kOutArcIndex, 0, NArchive::NUpdate::NOperationResult::kOK)); | ||
329 | } | ||
330 | |||
331 | if (unpackSize) | ||
332 | { | ||
333 | RINOK(ReportArcProp(reportArcProp, kpidSize, &sizeProp)); | ||
334 | } | ||
335 | if (numBlocks) | ||
336 | { | ||
337 | NCOM::CPropVariant prop; | ||
338 | prop = *numBlocks; | ||
339 | RINOK(ReportArcProp(reportArcProp, kpidNumBlocks, &prop)); | ||
340 | } | ||
341 | return S_OK; | ||
342 | } | ||
343 | */ | ||
308 | 344 | ||
309 | static HRESULT UpdateArchive( | 345 | static HRESULT UpdateArchive( |
310 | UInt64 unpackSize, | 346 | UInt64 unpackSize, |
311 | ISequentialOutStream *outStream, | 347 | ISequentialOutStream *outStream, |
312 | const CProps &props, | 348 | const CProps &props, |
313 | IArchiveUpdateCallback *updateCallback) | 349 | IArchiveUpdateCallback *updateCallback |
350 | // , ArchiveUpdateCallbackArcProp *reportArcProp | ||
351 | ) | ||
314 | { | 352 | { |
315 | RINOK(updateCallback->SetTotal(unpackSize)); | 353 | { |
316 | CMyComPtr<ISequentialInStream> fileInStream; | 354 | CMyComPtr<ISequentialInStream> fileInStream; |
317 | RINOK(updateCallback->GetStream(0, &fileInStream)); | 355 | RINOK(updateCallback->GetStream(0, &fileInStream)); |
318 | CLocalProgress *localProgressSpec = new CLocalProgress; | 356 | if (!fileInStream) |
319 | CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec; | 357 | return S_FALSE; |
320 | localProgressSpec->Init(updateCallback, true); | 358 | { |
321 | NCompress::NBZip2::CEncoder *encoderSpec = new NCompress::NBZip2::CEncoder; | 359 | CMyComPtr<IStreamGetSize> streamGetSize; |
322 | CMyComPtr<ICompressCoder> encoder = encoderSpec; | 360 | fileInStream.QueryInterface(IID_IStreamGetSize, &streamGetSize); |
323 | RINOK(props.SetCoderProps(encoderSpec, NULL)); | 361 | if (streamGetSize) |
324 | RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, localProgress)); | 362 | { |
363 | UInt64 size; | ||
364 | if (streamGetSize->GetSize(&size) == S_OK) | ||
365 | unpackSize = size; | ||
366 | } | ||
367 | } | ||
368 | RINOK(updateCallback->SetTotal(unpackSize)); | ||
369 | CLocalProgress *localProgressSpec = new CLocalProgress; | ||
370 | CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec; | ||
371 | localProgressSpec->Init(updateCallback, true); | ||
372 | { | ||
373 | NCompress::NBZip2::CEncoder *encoderSpec = new NCompress::NBZip2::CEncoder; | ||
374 | CMyComPtr<ICompressCoder> encoder = encoderSpec; | ||
375 | RINOK(props.SetCoderProps(encoderSpec, NULL)); | ||
376 | RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, localProgress)); | ||
377 | /* | ||
378 | if (reportArcProp) | ||
379 | { | ||
380 | unpackSize = encoderSpec->GetInProcessedSize(); | ||
381 | RINOK(ReportArcProps(reportArcProp, &unpackSize, &encoderSpec->NumBlocks)); | ||
382 | } | ||
383 | */ | ||
384 | } | ||
385 | } | ||
325 | return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); | 386 | return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); |
326 | } | 387 | } |
327 | 388 | ||
328 | STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) | 389 | STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) |
329 | { | 390 | { |
330 | *type = NFileTimeType::kUnix; | 391 | *timeType = GET_FileTimeType_NotDefined_for_GetFileTimeType; |
392 | // *timeType = NFileTimeType::kUnix; | ||
331 | return S_OK; | 393 | return S_OK; |
332 | } | 394 | } |
333 | 395 | ||
@@ -345,6 +407,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
345 | return E_FAIL; | 407 | return E_FAIL; |
346 | RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive)); | 408 | RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive)); |
347 | 409 | ||
410 | /* | ||
411 | CMyComPtr<IArchiveUpdateCallbackArcProp> reportArcProp; | ||
412 | updateCallback->QueryInterface(IID_IArchiveUpdateCallbackArcProp, (void **)&reportArcProp); | ||
413 | */ | ||
414 | |||
348 | if (IntToBool(newProps)) | 415 | if (IntToBool(newProps)) |
349 | { | 416 | { |
350 | { | 417 | { |
@@ -396,6 +463,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
396 | 463 | ||
397 | return NCompress::CopyStream(_stream, outStream, progress); | 464 | return NCompress::CopyStream(_stream, outStream, progress); |
398 | 465 | ||
466 | // return ReportArcProps(reportArcProp, NULL, NULL); | ||
467 | |||
399 | COM_TRY_END | 468 | COM_TRY_END |
400 | } | 469 | } |
401 | 470 | ||
@@ -410,7 +479,8 @@ REGISTER_ARC_IO( | |||
410 | "bzip2", "bz2 bzip2 tbz2 tbz", "* * .tar .tar", 2, | 479 | "bzip2", "bz2 bzip2 tbz2 tbz", "* * .tar .tar", 2, |
411 | k_Signature, | 480 | k_Signature, |
412 | 0, | 481 | 0, |
413 | NArcInfoFlags::kKeepName, | 482 | NArcInfoFlags::kKeepName |
414 | IsArc_BZip2) | 483 | , 0 |
484 | , IsArc_BZip2) | ||
415 | 485 | ||
416 | }} | 486 | }} |
diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp index fafd7aa..804c921 100644 --- a/CPP/7zip/Archive/Cab/CabHandler.cpp +++ b/CPP/7zip/Archive/Cab/CabHandler.cpp | |||
@@ -295,15 +295,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
295 | 295 | ||
296 | case kpidMTime: | 296 | case kpidMTime: |
297 | { | 297 | { |
298 | FILETIME localFileTime, utcFileTime; | 298 | PropVariant_SetFrom_DosTime(prop, item.Time); |
299 | if (NTime::DosTimeToFileTime(item.Time, localFileTime)) | ||
300 | { | ||
301 | if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime)) | ||
302 | utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0; | ||
303 | } | ||
304 | else | ||
305 | utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0; | ||
306 | prop = utcFileTime; | ||
307 | break; | 299 | break; |
308 | } | 300 | } |
309 | 301 | ||
diff --git a/CPP/7zip/Archive/Chm/ChmIn.h b/CPP/7zip/Archive/Chm/ChmIn.h index f7b75d8..7cba0c7 100644 --- a/CPP/7zip/Archive/Chm/ChmIn.h +++ b/CPP/7zip/Archive/Chm/ChmIn.h | |||
@@ -84,6 +84,11 @@ struct CResetTable | |||
84 | // unsigned BlockSizeBits; | 84 | // unsigned BlockSizeBits; |
85 | CRecordVector<UInt64> ResetOffsets; | 85 | CRecordVector<UInt64> ResetOffsets; |
86 | 86 | ||
87 | CResetTable(): | ||
88 | UncompressedSize(0), | ||
89 | CompressedSize(0) | ||
90 | {} | ||
91 | |||
87 | bool GetCompressedSizeOfBlocks(UInt64 blockIndex, UInt32 numBlocks, UInt64 &size) const | 92 | bool GetCompressedSizeOfBlocks(UInt64 blockIndex, UInt32 numBlocks, UInt64 &size) const |
88 | { | 93 | { |
89 | if (blockIndex >= ResetOffsets.Size()) | 94 | if (blockIndex >= ResetOffsets.Size()) |
@@ -118,6 +123,12 @@ struct CLzxInfo | |||
118 | 123 | ||
119 | CResetTable ResetTable; | 124 | CResetTable ResetTable; |
120 | 125 | ||
126 | CLzxInfo(): | ||
127 | Version(0), | ||
128 | ResetIntervalBits(0), | ||
129 | CacheSize(0) | ||
130 | {} | ||
131 | |||
121 | unsigned GetNumDictBits() const | 132 | unsigned GetNumDictBits() const |
122 | { | 133 | { |
123 | if (Version == 2 || Version == 3) | 134 | if (Version == 2 || Version == 3) |
diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp index 8901220..1b9a93e 100644 --- a/CPP/7zip/Archive/Common/HandlerOut.cpp +++ b/CPP/7zip/Archive/Common/HandlerOut.cpp | |||
@@ -240,34 +240,42 @@ void CSingleMethodProps::Init() | |||
240 | } | 240 | } |
241 | 241 | ||
242 | 242 | ||
243 | HRESULT CSingleMethodProps::SetProperty(const wchar_t *name2, const PROPVARIANT &value) | ||
244 | { | ||
245 | // processed = false; | ||
246 | UString name = name2; | ||
247 | name.MakeLower_Ascii(); | ||
248 | if (name.IsEmpty()) | ||
249 | return E_INVALIDARG; | ||
250 | if (name.IsPrefixedBy_Ascii_NoCase("x")) | ||
251 | { | ||
252 | UInt32 a = 9; | ||
253 | RINOK(ParsePropToUInt32(name.Ptr(1), value, a)); | ||
254 | _level = a; | ||
255 | AddProp_Level(a); | ||
256 | // processed = true; | ||
257 | return S_OK; | ||
258 | } | ||
259 | { | ||
260 | HRESULT hres; | ||
261 | if (SetCommonProperty(name, value, hres)) | ||
262 | { | ||
263 | // processed = true; | ||
264 | return S_OK; | ||
265 | } | ||
266 | } | ||
267 | RINOK(ParseMethodFromPROPVARIANT(name, value)); | ||
268 | return S_OK; | ||
269 | } | ||
270 | |||
271 | |||
243 | HRESULT CSingleMethodProps::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) | 272 | HRESULT CSingleMethodProps::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) |
244 | { | 273 | { |
245 | Init(); | 274 | Init(); |
246 | 275 | ||
247 | for (UInt32 i = 0; i < numProps; i++) | 276 | for (UInt32 i = 0; i < numProps; i++) |
248 | { | 277 | { |
249 | UString name = names[i]; | 278 | RINOK(SetProperty(names[i], values[i])); |
250 | name.MakeLower_Ascii(); | ||
251 | if (name.IsEmpty()) | ||
252 | return E_INVALIDARG; | ||
253 | const PROPVARIANT &value = values[i]; | ||
254 | if (name[0] == L'x') | ||
255 | { | ||
256 | UInt32 a = 9; | ||
257 | RINOK(ParsePropToUInt32(name.Ptr(1), value, a)); | ||
258 | _level = a; | ||
259 | AddProp_Level(a); | ||
260 | continue; | ||
261 | } | ||
262 | { | ||
263 | HRESULT hres; | ||
264 | if (SetCommonProperty(name, value, hres)) | ||
265 | { | ||
266 | RINOK(hres) | ||
267 | continue; | ||
268 | } | ||
269 | } | ||
270 | RINOK(ParseMethodFromPROPVARIANT(names[i], value)); | ||
271 | } | 279 | } |
272 | 280 | ||
273 | return S_OK; | 281 | return S_OK; |
@@ -275,4 +283,29 @@ HRESULT CSingleMethodProps::SetProperties(const wchar_t * const *names, const PR | |||
275 | 283 | ||
276 | #endif | 284 | #endif |
277 | 285 | ||
286 | |||
287 | static HRESULT PROPVARIANT_to_BoolPair(const PROPVARIANT &prop, CBoolPair &dest) | ||
288 | { | ||
289 | RINOK(PROPVARIANT_to_bool(prop, dest.Val)); | ||
290 | dest.Def = true; | ||
291 | return S_OK; | ||
292 | } | ||
293 | |||
294 | HRESULT CHandlerTimeOptions::Parse(const UString &name, const PROPVARIANT &prop, bool &processed) | ||
295 | { | ||
296 | processed = true; | ||
297 | if (name.IsEqualTo_Ascii_NoCase("tm")) { return PROPVARIANT_to_BoolPair(prop, Write_MTime); } | ||
298 | if (name.IsEqualTo_Ascii_NoCase("ta")) { return PROPVARIANT_to_BoolPair(prop, Write_ATime); } | ||
299 | if (name.IsEqualTo_Ascii_NoCase("tc")) { return PROPVARIANT_to_BoolPair(prop, Write_CTime); } | ||
300 | if (name.IsPrefixedBy_Ascii_NoCase("tp")) | ||
301 | { | ||
302 | UInt32 v = 0; | ||
303 | RINOK(ParsePropToUInt32(name.Ptr(2), prop, v)); | ||
304 | Prec = v; | ||
305 | return S_OK; | ||
306 | } | ||
307 | processed = false; | ||
308 | return S_OK; | ||
309 | } | ||
310 | |||
278 | } | 311 | } |
diff --git a/CPP/7zip/Archive/Common/HandlerOut.h b/CPP/7zip/Archive/Common/HandlerOut.h index b3d07e9..41ee189 100644 --- a/CPP/7zip/Archive/Common/HandlerOut.h +++ b/CPP/7zip/Archive/Common/HandlerOut.h | |||
@@ -16,6 +16,7 @@ class CCommonMethodProps | |||
16 | protected: | 16 | protected: |
17 | void InitCommon() | 17 | void InitCommon() |
18 | { | 18 | { |
19 | // _Write_MTime = true; | ||
19 | #ifndef _7ZIP_ST | 20 | #ifndef _7ZIP_ST |
20 | _numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors(); | 21 | _numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors(); |
21 | _numThreads_WasForced = false; | 22 | _numThreads_WasForced = false; |
@@ -118,11 +119,36 @@ public: | |||
118 | CSingleMethodProps() { InitSingle(); } | 119 | CSingleMethodProps() { InitSingle(); } |
119 | 120 | ||
120 | int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; } | 121 | int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; } |
122 | HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &values); | ||
121 | HRESULT SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps); | 123 | HRESULT SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps); |
122 | }; | 124 | }; |
123 | 125 | ||
124 | #endif | 126 | #endif |
125 | 127 | ||
128 | struct CHandlerTimeOptions | ||
129 | { | ||
130 | CBoolPair Write_MTime; | ||
131 | CBoolPair Write_ATime; | ||
132 | CBoolPair Write_CTime; | ||
133 | UInt32 Prec; | ||
134 | |||
135 | void Init() | ||
136 | { | ||
137 | Write_MTime.Init(); | ||
138 | Write_MTime.Val = true; | ||
139 | Write_ATime.Init(); | ||
140 | Write_CTime.Init(); | ||
141 | Prec = (UInt32)(Int32)-1; | ||
142 | } | ||
143 | |||
144 | CHandlerTimeOptions() | ||
145 | { | ||
146 | Init(); | ||
147 | } | ||
148 | |||
149 | HRESULT Parse(const UString &name, const PROPVARIANT &prop, bool &processed); | ||
150 | }; | ||
151 | |||
126 | } | 152 | } |
127 | 153 | ||
128 | #endif | 154 | #endif |
diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/CPP/7zip/Archive/Common/ItemNameUtils.cpp index 905a863..8caf1d1 100644 --- a/CPP/7zip/Archive/Common/ItemNameUtils.cpp +++ b/CPP/7zip/Archive/Common/ItemNameUtils.cpp | |||
@@ -79,6 +79,29 @@ void ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool | |||
79 | } | 79 | } |
80 | 80 | ||
81 | 81 | ||
82 | void NormalizeSlashes_in_FileName_for_OsPath(wchar_t *name, unsigned len) | ||
83 | { | ||
84 | for (unsigned i = 0; i < len; i++) | ||
85 | { | ||
86 | wchar_t c = name[i]; | ||
87 | if (c == L'/') | ||
88 | c = L'_'; | ||
89 | #if WCHAR_PATH_SEPARATOR != L'/' | ||
90 | else if (c == L'\\') | ||
91 | c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme | ||
92 | #endif | ||
93 | else | ||
94 | continue; | ||
95 | name[i] = c; | ||
96 | } | ||
97 | } | ||
98 | |||
99 | void NormalizeSlashes_in_FileName_for_OsPath(UString &name) | ||
100 | { | ||
101 | NormalizeSlashes_in_FileName_for_OsPath(name.GetBuf(), name.Len()); | ||
102 | } | ||
103 | |||
104 | |||
82 | bool HasTailSlash(const AString &name, UINT | 105 | bool HasTailSlash(const AString &name, UINT |
83 | #if defined(_WIN32) && !defined(UNDER_CE) | 106 | #if defined(_WIN32) && !defined(UNDER_CE) |
84 | codePage | 107 | codePage |
diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.h b/CPP/7zip/Archive/Common/ItemNameUtils.h index 6a4d6c7..3f5f4e8 100644 --- a/CPP/7zip/Archive/Common/ItemNameUtils.h +++ b/CPP/7zip/Archive/Common/ItemNameUtils.h | |||
@@ -14,6 +14,8 @@ UString GetOsPath(const UString &name); | |||
14 | UString GetOsPath_Remove_TailSlash(const UString &name); | 14 | UString GetOsPath_Remove_TailSlash(const UString &name); |
15 | 15 | ||
16 | void ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool useBackslashReplacement = false); | 16 | void ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool useBackslashReplacement = false); |
17 | void NormalizeSlashes_in_FileName_for_OsPath(wchar_t *s, unsigned len); | ||
18 | void NormalizeSlashes_in_FileName_for_OsPath(UString &name); | ||
17 | 19 | ||
18 | bool HasTailSlash(const AString &name, UINT codePage); | 20 | bool HasTailSlash(const AString &name, UINT codePage); |
19 | 21 | ||
diff --git a/CPP/7zip/Archive/CpioHandler.cpp b/CPP/7zip/Archive/CpioHandler.cpp index ffdab16..b7e7564 100644 --- a/CPP/7zip/Archive/CpioHandler.cpp +++ b/CPP/7zip/Archive/CpioHandler.cpp | |||
@@ -652,11 +652,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
652 | case kpidMTime: | 652 | case kpidMTime: |
653 | { | 653 | { |
654 | if (item.MTime != 0) | 654 | if (item.MTime != 0) |
655 | { | 655 | PropVariant_SetFrom_UnixTime(prop, item.MTime); |
656 | FILETIME utc; | ||
657 | NTime::UnixTimeToFileTime(item.MTime, utc); | ||
658 | prop = utc; | ||
659 | } | ||
660 | break; | 656 | break; |
661 | } | 657 | } |
662 | case kpidPosixAttrib: prop = item.Mode; break; | 658 | case kpidPosixAttrib: prop = item.Mode; break; |
diff --git a/CPP/7zip/Archive/DllExports2.cpp b/CPP/7zip/Archive/DllExports2.cpp index 967a7cb..1f71486 100644 --- a/CPP/7zip/Archive/DllExports2.cpp +++ b/CPP/7zip/Archive/DllExports2.cpp | |||
@@ -125,6 +125,24 @@ STDAPI SetCaseSensitive(Int32 caseSensitive) | |||
125 | return S_OK; | 125 | return S_OK; |
126 | } | 126 | } |
127 | 127 | ||
128 | /* | ||
129 | UInt32 g_ClientVersion; | ||
130 | STDAPI SetClientVersion(UInt32 version); | ||
131 | STDAPI SetClientVersion(UInt32 version) | ||
132 | { | ||
133 | g_ClientVersion = version; | ||
134 | return S_OK; | ||
135 | } | ||
136 | */ | ||
137 | |||
138 | /* | ||
139 | STDAPI SetProperty(Int32 id, const PROPVARIANT *value); | ||
140 | STDAPI SetProperty(Int32 id, const PROPVARIANT *value) | ||
141 | { | ||
142 | return S_OK; | ||
143 | } | ||
144 | */ | ||
145 | |||
128 | #ifdef EXTERNAL_CODECS | 146 | #ifdef EXTERNAL_CODECS |
129 | 147 | ||
130 | CExternalCodecs g_ExternalCodecs; | 148 | CExternalCodecs g_ExternalCodecs; |
diff --git a/CPP/7zip/Archive/ExtHandler.cpp b/CPP/7zip/Archive/ExtHandler.cpp index 6c095d9..01e12ed 100644 --- a/CPP/7zip/Archive/ExtHandler.cpp +++ b/CPP/7zip/Archive/ExtHandler.cpp | |||
@@ -343,6 +343,8 @@ struct CHeader | |||
343 | bool UseGdtChecksum() const { return (FeatureRoCompat & RO_COMPAT_GDT_CSUM) != 0; } | 343 | bool UseGdtChecksum() const { return (FeatureRoCompat & RO_COMPAT_GDT_CSUM) != 0; } |
344 | bool UseMetadataChecksum() const { return (FeatureRoCompat & RO_COMPAT_METADATA_CSUM) != 0; } | 344 | bool UseMetadataChecksum() const { return (FeatureRoCompat & RO_COMPAT_METADATA_CSUM) != 0; } |
345 | 345 | ||
346 | UInt64 GetPhySize() const { return NumBlocks << BlockBits; } | ||
347 | |||
346 | bool Parse(const Byte *p); | 348 | bool Parse(const Byte *p); |
347 | }; | 349 | }; |
348 | 350 | ||
@@ -638,7 +640,7 @@ struct CNode | |||
638 | CExtTime MTime; | 640 | CExtTime MTime; |
639 | CExtTime ATime; | 641 | CExtTime ATime; |
640 | CExtTime CTime; | 642 | CExtTime CTime; |
641 | // CExtTime InodeChangeTime; | 643 | CExtTime ChangeTime; |
642 | // CExtTime DTime; | 644 | // CExtTime DTime; |
643 | 645 | ||
644 | UInt64 NumBlocks; | 646 | UInt64 NumBlocks; |
@@ -674,14 +676,14 @@ bool CNode::Parse(const Byte *p, const CHeader &_h) | |||
674 | ATime.Extra = 0; | 676 | ATime.Extra = 0; |
675 | CTime.Extra = 0; | 677 | CTime.Extra = 0; |
676 | CTime.Val = 0; | 678 | CTime.Val = 0; |
677 | // InodeChangeTime.Extra = 0; | 679 | ChangeTime.Extra = 0; |
678 | // DTime.Extra = 0; | 680 | // DTime.Extra = 0; |
679 | 681 | ||
680 | LE_16 (0x00, Mode); | 682 | LE_16 (0x00, Mode); |
681 | LE_16 (0x02, Uid); | 683 | LE_16 (0x02, Uid); |
682 | LE_32 (0x04, FileSize); | 684 | LE_32 (0x04, FileSize); |
683 | LE_32 (0x08, ATime.Val); | 685 | LE_32 (0x08, ATime.Val); |
684 | // LE_32 (0x0C, InodeChangeTime.Val); | 686 | LE_32 (0x0C, ChangeTime.Val); |
685 | LE_32 (0x10, MTime.Val); | 687 | LE_32 (0x10, MTime.Val); |
686 | // LE_32 (0x14, DTime.Val); | 688 | // LE_32 (0x14, DTime.Val); |
687 | LE_16 (0x18, Gid); | 689 | LE_16 (0x18, Gid); |
@@ -742,7 +744,7 @@ bool CNode::Parse(const Byte *p, const CHeader &_h) | |||
742 | { | 744 | { |
743 | // UInt16 checksumUpper; | 745 | // UInt16 checksumUpper; |
744 | // LE_16 (0x82, checksumUpper); | 746 | // LE_16 (0x82, checksumUpper); |
745 | // LE_32 (0x84, InodeChangeTime.Extra); | 747 | LE_32 (0x84, ChangeTime.Extra); |
746 | LE_32 (0x88, MTime.Extra); | 748 | LE_32 (0x88, MTime.Extra); |
747 | LE_32 (0x8C, ATime.Extra); | 749 | LE_32 (0x8C, ATime.Extra); |
748 | LE_32 (0x90, CTime.Val); | 750 | LE_32 (0x90, CTime.Val); |
@@ -1148,7 +1150,7 @@ HRESULT CHandler::Open2(IInStream *inStream) | |||
1148 | } | 1150 | } |
1149 | 1151 | ||
1150 | _isArc = true; | 1152 | _isArc = true; |
1151 | _phySize = _h.NumBlocks << _h.BlockBits; | 1153 | _phySize = _h.GetPhySize(); |
1152 | 1154 | ||
1153 | if (_openCallback) | 1155 | if (_openCallback) |
1154 | { | 1156 | { |
@@ -1744,8 +1746,8 @@ static const UInt32 kProps[] = | |||
1744 | kpidLinks, | 1746 | kpidLinks, |
1745 | kpidSymLink, | 1747 | kpidSymLink, |
1746 | kpidCharacts, | 1748 | kpidCharacts, |
1747 | kpidUser, | 1749 | kpidUserId, |
1748 | kpidGroup | 1750 | kpidGroupId |
1749 | }; | 1751 | }; |
1750 | 1752 | ||
1751 | 1753 | ||
@@ -1792,11 +1794,7 @@ static void StringToProp(bool isUTF, const char *s, unsigned size, NCOM::CPropVa | |||
1792 | static void UnixTimeToProp(UInt32 val, NCOM::CPropVariant &prop) | 1794 | static void UnixTimeToProp(UInt32 val, NCOM::CPropVariant &prop) |
1793 | { | 1795 | { |
1794 | if (val != 0) | 1796 | if (val != 0) |
1795 | { | 1797 | PropVariant_SetFrom_UnixTime(prop, val); |
1796 | FILETIME ft; | ||
1797 | NTime::UnixTimeToFileTime(val, ft); | ||
1798 | prop = ft; | ||
1799 | } | ||
1800 | } | 1798 | } |
1801 | 1799 | ||
1802 | STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | 1800 | STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) |
@@ -1988,15 +1986,19 @@ static void ExtTimeToProp(const CExtTime &t, NCOM::CPropVariant &prop) | |||
1988 | return; | 1986 | return; |
1989 | 1987 | ||
1990 | FILETIME ft; | 1988 | FILETIME ft; |
1989 | unsigned low100ns = 0; | ||
1991 | // if (t.Extra != 0) | 1990 | // if (t.Extra != 0) |
1992 | { | 1991 | { |
1993 | // 1901-2446 : | 1992 | // 1901-2446 : |
1994 | Int64 v = (Int64)(Int32)t.Val; | 1993 | Int64 v = (Int64)(Int32)t.Val; |
1995 | v += (UInt64)(t.Extra & 3) << 32; // 2 low bits are offset for main timestamp | 1994 | v += (UInt64)(t.Extra & 3) << 32; // 2 low bits are offset for main timestamp |
1996 | UInt64 ft64 = NTime::UnixTime64ToFileTime64(v); | 1995 | UInt64 ft64 = NTime::UnixTime64_To_FileTime64(v); |
1997 | const UInt32 ns = (t.Extra >> 2); | 1996 | const UInt32 ns = (t.Extra >> 2); |
1998 | if (ns < 1000000000) | 1997 | if (ns < 1000000000) |
1998 | { | ||
1999 | ft64 += ns / 100; | 1999 | ft64 += ns / 100; |
2000 | low100ns = (unsigned)(ns % 100); | ||
2001 | } | ||
2000 | ft.dwLowDateTime = (DWORD)ft64; | 2002 | ft.dwLowDateTime = (DWORD)ft64; |
2001 | ft.dwHighDateTime = (DWORD)(ft64 >> 32); | 2003 | ft.dwHighDateTime = (DWORD)(ft64 >> 32); |
2002 | } | 2004 | } |
@@ -2011,7 +2013,7 @@ static void ExtTimeToProp(const CExtTime &t, NCOM::CPropVariant &prop) | |||
2011 | // NTime::UnixTimeToFileTime(t.Val, ft); // for | 2013 | // NTime::UnixTimeToFileTime(t.Val, ft); // for |
2012 | } | 2014 | } |
2013 | */ | 2015 | */ |
2014 | prop = ft; | 2016 | prop.SetAsTimeFrom_FT_Prec_Ns100(ft, k_PropVar_TimePrec_1ns, low100ns); |
2015 | } | 2017 | } |
2016 | 2018 | ||
2017 | 2019 | ||
@@ -2103,10 +2105,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
2103 | case kpidCTime: ExtTimeToProp(node.CTime, prop); break; | 2105 | case kpidCTime: ExtTimeToProp(node.CTime, prop); break; |
2104 | case kpidATime: ExtTimeToProp(node.ATime, prop); break; | 2106 | case kpidATime: ExtTimeToProp(node.ATime, prop); break; |
2105 | // case kpidDTime: ExtTimeToProp(node.DTime, prop); break; | 2107 | // case kpidDTime: ExtTimeToProp(node.DTime, prop); break; |
2106 | // case kpidChangeTime: ExtTimeToProp(node.InodeChangeTime, prop); break; | 2108 | case kpidChangeTime: ExtTimeToProp(node.ChangeTime, prop); break; |
2107 | 2109 | case kpidUserId: prop = (UInt32)node.Uid; break; | |
2108 | case kpidUser: prop = (UInt32)node.Uid; break; | 2110 | case kpidGroupId: prop = (UInt32)node.Gid; break; |
2109 | case kpidGroup: prop = (UInt32)node.Gid; break; | ||
2110 | case kpidLinks: prop = node.NumLinks; break; | 2111 | case kpidLinks: prop = node.NumLinks; break; |
2111 | case kpidINode: prop = (UInt32)item.Node; break; | 2112 | case kpidINode: prop = (UInt32)item.Node; break; |
2112 | case kpidStreamId: if (!isDir) prop = (UInt32)item.Node; break; | 2113 | case kpidStreamId: if (!isDir) prop = (UInt32)item.Node; break; |
@@ -2827,17 +2828,29 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) | |||
2827 | } | 2828 | } |
2828 | 2829 | ||
2829 | 2830 | ||
2830 | API_FUNC_static_IsArc IsArc_Ext(const Byte *p, size_t size) | 2831 | API_FUNC_IsArc IsArc_Ext_PhySize(const Byte *p, size_t size, UInt64 *phySize); |
2832 | API_FUNC_IsArc IsArc_Ext_PhySize(const Byte *p, size_t size, UInt64 *phySize) | ||
2831 | { | 2833 | { |
2834 | if (phySize) | ||
2835 | *phySize = 0; | ||
2832 | if (size < kHeaderSize) | 2836 | if (size < kHeaderSize) |
2833 | return k_IsArc_Res_NEED_MORE; | 2837 | return k_IsArc_Res_NEED_MORE; |
2834 | CHeader h; | 2838 | CHeader h; |
2835 | if (!h.Parse(p + kHeaderDataOffset)) | 2839 | if (!h.Parse(p + kHeaderDataOffset)) |
2836 | return k_IsArc_Res_NO; | 2840 | return k_IsArc_Res_NO; |
2841 | if (phySize) | ||
2842 | *phySize = h.GetPhySize(); | ||
2837 | return k_IsArc_Res_YES; | 2843 | return k_IsArc_Res_YES; |
2838 | } | 2844 | } |
2845 | |||
2846 | |||
2847 | API_FUNC_IsArc IsArc_Ext(const Byte *p, size_t size); | ||
2848 | API_FUNC_IsArc IsArc_Ext(const Byte *p, size_t size) | ||
2849 | { | ||
2850 | return IsArc_Ext_PhySize(p, size, NULL); | ||
2839 | } | 2851 | } |
2840 | 2852 | ||
2853 | |||
2841 | static const Byte k_Signature[] = { 0x53, 0xEF }; | 2854 | static const Byte k_Signature[] = { 0x53, 0xEF }; |
2842 | 2855 | ||
2843 | REGISTER_ARC_I( | 2856 | REGISTER_ARC_I( |
diff --git a/CPP/7zip/Archive/FatHandler.cpp b/CPP/7zip/Archive/FatHandler.cpp index 1cbc850..826b4fd 100644 --- a/CPP/7zip/Archive/FatHandler.cpp +++ b/CPP/7zip/Archive/FatHandler.cpp | |||
@@ -111,14 +111,14 @@ static int GetLog(UInt32 num) | |||
111 | 111 | ||
112 | static const UInt32 kHeaderSize = 512; | 112 | static const UInt32 kHeaderSize = 512; |
113 | 113 | ||
114 | API_FUNC_static_IsArc IsArc_Fat(const Byte *p, size_t size) | 114 | API_FUNC_IsArc IsArc_Fat(const Byte *p, size_t size); |
115 | API_FUNC_IsArc IsArc_Fat(const Byte *p, size_t size) | ||
115 | { | 116 | { |
116 | if (size < kHeaderSize) | 117 | if (size < kHeaderSize) |
117 | return k_IsArc_Res_NEED_MORE; | 118 | return k_IsArc_Res_NEED_MORE; |
118 | CHeader h; | 119 | CHeader h; |
119 | return h.Parse(p) ? k_IsArc_Res_YES : k_IsArc_Res_NO; | 120 | return h.Parse(p) ? k_IsArc_Res_YES : k_IsArc_Res_NO; |
120 | } | 121 | } |
121 | } | ||
122 | 122 | ||
123 | bool CHeader::Parse(const Byte *p) | 123 | bool CHeader::Parse(const Byte *p) |
124 | { | 124 | { |
@@ -846,17 +846,18 @@ static const CStatProp kArcProps[] = | |||
846 | IMP_IInArchive_Props | 846 | IMP_IInArchive_Props |
847 | IMP_IInArchive_ArcProps_WITH_NAME | 847 | IMP_IInArchive_ArcProps_WITH_NAME |
848 | 848 | ||
849 | |||
849 | static void FatTimeToProp(UInt32 dosTime, UInt32 ms10, NWindows::NCOM::CPropVariant &prop) | 850 | static void FatTimeToProp(UInt32 dosTime, UInt32 ms10, NWindows::NCOM::CPropVariant &prop) |
850 | { | 851 | { |
851 | FILETIME localFileTime, utc; | 852 | FILETIME localFileTime, utc; |
852 | if (NWindows::NTime::DosTimeToFileTime(dosTime, localFileTime)) | 853 | if (NWindows::NTime::DosTime_To_FileTime(dosTime, localFileTime)) |
853 | if (LocalFileTimeToFileTime(&localFileTime, &utc)) | 854 | if (LocalFileTimeToFileTime(&localFileTime, &utc)) |
854 | { | 855 | { |
855 | UInt64 t64 = (((UInt64)utc.dwHighDateTime) << 32) + utc.dwLowDateTime; | 856 | UInt64 t64 = (((UInt64)utc.dwHighDateTime) << 32) + utc.dwLowDateTime; |
856 | t64 += ms10 * 100000; | 857 | t64 += ms10 * 100000; |
857 | utc.dwLowDateTime = (DWORD)t64; | 858 | utc.dwLowDateTime = (DWORD)t64; |
858 | utc.dwHighDateTime = (DWORD)(t64 >> 32); | 859 | utc.dwHighDateTime = (DWORD)(t64 >> 32); |
859 | prop = utc; | 860 | prop.SetAsTimeFrom_FT_Prec(utc, k_PropVar_TimePrec_Base + 2); |
860 | } | 861 | } |
861 | } | 862 | } |
862 | 863 | ||
@@ -892,7 +893,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | |||
892 | case kpidPhySize: prop = PhySize; break; | 893 | case kpidPhySize: prop = PhySize; break; |
893 | case kpidFreeSpace: prop = (UInt64)NumFreeClusters << Header.ClusterSizeLog; break; | 894 | case kpidFreeSpace: prop = (UInt64)NumFreeClusters << Header.ClusterSizeLog; break; |
894 | case kpidHeadersSize: prop = GetHeadersSize(); break; | 895 | case kpidHeadersSize: prop = GetHeadersSize(); break; |
895 | case kpidMTime: if (VolItemDefined) FatTimeToProp(VolItem.MTime, 0, prop); break; | 896 | case kpidMTime: if (VolItemDefined) PropVariant_SetFrom_DosTime(prop, VolItem.MTime); break; |
896 | case kpidShortComment: | 897 | case kpidShortComment: |
897 | case kpidVolumeName: if (VolItemDefined) prop = VolItem.GetVolName(); break; | 898 | case kpidVolumeName: if (VolItemDefined) prop = VolItem.GetVolName(); break; |
898 | case kpidNumFats: if (Header.NumFats != 2) prop = Header.NumFats; break; | 899 | case kpidNumFats: if (Header.NumFats != 2) prop = Header.NumFats; break; |
@@ -920,9 +921,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
920 | case kpidPath: prop = GetItemPath(index); break; | 921 | case kpidPath: prop = GetItemPath(index); break; |
921 | case kpidShortName: prop = item.GetShortName(); break; | 922 | case kpidShortName: prop = item.GetShortName(); break; |
922 | case kpidIsDir: prop = item.IsDir(); break; | 923 | case kpidIsDir: prop = item.IsDir(); break; |
923 | case kpidMTime: FatTimeToProp(item.MTime, 0, prop); break; | 924 | case kpidMTime: PropVariant_SetFrom_DosTime(prop, item.MTime); break; |
924 | case kpidCTime: FatTimeToProp(item.CTime, item.CTime2, prop); break; | 925 | case kpidCTime: FatTimeToProp(item.CTime, item.CTime2, prop); break; |
925 | case kpidATime: FatTimeToProp(((UInt32)item.ADate << 16), 0, prop); break; | 926 | case kpidATime: PropVariant_SetFrom_DosTime(prop, ((UInt32)item.ADate << 16)); break; |
926 | case kpidAttrib: prop = (UInt32)item.Attrib; break; | 927 | case kpidAttrib: prop = (UInt32)item.Attrib; break; |
927 | case kpidSize: if (!item.IsDir()) prop = item.Size; break; | 928 | case kpidSize: if (!item.IsDir()) prop = item.Size; break; |
928 | case kpidPackSize: if (!item.IsDir()) prop = Header.GetFilePackSize(item.Size); break; | 929 | case kpidPackSize: if (!item.IsDir()) prop = Header.GetFilePackSize(item.Size); break; |
diff --git a/CPP/7zip/Archive/GptHandler.cpp b/CPP/7zip/Archive/GptHandler.cpp index 2b3a673..0d2caa3 100644 --- a/CPP/7zip/Archive/GptHandler.cpp +++ b/CPP/7zip/Archive/GptHandler.cpp | |||
@@ -23,6 +23,11 @@ | |||
23 | using namespace NWindows; | 23 | using namespace NWindows; |
24 | 24 | ||
25 | namespace NArchive { | 25 | namespace NArchive { |
26 | |||
27 | namespace NFat { | ||
28 | API_FUNC_IsArc IsArc_Fat(const Byte *p, size_t size); | ||
29 | } | ||
30 | |||
26 | namespace NGpt { | 31 | namespace NGpt { |
27 | 32 | ||
28 | #define SIGNATURE { 'E', 'F', 'I', ' ', 'P', 'A', 'R', 'T', 0, 0, 1, 0 } | 33 | #define SIGNATURE { 'E', 'F', 'I', ' ', 'P', 'A', 'R', 'T', 0, 0, 1, 0 } |
@@ -51,6 +56,7 @@ struct CPartition | |||
51 | UInt64 FirstLba; | 56 | UInt64 FirstLba; |
52 | UInt64 LastLba; | 57 | UInt64 LastLba; |
53 | UInt64 Flags; | 58 | UInt64 Flags; |
59 | const char *Ext; // detected later | ||
54 | Byte Name[kNameLen * 2]; | 60 | Byte Name[kNameLen * 2]; |
55 | 61 | ||
56 | bool IsUnused() const | 62 | bool IsUnused() const |
@@ -73,6 +79,7 @@ struct CPartition | |||
73 | LastLba = Get64(p + 40); | 79 | LastLba = Get64(p + 40); |
74 | Flags = Get64(p + 48); | 80 | Flags = Get64(p + 48); |
75 | memcpy(Name, p + 56, kNameLen * 2); | 81 | memcpy(Name, p + 56, kNameLen * 2); |
82 | Ext = NULL; | ||
76 | } | 83 | } |
77 | }; | 84 | }; |
78 | 85 | ||
@@ -252,6 +259,28 @@ HRESULT CHandler::Open2(IInStream *stream) | |||
252 | return S_OK; | 259 | return S_OK; |
253 | } | 260 | } |
254 | 261 | ||
262 | |||
263 | |||
264 | static const unsigned k_Ntfs_Fat_HeaderSize = 512; | ||
265 | |||
266 | static const Byte k_NtfsSignature[] = { 'N', 'T', 'F', 'S', ' ', ' ', ' ', ' ', 0 }; | ||
267 | |||
268 | static bool IsNtfs(const Byte *p) | ||
269 | { | ||
270 | if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA) | ||
271 | return false; | ||
272 | if (memcmp(p + 3, k_NtfsSignature, ARRAY_SIZE(k_NtfsSignature)) != 0) | ||
273 | return false; | ||
274 | switch (p[0]) | ||
275 | { | ||
276 | case 0xE9: /* codeOffset = 3 + (Int16)Get16(p + 1); */ break; | ||
277 | case 0xEB: if (p[2] != 0x90) return false; /* codeOffset = 2 + (int)(signed char)p[1]; */ break; | ||
278 | default: return false; | ||
279 | } | ||
280 | return true; | ||
281 | } | ||
282 | |||
283 | |||
255 | STDMETHODIMP CHandler::Open(IInStream *stream, | 284 | STDMETHODIMP CHandler::Open(IInStream *stream, |
256 | const UInt64 * /* maxCheckStartPosition */, | 285 | const UInt64 * /* maxCheckStartPosition */, |
257 | IArchiveOpenCallback * /* openArchiveCallback */) | 286 | IArchiveOpenCallback * /* openArchiveCallback */) |
@@ -260,6 +289,42 @@ STDMETHODIMP CHandler::Open(IInStream *stream, | |||
260 | Close(); | 289 | Close(); |
261 | RINOK(Open2(stream)); | 290 | RINOK(Open2(stream)); |
262 | _stream = stream; | 291 | _stream = stream; |
292 | |||
293 | FOR_VECTOR (fileIndex, _items) | ||
294 | { | ||
295 | CPartition &item = _items[fileIndex]; | ||
296 | const int typeIndex = FindPartType(item.Type); | ||
297 | if (typeIndex < 0) | ||
298 | continue; | ||
299 | const CPartType &t = kPartTypes[(unsigned)typeIndex]; | ||
300 | if (t.Ext) | ||
301 | { | ||
302 | item.Ext = t.Ext; | ||
303 | continue; | ||
304 | } | ||
305 | if (t.Type && IsString1PrefixedByString2_NoCase_Ascii(t.Type, "Windows")) | ||
306 | { | ||
307 | CMyComPtr<ISequentialInStream> inStream; | ||
308 | if (GetStream(fileIndex, &inStream) == S_OK && inStream) | ||
309 | { | ||
310 | Byte temp[k_Ntfs_Fat_HeaderSize]; | ||
311 | if (ReadStream_FAIL(inStream, temp, k_Ntfs_Fat_HeaderSize) == S_OK) | ||
312 | { | ||
313 | if (IsNtfs(temp)) | ||
314 | { | ||
315 | item.Ext = "ntfs"; | ||
316 | continue; | ||
317 | } | ||
318 | if (NFat::IsArc_Fat(temp, k_Ntfs_Fat_HeaderSize) == k_IsArc_Res_YES) | ||
319 | { | ||
320 | item.Ext = "fat"; | ||
321 | continue; | ||
322 | } | ||
323 | } | ||
324 | } | ||
325 | } | ||
326 | } | ||
327 | |||
263 | return S_OK; | 328 | return S_OK; |
264 | COM_TRY_END | 329 | COM_TRY_END |
265 | } | 330 | } |
@@ -355,13 +420,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
355 | } | 420 | } |
356 | { | 421 | { |
357 | s += '.'; | 422 | s += '.'; |
358 | const char *ext = NULL; | 423 | s += (item.Ext ? item.Ext : "img"); |
359 | int typeIndex = FindPartType(item.Type); | ||
360 | if (typeIndex >= 0) | ||
361 | ext = kPartTypes[(unsigned)typeIndex].Ext; | ||
362 | if (!ext) | ||
363 | ext = "img"; | ||
364 | s += ext; | ||
365 | } | 424 | } |
366 | prop = s; | 425 | prop = s; |
367 | break; | 426 | break; |
@@ -375,7 +434,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
375 | { | 434 | { |
376 | char s[48]; | 435 | char s[48]; |
377 | const char *res; | 436 | const char *res; |
378 | int typeIndex = FindPartType(item.Type); | 437 | const int typeIndex = FindPartType(item.Type); |
379 | if (typeIndex >= 0 && kPartTypes[(unsigned)typeIndex].Type) | 438 | if (typeIndex >= 0 && kPartTypes[(unsigned)typeIndex].Type) |
380 | res = kPartTypes[(unsigned)typeIndex].Type; | 439 | res = kPartTypes[(unsigned)typeIndex].Type; |
381 | else | 440 | else |
diff --git a/CPP/7zip/Archive/GzHandler.cpp b/CPP/7zip/Archive/GzHandler.cpp index 0054840..35e642e 100644 --- a/CPP/7zip/Archive/GzHandler.cpp +++ b/CPP/7zip/Archive/GzHandler.cpp | |||
@@ -475,6 +475,7 @@ class CHandler: | |||
475 | NDecoder::CCOMCoder *_decoderSpec; | 475 | NDecoder::CCOMCoder *_decoderSpec; |
476 | 476 | ||
477 | CSingleMethodProps _props; | 477 | CSingleMethodProps _props; |
478 | CHandlerTimeOptions _timeOptions; | ||
478 | 479 | ||
479 | public: | 480 | public: |
480 | MY_UNKNOWN_IMP4( | 481 | MY_UNKNOWN_IMP4( |
@@ -487,8 +488,15 @@ public: | |||
487 | STDMETHOD(OpenSeq)(ISequentialInStream *stream); | 488 | STDMETHOD(OpenSeq)(ISequentialInStream *stream); |
488 | STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps); | 489 | STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps); |
489 | 490 | ||
490 | CHandler() | 491 | CHandler(): |
492 | _isArc(false), | ||
493 | _decoderSpec(NULL) | ||
494 | {} | ||
495 | |||
496 | void CreateDecoder() | ||
491 | { | 497 | { |
498 | if (_decoder) | ||
499 | return; | ||
492 | _decoderSpec = new NDecoder::CCOMCoder; | 500 | _decoderSpec = new NDecoder::CCOMCoder; |
493 | _decoder = _decoderSpec; | 501 | _decoder = _decoderSpec; |
494 | } | 502 | } |
@@ -528,7 +536,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | |||
528 | case kpidErrorFlags: | 536 | case kpidErrorFlags: |
529 | { | 537 | { |
530 | UInt32 v = 0; | 538 | UInt32 v = 0; |
531 | if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;; | 539 | if (!_isArc) v |= kpv_ErrorFlags_IsNotArc; |
532 | if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd; | 540 | if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd; |
533 | if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; | 541 | if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; |
534 | prop = v; | 542 | prop = v; |
@@ -567,12 +575,13 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN | |||
567 | break; | 575 | break; |
568 | // case kpidComment: if (_item.CommentIsPresent()) prop = MultiByteToUnicodeString(_item.Comment, CP_ACP); break; | 576 | // case kpidComment: if (_item.CommentIsPresent()) prop = MultiByteToUnicodeString(_item.Comment, CP_ACP); break; |
569 | case kpidMTime: | 577 | case kpidMTime: |
578 | // gzip specification: MTIME = 0 means no time stamp is available. | ||
570 | if (_item.Time != 0) | 579 | if (_item.Time != 0) |
571 | { | 580 | PropVariant_SetFrom_UnixTime(prop, _item.Time); |
572 | FILETIME utc; | 581 | break; |
573 | NTime::UnixTimeToFileTime(_item.Time, utc); | 582 | case kpidTimeType: |
574 | prop = utc; | 583 | if (_item.Time != 0) |
575 | } | 584 | prop = (UInt32)NFileTimeType::kUnix; |
576 | break; | 585 | break; |
577 | case kpidSize: | 586 | case kpidSize: |
578 | { | 587 | { |
@@ -644,6 +653,7 @@ STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) | |||
644 | try | 653 | try |
645 | { | 654 | { |
646 | Close(); | 655 | Close(); |
656 | CreateDecoder(); | ||
647 | _decoderSpec->SetInStream(stream); | 657 | _decoderSpec->SetInStream(stream); |
648 | _decoderSpec->InitInStream(true); | 658 | _decoderSpec->InitInStream(true); |
649 | RINOK(_item.ReadHeader(_decoderSpec)); | 659 | RINOK(_item.ReadHeader(_decoderSpec)); |
@@ -672,7 +682,8 @@ STDMETHODIMP CHandler::Close() | |||
672 | _headerSize = 0; | 682 | _headerSize = 0; |
673 | 683 | ||
674 | _stream.Release(); | 684 | _stream.Release(); |
675 | _decoderSpec->ReleaseInStream(); | 685 | if (_decoder) |
686 | _decoderSpec->ReleaseInStream(); | ||
676 | return S_OK; | 687 | return S_OK; |
677 | } | 688 | } |
678 | 689 | ||
@@ -699,6 +710,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
699 | 710 | ||
700 | extractCallback->PrepareOperation(askMode); | 711 | extractCallback->PrepareOperation(askMode); |
701 | 712 | ||
713 | CreateDecoder(); | ||
714 | |||
702 | COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; | 715 | COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; |
703 | CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); | 716 | CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); |
704 | outStreamSpec->SetStream(realOutStream); | 717 | outStreamSpec->SetStream(realOutStream); |
@@ -873,21 +886,99 @@ static const Byte kHostOS = | |||
873 | NHostOS::kUnix; | 886 | NHostOS::kUnix; |
874 | #endif | 887 | #endif |
875 | 888 | ||
889 | |||
890 | /* | ||
891 | static HRESULT ReportItemProp(IArchiveUpdateCallbackArcProp *reportArcProp, PROPID propID, const PROPVARIANT *value) | ||
892 | { | ||
893 | return reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, 0, propID, value); | ||
894 | } | ||
895 | |||
896 | static HRESULT ReportArcProp(IArchiveUpdateCallbackArcProp *reportArcProp, PROPID propID, const PROPVARIANT *value) | ||
897 | { | ||
898 | return reportArcProp->ReportProp(NEventIndexType::kArcProp, 0, propID, value); | ||
899 | } | ||
900 | |||
901 | static HRESULT ReportArcProps(IArchiveUpdateCallbackArcProp *reportArcProp, | ||
902 | const CItem &item, | ||
903 | bool needTime, | ||
904 | bool needCrc, | ||
905 | const UInt64 *unpackSize) | ||
906 | { | ||
907 | NCOM::CPropVariant timeProp; | ||
908 | NCOM::CPropVariant sizeProp; | ||
909 | if (needTime) | ||
910 | { | ||
911 | FILETIME ft; | ||
912 | NTime::UnixTimeToFileTime(item.Time, ft); | ||
913 | timeProp.SetAsTimeFrom_FT_Prec(ft, k_PropVar_TimePrec_Unix); | ||
914 | } | ||
915 | if (unpackSize) | ||
916 | { | ||
917 | sizeProp = *unpackSize; | ||
918 | RINOK(ReportItemProp(reportArcProp, kpidSize, &sizeProp)); | ||
919 | } | ||
920 | if (needCrc) | ||
921 | { | ||
922 | NCOM::CPropVariant prop; | ||
923 | prop = item.Crc; | ||
924 | RINOK(ReportItemProp(reportArcProp, kpidCRC, &prop)); | ||
925 | } | ||
926 | { | ||
927 | RINOK(ReportItemProp(reportArcProp, kpidMTime, &timeProp)); | ||
928 | } | ||
929 | |||
930 | RINOK(reportArcProp->ReportFinished(NEventIndexType::kOutArcIndex, 0, NArchive::NUpdate::NOperationResult::kOK)); | ||
931 | |||
932 | if (unpackSize) | ||
933 | { | ||
934 | RINOK(ReportArcProp(reportArcProp, kpidSize, &sizeProp)); | ||
935 | } | ||
936 | { | ||
937 | RINOK(ReportArcProp(reportArcProp, kpidComboMTime, &timeProp)); | ||
938 | } | ||
939 | return S_OK; | ||
940 | } | ||
941 | */ | ||
942 | |||
876 | static HRESULT UpdateArchive( | 943 | static HRESULT UpdateArchive( |
877 | ISequentialOutStream *outStream, | 944 | ISequentialOutStream *outStream, |
878 | UInt64 unpackSize, | 945 | UInt64 unpackSize, |
879 | CItem &item, | 946 | CItem &item, |
880 | const CSingleMethodProps &props, | 947 | const CSingleMethodProps &props, |
881 | IArchiveUpdateCallback *updateCallback) | 948 | const CHandlerTimeOptions &timeOptions, |
949 | IArchiveUpdateCallback *updateCallback | ||
950 | // , IArchiveUpdateCallbackArcProp *reportArcProp | ||
951 | ) | ||
882 | { | 952 | { |
883 | UInt64 complexity = 0; | 953 | UInt64 unpackSizeReal; |
884 | RINOK(updateCallback->SetTotal(unpackSize)); | 954 | { |
885 | RINOK(updateCallback->SetCompleted(&complexity)); | ||
886 | |||
887 | CMyComPtr<ISequentialInStream> fileInStream; | 955 | CMyComPtr<ISequentialInStream> fileInStream; |
888 | 956 | ||
889 | RINOK(updateCallback->GetStream(0, &fileInStream)); | 957 | RINOK(updateCallback->GetStream(0, &fileInStream)); |
890 | 958 | ||
959 | if (!fileInStream) | ||
960 | return S_FALSE; | ||
961 | |||
962 | { | ||
963 | CMyComPtr<IStreamGetProps> getProps; | ||
964 | fileInStream->QueryInterface(IID_IStreamGetProps, (void **)&getProps); | ||
965 | if (getProps) | ||
966 | { | ||
967 | FILETIME mTime; | ||
968 | UInt64 size; | ||
969 | if (getProps->GetProps(&size, NULL, NULL, &mTime, NULL) == S_OK) | ||
970 | { | ||
971 | unpackSize = size; | ||
972 | if (timeOptions.Write_MTime.Val) | ||
973 | NTime::FileTime_To_UnixTime(mTime, item.Time); | ||
974 | } | ||
975 | } | ||
976 | } | ||
977 | |||
978 | UInt64 complexity = 0; | ||
979 | RINOK(updateCallback->SetTotal(unpackSize)); | ||
980 | RINOK(updateCallback->SetCompleted(&complexity)); | ||
981 | |||
891 | CSequentialInStreamWithCRC *inStreamSpec = new CSequentialInStreamWithCRC; | 982 | CSequentialInStreamWithCRC *inStreamSpec = new CSequentialInStreamWithCRC; |
892 | CMyComPtr<ISequentialInStream> crcStream(inStreamSpec); | 983 | CMyComPtr<ISequentialInStream> crcStream(inStreamSpec); |
893 | inStreamSpec->SetStream(fileInStream); | 984 | inStreamSpec->SetStream(fileInStream); |
@@ -911,14 +1002,50 @@ static HRESULT UpdateArchive( | |||
911 | RINOK(deflateEncoder->Code(crcStream, outStream, NULL, NULL, progress)); | 1002 | RINOK(deflateEncoder->Code(crcStream, outStream, NULL, NULL, progress)); |
912 | 1003 | ||
913 | item.Crc = inStreamSpec->GetCRC(); | 1004 | item.Crc = inStreamSpec->GetCRC(); |
914 | item.Size32 = (UInt32)inStreamSpec->GetSize(); | 1005 | unpackSizeReal = inStreamSpec->GetSize(); |
1006 | item.Size32 = (UInt32)unpackSizeReal; | ||
915 | RINOK(item.WriteFooter(outStream)); | 1007 | RINOK(item.WriteFooter(outStream)); |
1008 | } | ||
1009 | /* | ||
1010 | if (reportArcProp) | ||
1011 | { | ||
1012 | RINOK(ReportArcProps(reportArcProp, | ||
1013 | item, | ||
1014 | props._Write_MTime, // item.Time != 0, | ||
1015 | true, // writeCrc | ||
1016 | &unpackSizeReal)); | ||
1017 | } | ||
1018 | */ | ||
916 | return updateCallback->SetOperationResult(NUpdate::NOperationResult::kOK); | 1019 | return updateCallback->SetOperationResult(NUpdate::NOperationResult::kOK); |
917 | } | 1020 | } |
918 | 1021 | ||
1022 | |||
919 | STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) | 1023 | STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) |
920 | { | 1024 | { |
921 | *timeType = NFileTimeType::kUnix; | 1025 | /* |
1026 | if (_item.Time != 0) | ||
1027 | { | ||
1028 | we set NFileTimeType::kUnix in precision, | ||
1029 | and we return NFileTimeType::kUnix in kpidTimeType | ||
1030 | so GetFileTimeType() value is not used in any version of 7-zip. | ||
1031 | } | ||
1032 | else // (_item.Time == 0) | ||
1033 | { | ||
1034 | kpidMTime and kpidTimeType are not defined | ||
1035 | before 22.00 : GetFileTimeType() value is used in GetUpdatePairInfoList(); | ||
1036 | 22.00 : GetFileTimeType() value is not used | ||
1037 | } | ||
1038 | */ | ||
1039 | |||
1040 | UInt32 t; | ||
1041 | t = NFileTimeType::kUnix; | ||
1042 | if (_isArc ? (_item.Time == 0) : !_timeOptions.Write_MTime.Val) | ||
1043 | { | ||
1044 | t = GET_FileTimeType_NotDefined_for_GetFileTimeType; | ||
1045 | // t = k_PropVar_TimePrec_1ns; // failed in 7-Zip 21 | ||
1046 | // t = (UInt32)(Int32)NFileTimeType::kNotDefined; // failed in 7-Zip 21 | ||
1047 | } | ||
1048 | *timeType = t; | ||
922 | return S_OK; | 1049 | return S_OK; |
923 | } | 1050 | } |
924 | 1051 | ||
@@ -936,6 +1063,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
936 | return E_FAIL; | 1063 | return E_FAIL; |
937 | RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive)); | 1064 | RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive)); |
938 | 1065 | ||
1066 | /* | ||
1067 | CMyComPtr<IArchiveUpdateCallbackArcProp> reportArcProp; | ||
1068 | updateCallback->QueryInterface(IID_IArchiveUpdateCallbackArcProp, (void **)&reportArcProp); | ||
1069 | */ | ||
1070 | |||
939 | CItem newItem; | 1071 | CItem newItem; |
940 | 1072 | ||
941 | if (!IntToBool(newProps)) | 1073 | if (!IntToBool(newProps)) |
@@ -945,11 +1077,12 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
945 | else | 1077 | else |
946 | { | 1078 | { |
947 | newItem.HostOS = kHostOS; | 1079 | newItem.HostOS = kHostOS; |
1080 | if (_timeOptions.Write_MTime.Val) | ||
948 | { | 1081 | { |
949 | NCOM::CPropVariant prop; | 1082 | NCOM::CPropVariant prop; |
950 | RINOK(updateCallback->GetProperty(0, kpidMTime, &prop)); | 1083 | RINOK(updateCallback->GetProperty(0, kpidMTime, &prop)); |
951 | if (prop.vt == VT_FILETIME) | 1084 | if (prop.vt == VT_FILETIME) |
952 | NTime::FileTimeToUnixTime(prop.filetime, newItem.Time); | 1085 | NTime::FileTime_To_UnixTime(prop.filetime, newItem.Time); |
953 | else if (prop.vt == VT_EMPTY) | 1086 | else if (prop.vt == VT_EMPTY) |
954 | newItem.Time = 0; | 1087 | newItem.Time = 0; |
955 | else | 1088 | else |
@@ -990,7 +1123,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
990 | return E_INVALIDARG; | 1123 | return E_INVALIDARG; |
991 | size = prop.uhVal.QuadPart; | 1124 | size = prop.uhVal.QuadPart; |
992 | } | 1125 | } |
993 | return UpdateArchive(outStream, size, newItem, _props, updateCallback); | 1126 | return UpdateArchive(outStream, size, newItem, _props, _timeOptions, updateCallback); |
994 | } | 1127 | } |
995 | 1128 | ||
996 | if (indexInArchive != 0) | 1129 | if (indexInArchive != 0) |
@@ -1022,6 +1155,14 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
1022 | } | 1155 | } |
1023 | RINOK(_stream->Seek((Int64)offset, STREAM_SEEK_SET, NULL)); | 1156 | RINOK(_stream->Seek((Int64)offset, STREAM_SEEK_SET, NULL)); |
1024 | 1157 | ||
1158 | /* | ||
1159 | if (reportArcProp) | ||
1160 | ReportArcProps(reportArcProp, newItem, | ||
1161 | _props._Write_MTime, | ||
1162 | false, // writeCrc | ||
1163 | NULL); // unpacksize | ||
1164 | */ | ||
1165 | |||
1025 | return NCompress::CopyStream(_stream, outStream, progress); | 1166 | return NCompress::CopyStream(_stream, outStream, progress); |
1026 | 1167 | ||
1027 | COM_TRY_END | 1168 | COM_TRY_END |
@@ -1029,16 +1170,48 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
1029 | 1170 | ||
1030 | STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) | 1171 | STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) |
1031 | { | 1172 | { |
1032 | return _props.SetProperties(names, values, numProps); | 1173 | _timeOptions.Init(); |
1174 | _props.Init(); | ||
1175 | |||
1176 | for (UInt32 i = 0; i < numProps; i++) | ||
1177 | { | ||
1178 | UString name = names[i]; | ||
1179 | name.MakeLower_Ascii(); | ||
1180 | if (name.IsEmpty()) | ||
1181 | return E_INVALIDARG; | ||
1182 | const PROPVARIANT &value = values[i]; | ||
1183 | { | ||
1184 | bool processed = false; | ||
1185 | RINOK(_timeOptions.Parse(name, value, processed)); | ||
1186 | if (processed) | ||
1187 | { | ||
1188 | if (_timeOptions.Write_CTime.Val || | ||
1189 | _timeOptions.Write_ATime.Val) | ||
1190 | return E_INVALIDARG; | ||
1191 | if ( _timeOptions.Prec != (UInt32)(Int32)-1 | ||
1192 | && _timeOptions.Prec != k_PropVar_TimePrec_0 | ||
1193 | && _timeOptions.Prec != k_PropVar_TimePrec_Unix | ||
1194 | && _timeOptions.Prec != k_PropVar_TimePrec_HighPrec | ||
1195 | && _timeOptions.Prec != k_PropVar_TimePrec_Base) | ||
1196 | return E_INVALIDARG; | ||
1197 | continue; | ||
1198 | } | ||
1199 | } | ||
1200 | RINOK(_props.SetProperty(name, value)); | ||
1201 | } | ||
1202 | return S_OK; | ||
1033 | } | 1203 | } |
1034 | 1204 | ||
1035 | static const Byte k_Signature[] = { kSignature_0, kSignature_1, kSignature_2 }; | 1205 | static const Byte k_Signature[] = { kSignature_0, kSignature_1, kSignature_2 }; |
1036 | 1206 | ||
1037 | REGISTER_ARC_IO( | 1207 | REGISTER_ARC_IO( |
1038 | "gzip", "gz gzip tgz tpz apk", "* * .tar .tar .tar", 0xEF, | 1208 | "gzip", "gz gzip tgz tpz apk", "* * .tar .tar .tar", 0xEF, |
1039 | k_Signature, | 1209 | k_Signature, 0, |
1040 | 0, | 1210 | NArcInfoFlags::kKeepName |
1041 | NArcInfoFlags::kKeepName, | 1211 | | NArcInfoFlags::kMTime |
1042 | IsArc_Gz) | 1212 | | NArcInfoFlags::kMTime_Default |
1213 | , TIME_PREC_TO_ARC_FLAGS_MASK (NFileTimeType::kUnix) | ||
1214 | | TIME_PREC_TO_ARC_FLAGS_TIME_DEFAULT (NFileTimeType::kUnix) | ||
1215 | , IsArc_Gz) | ||
1043 | 1216 | ||
1044 | }} | 1217 | }} |
diff --git a/CPP/7zip/Archive/HandlerCont.cpp b/CPP/7zip/Archive/HandlerCont.cpp index 6f196de..3cbfdac 100644 --- a/CPP/7zip/Archive/HandlerCont.cpp +++ b/CPP/7zip/Archive/HandlerCont.cpp | |||
@@ -14,6 +14,10 @@ | |||
14 | 14 | ||
15 | namespace NArchive { | 15 | namespace NArchive { |
16 | 16 | ||
17 | namespace NExt { | ||
18 | API_FUNC_IsArc IsArc_Ext(const Byte *p, size_t size); | ||
19 | } | ||
20 | |||
17 | STDMETHODIMP CHandlerCont::Extract(const UInt32 *indices, UInt32 numItems, | 21 | STDMETHODIMP CHandlerCont::Extract(const UInt32 *indices, UInt32 numItems, |
18 | Int32 testMode, IArchiveExtractCallback *extractCallback) | 22 | Int32 testMode, IArchiveExtractCallback *extractCallback) |
19 | { | 23 | { |
@@ -132,11 +136,12 @@ STDMETHODIMP CHandlerImg::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosit | |||
132 | } | 136 | } |
133 | 137 | ||
134 | static const Byte k_GDP_Signature[] = { 'E', 'F', 'I', ' ', 'P', 'A', 'R', 'T' }; | 138 | static const Byte k_GDP_Signature[] = { 'E', 'F', 'I', ' ', 'P', 'A', 'R', 'T' }; |
135 | 139 | // static const Byte k_Ext_Signature[] = { 0x53, 0xEF }; | |
140 | // static const unsigned k_Ext_Signature_offset = 0x438; | ||
136 | 141 | ||
137 | static const char *GetImgExt(ISequentialInStream *stream) | 142 | static const char *GetImgExt(ISequentialInStream *stream) |
138 | { | 143 | { |
139 | const size_t kHeaderSize = 1 << 10; | 144 | const size_t kHeaderSize = 1 << 11; |
140 | Byte buf[kHeaderSize]; | 145 | Byte buf[kHeaderSize]; |
141 | if (ReadStream_FAIL(stream, buf, kHeaderSize) == S_OK) | 146 | if (ReadStream_FAIL(stream, buf, kHeaderSize) == S_OK) |
142 | { | 147 | { |
@@ -146,6 +151,8 @@ static const char *GetImgExt(ISequentialInStream *stream) | |||
146 | return "gpt"; | 151 | return "gpt"; |
147 | return "mbr"; | 152 | return "mbr"; |
148 | } | 153 | } |
154 | if (NExt::IsArc_Ext(buf, kHeaderSize) == k_IsArc_Res_YES) | ||
155 | return "ext"; | ||
149 | } | 156 | } |
150 | return NULL; | 157 | return NULL; |
151 | } | 158 | } |
@@ -208,6 +215,33 @@ STDMETHODIMP CHandlerImg::GetNumberOfItems(UInt32 *numItems) | |||
208 | return S_OK; | 215 | return S_OK; |
209 | } | 216 | } |
210 | 217 | ||
218 | |||
219 | class CHandlerImgProgress: | ||
220 | public ICompressProgressInfo, | ||
221 | public CMyUnknownImp | ||
222 | { | ||
223 | public: | ||
224 | CHandlerImg &Handler; | ||
225 | CMyComPtr<ICompressProgressInfo> _ratioProgress; | ||
226 | |||
227 | CHandlerImgProgress(CHandlerImg &handler) : Handler(handler) {} | ||
228 | |||
229 | // MY_UNKNOWN_IMP1(ICompressProgressInfo) | ||
230 | MY_UNKNOWN_IMP | ||
231 | |||
232 | STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); | ||
233 | }; | ||
234 | |||
235 | |||
236 | STDMETHODIMP CHandlerImgProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) | ||
237 | { | ||
238 | UInt64 inSize2; | ||
239 | if (Handler.Get_PackSizeProcessed(inSize2)) | ||
240 | inSize = &inSize2; | ||
241 | return _ratioProgress->SetRatioInfo(inSize, outSize); | ||
242 | } | ||
243 | |||
244 | |||
211 | STDMETHODIMP CHandlerImg::Extract(const UInt32 *indices, UInt32 numItems, | 245 | STDMETHODIMP CHandlerImg::Extract(const UInt32 *indices, UInt32 numItems, |
212 | Int32 testMode, IArchiveExtractCallback *extractCallback) | 246 | Int32 testMode, IArchiveExtractCallback *extractCallback) |
213 | { | 247 | { |
@@ -227,10 +261,6 @@ STDMETHODIMP CHandlerImg::Extract(const UInt32 *indices, UInt32 numItems, | |||
227 | return S_OK; | 261 | return S_OK; |
228 | RINOK(extractCallback->PrepareOperation(askMode)); | 262 | RINOK(extractCallback->PrepareOperation(askMode)); |
229 | 263 | ||
230 | CLocalProgress *lps = new CLocalProgress; | ||
231 | CMyComPtr<ICompressProgressInfo> progress = lps; | ||
232 | lps->Init(extractCallback, false); | ||
233 | |||
234 | int opRes = NExtract::NOperationResult::kDataError; | 264 | int opRes = NExtract::NOperationResult::kDataError; |
235 | 265 | ||
236 | ClearStreamVars(); | 266 | ClearStreamVars(); |
@@ -242,6 +272,19 @@ STDMETHODIMP CHandlerImg::Extract(const UInt32 *indices, UInt32 numItems, | |||
242 | 272 | ||
243 | if (hres == S_OK && inStream) | 273 | if (hres == S_OK && inStream) |
244 | { | 274 | { |
275 | CLocalProgress *lps = new CLocalProgress; | ||
276 | CMyComPtr<ICompressProgressInfo> progress = lps; | ||
277 | lps->Init(extractCallback, false); | ||
278 | |||
279 | if (Init_PackSizeProcessed()) | ||
280 | { | ||
281 | CHandlerImgProgress *imgProgressSpec = new CHandlerImgProgress(*this); | ||
282 | CMyComPtr<ICompressProgressInfo> imgProgress = imgProgressSpec; | ||
283 | imgProgressSpec->_ratioProgress = progress; | ||
284 | progress.Release(); | ||
285 | progress = imgProgress; | ||
286 | } | ||
287 | |||
245 | NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); | 288 | NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); |
246 | CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; | 289 | CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; |
247 | 290 | ||
diff --git a/CPP/7zip/Archive/HandlerCont.h b/CPP/7zip/Archive/HandlerCont.h index 0b92d19..3c64592 100644 --- a/CPP/7zip/Archive/HandlerCont.h +++ b/CPP/7zip/Archive/HandlerCont.h | |||
@@ -94,7 +94,19 @@ protected: | |||
94 | 94 | ||
95 | virtual HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback) = 0; | 95 | virtual HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback) = 0; |
96 | virtual void CloseAtError(); | 96 | virtual void CloseAtError(); |
97 | |||
98 | // returns (true), if Get_PackSizeProcessed() is required in Extract() | ||
99 | virtual bool Init_PackSizeProcessed() | ||
100 | { | ||
101 | return false; | ||
102 | } | ||
97 | public: | 103 | public: |
104 | virtual bool Get_PackSizeProcessed(UInt64 &size) | ||
105 | { | ||
106 | size = 0; | ||
107 | return false; | ||
108 | } | ||
109 | |||
98 | MY_UNKNOWN_IMP3(IInArchive, IInArchiveGetStream, IInStream) | 110 | MY_UNKNOWN_IMP3(IInArchive, IInArchiveGetStream, IInStream) |
99 | INTERFACE_IInArchive_Img(PURE) | 111 | INTERFACE_IInArchive_Img(PURE) |
100 | 112 | ||
diff --git a/CPP/7zip/Archive/HfsHandler.cpp b/CPP/7zip/Archive/HfsHandler.cpp index b70a291..f0a85f1 100644 --- a/CPP/7zip/Archive/HfsHandler.cpp +++ b/CPP/7zip/Archive/HfsHandler.cpp | |||
@@ -240,7 +240,7 @@ struct CItem | |||
240 | UInt32 ID; | 240 | UInt32 ID; |
241 | UInt32 CTime; | 241 | UInt32 CTime; |
242 | UInt32 MTime; | 242 | UInt32 MTime; |
243 | // UInt32 AttrMTime; | 243 | UInt32 AttrMTime; |
244 | UInt32 ATime; | 244 | UInt32 ATime; |
245 | // UInt32 BackupDate; | 245 | // UInt32 BackupDate; |
246 | 246 | ||
@@ -1000,7 +1000,7 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents | |||
1000 | 1000 | ||
1001 | item.CTime = Get32(r + 0xC); | 1001 | item.CTime = Get32(r + 0xC); |
1002 | item.MTime = Get32(r + 0x10); | 1002 | item.MTime = Get32(r + 0x10); |
1003 | // item.AttrMTime = Get32(r + 0x14); | 1003 | item.AttrMTime = Get32(r + 0x14); |
1004 | item.ATime = Get32(r + 0x18); | 1004 | item.ATime = Get32(r + 0x18); |
1005 | // item.BackupDate = Get32(r + 0x1C); | 1005 | // item.BackupDate = Get32(r + 0x1C); |
1006 | 1006 | ||
@@ -1404,6 +1404,7 @@ static const Byte kProps[] = | |||
1404 | kpidCTime, | 1404 | kpidCTime, |
1405 | kpidMTime, | 1405 | kpidMTime, |
1406 | kpidATime, | 1406 | kpidATime, |
1407 | kpidChangeTime, | ||
1407 | kpidPosixAttrib | 1408 | kpidPosixAttrib |
1408 | }; | 1409 | }; |
1409 | 1410 | ||
@@ -1421,9 +1422,11 @@ IMP_IInArchive_ArcProps | |||
1421 | 1422 | ||
1422 | static void HfsTimeToProp(UInt32 hfsTime, NWindows::NCOM::CPropVariant &prop) | 1423 | static void HfsTimeToProp(UInt32 hfsTime, NWindows::NCOM::CPropVariant &prop) |
1423 | { | 1424 | { |
1425 | if (hfsTime == 0) | ||
1426 | return; | ||
1424 | FILETIME ft; | 1427 | FILETIME ft; |
1425 | HfsTimeToFileTime(hfsTime, ft); | 1428 | HfsTimeToFileTime(hfsTime, ft); |
1426 | prop = ft; | 1429 | prop.SetAsTimeFrom_FT_Prec(ft, k_PropVar_TimePrec_Base); |
1427 | } | 1430 | } |
1428 | 1431 | ||
1429 | STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | 1432 | STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) |
@@ -1447,10 +1450,13 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | |||
1447 | case kpidMTime: HfsTimeToProp(Header.MTime, prop); break; | 1450 | case kpidMTime: HfsTimeToProp(Header.MTime, prop); break; |
1448 | case kpidCTime: | 1451 | case kpidCTime: |
1449 | { | 1452 | { |
1450 | FILETIME localFt, ft; | 1453 | if (Header.CTime != 0) |
1451 | HfsTimeToFileTime(Header.CTime, localFt); | 1454 | { |
1452 | if (LocalFileTimeToFileTime(&localFt, &ft)) | 1455 | FILETIME localFt, ft; |
1453 | prop = ft; | 1456 | HfsTimeToFileTime(Header.CTime, localFt); |
1457 | if (LocalFileTimeToFileTime(&localFt, &ft)) | ||
1458 | prop.SetAsTimeFrom_FT_Prec(ft, k_PropVar_TimePrec_Base); | ||
1459 | } | ||
1454 | break; | 1460 | break; |
1455 | } | 1461 | } |
1456 | case kpidIsTree: prop = true; break; | 1462 | case kpidIsTree: prop = true; break; |
@@ -1578,6 +1584,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
1578 | case kpidCTime: HfsTimeToProp(item.CTime, prop); break; | 1584 | case kpidCTime: HfsTimeToProp(item.CTime, prop); break; |
1579 | case kpidMTime: HfsTimeToProp(item.MTime, prop); break; | 1585 | case kpidMTime: HfsTimeToProp(item.MTime, prop); break; |
1580 | case kpidATime: HfsTimeToProp(item.ATime, prop); break; | 1586 | case kpidATime: HfsTimeToProp(item.ATime, prop); break; |
1587 | case kpidChangeTime: HfsTimeToProp(item.AttrMTime, prop); break; | ||
1581 | 1588 | ||
1582 | case kpidPosixAttrib: if (ref.AttrIndex < 0) prop = (UInt32)item.FileMode; break; | 1589 | case kpidPosixAttrib: if (ref.AttrIndex < 0) prop = (UInt32)item.FileMode; break; |
1583 | } | 1590 | } |
diff --git a/CPP/7zip/Archive/IArchive.h b/CPP/7zip/Archive/IArchive.h index 6df76d2..9551dfa 100644 --- a/CPP/7zip/Archive/IArchive.h +++ b/CPP/7zip/Archive/IArchive.h | |||
@@ -38,9 +38,11 @@ namespace NFileTimeType | |||
38 | { | 38 | { |
39 | enum EEnum | 39 | enum EEnum |
40 | { | 40 | { |
41 | kWindows, | 41 | kNotDefined = -1, |
42 | kWindows = 0, | ||
42 | kUnix, | 43 | kUnix, |
43 | kDOS | 44 | kDOS, |
45 | k1ns | ||
44 | }; | 46 | }; |
45 | } | 47 | } |
46 | 48 | ||
@@ -60,8 +62,31 @@ namespace NArcInfoFlags | |||
60 | const UInt32 kHardLinks = 1 << 11; // the handler supports hard links | 62 | const UInt32 kHardLinks = 1 << 11; // the handler supports hard links |
61 | const UInt32 kByExtOnlyOpen = 1 << 12; // call handler only if file extension matches | 63 | const UInt32 kByExtOnlyOpen = 1 << 12; // call handler only if file extension matches |
62 | const UInt32 kHashHandler = 1 << 13; // the handler contains the hashes (checksums) | 64 | const UInt32 kHashHandler = 1 << 13; // the handler contains the hashes (checksums) |
65 | const UInt32 kCTime = 1 << 14; | ||
66 | const UInt32 kCTime_Default = 1 << 15; | ||
67 | const UInt32 kATime = 1 << 16; | ||
68 | const UInt32 kATime_Default = 1 << 17; | ||
69 | const UInt32 kMTime = 1 << 18; | ||
70 | const UInt32 kMTime_Default = 1 << 19; | ||
71 | // const UInt32 kTTime_Reserved = 1 << 20; | ||
72 | // const UInt32 kTTime_Reserved_Default = 1 << 21; | ||
63 | } | 73 | } |
64 | 74 | ||
75 | namespace NArcInfoTimeFlags | ||
76 | { | ||
77 | const unsigned kTime_Prec_Mask_bit_index = 0; | ||
78 | const unsigned kTime_Prec_Mask_num_bits = 26; | ||
79 | |||
80 | const unsigned kTime_Prec_Default_bit_index = 27; | ||
81 | const unsigned kTime_Prec_Default_num_bits = 5; | ||
82 | } | ||
83 | |||
84 | #define TIME_PREC_TO_ARC_FLAGS_MASK(x) \ | ||
85 | ((UInt32)1 << (NArcInfoTimeFlags::kTime_Prec_Mask_bit_index + (x))) | ||
86 | |||
87 | #define TIME_PREC_TO_ARC_FLAGS_TIME_DEFAULT(x) \ | ||
88 | ((UInt32)(x) << NArcInfoTimeFlags::kTime_Prec_Default_bit_index) | ||
89 | |||
65 | namespace NArchive | 90 | namespace NArchive |
66 | { | 91 | { |
67 | namespace NHandlerPropID | 92 | namespace NHandlerPropID |
@@ -79,8 +104,8 @@ namespace NArchive | |||
79 | kSignatureOffset, // VT_UI4 | 104 | kSignatureOffset, // VT_UI4 |
80 | kAltStreams, // VT_BOOL | 105 | kAltStreams, // VT_BOOL |
81 | kNtSecure, // VT_BOOL | 106 | kNtSecure, // VT_BOOL |
82 | kFlags // VT_UI4 | 107 | kFlags, // VT_UI4 |
83 | // kVersion // VT_UI4 ((VER_MAJOR << 8) | VER_MINOR) | 108 | kTimeFlags // VT_UI4 |
84 | }; | 109 | }; |
85 | } | 110 | } |
86 | 111 | ||
@@ -123,6 +148,7 @@ namespace NArchive | |||
123 | kInArcIndex, | 148 | kInArcIndex, |
124 | kBlockIndex, | 149 | kBlockIndex, |
125 | kOutArcIndex | 150 | kOutArcIndex |
151 | // kArcProp | ||
126 | }; | 152 | }; |
127 | } | 153 | } |
128 | 154 | ||
@@ -133,7 +159,8 @@ namespace NArchive | |||
133 | enum | 159 | enum |
134 | { | 160 | { |
135 | kOK = 0 | 161 | kOK = 0 |
136 | // , kError | 162 | // kError = 1, |
163 | // kError_FileChanged | ||
137 | }; | 164 | }; |
138 | } | 165 | } |
139 | } | 166 | } |
@@ -461,9 +488,10 @@ namespace NUpdateNotifyOp | |||
461 | kSkip, | 488 | kSkip, |
462 | kDelete, | 489 | kDelete, |
463 | kHeader, | 490 | kHeader, |
464 | kHashRead | 491 | kHashRead, |
465 | 492 | kInFileChanged | |
466 | // kNumDefined | 493 | // , kOpFinished |
494 | // , kNumDefined | ||
467 | }; | 495 | }; |
468 | }; | 496 | }; |
469 | 497 | ||
@@ -493,6 +521,20 @@ ARCHIVE_INTERFACE(IArchiveGetDiskProperty, 0x84) | |||
493 | }; | 521 | }; |
494 | 522 | ||
495 | /* | 523 | /* |
524 | #define INTERFACE_IArchiveUpdateCallbackArcProp(x) \ | ||
525 | STDMETHOD(ReportProp)(UInt32 indexType, UInt32 index, PROPID propID, const PROPVARIANT *value) x; \ | ||
526 | STDMETHOD(ReportRawProp)(UInt32 indexType, UInt32 index, PROPID propID, const void *data, UInt32 dataSize, UInt32 propType) x; \ | ||
527 | STDMETHOD(ReportFinished)(UInt32 indexType, UInt32 index, Int32 opRes) x; \ | ||
528 | STDMETHOD(DoNeedArcProp)(PROPID propID, Int32 *answer) x; \ | ||
529 | |||
530 | |||
531 | ARCHIVE_INTERFACE(IArchiveUpdateCallbackArcProp, 0x85) | ||
532 | { | ||
533 | INTERFACE_IArchiveUpdateCallbackArcProp(PURE); | ||
534 | }; | ||
535 | */ | ||
536 | |||
537 | /* | ||
496 | UpdateItems() | 538 | UpdateItems() |
497 | ------------- | 539 | ------------- |
498 | 540 | ||
@@ -636,9 +678,40 @@ extern "C" | |||
636 | 678 | ||
637 | typedef HRESULT (WINAPI *Func_SetCaseSensitive)(Int32 caseSensitive); | 679 | typedef HRESULT (WINAPI *Func_SetCaseSensitive)(Int32 caseSensitive); |
638 | typedef HRESULT (WINAPI *Func_SetLargePageMode)(); | 680 | typedef HRESULT (WINAPI *Func_SetLargePageMode)(); |
681 | // typedef HRESULT (WINAPI *Func_SetClientVersion)(UInt32 version); | ||
639 | 682 | ||
640 | typedef IOutArchive * (*Func_CreateOutArchive)(); | 683 | typedef IOutArchive * (*Func_CreateOutArchive)(); |
641 | typedef IInArchive * (*Func_CreateInArchive)(); | 684 | typedef IInArchive * (*Func_CreateInArchive)(); |
642 | } | 685 | } |
643 | 686 | ||
687 | |||
688 | /* | ||
689 | if there is no time in archive, external MTime of archive | ||
690 | will be used instead of _item.Time from archive. | ||
691 | For 7-zip before 22.00 we need to return some supported value. | ||
692 | But (kpidTimeType > kDOS) is not allowed in 7-Zip before 22.00. | ||
693 | So we return highest precision value supported by old 7-Zip. | ||
694 | new 7-Zip 22.00 doesn't use that value in usual cases. | ||
695 | */ | ||
696 | |||
697 | |||
698 | #define DECLARE_AND_SET_CLIENT_VERSION_VAR | ||
699 | #define GET_FileTimeType_NotDefined_for_GetFileTimeType \ | ||
700 | NFileTimeType::kWindows | ||
701 | |||
702 | /* | ||
703 | extern UInt32 g_ClientVersion; | ||
704 | |||
705 | #define GET_CLIENT_VERSION(major, minor) \ | ||
706 | ((UInt32)(((UInt32)(major) << 16) | (UInt32)(minor))) | ||
707 | |||
708 | #define DECLARE_AND_SET_CLIENT_VERSION_VAR \ | ||
709 | UInt32 g_ClientVersion = GET_CLIENT_VERSION(MY_VER_MAJOR, MY_VER_MINOR); | ||
710 | |||
711 | #define GET_FileTimeType_NotDefined_for_GetFileTimeType \ | ||
712 | ((UInt32)(g_ClientVersion >= GET_CLIENT_VERSION(22, 0) ? \ | ||
713 | (UInt32)(Int32)NFileTimeType::kNotDefined : \ | ||
714 | NFileTimeType::kWindows)) | ||
715 | */ | ||
716 | |||
644 | #endif | 717 | #endif |
diff --git a/CPP/7zip/Archive/Icons/apfs.ico b/CPP/7zip/Archive/Icons/apfs.ico new file mode 100644 index 0000000..124eb76 --- /dev/null +++ b/CPP/7zip/Archive/Icons/apfs.ico | |||
Binary files differ | |||
diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp index 87f4aa3..8588a7c 100644 --- a/CPP/7zip/Archive/Iso/IsoHandler.cpp +++ b/CPP/7zip/Archive/Iso/IsoHandler.cpp | |||
@@ -6,9 +6,6 @@ | |||
6 | #include "../../../Common/MyLinux.h" | 6 | #include "../../../Common/MyLinux.h" |
7 | #include "../../../Common/StringConvert.h" | 7 | #include "../../../Common/StringConvert.h" |
8 | 8 | ||
9 | #include "../../../Windows/PropVariant.h" | ||
10 | #include "../../../Windows/TimeUtils.h" | ||
11 | |||
12 | #include "../../Common/LimitedStreams.h" | 9 | #include "../../Common/LimitedStreams.h" |
13 | #include "../../Common/ProgressUtils.h" | 10 | #include "../../Common/ProgressUtils.h" |
14 | 11 | ||
@@ -34,8 +31,8 @@ static const Byte kProps[] = | |||
34 | // kpidCTime, | 31 | // kpidCTime, |
35 | // kpidATime, | 32 | // kpidATime, |
36 | kpidPosixAttrib, | 33 | kpidPosixAttrib, |
37 | // kpidUser, | 34 | // kpidUserId, |
38 | // kpidGroup, | 35 | // kpidGroupId, |
39 | // kpidLinks, | 36 | // kpidLinks, |
40 | kpidSymLink | 37 | kpidSymLink |
41 | }; | 38 | }; |
@@ -127,8 +124,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | |||
127 | prop = s; | 124 | prop = s; |
128 | break; | 125 | break; |
129 | } | 126 | } |
130 | case kpidCTime: { FILETIME utc; if (vol.CTime.GetFileTime(utc)) prop = utc; break; } | 127 | case kpidCTime: { vol.CTime.GetFileTime(prop); break; } |
131 | case kpidMTime: { FILETIME utc; if (vol.MTime.GetFileTime(utc)) prop = utc; break; } | 128 | case kpidMTime: { vol.MTime.GetFileTime(prop); break; } |
132 | } | 129 | } |
133 | } | 130 | } |
134 | 131 | ||
@@ -242,8 +239,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
242 | case kpidPosixAttrib: | 239 | case kpidPosixAttrib: |
243 | /* | 240 | /* |
244 | case kpidLinks: | 241 | case kpidLinks: |
245 | case kpidUser: | 242 | case kpidUserId: |
246 | case kpidGroup: | 243 | case kpidGroupId: |
247 | */ | 244 | */ |
248 | { | 245 | { |
249 | if (_archive.IsSusp) | 246 | if (_archive.IsSusp) |
@@ -254,8 +251,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
254 | case kpidPosixAttrib: t = k_Px_Mode; break; | 251 | case kpidPosixAttrib: t = k_Px_Mode; break; |
255 | /* | 252 | /* |
256 | case kpidLinks: t = k_Px_Links; break; | 253 | case kpidLinks: t = k_Px_Links; break; |
257 | case kpidUser: t = k_Px_User; break; | 254 | case kpidUserId: t = k_Px_User; break; |
258 | case kpidGroup: t = k_Px_Group; break; | 255 | case kpidGroupId: t = k_Px_Group; break; |
259 | */ | 256 | */ |
260 | } | 257 | } |
261 | UInt32 v; | 258 | UInt32 v; |
@@ -276,9 +273,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
276 | // case kpidCTime: | 273 | // case kpidCTime: |
277 | // case kpidATime: | 274 | // case kpidATime: |
278 | { | 275 | { |
279 | FILETIME utc; | 276 | // if |
280 | if (/* propID == kpidMTime && */ item.DateTime.GetFileTime(utc)) | 277 | item.DateTime.GetFileTime(prop); |
281 | prop = utc; | ||
282 | /* | 278 | /* |
283 | else | 279 | else |
284 | { | 280 | { |
diff --git a/CPP/7zip/Archive/Iso/IsoIn.cpp b/CPP/7zip/Archive/Iso/IsoIn.cpp index 211b3ee..6780235 100644 --- a/CPP/7zip/Archive/Iso/IsoIn.cpp +++ b/CPP/7zip/Archive/Iso/IsoIn.cpp | |||
@@ -587,6 +587,8 @@ HRESULT CInArchive::Open2() | |||
587 | for (MainVolDescIndex = VolDescs.Size() - 1; MainVolDescIndex > 0; MainVolDescIndex--) | 587 | for (MainVolDescIndex = VolDescs.Size() - 1; MainVolDescIndex > 0; MainVolDescIndex--) |
588 | if (VolDescs[MainVolDescIndex].IsJoliet()) | 588 | if (VolDescs[MainVolDescIndex].IsJoliet()) |
589 | break; | 589 | break; |
590 | /* FIXME: some volume can contain Rock Ridge, that is better than | ||
591 | Joliet volume. So we need some way to detect such case */ | ||
590 | // MainVolDescIndex = 0; // to read primary volume | 592 | // MainVolDescIndex = 0; // to read primary volume |
591 | const CVolumeDescriptor &vd = VolDescs[MainVolDescIndex]; | 593 | const CVolumeDescriptor &vd = VolDescs[MainVolDescIndex]; |
592 | if (vd.LogicalBlockSize != kBlockSize) | 594 | if (vd.LogicalBlockSize != kBlockSize) |
diff --git a/CPP/7zip/Archive/Iso/IsoIn.h b/CPP/7zip/Archive/Iso/IsoIn.h index 347f9e9..a705b06 100644 --- a/CPP/7zip/Archive/Iso/IsoIn.h +++ b/CPP/7zip/Archive/Iso/IsoIn.h | |||
@@ -127,17 +127,18 @@ struct CDateTime | |||
127 | bool NotSpecified() const { return Year == 0 && Month == 0 && Day == 0 && | 127 | bool NotSpecified() const { return Year == 0 && Month == 0 && Day == 0 && |
128 | Hour == 0 && Minute == 0 && Second == 0 && GmtOffset == 0; } | 128 | Hour == 0 && Minute == 0 && Second == 0 && GmtOffset == 0; } |
129 | 129 | ||
130 | bool GetFileTime(FILETIME &ft) const | 130 | bool GetFileTime(NWindows::NCOM::CPropVariant &prop) const |
131 | { | 131 | { |
132 | UInt64 value; | 132 | UInt64 v; |
133 | bool res = NWindows::NTime::GetSecondsSince1601(Year, Month, Day, Hour, Minute, Second, value); | 133 | const bool res = NWindows::NTime::GetSecondsSince1601(Year, Month, Day, Hour, Minute, Second, v); |
134 | if (res) | 134 | if (res) |
135 | { | 135 | { |
136 | value -= (Int64)((Int32)GmtOffset * 15 * 60); | 136 | v -= (Int64)((Int32)GmtOffset * 15 * 60); |
137 | value *= 10000000; | 137 | v *= 10000000; |
138 | if (Hundredths < 100) | ||
139 | v += (UInt32)Hundredths * 100000; | ||
140 | prop.SetAsTimeFrom_Ft64_Prec(v, k_PropVar_TimePrec_Base + 2); | ||
138 | } | 141 | } |
139 | ft.dwLowDateTime = (DWORD)value; | ||
140 | ft.dwHighDateTime = (DWORD)(value >> 32); | ||
141 | return res; | 142 | return res; |
142 | } | 143 | } |
143 | }; | 144 | }; |
diff --git a/CPP/7zip/Archive/Iso/IsoItem.h b/CPP/7zip/Archive/Iso/IsoItem.h index a42ae03..8c2a725 100644 --- a/CPP/7zip/Archive/Iso/IsoItem.h +++ b/CPP/7zip/Archive/Iso/IsoItem.h | |||
@@ -25,17 +25,16 @@ struct CRecordingDateTime | |||
25 | Byte Second; | 25 | Byte Second; |
26 | signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded. | 26 | signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded. |
27 | 27 | ||
28 | bool GetFileTime(FILETIME &ft) const | 28 | bool GetFileTime(NWindows::NCOM::CPropVariant &prop) const |
29 | { | 29 | { |
30 | UInt64 value; | 30 | UInt64 v; |
31 | bool res = NWindows::NTime::GetSecondsSince1601(Year + 1900, Month, Day, Hour, Minute, Second, value); | 31 | const bool res = NWindows::NTime::GetSecondsSince1601(Year + 1900, Month, Day, Hour, Minute, Second, v); |
32 | if (res) | 32 | if (res) |
33 | { | 33 | { |
34 | value -= (Int64)((Int32)GmtOffset * 15 * 60); | 34 | v -= (Int64)((Int32)GmtOffset * 15 * 60); |
35 | value *= 10000000; | 35 | v *= 10000000; |
36 | prop.SetAsTimeFrom_Ft64_Prec(v, k_PropVar_TimePrec_Base); | ||
36 | } | 37 | } |
37 | ft.dwLowDateTime = (DWORD)value; | ||
38 | ft.dwHighDateTime = (DWORD)(value >> 32); | ||
39 | return res; | 38 | return res; |
40 | } | 39 | } |
41 | }; | 40 | }; |
diff --git a/CPP/7zip/Archive/LpHandler.cpp b/CPP/7zip/Archive/LpHandler.cpp new file mode 100644 index 0000000..b2720f4 --- /dev/null +++ b/CPP/7zip/Archive/LpHandler.cpp | |||
@@ -0,0 +1,1173 @@ | |||
1 | // LpHandler.cpp | ||
2 | |||
3 | #include "StdAfx.h" | ||
4 | |||
5 | #include "../../../C/CpuArch.h" | ||
6 | #include "../../../C/Sha256.h" | ||
7 | |||
8 | #include "../../Common/ComTry.h" | ||
9 | #include "../../Common/IntToString.h" | ||
10 | #include "../../Common/MyBuffer.h" | ||
11 | |||
12 | #include "../../Windows/PropVariantUtils.h" | ||
13 | |||
14 | #include "../Common/LimitedStreams.h" | ||
15 | #include "../Common/ProgressUtils.h" | ||
16 | #include "../Common/RegisterArc.h" | ||
17 | #include "../Common/StreamUtils.h" | ||
18 | |||
19 | #include "../Compress/CopyCoder.h" | ||
20 | |||
21 | #define Get16(p) GetUi16(p) | ||
22 | #define Get32(p) GetUi32(p) | ||
23 | #define Get64(p) GetUi64(p) | ||
24 | |||
25 | #define G16(_offs_, dest) dest = Get16(p + (_offs_)); | ||
26 | #define G32(_offs_, dest) dest = Get32(p + (_offs_)); | ||
27 | #define G64(_offs_, dest) dest = Get64(p + (_offs_)); | ||
28 | |||
29 | using namespace NWindows; | ||
30 | |||
31 | namespace NArchive { | ||
32 | |||
33 | namespace NExt { | ||
34 | API_FUNC_IsArc IsArc_Ext_PhySize(const Byte *p, size_t size, UInt64 *phySize); | ||
35 | } | ||
36 | |||
37 | namespace NLp { | ||
38 | |||
39 | /* | ||
40 | Android 10+ use Android's Dynamic Partitions to allow the | ||
41 | different read-only system partitions (e.g. system, vendor, product) | ||
42 | to share the same pool of storage space (as LVM in Linux). | ||
43 | Name for partition: "super" (for GPT) or "super.img" (for file). | ||
44 | Dynamic Partition Tools: lpmake | ||
45 | All partitions that are A/B-ed should be named as follows (slots are always named a, b, etc.): | ||
46 | boot_a, boot_b, system_a, system_b, vendor_a, vendor_b. | ||
47 | */ | ||
48 | |||
49 | #define LP_METADATA_MAJOR_VERSION 10 | ||
50 | // #define LP_METADATA_MINOR_VERSION_MIN 0 | ||
51 | // #define LP_METADATA_MINOR_VERSION_MAX 2 | ||
52 | |||
53 | // #define LP_SECTOR_SIZE 512 | ||
54 | static const unsigned kSectorSizeLog = 9; | ||
55 | |||
56 | /* Amount of space reserved at the start of every super partition to avoid | ||
57 | * creating an accidental boot sector. */ | ||
58 | #define LP_PARTITION_RESERVED_BYTES 4096 | ||
59 | #define LP_METADATA_GEOMETRY_SIZE 4096 | ||
60 | #define LP_METADATA_HEADER_MAGIC 0x414C5030 | ||
61 | |||
62 | #define SIGNATURE { 0x67, 0x44, 0x6c, 0x61, 0x34, 0, 0, 0 } | ||
63 | static const unsigned k_SignatureSize = 8; | ||
64 | static const Byte k_Signature[k_SignatureSize] = SIGNATURE; | ||
65 | |||
66 | // The length (36) is the same as the maximum length of a GPT partition name. | ||
67 | static const unsigned kNameLen = 36; | ||
68 | |||
69 | static void AddName36ToString(AString &s, const char *name, bool strictConvert) | ||
70 | { | ||
71 | for (unsigned i = 0; i < kNameLen; i++) | ||
72 | { | ||
73 | char c = name[i]; | ||
74 | if (c == 0) | ||
75 | return; | ||
76 | if (strictConvert && c < 32) | ||
77 | c = '_'; | ||
78 | s += c; | ||
79 | } | ||
80 | } | ||
81 | |||
82 | |||
83 | static const unsigned k_Geometry_Size = 0x34; | ||
84 | |||
85 | // LpMetadataGeometry | ||
86 | struct CGeometry | ||
87 | { | ||
88 | // UInt32 magic; | ||
89 | // UInt32 struct_size; | ||
90 | // Byte checksum[32]; /* SHA256 checksum of this struct, with this field set to 0. */ | ||
91 | |||
92 | /* Maximum amount of space a single copy of the metadata can use, | ||
93 | a multiple of LP_SECTOR_SIZE. */ | ||
94 | UInt32 metadata_max_size; | ||
95 | |||
96 | /* Number of copies of the metadata to keep. | ||
97 | For Non-A/B: 1, For A/B: 2, for A/B/C: 3. | ||
98 | A backup copy of each slot is kept */ | ||
99 | UInt32 metadata_slot_count; | ||
100 | |||
101 | /* minimal alignment for partition and extent sizes, a multiple of LP_SECTOR_SIZE. */ | ||
102 | UInt32 logical_block_size; | ||
103 | |||
104 | bool Parse(const Byte *p) | ||
105 | { | ||
106 | G32 (40, metadata_max_size); | ||
107 | G32 (44, metadata_slot_count); | ||
108 | G32 (48, logical_block_size); | ||
109 | if (metadata_slot_count == 0 || metadata_slot_count >= ((UInt32)1 << 20)) | ||
110 | return false; | ||
111 | if (metadata_max_size == 0) | ||
112 | return false; | ||
113 | if ((metadata_max_size & (((UInt32)1 << kSectorSizeLog) - 1)) != 0) | ||
114 | return false; | ||
115 | return true; | ||
116 | } | ||
117 | |||
118 | UInt64 GetTotalMetadataSize() const | ||
119 | { | ||
120 | // there are 2 copies of GEOMETRY and METADATA slots | ||
121 | return LP_PARTITION_RESERVED_BYTES + | ||
122 | LP_METADATA_GEOMETRY_SIZE * 2 + | ||
123 | ((UInt64)metadata_max_size * metadata_slot_count) * 2; | ||
124 | } | ||
125 | }; | ||
126 | |||
127 | |||
128 | |||
129 | // LpMetadataTableDescriptor | ||
130 | struct CDescriptor | ||
131 | { | ||
132 | UInt32 offset; /* Location of the table, relative to end of the metadata header. */ | ||
133 | UInt32 num_entries; /* Number of entries in the table. */ | ||
134 | UInt32 entry_size; /* Size of each entry in the table, in bytes. */ | ||
135 | |||
136 | void Parse(const Byte *p) | ||
137 | { | ||
138 | G32 (0, offset); | ||
139 | G32 (4, num_entries); | ||
140 | G32 (8, entry_size); | ||
141 | } | ||
142 | |||
143 | bool CheckLimits(UInt32 limit) const | ||
144 | { | ||
145 | if (entry_size == 0) | ||
146 | return false; | ||
147 | const UInt32 size = num_entries * entry_size; | ||
148 | if (size / entry_size != num_entries) | ||
149 | return false; | ||
150 | if (offset > limit || limit - offset < size) | ||
151 | return false; | ||
152 | return true; | ||
153 | } | ||
154 | }; | ||
155 | |||
156 | |||
157 | // #define LP_PARTITION_ATTR_NONE 0x0 | ||
158 | // #define LP_PARTITION_ATTR_READONLY (1 << 0) | ||
159 | |||
160 | /* This flag is only intended to be used with super_empty.img and super.img on | ||
161 | * retrofit devices. On these devices there are A and B super partitions, and | ||
162 | * we don't know ahead of time which slot the image will be applied to. | ||
163 | * | ||
164 | * If set, the partition name needs a slot suffix applied. The slot suffix is | ||
165 | * determined by the metadata slot number (0 = _a, 1 = _b). | ||
166 | */ | ||
167 | // #define LP_PARTITION_ATTR_SLOT_SUFFIXED (1 << 1) | ||
168 | |||
169 | /* This flag is applied automatically when using MetadataBuilder::NewForUpdate. | ||
170 | * It signals that the partition was created (or modified) for a snapshot-based | ||
171 | * update. If this flag is not present, the partition was likely flashed via | ||
172 | * fastboot. | ||
173 | */ | ||
174 | // #define LP_PARTITION_ATTR_UPDATED (1 << 2) | ||
175 | |||
176 | /* This flag marks a partition as disabled. It should not be used or mapped. */ | ||
177 | // #define LP_PARTITION_ATTR_DISABLED (1 << 3) | ||
178 | |||
179 | static const char * const g_PartitionAttr[] = | ||
180 | { | ||
181 | "READONLY" | ||
182 | , "SLOT_SUFFIXED" | ||
183 | , "UPDATED" | ||
184 | , "DISABLED" | ||
185 | }; | ||
186 | |||
187 | static unsigned const k_MetaPartition_Size = 52; | ||
188 | |||
189 | // LpMetadataPartition | ||
190 | struct CPartition | ||
191 | { | ||
192 | /* ASCII characters: alphanumeric or _. at least one ASCII character, | ||
193 | (name) must be unique across all partition names. */ | ||
194 | char name[kNameLen]; | ||
195 | |||
196 | UInt32 attributes; /* (LP_PARTITION_ATTR_*). */ | ||
197 | |||
198 | /* Index of the first extent owned by this partition. The extent will | ||
199 | * start at logical sector 0. Gaps between extents are not allowed. */ | ||
200 | UInt32 first_extent_index; | ||
201 | |||
202 | /* Number of extents in the partition. Every partition must have at least one extent. */ | ||
203 | UInt32 num_extents; | ||
204 | |||
205 | /* Group this partition belongs to. */ | ||
206 | UInt32 group_index; | ||
207 | |||
208 | void Parse(const Byte *p) | ||
209 | { | ||
210 | memcpy(name, p, kNameLen); | ||
211 | G32 (36, attributes); | ||
212 | G32 (40, first_extent_index); | ||
213 | G32 (44, num_extents); | ||
214 | G32 (48, group_index); | ||
215 | } | ||
216 | |||
217 | // calced properties: | ||
218 | UInt32 MethodsMask; | ||
219 | UInt64 NumSectors; | ||
220 | UInt64 NumSectors_Pack; | ||
221 | const char *Ext; | ||
222 | |||
223 | UInt64 GetSize() const { return NumSectors << kSectorSizeLog; } | ||
224 | UInt64 GetPackSize() const { return NumSectors_Pack << kSectorSizeLog; } | ||
225 | |||
226 | CPartition(): | ||
227 | MethodsMask(0), | ||
228 | NumSectors(0), | ||
229 | NumSectors_Pack(0), | ||
230 | Ext(NULL) | ||
231 | {} | ||
232 | }; | ||
233 | |||
234 | |||
235 | |||
236 | |||
237 | #define LP_TARGET_TYPE_LINEAR 0 | ||
238 | /* This extent is a dm-zero target. The index is ignored and must be 0. */ | ||
239 | #define LP_TARGET_TYPE_ZERO 1 | ||
240 | |||
241 | static const char * const g_Methods[] = | ||
242 | { | ||
243 | "RAW" // "LINEAR" | ||
244 | , "ZERO" | ||
245 | }; | ||
246 | |||
247 | static unsigned const k_MetaExtent_Size = 24; | ||
248 | |||
249 | // LpMetadataExtent | ||
250 | struct CExtent | ||
251 | { | ||
252 | UInt64 num_sectors; /* Length in 512-byte sectors. */ | ||
253 | UInt32 target_type; /* Target type for device-mapper (LP_TARGET_TYPE_*). */ | ||
254 | |||
255 | /* for LINEAR: The sector on the physical partition that this extent maps onto. | ||
256 | for ZERO: must be 0. */ | ||
257 | UInt64 target_data; | ||
258 | |||
259 | /* for LINEAR: index into the block devices table. | ||
260 | for ZERO: must be 0. */ | ||
261 | UInt32 target_source; | ||
262 | |||
263 | bool IsRAW() const { return target_type == LP_TARGET_TYPE_LINEAR; } | ||
264 | |||
265 | void Parse(const Byte *p) | ||
266 | { | ||
267 | G64 (0, num_sectors); | ||
268 | G32 (8, target_type); | ||
269 | G64 (12, target_data); | ||
270 | G32 (20, target_source); | ||
271 | } | ||
272 | }; | ||
273 | |||
274 | |||
275 | /* This flag is only intended to be used with super_empty.img and super.img on | ||
276 | * retrofit devices. If set, the group needs a slot suffix to be interpreted | ||
277 | * correctly. The suffix is automatically applied by ReadMetadata(). | ||
278 | */ | ||
279 | // #define LP_GROUP_SLOT_SUFFIXED (1 << 0) | ||
280 | static unsigned const k_Group_Size = 48; | ||
281 | |||
282 | // LpMetadataPartitionGroup | ||
283 | struct CGroup | ||
284 | { | ||
285 | char name[kNameLen]; | ||
286 | UInt32 flags; /* (LP_GROUP_*). */ | ||
287 | UInt64 maximum_size; /* Maximum size in bytes. If 0, the group has no maximum size. */ | ||
288 | |||
289 | void Parse(const Byte *p) | ||
290 | { | ||
291 | memcpy(name, p, kNameLen); | ||
292 | G32 (36, flags); | ||
293 | G64 (40, maximum_size); | ||
294 | } | ||
295 | }; | ||
296 | |||
297 | |||
298 | |||
299 | |||
300 | /* This flag is only intended to be used with super_empty.img and super.img on | ||
301 | * retrofit devices. On these devices there are A and B super partitions, and | ||
302 | * we don't know ahead of time which slot the image will be applied to. | ||
303 | * | ||
304 | * If set, the block device needs a slot suffix applied before being used with | ||
305 | * IPartitionOpener. The slot suffix is determined by the metadata slot number | ||
306 | * (0 = _a, 1 = _b). | ||
307 | */ | ||
308 | // #define LP_BLOCK_DEVICE_SLOT_SUFFIXED (1 << 0) | ||
309 | |||
310 | static unsigned const k_Device_Size = 64; | ||
311 | |||
312 | /* This struct defines an entry in the block_devices table. There must be at | ||
313 | * least one device, and the first device must represent the partition holding | ||
314 | * the super metadata. | ||
315 | */ | ||
316 | // LpMetadataBlockDevice | ||
317 | struct CDevice | ||
318 | { | ||
319 | /* 0: First usable sector for allocating logical partitions. this will be | ||
320 | * the first sector after the initial geometry blocks, followed by the | ||
321 | * space consumed by metadata_max_size*metadata_slot_count*2. | ||
322 | */ | ||
323 | UInt64 first_logical_sector; | ||
324 | |||
325 | /* 8: Alignment for defining partitions or partition extents. For example, | ||
326 | * an alignment of 1MiB will require that all partitions have a size evenly | ||
327 | * divisible by 1MiB, and that the smallest unit the partition can grow by | ||
328 | * is 1MiB. | ||
329 | * | ||
330 | * Alignment is normally determined at runtime when growing or adding | ||
331 | * partitions. If for some reason the alignment cannot be determined, then | ||
332 | * this predefined alignment in the geometry is used instead. By default | ||
333 | * it is set to 1MiB. | ||
334 | */ | ||
335 | UInt32 alignment; | ||
336 | |||
337 | /* 12: Alignment offset for "stacked" devices. For example, if the "super" | ||
338 | * partition itself is not aligned within the parent block device's | ||
339 | * partition table, then we adjust for this in deciding where to place | ||
340 | * |first_logical_sector|. | ||
341 | * | ||
342 | * Similar to |alignment|, this will be derived from the operating system. | ||
343 | * If it cannot be determined, it is assumed to be 0. | ||
344 | */ | ||
345 | UInt32 alignment_offset; | ||
346 | |||
347 | /* 16: Block device size, as specified when the metadata was created. This | ||
348 | * can be used to verify the geometry against a target device. | ||
349 | */ | ||
350 | UInt64 size; | ||
351 | |||
352 | /* 24: Partition name in the GPT*/ | ||
353 | char partition_name[kNameLen]; | ||
354 | |||
355 | /* 60: Flags (see LP_BLOCK_DEVICE_* flags below). */ | ||
356 | UInt32 flags; | ||
357 | |||
358 | void Parse(const Byte *p) | ||
359 | { | ||
360 | memcpy(partition_name, p + 24, kNameLen); | ||
361 | G64 (0, first_logical_sector); | ||
362 | G32 (8, alignment); | ||
363 | G32 (12, alignment_offset); | ||
364 | G64 (16, size); | ||
365 | G32 (60, flags); | ||
366 | } | ||
367 | }; | ||
368 | |||
369 | |||
370 | /* This device uses Virtual A/B. Note that on retrofit devices, the expanded | ||
371 | * header may not be present. | ||
372 | */ | ||
373 | // #define LP_HEADER_FLAG_VIRTUAL_AB_DEVICE 0x1 | ||
374 | |||
375 | static const char * const g_Header_Flags[] = | ||
376 | { | ||
377 | "VIRTUAL_AB" | ||
378 | }; | ||
379 | |||
380 | |||
381 | static const unsigned k_LpMetadataHeader10_size = 128; | ||
382 | static const unsigned k_LpMetadataHeader12_size = 256; | ||
383 | |||
384 | struct LpMetadataHeader | ||
385 | { | ||
386 | /* 0: Four bytes equal to LP_METADATA_HEADER_MAGIC. */ | ||
387 | UInt32 magic; | ||
388 | |||
389 | /* 4: Version number required to read this metadata. If the version is not | ||
390 | * equal to the library version, the metadata should be considered | ||
391 | * incompatible. | ||
392 | */ | ||
393 | UInt16 major_version; | ||
394 | |||
395 | /* 6: Minor version. A library supporting newer features should be able to | ||
396 | * read metadata with an older minor version. However, an older library | ||
397 | * should not support reading metadata if its minor version is higher. | ||
398 | */ | ||
399 | UInt16 minor_version; | ||
400 | |||
401 | /* 8: The size of this header struct. */ | ||
402 | UInt32 header_size; | ||
403 | |||
404 | /* 12: SHA256 checksum of the header, up to |header_size| bytes, computed as | ||
405 | * if this field were set to 0. | ||
406 | */ | ||
407 | // Byte header_checksum[32]; | ||
408 | |||
409 | /* 44: The total size of all tables. This size is contiguous; tables may not | ||
410 | * have gaps in between, and they immediately follow the header. | ||
411 | */ | ||
412 | UInt32 tables_size; | ||
413 | |||
414 | /* 48: SHA256 checksum of all table contents. */ | ||
415 | Byte tables_checksum[32]; | ||
416 | |||
417 | /* 80: Partition table descriptor. */ | ||
418 | CDescriptor partitions; | ||
419 | /* 92: Extent table descriptor. */ | ||
420 | CDescriptor extents; | ||
421 | /* 104: Updateable group descriptor. */ | ||
422 | CDescriptor groups; | ||
423 | /* 116: Block device table. */ | ||
424 | CDescriptor block_devices; | ||
425 | |||
426 | /* Everything past here is header version 1.2+, and is only included if | ||
427 | * needed. When liblp supporting >= 1.2 reads a < 1.2 header, it must | ||
428 | * zero these additional fields. | ||
429 | */ | ||
430 | |||
431 | /* 128: See LP_HEADER_FLAG_ constants for possible values. Header flags are | ||
432 | * independent of the version number and intended to be informational only. | ||
433 | * New flags can be added without bumping the version. | ||
434 | */ | ||
435 | // UInt32 flags; | ||
436 | |||
437 | /* 132: Reserved (zero), pad to 256 bytes. */ | ||
438 | // Byte reserved[124]; | ||
439 | |||
440 | void Parse128(const Byte *p) | ||
441 | { | ||
442 | G32 (0, magic); | ||
443 | G16 (4, major_version); | ||
444 | G16 (6, minor_version); | ||
445 | G32 (8, header_size) | ||
446 | // Byte header_checksum[32]; | ||
447 | G32 (44, tables_size) | ||
448 | memcpy (tables_checksum, p + 48, 32); | ||
449 | partitions.Parse(p + 80); | ||
450 | extents.Parse(p + 92); | ||
451 | groups.Parse(p + 104); | ||
452 | block_devices.Parse(p + 116); | ||
453 | /* Everything past here is header version 1.2+, and is only included if | ||
454 | * needed. When liblp supporting >= 1.2 reads a < 1.2 header, it must | ||
455 | * zero these additional fields. | ||
456 | */ | ||
457 | } | ||
458 | }; | ||
459 | |||
460 | |||
461 | static bool CheckSha256(const Byte *data, size_t size, const Byte *checksum) | ||
462 | { | ||
463 | CSha256 sha; | ||
464 | Sha256_Init(&sha); | ||
465 | Sha256_Update(&sha, data, size); | ||
466 | Byte calced[32]; | ||
467 | Sha256_Final(&sha, calced); | ||
468 | return memcmp(checksum, calced, 32) == 0; | ||
469 | } | ||
470 | |||
471 | static bool CheckSha256_csOffset(Byte *data, size_t size, unsigned hashOffset) | ||
472 | { | ||
473 | Byte checksum[32]; | ||
474 | Byte *shaData = &data[hashOffset]; | ||
475 | memcpy(checksum, shaData, 32); | ||
476 | memset(shaData, 0, 32); | ||
477 | return CheckSha256(data, size, checksum); | ||
478 | } | ||
479 | |||
480 | |||
481 | |||
482 | class CHandler: | ||
483 | public IInArchive, | ||
484 | public IInArchiveGetStream, | ||
485 | public CMyUnknownImp | ||
486 | { | ||
487 | CRecordVector<CPartition> _items; | ||
488 | CRecordVector<CExtent> Extents; | ||
489 | |||
490 | CMyComPtr<IInStream> _stream; | ||
491 | UInt64 _totalSize; | ||
492 | // UInt64 _usedSize; | ||
493 | // UInt64 _headersSize; | ||
494 | |||
495 | CGeometry geom; | ||
496 | UInt16 Major_version; | ||
497 | UInt16 Minor_version; | ||
498 | UInt32 Flags; | ||
499 | |||
500 | Int32 _mainFileIndex; | ||
501 | UInt32 MethodsMask; | ||
502 | bool _headerWarning; | ||
503 | AString GroupsString; | ||
504 | AString DevicesString; | ||
505 | AString DeviceArcName; | ||
506 | |||
507 | HRESULT Open2(IInStream *stream); | ||
508 | |||
509 | public: | ||
510 | MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) | ||
511 | INTERFACE_IInArchive(;) | ||
512 | STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); | ||
513 | }; | ||
514 | |||
515 | |||
516 | static void AddComment_UInt64(AString &s, const char *name, UInt64 val) | ||
517 | { | ||
518 | s.Add_Space(); | ||
519 | s += name; | ||
520 | s += '='; | ||
521 | s.Add_UInt64(val); | ||
522 | } | ||
523 | |||
524 | |||
525 | static bool IsBufZero(const Byte *data, size_t size) | ||
526 | { | ||
527 | for (size_t i = 0; i < size; i += 4) | ||
528 | if (*(const UInt32 *)(const void *)(data + i) != 0) | ||
529 | return false; | ||
530 | return true; | ||
531 | } | ||
532 | |||
533 | |||
534 | HRESULT CHandler::Open2(IInStream *stream) | ||
535 | { | ||
536 | RINOK(stream->Seek(LP_PARTITION_RESERVED_BYTES, STREAM_SEEK_SET, NULL)); | ||
537 | { | ||
538 | Byte buf[k_Geometry_Size]; | ||
539 | RINOK(ReadStream_FALSE(stream, buf, k_Geometry_Size)); | ||
540 | if (memcmp(buf, k_Signature, k_SignatureSize) != 0) | ||
541 | return S_FALSE; | ||
542 | if (!geom.Parse(buf)) | ||
543 | return S_FALSE; | ||
544 | if (!CheckSha256_csOffset(buf, k_Geometry_Size, 8)) | ||
545 | return S_FALSE; | ||
546 | } | ||
547 | |||
548 | CByteBuffer buffer; | ||
549 | RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); | ||
550 | buffer.Alloc(LP_METADATA_GEOMETRY_SIZE * 2); | ||
551 | { | ||
552 | // buffer.Size() >= LP_PARTITION_RESERVED_BYTES | ||
553 | RINOK(ReadStream_FALSE(stream, buffer, LP_PARTITION_RESERVED_BYTES)); | ||
554 | if (!IsBufZero(buffer, LP_PARTITION_RESERVED_BYTES)) | ||
555 | { | ||
556 | _headerWarning = true; | ||
557 | // return S_FALSE; | ||
558 | } | ||
559 | } | ||
560 | |||
561 | RINOK(ReadStream_FALSE(stream, buffer, LP_METADATA_GEOMETRY_SIZE * 2)); | ||
562 | // we check that 2 copies of GEOMETRY are identical: | ||
563 | if (memcmp(buffer, buffer + LP_METADATA_GEOMETRY_SIZE, LP_METADATA_GEOMETRY_SIZE) != 0 | ||
564 | || !IsBufZero(buffer + k_Geometry_Size, LP_METADATA_GEOMETRY_SIZE - k_Geometry_Size)) | ||
565 | { | ||
566 | _headerWarning = true; | ||
567 | // return S_FALSE; | ||
568 | } | ||
569 | |||
570 | RINOK(ReadStream_FALSE(stream, buffer, k_LpMetadataHeader10_size)); | ||
571 | LpMetadataHeader header; | ||
572 | header.Parse128(buffer); | ||
573 | if (header.magic != LP_METADATA_HEADER_MAGIC || | ||
574 | header.major_version != LP_METADATA_MAJOR_VERSION || | ||
575 | header.header_size < k_LpMetadataHeader10_size) | ||
576 | return S_FALSE; | ||
577 | Flags = 0; | ||
578 | if (header.header_size > k_LpMetadataHeader10_size) | ||
579 | { | ||
580 | if (header.header_size != k_LpMetadataHeader12_size) | ||
581 | return S_FALSE; | ||
582 | RINOK(ReadStream_FALSE(stream, buffer + k_LpMetadataHeader10_size, | ||
583 | header.header_size - k_LpMetadataHeader10_size)); | ||
584 | Flags = Get32(buffer + k_LpMetadataHeader10_size); | ||
585 | } | ||
586 | Major_version = header.major_version; | ||
587 | Minor_version = header.minor_version; | ||
588 | |||
589 | if (!CheckSha256_csOffset(buffer, header.header_size, 12)) | ||
590 | return S_FALSE; | ||
591 | |||
592 | if (geom.metadata_max_size < header.tables_size || | ||
593 | geom.metadata_max_size - header.tables_size < header.header_size) | ||
594 | return S_FALSE; | ||
595 | |||
596 | buffer.AllocAtLeast(header.tables_size); | ||
597 | RINOK(ReadStream_FALSE(stream, buffer, header.tables_size)); | ||
598 | |||
599 | const UInt64 totalMetaSize = geom.GetTotalMetadataSize(); | ||
600 | // _headersSize = _totalSize; | ||
601 | _totalSize = totalMetaSize; | ||
602 | |||
603 | if (!CheckSha256(buffer, header.tables_size, header.tables_checksum)) | ||
604 | return S_FALSE; | ||
605 | |||
606 | { | ||
607 | const CDescriptor &d = header.partitions; | ||
608 | if (!d.CheckLimits(header.tables_size)) | ||
609 | return S_FALSE; | ||
610 | if (d.entry_size != k_MetaPartition_Size) | ||
611 | return S_FALSE; | ||
612 | for (UInt32 i = 0; i < d.num_entries; i++) | ||
613 | { | ||
614 | CPartition part; | ||
615 | part.Parse(buffer + d.offset + i * d.entry_size); | ||
616 | const UInt32 extLimit = part.first_extent_index + part.num_extents; | ||
617 | if (extLimit < part.first_extent_index || | ||
618 | extLimit > header.extents.num_entries || | ||
619 | part.group_index >= header.groups.num_entries) | ||
620 | return S_FALSE; | ||
621 | _items.Add(part); | ||
622 | } | ||
623 | } | ||
624 | { | ||
625 | const CDescriptor &d = header.extents; | ||
626 | if (!d.CheckLimits(header.tables_size)) | ||
627 | return S_FALSE; | ||
628 | if (d.entry_size != k_MetaExtent_Size) | ||
629 | return S_FALSE; | ||
630 | for (UInt32 i = 0; i < d.num_entries; i++) | ||
631 | { | ||
632 | CExtent e; | ||
633 | e.Parse(buffer + d.offset + i * d.entry_size); | ||
634 | // if (e.target_type > LP_TARGET_TYPE_ZERO) return S_FALSE; | ||
635 | if (e.IsRAW()) | ||
636 | { | ||
637 | if (e.target_source >= header.block_devices.num_entries) | ||
638 | return S_FALSE; | ||
639 | const UInt64 endSector = e.target_data + e.num_sectors; | ||
640 | const UInt64 endOffset = endSector << kSectorSizeLog; | ||
641 | if (_totalSize < endOffset) | ||
642 | _totalSize = endOffset; | ||
643 | } | ||
644 | MethodsMask |= (UInt32)1 << e.target_type; | ||
645 | Extents.Add(e); | ||
646 | } | ||
647 | } | ||
648 | |||
649 | // _usedSize = _totalSize; | ||
650 | { | ||
651 | const CDescriptor &d = header.groups; | ||
652 | if (!d.CheckLimits(header.tables_size)) | ||
653 | return S_FALSE; | ||
654 | if (d.entry_size != k_Group_Size) | ||
655 | return S_FALSE; | ||
656 | AString s; | ||
657 | for (UInt32 i = 0; i < d.num_entries; i++) | ||
658 | { | ||
659 | CGroup g; | ||
660 | g.Parse(buffer + d.offset + i * d.entry_size); | ||
661 | if (_totalSize < g.maximum_size) | ||
662 | _totalSize = g.maximum_size; | ||
663 | s += " "; | ||
664 | AddName36ToString(s, g.name, true); | ||
665 | AddComment_UInt64(s, "maximum_size", g.maximum_size); | ||
666 | AddComment_UInt64(s, "flags", g.flags); | ||
667 | s.Add_LF(); | ||
668 | } | ||
669 | GroupsString = s; | ||
670 | } | ||
671 | |||
672 | { | ||
673 | const CDescriptor &d = header.block_devices; | ||
674 | if (!d.CheckLimits(header.tables_size)) | ||
675 | return S_FALSE; | ||
676 | if (d.entry_size != k_Device_Size) | ||
677 | return S_FALSE; | ||
678 | AString s; | ||
679 | // CRecordVector<CDevice> devices; | ||
680 | for (UInt32 i = 0; i < d.num_entries; i++) | ||
681 | { | ||
682 | CDevice v; | ||
683 | v.Parse(buffer + d.offset + i * d.entry_size); | ||
684 | // if (i == 0) | ||
685 | { | ||
686 | // it's super_device is first device; | ||
687 | if (totalMetaSize > (v.first_logical_sector << kSectorSizeLog)) | ||
688 | return S_FALSE; | ||
689 | } | ||
690 | if (_totalSize < v.size) | ||
691 | _totalSize = v.size; | ||
692 | s += " "; | ||
693 | if (i == 0) | ||
694 | AddName36ToString(DeviceArcName, v.partition_name, true); | ||
695 | // devices.Add(v); | ||
696 | AddName36ToString(s, v.partition_name, true); | ||
697 | AddComment_UInt64(s, "size", v.size); | ||
698 | AddComment_UInt64(s, "first_logical_sector", v.first_logical_sector); | ||
699 | AddComment_UInt64(s, "alignment", v.alignment); | ||
700 | AddComment_UInt64(s, "alignment_offset", v.alignment_offset); | ||
701 | AddComment_UInt64(s, "flags", v.flags); | ||
702 | s.Add_LF(); | ||
703 | } | ||
704 | DevicesString = s; | ||
705 | } | ||
706 | |||
707 | { | ||
708 | FOR_VECTOR (i, _items) | ||
709 | { | ||
710 | CPartition &part = _items[i]; | ||
711 | if (part.first_extent_index > Extents.Size() || | ||
712 | part.num_extents > Extents.Size() - part.first_extent_index) | ||
713 | return S_FALSE; | ||
714 | |||
715 | UInt64 numSectors = 0; | ||
716 | UInt64 numSectors_Pack = 0; | ||
717 | UInt32 methods = 0; | ||
718 | for (UInt32 k = 0; k < part.num_extents; k++) | ||
719 | { | ||
720 | const CExtent &e = Extents[part.first_extent_index + k]; | ||
721 | numSectors += e.num_sectors; | ||
722 | if (e.IsRAW()) | ||
723 | numSectors_Pack += e.num_sectors; | ||
724 | methods |= (UInt32)1 << e.target_type; | ||
725 | } | ||
726 | part.NumSectors = numSectors; | ||
727 | part.NumSectors_Pack = numSectors_Pack; | ||
728 | part.MethodsMask = methods; | ||
729 | } | ||
730 | } | ||
731 | |||
732 | return S_OK; | ||
733 | } | ||
734 | |||
735 | |||
736 | STDMETHODIMP CHandler::Open(IInStream *stream, | ||
737 | const UInt64 * /* maxCheckStartPosition */, | ||
738 | IArchiveOpenCallback * /* openArchiveCallback */) | ||
739 | { | ||
740 | COM_TRY_BEGIN | ||
741 | Close(); | ||
742 | RINOK(Open2(stream)); | ||
743 | _stream = stream; | ||
744 | |||
745 | int mainFileIndex = -1; | ||
746 | unsigned numNonEmptyParts = 0; | ||
747 | |||
748 | FOR_VECTOR (fileIndex, _items) | ||
749 | { | ||
750 | CPartition &item = _items[fileIndex]; | ||
751 | if (item.NumSectors != 0) | ||
752 | { | ||
753 | mainFileIndex = fileIndex; | ||
754 | numNonEmptyParts++; | ||
755 | CMyComPtr<ISequentialInStream> parseStream; | ||
756 | if (GetStream(fileIndex, &parseStream) == S_OK && parseStream) | ||
757 | { | ||
758 | const size_t kParseSize = 1 << 11; | ||
759 | Byte buf[kParseSize]; | ||
760 | if (ReadStream_FAIL(parseStream, buf, kParseSize) == S_OK) | ||
761 | { | ||
762 | UInt64 extSize; | ||
763 | if (NExt::IsArc_Ext_PhySize(buf, kParseSize, &extSize) == k_IsArc_Res_YES) | ||
764 | if (extSize == item.GetSize()) | ||
765 | item.Ext = "ext"; | ||
766 | } | ||
767 | } | ||
768 | } | ||
769 | } | ||
770 | if (numNonEmptyParts == 1) | ||
771 | _mainFileIndex = mainFileIndex; | ||
772 | |||
773 | return S_OK; | ||
774 | COM_TRY_END | ||
775 | } | ||
776 | |||
777 | |||
778 | STDMETHODIMP CHandler::Close() | ||
779 | { | ||
780 | _totalSize = 0; | ||
781 | // _usedSize = 0; | ||
782 | // _headersSize = 0; | ||
783 | _items.Clear(); | ||
784 | Extents.Clear(); | ||
785 | _stream.Release(); | ||
786 | _mainFileIndex = -1; | ||
787 | _headerWarning = false; | ||
788 | MethodsMask = 0; | ||
789 | GroupsString.Empty(); | ||
790 | DevicesString.Empty(); | ||
791 | DeviceArcName.Empty(); | ||
792 | return S_OK; | ||
793 | } | ||
794 | |||
795 | |||
796 | static const Byte kProps[] = | ||
797 | { | ||
798 | kpidPath, | ||
799 | kpidSize, | ||
800 | kpidPackSize, | ||
801 | kpidCharacts, | ||
802 | kpidMethod, | ||
803 | kpidNumBlocks, | ||
804 | kpidOffset | ||
805 | }; | ||
806 | |||
807 | static const Byte kArcProps[] = | ||
808 | { | ||
809 | kpidUnpackVer, | ||
810 | kpidMethod, | ||
811 | kpidClusterSize, | ||
812 | // kpidHeadersSize, | ||
813 | // kpidFreeSpace, | ||
814 | kpidName, | ||
815 | kpidComment | ||
816 | }; | ||
817 | |||
818 | IMP_IInArchive_Props | ||
819 | IMP_IInArchive_ArcProps | ||
820 | |||
821 | STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | ||
822 | { | ||
823 | COM_TRY_BEGIN | ||
824 | NCOM::CPropVariant prop; | ||
825 | switch (propID) | ||
826 | { | ||
827 | case kpidMainSubfile: | ||
828 | { | ||
829 | if (_mainFileIndex >= 0) | ||
830 | prop = (UInt32)_mainFileIndex; | ||
831 | break; | ||
832 | } | ||
833 | case kpidPhySize: prop = _totalSize; break; | ||
834 | |||
835 | // case kpidFreeSpace: if (_usedSize != 0) prop = _totalSize - _usedSize; break; | ||
836 | // case kpidHeadersSize: prop = _headersSize; break; | ||
837 | |||
838 | case kpidMethod: | ||
839 | { | ||
840 | const UInt32 m = MethodsMask; | ||
841 | if (m != 0) | ||
842 | { | ||
843 | FLAGS_TO_PROP(g_Methods, m, prop); | ||
844 | } | ||
845 | break; | ||
846 | } | ||
847 | |||
848 | case kpidUnpackVer: | ||
849 | { | ||
850 | AString s; | ||
851 | s.Add_UInt32(Major_version); | ||
852 | s += '.'; | ||
853 | s.Add_UInt32(Minor_version); | ||
854 | prop = s; | ||
855 | break; | ||
856 | } | ||
857 | |||
858 | case kpidClusterSize: | ||
859 | prop = geom.logical_block_size; | ||
860 | break; | ||
861 | |||
862 | case kpidComment: | ||
863 | { | ||
864 | AString s; | ||
865 | |||
866 | s += "metadata_slot_count: "; | ||
867 | s.Add_UInt32(geom.metadata_slot_count); | ||
868 | s.Add_LF(); | ||
869 | |||
870 | s += "metadata_max_size: "; | ||
871 | s.Add_UInt32(geom.metadata_max_size); | ||
872 | s.Add_LF(); | ||
873 | |||
874 | if (Flags != 0) | ||
875 | { | ||
876 | s += "flags: "; | ||
877 | s += FlagsToString(g_Header_Flags, ARRAY_SIZE(g_Header_Flags), Flags); | ||
878 | s.Add_LF(); | ||
879 | } | ||
880 | |||
881 | if (!GroupsString.IsEmpty()) | ||
882 | { | ||
883 | s += "Groups:"; | ||
884 | s.Add_LF(); | ||
885 | s += GroupsString; | ||
886 | } | ||
887 | |||
888 | if (!DevicesString.IsEmpty()) | ||
889 | { | ||
890 | s += "BlockDevices:"; | ||
891 | s.Add_LF(); | ||
892 | s += DevicesString; | ||
893 | } | ||
894 | |||
895 | if (!s.IsEmpty()) | ||
896 | prop = s; | ||
897 | break; | ||
898 | } | ||
899 | |||
900 | case kpidName: | ||
901 | if (!DeviceArcName.IsEmpty()) | ||
902 | prop = DeviceArcName + ".lpimg"; | ||
903 | break; | ||
904 | |||
905 | case kpidWarningFlags: | ||
906 | if (_headerWarning) | ||
907 | { | ||
908 | UInt32 v = kpv_ErrorFlags_HeadersError; | ||
909 | prop = v; | ||
910 | } | ||
911 | break; | ||
912 | } | ||
913 | prop.Detach(value); | ||
914 | return S_OK; | ||
915 | COM_TRY_END | ||
916 | } | ||
917 | |||
918 | |||
919 | STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) | ||
920 | { | ||
921 | *numItems = _items.Size(); | ||
922 | return S_OK; | ||
923 | } | ||
924 | |||
925 | |||
926 | STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) | ||
927 | { | ||
928 | COM_TRY_BEGIN | ||
929 | NCOM::CPropVariant prop; | ||
930 | |||
931 | const CPartition &item = _items[index]; | ||
932 | |||
933 | switch (propID) | ||
934 | { | ||
935 | case kpidPath: | ||
936 | { | ||
937 | AString s; | ||
938 | AddName36ToString(s, item.name, false); | ||
939 | if (s.IsEmpty()) | ||
940 | s.Add_UInt32(index); | ||
941 | if (item.num_extents != 0) | ||
942 | { | ||
943 | s += '.'; | ||
944 | s += (item.Ext ? item.Ext : "img"); | ||
945 | } | ||
946 | prop = s; | ||
947 | break; | ||
948 | } | ||
949 | |||
950 | case kpidSize: prop = item.GetSize(); break; | ||
951 | case kpidPackSize: prop = item.GetPackSize(); break; | ||
952 | case kpidNumBlocks: prop = item.num_extents; break; | ||
953 | case kpidMethod: | ||
954 | { | ||
955 | const UInt32 m = item.MethodsMask; | ||
956 | if (m != 0) | ||
957 | { | ||
958 | FLAGS_TO_PROP(g_Methods, m, prop); | ||
959 | } | ||
960 | break; | ||
961 | } | ||
962 | case kpidOffset: | ||
963 | if (item.num_extents != 0) | ||
964 | if (item.first_extent_index < Extents.Size()) | ||
965 | prop = Extents[item.first_extent_index].target_data << kSectorSizeLog; | ||
966 | break; | ||
967 | |||
968 | case kpidCharacts: | ||
969 | { | ||
970 | AString s; | ||
971 | s += "group:"; | ||
972 | s.Add_UInt32(item.group_index); | ||
973 | s.Add_Space(); | ||
974 | s += FlagsToString(g_PartitionAttr, ARRAY_SIZE(g_PartitionAttr), item.attributes); | ||
975 | prop = s; | ||
976 | break; | ||
977 | } | ||
978 | } | ||
979 | |||
980 | prop.Detach(value); | ||
981 | return S_OK; | ||
982 | COM_TRY_END | ||
983 | } | ||
984 | |||
985 | |||
986 | |||
987 | STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) | ||
988 | { | ||
989 | COM_TRY_BEGIN | ||
990 | *stream = NULL; | ||
991 | |||
992 | const CPartition &item = _items[index]; | ||
993 | |||
994 | if (item.first_extent_index > Extents.Size() | ||
995 | || item.num_extents > Extents.Size() - item.first_extent_index) | ||
996 | return S_FALSE; | ||
997 | |||
998 | if (item.num_extents == 0) | ||
999 | return CreateLimitedInStream(_stream, 0, 0, stream); | ||
1000 | |||
1001 | if (item.num_extents == 1) | ||
1002 | { | ||
1003 | const CExtent &e = Extents[item.first_extent_index]; | ||
1004 | if (e.IsRAW()) | ||
1005 | { | ||
1006 | const UInt64 pos = e.target_data << kSectorSizeLog; | ||
1007 | if ((pos >> kSectorSizeLog) != e.target_data) | ||
1008 | return S_FALSE; | ||
1009 | const UInt64 size = item.GetSize(); | ||
1010 | if (pos + size < pos) | ||
1011 | return S_FALSE; | ||
1012 | return CreateLimitedInStream(_stream, pos, size, stream); | ||
1013 | } | ||
1014 | } | ||
1015 | |||
1016 | CExtentsStream *extentStreamSpec = new CExtentsStream(); | ||
1017 | CMyComPtr<ISequentialInStream> extentStream = extentStreamSpec; | ||
1018 | |||
1019 | // const unsigned kNumDebugExtents = 10; | ||
1020 | extentStreamSpec->Extents.Reserve(item.num_extents + 1 | ||
1021 | // + kNumDebugExtents | ||
1022 | ); | ||
1023 | |||
1024 | UInt64 virt = 0; | ||
1025 | for (UInt32 k = 0; k < item.num_extents; k++) | ||
1026 | { | ||
1027 | const CExtent &e = Extents[item.first_extent_index + k]; | ||
1028 | |||
1029 | CSeekExtent se; | ||
1030 | { | ||
1031 | const UInt64 numSectors = e.num_sectors; | ||
1032 | if (numSectors == 0) | ||
1033 | { | ||
1034 | continue; | ||
1035 | // return S_FALSE; | ||
1036 | } | ||
1037 | const UInt64 numBytes = numSectors << kSectorSizeLog; | ||
1038 | if ((numBytes >> kSectorSizeLog) != numSectors) | ||
1039 | return S_FALSE; | ||
1040 | if (numBytes >= ((UInt64)1 << 63) - virt) | ||
1041 | return S_FALSE; | ||
1042 | |||
1043 | se.Virt = virt; | ||
1044 | virt += numBytes; | ||
1045 | } | ||
1046 | |||
1047 | const UInt64 phySector = e.target_data; | ||
1048 | if (e.target_type == LP_TARGET_TYPE_ZERO) | ||
1049 | { | ||
1050 | if (phySector != 0) | ||
1051 | return S_FALSE; | ||
1052 | se.SetAs_ZeroFill(); | ||
1053 | } | ||
1054 | else if (e.target_type == LP_TARGET_TYPE_LINEAR) | ||
1055 | { | ||
1056 | se.Phy = phySector << kSectorSizeLog; | ||
1057 | if ((se.Phy >> kSectorSizeLog) != phySector) | ||
1058 | return S_FALSE; | ||
1059 | if (se.Phy >= ((UInt64)1 << 63)) | ||
1060 | return S_FALSE; | ||
1061 | } | ||
1062 | else | ||
1063 | return S_FALSE; | ||
1064 | |||
1065 | extentStreamSpec->Extents.AddInReserved(se); | ||
1066 | |||
1067 | /* | ||
1068 | { | ||
1069 | // for debug | ||
1070 | const UInt64 kAdd = (e.num_sectors << kSectorSizeLog) / kNumDebugExtents; | ||
1071 | for (unsigned i = 0; i < kNumDebugExtents; i++) | ||
1072 | { | ||
1073 | se.Phy += kAdd; | ||
1074 | // se.Phy += (UInt64)1 << 63; // for debug | ||
1075 | // se.Phy += 1; // for debug | ||
1076 | se.Virt += kAdd; | ||
1077 | extentStreamSpec->Extents.AddInReserved(se); | ||
1078 | } | ||
1079 | } | ||
1080 | */ | ||
1081 | } | ||
1082 | |||
1083 | CSeekExtent se; | ||
1084 | se.Phy = 0; | ||
1085 | se.Virt = virt; | ||
1086 | extentStreamSpec->Extents.Add(se); | ||
1087 | extentStreamSpec->Stream = _stream; | ||
1088 | extentStreamSpec->Init(); | ||
1089 | *stream = extentStream.Detach(); | ||
1090 | |||
1091 | return S_OK; | ||
1092 | COM_TRY_END | ||
1093 | } | ||
1094 | |||
1095 | |||
1096 | STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, | ||
1097 | Int32 testMode, IArchiveExtractCallback *extractCallback) | ||
1098 | { | ||
1099 | COM_TRY_BEGIN | ||
1100 | const bool allFilesMode = (numItems == (UInt32)(Int32)-1); | ||
1101 | if (allFilesMode) | ||
1102 | numItems = _items.Size(); | ||
1103 | if (numItems == 0) | ||
1104 | return S_OK; | ||
1105 | UInt64 totalSize = 0; | ||
1106 | UInt32 i; | ||
1107 | for (i = 0; i < numItems; i++) | ||
1108 | { | ||
1109 | const UInt32 index = allFilesMode ? i : indices[i]; | ||
1110 | totalSize += _items[index].GetSize(); | ||
1111 | } | ||
1112 | extractCallback->SetTotal(totalSize); | ||
1113 | |||
1114 | totalSize = 0; | ||
1115 | |||
1116 | NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); | ||
1117 | CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; | ||
1118 | |||
1119 | CLocalProgress *lps = new CLocalProgress; | ||
1120 | CMyComPtr<ICompressProgressInfo> progress = lps; | ||
1121 | lps->Init(extractCallback, false); | ||
1122 | |||
1123 | for (i = 0; i < numItems; i++) | ||
1124 | { | ||
1125 | lps->InSize = totalSize; | ||
1126 | lps->OutSize = totalSize; | ||
1127 | RINOK(lps->SetCur()); | ||
1128 | CMyComPtr<ISequentialOutStream> outStream; | ||
1129 | const Int32 askMode = testMode ? | ||
1130 | NExtract::NAskMode::kTest : | ||
1131 | NExtract::NAskMode::kExtract; | ||
1132 | const UInt32 index = allFilesMode ? i : indices[i]; | ||
1133 | |||
1134 | RINOK(extractCallback->GetStream(index, &outStream, askMode)); | ||
1135 | |||
1136 | const UInt64 size = _items[index].GetSize(); | ||
1137 | totalSize += size; | ||
1138 | if (!testMode && !outStream) | ||
1139 | continue; | ||
1140 | |||
1141 | RINOK(extractCallback->PrepareOperation(askMode)); | ||
1142 | |||
1143 | CMyComPtr<ISequentialInStream> inStream; | ||
1144 | const HRESULT hres = GetStream(index, &inStream); | ||
1145 | int opRes = NExtract::NOperationResult::kUnsupportedMethod; | ||
1146 | if (hres != S_FALSE) | ||
1147 | { | ||
1148 | if (hres != S_OK) | ||
1149 | return hres; | ||
1150 | RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); | ||
1151 | opRes = NExtract::NOperationResult::kDataError; | ||
1152 | if (copyCoderSpec->TotalSize == size) | ||
1153 | opRes = NExtract::NOperationResult::kOK; | ||
1154 | else if (copyCoderSpec->TotalSize < size) | ||
1155 | opRes = NExtract::NOperationResult::kUnexpectedEnd; | ||
1156 | } | ||
1157 | outStream.Release(); | ||
1158 | RINOK(extractCallback->SetOperationResult(opRes)); | ||
1159 | } | ||
1160 | |||
1161 | return S_OK; | ||
1162 | COM_TRY_END | ||
1163 | } | ||
1164 | |||
1165 | |||
1166 | REGISTER_ARC_I( | ||
1167 | "LP", "lpimg img", NULL, 0xc1, | ||
1168 | k_Signature, | ||
1169 | LP_PARTITION_RESERVED_BYTES, | ||
1170 | 0, | ||
1171 | NULL) | ||
1172 | |||
1173 | }} | ||
diff --git a/CPP/7zip/Archive/LzhHandler.cpp b/CPP/7zip/Archive/LzhHandler.cpp index e1984d2..6711da6 100644 --- a/CPP/7zip/Archive/LzhHandler.cpp +++ b/CPP/7zip/Archive/LzhHandler.cpp | |||
@@ -487,22 +487,11 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
487 | case kpidHostOS: PAIR_TO_PROP(g_OsPairs, item.OsId, prop); break; | 487 | case kpidHostOS: PAIR_TO_PROP(g_OsPairs, item.OsId, prop); break; |
488 | case kpidMTime: | 488 | case kpidMTime: |
489 | { | 489 | { |
490 | FILETIME utc; | ||
491 | UInt32 unixTime; | 490 | UInt32 unixTime; |
492 | if (item.GetUnixTime(unixTime)) | 491 | if (item.GetUnixTime(unixTime)) |
493 | NTime::UnixTimeToFileTime(unixTime, utc); | 492 | PropVariant_SetFrom_UnixTime(prop, unixTime); |
494 | else | 493 | else |
495 | { | 494 | PropVariant_SetFrom_DosTime(prop, item.ModifiedTime); |
496 | FILETIME localFileTime; | ||
497 | if (DosTimeToFileTime(item.ModifiedTime, localFileTime)) | ||
498 | { | ||
499 | if (!LocalFileTimeToFileTime(&localFileTime, &utc)) | ||
500 | utc.dwHighDateTime = utc.dwLowDateTime = 0; | ||
501 | } | ||
502 | else | ||
503 | utc.dwHighDateTime = utc.dwLowDateTime = 0; | ||
504 | } | ||
505 | prop = utc; | ||
506 | break; | 495 | break; |
507 | } | 496 | } |
508 | // case kpidAttrib: prop = (UInt32)item.Attributes; break; | 497 | // case kpidAttrib: prop = (UInt32)item.Attributes; break; |
diff --git a/CPP/7zip/Archive/NtfsHandler.cpp b/CPP/7zip/Archive/NtfsHandler.cpp index daa01fe..7d0c6f7 100644 --- a/CPP/7zip/Archive/NtfsHandler.cpp +++ b/CPP/7zip/Archive/NtfsHandler.cpp | |||
@@ -278,7 +278,7 @@ struct CSiAttr | |||
278 | { | 278 | { |
279 | UInt64 CTime; | 279 | UInt64 CTime; |
280 | UInt64 MTime; | 280 | UInt64 MTime; |
281 | // UInt64 ThisRecMTime; | 281 | UInt64 ThisRecMTime; |
282 | UInt64 ATime; | 282 | UInt64 ATime; |
283 | UInt32 Attrib; | 283 | UInt32 Attrib; |
284 | 284 | ||
@@ -300,7 +300,7 @@ bool CSiAttr::Parse(const Byte *p, unsigned size) | |||
300 | return false; | 300 | return false; |
301 | G64(p + 0x00, CTime); | 301 | G64(p + 0x00, CTime); |
302 | G64(p + 0x08, MTime); | 302 | G64(p + 0x08, MTime); |
303 | // G64(p + 0x10, ThisRecMTime); | 303 | G64(p + 0x10, ThisRecMTime); |
304 | G64(p + 0x18, ATime); | 304 | G64(p + 0x18, ATime); |
305 | G32(p + 0x20, Attrib); | 305 | G32(p + 0x20, Attrib); |
306 | SecurityId = 0; | 306 | SecurityId = 0; |
@@ -2301,6 +2301,7 @@ static const Byte kProps[] = | |||
2301 | kpidMTime, | 2301 | kpidMTime, |
2302 | kpidCTime, | 2302 | kpidCTime, |
2303 | kpidATime, | 2303 | kpidATime, |
2304 | kpidChangeTime, | ||
2304 | kpidAttrib, | 2305 | kpidAttrib, |
2305 | kpidLinks, | 2306 | kpidLinks, |
2306 | kpidINode, | 2307 | kpidINode, |
@@ -2577,7 +2578,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
2577 | case kpidMTime: NtfsTimeToProp(rec.SiAttr.MTime, prop); break; | 2578 | case kpidMTime: NtfsTimeToProp(rec.SiAttr.MTime, prop); break; |
2578 | case kpidCTime: NtfsTimeToProp(rec.SiAttr.CTime, prop); break; | 2579 | case kpidCTime: NtfsTimeToProp(rec.SiAttr.CTime, prop); break; |
2579 | case kpidATime: NtfsTimeToProp(rec.SiAttr.ATime, prop); break; | 2580 | case kpidATime: NtfsTimeToProp(rec.SiAttr.ATime, prop); break; |
2580 | // case kpidRecMTime: if (fn) NtfsTimeToProp(rec.SiAttr.ThisRecMTime, prop); break; | 2581 | case kpidChangeTime: NtfsTimeToProp(rec.SiAttr.ThisRecMTime, prop); break; |
2581 | 2582 | ||
2582 | /* | 2583 | /* |
2583 | case kpidMTime2: if (fn) NtfsTimeToProp(fn->MTime, prop); break; | 2584 | case kpidMTime2: if (fn) NtfsTimeToProp(fn->MTime, prop); break; |
diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp index ee26557..34a38ac 100644 --- a/CPP/7zip/Archive/PeHandler.cpp +++ b/CPP/7zip/Archive/PeHandler.cpp | |||
@@ -885,11 +885,7 @@ IMP_IInArchive_ArcProps_WITH_NAME | |||
885 | static void TimeToProp(UInt32 unixTime, NCOM::CPropVariant &prop) | 885 | static void TimeToProp(UInt32 unixTime, NCOM::CPropVariant &prop) |
886 | { | 886 | { |
887 | if (unixTime != 0) | 887 | if (unixTime != 0) |
888 | { | 888 | PropVariant_SetFrom_UnixTime(prop, unixTime); |
889 | FILETIME ft; | ||
890 | NTime::UnixTimeToFileTime(unixTime, ft); | ||
891 | prop = ft; | ||
892 | } | ||
893 | } | 889 | } |
894 | 890 | ||
895 | STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | 891 | STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) |
diff --git a/CPP/7zip/Archive/PpmdHandler.cpp b/CPP/7zip/Archive/PpmdHandler.cpp index 05a07e5..101bfd9 100644 --- a/CPP/7zip/Archive/PpmdHandler.cpp +++ b/CPP/7zip/Archive/PpmdHandler.cpp | |||
@@ -174,7 +174,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN | |||
174 | { | 174 | { |
175 | // time can be in Unix format ??? | 175 | // time can be in Unix format ??? |
176 | FILETIME utc; | 176 | FILETIME utc; |
177 | if (NTime::DosTimeToFileTime(_item.Time, utc)) | 177 | if (NTime::DosTime_To_FileTime(_item.Time, utc)) |
178 | prop = utc; | 178 | prop = utc; |
179 | break; | 179 | break; |
180 | } | 180 | } |
diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.cpp b/CPP/7zip/Archive/Rar/Rar5Handler.cpp index bb8a2ed..563695f 100644 --- a/CPP/7zip/Archive/Rar/Rar5Handler.cpp +++ b/CPP/7zip/Archive/Rar/Rar5Handler.cpp | |||
@@ -1591,14 +1591,14 @@ STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data | |||
1591 | static void TimeRecordToProp(const CItem &item, unsigned stampIndex, NCOM::CPropVariant &prop) | 1591 | static void TimeRecordToProp(const CItem &item, unsigned stampIndex, NCOM::CPropVariant &prop) |
1592 | { | 1592 | { |
1593 | unsigned size; | 1593 | unsigned size; |
1594 | int offset = item.FindExtra(NExtraID::kTime, size); | 1594 | const int offset = item.FindExtra(NExtraID::kTime, size); |
1595 | if (offset < 0) | 1595 | if (offset < 0) |
1596 | return; | 1596 | return; |
1597 | 1597 | ||
1598 | const Byte *p = item.Extra + (unsigned)offset; | 1598 | const Byte *p = item.Extra + (unsigned)offset; |
1599 | UInt64 flags; | 1599 | UInt64 flags; |
1600 | { | 1600 | { |
1601 | unsigned num = ReadVarInt(p, size, &flags); | 1601 | const unsigned num = ReadVarInt(p, size, &flags); |
1602 | if (num == 0) | 1602 | if (num == 0) |
1603 | return; | 1603 | return; |
1604 | p += num; | 1604 | p += num; |
@@ -1610,8 +1610,8 @@ static void TimeRecordToProp(const CItem &item, unsigned stampIndex, NCOM::CProp | |||
1610 | 1610 | ||
1611 | unsigned numStamps = 0; | 1611 | unsigned numStamps = 0; |
1612 | unsigned curStamp = 0; | 1612 | unsigned curStamp = 0; |
1613 | unsigned i; | 1613 | |
1614 | for (i = 0; i < 3; i++) | 1614 | for (unsigned i = 0; i < 3; i++) |
1615 | if ((flags & (NTimeRecord::NFlags::kMTime << i)) != 0) | 1615 | if ((flags & (NTimeRecord::NFlags::kMTime << i)) != 0) |
1616 | { | 1616 | { |
1617 | if (i == stampIndex) | 1617 | if (i == stampIndex) |
@@ -1620,20 +1620,28 @@ static void TimeRecordToProp(const CItem &item, unsigned stampIndex, NCOM::CProp | |||
1620 | } | 1620 | } |
1621 | 1621 | ||
1622 | FILETIME ft; | 1622 | FILETIME ft; |
1623 | 1623 | ||
1624 | unsigned timePrec = 0; | ||
1625 | unsigned ns100 = 0; | ||
1626 | |||
1624 | if ((flags & NTimeRecord::NFlags::kUnixTime) != 0) | 1627 | if ((flags & NTimeRecord::NFlags::kUnixTime) != 0) |
1625 | { | 1628 | { |
1626 | curStamp *= 4; | 1629 | curStamp *= 4; |
1627 | if (curStamp + 4 > size) | 1630 | if (curStamp + 4 > size) |
1628 | return; | 1631 | return; |
1629 | const Byte *p2 = p + curStamp; | 1632 | p += curStamp; |
1630 | UInt64 val = NTime::UnixTimeToFileTime64(Get32(p2)); | 1633 | UInt64 val = NTime::UnixTime_To_FileTime64(Get32(p)); |
1631 | numStamps *= 4; | 1634 | numStamps *= 4; |
1635 | timePrec = k_PropVar_TimePrec_Unix; | ||
1632 | if ((flags & NTimeRecord::NFlags::kUnixNs) != 0 && numStamps * 2 <= size) | 1636 | if ((flags & NTimeRecord::NFlags::kUnixNs) != 0 && numStamps * 2 <= size) |
1633 | { | 1637 | { |
1634 | const UInt32 ns = Get32(p2 + numStamps) & 0x3FFFFFFF; | 1638 | const UInt32 ns = Get32(p + numStamps) & 0x3FFFFFFF; |
1635 | if (ns < 1000000000) | 1639 | if (ns < 1000000000) |
1640 | { | ||
1636 | val += ns / 100; | 1641 | val += ns / 100; |
1642 | ns100 = (unsigned)(ns % 100); | ||
1643 | timePrec = k_PropVar_TimePrec_1ns; | ||
1644 | } | ||
1637 | } | 1645 | } |
1638 | ft.dwLowDateTime = (DWORD)val; | 1646 | ft.dwLowDateTime = (DWORD)val; |
1639 | ft.dwHighDateTime = (DWORD)(val >> 32); | 1647 | ft.dwHighDateTime = (DWORD)(val >> 32); |
@@ -1643,12 +1651,12 @@ static void TimeRecordToProp(const CItem &item, unsigned stampIndex, NCOM::CProp | |||
1643 | curStamp *= 8; | 1651 | curStamp *= 8; |
1644 | if (curStamp + 8 > size) | 1652 | if (curStamp + 8 > size) |
1645 | return; | 1653 | return; |
1646 | const Byte *p2 = p + curStamp; | 1654 | p += curStamp; |
1647 | ft.dwLowDateTime = Get32(p2); | 1655 | ft.dwLowDateTime = Get32(p); |
1648 | ft.dwHighDateTime = Get32(p2 + 4); | 1656 | ft.dwHighDateTime = Get32(p + 4); |
1649 | } | 1657 | } |
1650 | 1658 | ||
1651 | prop = ft; | 1659 | prop.SetAsTimeFrom_FT_Prec_Ns100(ft, timePrec, ns100); |
1652 | } | 1660 | } |
1653 | 1661 | ||
1654 | 1662 | ||
@@ -1715,21 +1723,13 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
1715 | { | 1723 | { |
1716 | TimeRecordToProp(item, NTimeRecord::k_Index_MTime, prop); | 1724 | TimeRecordToProp(item, NTimeRecord::k_Index_MTime, prop); |
1717 | if (prop.vt == VT_EMPTY && item.Has_UnixMTime()) | 1725 | if (prop.vt == VT_EMPTY && item.Has_UnixMTime()) |
1718 | { | 1726 | PropVariant_SetFrom_UnixTime(prop, item.UnixMTime); |
1719 | FILETIME ft; | ||
1720 | NWindows::NTime::UnixTimeToFileTime(item.UnixMTime, ft); | ||
1721 | prop = ft; | ||
1722 | } | ||
1723 | if (prop.vt == VT_EMPTY && ref.Parent >= 0) | 1727 | if (prop.vt == VT_EMPTY && ref.Parent >= 0) |
1724 | { | 1728 | { |
1725 | const CItem &baseItem = _items[_refs[ref.Parent].Item]; | 1729 | const CItem &baseItem = _items[_refs[ref.Parent].Item]; |
1726 | TimeRecordToProp(baseItem, NTimeRecord::k_Index_MTime, prop); | 1730 | TimeRecordToProp(baseItem, NTimeRecord::k_Index_MTime, prop); |
1727 | if (prop.vt == VT_EMPTY && baseItem.Has_UnixMTime()) | 1731 | if (prop.vt == VT_EMPTY && baseItem.Has_UnixMTime()) |
1728 | { | 1732 | PropVariant_SetFrom_UnixTime(prop, baseItem.UnixMTime); |
1729 | FILETIME ft; | ||
1730 | NWindows::NTime::UnixTimeToFileTime(baseItem.UnixMTime, ft); | ||
1731 | prop = ft; | ||
1732 | } | ||
1733 | } | 1733 | } |
1734 | break; | 1734 | break; |
1735 | } | 1735 | } |
diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp index 7491c50..ecadf85 100644 --- a/CPP/7zip/Archive/Rar/RarHandler.cpp +++ b/CPP/7zip/Archive/Rar/RarHandler.cpp | |||
@@ -360,7 +360,7 @@ void CInArchive::ReadName(const Byte *p, unsigned nameSize, CItem &item) | |||
360 | static int ReadTime(const Byte *p, unsigned size, Byte mask, CRarTime &rarTime) | 360 | static int ReadTime(const Byte *p, unsigned size, Byte mask, CRarTime &rarTime) |
361 | { | 361 | { |
362 | rarTime.LowSecond = (Byte)(((mask & 4) != 0) ? 1 : 0); | 362 | rarTime.LowSecond = (Byte)(((mask & 4) != 0) ? 1 : 0); |
363 | unsigned numDigits = (mask & 3); | 363 | const unsigned numDigits = (mask & 3); |
364 | rarTime.SubTime[0] = | 364 | rarTime.SubTime[0] = |
365 | rarTime.SubTime[1] = | 365 | rarTime.SubTime[1] = |
366 | rarTime.SubTime[2] = 0; | 366 | rarTime.SubTime[2] = 0; |
@@ -405,8 +405,8 @@ bool CInArchive::ReadHeaderReal(const Byte *p, unsigned size, CItem &item) | |||
405 | 405 | ||
406 | item.MTime.LowSecond = 0; | 406 | item.MTime.LowSecond = 0; |
407 | item.MTime.SubTime[0] = | 407 | item.MTime.SubTime[0] = |
408 | item.MTime.SubTime[1] = | 408 | item.MTime.SubTime[1] = |
409 | item.MTime.SubTime[2] = 0; | 409 | item.MTime.SubTime[2] = 0; |
410 | 410 | ||
411 | p += kFileHeaderSize; | 411 | p += kFileHeaderSize; |
412 | size -= kFileHeaderSize; | 412 | size -= kFileHeaderSize; |
@@ -941,31 +941,32 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) | |||
941 | return S_OK; | 941 | return S_OK; |
942 | } | 942 | } |
943 | 943 | ||
944 | static bool RarTimeToFileTime(const CRarTime &rarTime, FILETIME &result) | 944 | static bool RarTimeToFileTime(const CRarTime &rarTime, FILETIME &ft) |
945 | { | 945 | { |
946 | if (!NTime::DosTimeToFileTime(rarTime.DosTime, result)) | 946 | if (!NTime::DosTime_To_FileTime(rarTime.DosTime, ft)) |
947 | return false; | 947 | return false; |
948 | UInt64 value = (((UInt64)result.dwHighDateTime) << 32) + result.dwLowDateTime; | 948 | UInt64 v = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; |
949 | value += (UInt64)rarTime.LowSecond * 10000000; | 949 | v += (UInt32)rarTime.LowSecond * 10000000; |
950 | value += ((UInt64)rarTime.SubTime[2] << 16) + | 950 | v += |
951 | ((UInt64)rarTime.SubTime[1] << 8) + | 951 | ((UInt32)rarTime.SubTime[2] << 16) + |
952 | ((UInt64)rarTime.SubTime[0]); | 952 | ((UInt32)rarTime.SubTime[1] << 8) + |
953 | result.dwLowDateTime = (DWORD)value; | 953 | ((UInt32)rarTime.SubTime[0]); |
954 | result.dwHighDateTime = DWORD(value >> 32); | 954 | ft.dwLowDateTime = (DWORD)v; |
955 | ft.dwHighDateTime = (DWORD)(v >> 32); | ||
955 | return true; | 956 | return true; |
956 | } | 957 | } |
957 | 958 | ||
958 | static void RarTimeToProp(const CRarTime &rarTime, NCOM::CPropVariant &prop) | 959 | static void RarTimeToProp(const CRarTime &rarTime, NCOM::CPropVariant &prop) |
959 | { | 960 | { |
960 | FILETIME localFileTime, utcFileTime; | 961 | FILETIME localFileTime, utc; |
961 | if (RarTimeToFileTime(rarTime, localFileTime)) | 962 | if (RarTimeToFileTime(rarTime, localFileTime) |
962 | { | 963 | && LocalFileTimeToFileTime(&localFileTime, &utc)) |
963 | if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime)) | 964 | prop.SetAsTimeFrom_FT_Prec(utc, k_PropVar_TimePrec_100ns); |
964 | utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0; | 965 | /* |
965 | } | ||
966 | else | 966 | else |
967 | utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0; | 967 | utc.dwHighDateTime = utc.dwLowDateTime = 0; |
968 | prop = utcFileTime; | 968 | // prop.SetAsTimeFrom_FT_Prec(utc, k_PropVar_TimePrec_100ns); |
969 | */ | ||
969 | } | 970 | } |
970 | 971 | ||
971 | STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) | 972 | STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) |
diff --git a/CPP/7zip/Archive/Rar/RarVol.h b/CPP/7zip/Archive/Rar/RarVol.h index 9626433..2f5bbd3 100644 --- a/CPP/7zip/Archive/Rar/RarVol.h +++ b/CPP/7zip/Archive/Rar/RarVol.h | |||
@@ -52,7 +52,7 @@ public: | |||
52 | ext.IsEqualTo_Ascii_NoCase("r01")) | 52 | ext.IsEqualTo_Ascii_NoCase("r01")) |
53 | { | 53 | { |
54 | _changed = ext; | 54 | _changed = ext; |
55 | _before = name.Left(dotPos + 1); | 55 | _before.SetFrom(name.Ptr(), dotPos + 1); |
56 | return true; | 56 | return true; |
57 | } | 57 | } |
58 | } | 58 | } |
@@ -60,16 +60,23 @@ public: | |||
60 | 60 | ||
61 | if (newStyle) | 61 | if (newStyle) |
62 | { | 62 | { |
63 | unsigned i = base.Len(); | 63 | unsigned k = base.Len(); |
64 | |||
65 | for (; k != 0; k--) | ||
66 | if (IsDigit(base[k - 1])) | ||
67 | break; | ||
68 | |||
69 | unsigned i = k; | ||
64 | 70 | ||
65 | for (; i != 0; i--) | 71 | for (; i != 0; i--) |
66 | if (!IsDigit(base[i - 1])) | 72 | if (!IsDigit(base[i - 1])) |
67 | break; | 73 | break; |
68 | 74 | ||
69 | if (i != base.Len()) | 75 | if (i != k) |
70 | { | 76 | { |
71 | _before = base.Left(i); | 77 | _before.SetFrom(base.Ptr(), i); |
72 | _changed = base.Ptr(i); | 78 | _changed.SetFrom(base.Ptr(i), k - i); |
79 | _after.Insert(0, base.Ptr(k)); | ||
73 | return true; | 80 | return true; |
74 | } | 81 | } |
75 | } | 82 | } |
diff --git a/CPP/7zip/Archive/RpmHandler.cpp b/CPP/7zip/Archive/RpmHandler.cpp index e0ec28c..366f8ef 100644 --- a/CPP/7zip/Archive/RpmHandler.cpp +++ b/CPP/7zip/Archive/RpmHandler.cpp | |||
@@ -215,11 +215,7 @@ class CHandler: public CHandlerCont | |||
215 | void SetTime(NCOM::CPropVariant &prop) const | 215 | void SetTime(NCOM::CPropVariant &prop) const |
216 | { | 216 | { |
217 | if (_time_Defined && _buildTime != 0) | 217 | if (_time_Defined && _buildTime != 0) |
218 | { | 218 | PropVariant_SetFrom_UnixTime(prop, _buildTime); |
219 | FILETIME ft; | ||
220 | NTime::UnixTimeToFileTime(_buildTime, ft); | ||
221 | prop = ft; | ||
222 | } | ||
223 | } | 219 | } |
224 | 220 | ||
225 | void SetStringProp(const AString &s, NCOM::CPropVariant &prop) const | 221 | void SetStringProp(const AString &s, NCOM::CPropVariant &prop) const |
diff --git a/CPP/7zip/Archive/SparseHandler.cpp b/CPP/7zip/Archive/SparseHandler.cpp new file mode 100644 index 0000000..47e3ed8 --- /dev/null +++ b/CPP/7zip/Archive/SparseHandler.cpp | |||
@@ -0,0 +1,548 @@ | |||
1 | // SparseHandler.cpp | ||
2 | |||
3 | #include "StdAfx.h" | ||
4 | |||
5 | #include "../../../C/CpuArch.h" | ||
6 | |||
7 | #include "../../Common/ComTry.h" | ||
8 | |||
9 | #include "../../Windows/PropVariantUtils.h" | ||
10 | |||
11 | #include "../Common/RegisterArc.h" | ||
12 | #include "../Common/StreamUtils.h" | ||
13 | |||
14 | #include "HandlerCont.h" | ||
15 | |||
16 | #define Get16(p) GetUi16(p) | ||
17 | #define Get32(p) GetUi32(p) | ||
18 | |||
19 | #define G16(_offs_, dest) dest = Get16(p + (_offs_)); | ||
20 | #define G32(_offs_, dest) dest = Get32(p + (_offs_)); | ||
21 | |||
22 | using namespace NWindows; | ||
23 | |||
24 | namespace NArchive { | ||
25 | namespace NSparse { | ||
26 | |||
27 | // libsparse and simg2img | ||
28 | |||
29 | struct CHeader | ||
30 | { | ||
31 | // UInt32 magic; /* 0xed26ff3a */ | ||
32 | // UInt16 major_version; /* (0x1) - reject images with higher major versions */ | ||
33 | // UInt16 minor_version; /* (0x0) - allow images with higer minor versions */ | ||
34 | UInt16 file_hdr_sz; /* 28 bytes for first revision of the file format */ | ||
35 | UInt16 chunk_hdr_sz; /* 12 bytes for first revision of the file format */ | ||
36 | UInt32 BlockSize; /* block size in bytes, must be a multiple of 4 (4096) */ | ||
37 | UInt32 NumBlocks; /* total blocks in the non-sparse output image */ | ||
38 | UInt32 NumChunks; /* total chunks in the sparse input image */ | ||
39 | // UInt32 image_checksum; /* CRC32 checksum of the original data, counting "don't care" as 0. */ | ||
40 | |||
41 | void Parse(const Byte *p) | ||
42 | { | ||
43 | // G16 (4, major_version); | ||
44 | // G16 (6, minor_version); | ||
45 | G16 (8, file_hdr_sz); | ||
46 | G16 (10, chunk_hdr_sz); | ||
47 | G32 (12, BlockSize); | ||
48 | G32 (16, NumBlocks); | ||
49 | G32 (20, NumChunks); | ||
50 | // G32 (24, image_checksum); | ||
51 | } | ||
52 | }; | ||
53 | |||
54 | // #define SPARSE_HEADER_MAGIC 0xed26ff3a | ||
55 | |||
56 | #define CHUNK_TYPE_RAW 0xCAC1 | ||
57 | #define CHUNK_TYPE_FILL 0xCAC2 | ||
58 | #define CHUNK_TYPE_DONT_CARE 0xCAC3 | ||
59 | #define CHUNK_TYPE_CRC32 0xCAC4 | ||
60 | |||
61 | #define MY__CHUNK_TYPE_FILL 0 | ||
62 | #define MY__CHUNK_TYPE_DONT_CARE 1 | ||
63 | #define MY__CHUNK_TYPE_RAW__START 2 | ||
64 | |||
65 | static const char * const g_Methods[] = | ||
66 | { | ||
67 | "RAW" | ||
68 | , "FILL" | ||
69 | , "SPARSE" // "DONT_CARE" | ||
70 | , "CRC32" | ||
71 | }; | ||
72 | |||
73 | static const unsigned kFillSize = 4; | ||
74 | |||
75 | struct CChunk | ||
76 | { | ||
77 | UInt32 VirtBlock; | ||
78 | Byte Fill [kFillSize]; | ||
79 | UInt64 PhyOffset; | ||
80 | }; | ||
81 | |||
82 | static const Byte k_Signature[] = { 0x3a, 0xff, 0x26, 0xed, 1, 0 }; | ||
83 | |||
84 | |||
85 | class CHandler: public CHandlerImg | ||
86 | { | ||
87 | CRecordVector<CChunk> Chunks; | ||
88 | UInt64 _virtSize_fromChunks; | ||
89 | unsigned _blockSizeLog; | ||
90 | UInt32 _chunkIndexPrev; | ||
91 | |||
92 | UInt64 _packSizeProcessed; | ||
93 | UInt64 _phySize; | ||
94 | UInt32 _methodFlags; | ||
95 | bool _isArc; | ||
96 | bool _headersError; | ||
97 | bool _unexpectedEnd; | ||
98 | // bool _unsupported; | ||
99 | UInt32 NumChunks; // from header | ||
100 | |||
101 | HRESULT Seek2(UInt64 offset) | ||
102 | { | ||
103 | _posInArc = offset; | ||
104 | return Stream->Seek(offset, STREAM_SEEK_SET, NULL); | ||
105 | } | ||
106 | |||
107 | void InitSeekPositions() | ||
108 | { | ||
109 | /* (_virtPos) and (_posInArc) is used only in Read() (that calls ReadPhy()). | ||
110 | So we must reset these variables before first call of Read() */ | ||
111 | Reset_VirtPos(); | ||
112 | Reset_PosInArc(); | ||
113 | _chunkIndexPrev = 0; | ||
114 | _packSizeProcessed = 0; | ||
115 | } | ||
116 | |||
117 | // virtual functions | ||
118 | bool Init_PackSizeProcessed() | ||
119 | { | ||
120 | _packSizeProcessed = 0; | ||
121 | return true; | ||
122 | } | ||
123 | bool Get_PackSizeProcessed(UInt64 &size) | ||
124 | { | ||
125 | size = _packSizeProcessed; | ||
126 | return true; | ||
127 | } | ||
128 | |||
129 | HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback); | ||
130 | HRESULT ReadPhy(UInt64 offset, void *data, UInt32 size, UInt32 &processed); | ||
131 | |||
132 | public: | ||
133 | INTERFACE_IInArchive_Img(;) | ||
134 | |||
135 | STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); | ||
136 | STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); | ||
137 | }; | ||
138 | |||
139 | |||
140 | |||
141 | static const Byte kProps[] = | ||
142 | { | ||
143 | kpidSize, | ||
144 | kpidPackSize | ||
145 | }; | ||
146 | |||
147 | static const Byte kArcProps[] = | ||
148 | { | ||
149 | kpidClusterSize, | ||
150 | kpidNumBlocks, | ||
151 | kpidMethod | ||
152 | }; | ||
153 | |||
154 | IMP_IInArchive_Props | ||
155 | IMP_IInArchive_ArcProps | ||
156 | |||
157 | STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | ||
158 | { | ||
159 | COM_TRY_BEGIN | ||
160 | NCOM::CPropVariant prop; | ||
161 | |||
162 | switch (propID) | ||
163 | { | ||
164 | case kpidMainSubfile: prop = (UInt32)0; break; | ||
165 | case kpidClusterSize: prop = (UInt32)((UInt32)1 << _blockSizeLog); break; | ||
166 | case kpidNumBlocks: prop = (UInt32)NumChunks; break; | ||
167 | case kpidPhySize: if (_phySize != 0) prop = _phySize; break; | ||
168 | |||
169 | case kpidMethod: | ||
170 | { | ||
171 | FLAGS_TO_PROP(g_Methods, _methodFlags, prop); | ||
172 | break; | ||
173 | } | ||
174 | |||
175 | case kpidErrorFlags: | ||
176 | { | ||
177 | UInt32 v = 0; | ||
178 | if (!_isArc) v |= kpv_ErrorFlags_IsNotArc; | ||
179 | if (_headersError) v |= kpv_ErrorFlags_HeadersError; | ||
180 | if (_unexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd; | ||
181 | // if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod; | ||
182 | if (!Stream && v == 0 && _isArc) | ||
183 | v = kpv_ErrorFlags_HeadersError; | ||
184 | if (v != 0) | ||
185 | prop = v; | ||
186 | break; | ||
187 | } | ||
188 | } | ||
189 | |||
190 | prop.Detach(value); | ||
191 | return S_OK; | ||
192 | COM_TRY_END | ||
193 | } | ||
194 | |||
195 | |||
196 | STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) | ||
197 | { | ||
198 | COM_TRY_BEGIN | ||
199 | NCOM::CPropVariant prop; | ||
200 | |||
201 | switch (propID) | ||
202 | { | ||
203 | case kpidSize: prop = _size; break; | ||
204 | case kpidPackSize: prop = _phySize; break; | ||
205 | case kpidExtension: prop = (_imgExt ? _imgExt : "img"); break; | ||
206 | } | ||
207 | |||
208 | prop.Detach(value); | ||
209 | return S_OK; | ||
210 | COM_TRY_END | ||
211 | } | ||
212 | |||
213 | |||
214 | static unsigned GetLogSize(UInt32 size) | ||
215 | { | ||
216 | unsigned k; | ||
217 | for (k = 0; k < 32; k++) | ||
218 | if (((UInt32)1 << k) == size) | ||
219 | return k; | ||
220 | return k; | ||
221 | } | ||
222 | |||
223 | |||
224 | HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) | ||
225 | { | ||
226 | const unsigned kHeaderSize = 28; | ||
227 | const unsigned kChunkHeaderSize = 12; | ||
228 | CHeader h; | ||
229 | { | ||
230 | Byte buf[kHeaderSize]; | ||
231 | RINOK(ReadStream_FALSE(stream, buf, kHeaderSize)); | ||
232 | if (memcmp(buf, k_Signature, 6) != 0) | ||
233 | return S_FALSE; | ||
234 | h.Parse(buf); | ||
235 | } | ||
236 | |||
237 | if (h.file_hdr_sz != kHeaderSize || | ||
238 | h.chunk_hdr_sz != kChunkHeaderSize) | ||
239 | return S_FALSE; | ||
240 | |||
241 | NumChunks = h.NumChunks; | ||
242 | |||
243 | const unsigned logSize = GetLogSize(h.BlockSize); | ||
244 | if (logSize < 2 || logSize >= 32) | ||
245 | return S_FALSE; | ||
246 | _blockSizeLog = logSize; | ||
247 | |||
248 | _size = (UInt64)h.NumBlocks << logSize; | ||
249 | |||
250 | if (h.NumChunks >= (UInt32)(Int32)-2) // it's our limit | ||
251 | return S_FALSE; | ||
252 | |||
253 | _isArc = true; | ||
254 | Chunks.Reserve(h.NumChunks + 1); | ||
255 | UInt64 offset = kHeaderSize; | ||
256 | UInt32 virtBlock = 0; | ||
257 | UInt32 i; | ||
258 | |||
259 | for (i = 0; i < h.NumChunks; i++) | ||
260 | { | ||
261 | { | ||
262 | const UInt32 mask = ((UInt32)1 << 16) - 1; | ||
263 | if ((i & mask) == mask && openCallback) | ||
264 | { | ||
265 | RINOK(openCallback->SetCompleted(NULL, &offset)); | ||
266 | } | ||
267 | } | ||
268 | Byte buf[kChunkHeaderSize]; | ||
269 | { | ||
270 | size_t processed = kChunkHeaderSize; | ||
271 | RINOK(ReadStream(stream, buf, &processed)); | ||
272 | if (kChunkHeaderSize != processed) | ||
273 | { | ||
274 | offset += kChunkHeaderSize; | ||
275 | break; | ||
276 | } | ||
277 | } | ||
278 | const UInt32 type = Get32(&buf[0]); | ||
279 | const UInt32 numBlocks = Get32(&buf[4]); | ||
280 | UInt32 size = Get32(&buf[8]); | ||
281 | |||
282 | if (type < CHUNK_TYPE_RAW || | ||
283 | type > CHUNK_TYPE_CRC32) | ||
284 | return S_FALSE; | ||
285 | if (size < kChunkHeaderSize) | ||
286 | return S_FALSE; | ||
287 | CChunk c; | ||
288 | c.PhyOffset = offset + kChunkHeaderSize; | ||
289 | c.VirtBlock = virtBlock; | ||
290 | offset += size; | ||
291 | size -= kChunkHeaderSize; | ||
292 | _methodFlags |= ((UInt32)1 << (type - CHUNK_TYPE_RAW)); | ||
293 | |||
294 | if (numBlocks > h.NumBlocks - virtBlock) | ||
295 | return S_FALSE; | ||
296 | |||
297 | if (type == CHUNK_TYPE_CRC32) | ||
298 | { | ||
299 | // crc chunk must be last chunk (i == h.NumChunks -1); | ||
300 | if (size != kFillSize || numBlocks != 0) | ||
301 | return S_FALSE; | ||
302 | { | ||
303 | size_t processed = kFillSize; | ||
304 | RINOK(ReadStream(stream, c.Fill, &processed)); | ||
305 | if (kFillSize != processed) | ||
306 | break; | ||
307 | } | ||
308 | continue; | ||
309 | } | ||
310 | // else | ||
311 | { | ||
312 | if (numBlocks == 0) | ||
313 | return S_FALSE; | ||
314 | |||
315 | if (type == CHUNK_TYPE_DONT_CARE) | ||
316 | { | ||
317 | if (size != 0) | ||
318 | return S_FALSE; | ||
319 | c.PhyOffset = MY__CHUNK_TYPE_DONT_CARE; | ||
320 | } | ||
321 | else if (type == CHUNK_TYPE_FILL) | ||
322 | { | ||
323 | if (size != kFillSize) | ||
324 | return S_FALSE; | ||
325 | c.PhyOffset = MY__CHUNK_TYPE_FILL; | ||
326 | size_t processed = kFillSize; | ||
327 | RINOK(ReadStream(stream, c.Fill, &processed)); | ||
328 | if (kFillSize != processed) | ||
329 | break; | ||
330 | } | ||
331 | else if (type == CHUNK_TYPE_RAW) | ||
332 | { | ||
333 | /* Here we require (size == virtSize). | ||
334 | Probably original decoder also requires it. | ||
335 | But maybe size of last chunk can be non-aligned with blockSize ? */ | ||
336 | const UInt32 virtSize = (numBlocks << _blockSizeLog); | ||
337 | if (size != virtSize || numBlocks != (virtSize >> _blockSizeLog)) | ||
338 | return S_FALSE; | ||
339 | } | ||
340 | else | ||
341 | return S_FALSE; | ||
342 | |||
343 | virtBlock += numBlocks; | ||
344 | Chunks.AddInReserved(c); | ||
345 | if (type == CHUNK_TYPE_RAW) | ||
346 | RINOK(stream->Seek(offset, STREAM_SEEK_SET, NULL)); | ||
347 | } | ||
348 | } | ||
349 | |||
350 | if (i != h.NumChunks) | ||
351 | _unexpectedEnd = true; | ||
352 | else if (virtBlock != h.NumBlocks) | ||
353 | _headersError = true; | ||
354 | |||
355 | _phySize = offset; | ||
356 | |||
357 | { | ||
358 | CChunk c; | ||
359 | c.VirtBlock = virtBlock; | ||
360 | c.PhyOffset = offset; | ||
361 | Chunks.AddInReserved(c); | ||
362 | } | ||
363 | _virtSize_fromChunks = (UInt64)virtBlock << _blockSizeLog; | ||
364 | |||
365 | Stream = stream; | ||
366 | return S_OK; | ||
367 | } | ||
368 | |||
369 | |||
370 | STDMETHODIMP CHandler::Close() | ||
371 | { | ||
372 | Chunks.Clear(); | ||
373 | _isArc = false; | ||
374 | _virtSize_fromChunks = 0; | ||
375 | // _unsupported = false; | ||
376 | _headersError = false; | ||
377 | _unexpectedEnd = false; | ||
378 | _phySize = 0; | ||
379 | _methodFlags = 0; | ||
380 | |||
381 | _chunkIndexPrev = 0; | ||
382 | _packSizeProcessed = 0; | ||
383 | |||
384 | // CHandlerImg: | ||
385 | Clear_HandlerImg_Vars(); | ||
386 | Stream.Release(); | ||
387 | return S_OK; | ||
388 | } | ||
389 | |||
390 | |||
391 | STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream) | ||
392 | { | ||
393 | COM_TRY_BEGIN | ||
394 | *stream = NULL; | ||
395 | if (Chunks.Size() < 1) | ||
396 | return S_FALSE; | ||
397 | if (Chunks.Size() < 2 && _virtSize_fromChunks != 0) | ||
398 | return S_FALSE; | ||
399 | // if (_unsupported) return S_FALSE; | ||
400 | InitSeekPositions(); | ||
401 | CMyComPtr<ISequentialInStream> streamTemp = this; | ||
402 | *stream = streamTemp.Detach(); | ||
403 | return S_OK; | ||
404 | COM_TRY_END | ||
405 | } | ||
406 | |||
407 | |||
408 | |||
409 | HRESULT CHandler::ReadPhy(UInt64 offset, void *data, UInt32 size, UInt32 &processed) | ||
410 | { | ||
411 | processed = 0; | ||
412 | if (offset > _phySize || offset + size > _phySize) | ||
413 | { | ||
414 | // we don't expect these cases, if (_phySize) was set correctly. | ||
415 | return S_FALSE; | ||
416 | } | ||
417 | if (offset != _posInArc) | ||
418 | { | ||
419 | const HRESULT res = Seek2(offset); | ||
420 | if (res != S_OK) | ||
421 | { | ||
422 | Reset_PosInArc(); // we don't trust seek_pos in case of error | ||
423 | return res; | ||
424 | } | ||
425 | } | ||
426 | { | ||
427 | size_t size2 = size; | ||
428 | const HRESULT res = ReadStream(Stream, data, &size2); | ||
429 | processed = (UInt32)size2; | ||
430 | _packSizeProcessed += size2; | ||
431 | _posInArc += size2; | ||
432 | if (res != S_OK) | ||
433 | Reset_PosInArc(); // we don't trust seek_pos in case of reading error | ||
434 | return res; | ||
435 | } | ||
436 | } | ||
437 | |||
438 | |||
439 | STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) | ||
440 | { | ||
441 | if (processedSize) | ||
442 | *processedSize = 0; | ||
443 | // const unsigned kLimit = (1 << 16) + 1; if (size > kLimit) size = kLimit; // for debug | ||
444 | if (_virtPos >= _virtSize_fromChunks) | ||
445 | return S_OK; | ||
446 | { | ||
447 | const UInt64 rem = _virtSize_fromChunks - _virtPos; | ||
448 | if (size > rem) | ||
449 | size = (UInt32)rem; | ||
450 | if (size == 0) | ||
451 | return S_OK; | ||
452 | } | ||
453 | |||
454 | UInt32 chunkIndex = _chunkIndexPrev; | ||
455 | if (chunkIndex + 1 >= Chunks.Size()) | ||
456 | return S_FALSE; | ||
457 | { | ||
458 | const UInt32 blockIndex = (UInt32)(_virtPos >> _blockSizeLog); | ||
459 | if (blockIndex < Chunks[chunkIndex ].VirtBlock || | ||
460 | blockIndex >= Chunks[chunkIndex + 1].VirtBlock) | ||
461 | { | ||
462 | unsigned left = 0, right = Chunks.Size() - 1; | ||
463 | for (;;) | ||
464 | { | ||
465 | const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); | ||
466 | if (mid == left) | ||
467 | break; | ||
468 | if (blockIndex < Chunks[mid].VirtBlock) | ||
469 | right = mid; | ||
470 | else | ||
471 | left = mid; | ||
472 | } | ||
473 | chunkIndex = left; | ||
474 | _chunkIndexPrev = chunkIndex; | ||
475 | } | ||
476 | } | ||
477 | |||
478 | const CChunk &c = Chunks[chunkIndex]; | ||
479 | const UInt64 offset = _virtPos - ((UInt64)c.VirtBlock << _blockSizeLog); | ||
480 | { | ||
481 | const UInt32 numBlocks = Chunks[chunkIndex + 1].VirtBlock - c.VirtBlock; | ||
482 | const UInt64 rem = ((UInt64)numBlocks << _blockSizeLog) - offset; | ||
483 | if (size > rem) | ||
484 | size = (UInt32)rem; | ||
485 | } | ||
486 | |||
487 | const UInt64 phyOffset = c.PhyOffset; | ||
488 | |||
489 | if (phyOffset >= MY__CHUNK_TYPE_RAW__START) | ||
490 | { | ||
491 | UInt32 processed = 0; | ||
492 | const HRESULT res = ReadPhy(phyOffset + offset, data, size, processed); | ||
493 | if (processedSize) | ||
494 | *processedSize = processed; | ||
495 | _virtPos += processed; | ||
496 | return res; | ||
497 | } | ||
498 | |||
499 | unsigned b = 0; | ||
500 | |||
501 | if (phyOffset == MY__CHUNK_TYPE_FILL) | ||
502 | { | ||
503 | const Byte b0 = c.Fill [0]; | ||
504 | const Byte b1 = c.Fill [1]; | ||
505 | const Byte b2 = c.Fill [2]; | ||
506 | const Byte b3 = c.Fill [3]; | ||
507 | if (b0 != b1 || | ||
508 | b0 != b2 || | ||
509 | b0 != b3) | ||
510 | { | ||
511 | if (processedSize) | ||
512 | *processedSize = size; | ||
513 | _virtPos += size; | ||
514 | Byte *dest = (Byte *)data; | ||
515 | while (size >= 4) | ||
516 | { | ||
517 | dest[0] = b0; | ||
518 | dest[1] = b1; | ||
519 | dest[2] = b2; | ||
520 | dest[3] = b3; | ||
521 | dest += 4; | ||
522 | size -= 4; | ||
523 | } | ||
524 | if (size > 0) dest[0] = b0; | ||
525 | if (size > 1) dest[1] = b1; | ||
526 | if (size > 2) dest[2] = b2; | ||
527 | return S_OK; | ||
528 | } | ||
529 | b = b0; | ||
530 | } | ||
531 | else if (phyOffset != MY__CHUNK_TYPE_DONT_CARE) | ||
532 | return S_FALSE; | ||
533 | |||
534 | memset(data, b, size); | ||
535 | _virtPos += size; | ||
536 | if (processedSize) | ||
537 | *processedSize = size; | ||
538 | return S_OK; | ||
539 | } | ||
540 | |||
541 | REGISTER_ARC_I( | ||
542 | "Sparse", "simg img", NULL, 0xc2, | ||
543 | k_Signature, | ||
544 | 0, | ||
545 | 0, | ||
546 | NULL) | ||
547 | |||
548 | }} | ||
diff --git a/CPP/7zip/Archive/SplitHandler.cpp b/CPP/7zip/Archive/SplitHandler.cpp index 6705aee..6bddfb8 100644 --- a/CPP/7zip/Archive/SplitHandler.cpp +++ b/CPP/7zip/Archive/SplitHandler.cpp | |||
@@ -162,7 +162,10 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) | |||
162 | numLetters++; | 162 | numLetters++; |
163 | } | 163 | } |
164 | } | 164 | } |
165 | else if (ext.Len() >= 2 && StringsAreEqual_Ascii(ext2.RightPtr(2), "01")) | 165 | else if (ext2.Len() >= 2 && ( |
166 | StringsAreEqual_Ascii(ext2.RightPtr(2), "01") | ||
167 | || StringsAreEqual_Ascii(ext2.RightPtr(2), "00") | ||
168 | )) | ||
166 | { | 169 | { |
167 | while (numLetters < ext2.Len()) | 170 | while (numLetters < ext2.Len()) |
168 | { | 171 | { |
@@ -170,7 +173,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) | |||
170 | break; | 173 | break; |
171 | numLetters++; | 174 | numLetters++; |
172 | } | 175 | } |
173 | if (numLetters != ext.Len()) | 176 | if (numLetters != ext2.Len()) |
174 | return S_FALSE; | 177 | return S_FALSE; |
175 | } | 178 | } |
176 | else | 179 | else |
diff --git a/CPP/7zip/Archive/SquashfsHandler.cpp b/CPP/7zip/Archive/SquashfsHandler.cpp index 74bc8fb..fe271bc 100644 --- a/CPP/7zip/Archive/SquashfsHandler.cpp +++ b/CPP/7zip/Archive/SquashfsHandler.cpp | |||
@@ -76,7 +76,7 @@ static const char * const k_Methods[] = | |||
76 | , "XZ" | 76 | , "XZ" |
77 | }; | 77 | }; |
78 | 78 | ||
79 | static const UInt32 kMetadataBlockSizeLog = 13; | 79 | static const unsigned kMetadataBlockSizeLog = 13; |
80 | static const UInt32 kMetadataBlockSize = (1 << kMetadataBlockSizeLog); | 80 | static const UInt32 kMetadataBlockSize = (1 << kMetadataBlockSizeLog); |
81 | 81 | ||
82 | enum | 82 | enum |
@@ -408,7 +408,7 @@ UInt32 CNode::Parse1(const Byte *p, UInt32 size, const CHeader &_h) | |||
408 | 408 | ||
409 | UInt32 CNode::Parse2(const Byte *p, UInt32 size, const CHeader &_h) | 409 | UInt32 CNode::Parse2(const Byte *p, UInt32 size, const CHeader &_h) |
410 | { | 410 | { |
411 | bool be = _h.be; | 411 | const bool be = _h.be; |
412 | if (size < 4) | 412 | if (size < 4) |
413 | return 0; | 413 | return 0; |
414 | { | 414 | { |
@@ -541,7 +541,7 @@ UInt32 CNode::Parse2(const Byte *p, UInt32 size, const CHeader &_h) | |||
541 | 541 | ||
542 | UInt32 CNode::Parse3(const Byte *p, UInt32 size, const CHeader &_h) | 542 | UInt32 CNode::Parse3(const Byte *p, UInt32 size, const CHeader &_h) |
543 | { | 543 | { |
544 | bool be = _h.be; | 544 | const bool be = _h.be; |
545 | if (size < 12) | 545 | if (size < 12) |
546 | return 0; | 546 | return 0; |
547 | 547 | ||
@@ -843,8 +843,8 @@ class CHandler: | |||
843 | CData _inodesData; | 843 | CData _inodesData; |
844 | CData _dirs; | 844 | CData _dirs; |
845 | CRecordVector<CFrag> _frags; | 845 | CRecordVector<CFrag> _frags; |
846 | // CByteBuffer _uids; | 846 | CByteBuffer _uids; |
847 | // CByteBuffer _gids; | 847 | CByteBuffer _gids; |
848 | CHeader _h; | 848 | CHeader _h; |
849 | bool _noPropsLZMA; | 849 | bool _noPropsLZMA; |
850 | bool _needCheckLzma; | 850 | bool _needCheckLzma; |
@@ -891,14 +891,20 @@ class CHandler: | |||
891 | _cachedUnpackBlockSize = 0; | 891 | _cachedUnpackBlockSize = 0; |
892 | } | 892 | } |
893 | 893 | ||
894 | HRESULT Seek2(UInt64 offset) | ||
895 | { | ||
896 | return _stream->Seek(offset, STREAM_SEEK_SET, NULL); | ||
897 | } | ||
898 | |||
894 | HRESULT Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool *outBufWasWritten, UInt32 *outBufWasWrittenSize, | 899 | HRESULT Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool *outBufWasWritten, UInt32 *outBufWasWrittenSize, |
895 | UInt32 inSize, UInt32 outSizeMax); | 900 | UInt32 inSize, UInt32 outSizeMax); |
896 | HRESULT ReadMetadataBlock(UInt32 &packSize); | 901 | HRESULT ReadMetadataBlock(UInt32 &packSize); |
902 | HRESULT ReadMetadataBlock2(); | ||
897 | HRESULT ReadData(CData &data, UInt64 start, UInt64 end); | 903 | HRESULT ReadData(CData &data, UInt64 start, UInt64 end); |
898 | 904 | ||
899 | HRESULT OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned level, int &nodeIndex); | 905 | HRESULT OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned level, int &nodeIndex); |
900 | HRESULT ScanInodes(UInt64 ptr); | 906 | HRESULT ScanInodes(UInt64 ptr); |
901 | // HRESULT ReadUids(UInt64 start, UInt32 num, CByteBuffer &ids); | 907 | HRESULT ReadUids(UInt64 start, UInt32 num, CByteBuffer &ids); |
902 | HRESULT Open2(IInStream *inStream); | 908 | HRESULT Open2(IInStream *inStream); |
903 | AString GetPath(int index) const; | 909 | AString GetPath(int index) const; |
904 | bool GetPackSize(int index, UInt64 &res, bool fillOffsets); | 910 | bool GetPackSize(int index, UInt64 &res, bool fillOffsets); |
@@ -938,9 +944,9 @@ static const Byte kProps[] = | |||
938 | kpidSize, | 944 | kpidSize, |
939 | kpidPackSize, | 945 | kpidPackSize, |
940 | kpidMTime, | 946 | kpidMTime, |
941 | kpidPosixAttrib | 947 | kpidPosixAttrib, |
942 | // kpidUser, | 948 | kpidUserId, |
943 | // kpidGroup, | 949 | kpidGroupId |
944 | // kpidLinks, | 950 | // kpidLinks, |
945 | // kpidOffset | 951 | // kpidOffset |
946 | }; | 952 | }; |
@@ -1280,14 +1286,14 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool | |||
1280 | HRESULT CHandler::ReadMetadataBlock(UInt32 &packSize) | 1286 | HRESULT CHandler::ReadMetadataBlock(UInt32 &packSize) |
1281 | { | 1287 | { |
1282 | Byte temp[3]; | 1288 | Byte temp[3]; |
1283 | unsigned offset = _h.NeedCheckData() ? 3 : 2; | 1289 | const unsigned offset = _h.NeedCheckData() ? 3 : 2; |
1284 | if (offset > packSize) | 1290 | if (offset > packSize) |
1285 | return S_FALSE; | 1291 | return S_FALSE; |
1286 | RINOK(ReadStream_FALSE(_stream, temp, offset)); | 1292 | RINOK(ReadStream_FALSE(_stream, temp, offset)); |
1287 | // if (NeedCheckData && Major < 4) checkByte must be = 0xFF | 1293 | // if (NeedCheckData && Major < 4) checkByte must be = 0xFF |
1288 | bool be = _h.be; | 1294 | const bool be = _h.be; |
1289 | UInt32 size = Get16(temp); | 1295 | UInt32 size = Get16(temp); |
1290 | bool isCompressed = ((size & kNotCompressedBit16) == 0); | 1296 | const bool isCompressed = ((size & kNotCompressedBit16) == 0); |
1291 | if (size != kNotCompressedBit16) | 1297 | if (size != kNotCompressedBit16) |
1292 | size &= ~kNotCompressedBit16; | 1298 | size &= ~kNotCompressedBit16; |
1293 | 1299 | ||
@@ -1311,12 +1317,20 @@ HRESULT CHandler::ReadMetadataBlock(UInt32 &packSize) | |||
1311 | return S_OK; | 1317 | return S_OK; |
1312 | } | 1318 | } |
1313 | 1319 | ||
1320 | |||
1321 | HRESULT CHandler::ReadMetadataBlock2() | ||
1322 | { | ||
1323 | _dynOutStreamSpec->Init(); | ||
1324 | UInt32 packSize = kMetadataBlockSize + 3; // check it | ||
1325 | return ReadMetadataBlock(packSize); | ||
1326 | } | ||
1327 | |||
1314 | HRESULT CHandler::ReadData(CData &data, UInt64 start, UInt64 end) | 1328 | HRESULT CHandler::ReadData(CData &data, UInt64 start, UInt64 end) |
1315 | { | 1329 | { |
1316 | if (end < start || end - start >= ((UInt64)1 << 32)) | 1330 | if (end < start || end - start >= ((UInt64)1 << 32)) |
1317 | return S_FALSE; | 1331 | return S_FALSE; |
1318 | const UInt32 size = (UInt32)(end - start); | 1332 | const UInt32 size = (UInt32)(end - start); |
1319 | RINOK(_stream->Seek(start, STREAM_SEEK_SET, NULL)); | 1333 | RINOK(Seek2(start)); |
1320 | _dynOutStreamSpec->Init(); | 1334 | _dynOutStreamSpec->Init(); |
1321 | UInt32 packPos = 0; | 1335 | UInt32 packPos = 0; |
1322 | while (packPos != size) | 1336 | while (packPos != size) |
@@ -1395,7 +1409,7 @@ HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned | |||
1395 | CRecordVector<CTempItem> tempItems; | 1409 | CRecordVector<CTempItem> tempItems; |
1396 | while (rem != 0) | 1410 | while (rem != 0) |
1397 | { | 1411 | { |
1398 | bool be = _h.be; | 1412 | const bool be = _h.be; |
1399 | UInt32 count; | 1413 | UInt32 count; |
1400 | CTempItem tempItem; | 1414 | CTempItem tempItem; |
1401 | if (_h.Major <= 2) | 1415 | if (_h.Major <= 2) |
@@ -1519,15 +1533,15 @@ HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned | |||
1519 | return S_OK; | 1533 | return S_OK; |
1520 | } | 1534 | } |
1521 | 1535 | ||
1522 | /* | ||
1523 | HRESULT CHandler::ReadUids(UInt64 start, UInt32 num, CByteBuffer &ids) | 1536 | HRESULT CHandler::ReadUids(UInt64 start, UInt32 num, CByteBuffer &ids) |
1524 | { | 1537 | { |
1525 | size_t size = num * 4; | 1538 | const size_t size = (size_t)num * 4; |
1526 | ids.SetCapacity(size); | 1539 | ids.Alloc(size); |
1527 | RINOK(_stream->Seek(start, STREAM_SEEK_SET, NULL)); | 1540 | if (num == 0) |
1541 | return S_OK; | ||
1542 | RINOK(Seek2(start)); | ||
1528 | return ReadStream_FALSE(_stream, ids, size); | 1543 | return ReadStream_FALSE(_stream, ids, size); |
1529 | } | 1544 | } |
1530 | */ | ||
1531 | 1545 | ||
1532 | HRESULT CHandler::Open2(IInStream *inStream) | 1546 | HRESULT CHandler::Open2(IInStream *inStream) |
1533 | { | 1547 | { |
@@ -1560,24 +1574,22 @@ HRESULT CHandler::Open2(IInStream *inStream) | |||
1560 | if (_h.NumFrags > kNumFilesMax) | 1574 | if (_h.NumFrags > kNumFilesMax) |
1561 | return S_FALSE; | 1575 | return S_FALSE; |
1562 | _frags.ClearAndReserve(_h.NumFrags); | 1576 | _frags.ClearAndReserve(_h.NumFrags); |
1563 | unsigned bigFrag = (_h.Major > 2); | 1577 | const unsigned bigFrag = (_h.Major > 2); |
1564 | 1578 | ||
1565 | unsigned fragPtrsInBlockLog = kMetadataBlockSizeLog - (3 + bigFrag); | 1579 | const unsigned fragPtrsInBlockLog = kMetadataBlockSizeLog - (3 + bigFrag); |
1566 | UInt32 numBlocks = (_h.NumFrags + (1 << fragPtrsInBlockLog) - 1) >> fragPtrsInBlockLog; | 1580 | const UInt32 numBlocks = (_h.NumFrags + (1 << fragPtrsInBlockLog) - 1) >> fragPtrsInBlockLog; |
1567 | size_t numBlocksBytes = (size_t)numBlocks << (2 + bigFrag); | 1581 | const size_t numBlocksBytes = (size_t)numBlocks << (2 + bigFrag); |
1568 | CByteBuffer data(numBlocksBytes); | 1582 | CByteBuffer data(numBlocksBytes); |
1569 | RINOK(inStream->Seek(_h.FragTable, STREAM_SEEK_SET, NULL)); | 1583 | RINOK(Seek2(_h.FragTable)); |
1570 | RINOK(ReadStream_FALSE(inStream, data, numBlocksBytes)); | 1584 | RINOK(ReadStream_FALSE(inStream, data, numBlocksBytes)); |
1571 | bool be = _h.be; | 1585 | const bool be = _h.be; |
1572 | 1586 | ||
1573 | for (UInt32 i = 0; i < numBlocks; i++) | 1587 | for (UInt32 i = 0; i < numBlocks; i++) |
1574 | { | 1588 | { |
1575 | UInt64 offset = bigFrag ? Get64(data + i * 8) : Get32(data + i * 4); | 1589 | const UInt64 offset = bigFrag ? Get64(data + i * 8) : Get32(data + i * 4); |
1576 | RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); | 1590 | RINOK(Seek2(offset)); |
1577 | _dynOutStreamSpec->Init(); | 1591 | RINOK(ReadMetadataBlock2()); |
1578 | UInt32 packSize = kMetadataBlockSize + 3; | 1592 | const UInt32 unpackSize = (UInt32)_dynOutStreamSpec->GetSize(); |
1579 | RINOK(ReadMetadataBlock(packSize)); | ||
1580 | UInt32 unpackSize = (UInt32)_dynOutStreamSpec->GetSize(); | ||
1581 | if (unpackSize != kMetadataBlockSize) | 1593 | if (unpackSize != kMetadataBlockSize) |
1582 | if (i != numBlocks - 1 || unpackSize != ((_h.NumFrags << (3 + bigFrag)) & (kMetadataBlockSize - 1))) | 1594 | if (i != numBlocks - 1 || unpackSize != ((_h.NumFrags << (3 + bigFrag)) & (kMetadataBlockSize - 1))) |
1583 | return S_FALSE; | 1595 | return S_FALSE; |
@@ -1605,8 +1617,6 @@ HRESULT CHandler::Open2(IInStream *inStream) | |||
1605 | return S_FALSE; | 1617 | return S_FALSE; |
1606 | } | 1618 | } |
1607 | 1619 | ||
1608 | // RINOK(inStream->Seek(_h.InodeTable, STREAM_SEEK_SET, NULL)); | ||
1609 | |||
1610 | RINOK(ReadData(_inodesData, _h.InodeTable, _h.DirTable)); | 1620 | RINOK(ReadData(_inodesData, _h.InodeTable, _h.DirTable)); |
1611 | RINOK(ReadData(_dirs, _h.DirTable, _h.FragTable)); | 1621 | RINOK(ReadData(_dirs, _h.DirTable, _h.FragTable)); |
1612 | 1622 | ||
@@ -1655,7 +1665,6 @@ HRESULT CHandler::Open2(IInStream *inStream) | |||
1655 | int rootNodeIndex; | 1665 | int rootNodeIndex; |
1656 | RINOK(OpenDir(-1, (UInt32)absOffset, (UInt32)_h.RootInode & 0xFFFF, 0, rootNodeIndex)); | 1666 | RINOK(OpenDir(-1, (UInt32)absOffset, (UInt32)_h.RootInode & 0xFFFF, 0, rootNodeIndex)); |
1657 | 1667 | ||
1658 | /* | ||
1659 | if (_h.Major < 4) | 1668 | if (_h.Major < 4) |
1660 | { | 1669 | { |
1661 | RINOK(ReadUids(_h.UidTable, _h.NumUids, _uids)); | 1670 | RINOK(ReadUids(_h.UidTable, _h.NumUids, _uids)); |
@@ -1663,33 +1672,34 @@ HRESULT CHandler::Open2(IInStream *inStream) | |||
1663 | } | 1672 | } |
1664 | else | 1673 | else |
1665 | { | 1674 | { |
1666 | UInt32 size = _h.NumIDs * 4; | 1675 | const UInt32 size = (UInt32)_h.NumIDs * 4; |
1667 | _uids.SetCapacity(size); | 1676 | _uids.Alloc(size); |
1668 | 1677 | ||
1669 | UInt32 numBlocks = (size + kMetadataBlockSize - 1) / kMetadataBlockSize; | 1678 | const UInt32 numBlocks = (size + kMetadataBlockSize - 1) / kMetadataBlockSize; |
1670 | UInt32 numBlocksBytes = numBlocks << 3; | 1679 | const UInt32 numBlocksBytes = numBlocks << 3; |
1671 | CByteBuffer data; | 1680 | CByteBuffer data; |
1672 | data.SetCapacity(numBlocksBytes); | 1681 | data.Alloc(numBlocksBytes); |
1673 | RINOK(inStream->Seek(_h.UidTable, STREAM_SEEK_SET, NULL)); | 1682 | RINOK(Seek2(_h.UidTable)); |
1674 | RINOK(ReadStream_FALSE(inStream, data, numBlocksBytes)); | 1683 | RINOK(ReadStream_FALSE(inStream, data, numBlocksBytes)); |
1675 | 1684 | ||
1676 | for (UInt32 i = 0; i < numBlocks; i++) | 1685 | for (UInt32 i = 0; i < numBlocks; i++) |
1677 | { | 1686 | { |
1678 | UInt64 offset = GetUi64(data + i * 8); | 1687 | const UInt64 offset = GetUi64(data + i * 8); |
1679 | UInt32 unpackSize, packSize; | 1688 | RINOK(Seek2(offset)); |
1680 | RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); | 1689 | // RINOK(ReadMetadataBlock(NULL, _uids + kMetadataBlockSize * i, packSize, unpackSize)); |
1681 | RINOK(ReadMetadataBlock(NULL, _uids + kMetadataBlockSize * i, packSize, unpackSize)); | 1690 | RINOK(ReadMetadataBlock2()); |
1691 | const size_t unpackSize = _dynOutStreamSpec->GetSize(); | ||
1682 | if (unpackSize != kMetadataBlockSize) | 1692 | if (unpackSize != kMetadataBlockSize) |
1683 | if (i != numBlocks - 1 || unpackSize != (size & (kMetadataBlockSize - 1))) | 1693 | if (i != numBlocks - 1 || unpackSize != (size & (kMetadataBlockSize - 1))) |
1684 | return S_FALSE; | 1694 | return S_FALSE; |
1695 | memcpy(_uids + kMetadataBlockSize * i, _dynOutStreamSpec->GetBuffer(), unpackSize); | ||
1685 | } | 1696 | } |
1686 | } | 1697 | } |
1687 | */ | ||
1688 | 1698 | ||
1689 | { | 1699 | { |
1690 | const UInt32 alignSize = 1 << 12; | 1700 | const UInt32 alignSize = 1 << 12; |
1691 | Byte buf[alignSize]; | 1701 | Byte buf[alignSize]; |
1692 | RINOK(inStream->Seek(_h.Size, STREAM_SEEK_SET, NULL)); | 1702 | RINOK(Seek2(_h.Size)); |
1693 | UInt32 rem = (UInt32)(0 - _h.Size) & (alignSize - 1); | 1703 | UInt32 rem = (UInt32)(0 - _h.Size) & (alignSize - 1); |
1694 | _sizeCalculated = _h.Size; | 1704 | _sizeCalculated = _h.Size; |
1695 | if (rem != 0) | 1705 | if (rem != 0) |
@@ -1710,7 +1720,7 @@ AString CHandler::GetPath(int index) const | |||
1710 | { | 1720 | { |
1711 | unsigned len = 0; | 1721 | unsigned len = 0; |
1712 | int indexMem = index; | 1722 | int indexMem = index; |
1713 | bool be = _h.be; | 1723 | const bool be = _h.be; |
1714 | do | 1724 | do |
1715 | { | 1725 | { |
1716 | const CItem &item = _items[index]; | 1726 | const CItem &item = _items[index]; |
@@ -1804,9 +1814,9 @@ bool CHandler::GetPackSize(int index, UInt64 &totalPack, bool fillOffsets) | |||
1804 | totalPack = 0; | 1814 | totalPack = 0; |
1805 | const CItem &item = _items[index]; | 1815 | const CItem &item = _items[index]; |
1806 | const CNode &node = _nodes[item.Node]; | 1816 | const CNode &node = _nodes[item.Node]; |
1807 | UInt32 ptr = _nodesPos[item.Node]; | 1817 | const UInt32 ptr = _nodesPos[item.Node]; |
1808 | const Byte *p = _inodesData.Data + ptr; | 1818 | const Byte *p = _inodesData.Data + ptr; |
1809 | bool be = _h.be; | 1819 | const bool be = _h.be; |
1810 | 1820 | ||
1811 | UInt32 type = node.Type; | 1821 | UInt32 type = node.Type; |
1812 | UInt32 offset; | 1822 | UInt32 offset; |
@@ -1936,11 +1946,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | |||
1936 | case kpidBigEndian: prop = _h.be; break; | 1946 | case kpidBigEndian: prop = _h.be; break; |
1937 | case kpidCTime: | 1947 | case kpidCTime: |
1938 | if (_h.CTime != 0) | 1948 | if (_h.CTime != 0) |
1939 | { | 1949 | PropVariant_SetFrom_UnixTime(prop, _h.CTime); |
1940 | FILETIME ft; | ||
1941 | NWindows::NTime::UnixTimeToFileTime(_h.CTime, ft); | ||
1942 | prop = ft; | ||
1943 | } | ||
1944 | break; | 1950 | break; |
1945 | case kpidCharacts: FLAGS_TO_PROP(k_Flags, _h.Flags, prop); break; | 1951 | case kpidCharacts: FLAGS_TO_PROP(k_Flags, _h.Flags, prop); break; |
1946 | // case kpidNumBlocks: prop = _h.NumFrags; break; | 1952 | // case kpidNumBlocks: prop = _h.NumFrags; break; |
@@ -1979,8 +1985,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
1979 | NWindows::NCOM::CPropVariant prop; | 1985 | NWindows::NCOM::CPropVariant prop; |
1980 | const CItem &item = _items[index]; | 1986 | const CItem &item = _items[index]; |
1981 | const CNode &node = _nodes[item.Node]; | 1987 | const CNode &node = _nodes[item.Node]; |
1982 | bool isDir = node.IsDir(); | 1988 | const bool isDir = node.IsDir(); |
1983 | bool be = _h.be; | 1989 | const bool be = _h.be; |
1984 | 1990 | ||
1985 | switch (propID) | 1991 | switch (propID) |
1986 | { | 1992 | { |
@@ -2031,9 +2037,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
2031 | if (offset != 0) | 2037 | if (offset != 0) |
2032 | { | 2038 | { |
2033 | const Byte *p = _inodesData.Data + _nodesPos[item.Node] + offset; | 2039 | const Byte *p = _inodesData.Data + _nodesPos[item.Node] + offset; |
2034 | FILETIME ft; | 2040 | PropVariant_SetFrom_UnixTime(prop, Get32(p)); |
2035 | NWindows::NTime::UnixTimeToFileTime(Get32(p), ft); | ||
2036 | prop = ft; | ||
2037 | } | 2041 | } |
2038 | break; | 2042 | break; |
2039 | } | 2043 | } |
@@ -2043,31 +2047,38 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
2043 | prop = (UInt32)(node.Mode & 0xFFF) | k_TypeToMode[node.Type]; | 2047 | prop = (UInt32)(node.Mode & 0xFFF) | k_TypeToMode[node.Type]; |
2044 | break; | 2048 | break; |
2045 | } | 2049 | } |
2046 | /* | 2050 | case kpidUserId: |
2047 | case kpidUser: | ||
2048 | { | 2051 | { |
2049 | UInt32 offset = node.Uid * 4; | 2052 | const UInt32 offset = (UInt32)node.Uid * 4; |
2050 | if (offset < _uids.Size()) | 2053 | if (offset < _uids.Size()) |
2051 | prop = (UInt32)Get32(_uids + offset); | 2054 | prop = (UInt32)Get32(_uids + offset); |
2052 | break; | 2055 | break; |
2053 | } | 2056 | } |
2054 | case kpidGroup: | 2057 | case kpidGroupId: |
2055 | { | 2058 | { |
2056 | if (_h.Major == 4 || node.Gid == _h.GetSpecGuidIndex()) | 2059 | if (_h.Major < 4) |
2057 | { | 2060 | { |
2058 | UInt32 offset = node.Uid * 4; | 2061 | if (node.Gid == _h.GetSpecGuidIndex()) |
2059 | if (offset < _uids.Size()) | 2062 | { |
2060 | prop = (UInt32)Get32(_uids + offset); | 2063 | const UInt32 offset = (UInt32)node.Uid * 4; |
2064 | if (offset < _uids.Size()) | ||
2065 | prop = (UInt32)Get32(_uids + offset); | ||
2066 | } | ||
2067 | else | ||
2068 | { | ||
2069 | const UInt32 offset = (UInt32)node.Gid * 4; | ||
2070 | if (offset < _gids.Size()) | ||
2071 | prop = (UInt32)Get32(_gids + offset); | ||
2072 | } | ||
2061 | } | 2073 | } |
2062 | else | 2074 | else |
2063 | { | 2075 | { |
2064 | UInt32 offset = node.Gid * 4; | 2076 | const UInt32 offset = (UInt32)node.Gid * 4; |
2065 | if (offset < _gids.Size()) | 2077 | if (offset < _uids.Size()) |
2066 | prop = (UInt32)Get32(_gids + offset); | 2078 | prop = (UInt32)Get32(_uids + offset); |
2067 | } | 2079 | } |
2068 | break; | 2080 | break; |
2069 | } | 2081 | } |
2070 | */ | ||
2071 | /* | 2082 | /* |
2072 | case kpidLinks: | 2083 | case kpidLinks: |
2073 | if (_h.Major >= 3 && node.Type != kType_FILE) | 2084 | if (_h.Major >= 3 && node.Type != kType_FILE) |
@@ -2128,7 +2139,7 @@ HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) | |||
2128 | packBlockSize != _cachedPackBlockSize) | 2139 | packBlockSize != _cachedPackBlockSize) |
2129 | { | 2140 | { |
2130 | ClearCache(); | 2141 | ClearCache(); |
2131 | RINOK(_stream->Seek(blockOffset, STREAM_SEEK_SET, NULL)); | 2142 | RINOK(Seek2(blockOffset)); |
2132 | _limitedInStreamSpec->Init(packBlockSize); | 2143 | _limitedInStreamSpec->Init(packBlockSize); |
2133 | 2144 | ||
2134 | if (compressed) | 2145 | if (compressed) |
diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp index 2f23dd8..bd04bd7 100644 --- a/CPP/7zip/Archive/Tar/TarHandler.cpp +++ b/CPP/7zip/Archive/Tar/TarHandler.cpp | |||
@@ -36,22 +36,34 @@ static const Byte kProps[] = | |||
36 | kpidSize, | 36 | kpidSize, |
37 | kpidPackSize, | 37 | kpidPackSize, |
38 | kpidMTime, | 38 | kpidMTime, |
39 | kpidCTime, | ||
40 | kpidATime, | ||
39 | kpidPosixAttrib, | 41 | kpidPosixAttrib, |
40 | kpidUser, | 42 | kpidUser, |
41 | kpidGroup, | 43 | kpidGroup, |
44 | kpidUserId, | ||
45 | kpidGroupId, | ||
42 | kpidSymLink, | 46 | kpidSymLink, |
43 | kpidHardLink, | 47 | kpidHardLink, |
44 | kpidCharacts | 48 | kpidCharacts, |
45 | // kpidLinkType | 49 | kpidComment |
50 | , kpidDeviceMajor | ||
51 | , kpidDeviceMinor | ||
52 | // , kpidDevice | ||
53 | // , kpidHeadersSize // for debug | ||
54 | // , kpidOffset // for debug | ||
46 | }; | 55 | }; |
47 | 56 | ||
48 | static const Byte kArcProps[] = | 57 | static const Byte kArcProps[] = |
49 | { | 58 | { |
50 | kpidHeadersSize, | 59 | kpidHeadersSize, |
51 | kpidCodePage, | 60 | kpidCodePage, |
52 | kpidCharacts | 61 | kpidCharacts, |
62 | kpidComment | ||
53 | }; | 63 | }; |
54 | 64 | ||
65 | static const char *k_Characts_Prefix = "PREFIX"; | ||
66 | |||
55 | IMP_IInArchive_Props | 67 | IMP_IInArchive_Props |
56 | IMP_IInArchive_ArcProps | 68 | IMP_IInArchive_ArcProps |
57 | 69 | ||
@@ -60,14 +72,14 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | |||
60 | NCOM::CPropVariant prop; | 72 | NCOM::CPropVariant prop; |
61 | switch (propID) | 73 | switch (propID) |
62 | { | 74 | { |
63 | case kpidPhySize: if (_phySizeDefined) prop = _phySize; break; | 75 | case kpidPhySize: if (_arc._phySize_Defined) prop = _arc._phySize; break; |
64 | case kpidHeadersSize: if (_phySizeDefined) prop = _headersSize; break; | 76 | case kpidHeadersSize: if (_arc._phySize_Defined) prop = _arc._headersSize; break; |
65 | case kpidErrorFlags: | 77 | case kpidErrorFlags: |
66 | { | 78 | { |
67 | UInt32 flags = 0; | 79 | UInt32 flags = 0; |
68 | if (!_isArc) | 80 | if (!_isArc) |
69 | flags |= kpv_ErrorFlags_IsNotArc; | 81 | flags |= kpv_ErrorFlags_IsNotArc; |
70 | else switch (_error) | 82 | else switch (_arc._error) |
71 | { | 83 | { |
72 | case k_ErrorType_UnexpectedEnd: flags = kpv_ErrorFlags_UnexpectedEnd; break; | 84 | case k_ErrorType_UnexpectedEnd: flags = kpv_ErrorFlags_UnexpectedEnd; break; |
73 | case k_ErrorType_Corrupted: flags = kpv_ErrorFlags_HeadersError; break; | 85 | case k_ErrorType_Corrupted: flags = kpv_ErrorFlags_HeadersError; break; |
@@ -82,7 +94,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | |||
82 | 94 | ||
83 | case kpidWarningFlags: | 95 | case kpidWarningFlags: |
84 | { | 96 | { |
85 | if (_warning) | 97 | if (_arc._is_Warning) |
86 | prop = kpv_ErrorFlags_HeadersError; | 98 | prop = kpv_ErrorFlags_HeadersError; |
87 | break; | 99 | break; |
88 | } | 100 | } |
@@ -107,37 +119,38 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | |||
107 | 119 | ||
108 | case kpidCharacts: | 120 | case kpidCharacts: |
109 | { | 121 | { |
110 | prop = _encodingCharacts.GetCharactsString(); | 122 | AString s; |
123 | if (_arc._are_Gnu) s.Add_OptSpaced("GNU"); | ||
124 | if (_arc._are_Posix) s.Add_OptSpaced("POSIX"); | ||
125 | if (_arc._are_Pax_Items) s.Add_OptSpaced("PAX_ITEM"); | ||
126 | if (_arc._pathPrefix_WasUsed) s.Add_OptSpaced(k_Characts_Prefix); | ||
127 | if (_arc._are_LongName) s.Add_OptSpaced("LongName"); | ||
128 | if (_arc._are_LongLink) s.Add_OptSpaced("LongLink"); | ||
129 | if (_arc._are_Pax) s.Add_OptSpaced("PAX"); | ||
130 | if (_arc._are_pax_path) s.Add_OptSpaced("path"); | ||
131 | if (_arc._are_pax_link) s.Add_OptSpaced("linkpath"); | ||
132 | if (_arc._are_mtime) s.Add_OptSpaced("mtime"); | ||
133 | if (_arc._are_atime) s.Add_OptSpaced("atime"); | ||
134 | if (_arc._are_ctime) s.Add_OptSpaced("ctime"); | ||
135 | if (_arc._is_PaxGlobal_Error) s.Add_OptSpaced("PAX_GLOBAL_ERROR"); | ||
136 | s.Add_OptSpaced(_encodingCharacts.GetCharactsString()); | ||
137 | prop = s; | ||
111 | break; | 138 | break; |
112 | } | 139 | } |
113 | } | ||
114 | prop.Detach(value); | ||
115 | return S_OK; | ||
116 | } | ||
117 | 140 | ||
118 | HRESULT CHandler::ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx &item) | 141 | case kpidComment: |
119 | { | 142 | { |
120 | item.HeaderPos = _phySize; | 143 | if (_arc.PaxGlobal_Defined) |
121 | EErrorType error; | 144 | { |
122 | HRESULT res = ReadItem(stream, filled, item, error); | 145 | AString s; |
123 | if (error == k_ErrorType_Warning) | 146 | _arc.PaxGlobal.Print_To_String(s); |
124 | _warning = true; | 147 | if (!s.IsEmpty()) |
125 | else if (error != k_ErrorType_OK) | 148 | prop = s; |
126 | _error = error; | 149 | } |
127 | RINOK(res); | 150 | break; |
128 | if (filled) | 151 | } |
129 | { | ||
130 | /* | ||
131 | if (item.IsSparse()) | ||
132 | _isSparse = true; | ||
133 | */ | ||
134 | if (item.IsPaxExtendedHeader()) | ||
135 | _thereIsPaxExtendedHeader = true; | ||
136 | if (item.IsThereWarning()) | ||
137 | _warning = true; | ||
138 | } | 152 | } |
139 | _phySize += item.HeaderSize; | 153 | prop.Detach(value); |
140 | _headersSize += item.HeaderSize; | ||
141 | return S_OK; | 154 | return S_OK; |
142 | } | 155 | } |
143 | 156 | ||
@@ -199,16 +212,20 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) | |||
199 | RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); | 212 | RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); |
200 | } | 213 | } |
201 | 214 | ||
202 | _phySizeDefined = true; | 215 | _arc._phySize_Defined = true; |
203 | 216 | ||
204 | // bool utf8_OK = true; | 217 | // bool utf8_OK = true; |
205 | 218 | ||
219 | _arc.SeqStream = stream; | ||
220 | _arc.InStream = stream; | ||
221 | _arc.OpenCallback = callback; | ||
222 | |||
223 | CItemEx item; | ||
206 | for (;;) | 224 | for (;;) |
207 | { | 225 | { |
208 | CItemEx item; | 226 | _arc.NumFiles = _items.Size(); |
209 | bool filled; | 227 | RINOK(_arc.ReadItem(item)); |
210 | RINOK(ReadItem2(stream, filled, item)); | 228 | if (!_arc.filled) |
211 | if (!filled) | ||
212 | break; | 229 | break; |
213 | 230 | ||
214 | _isArc = true; | 231 | _isArc = true; |
@@ -228,10 +245,10 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) | |||
228 | 245 | ||
229 | _items.Add(item); | 246 | _items.Add(item); |
230 | 247 | ||
231 | RINOK(stream->Seek((Int64)item.GetPackSizeAligned(), STREAM_SEEK_CUR, &_phySize)); | 248 | RINOK(stream->Seek((Int64)item.Get_PackSize_Aligned(), STREAM_SEEK_CUR, &_arc._phySize)); |
232 | if (_phySize > endPos) | 249 | if (_arc._phySize > endPos) |
233 | { | 250 | { |
234 | _error = k_ErrorType_UnexpectedEnd; | 251 | _arc._error = k_ErrorType_UnexpectedEnd; |
235 | break; | 252 | break; |
236 | } | 253 | } |
237 | /* | 254 | /* |
@@ -241,6 +258,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) | |||
241 | break; | 258 | break; |
242 | } | 259 | } |
243 | */ | 260 | */ |
261 | /* | ||
244 | if (callback) | 262 | if (callback) |
245 | { | 263 | { |
246 | if (_items.Size() == 1) | 264 | if (_items.Size() == 1) |
@@ -249,10 +267,11 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) | |||
249 | } | 267 | } |
250 | if ((_items.Size() & 0x3FF) == 0) | 268 | if ((_items.Size() & 0x3FF) == 0) |
251 | { | 269 | { |
252 | UInt64 numFiles = _items.Size(); | 270 | const UInt64 numFiles = _items.Size(); |
253 | RINOK(callback->SetCompleted(&numFiles, &_phySize)); | 271 | RINOK(callback->SetCompleted(&numFiles, &_phySize)); |
254 | } | 272 | } |
255 | } | 273 | } |
274 | */ | ||
256 | } | 275 | } |
257 | 276 | ||
258 | /* | 277 | /* |
@@ -266,7 +285,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) | |||
266 | 285 | ||
267 | if (_items.Size() == 0) | 286 | if (_items.Size() == 0) |
268 | { | 287 | { |
269 | if (_error != k_ErrorType_OK) | 288 | if (_arc._error != k_ErrorType_OK) |
270 | { | 289 | { |
271 | _isArc = false; | 290 | _isArc = false; |
272 | return S_FALSE; | 291 | return S_FALSE; |
@@ -294,6 +313,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) | |||
294 | STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openArchiveCallback) | 313 | STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openArchiveCallback) |
295 | { | 314 | { |
296 | COM_TRY_BEGIN | 315 | COM_TRY_BEGIN |
316 | // for (int i = 0; i < 10; i++) // for debug | ||
297 | { | 317 | { |
298 | Close(); | 318 | Close(); |
299 | RINOK(Open2(stream, openArchiveCallback)); | 319 | RINOK(Open2(stream, openArchiveCallback)); |
@@ -314,16 +334,11 @@ STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) | |||
314 | STDMETHODIMP CHandler::Close() | 334 | STDMETHODIMP CHandler::Close() |
315 | { | 335 | { |
316 | _isArc = false; | 336 | _isArc = false; |
317 | _warning = false; | ||
318 | _error = k_ErrorType_OK; | ||
319 | 337 | ||
320 | _phySizeDefined = false; | 338 | _arc.Clear(); |
321 | _phySize = 0; | 339 | |
322 | _headersSize = 0; | ||
323 | _curIndex = 0; | 340 | _curIndex = 0; |
324 | _latestIsRead = false; | 341 | _latestIsRead = false; |
325 | // _isSparse = false; | ||
326 | _thereIsPaxExtendedHeader = false; | ||
327 | _encodingCharacts.Clear(); | 342 | _encodingCharacts.Clear(); |
328 | _items.Clear(); | 343 | _items.Clear(); |
329 | _seqStream.Release(); | 344 | _seqStream.Release(); |
@@ -351,12 +366,12 @@ HRESULT CHandler::SkipTo(UInt32 index) | |||
351 | { | 366 | { |
352 | if (_latestIsRead) | 367 | if (_latestIsRead) |
353 | { | 368 | { |
354 | UInt64 packSize = _latestItem.GetPackSizeAligned(); | 369 | const UInt64 packSize = _latestItem.Get_PackSize_Aligned(); |
355 | RINOK(copyCoderSpec->Code(_seqStream, NULL, &packSize, &packSize, NULL)); | 370 | RINOK(copyCoderSpec->Code(_seqStream, NULL, &packSize, &packSize, NULL)); |
356 | _phySize += copyCoderSpec->TotalSize; | 371 | _arc._phySize += copyCoderSpec->TotalSize; |
357 | if (copyCoderSpec->TotalSize != packSize) | 372 | if (copyCoderSpec->TotalSize != packSize) |
358 | { | 373 | { |
359 | _error = k_ErrorType_UnexpectedEnd; | 374 | _arc._error = k_ErrorType_UnexpectedEnd; |
360 | return S_FALSE; | 375 | return S_FALSE; |
361 | } | 376 | } |
362 | _latestIsRead = false; | 377 | _latestIsRead = false; |
@@ -364,11 +379,12 @@ HRESULT CHandler::SkipTo(UInt32 index) | |||
364 | } | 379 | } |
365 | else | 380 | else |
366 | { | 381 | { |
367 | bool filled; | 382 | _arc.SeqStream = _seqStream; |
368 | RINOK(ReadItem2(_seqStream, filled, _latestItem)); | 383 | _arc.InStream = NULL; |
369 | if (!filled) | 384 | RINOK(_arc.ReadItem(_latestItem)); |
385 | if (!_arc.filled) | ||
370 | { | 386 | { |
371 | _phySizeDefined = true; | 387 | _arc._phySize_Defined = true; |
372 | return E_INVALIDARG; | 388 | return E_INVALIDARG; |
373 | } | 389 | } |
374 | _latestIsRead = true; | 390 | _latestIsRead = true; |
@@ -390,6 +406,69 @@ void CHandler::TarStringToUnicode(const AString &s, NWindows::NCOM::CPropVariant | |||
390 | prop = dest; | 406 | prop = dest; |
391 | } | 407 | } |
392 | 408 | ||
409 | |||
410 | static void PaxTimeToProp(const CPaxTime &pt, NWindows::NCOM::CPropVariant &prop) | ||
411 | { | ||
412 | UInt64 v; | ||
413 | if (!NTime::UnixTime64_To_FileTime64(pt.Sec, v)) | ||
414 | return; | ||
415 | if (pt.Ns != 0) | ||
416 | v += pt.Ns / 100; | ||
417 | FILETIME ft; | ||
418 | ft.dwLowDateTime = (DWORD)v; | ||
419 | ft.dwHighDateTime = (DWORD)(v >> 32); | ||
420 | prop.SetAsTimeFrom_FT_Prec_Ns100(ft, | ||
421 | k_PropVar_TimePrec_Base + pt.NumDigits, pt.Ns % 100); | ||
422 | } | ||
423 | |||
424 | |||
425 | #define ValToHex(t) ((char)(((t) < 10) ? ('0' + (t)) : ('a' + ((t) - 10)))) | ||
426 | |||
427 | static void AddByteToHex2(unsigned val, AString &s) | ||
428 | { | ||
429 | unsigned t; | ||
430 | t = val >> 4; | ||
431 | s += ValToHex(t); | ||
432 | t = val & 0xF; | ||
433 | s += ValToHex(t); | ||
434 | } | ||
435 | |||
436 | static void AddSpecCharToString(const char c, AString &s) | ||
437 | { | ||
438 | if ((Byte)c <= 0x20 || (Byte)c > 127) | ||
439 | { | ||
440 | s += '['; | ||
441 | AddByteToHex2((Byte)(c), s); | ||
442 | s += ']'; | ||
443 | } | ||
444 | else | ||
445 | s += c; | ||
446 | } | ||
447 | |||
448 | static void AddSpecUInt64(AString &s, const char *name, UInt64 v) | ||
449 | { | ||
450 | if (v != 0) | ||
451 | { | ||
452 | s.Add_OptSpaced(name); | ||
453 | if (v > 1) | ||
454 | { | ||
455 | s += ':'; | ||
456 | s.Add_UInt64(v); | ||
457 | } | ||
458 | } | ||
459 | } | ||
460 | |||
461 | static void AddSpecBools(AString &s, const char *name, bool b1, bool b2) | ||
462 | { | ||
463 | if (b1) | ||
464 | { | ||
465 | s.Add_OptSpaced(name); | ||
466 | if (b2) | ||
467 | s += '*'; | ||
468 | } | ||
469 | } | ||
470 | |||
471 | |||
393 | STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) | 472 | STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) |
394 | { | 473 | { |
395 | COM_TRY_BEGIN | 474 | COM_TRY_BEGIN |
@@ -413,49 +492,189 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
413 | { | 492 | { |
414 | case kpidPath: TarStringToUnicode(item->Name, prop, true); break; | 493 | case kpidPath: TarStringToUnicode(item->Name, prop, true); break; |
415 | case kpidIsDir: prop = item->IsDir(); break; | 494 | case kpidIsDir: prop = item->IsDir(); break; |
416 | case kpidSize: prop = item->GetUnpackSize(); break; | 495 | case kpidSize: prop = item->Get_UnpackSize(); break; |
417 | case kpidPackSize: prop = item->GetPackSizeAligned(); break; | 496 | case kpidPackSize: prop = item->Get_PackSize_Aligned(); break; |
418 | case kpidMTime: | 497 | case kpidMTime: |
419 | if (item->MTime != 0) | 498 | { |
499 | /* | ||
500 | // for debug: | ||
501 | PropVariant_SetFrom_UnixTime(prop, 1 << 30); | ||
502 | prop.wReserved1 = k_PropVar_TimePrec_Base + 1; | ||
503 | prop.wReserved2 = 12; | ||
504 | break; | ||
505 | */ | ||
506 | |||
507 | if (item->PaxTimes.MTime.IsDefined()) | ||
508 | PaxTimeToProp(item->PaxTimes.MTime, prop); | ||
509 | else | ||
510 | // if (item->MTime != 0) | ||
420 | { | 511 | { |
512 | // we allow (item->MTime == 0) | ||
421 | FILETIME ft; | 513 | FILETIME ft; |
422 | if (NTime::UnixTime64ToFileTime(item->MTime, ft)) | 514 | if (NTime::UnixTime64_To_FileTime(item->MTime, ft)) |
423 | prop = ft; | 515 | { |
516 | unsigned prec = k_PropVar_TimePrec_Unix; | ||
517 | if (item->MTime_IsBin) | ||
518 | { | ||
519 | /* we report here that it's Int64-UnixTime | ||
520 | instead of basic UInt32-UnixTime range */ | ||
521 | prec = k_PropVar_TimePrec_Base; | ||
522 | } | ||
523 | prop.SetAsTimeFrom_FT_Prec(ft, prec); | ||
524 | } | ||
424 | } | 525 | } |
425 | break; | 526 | break; |
527 | } | ||
528 | case kpidATime: | ||
529 | if (item->PaxTimes.ATime.IsDefined()) | ||
530 | PaxTimeToProp(item->PaxTimes.ATime, prop); | ||
531 | break; | ||
532 | case kpidCTime: | ||
533 | if (item->PaxTimes.CTime.IsDefined()) | ||
534 | PaxTimeToProp(item->PaxTimes.CTime, prop); | ||
535 | break; | ||
426 | case kpidPosixAttrib: prop = item->Get_Combined_Mode(); break; | 536 | case kpidPosixAttrib: prop = item->Get_Combined_Mode(); break; |
427 | case kpidUser: TarStringToUnicode(item->User, prop); break; | 537 | |
428 | case kpidGroup: TarStringToUnicode(item->Group, prop); break; | 538 | case kpidUser: |
429 | case kpidSymLink: if (item->LinkFlag == NFileHeader::NLinkFlag::kSymLink && !item->LinkName.IsEmpty()) TarStringToUnicode(item->LinkName, prop); break; | 539 | if (!item->User.IsEmpty()) |
430 | case kpidHardLink: if (item->LinkFlag == NFileHeader::NLinkFlag::kHardLink && !item->LinkName.IsEmpty()) TarStringToUnicode(item->LinkName, prop); break; | 540 | TarStringToUnicode(item->User, prop); |
431 | // case kpidLinkType: prop = (int)item->LinkFlag; break; | 541 | break; |
542 | case kpidGroup: | ||
543 | if (!item->Group.IsEmpty()) | ||
544 | TarStringToUnicode(item->Group, prop); | ||
545 | break; | ||
546 | |||
547 | case kpidUserId: | ||
548 | // if (item->UID != 0) | ||
549 | prop = (UInt32)item->UID; | ||
550 | break; | ||
551 | case kpidGroupId: | ||
552 | // if (item->GID != 0) | ||
553 | prop = (UInt32)item->GID; | ||
554 | break; | ||
555 | |||
556 | case kpidDeviceMajor: | ||
557 | if (item->DeviceMajor_Defined) | ||
558 | // if (item->DeviceMajor != 0) | ||
559 | prop = (UInt32)item->DeviceMajor; | ||
560 | break; | ||
561 | |||
562 | case kpidDeviceMinor: | ||
563 | if (item->DeviceMinor_Defined) | ||
564 | // if (item->DeviceMinor != 0) | ||
565 | prop = (UInt32)item->DeviceMinor; | ||
566 | break; | ||
567 | /* | ||
568 | case kpidDevice: | ||
569 | if (item->DeviceMajor_Defined) | ||
570 | if (item->DeviceMinor_Defined) | ||
571 | prop = (UInt64)MY_dev_makedev(item->DeviceMajor, item->DeviceMinor); | ||
572 | break; | ||
573 | */ | ||
574 | |||
575 | case kpidSymLink: | ||
576 | if (item->Is_SymLink()) | ||
577 | if (!item->LinkName.IsEmpty()) | ||
578 | TarStringToUnicode(item->LinkName, prop); | ||
579 | break; | ||
580 | case kpidHardLink: | ||
581 | if (item->Is_HardLink()) | ||
582 | if (!item->LinkName.IsEmpty()) | ||
583 | TarStringToUnicode(item->LinkName, prop); | ||
584 | break; | ||
585 | |||
432 | case kpidCharacts: | 586 | case kpidCharacts: |
433 | { | 587 | { |
434 | AString s = item->EncodingCharacts.GetCharactsString(); | 588 | AString s; |
435 | if (item->IsThereWarning()) | ||
436 | { | 589 | { |
437 | s.Add_Space_if_NotEmpty(); | 590 | s.Add_Space_if_NotEmpty(); |
438 | s += "HEADER_ERROR"; | 591 | AddSpecCharToString(item->LinkFlag, s); |
439 | } | 592 | } |
440 | prop = s; | 593 | if (item->IsMagic_GNU()) |
594 | s.Add_OptSpaced("GNU"); | ||
595 | else if (item->IsMagic_Posix_ustar_00()) | ||
596 | s.Add_OptSpaced("POSIX"); | ||
597 | else | ||
598 | { | ||
599 | s.Add_Space_if_NotEmpty(); | ||
600 | for (unsigned i = 0; i < sizeof(item->Magic); i++) | ||
601 | AddSpecCharToString(item->Magic[i], s); | ||
602 | } | ||
603 | |||
604 | if (item->IsSignedChecksum) | ||
605 | s.Add_OptSpaced("SignedChecksum"); | ||
606 | |||
607 | if (item->Prefix_WasUsed) | ||
608 | s.Add_OptSpaced(k_Characts_Prefix); | ||
609 | |||
610 | s.Add_OptSpaced(item->EncodingCharacts.GetCharactsString()); | ||
611 | |||
612 | // AddSpecUInt64(s, "LongName", item->Num_LongName_Records); | ||
613 | // AddSpecUInt64(s, "LongLink", item->Num_LongLink_Records); | ||
614 | AddSpecBools(s, "LongName", item->LongName_WasUsed, item->LongName_WasUsed_2); | ||
615 | AddSpecBools(s, "LongLink", item->LongLink_WasUsed, item->LongLink_WasUsed_2); | ||
616 | |||
617 | if (item->MTime_IsBin) | ||
618 | s.Add_OptSpaced("bin_mtime"); | ||
619 | if (item->PackSize_IsBin) | ||
620 | s.Add_OptSpaced("bin_psize"); | ||
621 | if (item->Size_IsBin) | ||
622 | s.Add_OptSpaced("bin_size"); | ||
623 | |||
624 | AddSpecUInt64(s, "PAX", item->Num_Pax_Records); | ||
625 | |||
626 | if (item->PaxTimes.MTime.IsDefined()) s.Add_OptSpaced("mtime"); | ||
627 | if (item->PaxTimes.ATime.IsDefined()) s.Add_OptSpaced("atime"); | ||
628 | if (item->PaxTimes.CTime.IsDefined()) s.Add_OptSpaced("ctime"); | ||
629 | |||
630 | if (item->pax_path_WasUsed) | ||
631 | s.Add_OptSpaced("pax_path"); | ||
632 | if (item->pax_link_WasUsed) | ||
633 | s.Add_OptSpaced("pax_linkpath"); | ||
634 | if (item->pax_size_WasUsed) | ||
635 | s.Add_OptSpaced("pax_size"); | ||
636 | |||
637 | if (item->IsThereWarning()) | ||
638 | s.Add_OptSpaced("WARNING"); | ||
639 | if (item->HeaderError) | ||
640 | s.Add_OptSpaced("ERROR"); | ||
641 | if (item->Pax_Error) | ||
642 | s.Add_OptSpaced("PAX_error"); | ||
643 | if (!item->PaxExtra.RawLines.IsEmpty()) | ||
644 | s.Add_OptSpaced("PAX_unsupported_line"); | ||
645 | if (item->Pax_Overflow) | ||
646 | s.Add_OptSpaced("PAX_overflow"); | ||
647 | if (!s.IsEmpty()) | ||
648 | prop = s; | ||
441 | break; | 649 | break; |
442 | } | 650 | } |
651 | case kpidComment: | ||
652 | { | ||
653 | AString s; | ||
654 | item->PaxExtra.Print_To_String(s); | ||
655 | if (!s.IsEmpty()) | ||
656 | prop = s; | ||
657 | break; | ||
658 | } | ||
659 | // case kpidHeadersSize: prop = item->HeaderSize; break; // for debug | ||
660 | // case kpidOffset: prop = item->HeaderPos; break; // for debug | ||
443 | } | 661 | } |
444 | prop.Detach(value); | 662 | prop.Detach(value); |
445 | return S_OK; | 663 | return S_OK; |
446 | COM_TRY_END | 664 | COM_TRY_END |
447 | } | 665 | } |
448 | 666 | ||
667 | |||
449 | HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, | 668 | HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, |
450 | Int32 testMode, IArchiveExtractCallback *extractCallback) | 669 | Int32 testMode, IArchiveExtractCallback *extractCallback) |
451 | { | 670 | { |
452 | COM_TRY_BEGIN | 671 | COM_TRY_BEGIN |
453 | ISequentialInStream *stream = _seqStream; | 672 | ISequentialInStream *stream = _seqStream; |
454 | bool seqMode = (_stream == NULL); | 673 | const bool seqMode = (_stream == NULL); |
455 | if (!seqMode) | 674 | if (!seqMode) |
456 | stream = _stream; | 675 | stream = _stream; |
457 | 676 | ||
458 | bool allFilesMode = (numItems == (UInt32)(Int32)-1); | 677 | const bool allFilesMode = (numItems == (UInt32)(Int32)-1); |
459 | if (allFilesMode) | 678 | if (allFilesMode) |
460 | numItems = _items.Size(); | 679 | numItems = _items.Size(); |
461 | if (_stream && numItems == 0) | 680 | if (_stream && numItems == 0) |
@@ -463,7 +682,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
463 | UInt64 totalSize = 0; | 682 | UInt64 totalSize = 0; |
464 | UInt32 i; | 683 | UInt32 i; |
465 | for (i = 0; i < numItems; i++) | 684 | for (i = 0; i < numItems; i++) |
466 | totalSize += _items[allFilesMode ? i : indices[i]].GetUnpackSize(); | 685 | totalSize += _items[allFilesMode ? i : indices[i]].Get_UnpackSize(); |
467 | extractCallback->SetTotal(totalSize); | 686 | extractCallback->SetTotal(totalSize); |
468 | 687 | ||
469 | UInt64 totalPackSize; | 688 | UInt64 totalPackSize; |
@@ -503,9 +722,9 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
503 | item = &_items[index]; | 722 | item = &_items[index]; |
504 | 723 | ||
505 | RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); | 724 | RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); |
506 | UInt64 unpackSize = item->GetUnpackSize(); | 725 | const UInt64 unpackSize = item->Get_UnpackSize(); |
507 | totalSize += unpackSize; | 726 | totalSize += unpackSize; |
508 | totalPackSize += item->GetPackSizeAligned(); | 727 | totalPackSize += item->Get_PackSize_Aligned(); |
509 | if (item->IsDir()) | 728 | if (item->IsDir()) |
510 | { | 729 | { |
511 | RINOK(extractCallback->PrepareOperation(askMode)); | 730 | RINOK(extractCallback->PrepareOperation(askMode)); |
@@ -539,7 +758,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
539 | 758 | ||
540 | Int32 opRes = NExtract::NOperationResult::kOK; | 759 | Int32 opRes = NExtract::NOperationResult::kOK; |
541 | CMyComPtr<ISequentialInStream> inStream2; | 760 | CMyComPtr<ISequentialInStream> inStream2; |
542 | if (!item->IsSparse()) | 761 | if (!item->Is_Sparse()) |
543 | inStream2 = inStream; | 762 | inStream2 = inStream; |
544 | else | 763 | else |
545 | { | 764 | { |
@@ -549,7 +768,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
549 | } | 768 | } |
550 | 769 | ||
551 | { | 770 | { |
552 | if (item->IsSymLink()) | 771 | if (item->Is_SymLink()) |
553 | { | 772 | { |
554 | RINOK(WriteStream(outStreamSpec, (const char *)item->LinkName, item->LinkName.Len())); | 773 | RINOK(WriteStream(outStreamSpec, (const char *)item->LinkName, item->LinkName.Len())); |
555 | } | 774 | } |
@@ -557,9 +776,9 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
557 | { | 776 | { |
558 | if (!seqMode) | 777 | if (!seqMode) |
559 | { | 778 | { |
560 | RINOK(_stream->Seek((Int64)item->GetDataPosition(), STREAM_SEEK_SET, NULL)); | 779 | RINOK(_stream->Seek((Int64)item->Get_DataPos(), STREAM_SEEK_SET, NULL)); |
561 | } | 780 | } |
562 | streamSpec->Init(item->GetPackSizeAligned()); | 781 | streamSpec->Init(item->Get_PackSize_Aligned()); |
563 | RINOK(copyCoder->Code(inStream2, outStream, NULL, NULL, progress)); | 782 | RINOK(copyCoder->Code(inStream2, outStream, NULL, NULL, progress)); |
564 | } | 783 | } |
565 | if (outStreamSpec->GetRem() != 0) | 784 | if (outStreamSpec->GetRem() != 0) |
@@ -628,7 +847,7 @@ STDMETHODIMP CSparseStream::Read(void *data, UInt32 size, UInt32 *processedSize) | |||
628 | unsigned left = 0, right = item.SparseBlocks.Size(); | 847 | unsigned left = 0, right = item.SparseBlocks.Size(); |
629 | for (;;) | 848 | for (;;) |
630 | { | 849 | { |
631 | unsigned mid = (left + right) / 2; | 850 | const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); |
632 | if (mid == left) | 851 | if (mid == left) |
633 | break; | 852 | break; |
634 | if (_virtPos < item.SparseBlocks[mid].Offset) | 853 | if (_virtPos < item.SparseBlocks[mid].Offset) |
@@ -648,7 +867,7 @@ STDMETHODIMP CSparseStream::Read(void *data, UInt32 size, UInt32 *processedSize) | |||
648 | UInt64 phyPos = PhyOffsets[left] + relat; | 867 | UInt64 phyPos = PhyOffsets[left] + relat; |
649 | if (_needStartSeek || _phyPos != phyPos) | 868 | if (_needStartSeek || _phyPos != phyPos) |
650 | { | 869 | { |
651 | RINOK(Handler->_stream->Seek((Int64)(item.GetDataPosition() + phyPos), STREAM_SEEK_SET, NULL)); | 870 | RINOK(Handler->_stream->Seek((Int64)(item.Get_DataPos() + phyPos), STREAM_SEEK_SET, NULL)); |
652 | _needStartSeek = false; | 871 | _needStartSeek = false; |
653 | _phyPos = phyPos; | 872 | _phyPos = phyPos; |
654 | } | 873 | } |
@@ -698,7 +917,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) | |||
698 | 917 | ||
699 | const CItemEx &item = _items[index]; | 918 | const CItemEx &item = _items[index]; |
700 | 919 | ||
701 | if (item.IsSparse()) | 920 | if (item.Is_Sparse()) |
702 | { | 921 | { |
703 | CSparseStream *streamSpec = new CSparseStream; | 922 | CSparseStream *streamSpec = new CSparseStream; |
704 | CMyComPtr<IInStream> streamTemp = streamSpec; | 923 | CMyComPtr<IInStream> streamTemp = streamSpec; |
@@ -718,24 +937,30 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) | |||
718 | return S_OK; | 937 | return S_OK; |
719 | } | 938 | } |
720 | 939 | ||
721 | if (item.IsSymLink()) | 940 | if (item.Is_SymLink()) |
722 | { | 941 | { |
723 | Create_BufInStream_WithReference((const Byte *)(const char *)item.LinkName, item.LinkName.Len(), (IInArchive *)this, stream); | 942 | Create_BufInStream_WithReference((const Byte *)(const char *)item.LinkName, item.LinkName.Len(), (IInArchive *)this, stream); |
724 | return S_OK; | 943 | return S_OK; |
725 | } | 944 | } |
726 | 945 | ||
727 | return CreateLimitedInStream(_stream, item.GetDataPosition(), item.PackSize, stream); | 946 | return CreateLimitedInStream(_stream, item.Get_DataPos(), item.PackSize, stream); |
728 | 947 | ||
729 | COM_TRY_END | 948 | COM_TRY_END |
730 | } | 949 | } |
731 | 950 | ||
951 | |||
732 | void CHandler::Init() | 952 | void CHandler::Init() |
733 | { | 953 | { |
734 | _forceCodePage = false; | 954 | _forceCodePage = false; |
735 | _curCodePage = _specifiedCodePage = CP_UTF8; // CP_OEMCP; | 955 | _curCodePage = _specifiedCodePage = CP_UTF8; // CP_OEMCP; |
736 | _thereIsPaxExtendedHeader = false; | 956 | _posixMode = false; |
957 | _posixMode_WasForced = false; | ||
958 | // TimeOptions.Clear(); | ||
959 | _handlerTimeOptions.Init(); | ||
960 | // _handlerTimeOptions.Write_MTime.Val = true; // it's default already | ||
737 | } | 961 | } |
738 | 962 | ||
963 | |||
739 | STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) | 964 | STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) |
740 | { | 965 | { |
741 | Init(); | 966 | Init(); |
@@ -768,8 +993,54 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR | |||
768 | else if (name.IsPrefixedBy_Ascii_NoCase("memuse")) | 993 | else if (name.IsPrefixedBy_Ascii_NoCase("memuse")) |
769 | { | 994 | { |
770 | } | 995 | } |
996 | else if (name.IsEqualTo("m")) | ||
997 | { | ||
998 | if (prop.vt != VT_BSTR) | ||
999 | return E_INVALIDARG; | ||
1000 | const UString s = prop.bstrVal; | ||
1001 | if (s.IsEqualTo_Ascii_NoCase("pax") || | ||
1002 | s.IsEqualTo_Ascii_NoCase("posix")) | ||
1003 | _posixMode = true; | ||
1004 | else if (s.IsEqualTo_Ascii_NoCase("gnu")) | ||
1005 | _posixMode = false; | ||
1006 | else | ||
1007 | return E_INVALIDARG; | ||
1008 | _posixMode_WasForced = true; | ||
1009 | } | ||
771 | else | 1010 | else |
1011 | { | ||
1012 | /* | ||
1013 | if (name.IsPrefixedBy_Ascii_NoCase("td")) | ||
1014 | { | ||
1015 | name.Delete(0, 3); | ||
1016 | if (prop.vt == VT_EMPTY) | ||
1017 | { | ||
1018 | if (name.IsEqualTo_Ascii_NoCase("n")) | ||
1019 | { | ||
1020 | // TimeOptions.UseNativeDigits = true; | ||
1021 | } | ||
1022 | else if (name.IsEqualTo_Ascii_NoCase("r")) | ||
1023 | { | ||
1024 | // TimeOptions.RemoveZeroDigits = true; | ||
1025 | } | ||
1026 | else | ||
1027 | return E_INVALIDARG; | ||
1028 | } | ||
1029 | else | ||
1030 | { | ||
1031 | UInt32 numTimeDigits = 0; | ||
1032 | RINOK(ParsePropToUInt32(name, prop, numTimeDigits)); | ||
1033 | TimeOptions.NumDigits_WasForced = true; | ||
1034 | TimeOptions.NumDigits = numTimeDigits; | ||
1035 | } | ||
1036 | } | ||
1037 | */ | ||
1038 | bool processed = false; | ||
1039 | RINOK(_handlerTimeOptions.Parse(name, prop, processed)); | ||
1040 | if (processed) | ||
1041 | continue; | ||
772 | return E_INVALIDARG; | 1042 | return E_INVALIDARG; |
1043 | } | ||
773 | } | 1044 | } |
774 | return S_OK; | 1045 | return S_OK; |
775 | } | 1046 | } |
diff --git a/CPP/7zip/Archive/Tar/TarHandler.h b/CPP/7zip/Archive/Tar/TarHandler.h index 4834c2a..44a9980 100644 --- a/CPP/7zip/Archive/Tar/TarHandler.h +++ b/CPP/7zip/Archive/Tar/TarHandler.h | |||
@@ -9,7 +9,7 @@ | |||
9 | 9 | ||
10 | #include "../../Compress/CopyCoder.h" | 10 | #include "../../Compress/CopyCoder.h" |
11 | 11 | ||
12 | #include "../IArchive.h" | 12 | #include "../Common/HandlerOut.h" |
13 | 13 | ||
14 | #include "TarIn.h" | 14 | #include "TarIn.h" |
15 | 15 | ||
@@ -29,31 +29,26 @@ public: | |||
29 | CMyComPtr<IInStream> _stream; | 29 | CMyComPtr<IInStream> _stream; |
30 | CMyComPtr<ISequentialInStream> _seqStream; | 30 | CMyComPtr<ISequentialInStream> _seqStream; |
31 | private: | 31 | private: |
32 | UInt32 _curIndex; | ||
33 | bool _latestIsRead; | ||
34 | CItemEx _latestItem; | ||
35 | |||
36 | UInt64 _phySize; | ||
37 | UInt64 _headersSize; | ||
38 | bool _phySizeDefined; | ||
39 | EErrorType _error; | ||
40 | bool _warning; | ||
41 | bool _isArc; | 32 | bool _isArc; |
42 | 33 | bool _posixMode_WasForced; | |
43 | // bool _isSparse; | 34 | bool _posixMode; |
44 | bool _thereIsPaxExtendedHeader; | ||
45 | |||
46 | bool _forceCodePage; | 35 | bool _forceCodePage; |
47 | UInt32 _specifiedCodePage; | 36 | UInt32 _specifiedCodePage; |
48 | UInt32 _curCodePage; | 37 | UInt32 _curCodePage; |
49 | UInt32 _openCodePage; | 38 | UInt32 _openCodePage; |
50 | 39 | // CTimeOptions TimeOptions; | |
40 | CHandlerTimeOptions _handlerTimeOptions; | ||
51 | CEncodingCharacts _encodingCharacts; | 41 | CEncodingCharacts _encodingCharacts; |
52 | 42 | ||
43 | UInt32 _curIndex; | ||
44 | bool _latestIsRead; | ||
45 | CItemEx _latestItem; | ||
46 | |||
47 | CArchive _arc; | ||
48 | |||
53 | NCompress::CCopyCoder *copyCoderSpec; | 49 | NCompress::CCopyCoder *copyCoderSpec; |
54 | CMyComPtr<ICompressCoder> copyCoder; | 50 | CMyComPtr<ICompressCoder> copyCoder; |
55 | 51 | ||
56 | HRESULT ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx &itemInfo); | ||
57 | HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); | 52 | HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); |
58 | HRESULT SkipTo(UInt32 index); | 53 | HRESULT SkipTo(UInt32 index); |
59 | void TarStringToUnicode(const AString &s, NWindows::NCOM::CPropVariant &prop, bool toOs = false) const; | 54 | void TarStringToUnicode(const AString &s, NWindows::NCOM::CPropVariant &prop, bool toOs = false) const; |
diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp index 5ddb4b2..53255e4 100644 --- a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp +++ b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp | |||
@@ -2,15 +2,16 @@ | |||
2 | 2 | ||
3 | #include "StdAfx.h" | 3 | #include "StdAfx.h" |
4 | 4 | ||
5 | // #include <stdio.h> | ||
6 | |||
5 | #include "../../../Common/ComTry.h" | 7 | #include "../../../Common/ComTry.h" |
6 | #include "../../../Common/Defs.h" | ||
7 | #include "../../../Common/MyLinux.h" | 8 | #include "../../../Common/MyLinux.h" |
8 | #include "../../../Common/StringConvert.h" | 9 | #include "../../../Common/StringConvert.h" |
9 | #include "../../../Common/UTFConvert.h" | ||
10 | 10 | ||
11 | #include "../../../Windows/PropVariant.h" | ||
12 | #include "../../../Windows/TimeUtils.h" | 11 | #include "../../../Windows/TimeUtils.h" |
13 | 12 | ||
13 | #include "../Common/ItemNameUtils.h" | ||
14 | |||
14 | #include "TarHandler.h" | 15 | #include "TarHandler.h" |
15 | #include "TarUpdate.h" | 16 | #include "TarUpdate.h" |
16 | 17 | ||
@@ -21,10 +22,35 @@ namespace NTar { | |||
21 | 22 | ||
22 | STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) | 23 | STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) |
23 | { | 24 | { |
24 | *type = NFileTimeType::kUnix; | 25 | UInt32 t = NFileTimeType::kUnix; |
26 | const UInt32 prec = _handlerTimeOptions.Prec; | ||
27 | if (prec != (UInt32)(Int32)-1) | ||
28 | { | ||
29 | t = NFileTimeType::kWindows; | ||
30 | if (prec == k_PropVar_TimePrec_0 || | ||
31 | prec == k_PropVar_TimePrec_100ns) | ||
32 | t = NFileTimeType::kWindows; | ||
33 | else if (prec == k_PropVar_TimePrec_HighPrec) | ||
34 | t = k_PropVar_TimePrec_1ns; | ||
35 | else if (prec >= k_PropVar_TimePrec_Base) | ||
36 | t = prec; | ||
37 | } | ||
38 | // 7-Zip before 22.00 fails, if unknown typeType. | ||
39 | *type = t; | ||
25 | return S_OK; | 40 | return S_OK; |
26 | } | 41 | } |
27 | 42 | ||
43 | |||
44 | void Get_AString_From_UString(const UString &s, AString &res, | ||
45 | UINT codePage, unsigned utfFlags) | ||
46 | { | ||
47 | if (codePage == CP_UTF8) | ||
48 | ConvertUnicodeToUTF8_Flags(s, res, utfFlags); | ||
49 | else | ||
50 | UnicodeStringToMultiByte2(res, s, codePage); | ||
51 | } | ||
52 | |||
53 | |||
28 | HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, AString &res, | 54 | HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, AString &res, |
29 | UINT codePage, unsigned utfFlags, bool convertSlash) | 55 | UINT codePage, unsigned utfFlags, bool convertSlash) |
30 | { | 56 | { |
@@ -36,14 +62,7 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro | |||
36 | UString s = prop.bstrVal; | 62 | UString s = prop.bstrVal; |
37 | if (convertSlash) | 63 | if (convertSlash) |
38 | NItemName::ReplaceSlashes_OsToUnix(s); | 64 | NItemName::ReplaceSlashes_OsToUnix(s); |
39 | 65 | Get_AString_From_UString(s, res, codePage, utfFlags); | |
40 | if (codePage == CP_UTF8) | ||
41 | { | ||
42 | ConvertUnicodeToUTF8_Flags(s, res, utfFlags); | ||
43 | // if (!ConvertUnicodeToUTF8(s, res)) // return E_INVALIDARG; | ||
44 | } | ||
45 | else | ||
46 | UnicodeStringToMultiByte2(res, s, codePage); | ||
47 | } | 66 | } |
48 | else if (prop.vt != VT_EMPTY) | 67 | else if (prop.vt != VT_EMPTY) |
49 | return E_INVALIDARG; | 68 | return E_INVALIDARG; |
@@ -70,12 +89,106 @@ static int CompareUpdateItems(void *const *p1, void *const *p2, void *) | |||
70 | } | 89 | } |
71 | 90 | ||
72 | 91 | ||
92 | static HRESULT GetTime(UInt32 i, UInt32 pid, IArchiveUpdateCallback *callback, | ||
93 | CPaxTime &pt) | ||
94 | { | ||
95 | pt.Clear(); | ||
96 | NCOM::CPropVariant prop; | ||
97 | RINOK(callback->GetProperty(i, pid, &prop)); | ||
98 | return Prop_To_PaxTime(prop, pt); | ||
99 | } | ||
100 | |||
101 | |||
102 | /* | ||
103 | static HRESULT GetDevice(IArchiveUpdateCallback *callback, UInt32 i, | ||
104 | UInt32 &majo, UInt32 &mino, bool &majo_defined, bool &mino_defined) | ||
105 | { | ||
106 | NWindows::NCOM::CPropVariant prop; | ||
107 | RINOK(callback->GetProperty(i, kpidDevice, &prop)); | ||
108 | if (prop.vt == VT_EMPTY) | ||
109 | return S_OK; | ||
110 | if (prop.vt != VT_UI8) | ||
111 | return E_INVALIDARG; | ||
112 | { | ||
113 | const UInt64 v = prop.uhVal.QuadPart; | ||
114 | majo = MY_dev_major(v); | ||
115 | mino = MY_dev_minor(v); | ||
116 | majo_defined = true; | ||
117 | mino_defined = true; | ||
118 | } | ||
119 | return S_OK; | ||
120 | } | ||
121 | */ | ||
122 | |||
123 | static HRESULT GetDevice(IArchiveUpdateCallback *callback, UInt32 i, | ||
124 | UInt32 pid, UInt32 &id, bool &defined) | ||
125 | { | ||
126 | defined = false; | ||
127 | NWindows::NCOM::CPropVariant prop; | ||
128 | RINOK(callback->GetProperty(i, pid, &prop)); | ||
129 | if (prop.vt == VT_EMPTY) | ||
130 | return S_OK; | ||
131 | if (prop.vt == VT_UI4) | ||
132 | { | ||
133 | id = prop.ulVal; | ||
134 | defined = true; | ||
135 | return S_OK; | ||
136 | } | ||
137 | return E_INVALIDARG; | ||
138 | } | ||
139 | |||
140 | |||
141 | static HRESULT GetUser(IArchiveUpdateCallback *callback, UInt32 i, | ||
142 | UInt32 pidName, UInt32 pidId, AString &name, UInt32 &id, | ||
143 | UINT codePage, unsigned utfFlags) | ||
144 | { | ||
145 | // printf("\ncallback->GetProperty(i, pidId, &prop))\n"); | ||
146 | |||
147 | bool isSet = false; | ||
148 | { | ||
149 | NWindows::NCOM::CPropVariant prop; | ||
150 | RINOK(callback->GetProperty(i, pidId, &prop)); | ||
151 | if (prop.vt == VT_UI4) | ||
152 | { | ||
153 | isSet = true; | ||
154 | id = prop.ulVal; | ||
155 | // printf("\ncallback->GetProperty(i, pidId, &prop)); = %d \n", (unsigned)id); | ||
156 | name.Empty(); | ||
157 | } | ||
158 | else if (prop.vt != VT_EMPTY) | ||
159 | return E_INVALIDARG; | ||
160 | } | ||
161 | { | ||
162 | NWindows::NCOM::CPropVariant prop; | ||
163 | RINOK(callback->GetProperty(i, pidName, &prop)); | ||
164 | if (prop.vt == VT_BSTR) | ||
165 | { | ||
166 | const UString s = prop.bstrVal; | ||
167 | Get_AString_From_UString(s, name, codePage, utfFlags); | ||
168 | if (!isSet) | ||
169 | id = 0; | ||
170 | } | ||
171 | else if (prop.vt == VT_UI4) | ||
172 | { | ||
173 | id = prop.ulVal; | ||
174 | name.Empty(); | ||
175 | } | ||
176 | else if (prop.vt != VT_EMPTY) | ||
177 | return E_INVALIDARG; | ||
178 | } | ||
179 | return S_OK; | ||
180 | } | ||
181 | |||
182 | |||
183 | |||
73 | STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, | 184 | STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, |
74 | IArchiveUpdateCallback *callback) | 185 | IArchiveUpdateCallback *callback) |
75 | { | 186 | { |
76 | COM_TRY_BEGIN | 187 | COM_TRY_BEGIN |
77 | 188 | ||
78 | if ((_stream && (_error != k_ErrorType_OK || _warning /* || _isSparse */)) || _seqStream) | 189 | if ((_stream && (_arc._error != k_ErrorType_OK || _arc._is_Warning |
190 | /* || _isSparse */ | ||
191 | )) || _seqStream) | ||
79 | return E_NOTIMPL; | 192 | return E_NOTIMPL; |
80 | CObjectVector<CUpdateItem> updateItems; | 193 | CObjectVector<CUpdateItem> updateItems; |
81 | const UINT codePage = (_forceCodePage ? _specifiedCodePage : _openCodePage); | 194 | const UINT codePage = (_forceCodePage ? _specifiedCodePage : _openCodePage); |
@@ -131,25 +244,30 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
131 | else | 244 | else |
132 | ui.Mode = prop.ulVal; | 245 | ui.Mode = prop.ulVal; |
133 | // 21.07 : we clear high file type bits as GNU TAR. | 246 | // 21.07 : we clear high file type bits as GNU TAR. |
134 | ui.Mode &= ~(UInt32)MY_LIN_S_IFMT; | 247 | // we will clear it later |
248 | // ui.Mode &= ~(UInt32)MY_LIN_S_IFMT; | ||
135 | } | 249 | } |
136 | 250 | ||
137 | { | 251 | if (_handlerTimeOptions.Write_MTime.Val) |
138 | NCOM::CPropVariant prop; | 252 | RINOK(GetTime(i, kpidMTime, callback, ui.PaxTimes.MTime)) |
139 | RINOK(callback->GetProperty(i, kpidMTime, &prop)); | 253 | if (_handlerTimeOptions.Write_ATime.Val) |
140 | if (prop.vt == VT_EMPTY) | 254 | RINOK(GetTime(i, kpidATime, callback, ui.PaxTimes.ATime)) |
141 | ui.MTime = 0; | 255 | if (_handlerTimeOptions.Write_CTime.Val) |
142 | else if (prop.vt != VT_FILETIME) | 256 | RINOK(GetTime(i, kpidCTime, callback, ui.PaxTimes.CTime)) |
143 | return E_INVALIDARG; | 257 | |
144 | else | ||
145 | ui.MTime = NTime::FileTimeToUnixTime64(prop.filetime); | ||
146 | } | ||
147 | |||
148 | RINOK(GetPropString(callback, i, kpidPath, ui.Name, codePage, utfFlags, true)); | 258 | RINOK(GetPropString(callback, i, kpidPath, ui.Name, codePage, utfFlags, true)); |
149 | if (ui.IsDir && !ui.Name.IsEmpty() && ui.Name.Back() != '/') | 259 | if (ui.IsDir && !ui.Name.IsEmpty() && ui.Name.Back() != '/') |
150 | ui.Name += '/'; | 260 | ui.Name += '/'; |
151 | RINOK(GetPropString(callback, i, kpidUser, ui.User, codePage, utfFlags, false)); | 261 | // ui.Name += '/'; // for debug |
152 | RINOK(GetPropString(callback, i, kpidGroup, ui.Group, codePage, utfFlags, false)); | 262 | |
263 | if (_posixMode) | ||
264 | { | ||
265 | RINOK(GetDevice(callback, i, kpidDeviceMajor, ui.DeviceMajor, ui.DeviceMajor_Defined)); | ||
266 | RINOK(GetDevice(callback, i, kpidDeviceMinor, ui.DeviceMinor, ui.DeviceMinor_Defined)); | ||
267 | } | ||
268 | |||
269 | RINOK(GetUser(callback, i, kpidUser, kpidUserId, ui.User, ui.UID, codePage, utfFlags)); | ||
270 | RINOK(GetUser(callback, i, kpidGroup, kpidGroupId, ui.Group, ui.GID, codePage, utfFlags)); | ||
153 | } | 271 | } |
154 | 272 | ||
155 | if (IntToBool(newData)) | 273 | if (IntToBool(newData)) |
@@ -169,13 +287,44 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
169 | updateItems.Add(ui); | 287 | updateItems.Add(ui); |
170 | } | 288 | } |
171 | 289 | ||
172 | if (_thereIsPaxExtendedHeader) | 290 | if (_arc._are_Pax_Items) |
173 | { | 291 | { |
174 | // we restore original order of files, if there is pax header block | 292 | // we restore original order of files, if there are pax items |
175 | updateItems.Sort(CompareUpdateItems, NULL); | 293 | updateItems.Sort(CompareUpdateItems, NULL); |
176 | } | 294 | } |
295 | |||
296 | CUpdateOptions options; | ||
297 | |||
298 | options.CodePage = codePage; | ||
299 | options.UtfFlags = utfFlags; | ||
300 | options.PosixMode = _posixMode; | ||
301 | |||
302 | options.Write_MTime = _handlerTimeOptions.Write_MTime; | ||
303 | options.Write_ATime = _handlerTimeOptions.Write_ATime; | ||
304 | options.Write_CTime = _handlerTimeOptions.Write_CTime; | ||
177 | 305 | ||
178 | return UpdateArchive(_stream, outStream, _items, updateItems, codePage, utfFlags, callback); | 306 | // options.TimeOptions = TimeOptions; |
307 | |||
308 | const UInt32 prec = _handlerTimeOptions.Prec; | ||
309 | if (prec != (UInt32)(Int32)-1) | ||
310 | { | ||
311 | unsigned numDigits = 0; | ||
312 | if (prec == 0) | ||
313 | numDigits = 7; | ||
314 | else if (prec == k_PropVar_TimePrec_HighPrec | ||
315 | || prec >= k_PropVar_TimePrec_1ns) | ||
316 | numDigits = 9; | ||
317 | else if (prec >= k_PropVar_TimePrec_Base) | ||
318 | numDigits = prec - k_PropVar_TimePrec_Base; | ||
319 | options.TimeOptions.NumDigitsMax = numDigits; | ||
320 | // options.TimeOptions.RemoveZeroMode = | ||
321 | // k_PaxTimeMode_DontRemoveZero; // pure for debug | ||
322 | // k_PaxTimeMode_RemoveZero_if_PureSecondOnly; // optimized code | ||
323 | // k_PaxTimeMode_RemoveZero_Always; // original pax code | ||
324 | } | ||
325 | |||
326 | return UpdateArchive(_stream, outStream, _items, updateItems, | ||
327 | options, callback); | ||
179 | 328 | ||
180 | COM_TRY_END | 329 | COM_TRY_END |
181 | } | 330 | } |
diff --git a/CPP/7zip/Archive/Tar/TarHeader.cpp b/CPP/7zip/Archive/Tar/TarHeader.cpp index 9c16c89..f1efddb 100644 --- a/CPP/7zip/Archive/Tar/TarHeader.cpp +++ b/CPP/7zip/Archive/Tar/TarHeader.cpp | |||
@@ -18,9 +18,82 @@ namespace NFileHeader { | |||
18 | // const char * const kGNUTar = "GNUtar "; // 7 chars and a null | 18 | // const char * const kGNUTar = "GNUtar "; // 7 chars and a null |
19 | // const char * const kEmpty = "\0\0\0\0\0\0\0\0"; | 19 | // const char * const kEmpty = "\0\0\0\0\0\0\0\0"; |
20 | // 7-Zip used kUsTar_00 before 21.07: | 20 | // 7-Zip used kUsTar_00 before 21.07: |
21 | // const char kUsTar_00[8] = { 'u', 's', 't', 'a', 'r', 0, '0', '0' } ; | 21 | const char k_Posix_ustar_00[8] = { 'u', 's', 't', 'a', 'r', 0, '0', '0' } ; |
22 | // GNU TAR uses such header: | 22 | // GNU TAR uses such header: |
23 | const char kUsTar_GNU[8] = { 'u', 's', 't', 'a', 'r', ' ', ' ', 0 } ; | 23 | const char k_GNU_ustar__[8] = { 'u', 's', 't', 'a', 'r', ' ', ' ', 0 } ; |
24 | } | 24 | } |
25 | 25 | ||
26 | /* | ||
27 | pre-POSIX.1-1988 (i.e. v7) tar header: | ||
28 | ----- | ||
29 | Link indicator: | ||
30 | '0' or 0 : Normal file | ||
31 | '1' : Hard link | ||
32 | '2' : Symbolic link | ||
33 | Some pre-POSIX.1-1988 tar implementations indicated a directory by having | ||
34 | a trailing slash (/) in the name. | ||
35 | |||
36 | Numeric values : octal with leading zeroes. | ||
37 | For historical reasons, a final NUL or space character should also be used. | ||
38 | Thus only 11 octal digits can be stored from 12 bytes field. | ||
39 | |||
40 | 2001 star : introduced a base-256 coding that is indicated by | ||
41 | setting the high-order bit of the leftmost byte of a numeric field. | ||
42 | GNU-tar and BSD-tar followed this idea. | ||
43 | |||
44 | versions of tar from before the first POSIX standard from 1988 | ||
45 | pad the values with spaces instead of zeroes. | ||
46 | |||
47 | UStar | ||
48 | ----- | ||
49 | UStar (Unix Standard TAR) : POSIX IEEE P1003.1 : 1988. | ||
50 | 257 signature: "ustar", 0, "00" | ||
51 | 265 32 Owner user name | ||
52 | 297 32 Owner group name | ||
53 | 329 8 Device major number | ||
54 | 337 8 Device minor number | ||
55 | 345 155 Filename prefix | ||
56 | |||
57 | POSIX.1-2001/pax | ||
58 | ---- | ||
59 | format is known as extended tar format or pax format | ||
60 | vendor-tagged vendor-specific enhancements. | ||
61 | tags Defined by the POSIX standard: | ||
62 | atime, mtime, path, linkpath, uname, gname, size, uid, gid, ... | ||
63 | |||
64 | |||
65 | PAX EXTENSION | ||
66 | ----------- | ||
67 | Hard links | ||
68 | A further difference from the ustar header block is that data blocks | ||
69 | for files of typeflag 1 (hard link) may be included, | ||
70 | which means that the size field may be greater than zero. | ||
71 | Archives created by pax -o linkdata shall include these data | ||
72 | blocks with the hard links. | ||
73 | * | ||
74 | |||
75 | compatiblity | ||
76 | ------------ | ||
77 | 7-Zip 16.03 supports "PaxHeader/" | ||
78 | 7-Zip 20.01 supports "PaxHeaders.X/" with optional "./" | ||
79 | 7-Zip 21.02 supports "@PaxHeader" with optional "./" "./" | ||
80 | |||
81 | GNU tar --format=posix uses "PaxHeaders/" in folder of file | ||
82 | |||
83 | |||
84 | GNU TAR format | ||
85 | ============== | ||
86 | v7 - Unix V7 | ||
87 | oldgnu - GNU tar <=1.12 : writes zero in last character in name | ||
88 | gnu - GNU tar 1.13 : doesn't write zero in last character in name | ||
89 | as 7-zip 21.07 | ||
90 | ustar - POSIX.1-1988 | ||
91 | posix (pax) - POSIX.1-2001 | ||
92 | |||
93 | gnu tar: | ||
94 | if (S_ISCHR (st->stat.st_mode) || S_ISBLK (st->stat.st_mode)) { | ||
95 | major_t devmajor = major (st->stat.st_rdev); | ||
96 | minor_t devminor = minor (st->stat.st_rdev); } | ||
97 | */ | ||
98 | |||
26 | }}} | 99 | }}} |
diff --git a/CPP/7zip/Archive/Tar/TarHeader.h b/CPP/7zip/Archive/Tar/TarHeader.h index b0f0ec3..1af3093 100644 --- a/CPP/7zip/Archive/Tar/TarHeader.h +++ b/CPP/7zip/Archive/Tar/TarHeader.h | |||
@@ -59,6 +59,9 @@ namespace NFileHeader | |||
59 | const char kGnu_LongName = 'L'; | 59 | const char kGnu_LongName = 'L'; |
60 | const char kSparse = 'S'; | 60 | const char kSparse = 'S'; |
61 | const char kLabel = 'V'; | 61 | const char kLabel = 'V'; |
62 | const char kPax = 'x'; // Extended header with meta data for the next file in the archive (POSIX.1-2001) | ||
63 | const char kPax_2 = 'X'; | ||
64 | const char kGlobal = 'g'; // Global extended header with meta data (POSIX.1-2001) | ||
62 | const char kDumpDir = 'D'; /* GNUTYPE_DUMPDIR. | 65 | const char kDumpDir = 'D'; /* GNUTYPE_DUMPDIR. |
63 | data: list of files created by the --incremental (-G) option | 66 | data: list of files created by the --incremental (-G) option |
64 | Each file name is preceded by either | 67 | Each file name is preceded by either |
@@ -66,6 +69,7 @@ namespace NFileHeader | |||
66 | - 'N' (file is a directory, or is not stored in the archive.) | 69 | - 'N' (file is a directory, or is not stored in the archive.) |
67 | Each file name is terminated by a null + an additional null after | 70 | Each file name is terminated by a null + an additional null after |
68 | the last file name. */ | 71 | the last file name. */ |
72 | // 'A'-'Z' Vendor specific extensions (POSIX.1-1988) | ||
69 | } | 73 | } |
70 | 74 | ||
71 | extern const char * const kLongLink; // = "././@LongLink"; | 75 | extern const char * const kLongLink; // = "././@LongLink"; |
@@ -76,8 +80,8 @@ namespace NFileHeader | |||
76 | // extern const char * const kUsTar; // = "ustar"; // 5 chars | 80 | // extern const char * const kUsTar; // = "ustar"; // 5 chars |
77 | // extern const char * const kGNUTar; // = "GNUtar "; // 7 chars and a null | 81 | // extern const char * const kGNUTar; // = "GNUtar "; // 7 chars and a null |
78 | // extern const char * const kEmpty; // = "\0\0\0\0\0\0\0\0" | 82 | // extern const char * const kEmpty; // = "\0\0\0\0\0\0\0\0" |
79 | // extern const char kUsTar_00[8]; | 83 | extern const char k_Posix_ustar_00[8]; |
80 | extern const char kUsTar_GNU[8]; | 84 | extern const char k_GNU_ustar__[8]; |
81 | } | 85 | } |
82 | } | 86 | } |
83 | 87 | ||
diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp index 58399d0..4fd8c5b 100644 --- a/CPP/7zip/Archive/Tar/TarIn.cpp +++ b/CPP/7zip/Archive/Tar/TarIn.cpp | |||
@@ -12,6 +12,45 @@ | |||
12 | 12 | ||
13 | #include "TarIn.h" | 13 | #include "TarIn.h" |
14 | 14 | ||
15 | #define NUM_UNROLL_BYTES (8 * 4) | ||
16 | |||
17 | MY_NO_INLINE static bool IsBufNonZero(const void *data, size_t size); | ||
18 | MY_NO_INLINE static bool IsBufNonZero(const void *data, size_t size) | ||
19 | { | ||
20 | const Byte *p = (const Byte *)data; | ||
21 | |||
22 | for (; size != 0 && ((unsigned)(ptrdiff_t)p & (NUM_UNROLL_BYTES - 1)) != 0; size--) | ||
23 | if (*p++ != 0) | ||
24 | return true; | ||
25 | |||
26 | if (size >= NUM_UNROLL_BYTES) | ||
27 | { | ||
28 | const Byte *lim = p + size; | ||
29 | size &= (NUM_UNROLL_BYTES - 1); | ||
30 | lim -= size; | ||
31 | do | ||
32 | { | ||
33 | if (*(const UInt64 *)(const void *)(p ) != 0) return true; | ||
34 | if (*(const UInt64 *)(const void *)(p + 8 * 1) != 0) return true; | ||
35 | if (*(const UInt64 *)(const void *)(p + 8 * 2) != 0) return true; | ||
36 | if (*(const UInt64 *)(const void *)(p + 8 * 3) != 0) return true; | ||
37 | // if (*(const UInt32 *)(const void *)(p ) != 0) return true; | ||
38 | // if (*(const UInt32 *)(const void *)(p + 4 * 1) != 0) return true; | ||
39 | // if (*(const UInt32 *)(const void *)(p + 4 * 2) != 0) return true; | ||
40 | // if (*(const UInt32 *)(const void *)(p + 4 * 3) != 0) return true; | ||
41 | p += NUM_UNROLL_BYTES; | ||
42 | } | ||
43 | while (p != lim); | ||
44 | } | ||
45 | |||
46 | for (; size != 0; size--) | ||
47 | if (*p++ != 0) | ||
48 | return true; | ||
49 | |||
50 | return false; | ||
51 | } | ||
52 | |||
53 | |||
15 | namespace NArchive { | 54 | namespace NArchive { |
16 | namespace NTar { | 55 | namespace NTar { |
17 | 56 | ||
@@ -41,10 +80,11 @@ static bool OctalToNumber(const char *srcString, unsigned size, UInt64 &res, boo | |||
41 | return (*end == ' ' || *end == 0); | 80 | return (*end == ' ' || *end == 0); |
42 | } | 81 | } |
43 | 82 | ||
44 | static bool OctalToNumber32(const char *srcString, unsigned size, UInt32 &res, bool allowEmpty = false) | 83 | static bool OctalToNumber32(const char *srcString, UInt32 &res, bool allowEmpty = false) |
45 | { | 84 | { |
85 | const unsigned kSize = 8; | ||
46 | UInt64 res64; | 86 | UInt64 res64; |
47 | if (!OctalToNumber(srcString, size, res64, allowEmpty)) | 87 | if (!OctalToNumber(srcString, kSize, res64, allowEmpty)) |
48 | return false; | 88 | return false; |
49 | res = (UInt32)res64; | 89 | res = (UInt32)res64; |
50 | return (res64 <= 0xFFFFFFFF); | 90 | return (res64 <= 0xFFFFFFFF); |
@@ -52,68 +92,61 @@ static bool OctalToNumber32(const char *srcString, unsigned size, UInt32 &res, b | |||
52 | 92 | ||
53 | #define RIF(x) { if (!(x)) return S_OK; } | 93 | #define RIF(x) { if (!(x)) return S_OK; } |
54 | 94 | ||
55 | /* | ||
56 | static bool IsEmptyData(const char *buf, size_t size) | ||
57 | { | ||
58 | for (unsigned i = 0; i < size; i++) | ||
59 | if (buf[i] != 0) | ||
60 | return false; | ||
61 | return true; | ||
62 | } | ||
63 | */ | ||
64 | |||
65 | static bool IsRecordLast(const char *buf) | ||
66 | { | ||
67 | for (unsigned i = 0; i < NFileHeader::kRecordSize; i++) | ||
68 | if (buf[i] != 0) | ||
69 | return false; | ||
70 | return true; | ||
71 | } | ||
72 | |||
73 | static void ReadString(const char *s, unsigned size, AString &result) | 95 | static void ReadString(const char *s, unsigned size, AString &result) |
74 | { | 96 | { |
75 | result.SetFrom_CalcLen(s, size); | 97 | result.SetFrom_CalcLen(s, size); |
76 | } | 98 | } |
77 | 99 | ||
78 | static bool ParseInt64(const char *p, Int64 &val) | 100 | static bool ParseInt64(const char *p, Int64 &val, bool &isBin) |
79 | { | 101 | { |
80 | UInt32 h = GetBe32(p); | 102 | const UInt32 h = GetBe32(p); |
81 | val = (Int64)GetBe64(p + 4); | 103 | val = (Int64)GetBe64(p + 4); |
104 | isBin = true; | ||
82 | if (h == (UInt32)1 << 31) | 105 | if (h == (UInt32)1 << 31) |
83 | return ((val >> 63) & 1) == 0; | 106 | return ((val >> 63) & 1) == 0; |
84 | if (h == (UInt32)(Int32)-1) | 107 | if (h == (UInt32)(Int32)-1) |
85 | return ((val >> 63) & 1) != 0; | 108 | return ((val >> 63) & 1) != 0; |
86 | UInt64 uv; | 109 | isBin = false; |
87 | bool res = OctalToNumber(p, 12, uv); | 110 | UInt64 u; |
88 | val = (Int64)uv; | 111 | const bool res = OctalToNumber(p, 12, u); |
112 | val = (Int64)u; | ||
89 | return res; | 113 | return res; |
90 | } | 114 | } |
91 | 115 | ||
92 | static bool ParseInt64_MTime(const char *p, Int64 &val) | 116 | static bool ParseInt64_MTime(const char *p, Int64 &val, bool &isBin) |
93 | { | 117 | { |
94 | // rare case tar : ZEROs in Docker-Windows TARs | 118 | // rare case tar : ZEROs in Docker-Windows TARs |
95 | // rare case tar : spaces | 119 | // rare case tar : spaces |
120 | isBin = false; | ||
96 | if (GetUi32(p) != 0) | 121 | if (GetUi32(p) != 0) |
97 | for (unsigned i = 0; i < 12; i++) | 122 | for (unsigned i = 0; i < 12; i++) |
98 | if (p[i] != ' ') | 123 | if (p[i] != ' ') |
99 | return ParseInt64(p, val); | 124 | return ParseInt64(p, val, isBin); |
100 | val = 0; | 125 | val = 0; |
101 | return true; | 126 | return true; |
102 | } | 127 | } |
103 | 128 | ||
104 | static bool ParseSize(const char *p, UInt64 &val) | 129 | static bool ParseSize(const char *p, UInt64 &val, bool &isBin) |
105 | { | 130 | { |
106 | if (GetBe32(p) == (UInt32)1 << 31) | 131 | if (GetBe32(p) == (UInt32)1 << 31) |
107 | { | 132 | { |
108 | // GNU extension | 133 | // GNU extension |
134 | isBin = true; | ||
109 | val = GetBe64(p + 4); | 135 | val = GetBe64(p + 4); |
110 | return ((val >> 63) & 1) == 0; | 136 | return ((val >> 63) & 1) == 0; |
111 | } | 137 | } |
138 | isBin = false; | ||
112 | return OctalToNumber(p, 12, val, | 139 | return OctalToNumber(p, 12, val, |
113 | true // 20.03: allow empty size for 'V' Label entry | 140 | true // 20.03: allow empty size for 'V' Label entry |
114 | ); | 141 | ); |
115 | } | 142 | } |
116 | 143 | ||
144 | static bool ParseSize(const char *p, UInt64 &val) | ||
145 | { | ||
146 | bool isBin; | ||
147 | return ParseSize(p, val, isBin); | ||
148 | } | ||
149 | |||
117 | #define CHECK(x) { if (!(x)) return k_IsArc_Res_NO; } | 150 | #define CHECK(x) { if (!(x)) return k_IsArc_Res_NO; } |
118 | 151 | ||
119 | API_FUNC_IsArc IsArc_Tar(const Byte *p2, size_t size) | 152 | API_FUNC_IsArc IsArc_Tar(const Byte *p2, size_t size) |
@@ -126,26 +159,27 @@ API_FUNC_IsArc IsArc_Tar(const Byte *p2, size_t size) | |||
126 | 159 | ||
127 | UInt32 mode; | 160 | UInt32 mode; |
128 | // we allow empty Mode value for LongName prefix items | 161 | // we allow empty Mode value for LongName prefix items |
129 | CHECK(OctalToNumber32(p, 8, mode, true)); p += 8; | 162 | CHECK(OctalToNumber32(p, mode, true)); p += 8; |
130 | 163 | ||
131 | // if (!OctalToNumber32(p, 8, item.UID)) item.UID = 0; | 164 | // if (!OctalToNumber32(p, item.UID)) item.UID = 0; |
132 | p += 8; | 165 | p += 8; |
133 | // if (!OctalToNumber32(p, 8, item.GID)) item.GID = 0; | 166 | // if (!OctalToNumber32(p, item.GID)) item.GID = 0; |
134 | p += 8; | 167 | p += 8; |
135 | 168 | ||
136 | UInt64 packSize; | 169 | UInt64 packSize; |
137 | Int64 time; | 170 | Int64 time; |
138 | UInt32 checkSum; | 171 | UInt32 checkSum; |
139 | CHECK(ParseSize(p, packSize)); p += 12; | 172 | bool isBin; |
140 | CHECK(ParseInt64_MTime(p, time)); p += 12; | 173 | CHECK(ParseSize(p, packSize, isBin)); p += 12; |
141 | CHECK(OctalToNumber32(p, 8, checkSum)); | 174 | CHECK(ParseInt64_MTime(p, time, isBin)); p += 12; |
175 | CHECK(OctalToNumber32(p, checkSum)); | ||
142 | return k_IsArc_Res_YES; | 176 | return k_IsArc_Res_YES; |
143 | } | 177 | } |
144 | 178 | ||
145 | static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemEx &item, EErrorType &error) | 179 | |
180 | HRESULT CArchive::GetNextItemReal(CItemEx &item) | ||
146 | { | 181 | { |
147 | char buf[NFileHeader::kRecordSize]; | 182 | char buf[NFileHeader::kRecordSize]; |
148 | char *p = buf; | ||
149 | 183 | ||
150 | error = k_ErrorType_OK; | 184 | error = k_ErrorType_OK; |
151 | filled = false; | 185 | filled = false; |
@@ -154,7 +188,7 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE | |||
154 | for (;;) | 188 | for (;;) |
155 | { | 189 | { |
156 | size_t processedSize = NFileHeader::kRecordSize; | 190 | size_t processedSize = NFileHeader::kRecordSize; |
157 | RINOK(ReadStream(stream, buf, &processedSize)); | 191 | RINOK(ReadStream(SeqStream, buf, &processedSize)); |
158 | if (processedSize == 0) | 192 | if (processedSize == 0) |
159 | { | 193 | { |
160 | if (!thereAreEmptyRecords) | 194 | if (!thereAreEmptyRecords) |
@@ -180,10 +214,14 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE | |||
180 | 214 | ||
181 | return S_OK; | 215 | return S_OK; |
182 | } | 216 | } |
183 | if (!IsRecordLast(buf)) | 217 | if (IsBufNonZero(buf, NFileHeader::kRecordSize)) |
184 | break; | 218 | break; |
185 | item.HeaderSize += NFileHeader::kRecordSize; | 219 | item.HeaderSize += NFileHeader::kRecordSize; |
186 | thereAreEmptyRecords = true; | 220 | thereAreEmptyRecords = true; |
221 | if (OpenCallback) | ||
222 | { | ||
223 | RINOK(Progress(item, 0)); | ||
224 | } | ||
187 | } | 225 | } |
188 | if (thereAreEmptyRecords) | 226 | if (thereAreEmptyRecords) |
189 | { | 227 | { |
@@ -191,52 +229,69 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE | |||
191 | return S_OK; | 229 | return S_OK; |
192 | } | 230 | } |
193 | 231 | ||
232 | char *p = buf; | ||
233 | |||
194 | error = k_ErrorType_Corrupted; | 234 | error = k_ErrorType_Corrupted; |
195 | ReadString(p, NFileHeader::kNameSize, item.Name); p += NFileHeader::kNameSize; | 235 | |
196 | item.NameCouldBeReduced = | 236 | // ReadString(p, NFileHeader::kNameSize, item.Name); |
237 | p += NFileHeader::kNameSize; | ||
238 | |||
239 | /* | ||
240 | item.Name_CouldBeReduced = | ||
197 | (item.Name.Len() == NFileHeader::kNameSize || | 241 | (item.Name.Len() == NFileHeader::kNameSize || |
198 | item.Name.Len() == NFileHeader::kNameSize - 1); | 242 | item.Name.Len() == NFileHeader::kNameSize - 1); |
243 | */ | ||
199 | 244 | ||
200 | // we allow empty Mode value for LongName prefix items | 245 | // we allow empty Mode value for LongName prefix items |
201 | RIF(OctalToNumber32(p, 8, item.Mode, true)); p += 8; | 246 | RIF(OctalToNumber32(p, item.Mode, true)); p += 8; |
202 | 247 | ||
203 | if (!OctalToNumber32(p, 8, item.UID)) { item.UID = 0; } p += 8; | 248 | if (!OctalToNumber32(p, item.UID)) { item.UID = 0; } p += 8; |
204 | if (!OctalToNumber32(p, 8, item.GID)) { item.GID = 0; } p += 8; | 249 | if (!OctalToNumber32(p, item.GID)) { item.GID = 0; } p += 8; |
205 | 250 | ||
206 | RIF(ParseSize(p, item.PackSize)); | 251 | RIF(ParseSize(p, item.PackSize, item.PackSize_IsBin)); |
207 | item.Size = item.PackSize; | 252 | item.Size = item.PackSize; |
253 | item.Size_IsBin = item.PackSize_IsBin; | ||
208 | p += 12; | 254 | p += 12; |
209 | RIF(ParseInt64_MTime(p, item.MTime)); p += 12; | 255 | RIF(ParseInt64_MTime(p, item.MTime, item.MTime_IsBin)); p += 12; |
210 | 256 | ||
211 | UInt32 checkSum; | 257 | UInt32 checkSum; |
212 | RIF(OctalToNumber32(p, 8, checkSum)); | 258 | RIF(OctalToNumber32(p, checkSum)); |
213 | memset(p, ' ', 8); p += 8; | 259 | memset(p, ' ', 8); p += 8; |
214 | 260 | ||
215 | item.LinkFlag = *p++; | 261 | item.LinkFlag = *p++; |
216 | 262 | ||
217 | ReadString(p, NFileHeader::kNameSize, item.LinkName); p += NFileHeader::kNameSize; | 263 | ReadString(p, NFileHeader::kNameSize, item.LinkName); p += NFileHeader::kNameSize; |
218 | item.LinkNameCouldBeReduced = | 264 | |
265 | /* | ||
266 | item.LinkName_CouldBeReduced = | ||
219 | (item.LinkName.Len() == NFileHeader::kNameSize || | 267 | (item.LinkName.Len() == NFileHeader::kNameSize || |
220 | item.LinkName.Len() == NFileHeader::kNameSize - 1); | 268 | item.LinkName.Len() == NFileHeader::kNameSize - 1); |
269 | */ | ||
221 | 270 | ||
222 | memcpy(item.Magic, p, 8); p += 8; | 271 | memcpy(item.Magic, p, 8); p += 8; |
223 | 272 | ||
224 | ReadString(p, NFileHeader::kUserNameSize, item.User); p += NFileHeader::kUserNameSize; | 273 | ReadString(p, NFileHeader::kUserNameSize, item.User); p += NFileHeader::kUserNameSize; |
225 | ReadString(p, NFileHeader::kGroupNameSize, item.Group); p += NFileHeader::kGroupNameSize; | 274 | ReadString(p, NFileHeader::kGroupNameSize, item.Group); p += NFileHeader::kGroupNameSize; |
226 | 275 | ||
227 | item.DeviceMajorDefined = (p[0] != 0); if (item.DeviceMajorDefined) { RIF(OctalToNumber32(p, 8, item.DeviceMajor)); } p += 8; | 276 | item.DeviceMajor_Defined = (p[0] != 0); if (item.DeviceMajor_Defined) { RIF(OctalToNumber32(p, item.DeviceMajor)); } p += 8; |
228 | item.DeviceMinorDefined = (p[0] != 0); if (item.DeviceMinorDefined) { RIF(OctalToNumber32(p, 8, item.DeviceMinor)); } p += 8; | 277 | item.DeviceMinor_Defined = (p[0] != 0); if (item.DeviceMinor_Defined) { RIF(OctalToNumber32(p, item.DeviceMinor)); } p += 8; |
229 | 278 | ||
230 | if (p[0] != 0) | 279 | if (p[0] != 0 |
280 | && item.IsMagic_ustar_5chars() | ||
281 | && (item.LinkFlag != 'L' )) | ||
231 | { | 282 | { |
232 | AString prefix; | 283 | item.Prefix_WasUsed = true; |
233 | ReadString(p, NFileHeader::kPrefixSize, prefix); | 284 | ReadString(p, NFileHeader::kPrefixSize, item.Name); |
234 | if (!prefix.IsEmpty() | 285 | item.Name += '/'; |
235 | && item.IsUstarMagic() | 286 | unsigned i; |
236 | && (item.LinkFlag != 'L' /* || prefix != "00000000000" */ )) | 287 | for (i = 0; i < NFileHeader::kNameSize; i++) |
237 | item.Name = prefix + '/' + item.Name; | 288 | if (buf[i] == 0) |
289 | break; | ||
290 | item.Name.AddFrom(buf, i); | ||
238 | } | 291 | } |
239 | 292 | else | |
293 | ReadString(buf, NFileHeader::kNameSize, item.Name); | ||
294 | |||
240 | p += NFileHeader::kPrefixSize; | 295 | p += NFileHeader::kPrefixSize; |
241 | 296 | ||
242 | if (item.LinkFlag == NFileHeader::NLinkFlag::kHardLink) | 297 | if (item.LinkFlag == NFileHeader::NLinkFlag::kHardLink) |
@@ -255,22 +310,25 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE | |||
255 | 310 | ||
256 | /* | 311 | /* |
257 | TAR standard requires sum of unsigned byte values. | 312 | TAR standard requires sum of unsigned byte values. |
258 | But some TAR programs use sum of signed byte values. | 313 | But some old TAR programs use sum of signed byte values. |
259 | So we check both values. | 314 | So we check both values. |
260 | */ | 315 | */ |
261 | UInt32 checkSumReal = 0; | 316 | // for (int y = 0; y < 100; y++) // for debug |
262 | Int32 checkSumReal_Signed = 0; | ||
263 | for (unsigned i = 0; i < NFileHeader::kRecordSize; i++) | ||
264 | { | 317 | { |
265 | char c = buf[i]; | 318 | UInt32 sum0 = 0; |
266 | checkSumReal_Signed += (signed char)c; | 319 | { |
267 | checkSumReal += (Byte)buf[i]; | 320 | for (unsigned i = 0; i < NFileHeader::kRecordSize; i++) |
268 | } | 321 | sum0 += (Byte)buf[i]; |
269 | 322 | } | |
270 | if (checkSumReal != checkSum) | 323 | if (sum0 != checkSum) |
271 | { | 324 | { |
272 | if ((UInt32)checkSumReal_Signed != checkSum) | 325 | Int32 sum = 0; |
273 | return S_OK; | 326 | for (unsigned i = 0; i < NFileHeader::kRecordSize; i++) |
327 | sum += (signed char)buf[i]; | ||
328 | if ((UInt32)sum != checkSum) | ||
329 | return S_OK; | ||
330 | item.IsSignedChecksum = true; | ||
331 | } | ||
274 | } | 332 | } |
275 | 333 | ||
276 | item.HeaderSize += NFileHeader::kRecordSize; | 334 | item.HeaderSize += NFileHeader::kRecordSize; |
@@ -280,7 +338,7 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE | |||
280 | Byte isExtended = (Byte)buf[482]; | 338 | Byte isExtended = (Byte)buf[482]; |
281 | if (isExtended != 0 && isExtended != 1) | 339 | if (isExtended != 0 && isExtended != 1) |
282 | return S_OK; | 340 | return S_OK; |
283 | RIF(ParseSize(buf + 483, item.Size)); | 341 | RIF(ParseSize(buf + 483, item.Size, item.Size_IsBin)); |
284 | UInt64 min = 0; | 342 | UInt64 min = 0; |
285 | for (unsigned i = 0; i < 4; i++) | 343 | for (unsigned i = 0; i < 4; i++) |
286 | { | 344 | { |
@@ -309,7 +367,7 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE | |||
309 | while (isExtended != 0) | 367 | while (isExtended != 0) |
310 | { | 368 | { |
311 | size_t processedSize = NFileHeader::kRecordSize; | 369 | size_t processedSize = NFileHeader::kRecordSize; |
312 | RINOK(ReadStream(stream, buf, &processedSize)); | 370 | RINOK(ReadStream(SeqStream, buf, &processedSize)); |
313 | if (processedSize != NFileHeader::kRecordSize) | 371 | if (processedSize != NFileHeader::kRecordSize) |
314 | { | 372 | { |
315 | error = k_ErrorType_UnexpectedEnd; | 373 | error = k_ErrorType_UnexpectedEnd; |
@@ -317,6 +375,12 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE | |||
317 | } | 375 | } |
318 | 376 | ||
319 | item.HeaderSize += NFileHeader::kRecordSize; | 377 | item.HeaderSize += NFileHeader::kRecordSize; |
378 | |||
379 | if (OpenCallback) | ||
380 | { | ||
381 | RINOK(Progress(item, 0)); | ||
382 | } | ||
383 | |||
320 | isExtended = (Byte)buf[21 * 24]; | 384 | isExtended = (Byte)buf[21 * 24]; |
321 | if (isExtended != 0 && isExtended != 1) | 385 | if (isExtended != 0 && isExtended != 1) |
322 | return S_OK; | 386 | return S_OK; |
@@ -346,172 +410,711 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE | |||
346 | return S_OK; | 410 | return S_OK; |
347 | } | 411 | } |
348 | 412 | ||
413 | if (item.PackSize >= (UInt64)1 << 63) | ||
414 | return S_OK; | ||
415 | |||
349 | filled = true; | 416 | filled = true; |
350 | error = k_ErrorType_OK; | 417 | error = k_ErrorType_OK; |
351 | return S_OK; | 418 | return S_OK; |
352 | } | 419 | } |
353 | 420 | ||
354 | 421 | ||
355 | static HRESULT ReadDataToString(ISequentialInStream *stream, CItemEx &item, AString &s, EErrorType &error) | 422 | HRESULT CArchive::Progress(const CItemEx &item, UInt64 posOffset) |
356 | { | 423 | { |
357 | const unsigned packSize = (unsigned)item.GetPackSizeAligned(); | 424 | const UInt64 pos = item.Get_DataPos() + posOffset; |
358 | size_t processedSize = packSize; | 425 | if (NumFiles - NumFiles_Prev < (1 << 16) |
359 | HRESULT res = ReadStream(stream, s.GetBuf(packSize), &processedSize); | 426 | // && NumRecords - NumRecords_Prev < (1 << 16) |
360 | item.HeaderSize += (unsigned)processedSize; | 427 | && pos - Pos_Prev < ((UInt32)1 << 28)) |
361 | s.ReleaseBuf_CalcLen((unsigned)item.PackSize); | 428 | return S_OK; |
362 | RINOK(res); | 429 | { |
363 | if (processedSize != packSize) | 430 | Pos_Prev = pos; |
364 | error = k_ErrorType_UnexpectedEnd; | 431 | NumFiles_Prev = NumFiles; |
432 | // NumRecords_Prev = NumRecords; | ||
433 | // Sleep(100); // for debug | ||
434 | return OpenCallback->SetCompleted(&NumFiles, &pos); | ||
435 | } | ||
436 | } | ||
437 | |||
438 | |||
439 | HRESULT CArchive::ReadDataToBuffer(const CItemEx &item, | ||
440 | CTempBuffer &tb, size_t stringLimit) | ||
441 | { | ||
442 | tb.Init(); | ||
443 | UInt64 packSize = item.Get_PackSize_Aligned(); | ||
444 | if (packSize == 0) | ||
445 | return S_OK; | ||
446 | |||
447 | UInt64 pos; | ||
448 | |||
449 | { | ||
450 | size_t size = stringLimit; | ||
451 | if (size > packSize) | ||
452 | size = (size_t)packSize; | ||
453 | tb.Buffer.AllocAtLeast(size); | ||
454 | size_t processedSize = size; | ||
455 | const HRESULT res = ReadStream(SeqStream, tb.Buffer, &processedSize); | ||
456 | pos = processedSize; | ||
457 | if (processedSize != size) | ||
458 | { | ||
459 | error = k_ErrorType_UnexpectedEnd; | ||
460 | return res; | ||
461 | } | ||
462 | RINOK(res); | ||
463 | |||
464 | packSize -= size; | ||
465 | |||
466 | size_t i; | ||
467 | const Byte *p = tb.Buffer; | ||
468 | for (i = 0; i < size; i++) | ||
469 | if (p[i] == 0) | ||
470 | break; | ||
471 | if (i >= item.PackSize) | ||
472 | tb.StringSize_IsConfirmed = true; | ||
473 | if (i > item.PackSize) | ||
474 | { | ||
475 | tb.StringSize = (size_t)item.PackSize; | ||
476 | tb.IsNonZeroTail = true; | ||
477 | } | ||
478 | else | ||
479 | { | ||
480 | tb.StringSize = i; | ||
481 | if (i != size) | ||
482 | { | ||
483 | tb.StringSize_IsConfirmed = true; | ||
484 | if (IsBufNonZero(p + i, size - i)) | ||
485 | tb.IsNonZeroTail = true; | ||
486 | } | ||
487 | } | ||
488 | |||
489 | if (packSize == 0) | ||
490 | return S_OK; | ||
491 | } | ||
492 | |||
493 | if (InStream) | ||
494 | { | ||
495 | RINOK(InStream->Seek((Int64)packSize, STREAM_SEEK_CUR, NULL)); | ||
496 | return S_OK; | ||
497 | } | ||
498 | const unsigned kBufSize = 1 << 15; | ||
499 | Buffer.AllocAtLeast(kBufSize); | ||
500 | |||
501 | do | ||
502 | { | ||
503 | if (OpenCallback) | ||
504 | { | ||
505 | RINOK(Progress(item, pos)); | ||
506 | } | ||
507 | |||
508 | unsigned size = kBufSize; | ||
509 | if (size > packSize) | ||
510 | size = (unsigned)packSize; | ||
511 | size_t processedSize = size; | ||
512 | const HRESULT res = ReadStream(SeqStream, Buffer, &processedSize); | ||
513 | if (processedSize != size) | ||
514 | { | ||
515 | error = k_ErrorType_UnexpectedEnd; | ||
516 | return res; | ||
517 | } | ||
518 | if (!tb.IsNonZeroTail) | ||
519 | { | ||
520 | if (IsBufNonZero(Buffer, size)) | ||
521 | tb.IsNonZeroTail = true; | ||
522 | } | ||
523 | packSize -= size; | ||
524 | pos += size; | ||
525 | } | ||
526 | while (packSize != 0); | ||
365 | return S_OK; | 527 | return S_OK; |
366 | } | 528 | } |
529 | |||
367 | 530 | ||
368 | static bool ParsePaxLongName(const AString &src, AString &dest) | 531 | |
532 | struct CPaxInfo: public CPaxTimes | ||
369 | { | 533 | { |
370 | dest.Empty(); | 534 | bool DoubleTagError; |
371 | for (unsigned pos = 0;;) | 535 | bool TagParsingError; |
536 | bool UnknownLines_Overflow; | ||
537 | bool Size_Defined; | ||
538 | bool UID_Defined; | ||
539 | bool GID_Defined; | ||
540 | bool Path_Defined; | ||
541 | bool Link_Defined; | ||
542 | bool User_Defined; | ||
543 | bool Group_Defined; | ||
544 | |||
545 | UInt64 Size; | ||
546 | UInt32 UID; | ||
547 | UInt32 GID; | ||
548 | |||
549 | AString Path; | ||
550 | AString Link; | ||
551 | AString User; | ||
552 | AString Group; | ||
553 | AString UnknownLines; | ||
554 | |||
555 | bool ParseID(const AString &val, bool &defined, UInt32 &res) | ||
372 | { | 556 | { |
373 | if (pos >= src.Len()) | 557 | if (defined) |
558 | DoubleTagError = true; | ||
559 | if (val.IsEmpty()) | ||
374 | return false; | 560 | return false; |
375 | const char *start = src.Ptr(pos); | 561 | const char *end2; |
376 | const char *end; | 562 | res = ConvertStringToUInt32(val.Ptr(), &end2); |
377 | const UInt32 lineLen = ConvertStringToUInt32(start, &end); | 563 | if (*end2 != 0) |
378 | if (end == start) | ||
379 | return false; | 564 | return false; |
380 | if (*end != ' ') | 565 | defined = true; |
566 | return true; | ||
567 | } | ||
568 | |||
569 | bool ParsePax(const CTempBuffer &tb, bool isFile); | ||
570 | }; | ||
571 | |||
572 | |||
573 | static bool ParsePaxTime(const AString &src, CPaxTime &pt, bool &doubleTagError) | ||
574 | { | ||
575 | if (pt.IsDefined()) | ||
576 | doubleTagError = true; | ||
577 | pt.Clear(); | ||
578 | const char *s = src.Ptr(); | ||
579 | bool isNegative = false; | ||
580 | if (*s == '-') | ||
581 | { | ||
582 | isNegative = true; | ||
583 | s++; | ||
584 | } | ||
585 | const char *end; | ||
586 | { | ||
587 | UInt64 sec = ConvertStringToUInt64(s, &end); | ||
588 | if (s == end) | ||
381 | return false; | 589 | return false; |
382 | if (lineLen > src.Len() - pos) | 590 | if (sec >= ((UInt64)1 << 63)) |
383 | return false; | 591 | return false; |
384 | unsigned offset = (unsigned)(end - start) + 1; | 592 | if (isNegative) |
385 | if (lineLen < offset) | 593 | sec = -(Int64)sec; |
594 | pt.Sec = sec; | ||
595 | } | ||
596 | if (*end == 0) | ||
597 | { | ||
598 | pt.Ns = 0; | ||
599 | pt.NumDigits = 0; | ||
600 | return true; | ||
601 | } | ||
602 | if (*end != '.') | ||
603 | return false; | ||
604 | s = end + 1; | ||
605 | |||
606 | UInt32 ns = 0; | ||
607 | unsigned i; | ||
608 | const unsigned kNsDigits = 9; | ||
609 | for (i = 0;; i++) | ||
610 | { | ||
611 | const char c = s[i]; | ||
612 | if (c == 0) | ||
613 | break; | ||
614 | if (c < '0' || c > '9') | ||
386 | return false; | 615 | return false; |
387 | if (IsString1PrefixedByString2(src.Ptr(pos + offset), "path=")) | 616 | // we ignore digits after 9 digits as GNU TAR |
617 | if (i < kNsDigits) | ||
618 | { | ||
619 | ns *= 10; | ||
620 | ns += c - '0'; | ||
621 | } | ||
622 | } | ||
623 | pt.NumDigits = (i < kNsDigits ? i : kNsDigits); | ||
624 | while (i < kNsDigits) | ||
625 | { | ||
626 | ns *= 10; | ||
627 | i++; | ||
628 | } | ||
629 | if (isNegative && ns != 0) | ||
630 | { | ||
631 | pt.Sec--; | ||
632 | ns = (UInt32)1000 * 1000 * 1000 - ns; | ||
633 | } | ||
634 | pt.Ns = ns; | ||
635 | return true; | ||
636 | } | ||
637 | |||
638 | |||
639 | bool CPaxInfo::ParsePax(const CTempBuffer &tb, bool isFile) | ||
640 | { | ||
641 | DoubleTagError = false; | ||
642 | TagParsingError = false; | ||
643 | UnknownLines_Overflow = false; | ||
644 | Size_Defined = false; | ||
645 | UID_Defined = false; | ||
646 | GID_Defined = false; | ||
647 | Path_Defined = false; | ||
648 | Link_Defined = false; | ||
649 | User_Defined = false; | ||
650 | Group_Defined = false; | ||
651 | |||
652 | // CPaxTimes::Clear(); | ||
653 | |||
654 | const char *s = (const char *)(const void *)(const Byte *)tb.Buffer; | ||
655 | size_t rem = tb.StringSize; | ||
656 | |||
657 | Clear(); | ||
658 | |||
659 | AString name, val; | ||
660 | |||
661 | while (rem != 0) | ||
662 | { | ||
663 | unsigned i; | ||
664 | for (i = 0;; i++) | ||
388 | { | 665 | { |
389 | offset += 5; // "path=" | 666 | if (i > 24 || i >= rem) // we use limitation for size of (size) field |
390 | dest = src.Mid(pos + offset, lineLen - offset); | ||
391 | if (dest.IsEmpty()) | ||
392 | return false; | 667 | return false; |
393 | if (dest.Back() != '\n') | 668 | if (s[i] == ' ') |
669 | break; | ||
670 | } | ||
671 | if (i == 0) | ||
672 | return false; | ||
673 | const char *end; | ||
674 | const UInt32 size = ConvertStringToUInt32(s, &end); | ||
675 | const unsigned offset = (unsigned)(end - s) + 1; | ||
676 | if (size > rem | ||
677 | || size <= offset + 1 | ||
678 | || offset != i + 1 | ||
679 | || s[size - 1] != '\n') | ||
680 | return false; | ||
681 | |||
682 | for (i = offset; i < size; i++) | ||
683 | if (s[i] == 0) | ||
394 | return false; | 684 | return false; |
395 | dest.DeleteBack(); | 685 | |
396 | return true; | 686 | for (i = offset; i < size - 1; i++) |
687 | if (s[i] == '=') | ||
688 | break; | ||
689 | if (i == size - 1) | ||
690 | return false; | ||
691 | |||
692 | name.SetFrom(s + offset, i - offset); | ||
693 | val.SetFrom(s + i + 1, size - 1 - (i + 1)); | ||
694 | |||
695 | bool parsed = false; | ||
696 | if (isFile) | ||
697 | { | ||
698 | bool isDetectedName = true; | ||
699 | // only lower case (name) is supported | ||
700 | if (name.IsEqualTo("path")) | ||
701 | { | ||
702 | if (Path_Defined) | ||
703 | DoubleTagError = true; | ||
704 | Path = val; | ||
705 | Path_Defined = true; | ||
706 | parsed = true; | ||
707 | } | ||
708 | else if (name.IsEqualTo("linkpath")) | ||
709 | { | ||
710 | if (Link_Defined) | ||
711 | DoubleTagError = true; | ||
712 | Link = val; | ||
713 | Link_Defined = true; | ||
714 | parsed = true; | ||
715 | } | ||
716 | else if (name.IsEqualTo("uname")) | ||
717 | { | ||
718 | if (User_Defined) | ||
719 | DoubleTagError = true; | ||
720 | User = val; | ||
721 | User_Defined = true; | ||
722 | parsed = true; | ||
723 | } | ||
724 | else if (name.IsEqualTo("gname")) | ||
725 | { | ||
726 | if (Group_Defined) | ||
727 | DoubleTagError = true; | ||
728 | Group = val; | ||
729 | Group_Defined = true; | ||
730 | parsed = true; | ||
731 | } | ||
732 | else if (name.IsEqualTo("uid")) | ||
733 | { | ||
734 | parsed = ParseID(val, UID_Defined, UID); | ||
735 | } | ||
736 | else if (name.IsEqualTo("gid")) | ||
737 | { | ||
738 | parsed = ParseID(val, GID_Defined, GID); | ||
739 | } | ||
740 | else if (name.IsEqualTo("size")) | ||
741 | { | ||
742 | if (Size_Defined) | ||
743 | DoubleTagError = true; | ||
744 | Size_Defined = false; | ||
745 | if (!val.IsEmpty()) | ||
746 | { | ||
747 | const char *end2; | ||
748 | Size = ConvertStringToUInt64(val.Ptr(), &end2); | ||
749 | if (*end2 == 0) | ||
750 | { | ||
751 | Size_Defined = true; | ||
752 | parsed = true; | ||
753 | } | ||
754 | } | ||
755 | } | ||
756 | else if (name.IsEqualTo("mtime")) | ||
757 | { parsed = ParsePaxTime(val, MTime, DoubleTagError); } | ||
758 | else if (name.IsEqualTo("atime")) | ||
759 | { parsed = ParsePaxTime(val, ATime, DoubleTagError); } | ||
760 | else if (name.IsEqualTo("ctime")) | ||
761 | { parsed = ParsePaxTime(val, CTime, DoubleTagError); } | ||
762 | else | ||
763 | isDetectedName = false; | ||
764 | if (isDetectedName && !parsed) | ||
765 | TagParsingError = true; | ||
397 | } | 766 | } |
398 | pos += lineLen; | 767 | if (!parsed) |
768 | { | ||
769 | if (!UnknownLines_Overflow) | ||
770 | { | ||
771 | const unsigned addSize = size - offset; | ||
772 | if (UnknownLines.Len() + addSize < (1 << 16)) | ||
773 | UnknownLines.AddFrom(s + offset, addSize); | ||
774 | else | ||
775 | UnknownLines_Overflow = true; | ||
776 | } | ||
777 | } | ||
778 | |||
779 | s += size; | ||
780 | rem -= size; | ||
399 | } | 781 | } |
782 | return true; | ||
400 | } | 783 | } |
401 | 784 | ||
402 | HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, EErrorType &error) | 785 | |
786 | HRESULT CArchive::ReadItem2(CItemEx &item) | ||
403 | { | 787 | { |
788 | // CItem | ||
789 | |||
790 | item.SparseBlocks.Clear(); | ||
791 | item.PaxTimes.Clear(); | ||
792 | |||
793 | // CItemEx | ||
794 | |||
404 | item.HeaderSize = 0; | 795 | item.HeaderSize = 0; |
796 | item.Num_Pax_Records = 0; | ||
405 | 797 | ||
406 | bool flagL = false; | 798 | item.LongName_WasUsed = false; |
407 | bool flagK = false; | 799 | item.LongName_WasUsed_2 = false; |
408 | AString nameL; | 800 | |
409 | AString nameK; | 801 | item.LongLink_WasUsed = false; |
410 | AString pax; | 802 | item.LongLink_WasUsed_2 = false; |
803 | |||
804 | item.HeaderError = false; | ||
805 | item.IsSignedChecksum = false; | ||
806 | item.Prefix_WasUsed = false; | ||
411 | 807 | ||
412 | for (;;) | 808 | item.Pax_Error = false; |
809 | item.Pax_Overflow = false; | ||
810 | item.pax_path_WasUsed = false; | ||
811 | item.pax_link_WasUsed = false; | ||
812 | item.pax_size_WasUsed = false; | ||
813 | |||
814 | item.PaxExtra.Clear(); | ||
815 | |||
816 | item.EncodingCharacts.Clear(); | ||
817 | |||
818 | // CArchive temp variable | ||
819 | |||
820 | NameBuf.Init(); | ||
821 | LinkBuf.Init(); | ||
822 | PaxBuf.Init(); | ||
823 | PaxBuf_global.Init(); | ||
824 | |||
825 | for (unsigned recordIndex = 0;; recordIndex++) | ||
413 | { | 826 | { |
414 | RINOK(GetNextItemReal(stream, filled, item, error)); | 827 | if (OpenCallback) |
828 | { | ||
829 | RINOK(Progress(item, 0)); | ||
830 | } | ||
831 | |||
832 | RINOK(GetNextItemReal(item)); | ||
833 | |||
834 | // NumRecords++; | ||
835 | |||
415 | if (!filled) | 836 | if (!filled) |
416 | { | 837 | { |
417 | if (error == k_ErrorType_OK && (flagL || flagK)) | 838 | if (error == k_ErrorType_OK) |
839 | if (item.LongName_WasUsed || | ||
840 | item.LongLink_WasUsed || | ||
841 | item.Num_Pax_Records != 0) | ||
418 | error = k_ErrorType_Corrupted; | 842 | error = k_ErrorType_Corrupted; |
419 | return S_OK; | ||
420 | } | 843 | } |
421 | 844 | ||
422 | if (error != k_ErrorType_OK) | 845 | if (error != k_ErrorType_OK) |
423 | return S_OK; | 846 | return S_OK; |
424 | 847 | ||
425 | if (item.LinkFlag == NFileHeader::NLinkFlag::kGnu_LongName || // file contains a long name | 848 | const char lf = item.LinkFlag; |
426 | item.LinkFlag == NFileHeader::NLinkFlag::kGnu_LongLink) // file contains a long linkname | 849 | if (lf == NFileHeader::NLinkFlag::kGnu_LongName || |
850 | lf == NFileHeader::NLinkFlag::kGnu_LongLink) | ||
427 | { | 851 | { |
428 | AString *name; | 852 | // GNU tar ignores item.Name after LinkFlag test |
429 | if (item.LinkFlag == NFileHeader::NLinkFlag::kGnu_LongName) | 853 | // 22.00 : now we also ignore item.Name here |
430 | { if (flagL) return S_OK; flagL = true; name = &nameL; } | 854 | /* |
431 | else | ||
432 | { if (flagK) return S_OK; flagK = true; name = &nameK; } | ||
433 | |||
434 | if (item.Name != NFileHeader::kLongLink && | 855 | if (item.Name != NFileHeader::kLongLink && |
435 | item.Name != NFileHeader::kLongLink2) | 856 | item.Name != NFileHeader::kLongLink2) |
857 | { | ||
858 | break; | ||
859 | // return S_OK; | ||
860 | } | ||
861 | */ | ||
862 | |||
863 | CTempBuffer *tb = | ||
864 | lf == NFileHeader::NLinkFlag::kGnu_LongName ? | ||
865 | &NameBuf : | ||
866 | &LinkBuf; | ||
867 | |||
868 | /* | ||
869 | if (item.PackSize > (1 << 29)) | ||
870 | { | ||
871 | // break; | ||
436 | return S_OK; | 872 | return S_OK; |
437 | if (item.PackSize > (1 << 14)) | 873 | } |
438 | return S_OK; | 874 | */ |
439 | 875 | ||
440 | RINOK(ReadDataToString(stream, item, *name, error)); | 876 | const unsigned kLongNameSizeMax = (unsigned)1 << 14; |
877 | RINOK(ReadDataToBuffer(item, *tb, kLongNameSizeMax)); | ||
441 | if (error != k_ErrorType_OK) | 878 | if (error != k_ErrorType_OK) |
442 | return S_OK; | 879 | return S_OK; |
443 | 880 | ||
881 | if (lf == NFileHeader::NLinkFlag::kGnu_LongName) | ||
882 | { | ||
883 | item.LongName_WasUsed_2 = | ||
884 | item.LongName_WasUsed; | ||
885 | item.LongName_WasUsed = true; | ||
886 | } | ||
887 | else | ||
888 | { | ||
889 | item.LongLink_WasUsed_2 = | ||
890 | item.LongLink_WasUsed; | ||
891 | item.LongLink_WasUsed = true; | ||
892 | } | ||
893 | |||
894 | if (!tb->StringSize_IsConfirmed) | ||
895 | tb->StringSize = 0; | ||
896 | item.HeaderSize += item.Get_PackSize_Aligned(); | ||
897 | if (tb->StringSize == 0 || | ||
898 | tb->StringSize + 1 != item.PackSize) | ||
899 | item.HeaderError = true; | ||
900 | if (tb->IsNonZeroTail) | ||
901 | item.HeaderError = true; | ||
444 | continue; | 902 | continue; |
445 | } | 903 | } |
446 | 904 | ||
447 | switch (item.LinkFlag) | 905 | if (lf == NFileHeader::NLinkFlag::kGlobal || |
906 | lf == NFileHeader::NLinkFlag::kPax || | ||
907 | lf == NFileHeader::NLinkFlag::kPax_2) | ||
448 | { | 908 | { |
449 | case 'g': | 909 | // GNU tar ignores item.Name after LinkFlag test |
450 | case 'x': | 910 | // 22.00 : now we also ignore item.Name here |
451 | case 'X': | 911 | /* |
912 | if (item.PackSize > (UInt32)1 << 26) | ||
452 | { | 913 | { |
453 | const char *s = item.Name.Ptr(); | 914 | break; // we don't want big PaxBuf files |
454 | if (IsString1PrefixedByString2(s, "./")) | 915 | // return S_OK; |
455 | s += 2; | ||
456 | if (IsString1PrefixedByString2(s, "./")) | ||
457 | s += 2; | ||
458 | if ( IsString1PrefixedByString2(s, "PaxHeader/") | ||
459 | || IsString1PrefixedByString2(s, "PaxHeaders.X/") | ||
460 | || IsString1PrefixedByString2(s, "PaxHeaders.4467/") | ||
461 | || StringsAreEqual_Ascii(s, "@PaxHeader") | ||
462 | ) | ||
463 | { | ||
464 | RINOK(ReadDataToString(stream, item, pax, error)); | ||
465 | if (error != k_ErrorType_OK) | ||
466 | return S_OK; | ||
467 | continue; | ||
468 | } | ||
469 | break; | ||
470 | } | 916 | } |
471 | case NFileHeader::NLinkFlag::kDumpDir: | 917 | */ |
918 | const unsigned kParsingPaxSizeMax = (unsigned)1 << 26; | ||
919 | |||
920 | const bool isStartHeader = (item.HeaderSize == NFileHeader::kRecordSize); | ||
921 | |||
922 | CTempBuffer *tb = (lf == NFileHeader::NLinkFlag::kGlobal ? &PaxBuf_global : &PaxBuf); | ||
923 | |||
924 | RINOK(ReadDataToBuffer(item, *tb, kParsingPaxSizeMax)); | ||
925 | if (error != k_ErrorType_OK) | ||
926 | return S_OK; | ||
927 | |||
928 | item.HeaderSize += item.Get_PackSize_Aligned(); | ||
929 | |||
930 | if (tb->StringSize != item.PackSize | ||
931 | || tb->StringSize == 0 | ||
932 | || tb->IsNonZeroTail) | ||
933 | item.Pax_Error = true; | ||
934 | |||
935 | item.Num_Pax_Records++; | ||
936 | if (lf != NFileHeader::NLinkFlag::kGlobal) | ||
472 | { | 937 | { |
473 | break; | 938 | item.PaxExtra.RecordPath = item.Name; |
474 | // GNU Extensions to the Archive Format | 939 | continue; |
475 | } | 940 | } |
476 | case NFileHeader::NLinkFlag::kSparse: | 941 | // break; // for debug |
477 | { | 942 | { |
478 | break; | 943 | if (PaxGlobal_Defined) |
479 | // GNU Extensions to the Archive Format | 944 | _is_PaxGlobal_Error = true; |
945 | CPaxInfo paxInfo; | ||
946 | if (paxInfo.ParsePax(PaxBuf_global, false)) | ||
947 | { | ||
948 | PaxGlobal.RawLines = paxInfo.UnknownLines; | ||
949 | PaxGlobal.RecordPath = item.Name; | ||
950 | PaxGlobal_Defined = true; | ||
951 | } | ||
952 | else | ||
953 | _is_PaxGlobal_Error = true; | ||
954 | if (isStartHeader) | ||
955 | { | ||
956 | // we skip global pax header info after parsing | ||
957 | item.HeaderPos += item.HeaderSize; | ||
958 | item.HeaderSize = 0; | ||
959 | } | ||
480 | } | 960 | } |
481 | default: | 961 | continue; |
482 | if (item.LinkFlag > '7' || (item.LinkFlag < '0' && item.LinkFlag != 0)) | ||
483 | return S_OK; | ||
484 | } | 962 | } |
485 | 963 | ||
486 | if (flagL) | 964 | /* |
965 | if (lf == NFileHeader::NLinkFlag::kDumpDir || | ||
966 | lf == NFileHeader::NLinkFlag::kSparse) | ||
487 | { | 967 | { |
488 | item.Name = nameL; | 968 | // GNU Extensions to the Archive Format |
489 | item.NameCouldBeReduced = false; | 969 | break; |
490 | } | 970 | } |
491 | 971 | if (lf > '7' || (lf < '0' && lf != 0)) | |
492 | if (flagK) | ||
493 | { | 972 | { |
494 | item.LinkName = nameK; | 973 | break; |
495 | item.LinkNameCouldBeReduced = false; | 974 | // return S_OK; |
496 | } | 975 | } |
497 | 976 | */ | |
498 | error = k_ErrorType_OK; | 977 | break; |
499 | 978 | } | |
500 | if (!pax.IsEmpty()) | 979 | |
980 | // we still use name from main header, if long_name is bad | ||
981 | if (item.LongName_WasUsed && NameBuf.StringSize != 0) | ||
982 | { | ||
983 | NameBuf.CopyToString(item.Name); | ||
984 | // item.Name_CouldBeReduced = false; | ||
985 | } | ||
986 | |||
987 | if (item.LongLink_WasUsed) | ||
988 | { | ||
989 | // we use empty link, if long_link is bad | ||
990 | LinkBuf.CopyToString(item.LinkName); | ||
991 | // item.LinkName_CouldBeReduced = false; | ||
992 | } | ||
993 | |||
994 | error = k_ErrorType_OK; | ||
995 | |||
996 | if (PaxBuf.StringSize != 0) | ||
997 | { | ||
998 | CPaxInfo paxInfo; | ||
999 | if (!paxInfo.ParsePax(PaxBuf, true)) | ||
1000 | item.Pax_Error = true; | ||
1001 | else | ||
501 | { | 1002 | { |
502 | AString name; | 1003 | if (paxInfo.Path_Defined) // if (!paxInfo.Path.IsEmpty()) |
503 | if (ParsePaxLongName(pax, name)) | 1004 | { |
504 | item.Name = name; | 1005 | item.Name = paxInfo.Path; |
505 | else | 1006 | item.pax_path_WasUsed = true; |
1007 | } | ||
1008 | if (paxInfo.Link_Defined) // (!paxInfo.Link.IsEmpty()) | ||
1009 | { | ||
1010 | item.LinkName = paxInfo.Link; | ||
1011 | item.pax_link_WasUsed = true; | ||
1012 | } | ||
1013 | if (paxInfo.User_Defined) | ||
1014 | { | ||
1015 | item.User = paxInfo.User; | ||
1016 | // item.pax_uname_WasUsed = true; | ||
1017 | } | ||
1018 | if (paxInfo.Group_Defined) | ||
1019 | { | ||
1020 | item.Group = paxInfo.Group; | ||
1021 | // item.pax_gname_WasUsed = true; | ||
1022 | } | ||
1023 | if (paxInfo.UID_Defined) | ||
506 | { | 1024 | { |
507 | // no "path" property is allowed in pax4467 | 1025 | item.UID = (UInt32)paxInfo.UID; |
508 | // error = k_ErrorType_Warning; | ||
509 | } | 1026 | } |
510 | pax.Empty(); | 1027 | if (paxInfo.GID_Defined) |
1028 | { | ||
1029 | item.GID = (UInt32)paxInfo.GID; | ||
1030 | } | ||
1031 | |||
1032 | if (paxInfo.Size_Defined) | ||
1033 | { | ||
1034 | const UInt64 piSize = paxInfo.Size; | ||
1035 | // GNU TAR ignores (item.Size) in that case | ||
1036 | if (item.Size != 0 && item.Size != piSize) | ||
1037 | item.Pax_Error = true; | ||
1038 | item.Size = piSize; | ||
1039 | item.PackSize = piSize; | ||
1040 | item.pax_size_WasUsed = true; | ||
1041 | } | ||
1042 | |||
1043 | item.PaxTimes = paxInfo; | ||
1044 | item.PaxExtra.RawLines = paxInfo.UnknownLines; | ||
1045 | if (paxInfo.UnknownLines_Overflow) | ||
1046 | item.Pax_Overflow = true; | ||
1047 | if (paxInfo.TagParsingError) | ||
1048 | item.Pax_Error = true; | ||
1049 | if (paxInfo.DoubleTagError) | ||
1050 | item.Pax_Error = true; | ||
511 | } | 1051 | } |
1052 | } | ||
512 | 1053 | ||
513 | return S_OK; | 1054 | return S_OK; |
1055 | } | ||
1056 | |||
1057 | |||
1058 | |||
1059 | HRESULT CArchive::ReadItem(CItemEx &item) | ||
1060 | { | ||
1061 | item.HeaderPos = _phySize; | ||
1062 | |||
1063 | const HRESULT res = ReadItem2(item); | ||
1064 | |||
1065 | /* | ||
1066 | if (error == k_ErrorType_Warning) | ||
1067 | _is_Warning = true; | ||
1068 | else | ||
1069 | */ | ||
1070 | |||
1071 | if (error != k_ErrorType_OK) | ||
1072 | _error = error; | ||
1073 | |||
1074 | RINOK(res); | ||
1075 | |||
1076 | if (filled) | ||
1077 | { | ||
1078 | if (item.IsMagic_GNU()) | ||
1079 | _are_Gnu = true; | ||
1080 | else if (item.IsMagic_Posix_ustar_00()) | ||
1081 | _are_Posix = true; | ||
1082 | |||
1083 | if (item.Num_Pax_Records != 0) | ||
1084 | _are_Pax = true; | ||
1085 | |||
1086 | if (item.PaxTimes.MTime.IsDefined()) _are_mtime = true; | ||
1087 | if (item.PaxTimes.ATime.IsDefined()) _are_atime = true; | ||
1088 | if (item.PaxTimes.CTime.IsDefined()) _are_ctime = true; | ||
1089 | |||
1090 | if (item.pax_path_WasUsed) | ||
1091 | _are_pax_path = true; | ||
1092 | if (item.pax_link_WasUsed) | ||
1093 | _are_pax_link = true; | ||
1094 | if (item.LongName_WasUsed) | ||
1095 | _are_LongName = true; | ||
1096 | if (item.LongLink_WasUsed) | ||
1097 | _are_LongLink = true; | ||
1098 | if (item.Prefix_WasUsed) | ||
1099 | _pathPrefix_WasUsed = true; | ||
1100 | /* | ||
1101 | if (item.IsSparse()) | ||
1102 | _isSparse = true; | ||
1103 | */ | ||
1104 | if (item.Is_PaxExtendedHeader()) | ||
1105 | _are_Pax_Items = true; | ||
1106 | if (item.IsThereWarning() | ||
1107 | || item.HeaderError | ||
1108 | || item.Pax_Error) | ||
1109 | _is_Warning = true; | ||
514 | } | 1110 | } |
1111 | |||
1112 | const UInt64 headerEnd = item.HeaderPos + item.HeaderSize; | ||
1113 | // _headersSize += headerEnd - _phySize; | ||
1114 | // we don't count skipped records | ||
1115 | _headersSize += item.HeaderSize; | ||
1116 | _phySize = headerEnd; | ||
1117 | return S_OK; | ||
515 | } | 1118 | } |
516 | 1119 | ||
517 | }} | 1120 | }} |
diff --git a/CPP/7zip/Archive/Tar/TarIn.h b/CPP/7zip/Archive/Tar/TarIn.h index 1c508bc..e99599a 100644 --- a/CPP/7zip/Archive/Tar/TarIn.h +++ b/CPP/7zip/Archive/Tar/TarIn.h | |||
@@ -3,7 +3,7 @@ | |||
3 | #ifndef __ARCHIVE_TAR_IN_H | 3 | #ifndef __ARCHIVE_TAR_IN_H |
4 | #define __ARCHIVE_TAR_IN_H | 4 | #define __ARCHIVE_TAR_IN_H |
5 | 5 | ||
6 | #include "../../IStream.h" | 6 | #include "../IArchive.h" |
7 | 7 | ||
8 | #include "TarItem.h" | 8 | #include "TarItem.h" |
9 | 9 | ||
@@ -14,11 +14,133 @@ enum EErrorType | |||
14 | { | 14 | { |
15 | k_ErrorType_OK, | 15 | k_ErrorType_OK, |
16 | k_ErrorType_Corrupted, | 16 | k_ErrorType_Corrupted, |
17 | k_ErrorType_UnexpectedEnd, | 17 | k_ErrorType_UnexpectedEnd |
18 | k_ErrorType_Warning | 18 | // , k_ErrorType_Warning |
19 | }; | ||
20 | |||
21 | |||
22 | struct CTempBuffer | ||
23 | { | ||
24 | CByteBuffer Buffer; | ||
25 | size_t StringSize; // num characters before zero Byte (StringSize <= item.PackSize) | ||
26 | bool IsNonZeroTail; | ||
27 | bool StringSize_IsConfirmed; | ||
28 | |||
29 | void CopyToString(AString &s) | ||
30 | { | ||
31 | s.Empty(); | ||
32 | if (StringSize != 0) | ||
33 | s.SetFrom((const char *)(const void *)(const Byte *)Buffer, (unsigned)StringSize); | ||
34 | } | ||
35 | |||
36 | void Init() | ||
37 | { | ||
38 | StringSize = 0; | ||
39 | IsNonZeroTail = false; | ||
40 | StringSize_IsConfirmed = false; | ||
41 | } | ||
42 | }; | ||
43 | |||
44 | |||
45 | class CArchive | ||
46 | { | ||
47 | public: | ||
48 | bool _phySize_Defined; | ||
49 | bool _is_Warning; | ||
50 | bool PaxGlobal_Defined; | ||
51 | bool _is_PaxGlobal_Error; | ||
52 | bool _are_Pax_Items; | ||
53 | bool _are_Gnu; | ||
54 | bool _are_Posix; | ||
55 | bool _are_Pax; | ||
56 | bool _are_mtime; | ||
57 | bool _are_atime; | ||
58 | bool _are_ctime; | ||
59 | bool _are_pax_path; | ||
60 | bool _are_pax_link; | ||
61 | bool _are_LongName; | ||
62 | bool _are_LongLink; | ||
63 | bool _pathPrefix_WasUsed; | ||
64 | // bool _isSparse; | ||
65 | |||
66 | // temp internal vars for ReadItem(): | ||
67 | bool filled; | ||
68 | private: | ||
69 | EErrorType error; | ||
70 | |||
71 | public: | ||
72 | UInt64 _phySize; | ||
73 | UInt64 _headersSize; | ||
74 | EErrorType _error; | ||
75 | |||
76 | ISequentialInStream *SeqStream; | ||
77 | IInStream *InStream; | ||
78 | IArchiveOpenCallback *OpenCallback; | ||
79 | UInt64 NumFiles; | ||
80 | UInt64 NumFiles_Prev; | ||
81 | UInt64 Pos_Prev; | ||
82 | // UInt64 NumRecords; | ||
83 | // UInt64 NumRecords_Prev; | ||
84 | |||
85 | CPaxExtra PaxGlobal; | ||
86 | |||
87 | void Clear() | ||
88 | { | ||
89 | SeqStream = NULL; | ||
90 | InStream = NULL; | ||
91 | OpenCallback = NULL; | ||
92 | NumFiles = 0; | ||
93 | NumFiles_Prev = 0; | ||
94 | Pos_Prev = 0; | ||
95 | // NumRecords = 0; | ||
96 | // NumRecords_Prev = 0; | ||
97 | |||
98 | PaxGlobal.Clear(); | ||
99 | PaxGlobal_Defined = false; | ||
100 | _is_PaxGlobal_Error = false; | ||
101 | _are_Pax_Items = false; // if there are final paxItems | ||
102 | _are_Gnu = false; | ||
103 | _are_Posix = false; | ||
104 | _are_Pax = false; | ||
105 | _are_mtime = false; | ||
106 | _are_atime = false; | ||
107 | _are_ctime = false; | ||
108 | _are_pax_path = false; | ||
109 | _are_pax_link = false; | ||
110 | _are_LongName = false; | ||
111 | _are_LongLink = false; | ||
112 | _pathPrefix_WasUsed = false; | ||
113 | // _isSparse = false; | ||
114 | |||
115 | _is_Warning = false; | ||
116 | _error = k_ErrorType_OK; | ||
117 | |||
118 | _phySize_Defined = false; | ||
119 | _phySize = 0; | ||
120 | _headersSize = 0; | ||
121 | } | ||
122 | |||
123 | private: | ||
124 | CTempBuffer NameBuf; | ||
125 | CTempBuffer LinkBuf; | ||
126 | CTempBuffer PaxBuf; | ||
127 | CTempBuffer PaxBuf_global; | ||
128 | |||
129 | CByteBuffer Buffer; | ||
130 | |||
131 | HRESULT ReadDataToBuffer(const CItemEx &item, CTempBuffer &tb, size_t stringLimit); | ||
132 | HRESULT Progress(const CItemEx &item, UInt64 posOffset); | ||
133 | HRESULT GetNextItemReal(CItemEx &item); | ||
134 | HRESULT ReadItem2(CItemEx &itemInfo); | ||
135 | public: | ||
136 | CArchive() | ||
137 | { | ||
138 | // we will call Clear() in CHandler::Close(). | ||
139 | // Clear(); // it's not required here | ||
140 | } | ||
141 | HRESULT ReadItem(CItemEx &itemInfo); | ||
19 | }; | 142 | }; |
20 | 143 | ||
21 | HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &itemInfo, EErrorType &error); | ||
22 | 144 | ||
23 | API_FUNC_IsArc IsArc_Tar(const Byte *p, size_t size); | 145 | API_FUNC_IsArc IsArc_Tar(const Byte *p, size_t size); |
24 | 146 | ||
diff --git a/CPP/7zip/Archive/Tar/TarItem.h b/CPP/7zip/Archive/Tar/TarItem.h index f947786..738618f 100644 --- a/CPP/7zip/Archive/Tar/TarItem.h +++ b/CPP/7zip/Archive/Tar/TarItem.h | |||
@@ -6,8 +6,6 @@ | |||
6 | #include "../../../Common/MyLinux.h" | 6 | #include "../../../Common/MyLinux.h" |
7 | #include "../../../Common/UTFConvert.h" | 7 | #include "../../../Common/UTFConvert.h" |
8 | 8 | ||
9 | #include "../Common/ItemNameUtils.h" | ||
10 | |||
11 | #include "TarHeader.h" | 9 | #include "TarHeader.h" |
12 | 10 | ||
13 | namespace NArchive { | 11 | namespace NArchive { |
@@ -19,50 +17,149 @@ struct CSparseBlock | |||
19 | UInt64 Size; | 17 | UInt64 Size; |
20 | }; | 18 | }; |
21 | 19 | ||
20 | |||
21 | enum EPaxTimeRemoveZeroMode | ||
22 | { | ||
23 | k_PaxTimeMode_DontRemoveZero, | ||
24 | k_PaxTimeMode_RemoveZero_if_PureSecondOnly, | ||
25 | k_PaxTimeMode_RemoveZero_Always | ||
26 | }; | ||
27 | |||
28 | struct CTimeOptions | ||
29 | { | ||
30 | EPaxTimeRemoveZeroMode RemoveZeroMode; | ||
31 | unsigned NumDigitsMax; | ||
32 | |||
33 | void Init() | ||
34 | { | ||
35 | RemoveZeroMode = k_PaxTimeMode_RemoveZero_if_PureSecondOnly; | ||
36 | NumDigitsMax = 0; | ||
37 | } | ||
38 | CTimeOptions() { Init(); } | ||
39 | }; | ||
40 | |||
41 | |||
42 | struct CPaxTime | ||
43 | { | ||
44 | Int32 NumDigits; // -1 means undefined | ||
45 | UInt32 Ns; // it's smaller than 1G. Even if (Sec < 0), larger (Ns) value means newer files. | ||
46 | Int64 Sec; // can be negative | ||
47 | |||
48 | Int64 GetSec() const { return NumDigits != -1 ? Sec : 0; } | ||
49 | |||
50 | bool IsDefined() const { return NumDigits != -1; } | ||
51 | // bool IsDefined_And_nonZero() const { return NumDigits != -1 && (Sec != 0 || Ns != 0); } | ||
52 | |||
53 | void Clear() | ||
54 | { | ||
55 | NumDigits = -1; | ||
56 | Ns = 0; | ||
57 | Sec = 0; | ||
58 | } | ||
59 | CPaxTime() { Clear(); } | ||
60 | |||
61 | /* | ||
62 | void ReducePrecison(int numDigits) | ||
63 | { | ||
64 | // we don't use this->NumDigits here | ||
65 | if (numDigits > 0) | ||
66 | { | ||
67 | if (numDigits >= 9) | ||
68 | return; | ||
69 | UInt32 r = 1; | ||
70 | for (unsigned i = numDigits; i < 9; i++) | ||
71 | r *= 10; | ||
72 | Ns /= r; | ||
73 | Ns *= r; | ||
74 | return; | ||
75 | } | ||
76 | Ns = 0; | ||
77 | if (numDigits == 0) | ||
78 | return; | ||
79 | UInt32 r; | ||
80 | if (numDigits == -1) r = 60; | ||
81 | else if (numDigits == -2) r = 60 * 60; | ||
82 | else if (numDigits == -3) r = 60 * 60 * 24; | ||
83 | else return; | ||
84 | Sec /= r; | ||
85 | Sec *= r; | ||
86 | } | ||
87 | */ | ||
88 | }; | ||
89 | |||
90 | |||
91 | struct CPaxTimes | ||
92 | { | ||
93 | CPaxTime MTime; | ||
94 | CPaxTime ATime; | ||
95 | CPaxTime CTime; | ||
96 | |||
97 | void Clear() | ||
98 | { | ||
99 | MTime.Clear(); | ||
100 | ATime.Clear(); | ||
101 | CTime.Clear(); | ||
102 | } | ||
103 | |||
104 | /* | ||
105 | void ReducePrecison(int numDigits) | ||
106 | { | ||
107 | MTime.ReducePrecison(numDigits); | ||
108 | CTime.ReducePrecison(numDigits); | ||
109 | ATime.ReducePrecison(numDigits); | ||
110 | } | ||
111 | */ | ||
112 | }; | ||
113 | |||
114 | |||
22 | struct CItem | 115 | struct CItem |
23 | { | 116 | { |
24 | AString Name; | ||
25 | UInt64 PackSize; | 117 | UInt64 PackSize; |
26 | UInt64 Size; | 118 | UInt64 Size; |
27 | Int64 MTime; | 119 | Int64 MTime; |
28 | 120 | ||
121 | char LinkFlag; | ||
122 | bool DeviceMajor_Defined; | ||
123 | bool DeviceMinor_Defined; | ||
124 | |||
29 | UInt32 Mode; | 125 | UInt32 Mode; |
30 | UInt32 UID; | 126 | UInt32 UID; |
31 | UInt32 GID; | 127 | UInt32 GID; |
32 | UInt32 DeviceMajor; | 128 | UInt32 DeviceMajor; |
33 | UInt32 DeviceMinor; | 129 | UInt32 DeviceMinor; |
34 | 130 | ||
131 | AString Name; | ||
35 | AString LinkName; | 132 | AString LinkName; |
36 | AString User; | 133 | AString User; |
37 | AString Group; | 134 | AString Group; |
38 | 135 | ||
39 | char Magic[8]; | 136 | char Magic[8]; |
40 | char LinkFlag; | 137 | |
41 | bool DeviceMajorDefined; | 138 | CPaxTimes PaxTimes; |
42 | bool DeviceMinorDefined; | ||
43 | 139 | ||
44 | CRecordVector<CSparseBlock> SparseBlocks; | 140 | CRecordVector<CSparseBlock> SparseBlocks; |
45 | 141 | ||
46 | void SetDefaultWriteFields() | 142 | void SetMagic_Posix(bool posixMode) |
47 | { | 143 | { |
48 | DeviceMajorDefined = false; | 144 | memcpy(Magic, posixMode ? |
49 | DeviceMinorDefined = false; | 145 | NFileHeader::NMagic::k_Posix_ustar_00 : |
50 | UID = 0; | 146 | NFileHeader::NMagic::k_GNU_ustar__, |
51 | GID = 0; | 147 | 8); |
52 | memcpy(Magic, NFileHeader::NMagic::kUsTar_GNU, 8); | ||
53 | } | 148 | } |
54 | 149 | ||
55 | bool IsSymLink() const { return LinkFlag == NFileHeader::NLinkFlag::kSymLink && (Size == 0); } | 150 | bool Is_SymLink() const { return LinkFlag == NFileHeader::NLinkFlag::kSymLink && (Size == 0); } |
56 | bool IsHardLink() const { return LinkFlag == NFileHeader::NLinkFlag::kHardLink; } | 151 | bool Is_HardLink() const { return LinkFlag == NFileHeader::NLinkFlag::kHardLink; } |
57 | bool IsSparse() const { return LinkFlag == NFileHeader::NLinkFlag::kSparse; } | 152 | bool Is_Sparse() const { return LinkFlag == NFileHeader::NLinkFlag::kSparse; } |
58 | UInt64 GetUnpackSize() const { return IsSymLink() ? LinkName.Len() : Size; } | 153 | |
59 | bool IsPaxExtendedHeader() const | 154 | UInt64 Get_UnpackSize() const { return Is_SymLink() ? LinkName.Len() : Size; } |
155 | |||
156 | bool Is_PaxExtendedHeader() const | ||
60 | { | 157 | { |
61 | switch (LinkFlag) | 158 | switch (LinkFlag) |
62 | { | 159 | { |
63 | case 'g': | 160 | case NFileHeader::NLinkFlag::kPax: |
64 | case 'x': | 161 | case NFileHeader::NLinkFlag::kPax_2: |
65 | case 'X': // Check it | 162 | case NFileHeader::NLinkFlag::kGlobal: |
66 | return true; | 163 | return true; |
67 | } | 164 | } |
68 | return false; | 165 | return false; |
@@ -72,6 +169,17 @@ struct CItem | |||
72 | { | 169 | { |
73 | return (Mode & ~(UInt32)MY_LIN_S_IFMT) | Get_FileTypeMode_from_LinkFlag(); | 170 | return (Mode & ~(UInt32)MY_LIN_S_IFMT) | Get_FileTypeMode_from_LinkFlag(); |
74 | } | 171 | } |
172 | |||
173 | void Set_LinkFlag_for_File(UInt32 mode) | ||
174 | { | ||
175 | Byte lf = NFileHeader::NLinkFlag::kNormal; | ||
176 | if (MY_LIN_S_ISCHR(mode)) lf = NFileHeader::NLinkFlag::kCharacter; | ||
177 | else if (MY_LIN_S_ISBLK(mode)) lf = NFileHeader::NLinkFlag::kBlock; | ||
178 | else if (MY_LIN_S_ISFIFO(mode)) lf = NFileHeader::NLinkFlag::kFIFO; | ||
179 | // else if (MY_LIN_S_ISDIR(mode)) lf = NFileHeader::NLinkFlag::kDirectory; | ||
180 | // else if (MY_LIN_S_ISLNK(mode)) lf = NFileHeader::NLinkFlag::kSymLink; | ||
181 | LinkFlag = lf; | ||
182 | } | ||
75 | 183 | ||
76 | UInt32 Get_FileTypeMode_from_LinkFlag() const | 184 | UInt32 Get_FileTypeMode_from_LinkFlag() const |
77 | { | 185 | { |
@@ -82,10 +190,10 @@ struct CItem | |||
82 | case NFileHeader::NLinkFlag::kDumpDir: | 190 | case NFileHeader::NLinkFlag::kDumpDir: |
83 | return MY_LIN_S_IFDIR; | 191 | return MY_LIN_S_IFDIR; |
84 | */ | 192 | */ |
85 | case NFileHeader::NLinkFlag::kSymLink: return MY_LIN_S_IFLNK; | 193 | case NFileHeader::NLinkFlag::kSymLink: return MY_LIN_S_IFLNK; |
86 | case NFileHeader::NLinkFlag::kBlock: return MY_LIN_S_IFBLK; | 194 | case NFileHeader::NLinkFlag::kBlock: return MY_LIN_S_IFBLK; |
87 | case NFileHeader::NLinkFlag::kCharacter: return MY_LIN_S_IFCHR; | 195 | case NFileHeader::NLinkFlag::kCharacter: return MY_LIN_S_IFCHR; |
88 | case NFileHeader::NLinkFlag::kFIFO: return MY_LIN_S_IFIFO; | 196 | case NFileHeader::NLinkFlag::kFIFO: return MY_LIN_S_IFIFO; |
89 | // case return MY_LIN_S_IFSOCK; | 197 | // case return MY_LIN_S_IFSOCK; |
90 | } | 198 | } |
91 | 199 | ||
@@ -104,20 +212,41 @@ struct CItem | |||
104 | case NFileHeader::NLinkFlag::kOldNormal: | 212 | case NFileHeader::NLinkFlag::kOldNormal: |
105 | case NFileHeader::NLinkFlag::kNormal: | 213 | case NFileHeader::NLinkFlag::kNormal: |
106 | case NFileHeader::NLinkFlag::kSymLink: | 214 | case NFileHeader::NLinkFlag::kSymLink: |
107 | return NItemName::HasTailSlash(Name, CP_OEMCP); | 215 | if (Name.IsEmpty()) |
216 | return false; | ||
217 | // GNU TAR uses last character as directory marker | ||
218 | // we also do it | ||
219 | return Name.Back() == '/'; | ||
220 | // return NItemName::HasTailSlash(Name, CP_OEMCP); | ||
108 | } | 221 | } |
109 | return false; | 222 | return false; |
110 | } | 223 | } |
111 | 224 | ||
112 | bool IsUstarMagic() const | 225 | bool IsMagic_ustar_5chars() const |
226 | { | ||
227 | for (unsigned i = 0; i < 5; i++) | ||
228 | if (Magic[i] != NFileHeader::NMagic::k_GNU_ustar__[i]) | ||
229 | return false; | ||
230 | return true; | ||
231 | } | ||
232 | |||
233 | bool IsMagic_Posix_ustar_00() const | ||
234 | { | ||
235 | for (unsigned i = 0; i < 8; i++) | ||
236 | if (Magic[i] != NFileHeader::NMagic::k_Posix_ustar_00[i]) | ||
237 | return false; | ||
238 | return true; | ||
239 | } | ||
240 | |||
241 | bool IsMagic_GNU() const | ||
113 | { | 242 | { |
114 | for (int i = 0; i < 5; i++) | 243 | for (unsigned i = 0; i < 8; i++) |
115 | if (Magic[i] != NFileHeader::NMagic::kUsTar_GNU[i]) | 244 | if (Magic[i] != NFileHeader::NMagic::k_GNU_ustar__[i]) |
116 | return false; | 245 | return false; |
117 | return true; | 246 | return true; |
118 | } | 247 | } |
119 | 248 | ||
120 | UInt64 GetPackSizeAligned() const { return (PackSize + 0x1FF) & (~((UInt64)0x1FF)); } | 249 | UInt64 Get_PackSize_Aligned() const { return (PackSize + 0x1FF) & (~((UInt64)0x1FF)); } |
121 | 250 | ||
122 | bool IsThereWarning() const | 251 | bool IsThereWarning() const |
123 | { | 252 | { |
@@ -163,18 +292,67 @@ struct CEncodingCharacts | |||
163 | }; | 292 | }; |
164 | 293 | ||
165 | 294 | ||
295 | struct CPaxExtra | ||
296 | { | ||
297 | AString RecordPath; | ||
298 | AString RawLines; | ||
299 | |||
300 | void Clear() | ||
301 | { | ||
302 | RecordPath.Empty(); | ||
303 | RawLines.Empty(); | ||
304 | } | ||
305 | |||
306 | void Print_To_String(AString &s) const | ||
307 | { | ||
308 | if (!RecordPath.IsEmpty()) | ||
309 | { | ||
310 | s += RecordPath; | ||
311 | s.Add_LF(); | ||
312 | } | ||
313 | if (!RawLines.IsEmpty()) | ||
314 | s += RawLines; | ||
315 | } | ||
316 | }; | ||
317 | |||
166 | 318 | ||
167 | struct CItemEx: public CItem | 319 | struct CItemEx: public CItem |
168 | { | 320 | { |
321 | bool HeaderError; | ||
322 | |||
323 | bool IsSignedChecksum; | ||
324 | bool Prefix_WasUsed; | ||
325 | |||
326 | bool Pax_Error; | ||
327 | bool Pax_Overflow; | ||
328 | bool pax_path_WasUsed; | ||
329 | bool pax_link_WasUsed; | ||
330 | bool pax_size_WasUsed; | ||
331 | |||
332 | bool MTime_IsBin; | ||
333 | bool PackSize_IsBin; | ||
334 | bool Size_IsBin; | ||
335 | |||
336 | bool LongName_WasUsed; | ||
337 | bool LongName_WasUsed_2; | ||
338 | |||
339 | bool LongLink_WasUsed; | ||
340 | bool LongLink_WasUsed_2; | ||
341 | |||
342 | // bool Name_CouldBeReduced; | ||
343 | // bool LinkName_CouldBeReduced; | ||
344 | |||
169 | UInt64 HeaderPos; | 345 | UInt64 HeaderPos; |
170 | unsigned HeaderSize; | 346 | UInt64 HeaderSize; |
171 | bool NameCouldBeReduced; | 347 | |
172 | bool LinkNameCouldBeReduced; | 348 | UInt64 Num_Pax_Records; |
349 | CPaxExtra PaxExtra; | ||
173 | 350 | ||
174 | CEncodingCharacts EncodingCharacts; | 351 | CEncodingCharacts EncodingCharacts; |
175 | 352 | ||
176 | UInt64 GetDataPosition() const { return HeaderPos + HeaderSize; } | 353 | UInt64 Get_DataPos() const { return HeaderPos + HeaderSize; } |
177 | UInt64 GetFullSize() const { return HeaderSize + PackSize; } | 354 | // UInt64 GetFullSize() const { return HeaderSize + PackSize; } |
355 | UInt64 Get_FullSize_Aligned() const { return HeaderSize + Get_PackSize_Aligned(); } | ||
178 | }; | 356 | }; |
179 | 357 | ||
180 | }} | 358 | }} |
diff --git a/CPP/7zip/Archive/Tar/TarOut.cpp b/CPP/7zip/Archive/Tar/TarOut.cpp index 271b854..f73c625 100644 --- a/CPP/7zip/Archive/Tar/TarOut.cpp +++ b/CPP/7zip/Archive/Tar/TarOut.cpp | |||
@@ -2,6 +2,10 @@ | |||
2 | 2 | ||
3 | #include "StdAfx.h" | 3 | #include "StdAfx.h" |
4 | 4 | ||
5 | #include "../../../../C/7zCrc.h" | ||
6 | |||
7 | #include "../../../Common/IntToString.h" | ||
8 | |||
5 | #include "../../Common/StreamUtils.h" | 9 | #include "../../Common/StreamUtils.h" |
6 | 10 | ||
7 | #include "TarOut.h" | 11 | #include "TarOut.h" |
@@ -9,23 +13,27 @@ | |||
9 | namespace NArchive { | 13 | namespace NArchive { |
10 | namespace NTar { | 14 | namespace NTar { |
11 | 15 | ||
12 | HRESULT COutArchive::WriteBytes(const void *data, unsigned size) | 16 | using namespace NFileHeader; |
13 | { | 17 | |
14 | Pos += size; | 18 | // it's path prefix assigned by 7-Zip to show that file path was cut |
15 | return WriteStream(m_Stream, data, size); | 19 | #define K_PREFIX_PATH_CUT "@PathCut" |
16 | } | 20 | |
21 | static const UInt32 k_7_oct_digits_Val_Max = ((UInt32)1 << (7 * 3)) - 1; | ||
17 | 22 | ||
18 | static bool WriteOctal_8(char *s, UInt32 val) | 23 | static void WriteOctal_8(char *s, UInt32 val) |
19 | { | 24 | { |
20 | const unsigned kNumDigits = 8 - 1; | 25 | const unsigned kNumDigits = 8 - 1; |
21 | if (val >= ((UInt32)1 << (kNumDigits * 3))) | 26 | if (val >= ((UInt32)1 << (kNumDigits * 3))) |
22 | return false; | 27 | { |
28 | val = 0; | ||
29 | // return false; | ||
30 | } | ||
23 | for (unsigned i = 0; i < kNumDigits; i++) | 31 | for (unsigned i = 0; i < kNumDigits; i++) |
24 | { | 32 | { |
25 | s[kNumDigits - 1 - i] = (char)('0' + (val & 7)); | 33 | s[kNumDigits - 1 - i] = (char)('0' + (val & 7)); |
26 | val >>= 3; | 34 | val >>= 3; |
27 | } | 35 | } |
28 | return true; | 36 | // return true; |
29 | } | 37 | } |
30 | 38 | ||
31 | static void WriteBin_64bit(char *s, UInt64 val) | 39 | static void WriteBin_64bit(char *s, UInt64 val) |
@@ -68,61 +76,93 @@ static void CopyString(char *dest, const AString &src, unsigned maxSize) | |||
68 | unsigned len = src.Len(); | 76 | unsigned len = src.Len(); |
69 | if (len == 0) | 77 | if (len == 0) |
70 | return; | 78 | return; |
71 | // 21.07: we don't require additional 0 character at the end | 79 | // 21.07: new gnu : we don't require additional 0 character at the end |
80 | // if (len >= maxSize) | ||
72 | if (len > maxSize) | 81 | if (len > maxSize) |
73 | { | 82 | { |
74 | len = maxSize; | 83 | len = maxSize; |
75 | // return false; | 84 | /* |
85 | // oldgnu needs 0 character at the end | ||
86 | len = maxSize - 1; | ||
87 | dest[len] = 0; | ||
88 | */ | ||
76 | } | 89 | } |
77 | memcpy(dest, src.Ptr(), len); | 90 | memcpy(dest, src.Ptr(), len); |
78 | // return true; | ||
79 | } | 91 | } |
80 | 92 | ||
81 | #define RETURN_IF_NOT_TRUE(x) { if (!(x)) return E_FAIL; } | 93 | // #define RETURN_IF_NOT_TRUE(x) { if (!(x)) return E_INVALIDARG; } |
94 | #define RETURN_IF_NOT_TRUE(x) { x; } | ||
82 | 95 | ||
83 | #define COPY_STRING_CHECK(dest, src, size) \ | 96 | #define COPY_STRING_CHECK(dest, src, size) \ |
84 | CopyString(dest, src, size); dest += (size); | 97 | CopyString(dest, src, size); dest += (size); |
85 | 98 | ||
86 | #define WRITE_OCTAL_8_CHECK(dest, src) \ | 99 | #define WRITE_OCTAL_8_CHECK(dest, src) \ |
87 | RETURN_IF_NOT_TRUE(WriteOctal_8(dest, src)); | 100 | RETURN_IF_NOT_TRUE(WriteOctal_8(dest, src)) |
88 | 101 | ||
89 | 102 | ||
90 | HRESULT COutArchive::WriteHeaderReal(const CItem &item) | 103 | HRESULT COutArchive::WriteHeaderReal(const CItem &item, bool isPax |
104 | // , bool zero_PackSize | ||
105 | // , bool zero_MTime | ||
106 | ) | ||
91 | { | 107 | { |
92 | char record[NFileHeader::kRecordSize]; | 108 | /* |
93 | memset(record, 0, NFileHeader::kRecordSize); | 109 | if (isPax) { we don't use Glob_Name and Prefix } |
110 | if (!isPax) | ||
111 | { | ||
112 | we use Glob_Name if it's not empty | ||
113 | we use Prefix if it's not empty | ||
114 | } | ||
115 | */ | ||
116 | char record[kRecordSize]; | ||
117 | memset(record, 0, kRecordSize); | ||
94 | char *cur = record; | 118 | char *cur = record; |
95 | 119 | ||
96 | COPY_STRING_CHECK (cur, item.Name, NFileHeader::kNameSize); | 120 | COPY_STRING_CHECK (cur, |
121 | (!isPax && !Glob_Name.IsEmpty()) ? Glob_Name : item.Name, | ||
122 | kNameSize); | ||
97 | 123 | ||
98 | WRITE_OCTAL_8_CHECK (cur, item.Mode); cur += 8; | 124 | WRITE_OCTAL_8_CHECK (cur, item.Mode); cur += 8; // & k_7_oct_digits_Val_Max |
99 | WRITE_OCTAL_8_CHECK (cur, item.UID); cur += 8; | 125 | WRITE_OCTAL_8_CHECK (cur, item.UID); cur += 8; |
100 | WRITE_OCTAL_8_CHECK (cur, item.GID); cur += 8; | 126 | WRITE_OCTAL_8_CHECK (cur, item.GID); cur += 8; |
101 | 127 | ||
102 | WriteOctal_12(cur, item.PackSize); cur += 12; | 128 | WriteOctal_12 (cur, /* zero_PackSize ? 0 : */ item.PackSize); cur += 12; |
103 | WriteOctal_12_Signed(cur, item.MTime); cur += 12; | 129 | WriteOctal_12_Signed (cur, /* zero_MTime ? 0 : */ item.MTime); cur += 12; |
104 | 130 | ||
105 | memset(cur, ' ', 8); // checksum field | 131 | // we will use binary init for checksum instead of memset |
132 | // checksum field: | ||
133 | // memset(cur, ' ', 8); | ||
106 | cur += 8; | 134 | cur += 8; |
107 | 135 | ||
108 | *cur++ = item.LinkFlag; | 136 | *cur++ = item.LinkFlag; |
109 | 137 | ||
110 | COPY_STRING_CHECK (cur, item.LinkName, NFileHeader::kNameSize); | 138 | COPY_STRING_CHECK (cur, item.LinkName, kNameSize); |
111 | 139 | ||
112 | memcpy(cur, item.Magic, 8); | 140 | memcpy(cur, item.Magic, 8); |
113 | cur += 8; | 141 | cur += 8; |
114 | 142 | ||
115 | COPY_STRING_CHECK (cur, item.User, NFileHeader::kUserNameSize); | 143 | COPY_STRING_CHECK (cur, item.User, kUserNameSize); |
116 | COPY_STRING_CHECK (cur, item.Group, NFileHeader::kGroupNameSize); | 144 | COPY_STRING_CHECK (cur, item.Group, kGroupNameSize); |
117 | 145 | ||
118 | if (item.DeviceMajorDefined) | 146 | const bool needDevice = (IsPosixMode && !isPax); |
119 | WRITE_OCTAL_8_CHECK (cur, item.DeviceMajor); | 147 | |
148 | if (item.DeviceMajor_Defined) | ||
149 | WRITE_OCTAL_8_CHECK (cur, item.DeviceMajor) | ||
150 | else if (needDevice) | ||
151 | WRITE_OCTAL_8_CHECK (cur, 0) | ||
120 | cur += 8; | 152 | cur += 8; |
121 | if (item.DeviceMinorDefined) | 153 | |
122 | WRITE_OCTAL_8_CHECK (cur, item.DeviceMinor); | 154 | if (item.DeviceMinor_Defined) |
155 | WRITE_OCTAL_8_CHECK (cur, item.DeviceMinor) | ||
156 | else if (needDevice) | ||
157 | WRITE_OCTAL_8_CHECK (cur, 0) | ||
123 | cur += 8; | 158 | cur += 8; |
124 | 159 | ||
125 | if (item.IsSparse()) | 160 | if (!isPax && !Prefix.IsEmpty()) |
161 | { | ||
162 | COPY_STRING_CHECK (cur, Prefix, kPrefixSize); | ||
163 | } | ||
164 | |||
165 | if (item.Is_Sparse()) | ||
126 | { | 166 | { |
127 | record[482] = (char)(item.SparseBlocks.Size() > 4 ? 1 : 0); | 167 | record[482] = (char)(item.SparseBlocks.Size() > 4 ? 1 : 0); |
128 | WriteOctal_12(record + 483, item.Size); | 168 | WriteOctal_12(record + 483, item.Size); |
@@ -136,31 +176,31 @@ HRESULT COutArchive::WriteHeaderReal(const CItem &item) | |||
136 | } | 176 | } |
137 | 177 | ||
138 | { | 178 | { |
139 | UInt32 checkSum = 0; | 179 | UInt32 sum = (unsigned)(' ') * 8; // we use binary init |
140 | { | 180 | { |
141 | for (unsigned i = 0; i < NFileHeader::kRecordSize; i++) | 181 | for (unsigned i = 0; i < kRecordSize; i++) |
142 | checkSum += (Byte)record[i]; | 182 | sum += (Byte)record[i]; |
143 | } | 183 | } |
144 | /* we use GNU TAR scheme: | 184 | /* checksum field is formatted differently from the |
145 | checksum field is formatted differently from the | ||
146 | other fields: it has [6] digits, a null, then a space. */ | 185 | other fields: it has [6] digits, a null, then a space. */ |
147 | // WRITE_OCTAL_8_CHECK(record + 148, checkSum); | 186 | // WRITE_OCTAL_8_CHECK(record + 148, sum); |
148 | const unsigned kNumDigits = 6; | 187 | const unsigned kNumDigits = 6; |
149 | for (unsigned i = 0; i < kNumDigits; i++) | 188 | for (unsigned i = 0; i < kNumDigits; i++) |
150 | { | 189 | { |
151 | record[148 + kNumDigits - 1 - i] = (char)('0' + (checkSum & 7)); | 190 | record[148 + kNumDigits - 1 - i] = (char)('0' + (sum & 7)); |
152 | checkSum >>= 3; | 191 | sum >>= 3; |
153 | } | 192 | } |
154 | record[148 + 6] = 0; | 193 | // record[148 + 6] = 0; // we need it, if we use memset(' ') init |
194 | record[148 + 7] = ' '; // we need it, if we use binary init | ||
155 | } | 195 | } |
156 | 196 | ||
157 | RINOK(WriteBytes(record, NFileHeader::kRecordSize)); | 197 | RINOK(Write_Data(record, kRecordSize)); |
158 | 198 | ||
159 | if (item.IsSparse()) | 199 | if (item.Is_Sparse()) |
160 | { | 200 | { |
161 | for (unsigned i = 4; i < item.SparseBlocks.Size();) | 201 | for (unsigned i = 4; i < item.SparseBlocks.Size();) |
162 | { | 202 | { |
163 | memset(record, 0, NFileHeader::kRecordSize); | 203 | memset(record, 0, kRecordSize); |
164 | for (unsigned t = 0; t < 21 && i < item.SparseBlocks.Size(); t++, i++) | 204 | for (unsigned t = 0; t < 21 && i < item.SparseBlocks.Size(); t++, i++) |
165 | { | 205 | { |
166 | const CSparseBlock &sb = item.SparseBlocks[i]; | 206 | const CSparseBlock &sb = item.SparseBlocks[i]; |
@@ -169,7 +209,7 @@ HRESULT COutArchive::WriteHeaderReal(const CItem &item) | |||
169 | WriteOctal_12(p + 12, sb.Size); | 209 | WriteOctal_12(p + 12, sb.Size); |
170 | } | 210 | } |
171 | record[21 * 24] = (char)(i < item.SparseBlocks.Size() ? 1 : 0); | 211 | record[21 * 24] = (char)(i < item.SparseBlocks.Size() ? 1 : 0); |
172 | RINOK(WriteBytes(record, NFileHeader::kRecordSize)); | 212 | RINOK(Write_Data(record, kRecordSize)); |
173 | } | 213 | } |
174 | } | 214 | } |
175 | 215 | ||
@@ -177,101 +217,426 @@ HRESULT COutArchive::WriteHeaderReal(const CItem &item) | |||
177 | } | 217 | } |
178 | 218 | ||
179 | 219 | ||
180 | /* OLD_GNU_TAR: writes short name with zero at the end | 220 | static void AddPaxLine(AString &s, const char *name, const AString &val) |
181 | NEW_GNU_TAR: writes short name without zero at the end */ | 221 | { |
222 | // s.Add_LF(); // for debug | ||
223 | const unsigned len = 3 + (unsigned)strlen(name) + val.Len(); | ||
224 | AString n; | ||
225 | for (unsigned numDigits = 1;; numDigits++) | ||
226 | { | ||
227 | n.Empty(); | ||
228 | n.Add_UInt32(numDigits + len); | ||
229 | if (numDigits == n.Len()) | ||
230 | break; | ||
231 | } | ||
232 | s += n; | ||
233 | s.Add_Space(); | ||
234 | s += name; | ||
235 | s += '='; | ||
236 | s += val; | ||
237 | s.Add_LF(); | ||
238 | } | ||
239 | |||
240 | |||
241 | static void AddPaxTime(AString &s, const char *name, const CPaxTime &pt, | ||
242 | const CTimeOptions &options) | ||
243 | { | ||
244 | unsigned numDigits = pt.NumDigits; | ||
245 | if (numDigits > options.NumDigitsMax) | ||
246 | numDigits = options.NumDigitsMax; | ||
247 | |||
248 | bool needNs = false; | ||
249 | UInt32 ns = 0; | ||
250 | if (numDigits != 0) | ||
251 | { | ||
252 | ns = pt.Ns; | ||
253 | // if (ns != 0) before reduction, we show all digits after digits reduction | ||
254 | needNs = (ns != 0 || options.RemoveZeroMode == k_PaxTimeMode_DontRemoveZero); | ||
255 | UInt32 d = 1; | ||
256 | for (unsigned k = numDigits; k < 9; k++) | ||
257 | d *= 10; | ||
258 | ns /= d; | ||
259 | ns *= d; | ||
260 | } | ||
261 | |||
262 | AString v; | ||
263 | { | ||
264 | Int64 sec = pt.Sec; | ||
265 | if (pt.Sec < 0) | ||
266 | { | ||
267 | sec = -sec; | ||
268 | v += '-'; | ||
269 | if (ns != 0) | ||
270 | { | ||
271 | ns = 1000*1000*1000 - ns; | ||
272 | sec--; | ||
273 | } | ||
274 | } | ||
275 | v.Add_UInt64(sec); | ||
276 | } | ||
277 | |||
278 | if (needNs) | ||
279 | { | ||
280 | AString d; | ||
281 | d.Add_UInt32(ns); | ||
282 | while (d.Len() < 9) | ||
283 | d.InsertAtFront('0'); | ||
284 | // here we have precision | ||
285 | while (d.Len() > (unsigned)numDigits) | ||
286 | d.DeleteBack(); | ||
287 | // GNU TAR reduces '0' digits. | ||
288 | if (options.RemoveZeroMode == k_PaxTimeMode_RemoveZero_Always) | ||
289 | while (!d.IsEmpty() && d.Back() == '0') | ||
290 | d.DeleteBack(); | ||
291 | |||
292 | if (!d.IsEmpty()) | ||
293 | { | ||
294 | v += '.'; | ||
295 | v += d; | ||
296 | // v += "1234567009999"; // for debug | ||
297 | // for (int y = 0; y < 1000; y++) v += '8'; // for debug | ||
298 | } | ||
299 | } | ||
300 | |||
301 | AddPaxLine(s, name, v); | ||
302 | } | ||
303 | |||
304 | |||
305 | static void AddPax_UInt32_ifBig(AString &s, const char *name, const UInt32 &v) | ||
306 | { | ||
307 | if (v > k_7_oct_digits_Val_Max) | ||
308 | { | ||
309 | AString s2; | ||
310 | s2.Add_UInt32(v); | ||
311 | AddPaxLine(s, name, s2); | ||
312 | } | ||
313 | } | ||
314 | |||
315 | |||
316 | /* OLD_GNU_TAR: writes name with zero at the end | ||
317 | NEW_GNU_TAR: can write name filled with all kNameSize characters */ | ||
182 | 318 | ||
183 | static const unsigned kNameSize_Max = | 319 | static const unsigned kNameSize_Max = |
184 | NFileHeader::kNameSize; // NEW_GNU_TAR / 7-Zip 21.07 | 320 | kNameSize; // NEW_GNU_TAR / 7-Zip 21.07 |
185 | // NFileHeader::kNameSize - 1; // OLD_GNU_TAR / old 7-Zip | 321 | // kNameSize - 1; // OLD_GNU_TAR / old 7-Zip |
186 | 322 | ||
187 | #define DOES_NAME_FIT_IN_FIELD(name) ((name).Len() <= kNameSize_Max) | 323 | #define DOES_NAME_FIT_IN_FIELD(name) ((name).Len() <= kNameSize_Max) |
188 | 324 | ||
325 | |||
189 | HRESULT COutArchive::WriteHeader(const CItem &item) | 326 | HRESULT COutArchive::WriteHeader(const CItem &item) |
190 | { | 327 | { |
191 | if (DOES_NAME_FIT_IN_FIELD(item.Name) && | 328 | Glob_Name.Empty(); |
192 | DOES_NAME_FIT_IN_FIELD(item.LinkName)) | 329 | Prefix.Empty(); |
193 | return WriteHeaderReal(item); | ||
194 | 330 | ||
195 | // here we can get all fields from main (item) or create new empty item | 331 | unsigned namePos = 0; |
196 | /* | 332 | bool needPathCut = false; |
197 | CItem mi; | 333 | bool allowPrefix = false; |
198 | mi.SetDefaultWriteFields(); | 334 | |
199 | */ | 335 | if (!DOES_NAME_FIT_IN_FIELD(item.Name)) |
200 | 336 | { | |
201 | CItem mi = item; | 337 | const char *s = item.Name; |
202 | mi.LinkName.Empty(); | 338 | const char *p = s + item.Name.Len() - 1; |
203 | // SparseBlocks will be ignored by IsSparse() | 339 | for (; *p == '/' && p != s; p--) |
204 | // mi.SparseBlocks.Clear(); | 340 | {} |
341 | for (; p != s && p[-1] != '/'; p--) | ||
342 | {} | ||
343 | namePos = (unsigned)(p - s); | ||
344 | needPathCut = true; | ||
345 | } | ||
205 | 346 | ||
206 | mi.Name = NFileHeader::kLongLink; | 347 | if (IsPosixMode) |
207 | // 21.07 : we set Mode and MTime props as in GNU TAR: | 348 | { |
208 | mi.Mode = 0644; // octal | 349 | AString s; |
209 | mi.MTime = 0; | 350 | |
351 | if (needPathCut) | ||
352 | { | ||
353 | const unsigned nameLen = item.Name.Len() - namePos; | ||
354 | if ( item.LinkFlag >= NLinkFlag::kNormal | ||
355 | && item.LinkFlag <= NLinkFlag::kDirectory | ||
356 | && namePos > 1 | ||
357 | && nameLen != 0 | ||
358 | // && IsPrefixAllowed | ||
359 | && item.IsMagic_Posix_ustar_00()) | ||
360 | { | ||
361 | /* GNU TAR decoder supports prefix field, only if (magic) | ||
362 | signature matches 6-bytes "ustar\0". | ||
363 | so here we use prefix field only in posix mode with posix signature */ | ||
364 | |||
365 | allowPrefix = true; | ||
366 | // allowPrefix = false; // for debug | ||
367 | if (namePos <= kPrefixSize + 1 && nameLen <= kNameSize_Max) | ||
368 | { | ||
369 | needPathCut = false; | ||
370 | /* we will set Prefix and Glob_Name later, for such conditions: | ||
371 | if (!DOES_NAME_FIT_IN_FIELD(item.Name) && !needPathCut) */ | ||
372 | } | ||
373 | } | ||
210 | 374 | ||
211 | for (int i = 0; i < 2; i++) | 375 | if (needPathCut) |
376 | AddPaxLine(s, "path", item.Name); | ||
377 | } | ||
378 | |||
379 | // AddPaxLine(s, "testname", AString("testval")); // for debug | ||
380 | |||
381 | if (item.LinkName.Len() > kNameSize_Max) | ||
382 | AddPaxLine(s, "linkpath", item.LinkName); | ||
383 | |||
384 | const UInt64 kPaxSize_Limit = ((UInt64)1 << 33); | ||
385 | // const UInt64 kPaxSize_Limit = ((UInt64)1 << 1); // for debug | ||
386 | // bool zero_PackSize = false; | ||
387 | if (item.PackSize >= kPaxSize_Limit) | ||
388 | { | ||
389 | /* GNU TAR in pax mode sets PackSize = 0 in main record, if pack_size >= 8 GiB | ||
390 | But old 7-Zip doesn't detect "size" property from pax header. | ||
391 | So we write real size (>= 8 GiB) to main record in binary format, | ||
392 | and old 7-Zip can decode size correctly */ | ||
393 | // zero_PackSize = true; | ||
394 | AString v; | ||
395 | v.Add_UInt64(item.PackSize); | ||
396 | AddPaxLine(s, "size", v); | ||
397 | } | ||
398 | |||
399 | /* GNU TAR encoder can set "devmajor" / "devminor" attributes, | ||
400 | but GNU TAR decoder doesn't parse "devmajor" / "devminor" */ | ||
401 | if (item.DeviceMajor_Defined) | ||
402 | AddPax_UInt32_ifBig(s, "devmajor", item.DeviceMajor); | ||
403 | if (item.DeviceMinor_Defined) | ||
404 | AddPax_UInt32_ifBig(s, "devminor", item.DeviceMinor); | ||
405 | |||
406 | AddPax_UInt32_ifBig(s, "uid", item.UID); | ||
407 | AddPax_UInt32_ifBig(s, "gid", item.GID); | ||
408 | |||
409 | const UInt64 kPax_MTime_Limit = ((UInt64)1 << 33); | ||
410 | const bool zero_MTime = ( | ||
411 | item.MTime < 0 || | ||
412 | item.MTime >= (Int64)kPax_MTime_Limit); | ||
413 | |||
414 | const CPaxTime &mtime = item.PaxTimes.MTime; | ||
415 | if (mtime.IsDefined()) | ||
416 | { | ||
417 | bool needPax = false; | ||
418 | if (zero_MTime) | ||
419 | needPax = true; | ||
420 | else if (TimeOptions.NumDigitsMax > 0) | ||
421 | if (mtime.Ns != 0 || | ||
422 | (mtime.NumDigits != 0 && | ||
423 | TimeOptions.RemoveZeroMode == k_PaxTimeMode_DontRemoveZero)) | ||
424 | needPax = true; | ||
425 | if (needPax) | ||
426 | AddPaxTime(s, "mtime", mtime, TimeOptions); | ||
427 | } | ||
428 | |||
429 | if (item.PaxTimes.ATime.IsDefined()) | ||
430 | AddPaxTime(s, "atime", item.PaxTimes.ATime, TimeOptions); | ||
431 | if (item.PaxTimes.CTime.IsDefined()) | ||
432 | AddPaxTime(s, "ctime", item.PaxTimes.CTime, TimeOptions); | ||
433 | |||
434 | if (item.User.Len() > kUserNameSize) | ||
435 | AddPaxLine(s, "uname", item.User); | ||
436 | if (item.Group.Len() > kGroupNameSize) | ||
437 | AddPaxLine(s, "gname", item.Group); | ||
438 | |||
439 | /* | ||
440 | // for debug | ||
441 | AString a ("11"); for (int y = 0; y < (1 << 24); y++) AddPaxLine(s, "temp", a); | ||
442 | */ | ||
443 | |||
444 | const unsigned paxSize = s.Len(); | ||
445 | if (paxSize != 0) | ||
446 | { | ||
447 | CItem mi = item; | ||
448 | mi.LinkName.Empty(); | ||
449 | // SparseBlocks will be ignored by Is_Sparse() | ||
450 | // mi.SparseBlocks.Clear(); | ||
451 | // we use "PaxHeader/*" for compatibility with previous 7-Zip decoder | ||
452 | |||
453 | // GNU TAR writes empty for these fields; | ||
454 | mi.User.Empty(); | ||
455 | mi.Group.Empty(); | ||
456 | mi.UID = 0; | ||
457 | mi.GID = 0; | ||
458 | |||
459 | mi.DeviceMajor_Defined = false; | ||
460 | mi.DeviceMinor_Defined = false; | ||
461 | |||
462 | mi.Name = "PaxHeader/@PaxHeader"; | ||
463 | mi.Mode = 0644; // octal | ||
464 | if (zero_MTime) | ||
465 | mi.MTime = 0; | ||
466 | mi.LinkFlag = NLinkFlag::kPax; | ||
467 | // mi.LinkFlag = 'Z'; // for debug | ||
468 | mi.PackSize = paxSize; | ||
469 | // for (unsigned y = 0; y < 1; y++) { // for debug | ||
470 | RINOK(WriteHeaderReal(mi, true)); // isPax | ||
471 | RINOK(Write_Data_And_Residual(s, paxSize)); | ||
472 | // } // for debug | ||
473 | /* | ||
474 | we can send (zero_MTime) for compatibility with gnu tar output. | ||
475 | we can send (zero_MTime = false) for better compatibility with old 7-Zip | ||
476 | */ | ||
477 | // return WriteHeaderReal(item); | ||
478 | /* | ||
479 | false, // isPax | ||
480 | false, // zero_PackSize | ||
481 | false); // zero_MTime | ||
482 | */ | ||
483 | } | ||
484 | } | ||
485 | else // !PosixMode | ||
486 | if (!DOES_NAME_FIT_IN_FIELD(item.Name) || | ||
487 | !DOES_NAME_FIT_IN_FIELD(item.LinkName)) | ||
212 | { | 488 | { |
213 | const AString *name; | 489 | // here we can get all fields from main (item) or create new empty item |
214 | // We suppose that GNU TAR also writes item for long link before item for LongName? | 490 | /* |
215 | if (i == 0) | 491 | CItem mi; |
492 | mi.SetDefaultWriteFields(); | ||
493 | */ | ||
494 | CItem mi = item; | ||
495 | mi.LinkName.Empty(); | ||
496 | // SparseBlocks will be ignored by Is_Sparse() | ||
497 | // mi.SparseBlocks.Clear(); | ||
498 | mi.Name = kLongLink; | ||
499 | // mi.Name = "././@BAD_LONG_LINK_TEST"; // for debug | ||
500 | // 21.07 : we set Mode and MTime props as in GNU TAR: | ||
501 | mi.Mode = 0644; // octal | ||
502 | mi.MTime = 0; | ||
503 | |||
504 | mi.User.Empty(); | ||
505 | mi.Group.Empty(); | ||
506 | /* | ||
507 | gnu tar sets "root" for such items: | ||
508 | uid_to_uname (0, &uname); | ||
509 | gid_to_gname (0, &gname); | ||
510 | */ | ||
511 | /* | ||
512 | mi.User = "root"; | ||
513 | mi.Group = "root"; | ||
514 | */ | ||
515 | mi.UID = 0; | ||
516 | mi.GID = 0; | ||
517 | mi.DeviceMajor_Defined = false; | ||
518 | mi.DeviceMinor_Defined = false; | ||
519 | |||
520 | |||
521 | for (unsigned i = 0; i < 2; i++) | ||
216 | { | 522 | { |
217 | mi.LinkFlag = NFileHeader::NLinkFlag::kGnu_LongLink; | 523 | const AString *name; |
218 | name = &item.LinkName; | 524 | // We suppose that GNU TAR also writes item for long link before item for LongName? |
525 | if (i == 0) | ||
526 | { | ||
527 | mi.LinkFlag = NLinkFlag::kGnu_LongLink; | ||
528 | name = &item.LinkName; | ||
529 | } | ||
530 | else | ||
531 | { | ||
532 | mi.LinkFlag = NLinkFlag::kGnu_LongName; | ||
533 | name = &item.Name; | ||
534 | } | ||
535 | if (DOES_NAME_FIT_IN_FIELD(*name)) | ||
536 | continue; | ||
537 | // GNU TAR writes null character after NAME to file. We do same here: | ||
538 | const unsigned nameStreamSize = name->Len() + 1; | ||
539 | mi.PackSize = nameStreamSize; | ||
540 | // for (unsigned y = 0; y < 3; y++) { // for debug | ||
541 | RINOK(WriteHeaderReal(mi)); | ||
542 | RINOK(Write_Data_And_Residual(name->Ptr(), nameStreamSize)); | ||
543 | // } | ||
544 | |||
545 | // for debug | ||
546 | /* | ||
547 | const unsigned kSize = (1 << 29) + 16; | ||
548 | CByteBuffer buf; | ||
549 | buf.Alloc(kSize); | ||
550 | memset(buf, 0, kSize); | ||
551 | memcpy(buf, name->Ptr(), name->Len()); | ||
552 | const unsigned nameStreamSize = kSize; | ||
553 | mi.PackSize = nameStreamSize; | ||
554 | // for (unsigned y = 0; y < 3; y++) { // for debug | ||
555 | RINOK(WriteHeaderReal(mi)); | ||
556 | RINOK(WriteBytes(buf, nameStreamSize)); | ||
557 | RINOK(FillDataResidual(nameStreamSize)); | ||
558 | */ | ||
219 | } | 559 | } |
560 | } | ||
561 | |||
562 | // bool fals = false; if (fals) // for debug: for bit-to-bit output compatibility with GNU TAR | ||
563 | |||
564 | if (!DOES_NAME_FIT_IN_FIELD(item.Name)) | ||
565 | { | ||
566 | const unsigned nameLen = item.Name.Len() - namePos; | ||
567 | if (!needPathCut) | ||
568 | Prefix.SetFrom(item.Name, namePos - 1); | ||
220 | else | 569 | else |
221 | { | 570 | { |
222 | mi.LinkFlag = NFileHeader::NLinkFlag::kGnu_LongName; | 571 | Glob_Name = K_PREFIX_PATH_CUT "/_pc_"; |
223 | name = &item.Name; | 572 | |
573 | if (namePos == 0) | ||
574 | Glob_Name += "root"; | ||
575 | else | ||
576 | { | ||
577 | Glob_Name += "crc32/"; | ||
578 | char temp[12]; | ||
579 | ConvertUInt32ToHex8Digits(CrcCalc(item.Name, namePos - 1), temp); | ||
580 | Glob_Name += temp; | ||
581 | } | ||
582 | |||
583 | if (!allowPrefix || Glob_Name.Len() + 1 + nameLen <= kNameSize_Max) | ||
584 | Glob_Name.Add_Slash(); | ||
585 | else | ||
586 | { | ||
587 | Prefix = Glob_Name; | ||
588 | Glob_Name.Empty(); | ||
589 | } | ||
224 | } | 590 | } |
225 | if (DOES_NAME_FIT_IN_FIELD(*name)) | 591 | Glob_Name.AddFrom(item.Name.Ptr(namePos), nameLen); |
226 | continue; | ||
227 | // GNU TAR writes null character after NAME to file. We do same here: | ||
228 | const unsigned nameStreamSize = name->Len() + 1; | ||
229 | mi.PackSize = nameStreamSize; | ||
230 | RINOK(WriteHeaderReal(mi)); | ||
231 | RINOK(WriteBytes(name->Ptr(), nameStreamSize)); | ||
232 | RINOK(FillDataResidual(nameStreamSize)); | ||
233 | } | 592 | } |
234 | 593 | ||
235 | // 21.07: WriteHeaderReal() writes short part of (Name) and (LinkName). | ||
236 | return WriteHeaderReal(item); | 594 | return WriteHeaderReal(item); |
237 | /* | ||
238 | mi = item; | ||
239 | if (!DOES_NAME_FIT_IN_FIELD(mi.Name)) | ||
240 | mi.Name.SetFrom(item.Name, kNameSize_Max); | ||
241 | if (!DOES_NAME_FIT_IN_FIELD(mi.LinkName)) | ||
242 | mi.LinkName.SetFrom(item.LinkName, kNameSize_Max); | ||
243 | return WriteHeaderReal(mi); | ||
244 | */ | ||
245 | } | 595 | } |
246 | 596 | ||
247 | HRESULT COutArchive::FillDataResidual(UInt64 dataSize) | 597 | |
598 | HRESULT COutArchive::Write_Data(const void *data, unsigned size) | ||
248 | { | 599 | { |
249 | unsigned lastRecordSize = ((unsigned)dataSize & (NFileHeader::kRecordSize - 1)); | 600 | Pos += size; |
250 | if (lastRecordSize == 0) | 601 | return WriteStream(Stream, data, size); |
602 | } | ||
603 | |||
604 | HRESULT COutArchive::Write_AfterDataResidual(UInt64 dataSize) | ||
605 | { | ||
606 | const unsigned v = ((unsigned)dataSize & (kRecordSize - 1)); | ||
607 | if (v == 0) | ||
251 | return S_OK; | 608 | return S_OK; |
252 | unsigned rem = NFileHeader::kRecordSize - lastRecordSize; | 609 | const unsigned rem = kRecordSize - v; |
253 | Byte buf[NFileHeader::kRecordSize]; | 610 | Byte buf[kRecordSize]; |
254 | memset(buf, 0, rem); | 611 | memset(buf, 0, rem); |
255 | return WriteBytes(buf, rem); | 612 | return Write_Data(buf, rem); |
613 | } | ||
614 | |||
615 | |||
616 | HRESULT COutArchive::Write_Data_And_Residual(const void *data, unsigned size) | ||
617 | { | ||
618 | RINOK(Write_Data(data, size)); | ||
619 | return Write_AfterDataResidual(size); | ||
256 | } | 620 | } |
257 | 621 | ||
622 | |||
258 | HRESULT COutArchive::WriteFinishHeader() | 623 | HRESULT COutArchive::WriteFinishHeader() |
259 | { | 624 | { |
260 | Byte record[NFileHeader::kRecordSize]; | 625 | Byte record[kRecordSize]; |
261 | memset(record, 0, NFileHeader::kRecordSize); | 626 | memset(record, 0, kRecordSize); |
262 | 627 | ||
263 | const unsigned kNumFinishRecords = 2; | 628 | const unsigned kNumFinishRecords = 2; |
264 | 629 | ||
265 | /* GNU TAR by default uses --blocking-factor=20 (512 * 20 = 10 KiB) | 630 | /* GNU TAR by default uses --blocking-factor=20 (512 * 20 = 10 KiB) |
266 | we also can use cluster alignment: | 631 | we also can use cluster alignment: |
267 | const unsigned numBlocks = (unsigned)(Pos / NFileHeader::kRecordSize) + kNumFinishRecords; | 632 | const unsigned numBlocks = (unsigned)(Pos / kRecordSize) + kNumFinishRecords; |
268 | const unsigned kNumClusterBlocks = (1 << 3); // 8 blocks = 4 KiB | 633 | const unsigned kNumClusterBlocks = (1 << 3); // 8 blocks = 4 KiB |
269 | const unsigned numFinishRecords = kNumFinishRecords + ((kNumClusterBlocks - numBlocks) & (kNumClusterBlocks - 1)); | 634 | const unsigned numFinishRecords = kNumFinishRecords + ((kNumClusterBlocks - numBlocks) & (kNumClusterBlocks - 1)); |
270 | */ | 635 | */ |
271 | 636 | ||
272 | for (unsigned i = 0; i < kNumFinishRecords; i++) | 637 | for (unsigned i = 0; i < kNumFinishRecords; i++) |
273 | { | 638 | { |
274 | RINOK(WriteBytes(record, NFileHeader::kRecordSize)); | 639 | RINOK(Write_Data(record, kRecordSize)); |
275 | } | 640 | } |
276 | return S_OK; | 641 | return S_OK; |
277 | } | 642 | } |
diff --git a/CPP/7zip/Archive/Tar/TarOut.h b/CPP/7zip/Archive/Tar/TarOut.h index ee9b965..34af20a 100644 --- a/CPP/7zip/Archive/Tar/TarOut.h +++ b/CPP/7zip/Archive/Tar/TarOut.h | |||
@@ -14,21 +14,38 @@ namespace NTar { | |||
14 | 14 | ||
15 | class COutArchive | 15 | class COutArchive |
16 | { | 16 | { |
17 | CMyComPtr<ISequentialOutStream> m_Stream; | 17 | CMyComPtr<ISequentialOutStream> Stream; |
18 | |||
19 | AString Glob_Name; | ||
20 | AString Prefix; | ||
21 | |||
22 | HRESULT WriteHeaderReal(const CItem &item, bool isPax = false | ||
23 | // , bool zero_PackSize = false | ||
24 | // , bool zero_MTime = false | ||
25 | ); | ||
26 | |||
27 | HRESULT Write_Data(const void *data, unsigned size); | ||
28 | HRESULT Write_Data_And_Residual(const void *data, unsigned size); | ||
18 | 29 | ||
19 | HRESULT WriteBytes(const void *data, unsigned size); | ||
20 | HRESULT WriteHeaderReal(const CItem &item); | ||
21 | public: | 30 | public: |
22 | UInt64 Pos; | 31 | UInt64 Pos; |
23 | 32 | bool IsPosixMode; | |
33 | // bool IsPrefixAllowed; // it's used only if (IsPosixMode == true) | ||
34 | CTimeOptions TimeOptions; | ||
35 | |||
24 | void Create(ISequentialOutStream *outStream) | 36 | void Create(ISequentialOutStream *outStream) |
25 | { | 37 | { |
26 | m_Stream = outStream; | 38 | Stream = outStream; |
27 | } | 39 | } |
28 | |||
29 | HRESULT WriteHeader(const CItem &item); | 40 | HRESULT WriteHeader(const CItem &item); |
30 | HRESULT FillDataResidual(UInt64 dataSize); | 41 | HRESULT Write_AfterDataResidual(UInt64 dataSize); |
31 | HRESULT WriteFinishHeader(); | 42 | HRESULT WriteFinishHeader(); |
43 | |||
44 | COutArchive(): | ||
45 | Pos(0), | ||
46 | IsPosixMode(false) | ||
47 | // , IsPrefixAllowed(true) | ||
48 | {} | ||
32 | }; | 49 | }; |
33 | 50 | ||
34 | }} | 51 | }} |
diff --git a/CPP/7zip/Archive/Tar/TarRegister.cpp b/CPP/7zip/Archive/Tar/TarRegister.cpp index 5014f04..a78c376 100644 --- a/CPP/7zip/Archive/Tar/TarRegister.cpp +++ b/CPP/7zip/Archive/Tar/TarRegister.cpp | |||
@@ -15,9 +15,17 @@ REGISTER_ARC_IO( | |||
15 | "tar", "tar ova", 0, 0xEE, | 15 | "tar", "tar ova", 0, 0xEE, |
16 | k_Signature, | 16 | k_Signature, |
17 | NFileHeader::kUstarMagic_Offset, | 17 | NFileHeader::kUstarMagic_Offset, |
18 | NArcInfoFlags::kStartOpen | | 18 | NArcInfoFlags::kStartOpen |
19 | NArcInfoFlags::kSymLinks | | 19 | | NArcInfoFlags::kSymLinks |
20 | NArcInfoFlags::kHardLinks, | 20 | | NArcInfoFlags::kHardLinks |
21 | IsArc_Tar) | 21 | | NArcInfoFlags::kMTime |
22 | | NArcInfoFlags::kMTime_Default | ||
23 | // | NArcInfoTimeFlags::kCTime | ||
24 | // | NArcInfoTimeFlags::kATime | ||
25 | , TIME_PREC_TO_ARC_FLAGS_MASK (NFileTimeType::kWindows) | ||
26 | | TIME_PREC_TO_ARC_FLAGS_MASK (NFileTimeType::kUnix) | ||
27 | | TIME_PREC_TO_ARC_FLAGS_MASK (NFileTimeType::k1ns) | ||
28 | | TIME_PREC_TO_ARC_FLAGS_TIME_DEFAULT (NFileTimeType::kUnix) | ||
29 | , IsArc_Tar) | ||
22 | 30 | ||
23 | }} | 31 | }} |
diff --git a/CPP/7zip/Archive/Tar/TarUpdate.cpp b/CPP/7zip/Archive/Tar/TarUpdate.cpp index 295e16b..caa0a82 100644 --- a/CPP/7zip/Archive/Tar/TarUpdate.cpp +++ b/CPP/7zip/Archive/Tar/TarUpdate.cpp | |||
@@ -2,6 +2,8 @@ | |||
2 | 2 | ||
3 | #include "StdAfx.h" | 3 | #include "StdAfx.h" |
4 | 4 | ||
5 | // #include <stdio.h> | ||
6 | |||
5 | #include "../../../Windows/TimeUtils.h" | 7 | #include "../../../Windows/TimeUtils.h" |
6 | 8 | ||
7 | #include "../../Common/LimitedStreams.h" | 9 | #include "../../Common/LimitedStreams.h" |
@@ -15,18 +17,161 @@ | |||
15 | namespace NArchive { | 17 | namespace NArchive { |
16 | namespace NTar { | 18 | namespace NTar { |
17 | 19 | ||
20 | static void FILETIME_To_PaxTime(const FILETIME &ft, CPaxTime &pt) | ||
21 | { | ||
22 | UInt32 ns; | ||
23 | pt.Sec = NWindows::NTime::FileTime_To_UnixTime64_and_Quantums(ft, ns); | ||
24 | pt.Ns = ns * 100; | ||
25 | pt.NumDigits = 7; | ||
26 | } | ||
27 | |||
28 | |||
29 | HRESULT Prop_To_PaxTime(const NWindows::NCOM::CPropVariant &prop, CPaxTime &pt) | ||
30 | { | ||
31 | pt.Clear(); | ||
32 | if (prop.vt == VT_EMPTY) | ||
33 | { | ||
34 | // pt.Sec = 0; | ||
35 | return S_OK; | ||
36 | } | ||
37 | if (prop.vt != VT_FILETIME) | ||
38 | return E_INVALIDARG; | ||
39 | { | ||
40 | UInt32 ns; | ||
41 | pt.Sec = NWindows::NTime::FileTime_To_UnixTime64_and_Quantums(prop.filetime, ns); | ||
42 | ns *= 100; | ||
43 | pt.NumDigits = 7; | ||
44 | const unsigned prec = prop.wReserved1; | ||
45 | if (prec >= k_PropVar_TimePrec_Base) | ||
46 | { | ||
47 | pt.NumDigits = prec - k_PropVar_TimePrec_Base; | ||
48 | if (prop.wReserved2 < 100) | ||
49 | ns += prop.wReserved2; | ||
50 | } | ||
51 | pt.Ns = ns; | ||
52 | return S_OK; | ||
53 | } | ||
54 | } | ||
55 | |||
56 | |||
57 | static HRESULT GetTime(IStreamGetProp *getProp, UInt32 pid, CPaxTime &pt) | ||
58 | { | ||
59 | pt.Clear(); | ||
60 | NWindows::NCOM::CPropVariant prop; | ||
61 | RINOK(getProp->GetProperty(pid, &prop)); | ||
62 | return Prop_To_PaxTime(prop, pt); | ||
63 | } | ||
64 | |||
65 | |||
66 | static HRESULT GetUser(IStreamGetProp *getProp, | ||
67 | UInt32 pidName, UInt32 pidId, AString &name, UInt32 &id, | ||
68 | UINT codePage, unsigned utfFlags) | ||
69 | { | ||
70 | // printf("\nGetUser\n"); | ||
71 | // we keep old values, if both GetProperty() return VT_EMPTY | ||
72 | // we clear old values, if any of GetProperty() returns non-VT_EMPTY; | ||
73 | bool isSet = false; | ||
74 | { | ||
75 | NWindows::NCOM::CPropVariant prop; | ||
76 | RINOK(getProp->GetProperty(pidId, &prop)); | ||
77 | if (prop.vt == VT_UI4) | ||
78 | { | ||
79 | isSet = true; | ||
80 | id = prop.ulVal; | ||
81 | name.Empty(); | ||
82 | } | ||
83 | else if (prop.vt != VT_EMPTY) | ||
84 | return E_INVALIDARG; | ||
85 | } | ||
86 | { | ||
87 | NWindows::NCOM::CPropVariant prop; | ||
88 | RINOK(getProp->GetProperty(pidName, &prop)); | ||
89 | if (prop.vt == VT_BSTR) | ||
90 | { | ||
91 | const UString s = prop.bstrVal; | ||
92 | Get_AString_From_UString(s, name, codePage, utfFlags); | ||
93 | // printf("\ngetProp->GetProperty(pidName, &prop) : %s" , name.Ptr()); | ||
94 | if (!isSet) | ||
95 | id = 0; | ||
96 | } | ||
97 | else if (prop.vt == VT_UI4) | ||
98 | { | ||
99 | id = prop.ulVal; | ||
100 | name.Empty(); | ||
101 | } | ||
102 | else if (prop.vt != VT_EMPTY) | ||
103 | return E_INVALIDARG; | ||
104 | } | ||
105 | return S_OK; | ||
106 | } | ||
107 | |||
108 | |||
109 | /* | ||
110 | static HRESULT GetDevice(IStreamGetProp *getProp, | ||
111 | UInt32 &majo, UInt32 &mino, bool &majo_defined, bool &mino_defined) | ||
112 | { | ||
113 | NWindows::NCOM::CPropVariant prop; | ||
114 | RINOK(getProp->GetProperty(kpidDevice, &prop)); | ||
115 | if (prop.vt == VT_EMPTY) | ||
116 | return S_OK; | ||
117 | if (prop.vt != VT_UI8) | ||
118 | return E_INVALIDARG; | ||
119 | { | ||
120 | printf("\nTarUpdate.cpp :: GetDevice()\n"); | ||
121 | const UInt64 v = prop.uhVal.QuadPart; | ||
122 | majo = MY_dev_major(v); | ||
123 | mino = MY_dev_minor(v); | ||
124 | majo_defined = true; | ||
125 | mino_defined = true; | ||
126 | } | ||
127 | return S_OK; | ||
128 | } | ||
129 | */ | ||
130 | |||
131 | static HRESULT GetDevice(IStreamGetProp *getProp, | ||
132 | UInt32 pid, UInt32 &id, bool &defined) | ||
133 | { | ||
134 | defined = false; | ||
135 | NWindows::NCOM::CPropVariant prop; | ||
136 | RINOK(getProp->GetProperty(pid, &prop)); | ||
137 | if (prop.vt == VT_EMPTY) | ||
138 | return S_OK; | ||
139 | if (prop.vt == VT_UI4) | ||
140 | { | ||
141 | id = prop.ulVal; | ||
142 | defined = true; | ||
143 | return S_OK; | ||
144 | } | ||
145 | return E_INVALIDARG; | ||
146 | } | ||
147 | |||
148 | |||
18 | HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, | 149 | HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, |
19 | const CObjectVector<NArchive::NTar::CItemEx> &inputItems, | 150 | const CObjectVector<NArchive::NTar::CItemEx> &inputItems, |
20 | const CObjectVector<CUpdateItem> &updateItems, | 151 | const CObjectVector<CUpdateItem> &updateItems, |
21 | UINT codePage, unsigned utfFlags, | 152 | const CUpdateOptions &options, |
22 | IArchiveUpdateCallback *updateCallback) | 153 | IArchiveUpdateCallback *updateCallback) |
23 | { | 154 | { |
24 | COutArchive outArchive; | 155 | COutArchive outArchive; |
25 | outArchive.Create(outStream); | 156 | outArchive.Create(outStream); |
26 | outArchive.Pos = 0; | 157 | outArchive.Pos = 0; |
158 | outArchive.IsPosixMode = options.PosixMode; | ||
159 | outArchive.TimeOptions = options.TimeOptions; | ||
27 | 160 | ||
28 | CMyComPtr<IOutStream> outSeekStream; | 161 | CMyComPtr<IOutStream> outSeekStream; |
29 | outStream->QueryInterface(IID_IOutStream, (void **)&outSeekStream); | 162 | outStream->QueryInterface(IID_IOutStream, (void **)&outSeekStream); |
163 | if (outSeekStream) | ||
164 | { | ||
165 | /* | ||
166 | // for debug | ||
167 | Byte buf[1 << 14]; | ||
168 | memset (buf, 0, sizeof(buf)); | ||
169 | RINOK(outStream->Write(buf, sizeof(buf), NULL)); | ||
170 | */ | ||
171 | // we need real outArchive.Pos, if outSeekStream->SetSize() will be used. | ||
172 | RINOK(outSeekStream->Seek(0, STREAM_SEEK_CUR, &outArchive.Pos)); | ||
173 | } | ||
174 | |||
30 | 175 | ||
31 | CMyComPtr<IArchiveUpdateCallbackFile> opCallback; | 176 | CMyComPtr<IArchiveUpdateCallbackFile> opCallback; |
32 | updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback); | 177 | updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback); |
@@ -40,7 +185,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, | |||
40 | if (ui.NewData) | 185 | if (ui.NewData) |
41 | complexity += ui.Size; | 186 | complexity += ui.Size; |
42 | else | 187 | else |
43 | complexity += inputItems[(unsigned)ui.IndexInArc].GetFullSize(); | 188 | complexity += inputItems[(unsigned)ui.IndexInArc].Get_FullSize_Aligned(); |
44 | } | 189 | } |
45 | 190 | ||
46 | RINOK(updateCallback->SetTotal(complexity)); | 191 | RINOK(updateCallback->SetTotal(complexity)); |
@@ -58,21 +203,31 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, | |||
58 | 203 | ||
59 | complexity = 0; | 204 | complexity = 0; |
60 | 205 | ||
61 | for (i = 0; i < updateItems.Size(); i++) | 206 | // const int kNumReduceDigits = -1; // for debug |
207 | |||
208 | for (i = 0;; i++) | ||
62 | { | 209 | { |
63 | lps->InSize = lps->OutSize = complexity; | 210 | lps->InSize = lps->OutSize = complexity; |
64 | RINOK(lps->SetCur()); | 211 | RINOK(lps->SetCur()); |
65 | 212 | ||
213 | if (i == updateItems.Size()) | ||
214 | return outArchive.WriteFinishHeader(); | ||
215 | |||
66 | const CUpdateItem &ui = updateItems[i]; | 216 | const CUpdateItem &ui = updateItems[i]; |
67 | CItem item; | 217 | CItem item; |
68 | 218 | ||
69 | if (ui.NewProps) | 219 | if (ui.NewProps) |
70 | { | 220 | { |
71 | item.SetDefaultWriteFields(); | 221 | item.SetMagic_Posix(options.PosixMode); |
72 | item.Mode = ui.Mode; | ||
73 | item.Name = ui.Name; | 222 | item.Name = ui.Name; |
74 | item.User = ui.User; | 223 | item.User = ui.User; |
75 | item.Group = ui.Group; | 224 | item.Group = ui.Group; |
225 | item.UID = ui.UID; | ||
226 | item.GID = ui.GID; | ||
227 | item.DeviceMajor = ui.DeviceMajor; | ||
228 | item.DeviceMinor = ui.DeviceMinor; | ||
229 | item.DeviceMajor_Defined = ui.DeviceMajor_Defined; | ||
230 | item.DeviceMinor_Defined = ui.DeviceMinor_Defined; | ||
76 | 231 | ||
77 | if (ui.IsDir) | 232 | if (ui.IsDir) |
78 | { | 233 | { |
@@ -81,11 +236,15 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, | |||
81 | } | 236 | } |
82 | else | 237 | else |
83 | { | 238 | { |
84 | item.LinkFlag = NFileHeader::NLinkFlag::kNormal; | ||
85 | item.PackSize = ui.Size; | 239 | item.PackSize = ui.Size; |
240 | item.Set_LinkFlag_for_File(ui.Mode); | ||
86 | } | 241 | } |
87 | 242 | ||
88 | item.MTime = ui.MTime; | 243 | // 22.00 |
244 | item.Mode = ui.Mode & ~(UInt32)MY_LIN_S_IFMT; | ||
245 | item.PaxTimes = ui.PaxTimes; | ||
246 | // item.PaxTimes.ReducePrecison(kNumReduceDigits); // for debug | ||
247 | item.MTime = ui.PaxTimes.MTime.GetSec(); | ||
89 | } | 248 | } |
90 | else | 249 | else |
91 | item = inputItems[(unsigned)ui.IndexInArc]; | 250 | item = inputItems[(unsigned)ui.IndexInArc]; |
@@ -93,7 +252,8 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, | |||
93 | AString symLink; | 252 | AString symLink; |
94 | if (ui.NewData || ui.NewProps) | 253 | if (ui.NewData || ui.NewProps) |
95 | { | 254 | { |
96 | RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidSymLink, symLink, codePage, utfFlags, true)); | 255 | RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidSymLink, symLink, |
256 | options.CodePage, options.UtfFlags, true)); | ||
97 | if (!symLink.IsEmpty()) | 257 | if (!symLink.IsEmpty()) |
98 | { | 258 | { |
99 | item.LinkFlag = NFileHeader::NLinkFlag::kSymLink; | 259 | item.LinkFlag = NFileHeader::NLinkFlag::kSymLink; |
@@ -120,7 +280,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, | |||
120 | } | 280 | } |
121 | else | 281 | else |
122 | { | 282 | { |
123 | HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream); | 283 | const HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream); |
124 | 284 | ||
125 | if (res == S_FALSE) | 285 | if (res == S_FALSE) |
126 | needWrite = false; | 286 | needWrite = false; |
@@ -128,31 +288,105 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, | |||
128 | { | 288 | { |
129 | RINOK(res); | 289 | RINOK(res); |
130 | 290 | ||
131 | if (fileInStream) | 291 | if (!fileInStream) |
292 | { | ||
293 | item.PackSize = 0; | ||
294 | item.Size = 0; | ||
295 | } | ||
296 | else | ||
132 | { | 297 | { |
133 | CMyComPtr<IStreamGetProps> getProps; | 298 | CMyComPtr<IStreamGetProps> getProps; |
134 | fileInStream->QueryInterface(IID_IStreamGetProps, (void **)&getProps); | 299 | CMyComPtr<IStreamGetProp> getProp; |
135 | if (getProps) | 300 | fileInStream->QueryInterface(IID_IStreamGetProp, (void **)&getProp); |
301 | if (getProp) | ||
302 | { | ||
303 | if (options.Write_MTime.Val) RINOK(GetTime(getProp, kpidMTime, item.PaxTimes.MTime)) | ||
304 | if (options.Write_ATime.Val) RINOK(GetTime(getProp, kpidATime, item.PaxTimes.ATime)) | ||
305 | if (options.Write_CTime.Val) RINOK(GetTime(getProp, kpidCTime, item.PaxTimes.CTime)) | ||
306 | |||
307 | if (options.PosixMode) | ||
308 | { | ||
309 | /* | ||
310 | RINOK(GetDevice(getProp, item.DeviceMajor, item.DeviceMinor, | ||
311 | item.DeviceMajor_Defined, item.DeviceMinor_Defined)); | ||
312 | */ | ||
313 | bool defined = false; | ||
314 | UInt32 val = 0; | ||
315 | RINOK(GetDevice(getProp, kpidDeviceMajor, val, defined)); | ||
316 | if (defined) | ||
317 | { | ||
318 | item.DeviceMajor = val; | ||
319 | item.DeviceMajor_Defined = true; | ||
320 | item.DeviceMinor = 0; | ||
321 | item.DeviceMinor_Defined = false; | ||
322 | RINOK(GetDevice(getProp, kpidDeviceMinor, item.DeviceMinor, item.DeviceMinor_Defined)); | ||
323 | } | ||
324 | } | ||
325 | |||
326 | RINOK(GetUser(getProp, kpidUser, kpidUserId, item.User, item.UID, options.CodePage, options.UtfFlags)); | ||
327 | RINOK(GetUser(getProp, kpidGroup, kpidGroupId, item.Group, item.GID, options.CodePage, options.UtfFlags)); | ||
328 | |||
329 | { | ||
330 | NWindows::NCOM::CPropVariant prop; | ||
331 | RINOK(getProp->GetProperty(kpidPosixAttrib, &prop)); | ||
332 | if (prop.vt == VT_EMPTY) | ||
333 | item.Mode = | ||
334 | MY_LIN_S_IRWXO | ||
335 | | MY_LIN_S_IRWXG | ||
336 | | MY_LIN_S_IRWXU | ||
337 | | (ui.IsDir ? MY_LIN_S_IFDIR : MY_LIN_S_IFREG); | ||
338 | else if (prop.vt != VT_UI4) | ||
339 | return E_INVALIDARG; | ||
340 | else | ||
341 | item.Mode = prop.ulVal; | ||
342 | // 21.07 : we clear high file type bits as GNU TAR. | ||
343 | item.Set_LinkFlag_for_File(item.Mode); | ||
344 | item.Mode &= ~(UInt32)MY_LIN_S_IFMT; | ||
345 | } | ||
346 | |||
347 | { | ||
348 | NWindows::NCOM::CPropVariant prop; | ||
349 | RINOK(getProp->GetProperty(kpidSize, &prop)); | ||
350 | if (prop.vt != VT_UI8) | ||
351 | return E_INVALIDARG; | ||
352 | const UInt64 size = prop.uhVal.QuadPart; | ||
353 | item.PackSize = size; | ||
354 | item.Size = size; | ||
355 | } | ||
356 | /* | ||
357 | printf("\nNum digits = %d %d\n", | ||
358 | (int)item.PaxTimes.MTime.NumDigits, | ||
359 | (int)item.PaxTimes.MTime.Ns); | ||
360 | */ | ||
361 | } | ||
362 | else | ||
136 | { | 363 | { |
137 | FILETIME mTime; | 364 | fileInStream->QueryInterface(IID_IStreamGetProps, (void **)&getProps); |
138 | UInt64 size2; | 365 | if (getProps) |
139 | if (getProps->GetProps(&size2, NULL, NULL, &mTime, NULL) == S_OK) | ||
140 | { | 366 | { |
141 | item.PackSize = size2; | 367 | FILETIME mTime, aTime, cTime; |
142 | item.Size = size2; | 368 | UInt64 size2; |
143 | item.MTime = NWindows::NTime::FileTimeToUnixTime64(mTime);; | 369 | if (getProps->GetProps(&size2, |
370 | options.Write_CTime.Val ? &cTime : NULL, | ||
371 | options.Write_ATime.Val ? &aTime : NULL, | ||
372 | options.Write_MTime.Val ? &mTime : NULL, | ||
373 | NULL) == S_OK) | ||
374 | { | ||
375 | item.PackSize = size2; | ||
376 | item.Size = size2; | ||
377 | if (options.Write_MTime.Val) FILETIME_To_PaxTime(mTime, item.PaxTimes.MTime); | ||
378 | if (options.Write_ATime.Val) FILETIME_To_PaxTime(aTime, item.PaxTimes.ATime); | ||
379 | if (options.Write_CTime.Val) FILETIME_To_PaxTime(cTime, item.PaxTimes.CTime); | ||
380 | } | ||
144 | } | 381 | } |
145 | } | 382 | } |
146 | } | 383 | } |
147 | else | ||
148 | { | ||
149 | item.PackSize = 0; | ||
150 | item.Size = 0; | ||
151 | } | ||
152 | 384 | ||
153 | { | 385 | { |
386 | // we must request kpidHardLink after updateCallback->GetStream() | ||
154 | AString hardLink; | 387 | AString hardLink; |
155 | RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidHardLink, hardLink, codePage, utfFlags, true)); | 388 | RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidHardLink, hardLink, |
389 | options.CodePage, options.UtfFlags, true)); | ||
156 | if (!hardLink.IsEmpty()) | 390 | if (!hardLink.IsEmpty()) |
157 | { | 391 | { |
158 | item.LinkFlag = NFileHeader::NLinkFlag::kHardLink; | 392 | item.LinkFlag = NFileHeader::NLinkFlag::kHardLink; |
@@ -165,37 +399,98 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, | |||
165 | } | 399 | } |
166 | } | 400 | } |
167 | 401 | ||
402 | // item.PaxTimes.ReducePrecison(kNumReduceDigits); // for debug | ||
403 | |||
404 | if (ui.NewProps) | ||
405 | item.MTime = item.PaxTimes.MTime.GetSec(); | ||
406 | |||
168 | if (needWrite) | 407 | if (needWrite) |
169 | { | 408 | { |
170 | UInt64 fileHeaderStartPos = outArchive.Pos; | 409 | const UInt64 headerPos = outArchive.Pos; |
410 | // item.PackSize = ((UInt64)1 << 33); // for debug | ||
171 | RINOK(outArchive.WriteHeader(item)); | 411 | RINOK(outArchive.WriteHeader(item)); |
172 | if (fileInStream) | 412 | if (fileInStream) |
173 | { | 413 | { |
174 | RINOK(copyCoder->Code(fileInStream, outStream, NULL, NULL, progress)); | 414 | for (unsigned numPasses = 0;; numPasses++) |
175 | outArchive.Pos += copyCoderSpec->TotalSize; | ||
176 | if (copyCoderSpec->TotalSize != item.PackSize) | ||
177 | { | 415 | { |
416 | /* we support 2 attempts to write header: | ||
417 | pass-0: main pass: | ||
418 | pass-1: additional pass, if size_of_file and size_of_header are changed */ | ||
419 | if (numPasses >= 2) | ||
420 | { | ||
421 | // opRes = NArchive::NUpdate::NOperationResult::kError_FileChanged; | ||
422 | // break; | ||
423 | return E_FAIL; | ||
424 | } | ||
425 | |||
426 | const UInt64 dataPos = outArchive.Pos; | ||
427 | RINOK(copyCoder->Code(fileInStream, outStream, NULL, NULL, progress)); | ||
428 | outArchive.Pos += copyCoderSpec->TotalSize; | ||
429 | RINOK(outArchive.Write_AfterDataResidual(copyCoderSpec->TotalSize)); | ||
430 | |||
431 | // if (numPasses >= 10) // for debug | ||
432 | if (copyCoderSpec->TotalSize == item.PackSize) | ||
433 | break; | ||
434 | |||
435 | if (opCallback) | ||
436 | { | ||
437 | RINOK(opCallback->ReportOperation( | ||
438 | NEventIndexType::kOutArcIndex, (UInt32)ui.IndexInClient, | ||
439 | NUpdateNotifyOp::kInFileChanged)) | ||
440 | } | ||
441 | |||
178 | if (!outSeekStream) | 442 | if (!outSeekStream) |
179 | return E_FAIL; | 443 | return E_FAIL; |
180 | UInt64 backOffset = outArchive.Pos - fileHeaderStartPos; | 444 | const UInt64 nextPos = outArchive.Pos; |
181 | RINOK(outSeekStream->Seek(-(Int64)backOffset, STREAM_SEEK_CUR, NULL)); | 445 | RINOK(outSeekStream->Seek(-(Int64)(nextPos - headerPos), STREAM_SEEK_CUR, NULL)); |
182 | outArchive.Pos = fileHeaderStartPos; | 446 | outArchive.Pos = headerPos; |
183 | item.PackSize = copyCoderSpec->TotalSize; | 447 | item.PackSize = copyCoderSpec->TotalSize; |
448 | |||
184 | RINOK(outArchive.WriteHeader(item)); | 449 | RINOK(outArchive.WriteHeader(item)); |
185 | RINOK(outSeekStream->Seek((Int64)item.PackSize, STREAM_SEEK_CUR, NULL)); | 450 | |
186 | outArchive.Pos += item.PackSize; | 451 | // if (numPasses >= 10) // for debug |
452 | if (outArchive.Pos == dataPos) | ||
453 | { | ||
454 | const UInt64 alignedSize = nextPos - dataPos; | ||
455 | if (alignedSize != 0) | ||
456 | { | ||
457 | RINOK(outSeekStream->Seek(alignedSize, STREAM_SEEK_CUR, NULL)); | ||
458 | outArchive.Pos += alignedSize; | ||
459 | } | ||
460 | break; | ||
461 | } | ||
462 | |||
463 | // size of header was changed. | ||
464 | // we remove data after header and try new attempt, if required | ||
465 | CMyComPtr<IInStream> fileSeekStream; | ||
466 | fileInStream->QueryInterface(IID_IInStream, (void **)&fileSeekStream); | ||
467 | if (!fileSeekStream) | ||
468 | return E_FAIL; | ||
469 | RINOK(fileSeekStream->Seek(0, STREAM_SEEK_SET, NULL)); | ||
470 | RINOK(outSeekStream->SetSize(outArchive.Pos)); | ||
471 | if (item.PackSize == 0) | ||
472 | break; | ||
187 | } | 473 | } |
188 | RINOK(outArchive.FillDataResidual(item.PackSize)); | ||
189 | } | 474 | } |
190 | } | 475 | } |
191 | 476 | ||
192 | complexity += item.PackSize; | 477 | complexity += item.PackSize; |
478 | fileInStream.Release(); | ||
193 | RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); | 479 | RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); |
194 | } | 480 | } |
195 | else | 481 | else |
196 | { | 482 | { |
483 | // (ui.NewData == false) | ||
484 | |||
485 | if (opCallback) | ||
486 | { | ||
487 | RINOK(opCallback->ReportOperation( | ||
488 | NEventIndexType::kInArcIndex, (UInt32)ui.IndexInArc, | ||
489 | NUpdateNotifyOp::kReplicate)) | ||
490 | } | ||
491 | |||
197 | const CItemEx &existItem = inputItems[(unsigned)ui.IndexInArc]; | 492 | const CItemEx &existItem = inputItems[(unsigned)ui.IndexInArc]; |
198 | UInt64 size; | 493 | UInt64 size, pos; |
199 | 494 | ||
200 | if (ui.NewProps) | 495 | if (ui.NewProps) |
201 | { | 496 | { |
@@ -216,44 +511,37 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, | |||
216 | item.PackSize = existItem.PackSize; | 511 | item.PackSize = existItem.PackSize; |
217 | } | 512 | } |
218 | 513 | ||
219 | item.DeviceMajorDefined = existItem.DeviceMajorDefined; | 514 | item.DeviceMajor_Defined = existItem.DeviceMajor_Defined; |
220 | item.DeviceMinorDefined = existItem.DeviceMinorDefined; | 515 | item.DeviceMinor_Defined = existItem.DeviceMinor_Defined; |
221 | item.DeviceMajor = existItem.DeviceMajor; | 516 | item.DeviceMajor = existItem.DeviceMajor; |
222 | item.DeviceMinor = existItem.DeviceMinor; | 517 | item.DeviceMinor = existItem.DeviceMinor; |
223 | item.UID = existItem.UID; | 518 | item.UID = existItem.UID; |
224 | item.GID = existItem.GID; | 519 | item.GID = existItem.GID; |
225 | 520 | ||
226 | RINOK(outArchive.WriteHeader(item)); | 521 | RINOK(outArchive.WriteHeader(item)); |
227 | RINOK(inStream->Seek((Int64)existItem.GetDataPosition(), STREAM_SEEK_SET, NULL)); | 522 | size = existItem.Get_PackSize_Aligned(); |
228 | size = existItem.PackSize; | 523 | pos = existItem.Get_DataPos(); |
229 | } | 524 | } |
230 | else | 525 | else |
231 | { | 526 | { |
232 | RINOK(inStream->Seek((Int64)existItem.HeaderPos, STREAM_SEEK_SET, NULL)); | 527 | size = existItem.Get_FullSize_Aligned(); |
233 | size = existItem.GetFullSize(); | 528 | pos = existItem.HeaderPos; |
234 | } | 529 | } |
235 | |||
236 | streamSpec->Init(size); | ||
237 | 530 | ||
238 | if (opCallback) | 531 | if (size != 0) |
239 | { | 532 | { |
240 | RINOK(opCallback->ReportOperation( | 533 | RINOK(inStream->Seek((Int64)pos, STREAM_SEEK_SET, NULL)); |
241 | NEventIndexType::kInArcIndex, (UInt32)ui.IndexInArc, | 534 | streamSpec->Init(size); |
242 | NUpdateNotifyOp::kReplicate)) | 535 | // 22.00 : we copy Residual data from old archive to new archive instead of zeroing |
536 | RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)); | ||
537 | if (copyCoderSpec->TotalSize != size) | ||
538 | return E_FAIL; | ||
539 | outArchive.Pos += size; | ||
540 | // RINOK(outArchive.Write_AfterDataResidual(existItem.PackSize)); | ||
541 | complexity += size; | ||
243 | } | 542 | } |
244 | |||
245 | RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)); | ||
246 | if (copyCoderSpec->TotalSize != size) | ||
247 | return E_FAIL; | ||
248 | outArchive.Pos += size; | ||
249 | RINOK(outArchive.FillDataResidual(existItem.PackSize)); | ||
250 | complexity += size; | ||
251 | } | 543 | } |
252 | } | 544 | } |
253 | |||
254 | lps->InSize = lps->OutSize = complexity; | ||
255 | RINOK(lps->SetCur()); | ||
256 | return outArchive.WriteFinishHeader(); | ||
257 | } | 545 | } |
258 | 546 | ||
259 | }} | 547 | }} |
diff --git a/CPP/7zip/Archive/Tar/TarUpdate.h b/CPP/7zip/Archive/Tar/TarUpdate.h index 1e3d021..ca0976d 100644 --- a/CPP/7zip/Archive/Tar/TarUpdate.h +++ b/CPP/7zip/Archive/Tar/TarUpdate.h | |||
@@ -15,27 +15,60 @@ struct CUpdateItem | |||
15 | int IndexInArc; | 15 | int IndexInArc; |
16 | unsigned IndexInClient; | 16 | unsigned IndexInClient; |
17 | UInt64 Size; | 17 | UInt64 Size; |
18 | Int64 MTime; | 18 | // Int64 MTime; |
19 | UInt32 Mode; | 19 | UInt32 Mode; |
20 | bool NewData; | 20 | bool NewData; |
21 | bool NewProps; | 21 | bool NewProps; |
22 | bool IsDir; | 22 | bool IsDir; |
23 | bool DeviceMajor_Defined; | ||
24 | bool DeviceMinor_Defined; | ||
25 | UInt32 UID; | ||
26 | UInt32 GID; | ||
27 | UInt32 DeviceMajor; | ||
28 | UInt32 DeviceMinor; | ||
23 | AString Name; | 29 | AString Name; |
24 | AString User; | 30 | AString User; |
25 | AString Group; | 31 | AString Group; |
26 | 32 | ||
27 | CUpdateItem(): Size(0), IsDir(false) {} | 33 | CPaxTimes PaxTimes; |
34 | |||
35 | CUpdateItem(): | ||
36 | Size(0), | ||
37 | IsDir(false), | ||
38 | DeviceMajor_Defined(false), | ||
39 | DeviceMinor_Defined(false), | ||
40 | UID(0), | ||
41 | GID(0) | ||
42 | {} | ||
43 | }; | ||
44 | |||
45 | |||
46 | struct CUpdateOptions | ||
47 | { | ||
48 | UINT CodePage; | ||
49 | unsigned UtfFlags; | ||
50 | bool PosixMode; | ||
51 | CBoolPair Write_MTime; | ||
52 | CBoolPair Write_ATime; | ||
53 | CBoolPair Write_CTime; | ||
54 | CTimeOptions TimeOptions; | ||
28 | }; | 55 | }; |
29 | 56 | ||
57 | |||
30 | HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, | 58 | HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, |
31 | const CObjectVector<CItemEx> &inputItems, | 59 | const CObjectVector<CItemEx> &inputItems, |
32 | const CObjectVector<CUpdateItem> &updateItems, | 60 | const CObjectVector<CUpdateItem> &updateItems, |
33 | UINT codePage, unsigned utfFlags, | 61 | const CUpdateOptions &options, |
34 | IArchiveUpdateCallback *updateCallback); | 62 | IArchiveUpdateCallback *updateCallback); |
35 | 63 | ||
36 | HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, AString &res, | 64 | HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, AString &res, |
37 | UINT codePage, unsigned utfFlags, bool convertSlash); | 65 | UINT codePage, unsigned utfFlags, bool convertSlash); |
38 | 66 | ||
67 | HRESULT Prop_To_PaxTime(const NWindows::NCOM::CPropVariant &prop, CPaxTime &pt); | ||
68 | |||
69 | void Get_AString_From_UString(const UString &s, AString &res, | ||
70 | UINT codePage, unsigned utfFlags); | ||
71 | |||
39 | }} | 72 | }} |
40 | 73 | ||
41 | #endif | 74 | #endif |
diff --git a/CPP/7zip/Archive/Udf/UdfHandler.cpp b/CPP/7zip/Archive/Udf/UdfHandler.cpp index 74ec0be..2232c64 100644 --- a/CPP/7zip/Archive/Udf/UdfHandler.cpp +++ b/CPP/7zip/Archive/Udf/UdfHandler.cpp | |||
@@ -27,11 +27,17 @@ static void UdfTimeToFileTime(const CTime &t, NWindows::NCOM::CPropVariant &prop | |||
27 | return; | 27 | return; |
28 | if (t.IsLocal()) | 28 | if (t.IsLocal()) |
29 | numSecs -= (Int64)((Int32)t.GetMinutesOffset() * 60); | 29 | numSecs -= (Int64)((Int32)t.GetMinutesOffset() * 60); |
30 | FILETIME ft; | 30 | const UInt32 m0 = d[9]; |
31 | UInt64 v = (((numSecs * 100 + d[9]) * 100 + d[10]) * 100 + d[11]) * 10; | 31 | const UInt32 m1 = d[10]; |
32 | ft.dwLowDateTime = (UInt32)v; | 32 | const UInt32 m2 = d[11]; |
33 | ft.dwHighDateTime = (UInt32)(v >> 32); | 33 | unsigned numDigits = 0; |
34 | prop = ft; | 34 | UInt64 v = numSecs * 10000000; |
35 | if (m0 < 100 && m1 < 100 && m2 < 100) | ||
36 | { | ||
37 | v += m0 * 100000 + m1 * 1000 + m2 * 10; | ||
38 | numDigits = 6; | ||
39 | } | ||
40 | prop.SetAsTimeFrom_Ft64_Prec(v, k_PropVar_TimePrec_Base + numDigits); | ||
35 | } | 41 | } |
36 | 42 | ||
37 | static const Byte kProps[] = | 43 | static const Byte kProps[] = |
@@ -41,7 +47,8 @@ static const Byte kProps[] = | |||
41 | kpidSize, | 47 | kpidSize, |
42 | kpidPackSize, | 48 | kpidPackSize, |
43 | kpidMTime, | 49 | kpidMTime, |
44 | kpidATime | 50 | kpidATime, |
51 | kpidChangeTime | ||
45 | }; | 52 | }; |
46 | 53 | ||
47 | static const Byte kArcProps[] = | 54 | static const Byte kArcProps[] = |
@@ -205,6 +212,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
205 | case kpidPackSize: if (!item.IsDir()) prop = (UInt64)item.NumLogBlockRecorded * vol.BlockSize; break; | 212 | case kpidPackSize: if (!item.IsDir()) prop = (UInt64)item.NumLogBlockRecorded * vol.BlockSize; break; |
206 | case kpidMTime: UdfTimeToFileTime(item.MTime, prop); break; | 213 | case kpidMTime: UdfTimeToFileTime(item.MTime, prop); break; |
207 | case kpidATime: UdfTimeToFileTime(item.ATime, prop); break; | 214 | case kpidATime: UdfTimeToFileTime(item.ATime, prop); break; |
215 | case kpidChangeTime: UdfTimeToFileTime(item.AttribTime, prop); break; | ||
208 | } | 216 | } |
209 | } | 217 | } |
210 | prop.Detach(value); | 218 | prop.Detach(value); |
diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp index 04d9228..d2d2b20 100644 --- a/CPP/7zip/Archive/Udf/UdfIn.cpp +++ b/CPP/7zip/Archive/Udf/UdfIn.cpp | |||
@@ -333,7 +333,7 @@ void CItem::Parse(const Byte *p) | |||
333 | NumLogBlockRecorded = Get64(p + 64); | 333 | NumLogBlockRecorded = Get64(p + 64); |
334 | ATime.Parse(p + 72); | 334 | ATime.Parse(p + 72); |
335 | MTime.Parse(p + 84); | 335 | MTime.Parse(p + 84); |
336 | // AttrtTime.Parse(p + 96); | 336 | AttribTime.Parse(p + 96); |
337 | // CheckPoint = Get32(p + 108); | 337 | // CheckPoint = Get32(p + 108); |
338 | // ExtendedAttrIcb.Parse(p + 112); | 338 | // ExtendedAttrIcb.Parse(p + 112); |
339 | // ImplId.Parse(p + 128); | 339 | // ImplId.Parse(p + 128); |
diff --git a/CPP/7zip/Archive/Udf/UdfIn.h b/CPP/7zip/Archive/Udf/UdfIn.h index c26f609..4e7dfa1 100644 --- a/CPP/7zip/Archive/Udf/UdfIn.h +++ b/CPP/7zip/Archive/Udf/UdfIn.h | |||
@@ -243,7 +243,7 @@ struct CItem | |||
243 | UInt64 NumLogBlockRecorded; | 243 | UInt64 NumLogBlockRecorded; |
244 | CTime ATime; | 244 | CTime ATime; |
245 | CTime MTime; | 245 | CTime MTime; |
246 | // CTime AttrtTime; | 246 | CTime AttribTime; // Attribute time : most recent date and time of the day of file creation or modification of the attributes of. |
247 | // UInt32 CheckPoint; | 247 | // UInt32 CheckPoint; |
248 | // CLongAllocDesc ExtendedAttrIcb; | 248 | // CLongAllocDesc ExtendedAttrIcb; |
249 | // CRegId ImplId; | 249 | // CRegId ImplId; |
diff --git a/CPP/7zip/Archive/VhdHandler.cpp b/CPP/7zip/Archive/VhdHandler.cpp index 8b9af45..60bc3d3 100644 --- a/CPP/7zip/Archive/VhdHandler.cpp +++ b/CPP/7zip/Archive/VhdHandler.cpp | |||
@@ -921,7 +921,8 @@ STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **strea | |||
921 | CLimitedInStream *streamSpec = new CLimitedInStream; | 921 | CLimitedInStream *streamSpec = new CLimitedInStream; |
922 | CMyComPtr<ISequentialInStream> streamTemp = streamSpec; | 922 | CMyComPtr<ISequentialInStream> streamTemp = streamSpec; |
923 | streamSpec->SetStream(Stream); | 923 | streamSpec->SetStream(Stream); |
924 | streamSpec->InitAndSeek(0, Footer.CurrentSize); | 924 | // fixme : check (startOffset = 0) |
925 | streamSpec->InitAndSeek(_startOffset, Footer.CurrentSize); | ||
925 | RINOK(streamSpec->SeekToStart()); | 926 | RINOK(streamSpec->SeekToStart()); |
926 | *stream = streamTemp.Detach(); | 927 | *stream = streamTemp.Detach(); |
927 | return S_OK; | 928 | return S_OK; |
diff --git a/CPP/7zip/Archive/VhdxHandler.cpp b/CPP/7zip/Archive/VhdxHandler.cpp index e1e4692..0fc83ac 100644 --- a/CPP/7zip/Archive/VhdxHandler.cpp +++ b/CPP/7zip/Archive/VhdxHandler.cpp | |||
@@ -171,6 +171,20 @@ struct CHeader | |||
171 | UInt64 LogOffset; | 171 | UInt64 LogOffset; |
172 | CGuid Guids[3]; | 172 | CGuid Guids[3]; |
173 | 173 | ||
174 | bool IsEqualTo(const CHeader &h) const | ||
175 | { | ||
176 | if (SequenceNumber != h.SequenceNumber) | ||
177 | return false; | ||
178 | if (LogLength != h.LogLength) | ||
179 | return false; | ||
180 | if (LogOffset != h.LogOffset) | ||
181 | return false; | ||
182 | for (unsigned i = 0; i < 3; i++) | ||
183 | if (!Guids[i].IsEqualTo(h.Guids[i])) | ||
184 | return false; | ||
185 | return true; | ||
186 | }; | ||
187 | |||
174 | bool Parse(Byte *p); | 188 | bool Parse(Byte *p); |
175 | }; | 189 | }; |
176 | 190 | ||
@@ -1174,7 +1188,18 @@ HRESULT CHandler::Open3() | |||
1174 | unsigned mainIndex; | 1188 | unsigned mainIndex; |
1175 | if (headers[0].SequenceNumber > headers[1].SequenceNumber) mainIndex = 0; | 1189 | if (headers[0].SequenceNumber > headers[1].SequenceNumber) mainIndex = 0; |
1176 | else if (headers[0].SequenceNumber < headers[1].SequenceNumber) mainIndex = 1; | 1190 | else if (headers[0].SequenceNumber < headers[1].SequenceNumber) mainIndex = 1; |
1177 | else return S_FALSE; | 1191 | else |
1192 | { | ||
1193 | /* Disk2vhd v2.02 can create image with 2 full copies of headers. | ||
1194 | It's violation of VHDX specification: | ||
1195 | "A header is current if it is the only valid header | ||
1196 | or if it is valid and its SequenceNumber field is | ||
1197 | greater than the other header's SequenceNumber". | ||
1198 | but we support such Disk2vhd archives. */ | ||
1199 | if (!headers[0].IsEqualTo(headers[1])) | ||
1200 | return S_FALSE; | ||
1201 | mainIndex = 0; | ||
1202 | } | ||
1178 | 1203 | ||
1179 | const CHeader &h = headers[mainIndex]; | 1204 | const CHeader &h = headers[mainIndex]; |
1180 | Header = h; | 1205 | Header = h; |
@@ -1567,6 +1592,7 @@ static void AddComment_BlockSize(UString &s, const char *name, unsigned logSize) | |||
1567 | 1592 | ||
1568 | void CHandler::AddComment(UString &s) const | 1593 | void CHandler::AddComment(UString &s) const |
1569 | { | 1594 | { |
1595 | AddComment_UInt64(s, "VirtualDiskSize", Meta.VirtualDiskSize); | ||
1570 | AddComment_UInt64(s, "PhysicalSize", _phySize); | 1596 | AddComment_UInt64(s, "PhysicalSize", _phySize); |
1571 | 1597 | ||
1572 | if (!_errorMessage.IsEmpty()) | 1598 | if (!_errorMessage.IsEmpty()) |
diff --git a/CPP/7zip/Archive/VmdkHandler.cpp b/CPP/7zip/Archive/VmdkHandler.cpp index fb5bb1f..40f5613 100644 --- a/CPP/7zip/Archive/VmdkHandler.cpp +++ b/CPP/7zip/Archive/VmdkHandler.cpp | |||
@@ -138,7 +138,7 @@ static bool Str_to_ValName(const AString &s, AString &name, AString &val) | |||
138 | int eq = s.Find('='); | 138 | int eq = s.Find('='); |
139 | if (eq < 0 || (qu >= 0 && eq > qu)) | 139 | if (eq < 0 || (qu >= 0 && eq > qu)) |
140 | return false; | 140 | return false; |
141 | name = s.Left(eq); | 141 | name.SetFrom(s.Ptr(), eq); |
142 | name.Trim(); | 142 | name.Trim(); |
143 | val = s.Ptr(eq + 1); | 143 | val = s.Ptr(eq + 1); |
144 | val.Trim(); | 144 | val.Trim(); |
diff --git a/CPP/7zip/Archive/Wim/WimHandler.cpp b/CPP/7zip/Archive/Wim/WimHandler.cpp index 9e39d02..3b39455 100644 --- a/CPP/7zip/Archive/Wim/WimHandler.cpp +++ b/CPP/7zip/Archive/Wim/WimHandler.cpp | |||
@@ -355,6 +355,7 @@ static void GetFileTime(const Byte *p, NCOM::CPropVariant &prop) | |||
355 | prop.vt = VT_FILETIME; | 355 | prop.vt = VT_FILETIME; |
356 | prop.filetime.dwLowDateTime = Get32(p); | 356 | prop.filetime.dwLowDateTime = Get32(p); |
357 | prop.filetime.dwHighDateTime = Get32(p + 4); | 357 | prop.filetime.dwHighDateTime = Get32(p + 4); |
358 | prop.Set_FtPrec(k_PropVar_TimePrec_100ns); | ||
358 | } | 359 | } |
359 | 360 | ||
360 | 361 | ||
@@ -842,7 +843,7 @@ public: | |||
842 | int dotPos = name.ReverseFind_Dot(); | 843 | int dotPos = name.ReverseFind_Dot(); |
843 | if (dotPos < 0) | 844 | if (dotPos < 0) |
844 | dotPos = name.Len(); | 845 | dotPos = name.Len(); |
845 | _before = name.Left(dotPos); | 846 | _before.SetFrom(name.Ptr(), dotPos); |
846 | _after = name.Ptr(dotPos); | 847 | _after = name.Ptr(dotPos); |
847 | } | 848 | } |
848 | 849 | ||
diff --git a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp index 6b4497f..5e8365a 100644 --- a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp +++ b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp | |||
@@ -32,8 +32,8 @@ static int AddUniqHash(const CStreamInfo *streams, CUIntVector &sorted, const By | |||
32 | unsigned left = 0, right = sorted.Size(); | 32 | unsigned left = 0, right = sorted.Size(); |
33 | while (left != right) | 33 | while (left != right) |
34 | { | 34 | { |
35 | unsigned mid = (left + right) / 2; | 35 | const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); |
36 | unsigned index = sorted[mid]; | 36 | const unsigned index = sorted[mid]; |
37 | const Byte *hash2 = streams[index].Hash; | 37 | const Byte *hash2 = streams[index].Hash; |
38 | 38 | ||
39 | unsigned i; | 39 | unsigned i; |
@@ -124,9 +124,9 @@ static int AddToHardLinkList(const CObjectVector<CMetaItem> &metaItems, unsigned | |||
124 | unsigned left = 0, right = indexes.Size(); | 124 | unsigned left = 0, right = indexes.Size(); |
125 | while (left != right) | 125 | while (left != right) |
126 | { | 126 | { |
127 | unsigned mid = (left + right) / 2; | 127 | const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); |
128 | unsigned index = indexes[mid]; | 128 | const unsigned index = indexes[mid]; |
129 | int comp = Compare_HardLink_MetaItems(mi, metaItems[index]); | 129 | const int comp = Compare_HardLink_MetaItems(mi, metaItems[index]); |
130 | if (comp == 0) | 130 | if (comp == 0) |
131 | return index; | 131 | return index; |
132 | if (comp < 0) | 132 | if (comp < 0) |
@@ -203,8 +203,8 @@ bool CDir::FindDir(const CObjectVector<CMetaItem> &items, const UString &name, u | |||
203 | unsigned left = 0, right = Dirs.Size(); | 203 | unsigned left = 0, right = Dirs.Size(); |
204 | while (left != right) | 204 | while (left != right) |
205 | { | 205 | { |
206 | unsigned mid = (left + right) / 2; | 206 | const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); |
207 | int comp = CompareFileNames(name, items[Dirs[mid].MetaIndex].Name); | 207 | const int comp = CompareFileNames(name, items[Dirs[mid].MetaIndex].Name); |
208 | if (comp == 0) | 208 | if (comp == 0) |
209 | { | 209 | { |
210 | index = mid; | 210 | index = mid; |
diff --git a/CPP/7zip/Archive/Wim/WimIn.cpp b/CPP/7zip/Archive/Wim/WimIn.cpp index fef6b34..f805521 100644 --- a/CPP/7zip/Archive/Wim/WimIn.cpp +++ b/CPP/7zip/Archive/Wim/WimIn.cpp | |||
@@ -567,9 +567,12 @@ void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCO | |||
567 | for (unsigned i = 0; i < len; i++) | 567 | for (unsigned i = 0; i < len; i++) |
568 | { | 568 | { |
569 | wchar_t c = Get16(meta + i * 2); | 569 | wchar_t c = Get16(meta + i * 2); |
570 | // 18.06 | 570 | if (c == L'/') |
571 | if (c == CHAR_PATH_SEPARATOR || c == '/') | 571 | c = L'_'; |
572 | c = '_'; | 572 | #if WCHAR_PATH_SEPARATOR != L'/' |
573 | else if (c == L'\\') | ||
574 | c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // 22.00 : WSL scheme | ||
575 | #endif | ||
573 | dest[i] = c; | 576 | dest[i] = c; |
574 | } | 577 | } |
575 | } | 578 | } |
diff --git a/CPP/7zip/Archive/Wim/WimRegister.cpp b/CPP/7zip/Archive/Wim/WimRegister.cpp index ecebe8d..e143f91 100644 --- a/CPP/7zip/Archive/Wim/WimRegister.cpp +++ b/CPP/7zip/Archive/Wim/WimRegister.cpp | |||
@@ -10,13 +10,20 @@ namespace NArchive { | |||
10 | namespace NWim { | 10 | namespace NWim { |
11 | 11 | ||
12 | REGISTER_ARC_IO( | 12 | REGISTER_ARC_IO( |
13 | "wim", "wim swm esd ppkg", 0, 0xE6, | 13 | "wim", "wim swm esd ppkg", NULL, 0xE6 |
14 | kSignature, | 14 | , kSignature, 0 |
15 | 0, | 15 | , NArcInfoFlags::kAltStreams |
16 | NArcInfoFlags::kAltStreams | | 16 | | NArcInfoFlags::kNtSecure |
17 | NArcInfoFlags::kNtSecure | | 17 | | NArcInfoFlags::kSymLinks |
18 | NArcInfoFlags::kSymLinks | | 18 | | NArcInfoFlags::kHardLinks |
19 | NArcInfoFlags::kHardLinks | 19 | | NArcInfoFlags::kCTime |
20 | // | NArcInfoFlags::kCTime_Default | ||
21 | | NArcInfoFlags::kATime | ||
22 | // | NArcInfoFlags::kATime_Default | ||
23 | | NArcInfoFlags::kMTime | ||
24 | | NArcInfoFlags::kMTime_Default | ||
25 | , TIME_PREC_TO_ARC_FLAGS_MASK (NFileTimeType::kWindows) | ||
26 | | TIME_PREC_TO_ARC_FLAGS_TIME_DEFAULT (NFileTimeType::kWindows) | ||
20 | , NULL) | 27 | , NULL) |
21 | 28 | ||
22 | }} | 29 | }} |
diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp index f1afab6..d358ca5 100644 --- a/CPP/7zip/Archive/XzHandler.cpp +++ b/CPP/7zip/Archive/XzHandler.cpp | |||
@@ -1089,7 +1089,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
1089 | 1089 | ||
1090 | STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) | 1090 | STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) |
1091 | { | 1091 | { |
1092 | *timeType = NFileTimeType::kUnix; | 1092 | *timeType = GET_FileTimeType_NotDefined_for_GetFileTimeType; |
1093 | // *timeType = NFileTimeType::kUnix; | ||
1093 | return S_OK; | 1094 | return S_OK; |
1094 | } | 1095 | } |
1095 | 1096 | ||
@@ -1136,7 +1137,6 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
1136 | if (prop.vt != VT_UI8) | 1137 | if (prop.vt != VT_UI8) |
1137 | return E_INVALIDARG; | 1138 | return E_INVALIDARG; |
1138 | dataSize = prop.uhVal.QuadPart; | 1139 | dataSize = prop.uhVal.QuadPart; |
1139 | RINOK(updateCallback->SetTotal(dataSize)); | ||
1140 | } | 1140 | } |
1141 | 1141 | ||
1142 | NCompress::NXz::CEncoder *encoderSpec = new NCompress::NXz::CEncoder; | 1142 | NCompress::NXz::CEncoder *encoderSpec = new NCompress::NXz::CEncoder; |
@@ -1266,15 +1266,28 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
1266 | } | 1266 | } |
1267 | } | 1267 | } |
1268 | 1268 | ||
1269 | CMyComPtr<ISequentialInStream> fileInStream; | 1269 | { |
1270 | RINOK(updateCallback->GetStream(0, &fileInStream)); | 1270 | CMyComPtr<ISequentialInStream> fileInStream; |
1271 | 1271 | RINOK(updateCallback->GetStream(0, &fileInStream)); | |
1272 | CLocalProgress *lps = new CLocalProgress; | 1272 | if (!fileInStream) |
1273 | CMyComPtr<ICompressProgressInfo> progress = lps; | 1273 | return S_FALSE; |
1274 | lps->Init(updateCallback, true); | 1274 | { |
1275 | 1275 | CMyComPtr<IStreamGetSize> streamGetSize; | |
1276 | RINOK(encoderSpec->Code(fileInStream, outStream, NULL, NULL, progress)); | 1276 | fileInStream.QueryInterface(IID_IStreamGetSize, &streamGetSize); |
1277 | 1277 | if (streamGetSize) | |
1278 | { | ||
1279 | UInt64 size; | ||
1280 | if (streamGetSize->GetSize(&size) == S_OK) | ||
1281 | dataSize = size; | ||
1282 | } | ||
1283 | } | ||
1284 | RINOK(updateCallback->SetTotal(dataSize)); | ||
1285 | CLocalProgress *lps = new CLocalProgress; | ||
1286 | CMyComPtr<ICompressProgressInfo> progress = lps; | ||
1287 | lps->Init(updateCallback, true); | ||
1288 | RINOK(encoderSpec->Code(fileInStream, outStream, NULL, NULL, progress)); | ||
1289 | } | ||
1290 | |||
1278 | return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); | 1291 | return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); |
1279 | } | 1292 | } |
1280 | 1293 | ||
@@ -1415,9 +1428,9 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR | |||
1415 | 1428 | ||
1416 | REGISTER_ARC_IO( | 1429 | REGISTER_ARC_IO( |
1417 | "xz", "xz txz", "* .tar", 0xC, | 1430 | "xz", "xz txz", "* .tar", 0xC, |
1418 | XZ_SIG, | 1431 | XZ_SIG, 0 |
1419 | 0, | 1432 | , NArcInfoFlags::kKeepName |
1420 | NArcInfoFlags::kKeepName, | 1433 | , 0 |
1421 | NULL) | 1434 | , NULL) |
1422 | 1435 | ||
1423 | }} | 1436 | }} |
diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp index d8168bb..1b3985f 100644 --- a/CPP/7zip/Archive/Zip/ZipHandler.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp | |||
@@ -190,6 +190,8 @@ static const Byte kProps[] = | |||
190 | kpidVolumeIndex, | 190 | kpidVolumeIndex, |
191 | kpidOffset | 191 | kpidOffset |
192 | // kpidIsAltStream | 192 | // kpidIsAltStream |
193 | // , kpidChangeTime // for debug | ||
194 | // , 255 // for debug | ||
193 | }; | 195 | }; |
194 | 196 | ||
195 | static const Byte kArcProps[] = | 197 | static const Byte kArcProps[] = |
@@ -347,6 +349,34 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) | |||
347 | return S_OK; | 349 | return S_OK; |
348 | } | 350 | } |
349 | 351 | ||
352 | |||
353 | static bool NtfsUnixTimeToProp(bool fromCentral, | ||
354 | const CExtraBlock &extra, | ||
355 | unsigned ntfsIndex, unsigned unixIndex, NWindows::NCOM::CPropVariant &prop) | ||
356 | { | ||
357 | { | ||
358 | FILETIME ft; | ||
359 | if (extra.GetNtfsTime(ntfsIndex, ft)) | ||
360 | { | ||
361 | PropVariant_SetFrom_NtfsTime(prop, ft); | ||
362 | return true; | ||
363 | } | ||
364 | } | ||
365 | { | ||
366 | UInt32 unixTime = 0; | ||
367 | if (!extra.GetUnixTime(fromCentral, unixIndex, unixTime)) | ||
368 | return false; | ||
369 | /* | ||
370 | // we allow unixTime == 0 | ||
371 | if (unixTime == 0) | ||
372 | return false; | ||
373 | */ | ||
374 | PropVariant_SetFrom_UnixTime(prop, unixTime); | ||
375 | return true; | ||
376 | } | ||
377 | } | ||
378 | |||
379 | |||
350 | STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) | 380 | STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) |
351 | { | 381 | { |
352 | COM_TRY_BEGIN | 382 | COM_TRY_BEGIN |
@@ -392,6 +422,30 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
392 | 422 | ||
393 | case kpidPackSize: prop = item.PackSize; break; | 423 | case kpidPackSize: prop = item.PackSize; break; |
394 | 424 | ||
425 | case kpidCTime: | ||
426 | NtfsUnixTimeToProp(item.FromCentral, extra, | ||
427 | NFileHeader::NNtfsExtra::kCTime, | ||
428 | NFileHeader::NUnixTime::kCTime, prop); | ||
429 | break; | ||
430 | |||
431 | case kpidATime: | ||
432 | NtfsUnixTimeToProp(item.FromCentral, extra, | ||
433 | NFileHeader::NNtfsExtra::kATime, | ||
434 | NFileHeader::NUnixTime::kATime, prop); | ||
435 | break; | ||
436 | |||
437 | case kpidMTime: | ||
438 | { | ||
439 | if (!NtfsUnixTimeToProp(item.FromCentral, extra, | ||
440 | NFileHeader::NNtfsExtra::kMTime, | ||
441 | NFileHeader::NUnixTime::kMTime, prop)) | ||
442 | { | ||
443 | if (item.Time != 0) | ||
444 | PropVariant_SetFrom_DosTime(prop, item.Time); | ||
445 | } | ||
446 | break; | ||
447 | } | ||
448 | |||
395 | case kpidTimeType: | 449 | case kpidTimeType: |
396 | { | 450 | { |
397 | FILETIME ft; | 451 | FILETIME ft; |
@@ -399,7 +453,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
399 | UInt32 type; | 453 | UInt32 type; |
400 | if (extra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, ft)) | 454 | if (extra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, ft)) |
401 | type = NFileTimeType::kWindows; | 455 | type = NFileTimeType::kWindows; |
402 | else if (extra.GetUnixTime(true, NFileHeader::NUnixTime::kMTime, unixTime)) | 456 | else if (extra.GetUnixTime(item.FromCentral, NFileHeader::NUnixTime::kMTime, unixTime)) |
403 | type = NFileTimeType::kUnix; | 457 | type = NFileTimeType::kUnix; |
404 | else | 458 | else |
405 | type = NFileTimeType::kDOS; | 459 | type = NFileTimeType::kDOS; |
@@ -407,64 +461,28 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
407 | break; | 461 | break; |
408 | } | 462 | } |
409 | 463 | ||
410 | case kpidCTime: | 464 | /* |
411 | { | 465 | // for debug to get Dos time values: |
412 | FILETIME utc; | 466 | case kpidChangeTime: if (item.Time != 0) PropVariant_SetFrom_DosTime(prop, item.Time); break; |
413 | bool defined = true; | 467 | // for debug |
414 | if (!extra.GetNtfsTime(NFileHeader::NNtfsExtra::kCTime, utc)) | 468 | // time difference (dos - utc) |
415 | { | 469 | case 255: |
416 | UInt32 unixTime = 0; | ||
417 | if (extra.GetUnixTime(true, NFileHeader::NUnixTime::kCTime, unixTime)) | ||
418 | NTime::UnixTimeToFileTime(unixTime, utc); | ||
419 | else | ||
420 | defined = false; | ||
421 | } | ||
422 | if (defined) | ||
423 | prop = utc; | ||
424 | break; | ||
425 | } | ||
426 | |||
427 | case kpidATime: | ||
428 | { | ||
429 | FILETIME utc; | ||
430 | bool defined = true; | ||
431 | if (!extra.GetNtfsTime(NFileHeader::NNtfsExtra::kATime, utc)) | ||
432 | { | ||
433 | UInt32 unixTime = 0; | ||
434 | if (extra.GetUnixTime(true, NFileHeader::NUnixTime::kATime, unixTime)) | ||
435 | NTime::UnixTimeToFileTime(unixTime, utc); | ||
436 | else | ||
437 | defined = false; | ||
438 | } | ||
439 | if (defined) | ||
440 | prop = utc; | ||
441 | |||
442 | break; | ||
443 | } | ||
444 | |||
445 | case kpidMTime: | ||
446 | { | 470 | { |
447 | FILETIME utc; | 471 | if (NtfsUnixTimeToProp(item.FromCentral, extra, |
448 | bool defined = true; | 472 | NFileHeader::NNtfsExtra::kMTime, |
449 | if (!extra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, utc)) | 473 | NFileHeader::NUnixTime::kMTime, prop)) |
450 | { | 474 | { |
451 | UInt32 unixTime = 0; | 475 | FILETIME localFileTime; |
452 | if (extra.GetUnixTime(true, NFileHeader::NUnixTime::kMTime, unixTime)) | 476 | if (item.Time != 0 && NTime::DosTime_To_FileTime(item.Time, localFileTime)) |
453 | NTime::UnixTimeToFileTime(unixTime, utc); | ||
454 | else | ||
455 | { | 477 | { |
456 | FILETIME localFileTime; | 478 | UInt64 t1 = FILETIME_To_UInt64(prop.filetime); |
457 | if (item.Time == 0) | 479 | UInt64 t2 = FILETIME_To_UInt64(localFileTime); |
458 | defined = false; | 480 | prop.Set_Int64(t2 - t1); |
459 | else if (!NTime::DosTimeToFileTime(item.Time, localFileTime) || | ||
460 | !LocalFileTimeToFileTime(&localFileTime, &utc)) | ||
461 | utc.dwHighDateTime = utc.dwLowDateTime = 0; | ||
462 | } | 481 | } |
463 | } | 482 | } |
464 | if (defined) | ||
465 | prop = utc; | ||
466 | break; | 483 | break; |
467 | } | 484 | } |
485 | */ | ||
468 | 486 | ||
469 | case kpidAttrib: prop = item.GetWinAttrib(); break; | 487 | case kpidAttrib: prop = item.GetWinAttrib(); break; |
470 | 488 | ||
@@ -1122,7 +1140,18 @@ HRESULT CZipDecoder::Decode( | |||
1122 | AString_Wipe charPassword; | 1140 | AString_Wipe charPassword; |
1123 | if (password) | 1141 | if (password) |
1124 | { | 1142 | { |
1125 | UnicodeStringToMultiByte2(charPassword, (LPCOLESTR)password, CP_ACP); | 1143 | /* |
1144 | // 22.00: do we need UTF-8 passwords here ? | ||
1145 | if (item.IsUtf8()) // 22.00 | ||
1146 | { | ||
1147 | // throw 1; | ||
1148 | ConvertUnicodeToUTF8((LPCOLESTR)password, charPassword); | ||
1149 | } | ||
1150 | else | ||
1151 | */ | ||
1152 | { | ||
1153 | UnicodeStringToMultiByte2(charPassword, (LPCOLESTR)password, CP_ACP); | ||
1154 | } | ||
1126 | /* | 1155 | /* |
1127 | if (wzAesMode || pkAesMode) | 1156 | if (wzAesMode || pkAesMode) |
1128 | { | 1157 | { |
@@ -1341,6 +1370,8 @@ HRESULT CZipDecoder::Decode( | |||
1341 | 1370 | ||
1342 | if (id == NFileHeader::NCompressionMethod::kStore && item.IsEncrypted()) | 1371 | if (id == NFileHeader::NCompressionMethod::kStore && item.IsEncrypted()) |
1343 | { | 1372 | { |
1373 | // for debug : we can disable this code (kStore + 50), if we want to test CopyCoder+Filter | ||
1374 | // here we use filter without CopyCoder | ||
1344 | readFromFilter = false; | 1375 | readFromFilter = false; |
1345 | 1376 | ||
1346 | COutStreamWithPadPKCS7 *padStreamSpec = NULL; | 1377 | COutStreamWithPadPKCS7 *padStreamSpec = NULL; |
@@ -1425,33 +1456,44 @@ HRESULT CZipDecoder::Decode( | |||
1425 | const UInt32 padSize = _pkAesDecoderSpec->GetPadSize((UInt32)processed); | 1456 | const UInt32 padSize = _pkAesDecoderSpec->GetPadSize((UInt32)processed); |
1426 | if (processed + padSize > coderPackSize) | 1457 | if (processed + padSize > coderPackSize) |
1427 | truncatedError = true; | 1458 | truncatedError = true; |
1459 | else if (processed + padSize < coderPackSize) | ||
1460 | dataAfterEnd = true; | ||
1428 | else | 1461 | else |
1429 | { | 1462 | { |
1430 | if (processed + padSize < coderPackSize) | ||
1431 | dataAfterEnd = true; | ||
1432 | else | ||
1433 | { | 1463 | { |
1434 | // here we can PKCS7 padding data from reminder (it can be inside stream buffer in coder). | 1464 | // here we check PKCS7 padding data from reminder (it can be inside stream buffer in coder). |
1435 | CMyComPtr<ICompressReadUnusedFromInBuf> readInStream; | 1465 | CMyComPtr<ICompressReadUnusedFromInBuf> readInStream; |
1436 | coder->QueryInterface(IID_ICompressReadUnusedFromInBuf, (void **)&readInStream); | 1466 | coder->QueryInterface(IID_ICompressReadUnusedFromInBuf, (void **)&readInStream); |
1437 | if (readInStream) | 1467 | // CCopyCoder() for kStore doesn't read data outside of (item.Size) |
1468 | if (readInStream || id == NFileHeader::NCompressionMethod::kStore) | ||
1438 | { | 1469 | { |
1439 | // change pad size, it we support another block size in ZipStron | 1470 | // change pad size, if we support another block size in ZipStrong. |
1440 | // here we request more to detect error with data after end. | 1471 | // here we request more data to detect error with data after end. |
1441 | const UInt32 kBufSize = NCrypto::NZipStrong::kAesPadAllign + 16; | 1472 | const UInt32 kBufSize = NCrypto::NZipStrong::kAesPadAllign + 16; |
1442 | Byte buf[kBufSize]; | 1473 | Byte buf[kBufSize]; |
1443 | UInt32 processedSize; | 1474 | UInt32 processedSize = 0; |
1444 | RINOK(readInStream->ReadUnusedFromInBuf(buf, kBufSize, &processedSize)); | 1475 | if (readInStream) |
1476 | { | ||
1477 | RINOK(readInStream->ReadUnusedFromInBuf(buf, kBufSize, &processedSize)); | ||
1478 | } | ||
1445 | if (processedSize > padSize) | 1479 | if (processedSize > padSize) |
1446 | dataAfterEnd = true; | 1480 | dataAfterEnd = true; |
1447 | else | 1481 | else |
1448 | { | 1482 | { |
1449 | if (ReadStream_FALSE(filterStream, buf + processedSize, padSize - processedSize) != S_OK) | 1483 | size_t processedSize2 = kBufSize - processedSize; |
1450 | padError = true; | 1484 | result = ReadStream(filterStream, buf + processedSize, &processedSize2); |
1451 | else | 1485 | if (result == S_OK) |
1452 | for (unsigned i = 0; i < padSize; i++) | 1486 | { |
1453 | if (buf[i] != padSize) | 1487 | processedSize2 += processedSize; |
1454 | padError = true; | 1488 | if (processedSize2 > padSize) |
1489 | dataAfterEnd = true; | ||
1490 | else if (processedSize2 < padSize) | ||
1491 | truncatedError = true; | ||
1492 | else | ||
1493 | for (unsigned i = 0; i < padSize; i++) | ||
1494 | if (buf[i] != padSize) | ||
1495 | padError = true; | ||
1496 | } | ||
1455 | } | 1497 | } |
1456 | } | 1498 | } |
1457 | } | 1499 | } |
diff --git a/CPP/7zip/Archive/Zip/ZipHandler.h b/CPP/7zip/Archive/Zip/ZipHandler.h index 3043e41..a70a1a7 100644 --- a/CPP/7zip/Archive/Zip/ZipHandler.h +++ b/CPP/7zip/Archive/Zip/ZipHandler.h | |||
@@ -57,7 +57,9 @@ private: | |||
57 | 57 | ||
58 | int m_MainMethod; | 58 | int m_MainMethod; |
59 | bool m_ForceAesMode; | 59 | bool m_ForceAesMode; |
60 | bool m_WriteNtfsTimeExtra; | 60 | |
61 | CHandlerTimeOptions TimeOptions; | ||
62 | |||
61 | bool _removeSfxBlock; | 63 | bool _removeSfxBlock; |
62 | bool m_ForceLocal; | 64 | bool m_ForceLocal; |
63 | bool m_ForceUtf8; | 65 | bool m_ForceUtf8; |
@@ -71,7 +73,8 @@ private: | |||
71 | _props.Init(); | 73 | _props.Init(); |
72 | m_MainMethod = -1; | 74 | m_MainMethod = -1; |
73 | m_ForceAesMode = false; | 75 | m_ForceAesMode = false; |
74 | m_WriteNtfsTimeExtra = true; | 76 | TimeOptions.Init(); |
77 | TimeOptions.Prec = k_PropVar_TimePrec_0; | ||
75 | _removeSfxBlock = false; | 78 | _removeSfxBlock = false; |
76 | m_ForceLocal = false; | 79 | m_ForceLocal = false; |
77 | m_ForceUtf8 = false; | 80 | m_ForceUtf8 = false; |
diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp index a9b3eae..77a71df 100644 --- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp | |||
@@ -30,7 +30,7 @@ namespace NZip { | |||
30 | 30 | ||
31 | STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) | 31 | STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) |
32 | { | 32 | { |
33 | *timeType = NFileTimeType::kDOS; | 33 | *timeType = TimeOptions.Prec; |
34 | return S_OK; | 34 | return S_OK; |
35 | } | 35 | } |
36 | 36 | ||
@@ -207,27 +207,58 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
207 | } | 207 | } |
208 | */ | 208 | */ |
209 | 209 | ||
210 | // 22.00 : kpidTimeType is useless here : the code was disabled | ||
211 | /* | ||
210 | { | 212 | { |
211 | CPropVariant prop; | 213 | CPropVariant prop; |
212 | RINOK(callback->GetProperty(i, kpidTimeType, &prop)); | 214 | RINOK(callback->GetProperty(i, kpidTimeType, &prop)); |
213 | if (prop.vt == VT_UI4) | 215 | if (prop.vt == VT_UI4) |
214 | ui.NtfsTimeIsDefined = (prop.ulVal == NFileTimeType::kWindows); | 216 | ui.NtfsTime_IsDefined = (prop.ulVal == NFileTimeType::kWindows); |
215 | else | 217 | else |
216 | ui.NtfsTimeIsDefined = m_WriteNtfsTimeExtra; | 218 | ui.NtfsTime_IsDefined = _Write_NtfsTime; |
217 | } | 219 | } |
218 | RINOK(GetTime(callback, i, kpidMTime, ui.Ntfs_MTime)); | 220 | */ |
219 | RINOK(GetTime(callback, i, kpidATime, ui.Ntfs_ATime)); | 221 | |
220 | RINOK(GetTime(callback, i, kpidCTime, ui.Ntfs_CTime)); | 222 | if (TimeOptions.Write_MTime.Val) RINOK (GetTime (callback, i, kpidMTime, ui.Ntfs_MTime)); |
223 | if (TimeOptions.Write_ATime.Val) RINOK (GetTime (callback, i, kpidATime, ui.Ntfs_ATime)); | ||
224 | if (TimeOptions.Write_CTime.Val) RINOK (GetTime (callback, i, kpidCTime, ui.Ntfs_CTime)); | ||
221 | 225 | ||
226 | if (TimeOptions.Prec != k_PropVar_TimePrec_DOS) | ||
222 | { | 227 | { |
223 | FILETIME localFileTime = { 0, 0 }; | 228 | if (TimeOptions.Prec == k_PropVar_TimePrec_Unix || |
224 | if (ui.Ntfs_MTime.dwHighDateTime != 0 || | 229 | TimeOptions.Prec == k_PropVar_TimePrec_Base) |
225 | ui.Ntfs_MTime.dwLowDateTime != 0) | 230 | ui.Write_UnixTime = ! FILETIME_IsZero (ui.Ntfs_MTime); |
226 | if (!FileTimeToLocalFileTime(&ui.Ntfs_MTime, &localFileTime)) | 231 | else |
227 | return E_INVALIDARG; | 232 | { |
228 | FileTimeToDosTime(localFileTime, ui.Time); | 233 | /* |
234 | // if we want to store zero timestamps as zero timestamp, use the following: | ||
235 | ui.Write_NtfsTime = | ||
236 | _Write_MTime || | ||
237 | _Write_ATime || | ||
238 | _Write_CTime; | ||
239 | */ | ||
240 | |||
241 | // We treat zero timestamp as no timestamp | ||
242 | ui.Write_NtfsTime = | ||
243 | ! FILETIME_IsZero (ui.Ntfs_MTime) || | ||
244 | ! FILETIME_IsZero (ui.Ntfs_ATime) || | ||
245 | ! FILETIME_IsZero (ui.Ntfs_CTime); | ||
246 | } | ||
229 | } | 247 | } |
230 | 248 | ||
249 | /* | ||
250 | how 0 in dos time works: | ||
251 | win10 explorer extract : some random date 1601-04-25. | ||
252 | winrar 6.10 : write time. | ||
253 | 7zip : MTime of archive is used | ||
254 | how 0 in tar works: | ||
255 | winrar 6.10 : 1970 | ||
256 | 0 in dos field can show that there is no timestamp. | ||
257 | we write correct 1970-01-01 in dos field, to support correct extraction in Win10. | ||
258 | */ | ||
259 | |||
260 | UtcFileTime_To_LocalDosTime(ui.Ntfs_MTime, ui.Time); | ||
261 | |||
231 | NItemName::ReplaceSlashes_OsToUnix(name); | 262 | NItemName::ReplaceSlashes_OsToUnix(name); |
232 | 263 | ||
233 | bool needSlash = ui.IsDir; | 264 | bool needSlash = ui.IsDir; |
@@ -441,11 +472,21 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
441 | if (mainMethod != NFileHeader::NCompressionMethod::kStore) | 472 | if (mainMethod != NFileHeader::NCompressionMethod::kStore) |
442 | options.MethodSequence.Add(NFileHeader::NCompressionMethod::kStore); | 473 | options.MethodSequence.Add(NFileHeader::NCompressionMethod::kStore); |
443 | 474 | ||
475 | CUpdateOptions uo; | ||
476 | uo.Write_MTime = TimeOptions.Write_MTime.Val; | ||
477 | uo.Write_ATime = TimeOptions.Write_ATime.Val; | ||
478 | uo.Write_CTime = TimeOptions.Write_CTime.Val; | ||
479 | /* | ||
480 | uo.Write_NtfsTime = _Write_NtfsTime && | ||
481 | (_Write_MTime || _Write_ATime || _Write_CTime); | ||
482 | uo.Write_UnixTime = _Write_UnixTime; | ||
483 | */ | ||
484 | |||
444 | return Update( | 485 | return Update( |
445 | EXTERNAL_CODECS_VARS | 486 | EXTERNAL_CODECS_VARS |
446 | m_Items, updateItems, outStream, | 487 | m_Items, updateItems, outStream, |
447 | m_Archive.IsOpen() ? &m_Archive : NULL, _removeSfxBlock, | 488 | m_Archive.IsOpen() ? &m_Archive : NULL, _removeSfxBlock, |
448 | options, callback); | 489 | uo, options, callback); |
449 | 490 | ||
450 | COM_TRY_END2 | 491 | COM_TRY_END2 |
451 | } | 492 | } |
@@ -494,10 +535,9 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR | |||
494 | return E_INVALIDARG; | 535 | return E_INVALIDARG; |
495 | } | 536 | } |
496 | } | 537 | } |
497 | else if (name.IsEqualTo("tc")) | 538 | |
498 | { | 539 | |
499 | RINOK(PROPVARIANT_to_bool(prop, m_WriteNtfsTimeExtra)); | 540 | |
500 | } | ||
501 | else if (name.IsEqualTo("cl")) | 541 | else if (name.IsEqualTo("cl")) |
502 | { | 542 | { |
503 | RINOK(PROPVARIANT_to_bool(prop, m_ForceLocal)); | 543 | RINOK(PROPVARIANT_to_bool(prop, m_ForceLocal)); |
@@ -532,7 +572,12 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR | |||
532 | } | 572 | } |
533 | else | 573 | else |
534 | { | 574 | { |
535 | RINOK(_props.SetProperty(name, prop)); | 575 | bool processed = false; |
576 | RINOK(TimeOptions.Parse(name, prop, processed)); | ||
577 | if (!processed) | ||
578 | { | ||
579 | RINOK(_props.SetProperty(name, prop)); | ||
580 | } | ||
536 | } | 581 | } |
537 | // RINOK(_props.MethodInfo.ParseParamsFromPROPVARIANT(name, prop)); | 582 | // RINOK(_props.MethodInfo.ParseParamsFromPROPVARIANT(name, prop)); |
538 | } | 583 | } |
diff --git a/CPP/7zip/Archive/Zip/ZipHeader.h b/CPP/7zip/Archive/Zip/ZipHeader.h index c47659a..34fa359 100644 --- a/CPP/7zip/Archive/Zip/ZipHeader.h +++ b/CPP/7zip/Archive/Zip/ZipHeader.h | |||
@@ -88,14 +88,15 @@ namespace NFileHeader | |||
88 | { | 88 | { |
89 | kZip64 = 0x01, | 89 | kZip64 = 0x01, |
90 | kNTFS = 0x0A, | 90 | kNTFS = 0x0A, |
91 | kUnix0 = 0x0D, // Info-ZIP : (UNIX) PK | ||
91 | kStrongEncrypt = 0x17, | 92 | kStrongEncrypt = 0x17, |
92 | kIzNtSecurityDescriptor = 0x4453, | 93 | kIzNtSecurityDescriptor = 0x4453, |
93 | kUnixTime = 0x5455, | 94 | kUnixTime = 0x5455, // "UT" (time) Info-ZIP |
94 | kUnixExtra = 0x5855, | 95 | kUnix1 = 0x5855, // Info-ZIP |
95 | kIzUnicodeComment = 0x6375, | 96 | kIzUnicodeComment = 0x6375, |
96 | kIzUnicodeName = 0x7075, | 97 | kIzUnicodeName = 0x7075, |
97 | kUnix2Extra = 0x7855, | 98 | kUnix2 = 0x7855, // Info-ZIP |
98 | kUnix3Extra = 0x7875, | 99 | kUnixN = 0x7875, // Info-ZIP |
99 | kWzAES = 0x9901, | 100 | kWzAES = 0x9901, |
100 | kApkAlign = 0xD935 | 101 | kApkAlign = 0xD935 |
101 | }; | 102 | }; |
diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp index 076d6bb..f2b69a9 100644 --- a/CPP/7zip/Archive/Zip/ZipIn.cpp +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp | |||
@@ -1045,9 +1045,24 @@ bool CInArchive::ReadExtra(const CLocalItem &item, unsigned extraSize, CExtraBlo | |||
1045 | 1045 | ||
1046 | if (cdItem) | 1046 | if (cdItem) |
1047 | { | 1047 | { |
1048 | if (isOK && ZIP64_IS_32_MAX(cdItem->LocalHeaderPos)) | 1048 | if (isOK) |
1049 | { if (size < 8) isOK = false; else { size -= 8; cdItem->LocalHeaderPos = ReadUInt64(); }} | 1049 | { |
1050 | 1050 | if (ZIP64_IS_32_MAX(cdItem->LocalHeaderPos)) | |
1051 | { if (size < 8) isOK = false; else { size -= 8; cdItem->LocalHeaderPos = ReadUInt64(); }} | ||
1052 | /* | ||
1053 | else if (size == 8) | ||
1054 | { | ||
1055 | size -= 8; | ||
1056 | const UInt64 v = ReadUInt64(); | ||
1057 | // soong_zip, an AOSP tool (written in the Go) writes incorrect value. | ||
1058 | // we can ignore that minor error here | ||
1059 | if (v != cdItem->LocalHeaderPos) | ||
1060 | isOK = false; // ignore error | ||
1061 | // isOK = false; // force error | ||
1062 | } | ||
1063 | */ | ||
1064 | } | ||
1065 | |||
1051 | if (isOK && ZIP64_IS_16_MAX(cdItem->Disk)) | 1066 | if (isOK && ZIP64_IS_16_MAX(cdItem->Disk)) |
1052 | { if (size < 4) isOK = false; else { size -= 4; cdItem->Disk = ReadUInt32(); }} | 1067 | { if (size < 4) isOK = false; else { size -= 4; cdItem->Disk = ReadUInt32(); }} |
1053 | } | 1068 | } |
@@ -1926,7 +1941,7 @@ static int FindItem(const CObjectVector<CItemEx> &items, const CItemEx &item) | |||
1926 | { | 1941 | { |
1927 | if (left >= right) | 1942 | if (left >= right) |
1928 | return -1; | 1943 | return -1; |
1929 | const unsigned index = (left + right) / 2; | 1944 | const unsigned index = (unsigned)(((size_t)left + (size_t)right) / 2); |
1930 | const CItemEx &item2 = items[index]; | 1945 | const CItemEx &item2 = items[index]; |
1931 | if (item.Disk < item2.Disk) | 1946 | if (item.Disk < item2.Disk) |
1932 | right = index; | 1947 | right = index; |
diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp index be33648..cffbb78 100644 --- a/CPP/7zip/Archive/Zip/ZipItem.cpp +++ b/CPP/7zip/Archive/Zip/ZipItem.cpp | |||
@@ -30,11 +30,12 @@ static const CUInt32PCharPair g_ExtraTypes[] = | |||
30 | { | 30 | { |
31 | { NExtraID::kZip64, "Zip64" }, | 31 | { NExtraID::kZip64, "Zip64" }, |
32 | { NExtraID::kNTFS, "NTFS" }, | 32 | { NExtraID::kNTFS, "NTFS" }, |
33 | { NExtraID::kUnix0, "UNIX" }, | ||
33 | { NExtraID::kStrongEncrypt, "StrongCrypto" }, | 34 | { NExtraID::kStrongEncrypt, "StrongCrypto" }, |
34 | { NExtraID::kUnixTime, "UT" }, | 35 | { NExtraID::kUnixTime, "UT" }, |
35 | { NExtraID::kUnixExtra, "UX" }, | 36 | { NExtraID::kUnix1, "UX" }, |
36 | { NExtraID::kUnix2Extra, "Ux" }, | 37 | { NExtraID::kUnix2, "Ux" }, |
37 | { NExtraID::kUnix3Extra, "ux" }, | 38 | { NExtraID::kUnixN, "ux" }, |
38 | { NExtraID::kIzUnicodeComment, "uc" }, | 39 | { NExtraID::kIzUnicodeComment, "uc" }, |
39 | { NExtraID::kIzUnicodeName, "up" }, | 40 | { NExtraID::kIzUnicodeName, "up" }, |
40 | { NExtraID::kIzNtSecurityDescriptor, "SD" }, | 41 | { NExtraID::kIzNtSecurityDescriptor, "SD" }, |
@@ -50,6 +51,23 @@ void CExtraSubBlock::PrintInfo(AString &s) const | |||
50 | if (pair.Value == ID) | 51 | if (pair.Value == ID) |
51 | { | 52 | { |
52 | s += pair.Name; | 53 | s += pair.Name; |
54 | if (ID == NExtraID::kUnixTime) | ||
55 | { | ||
56 | if (Data.Size() >= 1) | ||
57 | { | ||
58 | s += ':'; | ||
59 | const Byte flags = Data[0]; | ||
60 | if (flags & 1) s += 'M'; | ||
61 | if (flags & 2) s += 'A'; | ||
62 | if (flags & 4) s += 'C'; | ||
63 | const UInt32 size = (UInt32)(Data.Size()) - 1; | ||
64 | if (size % 4 == 0) | ||
65 | { | ||
66 | s += ':'; | ||
67 | s.Add_UInt32(size / 4); | ||
68 | } | ||
69 | } | ||
70 | } | ||
53 | /* | 71 | /* |
54 | if (ID == NExtraID::kApkAlign && Data.Size() >= 2) | 72 | if (ID == NExtraID::kApkAlign && Data.Size() >= 2) |
55 | { | 73 | { |
@@ -133,14 +151,22 @@ bool CExtraSubBlock::ExtractNtfsTime(unsigned index, FILETIME &ft) const | |||
133 | return false; | 151 | return false; |
134 | } | 152 | } |
135 | 153 | ||
136 | bool CExtraSubBlock::ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res) const | 154 | bool CExtraSubBlock::Extract_UnixTime(bool isCentral, unsigned index, UInt32 &res) const |
137 | { | 155 | { |
156 | /* Info-Zip : | ||
157 | The central-header extra field contains the modification | ||
158 | time only, or no timestamp at all. | ||
159 | Size of Data is used to flag its presence or absence | ||
160 | If "Flags" indicates that Modtime is present in the local header | ||
161 | field, it MUST be present in the central header field, too | ||
162 | */ | ||
163 | |||
138 | res = 0; | 164 | res = 0; |
139 | UInt32 size = (UInt32)Data.Size(); | 165 | UInt32 size = (UInt32)Data.Size(); |
140 | if (ID != NExtraID::kUnixTime || size < 5) | 166 | if (ID != NExtraID::kUnixTime || size < 5) |
141 | return false; | 167 | return false; |
142 | const Byte *p = (const Byte *)Data; | 168 | const Byte *p = (const Byte *)Data; |
143 | Byte flags = *p++; | 169 | const Byte flags = *p++; |
144 | size--; | 170 | size--; |
145 | if (isCentral) | 171 | if (isCentral) |
146 | { | 172 | { |
@@ -168,18 +194,35 @@ bool CExtraSubBlock::ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res | |||
168 | } | 194 | } |
169 | 195 | ||
170 | 196 | ||
171 | bool CExtraSubBlock::ExtractUnixExtraTime(unsigned index, UInt32 &res) const | 197 | // Info-ZIP's abandoned "Unix1 timestamps & owner ID info" |
198 | |||
199 | bool CExtraSubBlock::Extract_Unix01_Time(unsigned index, UInt32 &res) const | ||
172 | { | 200 | { |
173 | res = 0; | 201 | res = 0; |
174 | const size_t size = Data.Size(); | 202 | const unsigned offset = index * 4; |
175 | unsigned offset = index * 4; | 203 | if (Data.Size() < offset + 4) |
176 | if (ID != NExtraID::kUnixExtra || size < offset + 4) | 204 | return false; |
205 | if (ID != NExtraID::kUnix0 && | ||
206 | ID != NExtraID::kUnix1) | ||
177 | return false; | 207 | return false; |
178 | const Byte *p = (const Byte *)Data + offset; | 208 | const Byte *p = (const Byte *)Data + offset; |
179 | res = GetUi32(p); | 209 | res = GetUi32(p); |
180 | return true; | 210 | return true; |
181 | } | 211 | } |
182 | 212 | ||
213 | /* | ||
214 | // PKWARE's Unix "extra" is similar to Info-ZIP's abandoned "Unix1 timestamps" | ||
215 | bool CExtraSubBlock::Extract_Unix_Time(unsigned index, UInt32 &res) const | ||
216 | { | ||
217 | res = 0; | ||
218 | const unsigned offset = index * 4; | ||
219 | if (ID != NExtraID::kUnix0 || Data.Size() < offset) | ||
220 | return false; | ||
221 | const Byte *p = (const Byte *)Data + offset; | ||
222 | res = GetUi32(p); | ||
223 | return true; | ||
224 | } | ||
225 | */ | ||
183 | 226 | ||
184 | bool CExtraBlock::GetNtfsTime(unsigned index, FILETIME &ft) const | 227 | bool CExtraBlock::GetNtfsTime(unsigned index, FILETIME &ft) const |
185 | { | 228 | { |
@@ -199,7 +242,7 @@ bool CExtraBlock::GetUnixTime(bool isCentral, unsigned index, UInt32 &res) const | |||
199 | { | 242 | { |
200 | const CExtraSubBlock &sb = SubBlocks[i]; | 243 | const CExtraSubBlock &sb = SubBlocks[i]; |
201 | if (sb.ID == NFileHeader::NExtraID::kUnixTime) | 244 | if (sb.ID == NFileHeader::NExtraID::kUnixTime) |
202 | return sb.ExtractUnixTime(isCentral, index, res); | 245 | return sb.Extract_UnixTime(isCentral, index, res); |
203 | } | 246 | } |
204 | } | 247 | } |
205 | 248 | ||
@@ -214,8 +257,9 @@ bool CExtraBlock::GetUnixTime(bool isCentral, unsigned index, UInt32 &res) const | |||
214 | FOR_VECTOR (i, SubBlocks) | 257 | FOR_VECTOR (i, SubBlocks) |
215 | { | 258 | { |
216 | const CExtraSubBlock &sb = SubBlocks[i]; | 259 | const CExtraSubBlock &sb = SubBlocks[i]; |
217 | if (sb.ID == NFileHeader::NExtraID::kUnixExtra) | 260 | if (sb.ID == NFileHeader::NExtraID::kUnix0 || |
218 | return sb.ExtractUnixExtraTime(index, res); | 261 | sb.ID == NFileHeader::NExtraID::kUnix1) |
262 | return sb.Extract_Unix01_Time(index, res); | ||
219 | } | 263 | } |
220 | } | 264 | } |
221 | return false; | 265 | return false; |
diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h index 6ee8765..934d7ec 100644 --- a/CPP/7zip/Archive/Zip/ZipItem.h +++ b/CPP/7zip/Archive/Zip/ZipItem.h | |||
@@ -31,8 +31,9 @@ struct CExtraSubBlock | |||
31 | CByteBuffer Data; | 31 | CByteBuffer Data; |
32 | 32 | ||
33 | bool ExtractNtfsTime(unsigned index, FILETIME &ft) const; | 33 | bool ExtractNtfsTime(unsigned index, FILETIME &ft) const; |
34 | bool ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res) const; | 34 | bool Extract_UnixTime(bool isCentral, unsigned index, UInt32 &res) const; |
35 | bool ExtractUnixExtraTime(unsigned index, UInt32 &res) const; | 35 | bool Extract_Unix01_Time(unsigned index, UInt32 &res) const; |
36 | // bool Extract_Unix_Time(unsigned index, UInt32 &res) const; | ||
36 | 37 | ||
37 | bool CheckIzUnicode(const AString &s) const; | 38 | bool CheckIzUnicode(const AString &s) const; |
38 | 39 | ||
diff --git a/CPP/7zip/Archive/Zip/ZipOut.cpp b/CPP/7zip/Archive/Zip/ZipOut.cpp index efed0a4..8f3f43b 100644 --- a/CPP/7zip/Archive/Zip/ZipOut.cpp +++ b/CPP/7zip/Archive/Zip/ZipOut.cpp | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | #include "../../../../C/7zCrc.h" | 5 | #include "../../../../C/7zCrc.h" |
6 | 6 | ||
7 | #include "../../../Windows/TimeUtils.h" | ||
7 | #include "../../Common/OffsetStream.h" | 8 | #include "../../Common/OffsetStream.h" |
8 | 9 | ||
9 | #include "ZipOut.h" | 10 | #include "ZipOut.h" |
@@ -110,6 +111,40 @@ void COutArchive::WriteUtfName(const CItemOut &item) | |||
110 | WriteBytes(item.Name_Utf, (UInt16)item.Name_Utf.Size()); | 111 | WriteBytes(item.Name_Utf, (UInt16)item.Name_Utf.Size()); |
111 | } | 112 | } |
112 | 113 | ||
114 | |||
115 | static const unsigned k_Ntfs_ExtraSize = 4 + 2 + 2 + (3 * 8); | ||
116 | static const unsigned k_UnixTime_ExtraSize = 1 + (1 * 4); | ||
117 | |||
118 | void COutArchive::WriteTimeExtra(const CItemOut &item, bool writeNtfs) | ||
119 | { | ||
120 | if (writeNtfs) | ||
121 | { | ||
122 | // windows explorer ignores that extra | ||
123 | Write16(NFileHeader::NExtraID::kNTFS); | ||
124 | Write16(k_Ntfs_ExtraSize); | ||
125 | Write32(0); // reserved | ||
126 | Write16(NFileHeader::NNtfsExtra::kTagTime); | ||
127 | Write16(8 * 3); | ||
128 | WriteNtfsTime(item.Ntfs_MTime); | ||
129 | WriteNtfsTime(item.Ntfs_ATime); | ||
130 | WriteNtfsTime(item.Ntfs_CTime); | ||
131 | } | ||
132 | |||
133 | if (item.Write_UnixTime) | ||
134 | { | ||
135 | // windows explorer ignores that extra | ||
136 | // by specification : should we write to local header also? | ||
137 | Write16(NFileHeader::NExtraID::kUnixTime); | ||
138 | Write16(k_UnixTime_ExtraSize); | ||
139 | const Byte flags = (Byte)((unsigned)1 << NFileHeader::NUnixTime::kMTime); | ||
140 | Write8(flags); | ||
141 | UInt32 unixTime; | ||
142 | NWindows::NTime::FileTime_To_UnixTime(item.Ntfs_MTime, unixTime); | ||
143 | Write32(unixTime); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | |||
113 | void COutArchive::WriteLocalHeader(CItemOut &item, bool needCheck) | 148 | void COutArchive::WriteLocalHeader(CItemOut &item, bool needCheck) |
114 | { | 149 | { |
115 | m_LocalHeaderPos = m_CurPos; | 150 | m_LocalHeaderPos = m_CurPos; |
@@ -122,8 +157,14 @@ void COutArchive::WriteLocalHeader(CItemOut &item, bool needCheck) | |||
122 | if (needCheck && m_IsZip64) | 157 | if (needCheck && m_IsZip64) |
123 | isZip64 = true; | 158 | isZip64 = true; |
124 | 159 | ||
160 | // Why don't we write NTFS timestamps to local header? | ||
161 | // Probably we want to reduce size of archive? | ||
162 | const bool writeNtfs = false; // do not write NTFS timestamp to local header | ||
163 | // const bool writeNtfs = item.Write_NtfsTime; // write NTFS time to local header | ||
125 | const UInt32 localExtraSize = (UInt32)( | 164 | const UInt32 localExtraSize = (UInt32)( |
126 | (isZip64 ? (4 + 8 + 8): 0) | 165 | (isZip64 ? (4 + 8 + 8): 0) |
166 | + (writeNtfs ? 4 + k_Ntfs_ExtraSize : 0) | ||
167 | + (item.Write_UnixTime ? 4 + k_UnixTime_ExtraSize : 0) | ||
127 | + item.Get_UtfName_ExtraSize() | 168 | + item.Get_UtfName_ExtraSize() |
128 | + item.LocalExtra.GetSize()); | 169 | + item.LocalExtra.GetSize()); |
129 | if ((UInt16)localExtraSize != localExtraSize) | 170 | if ((UInt16)localExtraSize != localExtraSize) |
@@ -168,13 +209,12 @@ void COutArchive::WriteLocalHeader(CItemOut &item, bool needCheck) | |||
168 | Write64(packSize); | 209 | Write64(packSize); |
169 | } | 210 | } |
170 | 211 | ||
212 | WriteTimeExtra(item, writeNtfs); | ||
213 | |||
171 | WriteUtfName(item); | 214 | WriteUtfName(item); |
172 | 215 | ||
173 | WriteExtra(item.LocalExtra); | 216 | WriteExtra(item.LocalExtra); |
174 | 217 | ||
175 | // Why don't we write NTFS timestamps to local header? | ||
176 | // Probably we want to reduce size of archive? | ||
177 | |||
178 | const UInt32 localFileHeaderSize = (UInt32)(m_CurPos - m_LocalHeaderPos); | 218 | const UInt32 localFileHeaderSize = (UInt32)(m_CurPos - m_LocalHeaderPos); |
179 | if (needCheck && m_LocalFileHeaderSize != localFileHeaderSize) | 219 | if (needCheck && m_LocalFileHeaderSize != localFileHeaderSize) |
180 | throw CSystemException(E_FAIL); | 220 | throw CSystemException(E_FAIL); |
@@ -231,10 +271,10 @@ void COutArchive::WriteDescriptor(const CItemOut &item) | |||
231 | 271 | ||
232 | void COutArchive::WriteCentralHeader(const CItemOut &item) | 272 | void COutArchive::WriteCentralHeader(const CItemOut &item) |
233 | { | 273 | { |
234 | bool isUnPack64 = DOES_NEED_ZIP64(item.Size); | 274 | const bool isUnPack64 = DOES_NEED_ZIP64(item.Size); |
235 | bool isPack64 = DOES_NEED_ZIP64(item.PackSize); | 275 | const bool isPack64 = DOES_NEED_ZIP64(item.PackSize); |
236 | bool isPosition64 = DOES_NEED_ZIP64(item.LocalHeaderPos); | 276 | const bool isPosition64 = DOES_NEED_ZIP64(item.LocalHeaderPos); |
237 | bool isZip64 = isPack64 || isUnPack64 || isPosition64; | 277 | const bool isZip64 = isPack64 || isUnPack64 || isPosition64; |
238 | 278 | ||
239 | Write32(NSignature::kCentralFileHeader); | 279 | Write32(NSignature::kCentralFileHeader); |
240 | Write8(item.MadeByVersion.Version); | 280 | Write8(item.MadeByVersion.Version); |
@@ -249,10 +289,11 @@ void COutArchive::WriteCentralHeader(const CItemOut &item) | |||
249 | Write16((UInt16)item.Name.Len()); | 289 | Write16((UInt16)item.Name.Len()); |
250 | 290 | ||
251 | const UInt16 zip64ExtraSize = (UInt16)((isUnPack64 ? 8: 0) + (isPack64 ? 8: 0) + (isPosition64 ? 8: 0)); | 291 | const UInt16 zip64ExtraSize = (UInt16)((isUnPack64 ? 8: 0) + (isPack64 ? 8: 0) + (isPosition64 ? 8: 0)); |
252 | const UInt16 kNtfsExtraSize = 4 + 2 + 2 + (3 * 8); | 292 | const bool writeNtfs = item.Write_NtfsTime; |
253 | const size_t centralExtraSize = | 293 | const size_t centralExtraSize = |
254 | (isZip64 ? 4 + zip64ExtraSize : 0) | 294 | (isZip64 ? 4 + zip64ExtraSize : 0) |
255 | + (item.NtfsTimeIsDefined ? 4 + kNtfsExtraSize : 0) | 295 | + (writeNtfs ? 4 + k_Ntfs_ExtraSize : 0) |
296 | + (item.Write_UnixTime ? 4 + k_UnixTime_ExtraSize : 0) | ||
256 | + item.Get_UtfName_ExtraSize() | 297 | + item.Get_UtfName_ExtraSize() |
257 | + item.CentralExtra.GetSize(); | 298 | + item.CentralExtra.GetSize(); |
258 | 299 | ||
@@ -283,18 +324,7 @@ void COutArchive::WriteCentralHeader(const CItemOut &item) | |||
283 | Write64(item.LocalHeaderPos); | 324 | Write64(item.LocalHeaderPos); |
284 | } | 325 | } |
285 | 326 | ||
286 | if (item.NtfsTimeIsDefined) | 327 | WriteTimeExtra(item, writeNtfs); |
287 | { | ||
288 | Write16(NFileHeader::NExtraID::kNTFS); | ||
289 | Write16(kNtfsExtraSize); | ||
290 | Write32(0); // reserved | ||
291 | Write16(NFileHeader::NNtfsExtra::kTagTime); | ||
292 | Write16(8 * 3); | ||
293 | WriteNtfsTime(item.Ntfs_MTime); | ||
294 | WriteNtfsTime(item.Ntfs_ATime); | ||
295 | WriteNtfsTime(item.Ntfs_CTime); | ||
296 | } | ||
297 | |||
298 | WriteUtfName(item); | 328 | WriteUtfName(item); |
299 | 329 | ||
300 | WriteExtra(item.CentralExtra); | 330 | WriteExtra(item.CentralExtra); |
@@ -304,15 +334,15 @@ void COutArchive::WriteCentralHeader(const CItemOut &item) | |||
304 | 334 | ||
305 | void COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const CByteBuffer *comment) | 335 | void COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const CByteBuffer *comment) |
306 | { | 336 | { |
307 | UInt64 cdOffset = GetCurPos(); | 337 | const UInt64 cdOffset = GetCurPos(); |
308 | FOR_VECTOR (i, items) | 338 | FOR_VECTOR (i, items) |
309 | WriteCentralHeader(items[i]); | 339 | WriteCentralHeader(items[i]); |
310 | UInt64 cd64EndOffset = GetCurPos(); | 340 | const UInt64 cd64EndOffset = GetCurPos(); |
311 | UInt64 cdSize = cd64EndOffset - cdOffset; | 341 | const UInt64 cdSize = cd64EndOffset - cdOffset; |
312 | bool cdOffset64 = DOES_NEED_ZIP64(cdOffset); | 342 | const bool cdOffset64 = DOES_NEED_ZIP64(cdOffset); |
313 | bool cdSize64 = DOES_NEED_ZIP64(cdSize); | 343 | const bool cdSize64 = DOES_NEED_ZIP64(cdSize); |
314 | bool items64 = items.Size() >= 0xFFFF; | 344 | const bool items64 = items.Size() >= 0xFFFF; |
315 | bool isZip64 = (cdOffset64 || cdSize64 || items64); | 345 | const bool isZip64 = (cdOffset64 || cdSize64 || items64); |
316 | 346 | ||
317 | // isZip64 = true; // to test Zip64 | 347 | // isZip64 = true; // to test Zip64 |
318 | 348 | ||
diff --git a/CPP/7zip/Archive/Zip/ZipOut.h b/CPP/7zip/Archive/Zip/ZipOut.h index 3546411..a645d67 100644 --- a/CPP/7zip/Archive/Zip/ZipOut.h +++ b/CPP/7zip/Archive/Zip/ZipOut.h | |||
@@ -18,7 +18,8 @@ public: | |||
18 | FILETIME Ntfs_MTime; | 18 | FILETIME Ntfs_MTime; |
19 | FILETIME Ntfs_ATime; | 19 | FILETIME Ntfs_ATime; |
20 | FILETIME Ntfs_CTime; | 20 | FILETIME Ntfs_CTime; |
21 | bool NtfsTimeIsDefined; | 21 | bool Write_NtfsTime; |
22 | bool Write_UnixTime; | ||
22 | 23 | ||
23 | // It's possible that NtfsTime is not defined, but there is NtfsTime in Extra. | 24 | // It's possible that NtfsTime is not defined, but there is NtfsTime in Extra. |
24 | 25 | ||
@@ -32,7 +33,10 @@ public: | |||
32 | return 4 + 5 + size; | 33 | return 4 + 5 + size; |
33 | } | 34 | } |
34 | 35 | ||
35 | CItemOut(): NtfsTimeIsDefined(false) {} | 36 | CItemOut(): |
37 | Write_NtfsTime(false), | ||
38 | Write_UnixTime(false) | ||
39 | {} | ||
36 | }; | 40 | }; |
37 | 41 | ||
38 | 42 | ||
@@ -62,6 +66,7 @@ class COutArchive | |||
62 | Write32(ft.dwHighDateTime); | 66 | Write32(ft.dwHighDateTime); |
63 | } | 67 | } |
64 | 68 | ||
69 | void WriteTimeExtra(const CItemOut &item, bool writeNtfs); | ||
65 | void WriteUtfName(const CItemOut &item); | 70 | void WriteUtfName(const CItemOut &item); |
66 | void WriteExtra(const CExtraBlock &extra); | 71 | void WriteExtra(const CExtraBlock &extra); |
67 | void WriteCommonItemInfo(const CLocalItem &item, bool isZip64); | 72 | void WriteCommonItemInfo(const CLocalItem &item, bool isZip64); |
diff --git a/CPP/7zip/Archive/Zip/ZipRegister.cpp b/CPP/7zip/Archive/Zip/ZipRegister.cpp index e6929f1..3ad4715 100644 --- a/CPP/7zip/Archive/Zip/ZipRegister.cpp +++ b/CPP/7zip/Archive/Zip/ZipRegister.cpp | |||
@@ -20,9 +20,19 @@ REGISTER_ARC_IO( | |||
20 | "zip", "zip z01 zipx jar xpi odt ods docx xlsx epub ipa apk appx", 0, 1, | 20 | "zip", "zip z01 zipx jar xpi odt ods docx xlsx epub ipa apk appx", 0, 1, |
21 | k_Signature, | 21 | k_Signature, |
22 | 0, | 22 | 0, |
23 | NArcInfoFlags::kFindSignature | | 23 | NArcInfoFlags::kFindSignature |
24 | NArcInfoFlags::kMultiSignature | | 24 | | NArcInfoFlags::kMultiSignature |
25 | NArcInfoFlags::kUseGlobalOffset, | 25 | | NArcInfoFlags::kUseGlobalOffset |
26 | IsArc_Zip) | 26 | | NArcInfoFlags::kCTime |
27 | // | NArcInfoFlags::kCTime_Default | ||
28 | | NArcInfoFlags::kATime | ||
29 | // | NArcInfoFlags::kATime_Default | ||
30 | | NArcInfoFlags::kMTime | ||
31 | | NArcInfoFlags::kMTime_Default | ||
32 | , TIME_PREC_TO_ARC_FLAGS_MASK (NFileTimeType::kWindows) | ||
33 | | TIME_PREC_TO_ARC_FLAGS_MASK (NFileTimeType::kUnix) | ||
34 | | TIME_PREC_TO_ARC_FLAGS_MASK (NFileTimeType::kDOS) | ||
35 | | TIME_PREC_TO_ARC_FLAGS_TIME_DEFAULT (NFileTimeType::kWindows) | ||
36 | , IsArc_Zip) | ||
27 | 37 | ||
28 | }} | 38 | }} |
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp index 26636c7..7f13071 100644 --- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp +++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp | |||
@@ -74,7 +74,9 @@ static void Copy_From_UpdateItem_To_ItemOut(const CUpdateItem &ui, CItemOut &ite | |||
74 | item.Ntfs_MTime = ui.Ntfs_MTime; | 74 | item.Ntfs_MTime = ui.Ntfs_MTime; |
75 | item.Ntfs_ATime = ui.Ntfs_ATime; | 75 | item.Ntfs_ATime = ui.Ntfs_ATime; |
76 | item.Ntfs_CTime = ui.Ntfs_CTime; | 76 | item.Ntfs_CTime = ui.Ntfs_CTime; |
77 | item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined; | 77 | |
78 | item.Write_UnixTime = ui.Write_UnixTime; | ||
79 | item.Write_NtfsTime = ui.Write_NtfsTime; | ||
78 | } | 80 | } |
79 | 81 | ||
80 | static void SetFileHeader( | 82 | static void SetFileHeader( |
@@ -476,12 +478,9 @@ static void WriteDirHeader(COutArchive &archive, const CCompressionMethodMode *o | |||
476 | } | 478 | } |
477 | 479 | ||
478 | 480 | ||
479 | static inline bool IsZero_FILETIME(const FILETIME &ft) | 481 | static void UpdatePropsFromStream( |
480 | { | 482 | const CUpdateOptions &options, |
481 | return (ft.dwHighDateTime == 0 && ft.dwLowDateTime == 0); | 483 | CUpdateItem &item, ISequentialInStream *fileInStream, |
482 | } | ||
483 | |||
484 | static void UpdatePropsFromStream(CUpdateItem &item, ISequentialInStream *fileInStream, | ||
485 | IArchiveUpdateCallback *updateCallback, UInt64 &totalComplexity) | 484 | IArchiveUpdateCallback *updateCallback, UInt64 &totalComplexity) |
486 | { | 485 | { |
487 | CMyComPtr<IStreamGetProps> getProps; | 486 | CMyComPtr<IStreamGetProps> getProps; |
@@ -505,36 +504,100 @@ static void UpdatePropsFromStream(CUpdateItem &item, ISequentialInStream *fileIn | |||
505 | } | 504 | } |
506 | item.Size = size; | 505 | item.Size = size; |
507 | } | 506 | } |
508 | 507 | ||
509 | if (!IsZero_FILETIME(mTime)) | 508 | if (options.Write_MTime) |
510 | { | 509 | if (!FILETIME_IsZero(mTime)) |
511 | item.Ntfs_MTime = mTime; | ||
512 | FILETIME loc = { 0, 0 }; | ||
513 | if (FileTimeToLocalFileTime(&mTime, &loc)) | ||
514 | { | 510 | { |
515 | item.Time = 0; | 511 | item.Ntfs_MTime = mTime; |
516 | NTime::FileTimeToDosTime(loc, item.Time); | 512 | NTime::UtcFileTime_To_LocalDosTime(mTime, item.Time); |
517 | } | 513 | } |
518 | } | ||
519 | 514 | ||
520 | if (!IsZero_FILETIME(cTime)) item.Ntfs_CTime = cTime; | 515 | if (options.Write_CTime) if (!FILETIME_IsZero(cTime)) item.Ntfs_CTime = cTime; |
521 | if (!IsZero_FILETIME(aTime)) item.Ntfs_ATime = aTime; | 516 | if (options.Write_ATime) if (!FILETIME_IsZero(aTime)) item.Ntfs_ATime = aTime; |
522 | 517 | ||
523 | item.Attrib = attrib; | 518 | item.Attrib = attrib; |
524 | } | 519 | } |
525 | 520 | ||
526 | 521 | ||
522 | /* | ||
523 | static HRESULT ReportProps( | ||
524 | IArchiveUpdateCallbackArcProp *reportArcProp, | ||
525 | UInt32 index, | ||
526 | const CItemOut &item, | ||
527 | bool isAesMode) | ||
528 | { | ||
529 | PROPVARIANT prop; | ||
530 | prop.vt = VT_EMPTY; | ||
531 | prop.wReserved1 = 0; | ||
532 | |||
533 | NCOM::PropVarEm_Set_UInt64(&prop, item.Size); | ||
534 | RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidSize, &prop)); | ||
535 | |||
536 | NCOM::PropVarEm_Set_UInt64(&prop, item.PackSize); | ||
537 | RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidPackSize, &prop)); | ||
538 | |||
539 | if (!isAesMode) | ||
540 | { | ||
541 | NCOM::PropVarEm_Set_UInt32(&prop, item.Crc); | ||
542 | RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidCRC, &prop)); | ||
543 | } | ||
544 | |||
545 | RINOK(reportArcProp->ReportFinished(NEventIndexType::kOutArcIndex, index, NUpdate::NOperationResult::kOK)); | ||
546 | |||
547 | // if (opCallback) RINOK(opCallback->ReportOperation(NEventIndexType::kOutArcIndex, index, NUpdateNotifyOp::kOpFinished)) | ||
548 | |||
549 | return S_OK; | ||
550 | } | ||
551 | */ | ||
552 | |||
553 | /* | ||
554 | struct CTotalStats | ||
555 | { | ||
556 | UInt64 Size; | ||
557 | UInt64 PackSize; | ||
558 | |||
559 | void UpdateWithItem(const CItemOut &item) | ||
560 | { | ||
561 | Size += item.Size; | ||
562 | PackSize += item.PackSize; | ||
563 | } | ||
564 | }; | ||
565 | |||
566 | static HRESULT ReportArcProps(IArchiveUpdateCallbackArcProp *reportArcProp, | ||
567 | CTotalStats &st) | ||
568 | { | ||
569 | PROPVARIANT prop; | ||
570 | prop.vt = VT_EMPTY; | ||
571 | prop.wReserved1 = 0; | ||
572 | { | ||
573 | NWindows::NCOM::PropVarEm_Set_UInt64(&prop, st.Size); | ||
574 | RINOK(reportArcProp->ReportProp( | ||
575 | NEventIndexType::kArcProp, 0, kpidSize, &prop)); | ||
576 | } | ||
577 | { | ||
578 | NWindows::NCOM::PropVarEm_Set_UInt64(&prop, st.PackSize); | ||
579 | RINOK(reportArcProp->ReportProp( | ||
580 | NEventIndexType::kArcProp, 0, kpidPackSize, &prop)); | ||
581 | } | ||
582 | return S_OK; | ||
583 | } | ||
584 | */ | ||
585 | |||
586 | |||
527 | static HRESULT Update2St( | 587 | static HRESULT Update2St( |
528 | DECL_EXTERNAL_CODECS_LOC_VARS | 588 | DECL_EXTERNAL_CODECS_LOC_VARS |
529 | COutArchive &archive, | 589 | COutArchive &archive, |
530 | CInArchive *inArchive, | 590 | CInArchive *inArchive, |
531 | const CObjectVector<CItemEx> &inputItems, | 591 | const CObjectVector<CItemEx> &inputItems, |
532 | CObjectVector<CUpdateItem> &updateItems, | 592 | CObjectVector<CUpdateItem> &updateItems, |
593 | const CUpdateOptions &updateOptions, | ||
533 | const CCompressionMethodMode *options, bool outSeqMode, | 594 | const CCompressionMethodMode *options, bool outSeqMode, |
534 | const CByteBuffer *comment, | 595 | const CByteBuffer *comment, |
535 | IArchiveUpdateCallback *updateCallback, | 596 | IArchiveUpdateCallback *updateCallback, |
536 | UInt64 &totalComplexity, | 597 | UInt64 &totalComplexity, |
537 | IArchiveUpdateCallbackFile *opCallback) | 598 | IArchiveUpdateCallbackFile *opCallback |
599 | // , IArchiveUpdateCallbackArcProp *reportArcProp | ||
600 | ) | ||
538 | { | 601 | { |
539 | CLocalProgress *lps = new CLocalProgress; | 602 | CLocalProgress *lps = new CLocalProgress; |
540 | CMyComPtr<ICompressProgressInfo> progress = lps; | 603 | CMyComPtr<ICompressProgressInfo> progress = lps; |
@@ -575,7 +638,8 @@ static HRESULT Update2St( | |||
575 | } | 638 | } |
576 | else | 639 | else |
577 | { | 640 | { |
578 | CMyComPtr<ISequentialInStream> fileInStream; | 641 | CMyComPtr<ISequentialInStream> fileInStream; |
642 | { | ||
579 | HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream); | 643 | HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream); |
580 | if (res == S_FALSE) | 644 | if (res == S_FALSE) |
581 | { | 645 | { |
@@ -596,7 +660,7 @@ static HRESULT Update2St( | |||
596 | } | 660 | } |
597 | // seqMode = true; // to test seqMode | 661 | // seqMode = true; // to test seqMode |
598 | 662 | ||
599 | UpdatePropsFromStream(ui, fileInStream, updateCallback, totalComplexity); | 663 | UpdatePropsFromStream(updateOptions, ui, fileInStream, updateCallback, totalComplexity); |
600 | 664 | ||
601 | CCompressingResult compressingResult; | 665 | CCompressingResult compressingResult; |
602 | 666 | ||
@@ -629,10 +693,11 @@ static HRESULT Update2St( | |||
629 | SetItemInfoFromCompressingResult(compressingResult, options->IsRealAesMode(), options->AesKeyMode, item); | 693 | SetItemInfoFromCompressingResult(compressingResult, options->IsRealAesMode(), options->AesKeyMode, item); |
630 | 694 | ||
631 | archive.WriteLocalHeader_Replace(item); | 695 | archive.WriteLocalHeader_Replace(item); |
632 | 696 | } | |
633 | RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); | 697 | // if (reportArcProp) RINOK(ReportProps(reportArcProp, ui.IndexInClient, item, options->IsRealAesMode())) |
634 | unpackSizeTotal += item.Size; | 698 | RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); |
635 | packSizeTotal += item.PackSize; | 699 | unpackSizeTotal += item.Size; |
700 | packSizeTotal += item.PackSize; | ||
636 | } | 701 | } |
637 | } | 702 | } |
638 | else | 703 | else |
@@ -656,6 +721,14 @@ static HRESULT Update2St( | |||
656 | 721 | ||
657 | archive.WriteCentralDir(items, comment); | 722 | archive.WriteCentralDir(items, comment); |
658 | 723 | ||
724 | /* | ||
725 | CTotalStats stat; | ||
726 | stat.Size = unpackSizeTotal; | ||
727 | stat.PackSize = packSizeTotal; | ||
728 | if (reportArcProp) | ||
729 | RINOK(ReportArcProps(reportArcProp, stat)) | ||
730 | */ | ||
731 | |||
659 | lps->ProgressOffset += kCentralHeaderSize * updateItems.Size() + 1; | 732 | lps->ProgressOffset += kCentralHeaderSize * updateItems.Size() + 1; |
660 | return lps->SetCur(); | 733 | return lps->SetCur(); |
661 | } | 734 | } |
@@ -667,6 +740,7 @@ static HRESULT Update2( | |||
667 | CInArchive *inArchive, | 740 | CInArchive *inArchive, |
668 | const CObjectVector<CItemEx> &inputItems, | 741 | const CObjectVector<CItemEx> &inputItems, |
669 | CObjectVector<CUpdateItem> &updateItems, | 742 | CObjectVector<CUpdateItem> &updateItems, |
743 | const CUpdateOptions &updateOptions, | ||
670 | const CCompressionMethodMode &options, bool outSeqMode, | 744 | const CCompressionMethodMode &options, bool outSeqMode, |
671 | const CByteBuffer *comment, | 745 | const CByteBuffer *comment, |
672 | IArchiveUpdateCallback *updateCallback) | 746 | IArchiveUpdateCallback *updateCallback) |
@@ -674,6 +748,11 @@ static HRESULT Update2( | |||
674 | CMyComPtr<IArchiveUpdateCallbackFile> opCallback; | 748 | CMyComPtr<IArchiveUpdateCallbackFile> opCallback; |
675 | updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback); | 749 | updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback); |
676 | 750 | ||
751 | /* | ||
752 | CMyComPtr<IArchiveUpdateCallbackArcProp> reportArcProp; | ||
753 | updateCallback->QueryInterface(IID_IArchiveUpdateCallbackArcProp, (void **)&reportArcProp); | ||
754 | */ | ||
755 | |||
677 | bool unknownComplexity = false; | 756 | bool unknownComplexity = false; |
678 | UInt64 complexity = 0; | 757 | UInt64 complexity = 0; |
679 | UInt64 numFilesToCompress = 0; | 758 | UInt64 numFilesToCompress = 0; |
@@ -901,11 +980,23 @@ static HRESULT Update2( | |||
901 | return Update2St( | 980 | return Update2St( |
902 | EXTERNAL_CODECS_LOC_VARS | 981 | EXTERNAL_CODECS_LOC_VARS |
903 | archive, inArchive, | 982 | archive, inArchive, |
904 | inputItems, updateItems, &options2, outSeqMode, comment, updateCallback, totalComplexity, opCallback); | 983 | inputItems, updateItems, |
984 | updateOptions, | ||
985 | &options2, outSeqMode, | ||
986 | comment, updateCallback, totalComplexity, | ||
987 | opCallback | ||
988 | // , reportArcProp | ||
989 | ); | ||
905 | 990 | ||
906 | 991 | ||
907 | #ifndef _7ZIP_ST | 992 | #ifndef _7ZIP_ST |
908 | 993 | ||
994 | /* | ||
995 | CTotalStats stat; | ||
996 | stat.Size = 0; | ||
997 | stat.PackSize = 0; | ||
998 | */ | ||
999 | |||
909 | CObjectVector<CItemOut> items; | 1000 | CObjectVector<CItemOut> items; |
910 | 1001 | ||
911 | CMtProgressMixer *mtProgressMixerSpec = new CMtProgressMixer; | 1002 | CMtProgressMixer *mtProgressMixerSpec = new CMtProgressMixer; |
@@ -1021,7 +1112,7 @@ static HRESULT Update2( | |||
1021 | RINOK(res); | 1112 | RINOK(res); |
1022 | if (!fileInStream) | 1113 | if (!fileInStream) |
1023 | return E_INVALIDARG; | 1114 | return E_INVALIDARG; |
1024 | UpdatePropsFromStream(ui, fileInStream, updateCallback, totalComplexity); | 1115 | UpdatePropsFromStream(updateOptions, ui, fileInStream, updateCallback, totalComplexity); |
1025 | RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); | 1116 | RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); |
1026 | } | 1117 | } |
1027 | 1118 | ||
@@ -1122,6 +1213,13 @@ static HRESULT Update2( | |||
1122 | memRef.WriteToStream(memManager.GetBlockSize(), outStream); | 1213 | memRef.WriteToStream(memManager.GetBlockSize(), outStream); |
1123 | archive.MoveCurPos(item.PackSize); | 1214 | archive.MoveCurPos(item.PackSize); |
1124 | memRef.FreeOpt(&memManager); | 1215 | memRef.FreeOpt(&memManager); |
1216 | /* | ||
1217 | if (reportArcProp) | ||
1218 | { | ||
1219 | stat.UpdateWithItem(item); | ||
1220 | RINOK(ReportProps(reportArcProp, ui.IndexInClient, item, options.IsRealAesMode())); | ||
1221 | } | ||
1222 | */ | ||
1125 | } | 1223 | } |
1126 | else | 1224 | else |
1127 | { | 1225 | { |
@@ -1202,6 +1300,14 @@ static HRESULT Update2( | |||
1202 | options.IsRealAesMode(), options.AesKeyMode, item); | 1300 | options.IsRealAesMode(), options.AesKeyMode, item); |
1203 | 1301 | ||
1204 | archive.WriteLocalHeader_Replace(item); | 1302 | archive.WriteLocalHeader_Replace(item); |
1303 | |||
1304 | /* | ||
1305 | if (reportArcProp) | ||
1306 | { | ||
1307 | stat.UpdateWithItem(item); | ||
1308 | RINOK(ReportProps(reportArcProp, ui.IndexInClient, item, options.IsRealAesMode())); | ||
1309 | } | ||
1310 | */ | ||
1205 | } | 1311 | } |
1206 | else | 1312 | else |
1207 | { | 1313 | { |
@@ -1230,7 +1336,14 @@ static HRESULT Update2( | |||
1230 | RINOK(mtCompressProgressMixer.SetRatioInfo(0, NULL, NULL)); | 1336 | RINOK(mtCompressProgressMixer.SetRatioInfo(0, NULL, NULL)); |
1231 | 1337 | ||
1232 | archive.WriteCentralDir(items, comment); | 1338 | archive.WriteCentralDir(items, comment); |
1233 | 1339 | ||
1340 | /* | ||
1341 | if (reportArcProp) | ||
1342 | { | ||
1343 | RINOK(ReportArcProps(reportArcProp, stat)); | ||
1344 | } | ||
1345 | */ | ||
1346 | |||
1234 | complexity += kCentralHeaderSize * updateItems.Size() + 1; | 1347 | complexity += kCentralHeaderSize * updateItems.Size() + 1; |
1235 | mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity); | 1348 | mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity); |
1236 | return mtCompressProgressMixer.SetRatioInfo(0, NULL, NULL); | 1349 | return mtCompressProgressMixer.SetRatioInfo(0, NULL, NULL); |
@@ -1472,6 +1585,7 @@ HRESULT Update( | |||
1472 | CObjectVector<CUpdateItem> &updateItems, | 1585 | CObjectVector<CUpdateItem> &updateItems, |
1473 | ISequentialOutStream *seqOutStream, | 1586 | ISequentialOutStream *seqOutStream, |
1474 | CInArchive *inArchive, bool removeSfx, | 1587 | CInArchive *inArchive, bool removeSfx, |
1588 | const CUpdateOptions &updateOptions, | ||
1475 | const CCompressionMethodMode &compressionMethodMode, | 1589 | const CCompressionMethodMode &compressionMethodMode, |
1476 | IArchiveUpdateCallback *updateCallback) | 1590 | IArchiveUpdateCallback *updateCallback) |
1477 | { | 1591 | { |
@@ -1529,6 +1643,7 @@ HRESULT Update( | |||
1529 | EXTERNAL_CODECS_LOC_VARS | 1643 | EXTERNAL_CODECS_LOC_VARS |
1530 | outArchive, inArchive, | 1644 | outArchive, inArchive, |
1531 | inputItems, updateItems, | 1645 | inputItems, updateItems, |
1646 | updateOptions, | ||
1532 | compressionMethodMode, outSeqMode, | 1647 | compressionMethodMode, outSeqMode, |
1533 | inArchive ? &inArchive->ArcInfo.Comment : NULL, | 1648 | inArchive ? &inArchive->ArcInfo.Comment : NULL, |
1534 | updateCallback); | 1649 | updateCallback); |
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.h b/CPP/7zip/Archive/Zip/ZipUpdate.h index 95e72a4..d1e3534 100644 --- a/CPP/7zip/Archive/Zip/ZipUpdate.h +++ b/CPP/7zip/Archive/Zip/ZipUpdate.h | |||
@@ -30,7 +30,9 @@ struct CUpdateItem | |||
30 | bool NewData; | 30 | bool NewData; |
31 | bool NewProps; | 31 | bool NewProps; |
32 | bool IsDir; | 32 | bool IsDir; |
33 | bool NtfsTimeIsDefined; | 33 | bool Write_NtfsTime; |
34 | bool Write_UnixTime; | ||
35 | // bool Write_UnixTime_ATime; | ||
34 | bool IsUtf8; | 36 | bool IsUtf8; |
35 | // bool IsAltStream; | 37 | // bool IsAltStream; |
36 | int IndexInArc; | 38 | int IndexInArc; |
@@ -50,30 +52,50 @@ struct CUpdateItem | |||
50 | void Clear() | 52 | void Clear() |
51 | { | 53 | { |
52 | IsDir = false; | 54 | IsDir = false; |
53 | NtfsTimeIsDefined = false; | 55 | |
56 | Write_NtfsTime = false; | ||
57 | Write_UnixTime = false; | ||
58 | |||
54 | IsUtf8 = false; | 59 | IsUtf8 = false; |
55 | // IsAltStream = false; | 60 | // IsAltStream = false; |
61 | Time = 0; | ||
56 | Size = 0; | 62 | Size = 0; |
57 | Name.Empty(); | 63 | Name.Empty(); |
58 | Name_Utf.Free(); | 64 | Name_Utf.Free(); |
59 | Comment.Free(); | 65 | Comment.Free(); |
66 | |||
67 | FILETIME_Clear(Ntfs_MTime); | ||
68 | FILETIME_Clear(Ntfs_ATime); | ||
69 | FILETIME_Clear(Ntfs_CTime); | ||
60 | } | 70 | } |
61 | 71 | ||
62 | CUpdateItem(): | 72 | CUpdateItem(): |
63 | IsDir(false), | 73 | IsDir(false), |
64 | NtfsTimeIsDefined(false), | 74 | Write_NtfsTime(false), |
75 | Write_UnixTime(false), | ||
65 | IsUtf8(false), | 76 | IsUtf8(false), |
66 | // IsAltStream(false), | 77 | // IsAltStream(false), |
78 | Time(0), | ||
67 | Size(0) | 79 | Size(0) |
68 | {} | 80 | {} |
69 | }; | 81 | }; |
70 | 82 | ||
83 | |||
84 | struct CUpdateOptions | ||
85 | { | ||
86 | bool Write_MTime; | ||
87 | bool Write_ATime; | ||
88 | bool Write_CTime; | ||
89 | }; | ||
90 | |||
91 | |||
71 | HRESULT Update( | 92 | HRESULT Update( |
72 | DECL_EXTERNAL_CODECS_LOC_VARS | 93 | DECL_EXTERNAL_CODECS_LOC_VARS |
73 | const CObjectVector<CItemEx> &inputItems, | 94 | const CObjectVector<CItemEx> &inputItems, |
74 | CObjectVector<CUpdateItem> &updateItems, | 95 | CObjectVector<CUpdateItem> &updateItems, |
75 | ISequentialOutStream *seqOutStream, | 96 | ISequentialOutStream *seqOutStream, |
76 | CInArchive *inArchive, bool removeSfx, | 97 | CInArchive *inArchive, bool removeSfx, |
98 | const CUpdateOptions &updateOptions, | ||
77 | const CCompressionMethodMode &compressionMethodMode, | 99 | const CCompressionMethodMode &compressionMethodMode, |
78 | IArchiveUpdateCallback *updateCallback); | 100 | IArchiveUpdateCallback *updateCallback); |
79 | 101 | ||
diff --git a/CPP/7zip/Bundles/Alone2/makefile b/CPP/7zip/Bundles/Alone2/makefile index 56de5b2..357e78e 100644 --- a/CPP/7zip/Bundles/Alone2/makefile +++ b/CPP/7zip/Bundles/Alone2/makefile | |||
@@ -18,7 +18,6 @@ WIN_OBJS = $(WIN_OBJS) \ | |||
18 | $O\FileLink.obj \ | 18 | $O\FileLink.obj \ |
19 | $O\FileSystem.obj \ | 19 | $O\FileSystem.obj \ |
20 | $O\MemoryLock.obj \ | 20 | $O\MemoryLock.obj \ |
21 | $O\PropVariantConv.obj \ | ||
22 | $O\Registry.obj \ | 21 | $O\Registry.obj \ |
23 | $O\SystemInfo.obj \ | 22 | $O\SystemInfo.obj \ |
24 | 23 | ||
diff --git a/CPP/7zip/Bundles/Alone2/makefile.gcc b/CPP/7zip/Bundles/Alone2/makefile.gcc index 1e7e17f..f8d31db 100644 --- a/CPP/7zip/Bundles/Alone2/makefile.gcc +++ b/CPP/7zip/Bundles/Alone2/makefile.gcc | |||
@@ -81,7 +81,6 @@ COMMON_OBJS_2 = \ | |||
81 | WIN_OBJS_2 = \ | 81 | WIN_OBJS_2 = \ |
82 | $O/ErrorMsg.o \ | 82 | $O/ErrorMsg.o \ |
83 | $O/FileLink.o \ | 83 | $O/FileLink.o \ |
84 | $O/PropVariantConv.o \ | ||
85 | $O/SystemInfo.o \ | 84 | $O/SystemInfo.o \ |
86 | 85 | ||
87 | 7ZIP_COMMON_OBJS_2 = \ | 86 | 7ZIP_COMMON_OBJS_2 = \ |
diff --git a/CPP/7zip/Bundles/Fm/makefile b/CPP/7zip/Bundles/Fm/makefile index 2c80ca1..33813e8 100644 --- a/CPP/7zip/Bundles/Fm/makefile +++ b/CPP/7zip/Bundles/Fm/makefile | |||
@@ -20,7 +20,6 @@ WIN_OBJS = $(WIN_OBJS) \ | |||
20 | $O\MemoryLock.obj \ | 20 | $O\MemoryLock.obj \ |
21 | $O\Menu.obj \ | 21 | $O\Menu.obj \ |
22 | $O\ProcessUtils.obj \ | 22 | $O\ProcessUtils.obj \ |
23 | $O\PropVariantConv.obj \ | ||
24 | $O\Registry.obj \ | 23 | $O\Registry.obj \ |
25 | $O\ResourceString.obj \ | 24 | $O\ResourceString.obj \ |
26 | $O\SystemInfo.obj \ | 25 | $O\SystemInfo.obj \ |
diff --git a/CPP/7zip/Bundles/Fm/resource.rc b/CPP/7zip/Bundles/Fm/resource.rc index ffcff11..ebc2f74 100644 --- a/CPP/7zip/Bundles/Fm/resource.rc +++ b/CPP/7zip/Bundles/Fm/resource.rc | |||
@@ -3,5 +3,5 @@ | |||
3 | 3 | ||
4 | STRINGTABLE | 4 | STRINGTABLE |
5 | BEGIN | 5 | BEGIN |
6 | 100 "7z zip rar 001 cab iso xz txz lzma tar cpio bz2 bzip2 tbz2 tbz gz gzip tgz tpz z taz lzh lha rpm deb arj vhd vhdx wim swm esd fat ntfs dmg hfs xar squashfs" | 6 | 100 "7z zip rar 001 cab iso xz txz lzma tar cpio bz2 bzip2 tbz2 tbz gz gzip tgz tpz z taz lzh lha rpm deb arj vhd vhdx wim swm esd fat ntfs dmg hfs xar squashfs apfs" |
7 | END | 7 | END |
diff --git a/CPP/7zip/Bundles/Format7zF/Arc.mak b/CPP/7zip/Bundles/Format7zF/Arc.mak index d8468a6..209aea3 100644 --- a/CPP/7zip/Bundles/Format7zF/Arc.mak +++ b/CPP/7zip/Bundles/Format7zF/Arc.mak | |||
@@ -24,6 +24,7 @@ WIN_OBJS = \ | |||
24 | $O\FileIO.obj \ | 24 | $O\FileIO.obj \ |
25 | $O\FileName.obj \ | 25 | $O\FileName.obj \ |
26 | $O\PropVariant.obj \ | 26 | $O\PropVariant.obj \ |
27 | $O\PropVariantConv.obj \ | ||
27 | $O\PropVariantUtils.obj \ | 28 | $O\PropVariantUtils.obj \ |
28 | $O\Synchronization.obj \ | 29 | $O\Synchronization.obj \ |
29 | $O\System.obj \ | 30 | $O\System.obj \ |
@@ -53,6 +54,7 @@ WIN_OBJS = \ | |||
53 | $O\VirtThread.obj \ | 54 | $O\VirtThread.obj \ |
54 | 55 | ||
55 | AR_OBJS = \ | 56 | AR_OBJS = \ |
57 | $O\ApfsHandler.obj \ | ||
56 | $O\ApmHandler.obj \ | 58 | $O\ApmHandler.obj \ |
57 | $O\ArHandler.obj \ | 59 | $O\ArHandler.obj \ |
58 | $O\ArjHandler.obj \ | 60 | $O\ArjHandler.obj \ |
@@ -72,6 +74,7 @@ AR_OBJS = \ | |||
72 | $O\HandlerCont.obj \ | 74 | $O\HandlerCont.obj \ |
73 | $O\HfsHandler.obj \ | 75 | $O\HfsHandler.obj \ |
74 | $O\IhexHandler.obj \ | 76 | $O\IhexHandler.obj \ |
77 | $O\LpHandler.obj \ | ||
75 | $O\LzhHandler.obj \ | 78 | $O\LzhHandler.obj \ |
76 | $O\LzmaHandler.obj \ | 79 | $O\LzmaHandler.obj \ |
77 | $O\MachoHandler.obj \ | 80 | $O\MachoHandler.obj \ |
@@ -83,6 +86,7 @@ AR_OBJS = \ | |||
83 | $O\PpmdHandler.obj \ | 86 | $O\PpmdHandler.obj \ |
84 | $O\QcowHandler.obj \ | 87 | $O\QcowHandler.obj \ |
85 | $O\RpmHandler.obj \ | 88 | $O\RpmHandler.obj \ |
89 | $O\SparseHandler.obj \ | ||
86 | $O\SplitHandler.obj \ | 90 | $O\SplitHandler.obj \ |
87 | $O\SquashfsHandler.obj \ | 91 | $O\SquashfsHandler.obj \ |
88 | $O\SwfHandler.obj \ | 92 | $O\SwfHandler.obj \ |
diff --git a/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak b/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak index 8021f68..e5e1e21 100644 --- a/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak +++ b/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak | |||
@@ -59,6 +59,7 @@ WIN_OBJS = \ | |||
59 | $O/FileIO.o \ | 59 | $O/FileIO.o \ |
60 | $O/FileName.o \ | 60 | $O/FileName.o \ |
61 | $O/PropVariant.o \ | 61 | $O/PropVariant.o \ |
62 | $O/PropVariantConv.o \ | ||
62 | $O/PropVariantUtils.o \ | 63 | $O/PropVariantUtils.o \ |
63 | $O/System.o \ | 64 | $O/System.o \ |
64 | $O/TimeUtils.o \ | 65 | $O/TimeUtils.o \ |
@@ -82,6 +83,7 @@ WIN_OBJS = \ | |||
82 | $O/UniqBlocks.o \ | 83 | $O/UniqBlocks.o \ |
83 | 84 | ||
84 | AR_OBJS = \ | 85 | AR_OBJS = \ |
86 | $O/ApfsHandler.o \ | ||
85 | $O/ApmHandler.o \ | 87 | $O/ApmHandler.o \ |
86 | $O/ArHandler.o \ | 88 | $O/ArHandler.o \ |
87 | $O/ArjHandler.o \ | 89 | $O/ArjHandler.o \ |
@@ -101,6 +103,7 @@ AR_OBJS = \ | |||
101 | $O/HandlerCont.o \ | 103 | $O/HandlerCont.o \ |
102 | $O/HfsHandler.o \ | 104 | $O/HfsHandler.o \ |
103 | $O/IhexHandler.o \ | 105 | $O/IhexHandler.o \ |
106 | $O/LpHandler.o \ | ||
104 | $O/LzhHandler.o \ | 107 | $O/LzhHandler.o \ |
105 | $O/LzmaHandler.o \ | 108 | $O/LzmaHandler.o \ |
106 | $O/MachoHandler.o \ | 109 | $O/MachoHandler.o \ |
@@ -112,6 +115,7 @@ AR_OBJS = \ | |||
112 | $O/PpmdHandler.o \ | 115 | $O/PpmdHandler.o \ |
113 | $O/QcowHandler.o \ | 116 | $O/QcowHandler.o \ |
114 | $O/RpmHandler.o \ | 117 | $O/RpmHandler.o \ |
118 | $O/SparseHandler.o \ | ||
115 | $O/SplitHandler.o \ | 119 | $O/SplitHandler.o \ |
116 | $O/SquashfsHandler.o \ | 120 | $O/SquashfsHandler.o \ |
117 | $O/SwfHandler.o \ | 121 | $O/SwfHandler.o \ |
diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsp b/CPP/7zip/Bundles/Format7zF/Format7z.dsp index 6b55e93..cf2d9e8 100644 --- a/CPP/7zip/Bundles/Format7zF/Format7z.dsp +++ b/CPP/7zip/Bundles/Format7zF/Format7z.dsp | |||
@@ -2763,6 +2763,10 @@ SOURCE=..\..\Archive\Udf\UdfIn.h | |||
2763 | # End Group | 2763 | # End Group |
2764 | # Begin Source File | 2764 | # Begin Source File |
2765 | 2765 | ||
2766 | SOURCE=..\..\Archive\ApfsHandler.cpp | ||
2767 | # End Source File | ||
2768 | # Begin Source File | ||
2769 | |||
2766 | SOURCE=..\..\Archive\ApmHandler.cpp | 2770 | SOURCE=..\..\Archive\ApmHandler.cpp |
2767 | # End Source File | 2771 | # End Source File |
2768 | # Begin Source File | 2772 | # Begin Source File |
@@ -2851,6 +2855,10 @@ SOURCE=..\..\Archive\IhexHandler.cpp | |||
2851 | # End Source File | 2855 | # End Source File |
2852 | # Begin Source File | 2856 | # Begin Source File |
2853 | 2857 | ||
2858 | SOURCE=..\..\Archive\LpHandler.cpp | ||
2859 | # End Source File | ||
2860 | # Begin Source File | ||
2861 | |||
2854 | SOURCE=..\..\Archive\LzhHandler.cpp | 2862 | SOURCE=..\..\Archive\LzhHandler.cpp |
2855 | # End Source File | 2863 | # End Source File |
2856 | # Begin Source File | 2864 | # Begin Source File |
@@ -2905,6 +2913,10 @@ SOURCE=..\..\Archive\RpmHandler.cpp | |||
2905 | # End Source File | 2913 | # End Source File |
2906 | # Begin Source File | 2914 | # Begin Source File |
2907 | 2915 | ||
2916 | SOURCE=..\..\Archive\SparseHandler.cpp | ||
2917 | # End Source File | ||
2918 | # Begin Source File | ||
2919 | |||
2908 | SOURCE=..\..\Archive\SplitHandler.cpp | 2920 | SOURCE=..\..\Archive\SplitHandler.cpp |
2909 | # End Source File | 2921 | # End Source File |
2910 | # Begin Source File | 2922 | # Begin Source File |
@@ -3029,6 +3041,14 @@ SOURCE=..\..\..\Windows\PropVariant.h | |||
3029 | # End Source File | 3041 | # End Source File |
3030 | # Begin Source File | 3042 | # Begin Source File |
3031 | 3043 | ||
3044 | SOURCE=..\..\..\Windows\PropVariantConv.cpp | ||
3045 | # End Source File | ||
3046 | # Begin Source File | ||
3047 | |||
3048 | SOURCE=..\..\..\Windows\PropVariantConv.h | ||
3049 | # End Source File | ||
3050 | # Begin Source File | ||
3051 | |||
3032 | SOURCE=..\..\..\Windows\PropVariantUtils.cpp | 3052 | SOURCE=..\..\..\Windows\PropVariantUtils.cpp |
3033 | # End Source File | 3053 | # End Source File |
3034 | # Begin Source File | 3054 | # Begin Source File |
diff --git a/CPP/7zip/Bundles/Format7zF/resource.rc b/CPP/7zip/Bundles/Format7zF/resource.rc index aaaabea..9c797c1 100644 --- a/CPP/7zip/Bundles/Format7zF/resource.rc +++ b/CPP/7zip/Bundles/Format7zF/resource.rc | |||
@@ -28,10 +28,11 @@ MY_VERSION_INFO_DLL("7z Plugin" , "7z") | |||
28 | 22 ICON "../../Archive/Icons/ntfs.ico" | 28 | 22 ICON "../../Archive/Icons/ntfs.ico" |
29 | 23 ICON "../../Archive/Icons/xz.ico" | 29 | 23 ICON "../../Archive/Icons/xz.ico" |
30 | 24 ICON "../../Archive/Icons/squashfs.ico" | 30 | 24 ICON "../../Archive/Icons/squashfs.ico" |
31 | 25 ICON "../../Archive/Icons/apfs.ico" | ||
31 | 32 | ||
32 | 33 | ||
33 | 34 | ||
34 | STRINGTABLE | 35 | STRINGTABLE |
35 | BEGIN | 36 | BEGIN |
36 | 100 "7z:0 zip:1 rar:3 001:9 cab:7 iso:8 xz:23 txz:23 lzma:16 tar:13 cpio:12 bz2:2 bzip2:2 tbz2:2 tbz:2 gz:14 gzip:14 tgz:14 tpz:14 z:5 taz:5 lzh:6 lha:6 rpm:10 deb:11 arj:4 vhd:20 vhdx:20 wim:15 swm:15 esd:15 fat:21 ntfs:22 dmg:17 hfs:18 xar:19 squashfs:24" | 37 | 100 "7z:0 zip:1 rar:3 001:9 cab:7 iso:8 xz:23 txz:23 lzma:16 tar:13 cpio:12 bz2:2 bzip2:2 tbz2:2 tbz:2 gz:14 gzip:14 tgz:14 tpz:14 z:5 taz:5 lzh:6 lha:6 rpm:10 deb:11 arj:4 vhd:20 vhdx:20 wim:15 swm:15 esd:15 fat:21 ntfs:22 dmg:17 hfs:18 xar:19 squashfs:24 apfs:25" |
37 | END | 38 | END |
diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp index a08d9c0..71436f6 100644 --- a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp +++ b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp | |||
@@ -515,7 +515,7 @@ static int main2(int numArgs, const char *args[]) | |||
515 | 515 | ||
516 | if (inStreamSpec) | 516 | if (inStreamSpec) |
517 | { | 517 | { |
518 | if (!inStreamSpec->File.GetLength(fileSize)) | 518 | if (!inStreamSpec->GetLength(fileSize)) |
519 | throw "Cannot get file length"; | 519 | throw "Cannot get file length"; |
520 | fileSizeDefined = true; | 520 | fileSizeDefined = true; |
521 | if (!stdOutMode) | 521 | if (!stdOutMode) |
diff --git a/CPP/7zip/Common/FileStreams.cpp b/CPP/7zip/Common/FileStreams.cpp index 9e0e79c..6862a9b 100644 --- a/CPP/7zip/Common/FileStreams.cpp +++ b/CPP/7zip/Common/FileStreams.cpp | |||
@@ -2,18 +2,30 @@ | |||
2 | 2 | ||
3 | #include "StdAfx.h" | 3 | #include "StdAfx.h" |
4 | 4 | ||
5 | // #include <stdio.h> | ||
6 | |||
5 | #ifndef _WIN32 | 7 | #ifndef _WIN32 |
6 | #include <fcntl.h> | 8 | #include <fcntl.h> |
7 | #include <unistd.h> | 9 | #include <unistd.h> |
8 | #include <errno.h> | 10 | #include <errno.h> |
9 | #include "../../Windows/FileFind.h" | 11 | #include <grp.h> |
12 | #include <pwd.h> | ||
13 | |||
14 | // for major minor | ||
15 | // BSD: <sys/types.h> | ||
16 | #include <sys/sysmacros.h> | ||
17 | |||
10 | #endif | 18 | #endif |
11 | 19 | ||
20 | #include "../../Windows/FileFind.h" | ||
21 | |||
12 | #ifdef SUPPORT_DEVICE_FILE | 22 | #ifdef SUPPORT_DEVICE_FILE |
13 | #include "../../../C/Alloc.h" | 23 | #include "../../../C/Alloc.h" |
14 | #include "../../Common/Defs.h" | 24 | #include "../../Common/Defs.h" |
15 | #endif | 25 | #endif |
16 | 26 | ||
27 | #include "../PropID.h" | ||
28 | |||
17 | #include "FileStreams.h" | 29 | #include "FileStreams.h" |
18 | 30 | ||
19 | static inline HRESULT GetLastError_HRESULT() | 31 | static inline HRESULT GetLastError_HRESULT() |
@@ -37,12 +49,19 @@ static const UInt32 kClusterSize = 1 << 18; | |||
37 | #endif | 49 | #endif |
38 | 50 | ||
39 | CInFileStream::CInFileStream(): | 51 | CInFileStream::CInFileStream(): |
40 | #ifdef SUPPORT_DEVICE_FILE | 52 | #ifdef SUPPORT_DEVICE_FILE |
41 | VirtPos(0), | 53 | VirtPos(0), |
42 | PhyPos(0), | 54 | PhyPos(0), |
43 | Buf(0), | 55 | Buf(0), |
44 | BufSize(0), | 56 | BufSize(0), |
45 | #endif | 57 | #endif |
58 | #ifndef _WIN32 | ||
59 | _uid(0), | ||
60 | _gid(0), | ||
61 | StoreOwnerId(false), | ||
62 | StoreOwnerName(false), | ||
63 | #endif | ||
64 | _info_WasLoaded(false), | ||
46 | SupportHardLinks(false), | 65 | SupportHardLinks(false), |
47 | Callback(NULL), | 66 | Callback(NULL), |
48 | CallbackRef(0) | 67 | CallbackRef(0) |
@@ -56,7 +75,7 @@ CInFileStream::~CInFileStream() | |||
56 | #endif | 75 | #endif |
57 | 76 | ||
58 | if (Callback) | 77 | if (Callback) |
59 | Callback->InFileStream_On_Destroy(CallbackRef); | 78 | Callback->InFileStream_On_Destroy(this, CallbackRef); |
60 | } | 79 | } |
61 | 80 | ||
62 | STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) | 81 | STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) |
@@ -306,8 +325,14 @@ STDMETHODIMP CInFileStream::GetSize(UInt64 *size) | |||
306 | 325 | ||
307 | STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib) | 326 | STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib) |
308 | { | 327 | { |
328 | if (!_info_WasLoaded) | ||
329 | RINOK(ReloadProps()); | ||
330 | const BY_HANDLE_FILE_INFORMATION &info = _info; | ||
331 | /* | ||
309 | BY_HANDLE_FILE_INFORMATION info; | 332 | BY_HANDLE_FILE_INFORMATION info; |
310 | if (File.GetFileInformation(&info)) | 333 | if (!File.GetFileInformation(&info)) |
334 | return GetLastError_HRESULT(); | ||
335 | */ | ||
311 | { | 336 | { |
312 | if (size) *size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; | 337 | if (size) *size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; |
313 | if (cTime) *cTime = info.ftCreationTime; | 338 | if (cTime) *cTime = info.ftCreationTime; |
@@ -316,13 +341,18 @@ STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aT | |||
316 | if (attrib) *attrib = info.dwFileAttributes; | 341 | if (attrib) *attrib = info.dwFileAttributes; |
317 | return S_OK; | 342 | return S_OK; |
318 | } | 343 | } |
319 | return GetLastError_HRESULT(); | ||
320 | } | 344 | } |
321 | 345 | ||
322 | STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) | 346 | STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) |
323 | { | 347 | { |
348 | if (!_info_WasLoaded) | ||
349 | RINOK(ReloadProps()); | ||
350 | const BY_HANDLE_FILE_INFORMATION &info = _info; | ||
351 | /* | ||
324 | BY_HANDLE_FILE_INFORMATION info; | 352 | BY_HANDLE_FILE_INFORMATION info; |
325 | if (File.GetFileInformation(&info)) | 353 | if (!File.GetFileInformation(&info)) |
354 | return GetLastError_HRESULT(); | ||
355 | */ | ||
326 | { | 356 | { |
327 | props->Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; | 357 | props->Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; |
328 | props->VolID = info.dwVolumeSerialNumber; | 358 | props->VolID = info.dwVolumeSerialNumber; |
@@ -335,27 +365,114 @@ STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) | |||
335 | props->MTime = info.ftLastWriteTime; | 365 | props->MTime = info.ftLastWriteTime; |
336 | return S_OK; | 366 | return S_OK; |
337 | } | 367 | } |
338 | return GetLastError_HRESULT(); | ||
339 | } | 368 | } |
340 | 369 | ||
370 | STDMETHODIMP CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value) | ||
371 | { | ||
372 | if (!_info_WasLoaded) | ||
373 | RINOK(ReloadProps()); | ||
374 | |||
375 | if (!_info_WasLoaded) | ||
376 | return S_OK; | ||
377 | |||
378 | NWindows::NCOM::CPropVariant prop; | ||
379 | |||
380 | #ifdef SUPPORT_DEVICE_FILE | ||
381 | if (File.IsDeviceFile) | ||
382 | { | ||
383 | switch (propID) | ||
384 | { | ||
385 | case kpidSize: | ||
386 | if (File.SizeDefined) | ||
387 | prop = File.Size; | ||
388 | break; | ||
389 | // case kpidAttrib: prop = (UInt32)0; break; | ||
390 | case kpidPosixAttrib: | ||
391 | { | ||
392 | prop = (UInt32)NWindows::NFile::NFind::NAttributes:: | ||
393 | Get_PosixMode_From_WinAttrib(0); | ||
394 | /* GNU TAR by default can't extract file with MY_LIN_S_IFBLK attribute | ||
395 | so we don't use MY_LIN_S_IFBLK here */ | ||
396 | // prop = (UInt32)(MY_LIN_S_IFBLK | 0600); // for debug | ||
397 | break; | ||
398 | } | ||
399 | /* | ||
400 | case kpidDeviceMajor: | ||
401 | prop = (UInt32)8; // id for SCSI type device (sda) | ||
402 | break; | ||
403 | case kpidDeviceMinor: | ||
404 | prop = (UInt32)0; | ||
405 | break; | ||
406 | */ | ||
407 | } | ||
408 | } | ||
409 | else | ||
410 | #endif | ||
411 | { | ||
412 | switch (propID) | ||
413 | { | ||
414 | case kpidSize: | ||
415 | { | ||
416 | const UInt64 size = (((UInt64)_info.nFileSizeHigh) << 32) + _info.nFileSizeLow; | ||
417 | prop = size; | ||
418 | break; | ||
419 | } | ||
420 | case kpidAttrib: prop = (UInt32)_info.dwFileAttributes; break; | ||
421 | case kpidCTime: PropVariant_SetFrom_FiTime(prop, _info.ftCreationTime); break; | ||
422 | case kpidATime: PropVariant_SetFrom_FiTime(prop, _info.ftLastAccessTime); break; | ||
423 | case kpidMTime: PropVariant_SetFrom_FiTime(prop, _info.ftLastWriteTime); break; | ||
424 | case kpidPosixAttrib: | ||
425 | prop = (UInt32)NWindows::NFile::NFind::NAttributes:: | ||
426 | Get_PosixMode_From_WinAttrib(_info.dwFileAttributes); | ||
427 | // | (UInt32)(1 << 21); // for debug | ||
428 | break; | ||
429 | } | ||
430 | } | ||
431 | prop.Detach(value); | ||
432 | return S_OK; | ||
433 | } | ||
434 | |||
435 | |||
436 | STDMETHODIMP CInFileStream::ReloadProps() | ||
437 | { | ||
438 | #ifdef SUPPORT_DEVICE_FILE | ||
439 | if (File.IsDeviceFile) | ||
440 | { | ||
441 | memset(&_info, 0, sizeof(_info)); | ||
442 | if (File.SizeDefined) | ||
443 | { | ||
444 | _info.nFileSizeHigh = (DWORD)(File.Size >> 32); | ||
445 | _info.nFileSizeLow = (DWORD)(File.Size); | ||
446 | } | ||
447 | _info.nNumberOfLinks = 1; | ||
448 | _info_WasLoaded = true; | ||
449 | return S_OK; | ||
450 | } | ||
451 | #endif | ||
452 | _info_WasLoaded = File.GetFileInformation(&_info); | ||
453 | if (!_info_WasLoaded) | ||
454 | return GetLastError_HRESULT(); | ||
455 | return S_OK; | ||
456 | } | ||
457 | |||
458 | |||
341 | #elif !defined(_WIN32) | 459 | #elif !defined(_WIN32) |
342 | 460 | ||
343 | STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib) | 461 | STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib) |
344 | { | 462 | { |
463 | if (!_info_WasLoaded) | ||
464 | RINOK(ReloadProps()); | ||
465 | const struct stat &st = _info; | ||
466 | /* | ||
345 | struct stat st; | 467 | struct stat st; |
346 | if (File.my_fstat(&st) != 0) | 468 | if (File.my_fstat(&st) != 0) |
347 | return GetLastError_HRESULT(); | 469 | return GetLastError_HRESULT(); |
348 | 470 | */ | |
471 | |||
349 | if (size) *size = (UInt64)st.st_size; | 472 | if (size) *size = (UInt64)st.st_size; |
350 | #ifdef __APPLE__ | 473 | if (cTime) FiTime_To_FILETIME (ST_CTIME(st), *cTime); |
351 | if (cTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_ctimespec, *cTime); | 474 | if (aTime) FiTime_To_FILETIME (ST_ATIME(st), *aTime); |
352 | if (aTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_atimespec, *aTime); | 475 | if (mTime) FiTime_To_FILETIME (ST_MTIME(st), *mTime); |
353 | if (mTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_mtimespec, *mTime); | ||
354 | #else | ||
355 | if (cTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_ctim, *cTime); | ||
356 | if (aTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_atim, *aTime); | ||
357 | if (mTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_mtim, *mTime); | ||
358 | #endif | ||
359 | if (attrib) *attrib = NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode); | 476 | if (attrib) *attrib = NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode); |
360 | 477 | ||
361 | return S_OK; | 478 | return S_OK; |
@@ -365,9 +482,14 @@ STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aT | |||
365 | 482 | ||
366 | STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) | 483 | STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) |
367 | { | 484 | { |
485 | if (!_info_WasLoaded) | ||
486 | RINOK(ReloadProps()); | ||
487 | const struct stat &st = _info; | ||
488 | /* | ||
368 | struct stat st; | 489 | struct stat st; |
369 | if (File.my_fstat(&st) != 0) | 490 | if (File.my_fstat(&st) != 0) |
370 | return GetLastError_HRESULT(); | 491 | return GetLastError_HRESULT(); |
492 | */ | ||
371 | 493 | ||
372 | props->Size = (UInt64)st.st_size; | 494 | props->Size = (UInt64)st.st_size; |
373 | /* | 495 | /* |
@@ -381,15 +503,9 @@ STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) | |||
381 | props->NumLinks = (UInt32)st.st_nlink; // we reduce to UInt32 from (nlink_t) that is (unsigned long) | 503 | props->NumLinks = (UInt32)st.st_nlink; // we reduce to UInt32 from (nlink_t) that is (unsigned long) |
382 | props->Attrib = NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode); | 504 | props->Attrib = NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode); |
383 | 505 | ||
384 | #ifdef __APPLE__ | 506 | FiTime_To_FILETIME (ST_CTIME(st), props->CTime); |
385 | NWindows::NFile::NFind::timespec_To_FILETIME(st.st_ctimespec, props->CTime); | 507 | FiTime_To_FILETIME (ST_ATIME(st), props->ATime); |
386 | NWindows::NFile::NFind::timespec_To_FILETIME(st.st_atimespec, props->ATime); | 508 | FiTime_To_FILETIME (ST_MTIME(st), props->MTime); |
387 | NWindows::NFile::NFind::timespec_To_FILETIME(st.st_mtimespec, props->MTime); | ||
388 | #else | ||
389 | NWindows::NFile::NFind::timespec_To_FILETIME(st.st_ctim, props->CTime); | ||
390 | NWindows::NFile::NFind::timespec_To_FILETIME(st.st_atim, props->ATime); | ||
391 | NWindows::NFile::NFind::timespec_To_FILETIME(st.st_mtim, props->MTime); | ||
392 | #endif | ||
393 | 509 | ||
394 | /* | 510 | /* |
395 | printf("\nGetProps2() NumLinks=%d = st_dev=%d st_ino = %d\n" | 511 | printf("\nGetProps2() NumLinks=%d = st_dev=%d st_ino = %d\n" |
@@ -402,8 +518,130 @@ STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) | |||
402 | return S_OK; | 518 | return S_OK; |
403 | } | 519 | } |
404 | 520 | ||
521 | STDMETHODIMP CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value) | ||
522 | { | ||
523 | if (!_info_WasLoaded) | ||
524 | RINOK(ReloadProps()); | ||
525 | |||
526 | if (!_info_WasLoaded) | ||
527 | return S_OK; | ||
528 | |||
529 | const struct stat &st = _info; | ||
530 | |||
531 | NWindows::NCOM::CPropVariant prop; | ||
532 | { | ||
533 | switch (propID) | ||
534 | { | ||
535 | case kpidSize: prop = (UInt64)st.st_size; break; | ||
536 | case kpidAttrib: | ||
537 | prop = (UInt32)NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode); | ||
538 | break; | ||
539 | case kpidCTime: PropVariant_SetFrom_FiTime(prop, ST_CTIME(st)); break; | ||
540 | case kpidATime: PropVariant_SetFrom_FiTime(prop, ST_ATIME(st)); break; | ||
541 | case kpidMTime: PropVariant_SetFrom_FiTime(prop, ST_MTIME(st)); break; | ||
542 | case kpidPosixAttrib: prop = (UInt32)st.st_mode; break; | ||
543 | |||
544 | case kpidDeviceMajor: | ||
545 | { | ||
546 | // printf("\nst.st_rdev = %d\n", st.st_rdev); | ||
547 | if (S_ISCHR(st.st_mode) || | ||
548 | S_ISBLK(st.st_mode)) | ||
549 | prop = (UInt32)(major(st.st_rdev)); // + 1000); | ||
550 | // prop = (UInt32)12345678; // for debug | ||
551 | break; | ||
552 | } | ||
553 | |||
554 | case kpidDeviceMinor: | ||
555 | if (S_ISCHR(st.st_mode) || | ||
556 | S_ISBLK(st.st_mode)) | ||
557 | prop = (UInt32)(minor(st.st_rdev)); // + 100); | ||
558 | // prop = (UInt32)(st.st_rdev); // for debug | ||
559 | // printf("\nst.st_rdev = %d\n", st.st_rdev); | ||
560 | // prop = (UInt32)123456789; // for debug | ||
561 | break; | ||
562 | |||
563 | /* | ||
564 | case kpidDevice: | ||
565 | if (S_ISCHR(st.st_mode) || | ||
566 | S_ISBLK(st.st_mode)) | ||
567 | prop = (UInt64)(st.st_rdev); | ||
568 | break; | ||
569 | */ | ||
570 | |||
571 | case kpidUserId: | ||
572 | { | ||
573 | if (StoreOwnerId) | ||
574 | prop = (UInt32)st.st_uid; | ||
575 | break; | ||
576 | } | ||
577 | case kpidGroupId: | ||
578 | { | ||
579 | if (StoreOwnerId) | ||
580 | prop = (UInt32)st.st_gid; | ||
581 | break; | ||
582 | } | ||
583 | case kpidUser: | ||
584 | { | ||
585 | if (StoreOwnerName) | ||
586 | { | ||
587 | const uid_t uid = st.st_uid; | ||
588 | { | ||
589 | if (!OwnerName.IsEmpty() && _uid == uid) | ||
590 | prop = OwnerName; | ||
591 | else | ||
592 | { | ||
593 | const passwd *pw = getpwuid(uid); | ||
594 | if (pw) | ||
595 | { | ||
596 | // we can use utf-8 here. | ||
597 | // prop = pw->pw_name; | ||
598 | } | ||
599 | } | ||
600 | } | ||
601 | } | ||
602 | break; | ||
603 | } | ||
604 | case kpidGroup: | ||
605 | { | ||
606 | if (StoreOwnerName) | ||
607 | { | ||
608 | const uid_t gid = st.st_gid; | ||
609 | { | ||
610 | if (!OwnerGroup.IsEmpty() && _gid == gid) | ||
611 | prop = OwnerGroup; | ||
612 | else | ||
613 | { | ||
614 | const group *gr = getgrgid(gid); | ||
615 | if (gr) | ||
616 | { | ||
617 | // we can use utf-8 here. | ||
618 | // prop = gr->gr_name; | ||
619 | } | ||
620 | } | ||
621 | } | ||
622 | } | ||
623 | break; | ||
624 | } | ||
625 | } | ||
626 | } | ||
627 | prop.Detach(value); | ||
628 | return S_OK; | ||
629 | } | ||
630 | |||
631 | |||
632 | STDMETHODIMP CInFileStream::ReloadProps() | ||
633 | { | ||
634 | _info_WasLoaded = (File.my_fstat(&_info) == 0); | ||
635 | if (!_info_WasLoaded) | ||
636 | return GetLastError_HRESULT(); | ||
637 | return S_OK; | ||
638 | } | ||
639 | |||
405 | #endif | 640 | #endif |
406 | 641 | ||
642 | |||
643 | |||
644 | |||
407 | ////////////////////////// | 645 | ////////////////////////// |
408 | // COutFileStream | 646 | // COutFileStream |
409 | 647 | ||
diff --git a/CPP/7zip/Common/FileStreams.h b/CPP/7zip/Common/FileStreams.h index fe9f4c1..f2c19ee 100644 --- a/CPP/7zip/Common/FileStreams.h +++ b/CPP/7zip/Common/FileStreams.h | |||
@@ -14,10 +14,14 @@ | |||
14 | 14 | ||
15 | #include "../IStream.h" | 15 | #include "../IStream.h" |
16 | 16 | ||
17 | #include "UniqBlocks.h" | ||
18 | |||
19 | |||
20 | class CInFileStream; | ||
17 | struct IInFileStream_Callback | 21 | struct IInFileStream_Callback |
18 | { | 22 | { |
19 | virtual HRESULT InFileStream_On_Error(UINT_PTR val, DWORD error) = 0; | 23 | virtual HRESULT InFileStream_On_Error(UINT_PTR val, DWORD error) = 0; |
20 | virtual void InFileStream_On_Destroy(UINT_PTR val) = 0; | 24 | virtual void InFileStream_On_Destroy(CInFileStream *stream, UINT_PTR val) = 0; |
21 | }; | 25 | }; |
22 | 26 | ||
23 | class CInFileStream: | 27 | class CInFileStream: |
@@ -25,10 +29,11 @@ class CInFileStream: | |||
25 | public IStreamGetSize, | 29 | public IStreamGetSize, |
26 | public IStreamGetProps, | 30 | public IStreamGetProps, |
27 | public IStreamGetProps2, | 31 | public IStreamGetProps2, |
32 | public IStreamGetProp, | ||
28 | public CMyUnknownImp | 33 | public CMyUnknownImp |
29 | { | 34 | { |
30 | public: | ||
31 | NWindows::NFile::NIO::CInFile File; | 35 | NWindows::NFile::NIO::CInFile File; |
36 | public: | ||
32 | 37 | ||
33 | #ifdef USE_WIN_FILE | 38 | #ifdef USE_WIN_FILE |
34 | 39 | ||
@@ -42,22 +47,46 @@ public: | |||
42 | 47 | ||
43 | #endif | 48 | #endif |
44 | 49 | ||
50 | #ifdef _WIN32 | ||
51 | BY_HANDLE_FILE_INFORMATION _info; | ||
52 | #else | ||
53 | struct stat _info; | ||
54 | UInt32 _uid; | ||
55 | UInt32 _gid; | ||
56 | UString OwnerName; | ||
57 | UString OwnerGroup; | ||
58 | bool StoreOwnerId; | ||
59 | bool StoreOwnerName; | ||
60 | #endif | ||
61 | |||
62 | bool _info_WasLoaded; | ||
45 | bool SupportHardLinks; | 63 | bool SupportHardLinks; |
46 | |||
47 | IInFileStream_Callback *Callback; | 64 | IInFileStream_Callback *Callback; |
48 | UINT_PTR CallbackRef; | 65 | UINT_PTR CallbackRef; |
49 | 66 | ||
50 | virtual ~CInFileStream(); | 67 | virtual ~CInFileStream(); |
51 | 68 | ||
52 | CInFileStream(); | 69 | CInFileStream(); |
70 | |||
71 | void Set_PreserveATime(bool v) | ||
72 | { | ||
73 | File.PreserveATime = v; | ||
74 | } | ||
75 | |||
76 | bool GetLength(UInt64 &length) const throw() | ||
77 | { | ||
78 | return File.GetLength(length); | ||
79 | } | ||
53 | 80 | ||
54 | bool Open(CFSTR fileName) | 81 | bool Open(CFSTR fileName) |
55 | { | 82 | { |
83 | _info_WasLoaded = false; | ||
56 | return File.Open(fileName); | 84 | return File.Open(fileName); |
57 | } | 85 | } |
58 | 86 | ||
59 | bool OpenShared(CFSTR fileName, bool shareForWrite) | 87 | bool OpenShared(CFSTR fileName, bool shareForWrite) |
60 | { | 88 | { |
89 | _info_WasLoaded = false; | ||
61 | return File.OpenShared(fileName, shareForWrite); | 90 | return File.OpenShared(fileName, shareForWrite); |
62 | } | 91 | } |
63 | 92 | ||
@@ -65,6 +94,7 @@ public: | |||
65 | MY_QUERYINTERFACE_ENTRY(IStreamGetSize) | 94 | MY_QUERYINTERFACE_ENTRY(IStreamGetSize) |
66 | MY_QUERYINTERFACE_ENTRY(IStreamGetProps) | 95 | MY_QUERYINTERFACE_ENTRY(IStreamGetProps) |
67 | MY_QUERYINTERFACE_ENTRY(IStreamGetProps2) | 96 | MY_QUERYINTERFACE_ENTRY(IStreamGetProps2) |
97 | MY_QUERYINTERFACE_ENTRY(IStreamGetProp) | ||
68 | MY_QUERYINTERFACE_END | 98 | MY_QUERYINTERFACE_END |
69 | MY_ADDREF_RELEASE | 99 | MY_ADDREF_RELEASE |
70 | 100 | ||
@@ -74,6 +104,8 @@ public: | |||
74 | STDMETHOD(GetSize)(UInt64 *size); | 104 | STDMETHOD(GetSize)(UInt64 *size); |
75 | STDMETHOD(GetProps)(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib); | 105 | STDMETHOD(GetProps)(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib); |
76 | STDMETHOD(GetProps2)(CStreamFileProps *props); | 106 | STDMETHOD(GetProps2)(CStreamFileProps *props); |
107 | STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value); | ||
108 | STDMETHOD(ReloadProps)(); | ||
77 | }; | 109 | }; |
78 | 110 | ||
79 | class CStdInFileStream: | 111 | class CStdInFileStream: |
@@ -110,11 +142,11 @@ public: | |||
110 | 142 | ||
111 | UInt64 ProcessedSize; | 143 | UInt64 ProcessedSize; |
112 | 144 | ||
113 | bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) | 145 | bool SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) |
114 | { | 146 | { |
115 | return File.SetTime(cTime, aTime, mTime); | 147 | return File.SetTime(cTime, aTime, mTime); |
116 | } | 148 | } |
117 | bool SetMTime(const FILETIME *mTime) { return File.SetMTime(mTime); } | 149 | bool SetMTime(const CFiTime *mTime) { return File.SetMTime(mTime); } |
118 | 150 | ||
119 | MY_UNKNOWN_IMP1(IOutStream) | 151 | MY_UNKNOWN_IMP1(IOutStream) |
120 | 152 | ||
diff --git a/CPP/7zip/Common/InBuffer.cpp b/CPP/7zip/Common/InBuffer.cpp index 6f6eeca..fe6d149 100644 --- a/CPP/7zip/Common/InBuffer.cpp +++ b/CPP/7zip/Common/InBuffer.cpp | |||
@@ -77,7 +77,8 @@ bool CInBufferBase::ReadByte_FromNewBlock(Byte &b) | |||
77 | { | 77 | { |
78 | if (!ReadBlock()) | 78 | if (!ReadBlock()) |
79 | { | 79 | { |
80 | NumExtraBytes++; | 80 | // 22.00: we don't increment (NumExtraBytes) here |
81 | // NumExtraBytes++; | ||
81 | b = 0xFF; | 82 | b = 0xFF; |
82 | return false; | 83 | return false; |
83 | } | 84 | } |
diff --git a/CPP/7zip/Common/LimitedStreams.cpp b/CPP/7zip/Common/LimitedStreams.cpp index add6636..980c795 100644 --- a/CPP/7zip/Common/LimitedStreams.cpp +++ b/CPP/7zip/Common/LimitedStreams.cpp | |||
@@ -154,44 +154,70 @@ STDMETHODIMP CExtentsStream::Read(void *data, UInt32 size, UInt32 *processedSize | |||
154 | { | 154 | { |
155 | if (processedSize) | 155 | if (processedSize) |
156 | *processedSize = 0; | 156 | *processedSize = 0; |
157 | if (_virtPos >= Extents.Back().Virt) | 157 | const UInt64 virt = _virtPos; |
158 | if (virt >= Extents.Back().Virt) | ||
158 | return S_OK; | 159 | return S_OK; |
159 | if (size == 0) | 160 | if (size == 0) |
160 | return S_OK; | 161 | return S_OK; |
161 | 162 | ||
162 | unsigned left = 0, right = Extents.Size() - 1; | 163 | unsigned left = _prevExtentIndex; |
163 | for (;;) | 164 | if (virt < Extents[left].Virt || |
165 | virt >= Extents[left + 1].Virt) | ||
164 | { | 166 | { |
165 | unsigned mid = (left + right) / 2; | 167 | left = 0; |
166 | if (mid == left) | 168 | unsigned right = Extents.Size() - 1; |
167 | break; | 169 | for (;;) |
168 | if (_virtPos < Extents[mid].Virt) | 170 | { |
169 | right = mid; | 171 | const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); |
170 | else | 172 | if (mid == left) |
171 | left = mid; | 173 | break; |
174 | if (virt < Extents[mid].Virt) | ||
175 | right = mid; | ||
176 | else | ||
177 | left = mid; | ||
178 | } | ||
179 | _prevExtentIndex = left; | ||
172 | } | 180 | } |
173 | 181 | ||
174 | const CSeekExtent &extent = Extents[left]; | ||
175 | UInt64 phyPos = extent.Phy + (_virtPos - extent.Virt); | ||
176 | if (_needStartSeek || _phyPos != phyPos) | ||
177 | { | 182 | { |
178 | _needStartSeek = false; | 183 | const UInt64 rem = Extents[left + 1].Virt - virt; |
179 | _phyPos = phyPos; | 184 | if (size > rem) |
180 | RINOK(SeekToPhys()); | 185 | size = (UInt32)rem; |
181 | } | 186 | } |
182 | 187 | ||
183 | UInt64 rem = Extents[left + 1].Virt - _virtPos; | 188 | const CSeekExtent &extent = Extents[left]; |
184 | if (size > rem) | ||
185 | size = (UInt32)rem; | ||
186 | 189 | ||
187 | HRESULT res = Stream->Read(data, size, &size); | 190 | if (extent.Is_ZeroFill()) |
188 | _phyPos += size; | 191 | { |
192 | memset(data, 0, size); | ||
193 | _virtPos += size; | ||
194 | if (processedSize) | ||
195 | *processedSize = size; | ||
196 | return S_OK; | ||
197 | } | ||
198 | |||
199 | { | ||
200 | const UInt64 phy = extent.Phy + (virt - extent.Virt); | ||
201 | if (_phyPos != phy) | ||
202 | { | ||
203 | _phyPos = (UInt64)0 - 1; // we don't trust seek_pos in case of error | ||
204 | RINOK(Stream->Seek((Int64)phy, STREAM_SEEK_SET, NULL)); | ||
205 | _phyPos = phy; | ||
206 | } | ||
207 | } | ||
208 | |||
209 | const HRESULT res = Stream->Read(data, size, &size); | ||
189 | _virtPos += size; | 210 | _virtPos += size; |
211 | if (res == S_OK) | ||
212 | _phyPos += size; | ||
213 | else | ||
214 | _phyPos = (UInt64)0 - 1; // we don't trust seek_pos in case of error | ||
190 | if (processedSize) | 215 | if (processedSize) |
191 | *processedSize = size; | 216 | *processedSize = size; |
192 | return res; | 217 | return res; |
193 | } | 218 | } |
194 | 219 | ||
220 | |||
195 | STDMETHODIMP CExtentsStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) | 221 | STDMETHODIMP CExtentsStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) |
196 | { | 222 | { |
197 | switch (seekOrigin) | 223 | switch (seekOrigin) |
diff --git a/CPP/7zip/Common/LimitedStreams.h b/CPP/7zip/Common/LimitedStreams.h index ade2993..50c7cd8 100644 --- a/CPP/7zip/Common/LimitedStreams.h +++ b/CPP/7zip/Common/LimitedStreams.h | |||
@@ -101,21 +101,26 @@ public: | |||
101 | STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); | 101 | STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); |
102 | }; | 102 | }; |
103 | 103 | ||
104 | |||
105 | |||
106 | const UInt64 k_SeekExtent_Phy_Type_ZeroFill = (UInt64)(Int64)-1; | ||
107 | |||
104 | struct CSeekExtent | 108 | struct CSeekExtent |
105 | { | 109 | { |
106 | UInt64 Phy; | ||
107 | UInt64 Virt; | 110 | UInt64 Virt; |
111 | UInt64 Phy; | ||
112 | |||
113 | void SetAs_ZeroFill() { Phy = k_SeekExtent_Phy_Type_ZeroFill; } | ||
114 | bool Is_ZeroFill() const { return Phy == k_SeekExtent_Phy_Type_ZeroFill; } | ||
108 | }; | 115 | }; |
109 | 116 | ||
110 | class CExtentsStream: | 117 | class CExtentsStream: |
111 | public IInStream, | 118 | public IInStream, |
112 | public CMyUnknownImp | 119 | public CMyUnknownImp |
113 | { | 120 | { |
114 | UInt64 _phyPos; | ||
115 | UInt64 _virtPos; | 121 | UInt64 _virtPos; |
116 | bool _needStartSeek; | 122 | UInt64 _phyPos; |
117 | 123 | unsigned _prevExtentIndex; | |
118 | HRESULT SeekToPhys() { return Stream->Seek((Int64)_phyPos, STREAM_SEEK_SET, NULL); } | ||
119 | 124 | ||
120 | public: | 125 | public: |
121 | CMyComPtr<IInStream> Stream; | 126 | CMyComPtr<IInStream> Stream; |
@@ -129,11 +134,13 @@ public: | |||
129 | void Init() | 134 | void Init() |
130 | { | 135 | { |
131 | _virtPos = 0; | 136 | _virtPos = 0; |
132 | _phyPos = 0; | 137 | _phyPos = (UInt64)0 - 1; // we need Seek() for Stream |
133 | _needStartSeek = true; | 138 | _prevExtentIndex = 0; |
134 | } | 139 | } |
135 | }; | 140 | }; |
136 | 141 | ||
142 | |||
143 | |||
137 | class CLimitedSequentialOutStream: | 144 | class CLimitedSequentialOutStream: |
138 | public ISequentialOutStream, | 145 | public ISequentialOutStream, |
139 | public CMyUnknownImp | 146 | public CMyUnknownImp |
diff --git a/CPP/7zip/Common/PropId.cpp b/CPP/7zip/Common/PropId.cpp index 11d20d5..0e643e8 100644 --- a/CPP/7zip/Common/PropId.cpp +++ b/CPP/7zip/Common/PropId.cpp | |||
@@ -104,5 +104,12 @@ const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] = | |||
104 | VT_UI8, | 104 | VT_UI8, |
105 | VT_BOOL, | 105 | VT_BOOL, |
106 | VT_BSTR, | 106 | VT_BSTR, |
107 | VT_BSTR | 107 | VT_BSTR, |
108 | VT_BSTR, | ||
109 | VT_BOOL, | ||
110 | VT_FILETIME, // kpidChangeTime | ||
111 | VT_UI4, | ||
112 | VT_UI4, | ||
113 | VT_UI4, | ||
114 | VT_UI4 // kpidDeviceMinor | ||
108 | }; | 115 | }; |
diff --git a/CPP/7zip/Common/RegisterArc.h b/CPP/7zip/Common/RegisterArc.h index 3421ba1..a0384fa 100644 --- a/CPP/7zip/Common/RegisterArc.h +++ b/CPP/7zip/Common/RegisterArc.h | |||
@@ -7,7 +7,7 @@ | |||
7 | 7 | ||
8 | struct CArcInfo | 8 | struct CArcInfo |
9 | { | 9 | { |
10 | UInt16 Flags; | 10 | UInt32 Flags; |
11 | Byte Id; | 11 | Byte Id; |
12 | Byte SignatureSize; | 12 | Byte SignatureSize; |
13 | UInt16 SignatureOffset; | 13 | UInt16 SignatureOffset; |
@@ -17,6 +17,8 @@ struct CArcInfo | |||
17 | const char *Ext; | 17 | const char *Ext; |
18 | const char *AddExt; | 18 | const char *AddExt; |
19 | 19 | ||
20 | UInt32 TimeFlags; | ||
21 | |||
20 | Func_CreateInArchive CreateInArchive; | 22 | Func_CreateInArchive CreateInArchive; |
21 | Func_CreateOutArchive CreateOutArchive; | 23 | Func_CreateOutArchive CreateOutArchive; |
22 | Func_IsArc IsArc; | 24 | Func_IsArc IsArc; |
@@ -39,22 +41,22 @@ void RegisterArc(const CArcInfo *arcInfo) throw(); | |||
39 | #define IMP_CreateArcOut static IOutArchive *CreateArcOut() { return new CHandler(); } | 41 | #define IMP_CreateArcOut static IOutArchive *CreateArcOut() { return new CHandler(); } |
40 | #endif | 42 | #endif |
41 | 43 | ||
42 | #define REGISTER_ARC_V(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \ | 44 | #define REGISTER_ARC_V(n, e, ae, id, sigSize, sig, offs, flags, tf, crIn, crOut, isArc) \ |
43 | static const CArcInfo g_ArcInfo = { flags, id, sigSize, offs, sig, n, e, ae, crIn, crOut, isArc } ; \ | 45 | static const CArcInfo g_ArcInfo = { flags, id, sigSize, offs, sig, n, e, ae, tf, crIn, crOut, isArc } ; \ |
44 | 46 | ||
45 | #define REGISTER_ARC_R(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \ | 47 | #define REGISTER_ARC_R(n, e, ae, id, sigSize, sig, offs, flags, tf, crIn, crOut, isArc) \ |
46 | REGISTER_ARC_V(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \ | 48 | REGISTER_ARC_V (n, e, ae, id, sigSize, sig, offs, flags, tf, crIn, crOut, isArc) \ |
47 | struct CRegisterArc { CRegisterArc() { RegisterArc(&g_ArcInfo); }}; \ | 49 | struct CRegisterArc { CRegisterArc() { RegisterArc(&g_ArcInfo); }}; \ |
48 | static CRegisterArc g_RegisterArc; | 50 | static CRegisterArc g_RegisterArc; |
49 | 51 | ||
50 | 52 | ||
51 | #define REGISTER_ARC_I_CLS(cls, n, e, ae, id, sig, offs, flags, isArc) \ | 53 | #define REGISTER_ARC_I_CLS(cls, n, e, ae, id, sig, offs, flags, isArc) \ |
52 | IMP_CreateArcIn_2(cls) \ | 54 | IMP_CreateArcIn_2(cls) \ |
53 | REGISTER_ARC_R(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, NULL, isArc) | 55 | REGISTER_ARC_R(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, 0, CreateArc, NULL, isArc) |
54 | 56 | ||
55 | #define REGISTER_ARC_I_CLS_NO_SIG(cls, n, e, ae, id, offs, flags, isArc) \ | 57 | #define REGISTER_ARC_I_CLS_NO_SIG(cls, n, e, ae, id, offs, flags, isArc) \ |
56 | IMP_CreateArcIn_2(cls) \ | 58 | IMP_CreateArcIn_2(cls) \ |
57 | REGISTER_ARC_R(n, e, ae, id, 0, NULL, offs, flags, CreateArc, NULL, isArc) | 59 | REGISTER_ARC_R(n, e, ae, id, 0, NULL, offs, flags, 0, CreateArc, NULL, isArc) |
58 | 60 | ||
59 | #define REGISTER_ARC_I(n, e, ae, id, sig, offs, flags, isArc) \ | 61 | #define REGISTER_ARC_I(n, e, ae, id, sig, offs, flags, isArc) \ |
60 | REGISTER_ARC_I_CLS(CHandler(), n, e, ae, id, sig, offs, flags, isArc) | 62 | REGISTER_ARC_I_CLS(CHandler(), n, e, ae, id, sig, offs, flags, isArc) |
@@ -63,15 +65,15 @@ void RegisterArc(const CArcInfo *arcInfo) throw(); | |||
63 | REGISTER_ARC_I_CLS_NO_SIG(CHandler(), n, e, ae, id, offs, flags, isArc) | 65 | REGISTER_ARC_I_CLS_NO_SIG(CHandler(), n, e, ae, id, offs, flags, isArc) |
64 | 66 | ||
65 | 67 | ||
66 | #define REGISTER_ARC_IO(n, e, ae, id, sig, offs, flags, isArc) \ | 68 | #define REGISTER_ARC_IO(n, e, ae, id, sig, offs, flags, tf, isArc) \ |
67 | IMP_CreateArcIn \ | 69 | IMP_CreateArcIn \ |
68 | IMP_CreateArcOut \ | 70 | IMP_CreateArcOut \ |
69 | REGISTER_ARC_R(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, CreateArcOut, isArc) | 71 | REGISTER_ARC_R(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, tf, CreateArc, CreateArcOut, isArc) |
70 | 72 | ||
71 | #define REGISTER_ARC_IO_DECREMENT_SIG(n, e, ae, id, sig, offs, flags, isArc) \ | 73 | #define REGISTER_ARC_IO_DECREMENT_SIG(n, e, ae, id, sig, offs, flags, tf, isArc) \ |
72 | IMP_CreateArcIn \ | 74 | IMP_CreateArcIn \ |
73 | IMP_CreateArcOut \ | 75 | IMP_CreateArcOut \ |
74 | REGISTER_ARC_V(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, CreateArcOut, isArc) \ | 76 | REGISTER_ARC_V(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, tf, CreateArc, CreateArcOut, isArc) \ |
75 | struct CRegisterArcDecSig { CRegisterArcDecSig() { sig[0]--; RegisterArc(&g_ArcInfo); }}; \ | 77 | struct CRegisterArcDecSig { CRegisterArcDecSig() { sig[0]--; RegisterArc(&g_ArcInfo); }}; \ |
76 | static CRegisterArcDecSig g_RegisterArc; | 78 | static CRegisterArcDecSig g_RegisterArc; |
77 | 79 | ||
diff --git a/CPP/7zip/Common/UniqBlocks.cpp b/CPP/7zip/Common/UniqBlocks.cpp index 8f754e1..32dc276 100644 --- a/CPP/7zip/Common/UniqBlocks.cpp +++ b/CPP/7zip/Common/UniqBlocks.cpp | |||
@@ -11,10 +11,10 @@ unsigned CUniqBlocks::AddUniq(const Byte *data, size_t size) | |||
11 | unsigned left = 0, right = Sorted.Size(); | 11 | unsigned left = 0, right = Sorted.Size(); |
12 | while (left != right) | 12 | while (left != right) |
13 | { | 13 | { |
14 | unsigned mid = (left + right) / 2; | 14 | const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); |
15 | unsigned index = Sorted[mid]; | 15 | const unsigned index = Sorted[mid]; |
16 | const CByteBuffer &buf = Bufs[index]; | 16 | const CByteBuffer &buf = Bufs[index]; |
17 | size_t sizeMid = buf.Size(); | 17 | const size_t sizeMid = buf.Size(); |
18 | if (size < sizeMid) | 18 | if (size < sizeMid) |
19 | right = mid; | 19 | right = mid; |
20 | else if (size > sizeMid) | 20 | else if (size > sizeMid) |
@@ -23,7 +23,7 @@ unsigned CUniqBlocks::AddUniq(const Byte *data, size_t size) | |||
23 | { | 23 | { |
24 | if (size == 0) | 24 | if (size == 0) |
25 | return index; | 25 | return index; |
26 | int cmp = memcmp(data, buf, size); | 26 | const int cmp = memcmp(data, buf, size); |
27 | if (cmp == 0) | 27 | if (cmp == 0) |
28 | return index; | 28 | return index; |
29 | if (cmp < 0) | 29 | if (cmp < 0) |
diff --git a/CPP/7zip/Common/UniqBlocks.h b/CPP/7zip/Common/UniqBlocks.h index d6cd372..8479d68 100644 --- a/CPP/7zip/Common/UniqBlocks.h +++ b/CPP/7zip/Common/UniqBlocks.h | |||
@@ -3,9 +3,24 @@ | |||
3 | #ifndef __UNIQ_BLOCKS_H | 3 | #ifndef __UNIQ_BLOCKS_H |
4 | #define __UNIQ_BLOCKS_H | 4 | #define __UNIQ_BLOCKS_H |
5 | 5 | ||
6 | #include "../../Common/MyTypes.h" | ||
7 | #include "../../Common/MyBuffer.h" | 6 | #include "../../Common/MyBuffer.h" |
8 | #include "../../Common/MyVector.h" | 7 | #include "../../Common/MyString.h" |
8 | |||
9 | struct C_UInt32_UString_Map | ||
10 | { | ||
11 | CRecordVector<UInt32> Numbers; | ||
12 | UStringVector Strings; | ||
13 | |||
14 | void Add_UInt32(const UInt32 n) | ||
15 | { | ||
16 | Numbers.AddToUniqueSorted(n); | ||
17 | } | ||
18 | int Find(const UInt32 n) | ||
19 | { | ||
20 | return Numbers.FindInSorted(n); | ||
21 | } | ||
22 | }; | ||
23 | |||
9 | 24 | ||
10 | struct CUniqBlocks | 25 | struct CUniqBlocks |
11 | { | 26 | { |
diff --git a/CPP/7zip/Compress/BZip2Encoder.cpp b/CPP/7zip/Compress/BZip2Encoder.cpp index 25c3f04..62c15d6 100644 --- a/CPP/7zip/Compress/BZip2Encoder.cpp +++ b/CPP/7zip/Compress/BZip2Encoder.cpp | |||
@@ -98,8 +98,8 @@ THREAD_FUNC_RET_TYPE CThreadInfo::ThreadFunc() | |||
98 | bool needLeave = true; | 98 | bool needLeave = true; |
99 | try | 99 | try |
100 | { | 100 | { |
101 | UInt32 blockSize = Encoder->ReadRleBlock(m_Block); | 101 | const UInt32 blockSize = Encoder->ReadRleBlock(m_Block); |
102 | m_PackSize = Encoder->m_InStream.GetProcessedSize(); | 102 | m_UnpackSize = Encoder->m_InStream.GetProcessedSize(); |
103 | m_BlockIndex = Encoder->NextBlockIndex; | 103 | m_BlockIndex = Encoder->NextBlockIndex; |
104 | if (++Encoder->NextBlockIndex == Encoder->NumThreads) | 104 | if (++Encoder->NextBlockIndex == Encoder->NumThreads) |
105 | Encoder->NextBlockIndex = 0; | 105 | Encoder->NextBlockIndex = 0; |
@@ -222,7 +222,8 @@ UInt32 CEncoder::ReadRleBlock(Byte *buffer) | |||
222 | Byte prevByte; | 222 | Byte prevByte; |
223 | if (m_InStream.ReadByte(prevByte)) | 223 | if (m_InStream.ReadByte(prevByte)) |
224 | { | 224 | { |
225 | UInt32 blockSize = _props.BlockSizeMult * kBlockSizeStep - 1; | 225 | NumBlocks++; |
226 | const UInt32 blockSize = _props.BlockSizeMult * kBlockSizeStep - 1; | ||
226 | unsigned numReps = 1; | 227 | unsigned numReps = 1; |
227 | buffer[i++] = prevByte; | 228 | buffer[i++] = prevByte; |
228 | while (i < blockSize) // "- 1" to support RLE | 229 | while (i < blockSize) // "- 1" to support RLE |
@@ -722,8 +723,8 @@ HRESULT CThreadInfo::EncodeBlock3(UInt32 blockSize) | |||
722 | 723 | ||
723 | if (Encoder->Progress) | 724 | if (Encoder->Progress) |
724 | { | 725 | { |
725 | UInt64 unpackSize = Encoder->m_OutStream.GetProcessedSize(); | 726 | const UInt64 packSize = Encoder->m_OutStream.GetProcessedSize(); |
726 | res = Encoder->Progress->SetRatioInfo(&m_PackSize, &unpackSize); | 727 | res = Encoder->Progress->SetRatioInfo(&m_UnpackSize, &packSize); |
727 | } | 728 | } |
728 | 729 | ||
729 | Encoder->ThreadsInfo[blockIndex].CanWriteEvent.Set(); | 730 | Encoder->ThreadsInfo[blockIndex].CanWriteEvent.Set(); |
@@ -744,6 +745,7 @@ void CEncoder::WriteBytes(const Byte *data, UInt32 sizeInBits, Byte lastByte) | |||
744 | HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, | 745 | HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, |
745 | const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) | 746 | const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) |
746 | { | 747 | { |
748 | NumBlocks = 0; | ||
747 | #ifndef _7ZIP_ST | 749 | #ifndef _7ZIP_ST |
748 | Progress = progress; | 750 | Progress = progress; |
749 | RINOK(Create()); | 751 | RINOK(Create()); |
@@ -831,9 +833,9 @@ HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * | |||
831 | RINOK(ti.EncodeBlock3(blockSize)); | 833 | RINOK(ti.EncodeBlock3(blockSize)); |
832 | if (progress) | 834 | if (progress) |
833 | { | 835 | { |
834 | UInt64 packSize = m_InStream.GetProcessedSize(); | 836 | const UInt64 unpackSize = m_InStream.GetProcessedSize(); |
835 | UInt64 unpackSize = m_OutStream.GetProcessedSize(); | 837 | const UInt64 packSize = m_OutStream.GetProcessedSize(); |
836 | RINOK(progress->SetRatioInfo(&packSize, &unpackSize)); | 838 | RINOK(progress->SetRatioInfo(&unpackSize, &packSize)); |
837 | } | 839 | } |
838 | } | 840 | } |
839 | } | 841 | } |
@@ -845,7 +847,10 @@ HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * | |||
845 | WriteByte(kFinSig5); | 847 | WriteByte(kFinSig5); |
846 | 848 | ||
847 | WriteCrc(CombinedCrc.GetDigest()); | 849 | WriteCrc(CombinedCrc.GetDigest()); |
848 | return Flush(); | 850 | RINOK(Flush()); |
851 | if (!m_InStream.WasFinished()) | ||
852 | return E_FAIL; | ||
853 | return S_OK; | ||
849 | } | 854 | } |
850 | 855 | ||
851 | STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, | 856 | STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, |
diff --git a/CPP/7zip/Compress/BZip2Encoder.h b/CPP/7zip/Compress/BZip2Encoder.h index 5e63a73..e2828a9 100644 --- a/CPP/7zip/Compress/BZip2Encoder.h +++ b/CPP/7zip/Compress/BZip2Encoder.h | |||
@@ -129,7 +129,7 @@ public: | |||
129 | // it's not member of this thread. We just need one event per thread | 129 | // it's not member of this thread. We just need one event per thread |
130 | NWindows::NSynchronization::CAutoResetEvent CanWriteEvent; | 130 | NWindows::NSynchronization::CAutoResetEvent CanWriteEvent; |
131 | 131 | ||
132 | UInt64 m_PackSize; | 132 | UInt64 m_UnpackSize; |
133 | 133 | ||
134 | Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. | 134 | Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. |
135 | HRESULT Create(); | 135 | HRESULT Create(); |
@@ -195,6 +195,10 @@ public: | |||
195 | CThreadInfo ThreadsInfo; | 195 | CThreadInfo ThreadsInfo; |
196 | #endif | 196 | #endif |
197 | 197 | ||
198 | UInt64 NumBlocks; | ||
199 | |||
200 | UInt64 GetInProcessedSize() const { return m_InStream.GetProcessedSize(); } | ||
201 | |||
198 | UInt32 ReadRleBlock(Byte *buf); | 202 | UInt32 ReadRleBlock(Byte *buf); |
199 | void WriteBytes(const Byte *data, UInt32 sizeInBits, Byte lastByte); | 203 | void WriteBytes(const Byte *data, UInt32 sizeInBits, Byte lastByte); |
200 | 204 | ||
diff --git a/CPP/7zip/Compress/BitlDecoder.h b/CPP/7zip/Compress/BitlDecoder.h index e85942c..825864d 100644 --- a/CPP/7zip/Compress/BitlDecoder.h +++ b/CPP/7zip/Compress/BitlDecoder.h | |||
@@ -155,6 +155,10 @@ public: | |||
155 | MY_FORCE_INLINE | 155 | MY_FORCE_INLINE |
156 | bool ReadAlignedByte_FromBuf(Byte &b) | 156 | bool ReadAlignedByte_FromBuf(Byte &b) |
157 | { | 157 | { |
158 | if (this->_stream.NumExtraBytes != 0) | ||
159 | if (this->_stream.NumExtraBytes >= 4 | ||
160 | || kNumBigValueBits - this->_bitPos <= (this->_stream.NumExtraBytes << 3)) | ||
161 | return false; | ||
158 | if (this->_bitPos == kNumBigValueBits) | 162 | if (this->_bitPos == kNumBigValueBits) |
159 | return this->_stream.ReadByte_FromBuf(b); | 163 | return this->_stream.ReadByte_FromBuf(b); |
160 | b = (Byte)(_normalValue & 0xFF); | 164 | b = (Byte)(_normalValue & 0xFF); |
diff --git a/CPP/7zip/Compress/DeflateDecoder.cpp b/CPP/7zip/Compress/DeflateDecoder.cpp index 0206ce8..e4f66b7 100644 --- a/CPP/7zip/Compress/DeflateDecoder.cpp +++ b/CPP/7zip/Compress/DeflateDecoder.cpp | |||
@@ -426,7 +426,6 @@ STDMETHODIMP CCoder::ReadUnusedFromInBuf(void *data, UInt32 size, UInt32 *proces | |||
426 | { | 426 | { |
427 | AlignToByte(); | 427 | AlignToByte(); |
428 | UInt32 i = 0; | 428 | UInt32 i = 0; |
429 | if (!m_InBitStream.ExtraBitsWereRead()) | ||
430 | { | 429 | { |
431 | for (i = 0; i < size; i++) | 430 | for (i = 0; i < size; i++) |
432 | { | 431 | { |
diff --git a/CPP/7zip/Compress/LzmaEncoder.cpp b/CPP/7zip/Compress/LzmaEncoder.cpp index 4b3acd3..dabd77a 100644 --- a/CPP/7zip/Compress/LzmaEncoder.cpp +++ b/CPP/7zip/Compress/LzmaEncoder.cpp | |||
@@ -9,14 +9,15 @@ | |||
9 | 9 | ||
10 | #include "LzmaEncoder.h" | 10 | #include "LzmaEncoder.h" |
11 | 11 | ||
12 | #include "../../Common/IntToString.h" | ||
13 | #include "../../Windows/TimeUtils.h" | ||
14 | |||
15 | // #define LOG_LZMA_THREADS | 12 | // #define LOG_LZMA_THREADS |
16 | 13 | ||
17 | #ifdef LOG_LZMA_THREADS | 14 | #ifdef LOG_LZMA_THREADS |
15 | |||
18 | #include <stdio.h> | 16 | #include <stdio.h> |
19 | 17 | ||
18 | #include "../../Common/IntToString.h" | ||
19 | #include "../../Windows/TimeUtils.h" | ||
20 | |||
20 | EXTERN_C_BEGIN | 21 | EXTERN_C_BEGIN |
21 | void LzmaEnc_GetLzThreads(CLzmaEncHandle pp, HANDLE lz_threads[2]); | 22 | void LzmaEnc_GetLzThreads(CLzmaEncHandle pp, HANDLE lz_threads[2]); |
22 | EXTERN_C_END | 23 | EXTERN_C_END |
diff --git a/CPP/7zip/Guid.txt b/CPP/7zip/Guid.txt index 3b654bc..8fcdd84 100644 --- a/CPP/7zip/Guid.txt +++ b/CPP/7zip/Guid.txt | |||
@@ -19,6 +19,7 @@ | |||
19 | 0F IOutFolderArchive | 19 | 0F IOutFolderArchive |
20 | 10 IFolderArchiveUpdateCallback2 | 20 | 10 IFolderArchiveUpdateCallback2 |
21 | 11 IFolderScanProgress | 21 | 11 IFolderScanProgress |
22 | 12 IFolderSetZoneIdMode | ||
22 | 23 | ||
23 | 20 IFileExtractCallback.h::IGetProp | 24 | 20 IFileExtractCallback.h::IGetProp |
24 | 30 IFileExtractCallback.h::IFolderExtractToStreamCallback (old) | 25 | 30 IFileExtractCallback.h::IFolderExtractToStreamCallback (old) |
@@ -34,6 +35,7 @@ | |||
34 | 07 IOutStreamFinish | 35 | 07 IOutStreamFinish |
35 | 08 IStreamGetProps | 36 | 08 IStreamGetProps |
36 | 09 IStreamGetProps2 | 37 | 09 IStreamGetProps2 |
38 | 0A IStreamGetProp | ||
37 | 39 | ||
38 | 40 | ||
39 | 04 ICoder.h | 41 | 04 ICoder.h |
@@ -106,6 +108,8 @@ | |||
106 | 82 IArchiveUpdateCallback2 | 108 | 82 IArchiveUpdateCallback2 |
107 | 83 IArchiveUpdateCallbackFile | 109 | 83 IArchiveUpdateCallbackFile |
108 | 84 IArchiveGetDiskProperty | 110 | 84 IArchiveGetDiskProperty |
111 | 85 IArchiveUpdateCallbackArcProp (Reserved) | ||
112 | |||
109 | 113 | ||
110 | A0 IOutArchive | 114 | A0 IOutArchive |
111 | 115 | ||
@@ -169,6 +173,10 @@ Handler GUIDs: | |||
169 | 0C xz | 173 | 0C xz |
170 | 0D ppmd | 174 | 0D ppmd |
171 | 175 | ||
176 | C0 AVB | ||
177 | C1 LP | ||
178 | C2 Sparse | ||
179 | C3 APFS | ||
172 | C4 Vhdx | 180 | C4 Vhdx |
173 | C5 Base64 | 181 | C5 Base64 |
174 | C6 COFF | 182 | C6 COFF |
diff --git a/CPP/7zip/IStream.h b/CPP/7zip/IStream.h index 48c67c1..2793a1e 100644 --- a/CPP/7zip/IStream.h +++ b/CPP/7zip/IStream.h | |||
@@ -133,4 +133,11 @@ STREAM_INTERFACE(IStreamGetProps2, 0x09) | |||
133 | STDMETHOD(GetProps2)(CStreamFileProps *props) PURE; | 133 | STDMETHOD(GetProps2)(CStreamFileProps *props) PURE; |
134 | }; | 134 | }; |
135 | 135 | ||
136 | |||
137 | STREAM_INTERFACE(IStreamGetProp, 0x0a) | ||
138 | { | ||
139 | STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) PURE; | ||
140 | STDMETHOD(ReloadProps)() PURE; | ||
141 | }; | ||
142 | |||
136 | #endif | 143 | #endif |
diff --git a/CPP/7zip/PropID.h b/CPP/7zip/PropID.h index b818954..2da636f 100644 --- a/CPP/7zip/PropID.h +++ b/CPP/7zip/PropID.h | |||
@@ -105,7 +105,11 @@ enum | |||
105 | kpidCopyLink, | 105 | kpidCopyLink, |
106 | kpidArcFileName, | 106 | kpidArcFileName, |
107 | kpidIsHash, | 107 | kpidIsHash, |
108 | 108 | kpidChangeTime, | |
109 | kpidUserId, | ||
110 | kpidGroupId, | ||
111 | kpidDeviceMajor, | ||
112 | kpidDeviceMinor, | ||
109 | 113 | ||
110 | kpid_NUM_DEFINED, | 114 | kpid_NUM_DEFINED, |
111 | 115 | ||
@@ -127,4 +131,46 @@ const UInt32 kpv_ErrorFlags_DataError = 1 << 9; | |||
127 | const UInt32 kpv_ErrorFlags_CrcError = 1 << 10; | 131 | const UInt32 kpv_ErrorFlags_CrcError = 1 << 10; |
128 | // const UInt32 kpv_ErrorFlags_Unsupported = 1 << 11; | 132 | // const UInt32 kpv_ErrorFlags_Unsupported = 1 << 11; |
129 | 133 | ||
134 | /* | ||
135 | linux ctime : | ||
136 | file metadata was last changed. | ||
137 | changing the file modification time | ||
138 | counts as a metadata change, so will also have the side effect of updating the ctime. | ||
139 | |||
140 | PROPVARIANT for timestamps in 7-Zip: | ||
141 | { | ||
142 | vt = VT_FILETIME | ||
143 | wReserved1: set precision level | ||
144 | 0 : base value (backward compatibility value) | ||
145 | only filetime is used (7 digits precision). | ||
146 | wReserved2 and wReserved3 can contain random data | ||
147 | 1 : Unix (1 sec) | ||
148 | 2 : DOS (2 sec) | ||
149 | 3 : High Precision (1 ns) | ||
150 | 16 - 3 : (reserved) = 1 day | ||
151 | 16 - 2 : (reserved) = 1 hour | ||
152 | 16 - 1 : (reserved) = 1 minute | ||
153 | 16 + 0 : 1 sec (0 digits after point) | ||
154 | 16 + (1,2,3,4,5,6,7,8,9) : set subsecond precision level : | ||
155 | (number of decimal digits after point) | ||
156 | 16 + 9 : 1 ns (9 digits after point) | ||
157 | wReserved2 = ns % 100 : if (8 or 9 digits pecision) | ||
158 | = 0 : if not (8 or 9 digits pecision) | ||
159 | wReserved3 = 0; | ||
160 | filetime | ||
161 | } | ||
162 | |||
163 | NOTE: TAR-PAX archives created by GNU TAR don't keep | ||
164 | whole information about original level of precision, | ||
165 | and timestamp are stored in reduced form, where tail zero | ||
166 | digits after point are removed. | ||
167 | So 7-Zip can return different precision levels for different items for such TAR archives. | ||
168 | */ | ||
169 | |||
170 | /* | ||
171 | TimePrec returned by IOutArchive::GetFileTimeType() | ||
172 | is used only for updating, when we compare MTime timestamp | ||
173 | from archive with timestamp from directory. | ||
174 | */ | ||
175 | |||
130 | #endif | 176 | #endif |
diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp index cdb0e5d..cc20c11 100644 --- a/CPP/7zip/UI/Agent/Agent.cpp +++ b/CPP/7zip/UI/Agent/Agent.cpp | |||
@@ -25,6 +25,10 @@ using namespace NWindows; | |||
25 | 25 | ||
26 | CCodecs *g_CodecsObj; | 26 | CCodecs *g_CodecsObj; |
27 | 27 | ||
28 | static const bool k_keepEmptyDirPrefixes = | ||
29 | false; // 22.00 | ||
30 | // true; // 21.07 | ||
31 | |||
28 | #ifdef EXTERNAL_CODECS | 32 | #ifdef EXTERNAL_CODECS |
29 | CExternalCodecs g_ExternalCodecs; | 33 | CExternalCodecs g_ExternalCodecs; |
30 | const CExternalCodecs *g_ExternalCodecs_Ptr; | 34 | const CExternalCodecs *g_ExternalCodecs_Ptr; |
@@ -114,9 +118,9 @@ void CAgentFolder::LoadFolder(unsigned proxyDirIndex) | |||
114 | item.Index = i; | 118 | item.Index = i; |
115 | _items.Add(item); | 119 | _items.Add(item); |
116 | const CProxyFile2 &file = _proxy2->Files[dir.Items[i]]; | 120 | const CProxyFile2 &file = _proxy2->Files[dir.Items[i]]; |
117 | if (file.DirIndex >= 0) | 121 | if (file.DirIndex != -1) |
118 | LoadFolder(file.DirIndex); | 122 | LoadFolder(file.DirIndex); |
119 | if (_loadAltStreams && file.AltDirIndex >= 0) | 123 | if (_loadAltStreams && file.AltDirIndex != -1) |
120 | LoadFolder(file.AltDirIndex); | 124 | LoadFolder(file.AltDirIndex); |
121 | } | 125 | } |
122 | return; | 126 | return; |
@@ -211,21 +215,21 @@ void CAgentFolder::GetPrefix(UInt32 index, UString &prefix) const | |||
211 | unsigned len = 0; | 215 | unsigned len = 0; |
212 | while (proxyIndex != _proxyDirIndex && proxyIndex >= k_Proxy2_NumRootDirs) | 216 | while (proxyIndex != _proxyDirIndex && proxyIndex >= k_Proxy2_NumRootDirs) |
213 | { | 217 | { |
214 | const CProxyFile2 &file = _proxy2->Files[_proxy2->Dirs[proxyIndex].ArcIndex]; | 218 | const CProxyFile2 &file = _proxy2->Files[(unsigned)_proxy2->Dirs[proxyIndex].ArcIndex]; |
215 | len += file.NameLen + 1; | 219 | len += file.NameLen + 1; |
216 | proxyIndex = (file.Parent < 0) ? 0 : _proxy2->Files[file.Parent].GetDirIndex(file.IsAltStream); | 220 | proxyIndex = (file.Parent == -1) ? 0 : _proxy2->Files[(unsigned)file.Parent].GetDirIndex(file.IsAltStream); |
217 | } | 221 | } |
218 | 222 | ||
219 | wchar_t *p = prefix.GetBuf_SetEnd(len) + len; | 223 | wchar_t *p = prefix.GetBuf_SetEnd(len) + len; |
220 | proxyIndex = item.DirIndex; | 224 | proxyIndex = item.DirIndex; |
221 | while (proxyIndex != _proxyDirIndex && proxyIndex >= k_Proxy2_NumRootDirs) | 225 | while (proxyIndex != _proxyDirIndex && proxyIndex >= k_Proxy2_NumRootDirs) |
222 | { | 226 | { |
223 | const CProxyFile2 &file = _proxy2->Files[_proxy2->Dirs[proxyIndex].ArcIndex]; | 227 | const CProxyFile2 &file = _proxy2->Files[(unsigned)_proxy2->Dirs[proxyIndex].ArcIndex]; |
224 | p--; | 228 | p--; |
225 | *p = WCHAR_PATH_SEPARATOR; | 229 | *p = WCHAR_PATH_SEPARATOR; |
226 | p -= file.NameLen; | 230 | p -= file.NameLen; |
227 | wmemcpy(p, file.Name, file.NameLen); | 231 | wmemcpy(p, file.Name, file.NameLen); |
228 | proxyIndex = (file.Parent < 0) ? 0 : _proxy2->Files[file.Parent].GetDirIndex(file.IsAltStream); | 232 | proxyIndex = (file.Parent == -1) ? 0 : _proxy2->Files[(unsigned)file.Parent].GetDirIndex(file.IsAltStream); |
229 | } | 233 | } |
230 | } | 234 | } |
231 | else | 235 | else |
@@ -327,7 +331,7 @@ STDMETHODIMP CAgentFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT | |||
327 | /* | 331 | /* |
328 | if (propID == kpidNumAltStreams) | 332 | if (propID == kpidNumAltStreams) |
329 | { | 333 | { |
330 | if (item.AltDirIndex >= 0) | 334 | if (item.AltDirIndex != -1) |
331 | prop = _proxy2->Dirs[item.AltDirIndex].Items.Size(); | 335 | prop = _proxy2->Dirs[item.AltDirIndex].Items.Size(); |
332 | } | 336 | } |
333 | else | 337 | else |
@@ -887,12 +891,12 @@ STDMETHODIMP CAgentFolder::BindToFolder(const wchar_t *name, IFolderFolder **res | |||
887 | if (_proxy2) | 891 | if (_proxy2) |
888 | { | 892 | { |
889 | int index = _proxy2->FindItem(_proxyDirIndex, name, true); | 893 | int index = _proxy2->FindItem(_proxyDirIndex, name, true); |
890 | if (index < 0) | 894 | if (index == -1) |
891 | return E_INVALIDARG; | 895 | return E_INVALIDARG; |
892 | return BindToFolder_Internal(_proxy2->Files[_proxy2->Dirs[_proxyDirIndex].Items[index]].DirIndex, resultFolder); | 896 | return BindToFolder_Internal(_proxy2->Files[_proxy2->Dirs[_proxyDirIndex].Items[index]].DirIndex, resultFolder); |
893 | } | 897 | } |
894 | int index = _proxy->FindSubDir(_proxyDirIndex, name); | 898 | int index = _proxy->FindSubDir(_proxyDirIndex, name); |
895 | if (index < 0) | 899 | if (index == -1) |
896 | return E_INVALIDARG; | 900 | return E_INVALIDARG; |
897 | return BindToFolder_Internal(index, resultFolder); | 901 | return BindToFolder_Internal(index, resultFolder); |
898 | COM_TRY_END | 902 | COM_TRY_END |
@@ -956,7 +960,7 @@ STDMETHODIMP CAgentFolder::BindToAltStreams(UInt32 index, IFolderFolder **result | |||
956 | { | 960 | { |
957 | unsigned arcIndex = _proxy2->Dirs[_proxyDirIndex].ArcIndex; | 961 | unsigned arcIndex = _proxy2->Dirs[_proxyDirIndex].ArcIndex; |
958 | const CProxyFile2 &item = _proxy2->Files[arcIndex]; | 962 | const CProxyFile2 &item = _proxy2->Files[arcIndex]; |
959 | if (item.AltDirIndex < 0) | 963 | if (item.AltDirIndex == -1) |
960 | return S_OK; | 964 | return S_OK; |
961 | altDirIndex = item.AltDirIndex; | 965 | altDirIndex = item.AltDirIndex; |
962 | // parentFolder = _parentFolder; | 966 | // parentFolder = _parentFolder; |
@@ -972,7 +976,7 @@ STDMETHODIMP CAgentFolder::BindToAltStreams(UInt32 index, IFolderFolder **result | |||
972 | SET_realIndex_AND_dir_2 | 976 | SET_realIndex_AND_dir_2 |
973 | unsigned arcIndex = dir->Items[realIndex]; | 977 | unsigned arcIndex = dir->Items[realIndex]; |
974 | const CProxyFile2 &item = _proxy2->Files[arcIndex]; | 978 | const CProxyFile2 &item = _proxy2->Files[arcIndex]; |
975 | if (item.AltDirIndex < 0) | 979 | if (item.AltDirIndex == -1) |
976 | return S_OK; | 980 | return S_OK; |
977 | return BindToAltStreams_Internal(item.AltDirIndex, resultFolder); | 981 | return BindToAltStreams_Internal(item.AltDirIndex, resultFolder); |
978 | } | 982 | } |
@@ -1000,7 +1004,7 @@ STDMETHODIMP CAgentFolder::BindToAltStreams(const wchar_t *name, IFolderFolder * | |||
1000 | FOR_VECTOR (i, dir.Items) | 1004 | FOR_VECTOR (i, dir.Items) |
1001 | { | 1005 | { |
1002 | const CProxyFile2 &file = _proxy2->Files[dir.Items[i]]; | 1006 | const CProxyFile2 &file = _proxy2->Files[dir.Items[i]]; |
1003 | if (file.AltDirIndex >= 0) | 1007 | if (file.AltDirIndex != -1) |
1004 | if (CompareFileNames(file.Name, name) == 0) | 1008 | if (CompareFileNames(file.Name, name) == 0) |
1005 | return BindToAltStreams_Internal(file.AltDirIndex, resultFolder); | 1009 | return BindToAltStreams_Internal(file.AltDirIndex, resultFolder); |
1006 | } | 1010 | } |
@@ -1036,7 +1040,7 @@ STDMETHODIMP CAgentFolder::AreAltStreamsSupported(UInt32 index, Int32 *isSupport | |||
1036 | arcIndex = dir->Items[realIndex]; | 1040 | arcIndex = dir->Items[realIndex]; |
1037 | } | 1041 | } |
1038 | 1042 | ||
1039 | if (_proxy2->Files[arcIndex].AltDirIndex >= 0) | 1043 | if (_proxy2->Files[arcIndex].AltDirIndex != -1) |
1040 | *isSupported = BoolToInt(true); | 1044 | *isSupported = BoolToInt(true); |
1041 | return S_OK; | 1045 | return S_OK; |
1042 | } | 1046 | } |
@@ -1062,18 +1066,18 @@ STDMETHODIMP CAgentFolder::BindToParentFolder(IFolderFolder **resultFolder) | |||
1062 | else | 1066 | else |
1063 | { | 1067 | { |
1064 | const CProxyDir2 &fold = _proxy2->Dirs[_proxyDirIndex]; | 1068 | const CProxyDir2 &fold = _proxy2->Dirs[_proxyDirIndex]; |
1065 | const CProxyFile2 &file = _proxy2->Files[fold.ArcIndex]; | 1069 | const CProxyFile2 &file = _proxy2->Files[(unsigned)fold.ArcIndex]; |
1066 | int parentIndex = file.Parent; | 1070 | const int parentIndex = file.Parent; |
1067 | if (parentIndex < 0) | 1071 | if (parentIndex == -1) |
1068 | proxyDirIndex = k_Proxy2_RootDirIndex; | 1072 | proxyDirIndex = k_Proxy2_RootDirIndex; |
1069 | else | 1073 | else |
1070 | proxyDirIndex = _proxy2->Files[parentIndex].DirIndex; | 1074 | proxyDirIndex = _proxy2->Files[(unsigned)parentIndex].DirIndex; |
1071 | } | 1075 | } |
1072 | } | 1076 | } |
1073 | else | 1077 | else |
1074 | { | 1078 | { |
1075 | int parent = _proxy->Dirs[_proxyDirIndex].ParentDir; | 1079 | int parent = _proxy->Dirs[_proxyDirIndex].ParentDir; |
1076 | if (parent < 0) | 1080 | if (parent == -1) |
1077 | return S_OK; | 1081 | return S_OK; |
1078 | proxyDirIndex = parent; | 1082 | proxyDirIndex = parent; |
1079 | } | 1083 | } |
@@ -1239,8 +1243,8 @@ STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) | |||
1239 | const CProxyDir2 &dir = _proxy2->Dirs[_proxyDirIndex]; | 1243 | const CProxyDir2 &dir = _proxy2->Dirs[_proxyDirIndex]; |
1240 | if (propID == kpidName) | 1244 | if (propID == kpidName) |
1241 | { | 1245 | { |
1242 | if (dir.ArcIndex >= 0) | 1246 | if (dir.ArcIndex != -1) |
1243 | prop = _proxy2->Files[dir.ArcIndex].Name; | 1247 | prop = _proxy2->Files[(unsigned)dir.ArcIndex].Name; |
1244 | } | 1248 | } |
1245 | else if (propID == kpidPath) | 1249 | else if (propID == kpidPath) |
1246 | { | 1250 | { |
@@ -1477,8 +1481,8 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices, | |||
1477 | false, // multiArchives | 1481 | false, // multiArchives |
1478 | pathMode, | 1482 | pathMode, |
1479 | overwriteMode, | 1483 | overwriteMode, |
1480 | true // keepEmptyDirPrefixes | 1484 | _zoneMode, |
1481 | ); | 1485 | k_keepEmptyDirPrefixes); |
1482 | 1486 | ||
1483 | if (extractCallback2) | 1487 | if (extractCallback2) |
1484 | extractCallback2->SetTotal(_agentSpec->GetArc().GetEstmatedPhySize()); | 1488 | extractCallback2->SetTotal(_agentSpec->GetArc().GetEstmatedPhySize()); |
@@ -1500,6 +1504,15 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices, | |||
1500 | 1504 | ||
1501 | extractNtOptions.ReplaceColonForAltStream = IntToBool(replaceAltStreamColon); | 1505 | extractNtOptions.ReplaceColonForAltStream = IntToBool(replaceAltStreamColon); |
1502 | 1506 | ||
1507 | extractCallbackSpec->InitBeforeNewArchive(); | ||
1508 | |||
1509 | #if defined(_WIN32) && !defined(UNDER_CE) | ||
1510 | if (_zoneMode != NExtract::NZoneIdMode::kNone) | ||
1511 | { | ||
1512 | ReadZoneFile_Of_BaseFile(us2fs(_agentSpec->_archiveFilePath), extractCallbackSpec->ZoneBuf); | ||
1513 | } | ||
1514 | #endif | ||
1515 | |||
1503 | extractCallbackSpec->Init( | 1516 | extractCallbackSpec->Init( |
1504 | extractNtOptions, | 1517 | extractNtOptions, |
1505 | NULL, &_agentSpec->GetArc(), | 1518 | NULL, &_agentSpec->GetArc(), |
@@ -1645,8 +1658,8 @@ STDMETHODIMP CAgent::Open( | |||
1645 | CArc &arc = _archiveLink.Arcs.Back(); | 1658 | CArc &arc = _archiveLink.Arcs.Back(); |
1646 | if (!inStream) | 1659 | if (!inStream) |
1647 | { | 1660 | { |
1648 | arc.MTimeDefined = !fi.IsDevice; | 1661 | arc.MTime.Set_From_FiTime(fi.MTime); |
1649 | arc.MTime = fi.MTime; | 1662 | arc.MTime.Def = !fi.IsDevice; |
1650 | } | 1663 | } |
1651 | 1664 | ||
1652 | ArchiveType = GetTypeOfArc(arc); | 1665 | ArchiveType = GetTypeOfArc(arc); |
@@ -1783,8 +1796,8 @@ STDMETHODIMP CAgent::Extract( | |||
1783 | false, // multiArchives | 1796 | false, // multiArchives |
1784 | pathMode, | 1797 | pathMode, |
1785 | overwriteMode, | 1798 | overwriteMode, |
1786 | true // keepEmptyDirPrefixes | 1799 | NExtract::NZoneIdMode::kNone, |
1787 | ); | 1800 | k_keepEmptyDirPrefixes); |
1788 | 1801 | ||
1789 | CExtractNtOptions extractNtOptions; | 1802 | CExtractNtOptions extractNtOptions; |
1790 | extractNtOptions.AltStreams.Val = true; // change it!!! | 1803 | extractNtOptions.AltStreams.Val = true; // change it!!! |
diff --git a/CPP/7zip/UI/Agent/Agent.h b/CPP/7zip/UI/Agent/Agent.h index e9fe410..8e8a4c7 100644 --- a/CPP/7zip/UI/Agent/Agent.h +++ b/CPP/7zip/UI/Agent/Agent.h | |||
@@ -58,7 +58,7 @@ class CAgentFolder: | |||
58 | public IArchiveFolder, | 58 | public IArchiveFolder, |
59 | public IArchiveFolderInternal, | 59 | public IArchiveFolderInternal, |
60 | public IInArchiveGetStream, | 60 | public IInArchiveGetStream, |
61 | // public IFolderSetReplaceAltStreamCharsMode, | 61 | public IFolderSetZoneIdMode, |
62 | #ifdef NEW_FOLDER_INTERFACE | 62 | #ifdef NEW_FOLDER_INTERFACE |
63 | public IFolderOperations, | 63 | public IFolderOperations, |
64 | public IFolderSetFlatMode, | 64 | public IFolderSetFlatMode, |
@@ -78,7 +78,7 @@ public: | |||
78 | MY_QUERYINTERFACE_ENTRY(IArchiveFolder) | 78 | MY_QUERYINTERFACE_ENTRY(IArchiveFolder) |
79 | MY_QUERYINTERFACE_ENTRY(IArchiveFolderInternal) | 79 | MY_QUERYINTERFACE_ENTRY(IArchiveFolderInternal) |
80 | MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream) | 80 | MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream) |
81 | // MY_QUERYINTERFACE_ENTRY(IFolderSetReplaceAltStreamCharsMode) | 81 | MY_QUERYINTERFACE_ENTRY(IFolderSetZoneIdMode) |
82 | #ifdef NEW_FOLDER_INTERFACE | 82 | #ifdef NEW_FOLDER_INTERFACE |
83 | MY_QUERYINTERFACE_ENTRY(IFolderOperations) | 83 | MY_QUERYINTERFACE_ENTRY(IFolderOperations) |
84 | MY_QUERYINTERFACE_ENTRY(IFolderSetFlatMode) | 84 | MY_QUERYINTERFACE_ENTRY(IFolderSetFlatMode) |
@@ -92,7 +92,7 @@ public: | |||
92 | void GetRealIndices(const UInt32 *indices, UInt32 numItems, | 92 | void GetRealIndices(const UInt32 *indices, UInt32 numItems, |
93 | bool includeAltStreams, bool includeFolderSubItemsInFlatMode, CUIntVector &realIndices) const; | 93 | bool includeAltStreams, bool includeFolderSubItemsInFlatMode, CUIntVector &realIndices) const; |
94 | 94 | ||
95 | // INTERFACE_FolderSetReplaceAltStreamCharsMode(;) | 95 | INTERFACE_IFolderSetZoneIdMode(;) |
96 | 96 | ||
97 | INTERFACE_FolderFolder(;) | 97 | INTERFACE_FolderFolder(;) |
98 | INTERFACE_FolderAltStreams(;) | 98 | INTERFACE_FolderAltStreams(;) |
@@ -123,6 +123,7 @@ public: | |||
123 | _isAltStreamFolder(false), | 123 | _isAltStreamFolder(false), |
124 | _flatMode(false), | 124 | _flatMode(false), |
125 | _loadAltStreams(false) // _loadAltStreams alt streams works in flat mode, but we don't use it now | 125 | _loadAltStreams(false) // _loadAltStreams alt streams works in flat mode, but we don't use it now |
126 | , _zoneMode(NExtract::NZoneIdMode::kNone) | ||
126 | /* , _replaceAltStreamCharsMode(0) */ | 127 | /* , _replaceAltStreamCharsMode(0) */ |
127 | {} | 128 | {} |
128 | 129 | ||
@@ -169,6 +170,7 @@ public: | |||
169 | bool _flatMode; | 170 | bool _flatMode; |
170 | bool _loadAltStreams; // in Flat mode | 171 | bool _loadAltStreams; // in Flat mode |
171 | // Int32 _replaceAltStreamCharsMode; | 172 | // Int32 _replaceAltStreamCharsMode; |
173 | NExtract::NZoneIdMode::EEnum _zoneMode; | ||
172 | }; | 174 | }; |
173 | 175 | ||
174 | class CAgent: | 176 | class CAgent: |
diff --git a/CPP/7zip/UI/Agent/AgentOut.cpp b/CPP/7zip/UI/Agent/AgentOut.cpp index fae0e22..da8da6c 100644 --- a/CPP/7zip/UI/Agent/AgentOut.cpp +++ b/CPP/7zip/UI/Agent/AgentOut.cpp | |||
@@ -12,6 +12,8 @@ | |||
12 | 12 | ||
13 | #include "../../Common/FileStreams.h" | 13 | #include "../../Common/FileStreams.h" |
14 | 14 | ||
15 | #include "../../Archive/Common/ItemNameUtils.h" | ||
16 | |||
15 | #include "Agent.h" | 17 | #include "Agent.h" |
16 | #include "UpdateCallbackAgent.h" | 18 | #include "UpdateCallbackAgent.h" |
17 | 19 | ||
@@ -67,8 +69,8 @@ static HRESULT EnumerateArchiveItems(CAgent *agent, | |||
67 | unsigned arcIndex = item.SubFiles[i]; | 69 | unsigned arcIndex = item.SubFiles[i]; |
68 | const CProxyFile &fileItem = agent->_proxy->Files[arcIndex]; | 70 | const CProxyFile &fileItem = agent->_proxy->Files[arcIndex]; |
69 | CArcItem ai; | 71 | CArcItem ai; |
70 | RINOK(agent->GetArc().GetItemMTime(arcIndex, ai.MTime, ai.MTimeDefined)); | 72 | RINOK(agent->GetArc().GetItem_MTime(arcIndex, ai.MTime)); |
71 | RINOK(agent->GetArc().GetItemSize(arcIndex, ai.Size, ai.SizeDefined)); | 73 | RINOK(agent->GetArc().GetItem_Size(arcIndex, ai.Size, ai.Size_Defined)); |
72 | ai.IsDir = false; | 74 | ai.IsDir = false; |
73 | ai.Name = prefix + fileItem.Name; | 75 | ai.Name = prefix + fileItem.Name; |
74 | ai.Censored = true; // test it | 76 | ai.Censored = true; // test it |
@@ -83,9 +85,9 @@ static HRESULT EnumerateArchiveItems(CAgent *agent, | |||
83 | if (dirItem.IsLeaf()) | 85 | if (dirItem.IsLeaf()) |
84 | { | 86 | { |
85 | CArcItem ai; | 87 | CArcItem ai; |
86 | RINOK(agent->GetArc().GetItemMTime(dirItem.ArcIndex, ai.MTime, ai.MTimeDefined)); | 88 | RINOK(agent->GetArc().GetItem_MTime(dirItem.ArcIndex, ai.MTime)); |
87 | ai.IsDir = true; | 89 | ai.IsDir = true; |
88 | ai.SizeDefined = false; | 90 | ai.Size_Defined = false; |
89 | ai.Name = fullName; | 91 | ai.Name = fullName; |
90 | ai.Censored = true; // test it | 92 | ai.Censored = true; // test it |
91 | ai.IndexInServer = dirItem.ArcIndex; | 93 | ai.IndexInServer = dirItem.ArcIndex; |
@@ -111,18 +113,18 @@ static HRESULT EnumerateArchiveItems2(const CAgent *agent, | |||
111 | ai.IndexInServer = arcIndex; | 113 | ai.IndexInServer = arcIndex; |
112 | ai.Name = prefix + file.Name; | 114 | ai.Name = prefix + file.Name; |
113 | ai.Censored = true; // test it | 115 | ai.Censored = true; // test it |
114 | RINOK(agent->GetArc().GetItemMTime(arcIndex, ai.MTime, ai.MTimeDefined)); | 116 | RINOK(agent->GetArc().GetItem_MTime(arcIndex, ai.MTime)); |
115 | ai.IsDir = file.IsDir(); | 117 | ai.IsDir = file.IsDir(); |
116 | ai.SizeDefined = false; | 118 | ai.Size_Defined = false; |
117 | ai.IsAltStream = file.IsAltStream; | 119 | ai.IsAltStream = file.IsAltStream; |
118 | if (!ai.IsDir) | 120 | if (!ai.IsDir) |
119 | { | 121 | { |
120 | RINOK(agent->GetArc().GetItemSize(arcIndex, ai.Size, ai.SizeDefined)); | 122 | RINOK(agent->GetArc().GetItem_Size(arcIndex, ai.Size, ai.Size_Defined)); |
121 | ai.IsDir = false; | 123 | ai.IsDir = false; |
122 | } | 124 | } |
123 | arcItems.Add(ai); | 125 | arcItems.Add(ai); |
124 | 126 | ||
125 | if (file.AltDirIndex >= 0) | 127 | if (file.AltDirIndex != -1) |
126 | { | 128 | { |
127 | RINOK(EnumerateArchiveItems2(agent, file.AltDirIndex, ai.Name + L':', arcItems)); | 129 | RINOK(EnumerateArchiveItems2(agent, file.AltDirIndex, ai.Name + L':', arcItems)); |
128 | } | 130 | } |
@@ -264,10 +266,13 @@ STDMETHODIMP CAgent::DoOperation( | |||
264 | #endif | 266 | #endif |
265 | } | 267 | } |
266 | 268 | ||
267 | NFileTimeType::EEnum fileTimeType; | 269 | NFileTimeType::EEnum fileTimeType = NFileTimeType::kNotDefined; |
268 | UInt32 value; | 270 | UInt32 value; |
269 | RINOK(outArchive->GetFileTimeType(&value)); | 271 | RINOK(outArchive->GetFileTimeType(&value)); |
270 | 272 | // we support any future fileType here. | |
273 | // 22.00: | ||
274 | fileTimeType = (NFileTimeType::EEnum)value; | ||
275 | /* | ||
271 | switch (value) | 276 | switch (value) |
272 | { | 277 | { |
273 | case NFileTimeType::kWindows: | 278 | case NFileTimeType::kWindows: |
@@ -276,8 +281,11 @@ STDMETHODIMP CAgent::DoOperation( | |||
276 | fileTimeType = NFileTimeType::EEnum(value); | 281 | fileTimeType = NFileTimeType::EEnum(value); |
277 | break; | 282 | break; |
278 | default: | 283 | default: |
284 | { | ||
279 | return E_FAIL; | 285 | return E_FAIL; |
286 | } | ||
280 | } | 287 | } |
288 | */ | ||
281 | 289 | ||
282 | 290 | ||
283 | CObjectVector<CArcItem> arcItems; | 291 | CObjectVector<CArcItem> arcItems; |
@@ -389,11 +397,11 @@ STDMETHODIMP CAgent::DoOperation( | |||
389 | FOR_VECTOR(i, updatePairs2) | 397 | FOR_VECTOR(i, updatePairs2) |
390 | { | 398 | { |
391 | const CUpdatePair2 &up = updatePairs2[i]; | 399 | const CUpdatePair2 &up = updatePairs2[i]; |
392 | if (up.DirIndex >= 0 && up.NewData) | 400 | if (up.DirIndex != -1 && up.NewData) |
393 | { | 401 | { |
394 | const CDirItem &di = dirItems.Items[up.DirIndex]; | 402 | const CDirItem &di = dirItems.Items[(unsigned)up.DirIndex]; |
395 | if (!di.IsDir() && di.Size == 0) | 403 | if (!di.IsDir() && di.Size == 0) |
396 | processedItems[up.DirIndex] = 1; | 404 | processedItems[(unsigned)up.DirIndex] = 1; |
397 | } | 405 | } |
398 | } | 406 | } |
399 | } | 407 | } |
@@ -452,7 +460,7 @@ STDMETHODIMP CAgent::DeleteItems(ISequentialOutStream *outArchiveStream, | |||
452 | if (curIndex < realIndices.Size()) | 460 | if (curIndex < realIndices.Size()) |
453 | if (realIndices[curIndex] == i) | 461 | if (realIndices[curIndex] == i) |
454 | { | 462 | { |
455 | RINOK(GetArc().GetItemPath2(i, deletePath)); | 463 | RINOK(GetArc().GetItem_Path2(i, deletePath)); |
456 | RINOK(updateCallback100->DeleteOperation(deletePath)); | 464 | RINOK(updateCallback100->DeleteOperation(deletePath)); |
457 | 465 | ||
458 | curIndex++; | 466 | curIndex++; |
@@ -548,11 +556,14 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream, | |||
548 | true, // includeFolderSubItemsInFlatMode | 556 | true, // includeFolderSubItemsInFlatMode |
549 | realIndices); | 557 | realIndices); |
550 | 558 | ||
551 | int mainRealIndex = _agentFolder->GetRealIndex(indices[0]); | 559 | const UInt32 ind0 = indices[0]; |
552 | 560 | const int mainRealIndex = _agentFolder->GetRealIndex(ind0); | |
553 | UString fullPrefix = _agentFolder->GetFullPrefix(indices[0]); | 561 | const UString fullPrefix = _agentFolder->GetFullPrefix(ind0); |
554 | UString oldItemPath = fullPrefix + _agentFolder->GetName(indices[0]); | 562 | UString name = _agentFolder->GetName(ind0); |
555 | UString newItemPath = fullPrefix + newItemName; | 563 | // 22.00 : we normalize name |
564 | NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(name); | ||
565 | const UString oldItemPath = fullPrefix + name; | ||
566 | const UString newItemPath = fullPrefix + newItemName; | ||
556 | 567 | ||
557 | UStringVector newNames; | 568 | UStringVector newNames; |
558 | 569 | ||
@@ -568,10 +579,10 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream, | |||
568 | if (realIndices[curIndex] == i) | 579 | if (realIndices[curIndex] == i) |
569 | { | 580 | { |
570 | up2.NewProps = true; | 581 | up2.NewProps = true; |
571 | RINOK(GetArc().IsItemAnti(i, up2.IsAnti)); // it must work without that line too. | 582 | RINOK(GetArc().IsItem_Anti(i, up2.IsAnti)); // it must work without that line too. |
572 | 583 | ||
573 | UString oldFullPath; | 584 | UString oldFullPath; |
574 | RINOK(GetArc().GetItemPath2(i, oldFullPath)); | 585 | RINOK(GetArc().GetItem_Path2(i, oldFullPath)); |
575 | 586 | ||
576 | if (!IsPath1PrefixedByPath2(oldFullPath, oldItemPath)) | 587 | if (!IsPath1PrefixedByPath2(oldFullPath, oldItemPath)) |
577 | return E_INVALIDARG; | 588 | return E_INVALIDARG; |
diff --git a/CPP/7zip/UI/Agent/AgentProxy.cpp b/CPP/7zip/UI/Agent/AgentProxy.cpp index f0acd20..4c9c386 100644 --- a/CPP/7zip/UI/Agent/AgentProxy.cpp +++ b/CPP/7zip/UI/Agent/AgentProxy.cpp | |||
@@ -18,6 +18,8 @@ | |||
18 | #include "../../../Windows/PropVariant.h" | 18 | #include "../../../Windows/PropVariant.h" |
19 | #include "../../../Windows/PropVariantConv.h" | 19 | #include "../../../Windows/PropVariantConv.h" |
20 | 20 | ||
21 | #include "../../Archive/Common/ItemNameUtils.h" | ||
22 | |||
21 | #include "AgentProxy.h" | 23 | #include "AgentProxy.h" |
22 | 24 | ||
23 | using namespace NWindows; | 25 | using namespace NWindows; |
@@ -33,12 +35,12 @@ int CProxyArc::FindSubDir(unsigned dirIndex, const wchar_t *name, unsigned &inse | |||
33 | insertPos = left; | 35 | insertPos = left; |
34 | return -1; | 36 | return -1; |
35 | } | 37 | } |
36 | unsigned mid = (left + right) / 2; | 38 | const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); |
37 | unsigned dirIndex2 = subDirs[mid]; | 39 | const unsigned dirIndex2 = subDirs[mid]; |
38 | int compare = CompareFileNames(name, Dirs[dirIndex2].Name); | 40 | const int comp = CompareFileNames(name, Dirs[dirIndex2].Name); |
39 | if (compare == 0) | 41 | if (comp == 0) |
40 | return dirIndex2; | 42 | return dirIndex2; |
41 | if (compare < 0) | 43 | if (comp < 0) |
42 | right = mid; | 44 | right = mid; |
43 | else | 45 | else |
44 | left = mid + 1; | 46 | left = mid + 1; |
@@ -67,12 +69,12 @@ unsigned CProxyArc::AddDir(unsigned dirIndex, int arcIndex, const UString &name) | |||
67 | { | 69 | { |
68 | unsigned insertPos; | 70 | unsigned insertPos; |
69 | int subDirIndex = FindSubDir(dirIndex, name, insertPos); | 71 | int subDirIndex = FindSubDir(dirIndex, name, insertPos); |
70 | if (subDirIndex >= 0) | 72 | if (subDirIndex != -1) |
71 | { | 73 | { |
72 | if (arcIndex >= 0) | 74 | if (arcIndex != -1) |
73 | { | 75 | { |
74 | CProxyDir &item = Dirs[subDirIndex]; | 76 | CProxyDir &item = Dirs[(unsigned)subDirIndex]; |
75 | if (item.ArcIndex < 0) | 77 | if (item.ArcIndex == -1) |
76 | item.ArcIndex = arcIndex; | 78 | item.ArcIndex = arcIndex; |
77 | } | 79 | } |
78 | return subDirIndex; | 80 | return subDirIndex; |
@@ -98,27 +100,31 @@ void CProxyDir::Clear() | |||
98 | void CProxyArc::GetDirPathParts(int dirIndex, UStringVector &pathParts) const | 100 | void CProxyArc::GetDirPathParts(int dirIndex, UStringVector &pathParts) const |
99 | { | 101 | { |
100 | pathParts.Clear(); | 102 | pathParts.Clear(); |
101 | while (dirIndex >= 0) | 103 | while (dirIndex != -1) |
102 | { | 104 | { |
103 | const CProxyDir &dir = Dirs[dirIndex]; | 105 | const CProxyDir &dir = Dirs[dirIndex]; |
104 | dirIndex = dir.ParentDir; | 106 | dirIndex = dir.ParentDir; |
105 | if (dirIndex < 0) | 107 | if (dirIndex == -1) |
106 | break; | 108 | break; |
107 | pathParts.Insert(0, dir.Name); | 109 | pathParts.Insert(0, dir.Name); |
110 | // 22.00: we normalize name | ||
111 | NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(pathParts[0]); | ||
108 | } | 112 | } |
109 | } | 113 | } |
110 | 114 | ||
111 | UString CProxyArc::GetDirPath_as_Prefix(int dirIndex) const | 115 | UString CProxyArc::GetDirPath_as_Prefix(int dirIndex) const |
112 | { | 116 | { |
113 | UString s; | 117 | UString s; |
114 | while (dirIndex >= 0) | 118 | while (dirIndex != -1) |
115 | { | 119 | { |
116 | const CProxyDir &dir = Dirs[dirIndex]; | 120 | const CProxyDir &dir = Dirs[dirIndex]; |
117 | dirIndex = dir.ParentDir; | 121 | dirIndex = dir.ParentDir; |
118 | if (dirIndex < 0) | 122 | if (dirIndex == -1) |
119 | break; | 123 | break; |
120 | s.InsertAtFront(WCHAR_PATH_SEPARATOR); | 124 | s.InsertAtFront(WCHAR_PATH_SEPARATOR); |
121 | s.Insert(0, dir.Name); | 125 | s.Insert(0, dir.Name); |
126 | // 22.00: we normalize name | ||
127 | NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(s.GetBuf(), MyStringLen(dir.Name)); | ||
122 | } | 128 | } |
123 | return s; | 129 | return s; |
124 | } | 130 | } |
@@ -251,7 +257,7 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) | |||
251 | { | 257 | { |
252 | if (progress && (i & 0xFFFF) == 0) | 258 | if (progress && (i & 0xFFFF) == 0) |
253 | { | 259 | { |
254 | UInt64 currentItemIndex = i; | 260 | const UInt64 currentItemIndex = i; |
255 | RINOK(progress->SetCompleted(¤tItemIndex)); | 261 | RINOK(progress->SetCompleted(¤tItemIndex)); |
256 | } | 262 | } |
257 | 263 | ||
@@ -259,9 +265,9 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) | |||
259 | unsigned len = 0; | 265 | unsigned len = 0; |
260 | bool isPtrName = false; | 266 | bool isPtrName = false; |
261 | 267 | ||
262 | #if WCHAR_PATH_SEPARATOR != L'/' | 268 | #if WCHAR_PATH_SEPARATOR != L'/' |
263 | wchar_t replaceFromChar = 0; | 269 | wchar_t separatorChar = WCHAR_PATH_SEPARATOR; |
264 | #endif | 270 | #endif |
265 | 271 | ||
266 | #if defined(MY_CPU_LE) && defined(_WIN32) | 272 | #if defined(MY_CPU_LE) && defined(_WIN32) |
267 | // it works only if (sizeof(wchar_t) == 2) | 273 | // it works only if (sizeof(wchar_t) == 2) |
@@ -278,9 +284,9 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) | |||
278 | len = size / 2 - 1; | 284 | len = size / 2 - 1; |
279 | s = (const wchar_t *)p; | 285 | s = (const wchar_t *)p; |
280 | isPtrName = true; | 286 | isPtrName = true; |
281 | #if WCHAR_PATH_SEPARATOR != L'/' | 287 | #if WCHAR_PATH_SEPARATOR != L'/' |
282 | replaceFromChar = L'\\'; | 288 | separatorChar = L'/'; // 0 |
283 | #endif | 289 | #endif |
284 | } | 290 | } |
285 | } | 291 | } |
286 | if (!s) | 292 | if (!s) |
@@ -297,7 +303,7 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) | |||
297 | return E_FAIL; | 303 | return E_FAIL; |
298 | if (len == 0) | 304 | if (len == 0) |
299 | { | 305 | { |
300 | RINOK(arc.GetDefaultItemPath(i, path)); | 306 | RINOK(arc.GetItem_DefaultPath(i, path)); |
301 | len = path.Len(); | 307 | len = path.Len(); |
302 | s = path; | 308 | s = path; |
303 | } | 309 | } |
@@ -328,16 +334,12 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) | |||
328 | for (unsigned j = 0; j < len; j++) | 334 | for (unsigned j = 0; j < len; j++) |
329 | { | 335 | { |
330 | const wchar_t c = s[j]; | 336 | const wchar_t c = s[j]; |
331 | if (c == WCHAR_PATH_SEPARATOR || c == L'/') | 337 | if (c == L'/' |
332 | { | ||
333 | #if WCHAR_PATH_SEPARATOR != L'/' | 338 | #if WCHAR_PATH_SEPARATOR != L'/' |
334 | if (c == replaceFromChar) | 339 | || (c == separatorChar) |
335 | { | ||
336 | // s.ReplaceOneCharAtPos(j, WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT); | ||
337 | continue; | ||
338 | } | ||
339 | #endif | 340 | #endif |
340 | 341 | ) | |
342 | { | ||
341 | const unsigned kLevelLimit = 1 << 10; | 343 | const unsigned kLevelLimit = 1 << 10; |
342 | if (numLevels <= kLevelLimit) | 344 | if (numLevels <= kLevelLimit) |
343 | { | 345 | { |
@@ -345,6 +347,8 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) | |||
345 | name = "[LONG_PATH]"; | 347 | name = "[LONG_PATH]"; |
346 | else | 348 | else |
347 | name.SetFrom(s + namePos, j - namePos); | 349 | name.SetFrom(s + namePos, j - namePos); |
350 | // 22.00: we can normalize dir here | ||
351 | // NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(name); | ||
348 | curItem = AddDir(curItem, -1, name); | 352 | curItem = AddDir(curItem, -1, name); |
349 | } | 353 | } |
350 | namePos = j + 1; | 354 | namePos = j + 1; |
@@ -384,6 +388,8 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) | |||
384 | if (isDir) | 388 | if (isDir) |
385 | { | 389 | { |
386 | name = s; | 390 | name = s; |
391 | // 22.00: we can normalize dir here | ||
392 | // NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(name); | ||
387 | AddDir(curItem, (int)i, name); | 393 | AddDir(curItem, (int)i, name); |
388 | } | 394 | } |
389 | else | 395 | else |
@@ -418,14 +424,14 @@ void CProxyArc2::GetDirPathParts(int dirIndex, UStringVector &pathParts, bool &i | |||
418 | while (dirIndex >= (int)k_Proxy2_NumRootDirs) | 424 | while (dirIndex >= (int)k_Proxy2_NumRootDirs) |
419 | { | 425 | { |
420 | const CProxyDir2 &dir = Dirs[dirIndex]; | 426 | const CProxyDir2 &dir = Dirs[dirIndex]; |
421 | const CProxyFile2 &file = Files[dir.ArcIndex]; | 427 | const CProxyFile2 &file = Files[(unsigned)dir.ArcIndex]; |
422 | if (pathParts.IsEmpty() && dirIndex == file.AltDirIndex) | 428 | if (pathParts.IsEmpty() && dirIndex == file.AltDirIndex) |
423 | isAltStreamDir = true; | 429 | isAltStreamDir = true; |
424 | pathParts.Insert(0, file.Name); | 430 | pathParts.Insert(0, file.Name); |
425 | int par = file.Parent; | 431 | int par = file.Parent; |
426 | if (par < 0) | 432 | if (par == -1) |
427 | break; | 433 | break; |
428 | dirIndex = Files[par].DirIndex; | 434 | dirIndex = Files[(unsigned)par].DirIndex; |
429 | } | 435 | } |
430 | } | 436 | } |
431 | 437 | ||
@@ -436,7 +442,7 @@ bool CProxyArc2::IsAltDir(unsigned dirIndex) const | |||
436 | if (dirIndex == k_Proxy2_AltRootDirIndex) | 442 | if (dirIndex == k_Proxy2_AltRootDirIndex) |
437 | return true; | 443 | return true; |
438 | const CProxyDir2 &dir = Dirs[dirIndex]; | 444 | const CProxyDir2 &dir = Dirs[dirIndex]; |
439 | const CProxyFile2 &file = Files[dir.ArcIndex]; | 445 | const CProxyFile2 &file = Files[(unsigned)dir.ArcIndex]; |
440 | return ((int)dirIndex == file.AltDirIndex); | 446 | return ((int)dirIndex == file.AltDirIndex); |
441 | } | 447 | } |
442 | 448 | ||
@@ -448,7 +454,7 @@ UString CProxyArc2::GetDirPath_as_Prefix(unsigned dirIndex, bool &isAltStreamDir | |||
448 | isAltStreamDir = true; | 454 | isAltStreamDir = true; |
449 | else if (dirIndex >= k_Proxy2_NumRootDirs) | 455 | else if (dirIndex >= k_Proxy2_NumRootDirs) |
450 | { | 456 | { |
451 | const CProxyFile2 &file = Files[dir.ArcIndex]; | 457 | const CProxyFile2 &file = Files[(unsigned)dir.ArcIndex]; |
452 | isAltStreamDir = ((int)dirIndex == file.AltDirIndex); | 458 | isAltStreamDir = ((int)dirIndex == file.AltDirIndex); |
453 | } | 459 | } |
454 | return dir.PathPrefix; | 460 | return dir.PathPrefix; |
@@ -458,9 +464,9 @@ void CProxyArc2::AddRealIndices_of_ArcItem(unsigned arcIndex, bool includeAltStr | |||
458 | { | 464 | { |
459 | realIndices.Add(arcIndex); | 465 | realIndices.Add(arcIndex); |
460 | const CProxyFile2 &file = Files[arcIndex]; | 466 | const CProxyFile2 &file = Files[arcIndex]; |
461 | if (file.DirIndex >= 0) | 467 | if (file.DirIndex != -1) |
462 | AddRealIndices_of_Dir(file.DirIndex, includeAltStreams, realIndices); | 468 | AddRealIndices_of_Dir(file.DirIndex, includeAltStreams, realIndices); |
463 | if (includeAltStreams && file.AltDirIndex >= 0) | 469 | if (includeAltStreams && file.AltDirIndex != -1) |
464 | AddRealIndices_of_Dir(file.AltDirIndex, includeAltStreams, realIndices); | 470 | AddRealIndices_of_Dir(file.AltDirIndex, includeAltStreams, realIndices); |
465 | } | 471 | } |
466 | 472 | ||
@@ -520,15 +526,18 @@ void CProxyArc2::CalculateSizes(unsigned dirIndex, IInArchive *archive) | |||
520 | } | 526 | } |
521 | 527 | ||
522 | const CProxyFile2 &subFile = Files[index]; | 528 | const CProxyFile2 &subFile = Files[index]; |
523 | if (subFile.DirIndex < 0) | 529 | if (subFile.DirIndex == -1) |
524 | { | 530 | { |
525 | dir.NumSubFiles++; | 531 | dir.NumSubFiles++; |
526 | } | 532 | } |
527 | else | 533 | else |
528 | { | 534 | { |
535 | // 22.00: we normalize name | ||
536 | UString s = subFile.Name; | ||
537 | NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(s); | ||
529 | dir.NumSubDirs++; | 538 | dir.NumSubDirs++; |
530 | CProxyDir2 &f = Dirs[subFile.DirIndex]; | 539 | CProxyDir2 &f = Dirs[subFile.DirIndex]; |
531 | f.PathPrefix = dir.PathPrefix + subFile.Name + WCHAR_PATH_SEPARATOR; | 540 | f.PathPrefix = dir.PathPrefix + s + WCHAR_PATH_SEPARATOR; |
532 | CalculateSizes(subFile.DirIndex, archive); | 541 | CalculateSizes(subFile.DirIndex, archive); |
533 | dir.Size += f.Size; | 542 | dir.Size += f.Size; |
534 | dir.PackSize += f.PackSize; | 543 | dir.PackSize += f.PackSize; |
@@ -539,7 +548,7 @@ void CProxyArc2::CalculateSizes(unsigned dirIndex, IInArchive *archive) | |||
539 | dir.CrcIsDefined = false; | 548 | dir.CrcIsDefined = false; |
540 | } | 549 | } |
541 | 550 | ||
542 | if (subFile.AltDirIndex < 0) | 551 | if (subFile.AltDirIndex == -1) |
543 | { | 552 | { |
544 | // dir.NumSubFiles++; | 553 | // dir.NumSubFiles++; |
545 | } | 554 | } |
@@ -688,12 +697,12 @@ HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress) | |||
688 | 697 | ||
689 | if (file.IsAltStream) | 698 | if (file.IsAltStream) |
690 | { | 699 | { |
691 | if (file.Parent < 0) | 700 | if (file.Parent == -1) |
692 | dirIndex = k_Proxy2_AltRootDirIndex; | 701 | dirIndex = k_Proxy2_AltRootDirIndex; |
693 | else | 702 | else |
694 | { | 703 | { |
695 | int &folderIndex2 = Files[file.Parent].AltDirIndex; | 704 | int &folderIndex2 = Files[(unsigned)file.Parent].AltDirIndex; |
696 | if (folderIndex2 < 0) | 705 | if (folderIndex2 == -1) |
697 | { | 706 | { |
698 | folderIndex2 = Dirs.Size(); | 707 | folderIndex2 = Dirs.Size(); |
699 | CProxyDir2 &dir = Dirs.AddNew(); | 708 | CProxyDir2 &dir = Dirs.AddNew(); |
@@ -704,12 +713,12 @@ HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress) | |||
704 | } | 713 | } |
705 | else | 714 | else |
706 | { | 715 | { |
707 | if (file.Parent < 0) | 716 | if (file.Parent == -1) |
708 | dirIndex = k_Proxy2_RootDirIndex; | 717 | dirIndex = k_Proxy2_RootDirIndex; |
709 | else | 718 | else |
710 | { | 719 | { |
711 | dirIndex = Files[file.Parent].DirIndex; | 720 | dirIndex = Files[(unsigned)file.Parent].DirIndex; |
712 | if (dirIndex < 0) | 721 | if (dirIndex == -1) |
713 | return E_FAIL; | 722 | return E_FAIL; |
714 | } | 723 | } |
715 | } | 724 | } |
@@ -731,7 +740,7 @@ int CProxyArc2::FindItem(unsigned dirIndex, const wchar_t *name, bool foldersOnl | |||
731 | FOR_VECTOR (i, dir.Items) | 740 | FOR_VECTOR (i, dir.Items) |
732 | { | 741 | { |
733 | const CProxyFile2 &file = Files[dir.Items[i]]; | 742 | const CProxyFile2 &file = Files[dir.Items[i]]; |
734 | if (foldersOnly && file.DirIndex < 0) | 743 | if (foldersOnly && file.DirIndex == -1) |
735 | continue; | 744 | continue; |
736 | if (CompareFileNames(file.Name, name) == 0) | 745 | if (CompareFileNames(file.Name, name) == 0) |
737 | return i; | 746 | return i; |
diff --git a/CPP/7zip/UI/Agent/AgentProxy.h b/CPP/7zip/UI/Agent/AgentProxy.h index f2cb3d7..233174b 100644 --- a/CPP/7zip/UI/Agent/AgentProxy.h +++ b/CPP/7zip/UI/Agent/AgentProxy.h | |||
@@ -38,7 +38,7 @@ struct CProxyDir | |||
38 | ~CProxyDir() { delete [](wchar_t *)(void *)Name; } | 38 | ~CProxyDir() { delete [](wchar_t *)(void *)Name; } |
39 | 39 | ||
40 | void Clear(); | 40 | void Clear(); |
41 | bool IsLeaf() const { return ArcIndex >= 0; } | 41 | bool IsLeaf() const { return ArcIndex != -1; } |
42 | }; | 42 | }; |
43 | 43 | ||
44 | class CProxyArc | 44 | class CProxyArc |
@@ -82,7 +82,7 @@ struct CProxyFile2 | |||
82 | 82 | ||
83 | int GetDirIndex(bool forAltStreams) const { return forAltStreams ? AltDirIndex : DirIndex; } | 83 | int GetDirIndex(bool forAltStreams) const { return forAltStreams ? AltDirIndex : DirIndex; } |
84 | 84 | ||
85 | bool IsDir() const { return DirIndex >= 0; } | 85 | bool IsDir() const { return DirIndex != -1; } |
86 | CProxyFile2(): | 86 | CProxyFile2(): |
87 | DirIndex(-1), AltDirIndex(-1), Parent(-1), | 87 | DirIndex(-1), AltDirIndex(-1), Parent(-1), |
88 | Name(NULL), NameLen(0), | 88 | Name(NULL), NameLen(0), |
@@ -145,7 +145,7 @@ public: | |||
145 | { | 145 | { |
146 | const CProxyFile2 &file = Files[arcIndex]; | 146 | const CProxyFile2 &file = Files[arcIndex]; |
147 | 147 | ||
148 | if (file.Parent < 0) | 148 | if (file.Parent == -1) |
149 | return file.IsAltStream ? | 149 | return file.IsAltStream ? |
150 | k_Proxy2_AltRootDirIndex : | 150 | k_Proxy2_AltRootDirIndex : |
151 | k_Proxy2_RootDirIndex; | 151 | k_Proxy2_RootDirIndex; |
diff --git a/CPP/7zip/UI/Agent/ArchiveFolder.cpp b/CPP/7zip/UI/Agent/ArchiveFolder.cpp index a20b4f2..eca02ba 100644 --- a/CPP/7zip/UI/Agent/ArchiveFolder.cpp +++ b/CPP/7zip/UI/Agent/ArchiveFolder.cpp | |||
@@ -16,6 +16,12 @@ STDMETHODIMP CAgentFolder::SetReplaceAltStreamCharsMode(Int32 replaceAltStreamCh | |||
16 | } | 16 | } |
17 | */ | 17 | */ |
18 | 18 | ||
19 | STDMETHODIMP CAgentFolder::SetZoneIdMode(NExtract::NZoneIdMode::EEnum zoneMode) | ||
20 | { | ||
21 | _zoneMode = zoneMode; | ||
22 | return S_OK; | ||
23 | } | ||
24 | |||
19 | STDMETHODIMP CAgentFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 numItems, | 25 | STDMETHODIMP CAgentFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 numItems, |
20 | Int32 includeAltStreams, Int32 replaceAltStreamCharsMode, | 26 | Int32 includeAltStreams, Int32 replaceAltStreamCharsMode, |
21 | const wchar_t *path, IFolderOperationsExtractCallback *callback) | 27 | const wchar_t *path, IFolderOperationsExtractCallback *callback) |
diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp index 4a10ebe..cd18c99 100644 --- a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp +++ b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp | |||
@@ -210,7 +210,7 @@ HRESULT CAgentFolder::CommonUpdateOperation( | |||
210 | FOR_VECTOR (i, pathParts) | 210 | FOR_VECTOR (i, pathParts) |
211 | { | 211 | { |
212 | int next = _proxy->FindSubDir(_proxyDirIndex, pathParts[i]); | 212 | int next = _proxy->FindSubDir(_proxyDirIndex, pathParts[i]); |
213 | if (next < 0) | 213 | if (next == -1) |
214 | break; | 214 | break; |
215 | _proxyDirIndex = next; | 215 | _proxyDirIndex = next; |
216 | } | 216 | } |
@@ -226,7 +226,7 @@ HRESULT CAgentFolder::CommonUpdateOperation( | |||
226 | { | 226 | { |
227 | bool dirOnly = (i + 1 < pathParts.Size() || !isAltStreamFolder); | 227 | bool dirOnly = (i + 1 < pathParts.Size() || !isAltStreamFolder); |
228 | int index = _proxy2->FindItem(_proxyDirIndex, pathParts[i], dirOnly); | 228 | int index = _proxy2->FindItem(_proxyDirIndex, pathParts[i], dirOnly); |
229 | if (index < 0) | 229 | if (index == -1) |
230 | break; | 230 | break; |
231 | 231 | ||
232 | const CProxyFile2 &file = _proxy2->Files[_proxy2->Dirs[_proxyDirIndex].Items[index]]; | 232 | const CProxyFile2 &file = _proxy2->Files[_proxy2->Dirs[_proxyDirIndex].Items[index]]; |
@@ -235,7 +235,7 @@ HRESULT CAgentFolder::CommonUpdateOperation( | |||
235 | _proxyDirIndex = file.DirIndex; | 235 | _proxyDirIndex = file.DirIndex; |
236 | else | 236 | else |
237 | { | 237 | { |
238 | if (file.AltDirIndex >= 0) | 238 | if (file.AltDirIndex != -1) |
239 | _proxyDirIndex = file.AltDirIndex; | 239 | _proxyDirIndex = file.AltDirIndex; |
240 | break; | 240 | break; |
241 | } | 241 | } |
@@ -351,7 +351,7 @@ STDMETHODIMP CAgentFolder::CreateFolder(const wchar_t *name, IProgress *progress | |||
351 | } | 351 | } |
352 | else | 352 | else |
353 | { | 353 | { |
354 | if (_proxy->FindSubDir(_proxyDirIndex, name) >= 0) | 354 | if (_proxy->FindSubDir(_proxyDirIndex, name) != -1) |
355 | return ERROR_ALREADY_EXISTS; | 355 | return ERROR_ALREADY_EXISTS; |
356 | } | 356 | } |
357 | 357 | ||
diff --git a/CPP/7zip/UI/Agent/IFolderArchive.h b/CPP/7zip/UI/Agent/IFolderArchive.h index 565e37b..92eb616 100644 --- a/CPP/7zip/UI/Agent/IFolderArchive.h +++ b/CPP/7zip/UI/Agent/IFolderArchive.h | |||
@@ -116,4 +116,13 @@ FOLDER_ARCHIVE_INTERFACE(IFolderScanProgress, 0x11) | |||
116 | INTERFACE_IFolderScanProgress(PURE) | 116 | INTERFACE_IFolderScanProgress(PURE) |
117 | }; | 117 | }; |
118 | 118 | ||
119 | |||
120 | #define INTERFACE_IFolderSetZoneIdMode(x) \ | ||
121 | STDMETHOD(SetZoneIdMode)(NExtract::NZoneIdMode::EEnum zoneMode) x; \ | ||
122 | |||
123 | FOLDER_ARCHIVE_INTERFACE(IFolderSetZoneIdMode, 0x12) | ||
124 | { | ||
125 | INTERFACE_IFolderSetZoneIdMode(PURE) | ||
126 | }; | ||
127 | |||
119 | #endif | 128 | #endif |
diff --git a/CPP/7zip/UI/Client7z/Client7z.cpp b/CPP/7zip/UI/Client7z/Client7z.cpp index 0fa4cda..a55fa22 100644 --- a/CPP/7zip/UI/Client7z/Client7z.cpp +++ b/CPP/7zip/UI/Client7z/Client7z.cpp | |||
@@ -33,17 +33,29 @@ HINSTANCE g_hInstance; | |||
33 | HINSTANCE g_hInstance = 0; | 33 | HINSTANCE g_hInstance = 0; |
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | // You can find the list of all GUIDs in Guid.txt file. | 36 | // You can find full list of all GUIDs supported by 7-Zip in Guid.txt file. |
37 | // use another CLSIDs, if you want to support other formats (zip, rar, ...). | 37 | // 7z format GUID: {23170F69-40C1-278A-1000-000110070000} |
38 | // {23170F69-40C1-278A-1000-000110070000} | ||
39 | 38 | ||
40 | DEFINE_GUID(CLSID_CFormat7z, | 39 | #define DEFINE_GUID_ARC(name, id) DEFINE_GUID(name, \ |
41 | 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00); | 40 | 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, id, 0x00, 0x00); |
42 | DEFINE_GUID(CLSID_CFormatXz, | ||
43 | 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x0C, 0x00, 0x00); | ||
44 | 41 | ||
45 | #define CLSID_Format CLSID_CFormat7z | 42 | enum |
46 | // #define CLSID_Format CLSID_CFormatXz | 43 | { |
44 | kId_Zip = 1, | ||
45 | kId_BZip2 = 2, | ||
46 | kId_7z = 7, | ||
47 | kId_Xz = 0xC, | ||
48 | kId_Tar = 0xEE, | ||
49 | kId_GZip = 0xEF | ||
50 | }; | ||
51 | |||
52 | // use another id, if you want to support other formats (zip, Xz, ...). | ||
53 | // DEFINE_GUID_ARC (CLSID_Format, kId_Zip) | ||
54 | // DEFINE_GUID_ARC (CLSID_Format, kId_BZip2) | ||
55 | // DEFINE_GUID_ARC (CLSID_Format, kId_Xz) | ||
56 | // DEFINE_GUID_ARC (CLSID_Format, kId_Tar) | ||
57 | // DEFINE_GUID_ARC (CLSID_Format, kId_GZip) | ||
58 | DEFINE_GUID_ARC (CLSID_Format, kId_7z) | ||
47 | 59 | ||
48 | using namespace NWindows; | 60 | using namespace NWindows; |
49 | using namespace NFile; | 61 | using namespace NFile; |
@@ -229,6 +241,86 @@ static const char * const kIsNotArc = "Is not archive"; | |||
229 | static const char * const kHeadersError = "Headers Error"; | 241 | static const char * const kHeadersError = "Headers Error"; |
230 | 242 | ||
231 | 243 | ||
244 | struct CArcTime | ||
245 | { | ||
246 | FILETIME FT; | ||
247 | UInt16 Prec; | ||
248 | Byte Ns100; | ||
249 | bool Def; | ||
250 | |||
251 | CArcTime() | ||
252 | { | ||
253 | Clear(); | ||
254 | } | ||
255 | |||
256 | void Clear() | ||
257 | { | ||
258 | FT.dwHighDateTime = FT.dwLowDateTime = 0; | ||
259 | Prec = 0; | ||
260 | Ns100 = 0; | ||
261 | Def = false; | ||
262 | } | ||
263 | |||
264 | bool IsZero() const | ||
265 | { | ||
266 | return FT.dwLowDateTime == 0 && FT.dwHighDateTime == 0 && Ns100 == 0; | ||
267 | } | ||
268 | |||
269 | int GetNumDigits() const | ||
270 | { | ||
271 | if (Prec == k_PropVar_TimePrec_Unix || | ||
272 | Prec == k_PropVar_TimePrec_DOS) | ||
273 | return 0; | ||
274 | if (Prec == k_PropVar_TimePrec_HighPrec) | ||
275 | return 9; | ||
276 | if (Prec == k_PropVar_TimePrec_0) | ||
277 | return 7; | ||
278 | int digits = (int)Prec - (int)k_PropVar_TimePrec_Base; | ||
279 | if (digits < 0) | ||
280 | digits = 0; | ||
281 | return digits; | ||
282 | } | ||
283 | |||
284 | void Write_To_FiTime(CFiTime &dest) const | ||
285 | { | ||
286 | #ifdef _WIN32 | ||
287 | dest = FT; | ||
288 | #else | ||
289 | if (FILETIME_To_timespec(FT, dest)) | ||
290 | if ((Prec == k_PropVar_TimePrec_Base + 8 || | ||
291 | Prec == k_PropVar_TimePrec_Base + 9) | ||
292 | && Ns100 != 0) | ||
293 | { | ||
294 | dest.tv_nsec += Ns100; | ||
295 | } | ||
296 | #endif | ||
297 | } | ||
298 | |||
299 | void Set_From_Prop(const PROPVARIANT &prop) | ||
300 | { | ||
301 | FT = prop.filetime; | ||
302 | unsigned prec = 0; | ||
303 | unsigned ns100 = 0; | ||
304 | const unsigned prec_Temp = prop.wReserved1; | ||
305 | if (prec_Temp != 0 | ||
306 | && prec_Temp <= k_PropVar_TimePrec_1ns | ||
307 | && prop.wReserved3 == 0) | ||
308 | { | ||
309 | const unsigned ns100_Temp = prop.wReserved2; | ||
310 | if (ns100_Temp < 100) | ||
311 | { | ||
312 | ns100 = ns100_Temp; | ||
313 | prec = prec_Temp; | ||
314 | } | ||
315 | } | ||
316 | Prec = (UInt16)prec; | ||
317 | Ns100 = (Byte)ns100; | ||
318 | Def = true; | ||
319 | } | ||
320 | }; | ||
321 | |||
322 | |||
323 | |||
232 | class CArchiveExtractCallback: | 324 | class CArchiveExtractCallback: |
233 | public IArchiveExtractCallback, | 325 | public IArchiveExtractCallback, |
234 | public ICryptoGetTextPassword, | 326 | public ICryptoGetTextPassword, |
@@ -257,11 +349,10 @@ private: | |||
257 | bool _extractMode; | 349 | bool _extractMode; |
258 | struct CProcessedFileInfo | 350 | struct CProcessedFileInfo |
259 | { | 351 | { |
260 | FILETIME MTime; | 352 | CArcTime MTime; |
261 | UInt32 Attrib; | 353 | UInt32 Attrib; |
262 | bool isDir; | 354 | bool isDir; |
263 | bool AttribDefined; | 355 | bool Attrib_Defined; |
264 | bool MTimeDefined; | ||
265 | } _processedFileInfo; | 356 | } _processedFileInfo; |
266 | 357 | ||
267 | COutFileStream *_outFileStreamSpec; | 358 | COutFileStream *_outFileStreamSpec; |
@@ -328,32 +419,31 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, | |||
328 | if (prop.vt == VT_EMPTY) | 419 | if (prop.vt == VT_EMPTY) |
329 | { | 420 | { |
330 | _processedFileInfo.Attrib = 0; | 421 | _processedFileInfo.Attrib = 0; |
331 | _processedFileInfo.AttribDefined = false; | 422 | _processedFileInfo.Attrib_Defined = false; |
332 | } | 423 | } |
333 | else | 424 | else |
334 | { | 425 | { |
335 | if (prop.vt != VT_UI4) | 426 | if (prop.vt != VT_UI4) |
336 | return E_FAIL; | 427 | return E_FAIL; |
337 | _processedFileInfo.Attrib = prop.ulVal; | 428 | _processedFileInfo.Attrib = prop.ulVal; |
338 | _processedFileInfo.AttribDefined = true; | 429 | _processedFileInfo.Attrib_Defined = true; |
339 | } | 430 | } |
340 | } | 431 | } |
341 | 432 | ||
342 | RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.isDir)); | 433 | RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.isDir)); |
343 | 434 | ||
344 | { | 435 | { |
436 | _processedFileInfo.MTime.Clear(); | ||
345 | // Get Modified Time | 437 | // Get Modified Time |
346 | NCOM::CPropVariant prop; | 438 | NCOM::CPropVariant prop; |
347 | RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop)); | 439 | RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop)); |
348 | _processedFileInfo.MTimeDefined = false; | ||
349 | switch (prop.vt) | 440 | switch (prop.vt) |
350 | { | 441 | { |
351 | case VT_EMPTY: | 442 | case VT_EMPTY: |
352 | // _processedFileInfo.MTime = _utcMTimeDefault; | 443 | // _processedFileInfo.MTime = _utcMTimeDefault; |
353 | break; | 444 | break; |
354 | case VT_FILETIME: | 445 | case VT_FILETIME: |
355 | _processedFileInfo.MTime = prop.filetime; | 446 | _processedFileInfo.MTime.Set_From_Prop(prop); |
356 | _processedFileInfo.MTimeDefined = true; | ||
357 | break; | 447 | break; |
358 | default: | 448 | default: |
359 | return E_FAIL; | 449 | return E_FAIL; |
@@ -483,12 +573,16 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) | |||
483 | 573 | ||
484 | if (_outFileStream) | 574 | if (_outFileStream) |
485 | { | 575 | { |
486 | if (_processedFileInfo.MTimeDefined) | 576 | if (_processedFileInfo.MTime.Def) |
487 | _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime); | 577 | { |
578 | CFiTime ft; | ||
579 | _processedFileInfo.MTime.Write_To_FiTime(ft); | ||
580 | _outFileStreamSpec->SetMTime(&ft); | ||
581 | } | ||
488 | RINOK(_outFileStreamSpec->Close()); | 582 | RINOK(_outFileStreamSpec->Close()); |
489 | } | 583 | } |
490 | _outFileStream.Release(); | 584 | _outFileStream.Release(); |
491 | if (_extractMode && _processedFileInfo.AttribDefined) | 585 | if (_extractMode && _processedFileInfo.Attrib_Defined) |
492 | SetFileAttrib_PosixHighDetect(_diskFilePath, _processedFileInfo.Attrib); | 586 | SetFileAttrib_PosixHighDetect(_diskFilePath, _processedFileInfo.Attrib); |
493 | PrintNewLine(); | 587 | PrintNewLine(); |
494 | return S_OK; | 588 | return S_OK; |
@@ -513,17 +607,14 @@ STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) | |||
513 | ////////////////////////////////////////////////////////////// | 607 | ////////////////////////////////////////////////////////////// |
514 | // Archive Creating callback class | 608 | // Archive Creating callback class |
515 | 609 | ||
516 | struct CDirItem | 610 | struct CDirItem: public NWindows::NFile::NFind::CFileInfoBase |
517 | { | 611 | { |
518 | UInt64 Size; | 612 | UString Path_For_Handler; |
519 | FILETIME CTime; | 613 | FString FullPath; // for filesystem |
520 | FILETIME ATime; | 614 | |
521 | FILETIME MTime; | 615 | CDirItem(const NWindows::NFile::NFind::CFileInfo &fi): |
522 | UString Name; | 616 | CFileInfoBase(fi) |
523 | FString FullPath; | 617 | {} |
524 | UInt32 Attrib; | ||
525 | |||
526 | bool isDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } | ||
527 | }; | 618 | }; |
528 | 619 | ||
529 | class CArchiveUpdateCallback: | 620 | class CArchiveUpdateCallback: |
@@ -618,16 +709,17 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR | |||
618 | } | 709 | } |
619 | 710 | ||
620 | { | 711 | { |
621 | const CDirItem &dirItem = (*DirItems)[index]; | 712 | const CDirItem &di = (*DirItems)[index]; |
622 | switch (propID) | 713 | switch (propID) |
623 | { | 714 | { |
624 | case kpidPath: prop = dirItem.Name; break; | 715 | case kpidPath: prop = di.Path_For_Handler; break; |
625 | case kpidIsDir: prop = dirItem.isDir(); break; | 716 | case kpidIsDir: prop = di.IsDir(); break; |
626 | case kpidSize: prop = dirItem.Size; break; | 717 | case kpidSize: prop = di.Size; break; |
627 | case kpidAttrib: prop = dirItem.Attrib; break; | 718 | case kpidCTime: PropVariant_SetFrom_FiTime(prop, di.CTime); break; |
628 | case kpidCTime: prop = dirItem.CTime; break; | 719 | case kpidATime: PropVariant_SetFrom_FiTime(prop, di.ATime); break; |
629 | case kpidATime: prop = dirItem.ATime; break; | 720 | case kpidMTime: PropVariant_SetFrom_FiTime(prop, di.MTime); break; |
630 | case kpidMTime: prop = dirItem.MTime; break; | 721 | case kpidAttrib: prop = (UInt32)di.GetWinAttrib(); break; |
722 | case kpidPosixAttrib: prop = (UInt32)di.GetPosixAttrib(); break; | ||
631 | } | 723 | } |
632 | } | 724 | } |
633 | prop.Detach(value); | 725 | prop.Detach(value); |
@@ -657,9 +749,9 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream | |||
657 | RINOK(Finilize()); | 749 | RINOK(Finilize()); |
658 | 750 | ||
659 | const CDirItem &dirItem = (*DirItems)[index]; | 751 | const CDirItem &dirItem = (*DirItems)[index]; |
660 | GetStream2(dirItem.Name); | 752 | GetStream2(dirItem.Path_For_Handler); |
661 | 753 | ||
662 | if (dirItem.isDir()) | 754 | if (dirItem.IsDir()) |
663 | return S_OK; | 755 | return S_OK; |
664 | 756 | ||
665 | { | 757 | { |
@@ -848,7 +940,6 @@ int MY_CDECL main(int numArgs, const char *args[]) | |||
848 | unsigned i; | 940 | unsigned i; |
849 | for (i = 1; i < params.Size(); i++) | 941 | for (i = 1; i < params.Size(); i++) |
850 | { | 942 | { |
851 | CDirItem di; | ||
852 | const FString &name = params[i]; | 943 | const FString &name = params[i]; |
853 | 944 | ||
854 | NFind::CFileInfo fi; | 945 | NFind::CFileInfo fi; |
@@ -857,13 +948,10 @@ int MY_CDECL main(int numArgs, const char *args[]) | |||
857 | PrintError("Can't find file", name); | 948 | PrintError("Can't find file", name); |
858 | return 1; | 949 | return 1; |
859 | } | 950 | } |
951 | |||
952 | CDirItem di(fi); | ||
860 | 953 | ||
861 | di.Attrib = fi.Attrib; | 954 | di.Path_For_Handler = fs2us(name); |
862 | di.Size = fi.Size; | ||
863 | di.CTime = fi.CTime; | ||
864 | di.ATime = fi.ATime; | ||
865 | di.MTime = fi.MTime; | ||
866 | di.Name = fs2us(name); | ||
867 | di.FullPath = name; | 955 | di.FullPath = name; |
868 | dirItems.Add(di); | 956 | dirItems.Add(di); |
869 | } | 957 | } |
@@ -894,12 +982,14 @@ int MY_CDECL main(int numArgs, const char *args[]) | |||
894 | { | 982 | { |
895 | const wchar_t *names[] = | 983 | const wchar_t *names[] = |
896 | { | 984 | { |
985 | L"m", | ||
897 | L"s", | 986 | L"s", |
898 | L"x" | 987 | L"x" |
899 | }; | 988 | }; |
900 | const unsigned kNumProps = ARRAY_SIZE(names); | 989 | const unsigned kNumProps = ARRAY_SIZE(names); |
901 | NCOM::CPropVariant values[kNumProps] = | 990 | NCOM::CPropVariant values[kNumProps] = |
902 | { | 991 | { |
992 | L"lzma", | ||
903 | false, // solid mode OFF | 993 | false, // solid mode OFF |
904 | (UInt32)9 // compression level = 9 - ultra | 994 | (UInt32)9 // compression level = 9 - ultra |
905 | }; | 995 | }; |
@@ -910,7 +1000,11 @@ int MY_CDECL main(int numArgs, const char *args[]) | |||
910 | PrintError("ISetProperties unsupported"); | 1000 | PrintError("ISetProperties unsupported"); |
911 | return 1; | 1001 | return 1; |
912 | } | 1002 | } |
913 | RINOK(setProperties->SetProperties(names, values, kNumProps)); | 1003 | if (setProperties->SetProperties(names, values, kNumProps) != S_OK) |
1004 | { | ||
1005 | PrintError("SetProperties() error"); | ||
1006 | return 1; | ||
1007 | } | ||
914 | } | 1008 | } |
915 | */ | 1009 | */ |
916 | 1010 | ||
@@ -1035,7 +1129,13 @@ int MY_CDECL main(int numArgs, const char *args[]) | |||
1035 | CMyComPtr<ISetProperties> setProperties; | 1129 | CMyComPtr<ISetProperties> setProperties; |
1036 | archive->QueryInterface(IID_ISetProperties, (void **)&setProperties); | 1130 | archive->QueryInterface(IID_ISetProperties, (void **)&setProperties); |
1037 | if (setProperties) | 1131 | if (setProperties) |
1038 | setProperties->SetProperties(names, values, kNumProps); | 1132 | { |
1133 | if (setProperties->SetProperties(names, values, kNumProps) != S_OK) | ||
1134 | { | ||
1135 | PrintError("SetProperties() error"); | ||
1136 | return 1; | ||
1137 | } | ||
1138 | } | ||
1039 | */ | 1139 | */ |
1040 | 1140 | ||
1041 | HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback); | 1141 | HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback); |
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 | |||
101 | static 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 | |||
110 | static 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 | |||
141 | static const FChar * const k_ZoneId_StreamName = FTEXT(":Zone.Identifier"); | ||
142 | |||
143 | void 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 | |||
164 | static 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 | ||
100 | int CHardLinkNode::Compare(const CHardLinkNode &a) const | 177 | int CHardLinkNode::Compare(const CHardLinkNode &a) const |
@@ -190,9 +267,9 @@ HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector<UInt32> *r | |||
190 | 267 | ||
191 | CArchiveExtractCallback::CArchiveExtractCallback(): | 268 | CArchiveExtractCallback::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 | ||
284 | void CArchiveExtractCallback::InitBeforeNewArchive() | ||
285 | { | ||
286 | #if defined(_WIN32) && !defined(UNDER_CE) | ||
287 | ZoneBuf.Free(); | ||
288 | #endif | ||
289 | } | ||
290 | |||
207 | void CArchiveExtractCallback::Init( | 291 | void 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 | ||
419 | HRESULT CArchiveExtractCallback::GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined) | 509 | HRESULT 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 | |||
436 | HRESULT CArchiveExtractCallback::GetUnpackSize() | 522 | HRESULT CArchiveExtractCallback::GetUnpackSize() |
437 | { | 523 | { |
438 | return _arc->GetItemSize(_index, _curSize, _curSizeDefined); | 524 | return _arc->GetItem_Size(_index, _curSize, _curSizeDefined); |
439 | } | 525 | } |
440 | 526 | ||
441 | static void AddPathToMessage(UString &s, const FString &path) | 527 | static void AddPathToMessage(UString &s, const FString &path) |
@@ -454,8 +540,9 @@ HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FSt | |||
454 | HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *message, const FString &path) | 540 | HRESULT 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 | |||
935 | static 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 | ||
847 | HRESULT CArchiveExtractCallback::Read_fi_Props() | 974 | HRESULT 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 | ||
1068 | void 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 | ||
927 | void CArchiveExtractCallback::CreateFolders() | 1102 | void 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 | ||
2066 | void CArchiveExtractCallback::SetAttrib() | 2246 | void 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) | |||
2318 | bool CDirPathTime::SetDirTime() const | 2509 | bool 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 | ||
166 | struct CDirPathTime | 169 | struct 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 | ||
188 | struct 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 | |||
235 | struct 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 | |||
219 | class CArchiveExtractCallback: | 252 | class 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 | ||
374 | public: | 412 | public: |
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 | ||
534 | bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item); | 585 | bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item); |
535 | 586 | ||
587 | void 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 | |||
38 | STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value) | 39 | STDMETHODIMP 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 ¶ms, | |||
252 | ErrorMessageHRESULT(result); | 252 | ErrorMessageHRESULT(result); |
253 | } | 253 | } |
254 | 254 | ||
255 | void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup) | 255 | void 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 | ||
18 | void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup); | 18 | void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup, UInt32 writeZone); |
19 | void TestArchives(const UStringVector &arcPaths, bool hashMode = false); | 19 | void TestArchives(const UStringVector &arcPaths, bool hashMode = false); |
20 | 20 | ||
21 | void CalcChecksum(const UStringVector &paths, | 21 | void 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 | ||
154 | static HRESULT ExtractGroupCommand(const UStringVector &arcPaths, | 154 | static 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 | ||
231 | void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup) | 224 | void 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 | ||
236 | void TestArchives(const UStringVector &arcPaths, bool hashMode) | 237 | void 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 | ||
83 | struct CDirItem | 85 | |
86 | struct 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 | |||
231 | struct 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 | |||
207 | struct CArcItem | 385 | struct 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; | |||
23 | using namespace NFile; | 29 | using namespace NFile; |
24 | using namespace NName; | 30 | using namespace NName; |
25 | 31 | ||
32 | |||
33 | static 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 | |||
26 | void CDirItems::AddDirFileInfo(int phyParent, int logParent, int secureIndex, | 65 | void 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 | ||
1150 | HRESULT CDirItems::FillFixedReparse() | 1191 | HRESULT CDirItems::FillFixedReparse() |
@@ -1281,6 +1322,148 @@ HRESULT CDirItems::FillFixedReparse() | |||
1281 | #endif | 1322 | #endif |
1282 | 1323 | ||
1283 | 1324 | ||
1325 | #ifndef _WIN32 | ||
1326 | |||
1327 | HRESULT 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 | ||
1285 | static const char * const kCannotFindArchive = "Cannot find archive"; | 1468 | static 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 | ||
1537 | static 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 | ||
1356 | static void ConvertToLongName(const UString &prefix, UString &name) | 1544 | static 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 | ||
242 | int Find_FileName_InSortedVector(const UStringVector &fileName, const UString &name); | 242 | int Find_FileName_InSortedVector(const UStringVector &fileNames, const UString &name); |
243 | int Find_FileName_InSortedVector(const UStringVector &fileName, const UString &name) | 243 | int 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 | ||
32 | namespace 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 | ||
312 | void HashHexToString(char *dest, const Byte *data, UInt32 size); | ||
313 | |||
314 | static void AddHashResultLine( | 313 | static 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; | |||
16 | const unsigned k_HashCalc_ExtraSize = 8; | 16 | const unsigned k_HashCalc_ExtraSize = 8; |
17 | const unsigned k_HashCalc_NumGroups = 4; | 17 | const 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 | */ | ||
23 | void HashHexToString(char *dest, const Byte *data, UInt32 size); | ||
24 | |||
19 | enum | 25 | enum |
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 | |||
278 | HRESULT CCodecs::LoadCodecs() | 279 | HRESULT 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 | |||
96 | struct CArcInfoEx | 96 | struct 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) | |||
262 | void CHandler::AddItem(const CParseItem &item) | 262 | void 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 | ||
485 | static HRESULT Archive_GetArcBoolProp(IInArchive *arc, PROPID propid, bool &result) throw() | 485 | static 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 | ||
535 | HRESULT CArc::GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const | 535 | HRESULT 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 | ||
619 | HRESULT CArc::GetItemPath(UInt32 index, UString &result) const | 619 | HRESULT 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 | ||
761 | HRESULT CArc::GetDefaultItemPath(UInt32 index, UString &result) const | 761 | HRESULT 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 | ||
782 | HRESULT CArc::GetItemPath2(UInt32 index, UString &result) const | 782 | HRESULT 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 | ||
973 | HRESULT CArc::GetItemSize(UInt32 index, UInt64 &size, bool &defined) const | 973 | HRESULT 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 | ||
992 | HRESULT CArc::GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const | 992 | HRESULT 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 | |||
1023 | static void MakeCheckOrder(CCodecs *codecs, | 1052 | static 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() | |||
1229 | HRESULT CArc::ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes) | 1258 | HRESULT 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 | |||
263 | class CArc | 267 | class 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 | ||
274 | public: | 278 | public: |
@@ -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 | ||
134 | bool COutMultiVolStream::SetMTime(const FILETIME *mTime) | 136 | bool 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 | |||
137 | STDMETHODIMP CArchiveUpdateCallback::GetRootProp(PROPID propID, PROPVARIANT *value) | 159 | STDMETHODIMP 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 | /* | ||
847 | STDMETHODIMP 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 | |||
855 | STDMETHODIMP 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 | |||
878 | STDMETHODIMP 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 | |||
884 | STDMETHODIMP CArchiveUpdateCallback::ReportFinished(UInt32 indexType, UInt32 index, Int32 opRes) | ||
885 | { | ||
886 | return Callback->ReportFinished(indexType, index, opRes); | ||
887 | } | ||
888 | */ | ||
889 | |||
755 | STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) | 890 | STDMETHODIMP 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 | ||
821 | void CArchiveUpdateCallback::InFileStream_On_Destroy(UINT_PTR val) | 956 | void 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 | ||
50 | struct IUpdateCallbackUI | 57 | struct IUpdateCallbackUI |
@@ -70,6 +77,7 @@ struct CKeyKeyValPair | |||
70 | class CArchiveUpdateCallback: | 77 | class 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: | |||
92 | public: | 100 | public: |
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 @@ | |||
14 | using namespace NWindows; | 15 | using namespace NWindows; |
15 | using namespace NTime; | 16 | using namespace NTime; |
16 | 17 | ||
17 | static 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 | |||
31 | static 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 | |||
41 | static const char * const k_Duplicate_inArc_Message = "Duplicate filename in archive:"; | 102 | static const char * const k_Duplicate_inArc_Message = "Duplicate filename in archive:"; |
42 | static const char * const k_Duplicate_inDir_Message = "Duplicate filename on disk:"; | 103 | static const char * const k_Duplicate_inDir_Message = "Duplicate filename on disk:"; |
43 | static const char * const k_NotCensoredCollision_Message = "Internal file name collision (file on disk, file in archive):"; | 104 | static 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 | ||
65 | static int CompareArcItems(const unsigned *p1, const unsigned *p2, void *param) | 126 | static 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 | ||
36 | static 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 | |||
45 | static 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 | |||
36 | static void Key_Set_BoolPair(CKey &key, LPCTSTR name, const CBoolPair &b) | 52 | static 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 | ||
58 | static 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 | |||
67 | static 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 | |||
42 | static void Key_Get_BoolPair(CKey &key, LPCTSTR name, CBoolPair &b) | 75 | static 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"); | |||
169 | static LPCTSTR const kAltStreams = TEXT("AltStreams"); | 202 | static LPCTSTR const kAltStreams = TEXT("AltStreams"); |
170 | static LPCTSTR const kHardLinks = TEXT("HardLinks"); | 203 | static LPCTSTR const kHardLinks = TEXT("HardLinks"); |
171 | static LPCTSTR const kSymLinks = TEXT("SymLinks"); | 204 | static LPCTSTR const kSymLinks = TEXT("SymLinks"); |
205 | static LPCTSTR const kPreserveATime = TEXT("PreserveATime"); | ||
206 | |||
207 | static LPCTSTR const kTimePrec = TEXT("TimePrec"); | ||
208 | static LPCTSTR const kMTime = TEXT("MTime"); | ||
209 | static LPCTSTR const kATime = TEXT("ATime"); | ||
210 | static LPCTSTR const kCTime = TEXT("CTime"); | ||
211 | static LPCTSTR const kSetArcMTime = TEXT("SetArcMTime"); | ||
172 | 212 | ||
173 | static void SetRegString(CKey &key, LPCWSTR name, const UString &value) | 213 | static 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 | ||
181 | static 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 | |||
189 | static void GetRegString(CKey &key, LPCWSTR name, UString &value) | 221 | static 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 | ||
195 | static void GetRegUInt32(CKey &key, LPCTSTR name, UInt32 &value) | ||
196 | { | ||
197 | if (key.QueryValue(name, value) != ERROR_SUCCESS) | ||
198 | value = (UInt32)(Int32)-1; | ||
199 | } | ||
200 | |||
201 | static LPCWSTR const kMemUse = L"MemUse" | 227 | static 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"); | |||
478 | static LPCTSTR const kContextMenu = TEXT("ContextMenu"); | 518 | static LPCTSTR const kContextMenu = TEXT("ContextMenu"); |
479 | static LPCTSTR const kMenuIcons = TEXT("MenuIcons"); | 519 | static LPCTSTR const kMenuIcons = TEXT("MenuIcons"); |
480 | static LPCTSTR const kElimDup = TEXT("ElimDupExtract"); | 520 | static LPCTSTR const kElimDup = TEXT("ElimDupExtract"); |
521 | static LPCTSTR const kWriteZoneId = TEXT("WriteZoneIdExtract"); | ||
481 | 522 | ||
482 | void CContextMenuInfo::Save() const | 523 | void 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 | /* | ||
14 | CBoolPair::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 | |||
13 | namespace NExtract | 23 | namespace 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(); |
diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp index 24c21e8..7f791b0 100644 --- a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp +++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp | |||
@@ -56,6 +56,9 @@ HRESULT CExtractScanConsole::ScanProgress(const CDirItemsStat &st, const FString | |||
56 | 56 | ||
57 | HRESULT CExtractScanConsole::ScanError(const FString &path, DWORD systemError) | 57 | HRESULT CExtractScanConsole::ScanError(const FString &path, DWORD systemError) |
58 | { | 58 | { |
59 | // 22.00: | ||
60 | // ScanErrors.AddError(path, systemError); | ||
61 | |||
59 | ClosePercentsAndFlush(); | 62 | ClosePercentsAndFlush(); |
60 | 63 | ||
61 | if (_se) | 64 | if (_se) |
@@ -66,6 +69,10 @@ HRESULT CExtractScanConsole::ScanError(const FString &path, DWORD systemError) | |||
66 | _se->Flush(); | 69 | _se->Flush(); |
67 | } | 70 | } |
68 | return HRESULT_FROM_WIN32(systemError); | 71 | return HRESULT_FROM_WIN32(systemError); |
72 | |||
73 | // 22.00: commented | ||
74 | // CommonError(path, systemError, true); | ||
75 | // return S_OK; | ||
69 | } | 76 | } |
70 | 77 | ||
71 | 78 | ||
diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.h b/CPP/7zip/UI/Console/ExtractCallbackConsole.h index 5ac1d0b..7964813 100644 --- a/CPP/7zip/UI/Console/ExtractCallbackConsole.h +++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.h | |||
@@ -15,12 +15,33 @@ | |||
15 | 15 | ||
16 | #include "OpenCallbackConsole.h" | 16 | #include "OpenCallbackConsole.h" |
17 | 17 | ||
18 | /* | ||
19 | struct CErrorPathCodes2 | ||
20 | { | ||
21 | FStringVector Paths; | ||
22 | CRecordVector<DWORD> Codes; | ||
23 | |||
24 | void AddError(const FString &path, DWORD systemError) | ||
25 | { | ||
26 | Paths.Add(path); | ||
27 | Codes.Add(systemError); | ||
28 | } | ||
29 | void Clear() | ||
30 | { | ||
31 | Paths.Clear(); | ||
32 | Codes.Clear(); | ||
33 | } | ||
34 | }; | ||
35 | */ | ||
36 | |||
18 | class CExtractScanConsole: public IDirItemsCallback | 37 | class CExtractScanConsole: public IDirItemsCallback |
19 | { | 38 | { |
20 | CStdOutStream *_so; | 39 | CStdOutStream *_so; |
21 | CStdOutStream *_se; | 40 | CStdOutStream *_se; |
22 | CPercentPrinter _percent; | 41 | CPercentPrinter _percent; |
23 | 42 | ||
43 | // CErrorPathCodes2 ScanErrors; | ||
44 | |||
24 | bool NeedPercents() const { return _percent._so != NULL; } | 45 | bool NeedPercents() const { return _percent._so != NULL; } |
25 | 46 | ||
26 | void ClosePercentsAndFlush() | 47 | void ClosePercentsAndFlush() |
diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp index 9000e57..f764f07 100644 --- a/CPP/7zip/UI/Console/List.cpp +++ b/CPP/7zip/UI/Console/List.cpp | |||
@@ -124,6 +124,13 @@ static const char * const kPropIdToName[] = | |||
124 | , "Read-only" | 124 | , "Read-only" |
125 | , "Out Name" | 125 | , "Out Name" |
126 | , "Copy Link" | 126 | , "Copy Link" |
127 | , "ArcFileName" | ||
128 | , "IsHash" | ||
129 | , "Metadata Changed" | ||
130 | , "User ID" | ||
131 | , "Group ID" | ||
132 | , "Device Major" | ||
133 | , "Device Minor" | ||
127 | }; | 134 | }; |
128 | 135 | ||
129 | static const char kEmptyAttribChar = '.'; | 136 | static const char kEmptyAttribChar = '.'; |
@@ -303,22 +310,18 @@ struct CListUInt64Def | |||
303 | void Add(const CListUInt64Def &v) { if (v.Def) Add(v.Val); } | 310 | void Add(const CListUInt64Def &v) { if (v.Def) Add(v.Val); } |
304 | }; | 311 | }; |
305 | 312 | ||
306 | struct CListFileTimeDef | ||
307 | { | ||
308 | FILETIME Val; | ||
309 | bool Def; | ||
310 | 313 | ||
311 | CListFileTimeDef(): Def(false) { Val.dwLowDateTime = 0; Val.dwHighDateTime = 0; } | 314 | struct CListFileTimeDef: public CArcTime |
315 | { | ||
312 | void Update(const CListFileTimeDef &t) | 316 | void Update(const CListFileTimeDef &t) |
313 | { | 317 | { |
314 | if (t.Def && (!Def || CompareFileTime(&Val, &t.Val) < 0)) | 318 | if (t.Def && (!Def || CompareWith(t) < 0)) |
315 | { | 319 | (*this) = t; |
316 | Val = t.Val; | ||
317 | Def = true; | ||
318 | } | ||
319 | } | 320 | } |
320 | }; | 321 | }; |
321 | 322 | ||
323 | |||
324 | |||
322 | struct CListStat | 325 | struct CListStat |
323 | { | 326 | { |
324 | CListUInt64Def Size; | 327 | CListUInt64Def Size; |
@@ -493,12 +496,24 @@ void CFieldPrinter::PrintTitleLines() | |||
493 | g_StdOut << LinesString; | 496 | g_StdOut << LinesString; |
494 | } | 497 | } |
495 | 498 | ||
496 | static void PrintTime(char *dest, const FILETIME *ft) | 499 | static void PrintTime(char *dest, const CListFileTimeDef &t, bool showNS) |
497 | { | 500 | { |
498 | *dest = 0; | 501 | *dest = 0; |
499 | if (ft->dwLowDateTime == 0 && ft->dwHighDateTime == 0) | 502 | if (t.IsZero()) |
500 | return; | 503 | return; |
501 | ConvertUtcFileTimeToString(*ft, dest, kTimestampPrintLevel_SEC); | 504 | int prec = kTimestampPrintLevel_SEC; |
505 | if (showNS) | ||
506 | { | ||
507 | prec = kTimestampPrintLevel_NTFS; | ||
508 | if (t.Prec != 0) | ||
509 | { | ||
510 | prec = t.GetNumDigits(); | ||
511 | if (prec < kTimestampPrintLevel_DAY) | ||
512 | prec = kTimestampPrintLevel_NTFS; | ||
513 | } | ||
514 | } | ||
515 | |||
516 | ConvertUtcFileTimeToString2(t.FT, t.Ns100, dest, prec); | ||
502 | } | 517 | } |
503 | 518 | ||
504 | #ifndef _SFX | 519 | #ifndef _SFX |
@@ -631,7 +646,13 @@ HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &st) | |||
631 | { | 646 | { |
632 | case kpidSize: if (st.Size.Def) prop = st.Size.Val; break; | 647 | case kpidSize: if (st.Size.Def) prop = st.Size.Val; break; |
633 | case kpidPackSize: if (st.PackSize.Def) prop = st.PackSize.Val; break; | 648 | case kpidPackSize: if (st.PackSize.Def) prop = st.PackSize.Val; break; |
634 | case kpidMTime: if (st.MTime.Def) prop = st.MTime.Val; break; | 649 | case kpidMTime: |
650 | { | ||
651 | const CListFileTimeDef &mtime = st.MTime; | ||
652 | if (mtime.Def) | ||
653 | prop.SetAsTimeFrom_FT_Prec_Ns100(mtime.FT, mtime.Prec, mtime.Ns100); | ||
654 | break; | ||
655 | } | ||
635 | default: | 656 | default: |
636 | RINOK(Arc->Archive->GetProperty(index, f.PropID, &prop)); | 657 | RINOK(Arc->Archive->GetProperty(index, f.PropID, &prop)); |
637 | } | 658 | } |
@@ -653,7 +674,9 @@ HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &st) | |||
653 | } | 674 | } |
654 | else if (prop.vt == VT_FILETIME) | 675 | else if (prop.vt == VT_FILETIME) |
655 | { | 676 | { |
656 | PrintTime(temp + tempPos, &prop.filetime); | 677 | CListFileTimeDef t; |
678 | t.Set_From_Prop(prop); | ||
679 | PrintTime(temp + tempPos, t, techMode); | ||
657 | if (techMode) | 680 | if (techMode) |
658 | g_StdOut << temp + tempPos; | 681 | g_StdOut << temp + tempPos; |
659 | else | 682 | else |
@@ -726,7 +749,7 @@ void CFieldPrinter::PrintSum(const CListStat &st, UInt64 numDirs, const char *st | |||
726 | char s[64]; | 749 | char s[64]; |
727 | s[0] = 0; | 750 | s[0] = 0; |
728 | if (st.MTime.Def) | 751 | if (st.MTime.Def) |
729 | PrintTime(s, &st.MTime.Val); | 752 | PrintTime(s, st.MTime, false); // showNS |
730 | PrintString(f.TextAdjustment, f.Width, s); | 753 | PrintString(f.TextAdjustment, f.Width, s); |
731 | } | 754 | } |
732 | else if (f.PropID == kpidPath) | 755 | else if (f.PropID == kpidPath) |
@@ -770,16 +793,14 @@ static HRESULT GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, | |||
770 | 793 | ||
771 | static HRESULT GetItemMTime(IInArchive *archive, UInt32 index, CListFileTimeDef &t) | 794 | static HRESULT GetItemMTime(IInArchive *archive, UInt32 index, CListFileTimeDef &t) |
772 | { | 795 | { |
773 | t.Val.dwLowDateTime = 0; | 796 | /* maybe we could call CArc::GetItemMTime(UInt32 index, CArcTime &ft, bool &defined) here |
774 | t.Val.dwHighDateTime = 0; | 797 | that can set default timestamp, if not defined */ |
775 | t.Def = false; | 798 | t.Clear(); |
799 | // t.Def = false; | ||
776 | CPropVariant prop; | 800 | CPropVariant prop; |
777 | RINOK(archive->GetProperty(index, kpidMTime, &prop)); | 801 | RINOK(archive->GetProperty(index, kpidMTime, &prop)); |
778 | if (prop.vt == VT_FILETIME) | 802 | if (prop.vt == VT_FILETIME) |
779 | { | 803 | t.Set_From_Prop(prop); |
780 | t.Val = prop.filetime; | ||
781 | t.Def = true; | ||
782 | } | ||
783 | else if (prop.vt != VT_EMPTY) | 804 | else if (prop.vt != VT_EMPTY) |
784 | return E_FAIL; | 805 | return E_FAIL; |
785 | return S_OK; | 806 | return S_OK; |
@@ -879,7 +900,8 @@ static void PrintPropPair(CStdOutStream &so, const char *name, const wchar_t *va | |||
879 | static void PrintPropertyPair2(CStdOutStream &so, PROPID propID, const wchar_t *name, const CPropVariant &prop) | 900 | static void PrintPropertyPair2(CStdOutStream &so, PROPID propID, const wchar_t *name, const CPropVariant &prop) |
880 | { | 901 | { |
881 | UString s; | 902 | UString s; |
882 | ConvertPropertyToString2(s, prop, propID); | 903 | const int levelTopLimit = 9; // 1ns level |
904 | ConvertPropertyToString2(s, prop, propID, levelTopLimit); | ||
883 | if (!s.IsEmpty()) | 905 | if (!s.IsEmpty()) |
884 | { | 906 | { |
885 | AString nameA; | 907 | AString nameA; |
@@ -1249,7 +1271,7 @@ HRESULT ListArchives( | |||
1249 | if (NConsoleClose::TestBreakSignal()) | 1271 | if (NConsoleClose::TestBreakSignal()) |
1250 | return E_ABORT; | 1272 | return E_ABORT; |
1251 | 1273 | ||
1252 | HRESULT res = arc.GetItemPath2(i, fp.FilePath); | 1274 | HRESULT res = arc.GetItem_Path2(i, fp.FilePath); |
1253 | 1275 | ||
1254 | if (stdInMode && res == E_INVALIDARG) | 1276 | if (stdInMode && res == E_INVALIDARG) |
1255 | break; | 1277 | break; |
diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp index 0455ed5..d01aa4d 100644 --- a/CPP/7zip/UI/Console/Main.cpp +++ b/CPP/7zip/UI/Console/Main.cpp | |||
@@ -75,6 +75,8 @@ extern const CHasherInfo *g_Hashers[]; | |||
75 | const CExternalCodecs *g_ExternalCodecs_Ptr; | 75 | const CExternalCodecs *g_ExternalCodecs_Ptr; |
76 | #endif | 76 | #endif |
77 | 77 | ||
78 | DECLARE_AND_SET_CLIENT_VERSION_VAR | ||
79 | |||
78 | #if defined(PROG_VARIANT_Z) | 80 | #if defined(PROG_VARIANT_Z) |
79 | #define PROG_POSTFIX "z" | 81 | #define PROG_POSTFIX "z" |
80 | #define PROG_POSTFIX_2 " (z)" | 82 | #define PROG_POSTFIX_2 " (z)" |
@@ -510,7 +512,7 @@ static void PrintStat() | |||
510 | , &creationTimeFT, &exitTimeFT, &kernelTimeFT, &userTimeFT)) | 512 | , &creationTimeFT, &exitTimeFT, &kernelTimeFT, &userTimeFT)) |
511 | return; | 513 | return; |
512 | FILETIME curTimeFT; | 514 | FILETIME curTimeFT; |
513 | NTime::GetCurUtcFileTime(curTimeFT); | 515 | NTime::GetCurUtc_FiTime(curTimeFT); |
514 | 516 | ||
515 | #ifndef UNDER_CE | 517 | #ifndef UNDER_CE |
516 | 518 | ||
@@ -845,7 +847,7 @@ int Main2( | |||
845 | #if !defined(UNDER_CE) | 847 | #if !defined(UNDER_CE) |
846 | CONSOLE_SCREEN_BUFFER_INFO consoleInfo; | 848 | CONSOLE_SCREEN_BUFFER_INFO consoleInfo; |
847 | if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consoleInfo)) | 849 | if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consoleInfo)) |
848 | consoleWidth = (unsigned)consoleInfo.dwSize.X; | 850 | consoleWidth = (unsigned)(unsigned short)consoleInfo.dwSize.X; |
849 | #endif | 851 | #endif |
850 | 852 | ||
851 | #else | 853 | #else |
@@ -859,7 +861,7 @@ int Main2( | |||
859 | 861 | ||
860 | CREATE_CODECS_OBJECT | 862 | CREATE_CODECS_OBJECT |
861 | 863 | ||
862 | codecs->CaseSensitiveChange = options.CaseSensitiveChange; | 864 | codecs->CaseSensitive_Change = options.CaseSensitive_Change; |
863 | codecs->CaseSensitive = options.CaseSensitive; | 865 | codecs->CaseSensitive = options.CaseSensitive; |
864 | ThrowException_if_Error(codecs->Load()); | 866 | ThrowException_if_Error(codecs->Load()); |
865 | Codecs_AddHashArcHandler(codecs); | 867 | Codecs_AddHashArcHandler(codecs); |
@@ -952,9 +954,11 @@ int Main2( | |||
952 | 954 | ||
953 | so << endl << "Formats:" << endl; | 955 | so << endl << "Formats:" << endl; |
954 | 956 | ||
955 | const char * const kArcFlags = "KSNFMGOPBELHXC"; | 957 | const char * const kArcFlags = "KSNFMGOPBELHXCc+a+m+r+"; |
958 | const char * const kArcTimeFlags = "wudn"; | ||
956 | const unsigned kNumArcFlags = (unsigned)strlen(kArcFlags); | 959 | const unsigned kNumArcFlags = (unsigned)strlen(kArcFlags); |
957 | 960 | const unsigned kNumArcTimeFlags = (unsigned)strlen(kArcTimeFlags); | |
961 | |||
958 | for (i = 0; i < codecs->Formats.Size(); i++) | 962 | for (i = 0; i < codecs->Formats.Size(); i++) |
959 | { | 963 | { |
960 | const CArcInfoEx &arc = codecs->Formats[i]; | 964 | const CArcInfoEx &arc = codecs->Formats[i]; |
@@ -967,12 +971,22 @@ int Main2( | |||
967 | 971 | ||
968 | so << (char)(arc.UpdateEnabled ? 'C' : ' '); | 972 | so << (char)(arc.UpdateEnabled ? 'C' : ' '); |
969 | 973 | ||
970 | for (unsigned b = 0; b < kNumArcFlags; b++) | ||
971 | { | 974 | { |
972 | so << (char) | 975 | unsigned b; |
973 | ((arc.Flags & ((UInt32)1 << b)) != 0 ? kArcFlags[b] : ' '); | 976 | for (b = 0; b < kNumArcFlags; b++) |
977 | so << (char)((arc.Flags & ((UInt32)1 << b)) != 0 ? kArcFlags[b] : '.'); | ||
978 | so << ' '; | ||
974 | } | 979 | } |
975 | 980 | ||
981 | if (arc.TimeFlags != 0) | ||
982 | { | ||
983 | unsigned b; | ||
984 | for (b = 0; b < kNumArcTimeFlags; b++) | ||
985 | so << (char)((arc.TimeFlags & ((UInt32)1 << b)) != 0 ? kArcTimeFlags[b] : '.'); | ||
986 | so << arc.Get_DefaultTimePrec(); | ||
987 | so << ' '; | ||
988 | } | ||
989 | |||
976 | so << ' '; | 990 | so << ' '; |
977 | PrintString(so, arc.Name, 8); | 991 | PrintString(so, arc.Name, 8); |
978 | so << ' '; | 992 | so << ' '; |
diff --git a/CPP/7zip/UI/Console/PercentPrinter.cpp b/CPP/7zip/UI/Console/PercentPrinter.cpp index 4341fd9..49d0393 100644 --- a/CPP/7zip/UI/Console/PercentPrinter.cpp +++ b/CPP/7zip/UI/Console/PercentPrinter.cpp | |||
@@ -63,7 +63,8 @@ void CPercentPrinter::GetPercents() | |||
63 | { | 63 | { |
64 | char c = '%'; | 64 | char c = '%'; |
65 | UInt64 val = 0; | 65 | UInt64 val = 0; |
66 | if (Total == (UInt64)(Int64)-1) | 66 | if (Total == (UInt64)(Int64)-1 || |
67 | (Total == 0 && Completed != 0)) | ||
67 | { | 68 | { |
68 | val = Completed >> 20; | 69 | val = Completed >> 20; |
69 | c = 'M'; | 70 | c = 'M'; |
diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp index 0a25c22..1a6b820 100644 --- a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp +++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp | |||
@@ -11,6 +11,8 @@ | |||
11 | #include "../../../Windows/Synchronization.h" | 11 | #include "../../../Windows/Synchronization.h" |
12 | #endif | 12 | #endif |
13 | 13 | ||
14 | // #include "../Common/PropIDUtils.h" | ||
15 | |||
14 | #include "ConsoleClose.h" | 16 | #include "ConsoleClose.h" |
15 | #include "UserInputUtils.h" | 17 | #include "UserInputUtils.h" |
16 | #include "UpdateCallbackConsole.h" | 18 | #include "UpdateCallbackConsole.h" |
@@ -195,6 +197,22 @@ void CCallbackConsoleBase::CommonError(const FString &path, DWORD systemError, b | |||
195 | } | 197 | } |
196 | } | 198 | } |
197 | 199 | ||
200 | /* | ||
201 | void CCallbackConsoleBase::CommonError(const char *message) | ||
202 | { | ||
203 | ClosePercents2(); | ||
204 | |||
205 | if (_se) | ||
206 | { | ||
207 | if (_so) | ||
208 | _so->Flush(); | ||
209 | |||
210 | *_se << endl << kError << message << endl; | ||
211 | _se->Flush(); | ||
212 | } | ||
213 | } | ||
214 | */ | ||
215 | |||
198 | 216 | ||
199 | HRESULT CCallbackConsoleBase::ScanError_Base(const FString &path, DWORD systemError) | 217 | HRESULT CCallbackConsoleBase::ScanError_Base(const FString &path, DWORD systemError) |
200 | { | 218 | { |
@@ -519,6 +537,28 @@ HRESULT CCallbackConsoleBase::PrintProgress(const wchar_t *name, bool isDir, con | |||
519 | return CheckBreak2(); | 537 | return CheckBreak2(); |
520 | } | 538 | } |
521 | 539 | ||
540 | |||
541 | /* | ||
542 | void CCallbackConsoleBase::PrintInfoLine(const UString &s) | ||
543 | { | ||
544 | if (LogLevel < 1000) | ||
545 | return; | ||
546 | |||
547 | MT_LOCK | ||
548 | |||
549 | const bool show2 = (_so != NULL); | ||
550 | |||
551 | if (show2) | ||
552 | { | ||
553 | ClosePercents_for_so(); | ||
554 | _so->PrintUString(s, _tempA); | ||
555 | *_so << endl; | ||
556 | if (NeedFlush) | ||
557 | _so->Flush(); | ||
558 | } | ||
559 | } | ||
560 | */ | ||
561 | |||
522 | HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isDir, bool isAnti, UInt32 mode) | 562 | HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isDir, bool isAnti, UInt32 mode) |
523 | { | 563 | { |
524 | if (StdOutMode) | 564 | if (StdOutMode) |
@@ -562,10 +602,19 @@ HRESULT CUpdateCallbackConsole::ReadingFileError(const FString &path, DWORD syst | |||
562 | return ReadingFileError_Base(path, systemError); | 602 | return ReadingFileError_Base(path, systemError); |
563 | } | 603 | } |
564 | 604 | ||
565 | HRESULT CUpdateCallbackConsole::SetOperationResult(Int32) | 605 | HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 /* opRes */) |
566 | { | 606 | { |
567 | MT_LOCK | 607 | MT_LOCK |
568 | _percent.Files++; | 608 | _percent.Files++; |
609 | /* | ||
610 | if (opRes != NArchive::NUpdate::NOperationResult::kOK) | ||
611 | { | ||
612 | if (opRes == NArchive::NUpdate::NOperationResult::kError_FileChanged) | ||
613 | { | ||
614 | CommonError("Input file changed"); | ||
615 | } | ||
616 | } | ||
617 | */ | ||
569 | return S_OK; | 618 | return S_OK; |
570 | } | 619 | } |
571 | 620 | ||
@@ -616,6 +665,8 @@ HRESULT CUpdateCallbackConsole::ReportUpdateOperation(UInt32 op, const wchar_t * | |||
616 | case NUpdateNotifyOp::kSkip: s = "."; requiredLevel = 2; break; | 665 | case NUpdateNotifyOp::kSkip: s = "."; requiredLevel = 2; break; |
617 | case NUpdateNotifyOp::kDelete: s = "D"; requiredLevel = 3; break; | 666 | case NUpdateNotifyOp::kDelete: s = "D"; requiredLevel = 3; break; |
618 | case NUpdateNotifyOp::kHeader: s = "Header creation"; requiredLevel = 100; break; | 667 | case NUpdateNotifyOp::kHeader: s = "Header creation"; requiredLevel = 100; break; |
668 | case NUpdateNotifyOp::kInFileChanged: s = "Size of input file was changed:"; requiredLevel = 10; break; | ||
669 | // case NUpdateNotifyOp::kOpFinished: s = "Finished"; requiredLevel = 100; break; | ||
619 | default: | 670 | default: |
620 | { | 671 | { |
621 | temp[0] = 'o'; | 672 | temp[0] = 'o'; |
@@ -710,3 +761,119 @@ HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name, bool isDir) | |||
710 | } | 761 | } |
711 | return S_OK; | 762 | return S_OK; |
712 | } | 763 | } |
764 | |||
765 | /* | ||
766 | void GetPropName(PROPID propID, const wchar_t *name, AString &nameA, UString &nameU); | ||
767 | |||
768 | static void GetPropName(PROPID propID, UString &nameU) | ||
769 | { | ||
770 | AString nameA; | ||
771 | GetPropName(propID, NULL, nameA, nameU); | ||
772 | // if (!nameA.IsEmpty()) | ||
773 | nameU = nameA; | ||
774 | } | ||
775 | |||
776 | |||
777 | static void AddPropNamePrefix(UString &s, PROPID propID) | ||
778 | { | ||
779 | UString name; | ||
780 | GetPropName(propID, name); | ||
781 | s += name; | ||
782 | s += " = "; | ||
783 | } | ||
784 | |||
785 | void CCallbackConsoleBase::PrintPropInfo(UString &s, PROPID propID, const PROPVARIANT *value) | ||
786 | { | ||
787 | AddPropNamePrefix(s, propID); | ||
788 | { | ||
789 | UString dest; | ||
790 | const int level = 9; // we show up to ns precision level | ||
791 | ConvertPropertyToString2(dest, *value, propID, level); | ||
792 | s += dest; | ||
793 | } | ||
794 | PrintInfoLine(s); | ||
795 | } | ||
796 | |||
797 | static void Add_IndexType_Index(UString &s, UInt32 indexType, UInt32 index) | ||
798 | { | ||
799 | if (indexType == NArchive::NEventIndexType::kArcProp) | ||
800 | { | ||
801 | } | ||
802 | else | ||
803 | { | ||
804 | if (indexType == NArchive::NEventIndexType::kBlockIndex) | ||
805 | { | ||
806 | s += "#"; | ||
807 | } | ||
808 | else if (indexType == NArchive::NEventIndexType::kOutArcIndex) | ||
809 | { | ||
810 | } | ||
811 | else | ||
812 | { | ||
813 | s += "indexType_"; | ||
814 | s.Add_UInt32(indexType); | ||
815 | s.Add_Space(); | ||
816 | } | ||
817 | s.Add_UInt32(index); | ||
818 | } | ||
819 | s += ": "; | ||
820 | } | ||
821 | |||
822 | HRESULT CUpdateCallbackConsole::ReportProp(UInt32 indexType, UInt32 index, PROPID propID, const PROPVARIANT *value) | ||
823 | { | ||
824 | UString s; | ||
825 | Add_IndexType_Index(s, indexType, index); | ||
826 | PrintPropInfo(s, propID, value); | ||
827 | return S_OK; | ||
828 | } | ||
829 | |||
830 | static inline char GetHex(Byte value) | ||
831 | { | ||
832 | return (char)((value < 10) ? ('0' + value) : ('a' + (value - 10))); | ||
833 | } | ||
834 | |||
835 | static void AddHexToString(UString &dest, const Byte *data, UInt32 size) | ||
836 | { | ||
837 | for (UInt32 i = 0; i < size; i++) | ||
838 | { | ||
839 | Byte b = data[i]; | ||
840 | dest += GetHex((Byte)((b >> 4) & 0xF)); | ||
841 | dest += GetHex((Byte)(b & 0xF)); | ||
842 | } | ||
843 | } | ||
844 | |||
845 | void HashHexToString(char *dest, const Byte *data, UInt32 size); | ||
846 | |||
847 | HRESULT CUpdateCallbackConsole::ReportRawProp(UInt32 indexType, UInt32 index, | ||
848 | PROPID propID, const void *data, UInt32 dataSize, UInt32 propType) | ||
849 | { | ||
850 | UString s; | ||
851 | propType = propType; | ||
852 | Add_IndexType_Index(s, indexType, index); | ||
853 | AddPropNamePrefix(s, propID); | ||
854 | if (propID == kpidChecksum) | ||
855 | { | ||
856 | char temp[k_HashCalc_DigestSize_Max + 8]; | ||
857 | HashHexToString(temp, (const Byte *)data, dataSize); | ||
858 | s += temp; | ||
859 | } | ||
860 | else | ||
861 | AddHexToString(s, (const Byte *)data, dataSize); | ||
862 | PrintInfoLine(s); | ||
863 | return S_OK; | ||
864 | } | ||
865 | |||
866 | HRESULT CUpdateCallbackConsole::ReportFinished(UInt32 indexType, UInt32 index, Int32 opRes) | ||
867 | { | ||
868 | UString s; | ||
869 | Add_IndexType_Index(s, indexType, index); | ||
870 | s += "finished"; | ||
871 | if (opRes != NArchive::NUpdate::NOperationResult::kOK) | ||
872 | { | ||
873 | s += ": "; | ||
874 | s.Add_UInt32(opRes); | ||
875 | } | ||
876 | PrintInfoLine(s); | ||
877 | return S_OK; | ||
878 | } | ||
879 | */ | ||
diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.h b/CPP/7zip/UI/Console/UpdateCallbackConsole.h index 700d511..b7ffef0 100644 --- a/CPP/7zip/UI/Console/UpdateCallbackConsole.h +++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.h | |||
@@ -35,7 +35,8 @@ protected: | |||
35 | CStdOutStream *_se; | 35 | CStdOutStream *_se; |
36 | 36 | ||
37 | void CommonError(const FString &path, DWORD systemError, bool isWarning); | 37 | void CommonError(const FString &path, DWORD systemError, bool isWarning); |
38 | 38 | // void CommonError(const char *message); | |
39 | |||
39 | HRESULT ScanError_Base(const FString &path, DWORD systemError); | 40 | HRESULT ScanError_Base(const FString &path, DWORD systemError); |
40 | HRESULT OpenFileError_Base(const FString &name, DWORD systemError); | 41 | HRESULT OpenFileError_Base(const FString &name, DWORD systemError); |
41 | HRESULT ReadingFileError_Base(const FString &name, DWORD systemError); | 42 | HRESULT ReadingFileError_Base(const FString &name, DWORD systemError); |
@@ -89,6 +90,8 @@ public: | |||
89 | 90 | ||
90 | HRESULT PrintProgress(const wchar_t *name, bool isDir, const char *command, bool showInLog); | 91 | HRESULT PrintProgress(const wchar_t *name, bool isDir, const char *command, bool showInLog); |
91 | 92 | ||
93 | // void PrintInfoLine(const UString &s); | ||
94 | // void PrintPropInfo(UString &s, PROPID propID, const PROPVARIANT *value); | ||
92 | }; | 95 | }; |
93 | 96 | ||
94 | class CUpdateCallbackConsole: public IUpdateCallbackUI2, public CCallbackConsoleBase | 97 | class CUpdateCallbackConsole: public IUpdateCallbackUI2, public CCallbackConsoleBase |
diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp index 6907021..7dbb504 100644 --- a/CPP/7zip/UI/Explorer/ContextMenu.cpp +++ b/CPP/7zip/UI/Explorer/ContextMenu.cpp | |||
@@ -102,6 +102,7 @@ CZipContextMenu::CZipContextMenu(): | |||
102 | _isMenuForFM(false), | 102 | _isMenuForFM(false), |
103 | _dropMode(false), | 103 | _dropMode(false), |
104 | _bitmap(NULL), | 104 | _bitmap(NULL), |
105 | _writeZone((UInt32)(Int32)-1), | ||
105 | IsSeparator(false), | 106 | IsSeparator(false), |
106 | IsRoot(true), | 107 | IsRoot(true), |
107 | CurrentSubCommand(0) | 108 | CurrentSubCommand(0) |
@@ -560,6 +561,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, | |||
560 | ci.Load(); | 561 | ci.Load(); |
561 | 562 | ||
562 | _elimDup = ci.ElimDup; | 563 | _elimDup = ci.ElimDup; |
564 | _writeZone = ci.WriteZone; | ||
563 | 565 | ||
564 | HBITMAP bitmap = NULL; | 566 | HBITMAP bitmap = NULL; |
565 | if (ci.MenuIcons.Val) | 567 | if (ci.MenuIcons.Val) |
@@ -1167,7 +1169,8 @@ HRESULT CZipContextMenu::InvokeCommandCommon(const CCommandMapItem &cmi) | |||
1167 | { | 1169 | { |
1168 | ExtractArchives(_fileNames, cmi.Folder, | 1170 | ExtractArchives(_fileNames, cmi.Folder, |
1169 | (cmdID == kExtract), // showDialog | 1171 | (cmdID == kExtract), // showDialog |
1170 | (cmdID == kExtractTo) && _elimDup.Val // elimDup | 1172 | (cmdID == kExtractTo) && _elimDup.Val, // elimDup |
1173 | _writeZone | ||
1171 | ); | 1174 | ); |
1172 | break; | 1175 | break; |
1173 | } | 1176 | } |
diff --git a/CPP/7zip/UI/Explorer/ContextMenu.h b/CPP/7zip/UI/Explorer/ContextMenu.h index 285044e..5b56d63 100644 --- a/CPP/7zip/UI/Explorer/ContextMenu.h +++ b/CPP/7zip/UI/Explorer/ContextMenu.h | |||
@@ -129,6 +129,7 @@ private: | |||
129 | 129 | ||
130 | HBITMAP _bitmap; | 130 | HBITMAP _bitmap; |
131 | CBoolPair _elimDup; | 131 | CBoolPair _elimDup; |
132 | UInt32 _writeZone; | ||
132 | 133 | ||
133 | bool IsSeparator; | 134 | bool IsSeparator; |
134 | bool IsRoot; | 135 | bool IsRoot; |
diff --git a/CPP/7zip/UI/FileManager/FSFolder.cpp b/CPP/7zip/UI/FileManager/FSFolder.cpp index f3e04b3..72cb0ce 100644 --- a/CPP/7zip/UI/FileManager/FSFolder.cpp +++ b/CPP/7zip/UI/FileManager/FSFolder.cpp | |||
@@ -2,11 +2,19 @@ | |||
2 | 2 | ||
3 | #include "StdAfx.h" | 3 | #include "StdAfx.h" |
4 | 4 | ||
5 | #if defined(_MSC_VER) | ||
6 | #include <winternl.h> | ||
7 | #else | ||
8 | // mingw | ||
9 | #include <ddk/winddk.h> | ||
10 | #endif | ||
11 | |||
5 | #include "../../../Common/ComTry.h" | 12 | #include "../../../Common/ComTry.h" |
6 | #include "../../../Common/Defs.h" | 13 | #include "../../../Common/Defs.h" |
7 | #include "../../../Common/StringConvert.h" | 14 | #include "../../../Common/StringConvert.h" |
8 | #include "../../../Common/UTFConvert.h" | 15 | #include "../../../Common/UTFConvert.h" |
9 | 16 | ||
17 | #include "../../../Windows/DLL.h" | ||
10 | #include "../../../Windows/FileDir.h" | 18 | #include "../../../Windows/FileDir.h" |
11 | #include "../../../Windows/FileIO.h" | 19 | #include "../../../Windows/FileIO.h" |
12 | #include "../../../Windows/FileName.h" | 20 | #include "../../../Windows/FileName.h" |
@@ -56,12 +64,15 @@ static const Byte kProps[] = | |||
56 | kpidMTime, | 64 | kpidMTime, |
57 | kpidCTime, | 65 | kpidCTime, |
58 | kpidATime, | 66 | kpidATime, |
67 | #ifdef FS_SHOW_LINKS_INFO | ||
68 | kpidChangeTime, | ||
69 | #endif | ||
59 | kpidAttrib, | 70 | kpidAttrib, |
60 | kpidPackSize, | 71 | kpidPackSize, |
61 | #ifdef FS_SHOW_LINKS_INFO | 72 | #ifdef FS_SHOW_LINKS_INFO |
62 | kpidINode, | 73 | kpidINode, |
63 | kpidLinks, | 74 | kpidLinks, |
64 | #endif | 75 | #endif |
65 | kpidComment, | 76 | kpidComment, |
66 | kpidNumSubDirs, | 77 | kpidNumSubDirs, |
67 | kpidNumSubFiles, | 78 | kpidNumSubFiles, |
@@ -199,19 +210,23 @@ HRESULT CFSFolder::LoadSubItems(int dirItem, const FString &relPrefix) | |||
199 | */ | 210 | */ |
200 | } | 211 | } |
201 | 212 | ||
202 | #ifndef UNDER_CE | 213 | #ifndef UNDER_CE |
203 | 214 | ||
204 | fi.Reparse.Free(); | 215 | fi.Reparse.Free(); |
205 | fi.PackSize_Defined = false; | 216 | fi.PackSize_Defined = false; |
206 | 217 | ||
207 | #ifdef FS_SHOW_LINKS_INFO | 218 | #ifdef FS_SHOW_LINKS_INFO |
208 | fi.FileInfo_Defined = false; | 219 | fi.FileInfo_Defined = false; |
209 | fi.FileInfo_WasRequested = false; | 220 | fi.FileInfo_WasRequested = false; |
210 | fi.FileIndex = 0; | 221 | fi.FileIndex = 0; |
211 | fi.NumLinks = 0; | 222 | fi.NumLinks = 0; |
212 | #endif | 223 | fi.ChangeTime_Defined = false; |
224 | fi.ChangeTime_WasRequested = false; | ||
225 | #endif | ||
213 | 226 | ||
214 | fi.PackSize = fi.Size; | 227 | fi.PackSize = fi.Size; |
228 | |||
229 | #ifdef FS_SHOW_LINKS_INFO | ||
215 | if (fi.HasReparsePoint()) | 230 | if (fi.HasReparsePoint()) |
216 | { | 231 | { |
217 | fi.FileInfo_WasRequested = true; | 232 | fi.FileInfo_WasRequested = true; |
@@ -221,8 +236,9 @@ HRESULT CFSFolder::LoadSubItems(int dirItem, const FString &relPrefix) | |||
221 | fi.FileIndex = (((UInt64)info.nFileIndexHigh) << 32) + info.nFileIndexLow; | 236 | fi.FileIndex = (((UInt64)info.nFileIndexHigh) << 32) + info.nFileIndexLow; |
222 | fi.FileInfo_Defined = true; | 237 | fi.FileInfo_Defined = true; |
223 | } | 238 | } |
239 | #endif | ||
224 | 240 | ||
225 | #endif | 241 | #endif // UNDER_CE |
226 | 242 | ||
227 | /* unsigned fileIndex = */ Files.Add(fi); | 243 | /* unsigned fileIndex = */ Files.Add(fi); |
228 | 244 | ||
@@ -396,7 +412,9 @@ STDMETHODIMP_(UInt64) CFSFolder::GetItemSize(UInt32 index) | |||
396 | 412 | ||
397 | #endif | 413 | #endif |
398 | 414 | ||
415 | |||
399 | #ifdef FS_SHOW_LINKS_INFO | 416 | #ifdef FS_SHOW_LINKS_INFO |
417 | |||
400 | bool CFSFolder::ReadFileInfo(CDirItem &di) | 418 | bool CFSFolder::ReadFileInfo(CDirItem &di) |
401 | { | 419 | { |
402 | di.FileInfo_WasRequested = true; | 420 | di.FileInfo_WasRequested = true; |
@@ -409,7 +427,71 @@ bool CFSFolder::ReadFileInfo(CDirItem &di) | |||
409 | di.FileInfo_Defined = true; | 427 | di.FileInfo_Defined = true; |
410 | return true; | 428 | return true; |
411 | } | 429 | } |
412 | #endif | 430 | |
431 | |||
432 | typedef struct | ||
433 | { | ||
434 | LARGE_INTEGER CreationTime; | ||
435 | LARGE_INTEGER LastAccessTime; | ||
436 | LARGE_INTEGER LastWriteTime; | ||
437 | LARGE_INTEGER ChangeTime; | ||
438 | ULONG FileAttributes; | ||
439 | UInt32 Reserved; // it's expected for alignment | ||
440 | } | ||
441 | MY__FILE_BASIC_INFORMATION; | ||
442 | |||
443 | |||
444 | typedef enum | ||
445 | { | ||
446 | MY__FileDirectoryInformation = 1, | ||
447 | MY__FileFullDirectoryInformation, | ||
448 | MY__FileBothDirectoryInformation, | ||
449 | MY__FileBasicInformation | ||
450 | } | ||
451 | MY__FILE_INFORMATION_CLASS; | ||
452 | |||
453 | |||
454 | typedef NTSTATUS (WINAPI * Func_NtQueryInformationFile)( | ||
455 | HANDLE handle, IO_STATUS_BLOCK *io, | ||
456 | void *ptr, LONG len, MY__FILE_INFORMATION_CLASS cls); | ||
457 | |||
458 | #define MY__STATUS_SUCCESS 0 | ||
459 | |||
460 | static Func_NtQueryInformationFile f_NtQueryInformationFile; | ||
461 | static bool g_NtQueryInformationFile_WasRequested = false; | ||
462 | |||
463 | void CFSFolder::ReadChangeTime(CDirItem &di) | ||
464 | { | ||
465 | di.ChangeTime_WasRequested = true; | ||
466 | |||
467 | if (!g_NtQueryInformationFile_WasRequested) | ||
468 | { | ||
469 | g_NtQueryInformationFile_WasRequested = true; | ||
470 | f_NtQueryInformationFile = (Func_NtQueryInformationFile) | ||
471 | My_GetProcAddress(::GetModuleHandleW(L"ntdll.dll"), | ||
472 | "NtQueryInformationFile"); | ||
473 | } | ||
474 | if (!f_NtQueryInformationFile) | ||
475 | return; | ||
476 | |||
477 | NIO::CInFile file; | ||
478 | if (!file.Open_for_ReadAttributes(_path + GetRelPath(di))) | ||
479 | return; | ||
480 | MY__FILE_BASIC_INFORMATION fbi; | ||
481 | IO_STATUS_BLOCK IoStatusBlock; | ||
482 | const NTSTATUS status = f_NtQueryInformationFile(file.GetHandle(), &IoStatusBlock, | ||
483 | &fbi, sizeof(fbi), MY__FileBasicInformation); | ||
484 | if (status != MY__STATUS_SUCCESS) | ||
485 | return; | ||
486 | if (IoStatusBlock.Information != sizeof(fbi)) | ||
487 | return; | ||
488 | di.ChangeTime.dwLowDateTime = fbi.ChangeTime.u.LowPart; | ||
489 | di.ChangeTime.dwHighDateTime = fbi.ChangeTime.u.HighPart; | ||
490 | di.ChangeTime_Defined = true; | ||
491 | } | ||
492 | |||
493 | #endif // FS_SHOW_LINKS_INFO | ||
494 | |||
413 | 495 | ||
414 | STDMETHODIMP CFSFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) | 496 | STDMETHODIMP CFSFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) |
415 | { | 497 | { |
@@ -492,7 +574,14 @@ STDMETHODIMP CFSFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va | |||
492 | prop = fi.FileIndex; | 574 | prop = fi.FileIndex; |
493 | #endif | 575 | #endif |
494 | break; | 576 | break; |
495 | 577 | ||
578 | case kpidChangeTime: | ||
579 | if (!fi.ChangeTime_WasRequested) | ||
580 | ReadChangeTime(fi); | ||
581 | if (fi.ChangeTime_Defined) | ||
582 | prop = fi.ChangeTime; | ||
583 | break; | ||
584 | |||
496 | #endif | 585 | #endif |
497 | 586 | ||
498 | case kpidAttrib: prop = (UInt32)fi.Attrib; break; | 587 | case kpidAttrib: prop = (UInt32)fi.Attrib; break; |
diff --git a/CPP/7zip/UI/FileManager/FSFolder.h b/CPP/7zip/UI/FileManager/FSFolder.h index fac1ef9..4f8c344 100644 --- a/CPP/7zip/UI/FileManager/FSFolder.h +++ b/CPP/7zip/UI/FileManager/FSFolder.h | |||
@@ -18,6 +18,7 @@ namespace NFsFolder { | |||
18 | class CFSFolder; | 18 | class CFSFolder; |
19 | 19 | ||
20 | #define FS_SHOW_LINKS_INFO | 20 | #define FS_SHOW_LINKS_INFO |
21 | // #define FS_SHOW_CHANGE_TIME | ||
21 | 22 | ||
22 | struct CDirItem: public NWindows::NFile::NFind::CFileInfo | 23 | struct CDirItem: public NWindows::NFile::NFind::CFileInfo |
23 | { | 24 | { |
@@ -26,10 +27,13 @@ struct CDirItem: public NWindows::NFile::NFind::CFileInfo | |||
26 | #endif | 27 | #endif |
27 | 28 | ||
28 | #ifdef FS_SHOW_LINKS_INFO | 29 | #ifdef FS_SHOW_LINKS_INFO |
30 | FILETIME ChangeTime; | ||
29 | UInt64 FileIndex; | 31 | UInt64 FileIndex; |
30 | UInt32 NumLinks; | 32 | UInt32 NumLinks; |
31 | bool FileInfo_Defined; | 33 | bool FileInfo_Defined; |
32 | bool FileInfo_WasRequested; | 34 | bool FileInfo_WasRequested; |
35 | bool ChangeTime_Defined; | ||
36 | bool ChangeTime_WasRequested; | ||
33 | #endif | 37 | #endif |
34 | 38 | ||
35 | #ifndef UNDER_CE | 39 | #ifndef UNDER_CE |
@@ -158,6 +162,7 @@ private: | |||
158 | 162 | ||
159 | #ifdef FS_SHOW_LINKS_INFO | 163 | #ifdef FS_SHOW_LINKS_INFO |
160 | bool ReadFileInfo(CDirItem &di); | 164 | bool ReadFileInfo(CDirItem &di); |
165 | void ReadChangeTime(CDirItem &di); | ||
161 | #endif | 166 | #endif |
162 | 167 | ||
163 | public: | 168 | public: |
diff --git a/CPP/7zip/UI/FileManager/HelpUtils.cpp b/CPP/7zip/UI/FileManager/HelpUtils.cpp index 2db9501..5cb78fc 100644 --- a/CPP/7zip/UI/FileManager/HelpUtils.cpp +++ b/CPP/7zip/UI/FileManager/HelpUtils.cpp | |||
@@ -12,7 +12,20 @@ void ShowHelpWindow(LPCSTR) | |||
12 | 12 | ||
13 | #else | 13 | #else |
14 | 14 | ||
15 | // #define USE_EXTERNAL_HELP | ||
16 | |||
17 | #if defined(_MSC_VER) | ||
18 | #endif | ||
19 | |||
20 | #ifdef USE_EXTERNAL_HELP | ||
21 | |||
22 | #include "../../../Windows/ProcessUtils.h" | ||
23 | #include "../../../Windows/FileDir.h" | ||
24 | #include "../../../Windows/FileName.h" | ||
25 | |||
26 | #else | ||
15 | #include <HtmlHelp.h> | 27 | #include <HtmlHelp.h> |
28 | #endif | ||
16 | 29 | ||
17 | #include "../../../Common/StringConvert.h" | 30 | #include "../../../Common/StringConvert.h" |
18 | 31 | ||
@@ -25,8 +38,37 @@ void ShowHelpWindow(LPCSTR topicFile) | |||
25 | FString path = NWindows::NDLL::GetModuleDirPrefix(); | 38 | FString path = NWindows::NDLL::GetModuleDirPrefix(); |
26 | path += kHelpFileName; | 39 | path += kHelpFileName; |
27 | path += topicFile; | 40 | path += topicFile; |
41 | #ifdef USE_EXTERNAL_HELP | ||
42 | FString prog; | ||
43 | |||
44 | #ifdef UNDER_CE | ||
45 | prog = "\\Windows\\"; | ||
46 | #else | ||
47 | if (!NWindows::NFile::NDir::GetWindowsDir(prog)) | ||
48 | return; | ||
49 | NWindows::NFile::NName::NormalizeDirPathPrefix(prog); | ||
50 | #endif | ||
51 | prog += "hh.exe"; | ||
52 | |||
53 | UString params; | ||
54 | params += '"'; | ||
55 | params += fs2us(path); | ||
56 | params += '"'; | ||
57 | |||
58 | NWindows::CProcess process; | ||
59 | const WRes wres = process.Create(fs2us(prog), params, NULL); // curDir); | ||
60 | if (wres != 0) | ||
61 | { | ||
62 | /* | ||
63 | HRESULT hres = HRESULT_FROM_WIN32(wres); | ||
64 | ErrorMessageHRESULT(hres, imageName); | ||
65 | return hres; | ||
66 | */ | ||
67 | } | ||
68 | #else | ||
28 | // HWND hwnd = NULL; | 69 | // HWND hwnd = NULL; |
29 | HtmlHelp(NULL, GetSystemString(fs2us(path)), HH_DISPLAY_TOPIC, 0); | 70 | HtmlHelp(NULL, GetSystemString(fs2us(path)), HH_DISPLAY_TOPIC, 0); |
71 | #endif | ||
30 | } | 72 | } |
31 | 73 | ||
32 | #endif | 74 | #endif |
diff --git a/CPP/7zip/UI/FileManager/MenuPage.cpp b/CPP/7zip/UI/FileManager/MenuPage.cpp index 05f24d7..32dabae 100644 --- a/CPP/7zip/UI/FileManager/MenuPage.cpp +++ b/CPP/7zip/UI/FileManager/MenuPage.cpp | |||
@@ -32,6 +32,7 @@ static const UInt32 kLangIDs[] = | |||
32 | IDX_SYSTEM_CASCADED_MENU, | 32 | IDX_SYSTEM_CASCADED_MENU, |
33 | IDX_SYSTEM_ICON_IN_MENU, | 33 | IDX_SYSTEM_ICON_IN_MENU, |
34 | IDX_EXTRACT_ELIM_DUP, | 34 | IDX_EXTRACT_ELIM_DUP, |
35 | IDT_SYSTEM_ZONE, | ||
35 | IDT_SYSTEM_CONTEXT_MENU_ITEMS | 36 | IDT_SYSTEM_CONTEXT_MENU_ITEMS |
36 | }; | 37 | }; |
37 | 38 | ||
@@ -80,6 +81,16 @@ extern bool g_Is_Wow64; | |||
80 | #define KEY_WOW64_32KEY (0x0200) | 81 | #define KEY_WOW64_32KEY (0x0200) |
81 | #endif | 82 | #endif |
82 | 83 | ||
84 | |||
85 | static void LoadLang_Spec(UString &s, UInt32 id, const char *eng) | ||
86 | { | ||
87 | LangString(id, s); | ||
88 | if (s.IsEmpty()) | ||
89 | s = eng; | ||
90 | s.RemoveChar(L'&'); | ||
91 | } | ||
92 | |||
93 | |||
83 | bool CMenuPage::OnInit() | 94 | bool CMenuPage::OnInit() |
84 | { | 95 | { |
85 | _initMode = true; | 96 | _initMode = true; |
@@ -176,6 +187,44 @@ bool CMenuPage::OnInit() | |||
176 | CheckButton(IDX_EXTRACT_ELIM_DUP, ci.ElimDup.Val); | 187 | CheckButton(IDX_EXTRACT_ELIM_DUP, ci.ElimDup.Val); |
177 | 188 | ||
178 | _listView.Attach(GetItem(IDL_SYSTEM_OPTIONS)); | 189 | _listView.Attach(GetItem(IDL_SYSTEM_OPTIONS)); |
190 | _zoneCombo.Attach(GetItem(IDC_SYSTEM_ZONE)); | ||
191 | |||
192 | { | ||
193 | unsigned wz = ci.WriteZone; | ||
194 | if (wz == (UInt32)(Int32)-1) | ||
195 | wz = 0; | ||
196 | for (unsigned i = 0; i <= 3; i++) | ||
197 | { | ||
198 | unsigned val = i; | ||
199 | UString s; | ||
200 | if (i == 3) | ||
201 | { | ||
202 | if (wz < 3) | ||
203 | break; | ||
204 | val = wz; | ||
205 | } | ||
206 | else | ||
207 | { | ||
208 | #define MY_IDYES 406 | ||
209 | #define MY_IDNO 407 | ||
210 | if (i == 0) | ||
211 | LoadLang_Spec(s, MY_IDNO, "No"); | ||
212 | else if (i == 1) | ||
213 | LoadLang_Spec(s, MY_IDYES, "Yes"); | ||
214 | else | ||
215 | LangString(IDT_ZONE_FOR_OFFICE, s); | ||
216 | } | ||
217 | if (s.IsEmpty()) | ||
218 | s.Add_UInt32(val); | ||
219 | if (i == 0) | ||
220 | s.Insert(0, L"* "); | ||
221 | const int index = (int)_zoneCombo.AddString(s); | ||
222 | _zoneCombo.SetItemData(index, val); | ||
223 | if (val == wz) | ||
224 | _zoneCombo.SetCurSel(index); | ||
225 | } | ||
226 | } | ||
227 | |||
179 | 228 | ||
180 | const UInt32 newFlags = LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT; | 229 | const UInt32 newFlags = LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT; |
181 | _listView.SetExtendedListViewStyle(newFlags, newFlags); | 230 | _listView.SetExtendedListViewStyle(newFlags, newFlags); |
@@ -266,7 +315,11 @@ LONG CMenuPage::OnApply() | |||
266 | 315 | ||
267 | #endif | 316 | #endif |
268 | 317 | ||
269 | if (_cascaded_Changed || _menuIcons_Changed || _elimDup_Changed || _flags_Changed) | 318 | if (_cascaded_Changed |
319 | || _menuIcons_Changed | ||
320 | || _elimDup_Changed | ||
321 | || _writeZone_Changed | ||
322 | || _flags_Changed) | ||
270 | { | 323 | { |
271 | CContextMenuInfo ci; | 324 | CContextMenuInfo ci; |
272 | ci.Cascaded.Val = IsButtonCheckedBool(IDX_SYSTEM_CASCADED_MENU); | 325 | ci.Cascaded.Val = IsButtonCheckedBool(IDX_SYSTEM_CASCADED_MENU); |
@@ -278,6 +331,13 @@ LONG CMenuPage::OnApply() | |||
278 | ci.ElimDup.Val = IsButtonCheckedBool(IDX_EXTRACT_ELIM_DUP); | 331 | ci.ElimDup.Val = IsButtonCheckedBool(IDX_EXTRACT_ELIM_DUP); |
279 | ci.ElimDup.Def = _elimDup_Changed; | 332 | ci.ElimDup.Def = _elimDup_Changed; |
280 | 333 | ||
334 | { | ||
335 | int zoneIndex = (int)_zoneCombo.GetItemData_of_CurSel(); | ||
336 | if (zoneIndex <= 0) | ||
337 | zoneIndex = -1; | ||
338 | ci.WriteZone = (UInt32)(Int32)zoneIndex; | ||
339 | } | ||
340 | |||
281 | ci.Flags = 0; | 341 | ci.Flags = 0; |
282 | 342 | ||
283 | for (unsigned i = 0; i < ARRAY_SIZE(kMenuItems); i++) | 343 | for (unsigned i = 0; i < ARRAY_SIZE(kMenuItems); i++) |
@@ -321,6 +381,7 @@ bool CMenuPage::OnButtonClicked(int buttonID, HWND buttonHWND) | |||
321 | case IDX_SYSTEM_CASCADED_MENU: _cascaded_Changed = true; break; | 381 | case IDX_SYSTEM_CASCADED_MENU: _cascaded_Changed = true; break; |
322 | case IDX_SYSTEM_ICON_IN_MENU: _menuIcons_Changed = true; break; | 382 | case IDX_SYSTEM_ICON_IN_MENU: _menuIcons_Changed = true; break; |
323 | case IDX_EXTRACT_ELIM_DUP: _elimDup_Changed = true; break; | 383 | case IDX_EXTRACT_ELIM_DUP: _elimDup_Changed = true; break; |
384 | // case IDX_EXTRACT_WRITE_ZONE: _writeZone_Changed = true; break; | ||
324 | 385 | ||
325 | default: | 386 | default: |
326 | return CPropertyPage::OnButtonClicked(buttonID, buttonHWND); | 387 | return CPropertyPage::OnButtonClicked(buttonID, buttonHWND); |
@@ -330,6 +391,19 @@ bool CMenuPage::OnButtonClicked(int buttonID, HWND buttonHWND) | |||
330 | return true; | 391 | return true; |
331 | } | 392 | } |
332 | 393 | ||
394 | |||
395 | bool CMenuPage::OnCommand(int code, int itemID, LPARAM param) | ||
396 | { | ||
397 | if (code == CBN_SELCHANGE && itemID == IDC_SYSTEM_ZONE) | ||
398 | { | ||
399 | _writeZone_Changed = true; | ||
400 | Changed(); | ||
401 | return true; | ||
402 | } | ||
403 | return CPropertyPage::OnCommand(code, itemID, param); | ||
404 | } | ||
405 | |||
406 | |||
333 | bool CMenuPage::OnNotify(UINT controlID, LPNMHDR lParam) | 407 | bool CMenuPage::OnNotify(UINT controlID, LPNMHDR lParam) |
334 | { | 408 | { |
335 | if (lParam->hwndFrom == HWND(_listView)) | 409 | if (lParam->hwndFrom == HWND(_listView)) |
diff --git a/CPP/7zip/UI/FileManager/MenuPage.h b/CPP/7zip/UI/FileManager/MenuPage.h index 3807d9d..02aee6d 100644 --- a/CPP/7zip/UI/FileManager/MenuPage.h +++ b/CPP/7zip/UI/FileManager/MenuPage.h | |||
@@ -4,6 +4,7 @@ | |||
4 | #define __MENU_PAGE_H | 4 | #define __MENU_PAGE_H |
5 | 5 | ||
6 | #include "../../../Windows/Control/PropertyPage.h" | 6 | #include "../../../Windows/Control/PropertyPage.h" |
7 | #include "../../../Windows/Control/ComboBox.h" | ||
7 | #include "../../../Windows/Control/ListView.h" | 8 | #include "../../../Windows/Control/ListView.h" |
8 | 9 | ||
9 | struct CShellDll | 10 | struct CShellDll |
@@ -24,6 +25,7 @@ class CMenuPage: public NWindows::NControl::CPropertyPage | |||
24 | bool _cascaded_Changed; | 25 | bool _cascaded_Changed; |
25 | bool _menuIcons_Changed; | 26 | bool _menuIcons_Changed; |
26 | bool _elimDup_Changed; | 27 | bool _elimDup_Changed; |
28 | bool _writeZone_Changed; | ||
27 | bool _flags_Changed; | 29 | bool _flags_Changed; |
28 | 30 | ||
29 | void Clear_MenuChanged() | 31 | void Clear_MenuChanged() |
@@ -31,6 +33,7 @@ class CMenuPage: public NWindows::NControl::CPropertyPage | |||
31 | _cascaded_Changed = false; | 33 | _cascaded_Changed = false; |
32 | _menuIcons_Changed = false; | 34 | _menuIcons_Changed = false; |
33 | _elimDup_Changed = false; | 35 | _elimDup_Changed = false; |
36 | _writeZone_Changed = false; | ||
34 | _flags_Changed = false; | 37 | _flags_Changed = false; |
35 | } | 38 | } |
36 | 39 | ||
@@ -39,6 +42,7 @@ class CMenuPage: public NWindows::NControl::CPropertyPage | |||
39 | #endif | 42 | #endif |
40 | 43 | ||
41 | NWindows::NControl::CListView _listView; | 44 | NWindows::NControl::CListView _listView; |
45 | NWindows::NControl::CComboBox _zoneCombo; | ||
42 | 46 | ||
43 | virtual bool OnInit(); | 47 | virtual bool OnInit(); |
44 | virtual void OnNotifyHelp(); | 48 | virtual void OnNotifyHelp(); |
@@ -46,6 +50,7 @@ class CMenuPage: public NWindows::NControl::CPropertyPage | |||
46 | virtual bool OnItemChanged(const NMLISTVIEW *info); | 50 | virtual bool OnItemChanged(const NMLISTVIEW *info); |
47 | virtual LONG OnApply(); | 51 | virtual LONG OnApply(); |
48 | virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); | 52 | virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); |
53 | virtual bool OnCommand(int code, int itemID, LPARAM param); | ||
49 | public: | 54 | public: |
50 | }; | 55 | }; |
51 | 56 | ||
diff --git a/CPP/7zip/UI/FileManager/MenuPage2.rc b/CPP/7zip/UI/FileManager/MenuPage2.rc index af86226..4d1ba21 100644 --- a/CPP/7zip/UI/FileManager/MenuPage2.rc +++ b/CPP/7zip/UI/FileManager/MenuPage2.rc | |||
@@ -1,6 +1,8 @@ | |||
1 | #include "../GUI/ExtractDialogRes.h" | 1 | #include "../GUI/ExtractDialogRes.h" |
2 | 2 | ||
3 | #define y 82 | 3 | #define y 96 |
4 | |||
5 | #define zoneX 90 | ||
4 | 6 | ||
5 | CAPTION "7-Zip" | 7 | CAPTION "7-Zip" |
6 | BEGIN | 8 | BEGIN |
@@ -10,8 +12,17 @@ BEGIN | |||
10 | CONTROL "Icons in context menu", IDX_SYSTEM_ICON_IN_MENU, MY_CHECKBOX, m, m + 42, xc, 10 | 12 | CONTROL "Icons in context menu", IDX_SYSTEM_ICON_IN_MENU, MY_CHECKBOX, m, m + 42, xc, 10 |
11 | CONTROL "Eliminate duplication of root folder", IDX_EXTRACT_ELIM_DUP, MY_CHECKBOX, m, m + 56, xc, 10 | 13 | CONTROL "Eliminate duplication of root folder", IDX_EXTRACT_ELIM_DUP, MY_CHECKBOX, m, m + 56, xc, 10 |
12 | 14 | ||
13 | LTEXT "Context menu items:", IDT_SYSTEM_CONTEXT_MENU_ITEMS, m, m + 70, xc, 8 | 15 | LTEXT "Propagate Zone.Id stream:", IDT_SYSTEM_ZONE, m, m + 70, xc - zoneX, 8 |
16 | COMBOBOX IDC_SYSTEM_ZONE, m + xc - zoneX, m + 70 - 2, zoneX, 50, MY_COMBO | ||
17 | |||
18 | LTEXT "Context menu items:", IDT_SYSTEM_CONTEXT_MENU_ITEMS, m, m + 84, xc, 8 | ||
14 | CONTROL "List", IDL_SYSTEM_OPTIONS, "SysListView32", | 19 | CONTROL "List", IDL_SYSTEM_OPTIONS, "SysListView32", |
15 | LVS_REPORT | LVS_SINGLESEL | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP, | 20 | LVS_REPORT | LVS_SINGLESEL | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP, |
16 | m, m + y, xc, yc - y | 21 | m, m + y, xc, yc - y |
17 | END | 22 | END |
23 | |||
24 | |||
25 | STRINGTABLE | ||
26 | BEGIN | ||
27 | IDT_ZONE_FOR_OFFICE "For Office files" | ||
28 | END | ||
diff --git a/CPP/7zip/UI/FileManager/MenuPageRes.h b/CPP/7zip/UI/FileManager/MenuPageRes.h index ae0bf66..e2cf798 100644 --- a/CPP/7zip/UI/FileManager/MenuPageRes.h +++ b/CPP/7zip/UI/FileManager/MenuPageRes.h | |||
@@ -8,4 +8,8 @@ | |||
8 | 8 | ||
9 | #define IDX_SYSTEM_INTEGRATE_TO_MENU_2 2310 | 9 | #define IDX_SYSTEM_INTEGRATE_TO_MENU_2 2310 |
10 | 10 | ||
11 | #define IDT_SYSTEM_ZONE 3440 | ||
12 | #define IDT_ZONE_FOR_OFFICE 3441 | ||
13 | |||
11 | #define IDL_SYSTEM_OPTIONS 100 | 14 | #define IDL_SYSTEM_OPTIONS 100 |
15 | #define IDC_SYSTEM_ZONE 101 | ||
diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp index d87dfe3..3973bb2 100644 --- a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp +++ b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp | |||
@@ -380,7 +380,8 @@ void OnMenuActivating(HWND /* hWnd */, HMENU hMenu, int position) | |||
380 | kTimestampPrintLevel_MIN, | 380 | kTimestampPrintLevel_MIN, |
381 | kTimestampPrintLevel_SEC, | 381 | kTimestampPrintLevel_SEC, |
382 | // 1,2,3,4,5,6, | 382 | // 1,2,3,4,5,6, |
383 | kTimestampPrintLevel_NTFS | 383 | kTimestampPrintLevel_NTFS, |
384 | kTimestampPrintLevel_NS | ||
384 | }; | 385 | }; |
385 | 386 | ||
386 | unsigned last = kMenuID_Time; | 387 | unsigned last = kMenuID_Time; |
diff --git a/CPP/7zip/UI/FileManager/Panel.cpp b/CPP/7zip/UI/FileManager/Panel.cpp index e8c0b94..f7cdb5b 100644 --- a/CPP/7zip/UI/FileManager/Panel.cpp +++ b/CPP/7zip/UI/FileManager/Panel.cpp | |||
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | #include "../Common/ArchiveName.h" | 21 | #include "../Common/ArchiveName.h" |
22 | #include "../Common/CompressCall.h" | 22 | #include "../Common/CompressCall.h" |
23 | #include "../Common/ZipRegistry.h" | ||
23 | 24 | ||
24 | #include "../Agent/IFolderArchive.h" | 25 | #include "../Agent/IFolderArchive.h" |
25 | 26 | ||
@@ -971,9 +972,13 @@ void CPanel::ExtractArchives() | |||
971 | outFolder += '*'; | 972 | outFolder += '*'; |
972 | outFolder.Add_PathSepar(); | 973 | outFolder.Add_PathSepar(); |
973 | 974 | ||
975 | CContextMenuInfo ci; | ||
976 | ci.Load(); | ||
977 | |||
974 | ::ExtractArchives(paths, outFolder | 978 | ::ExtractArchives(paths, outFolder |
975 | , true // showDialog | 979 | , true // showDialog |
976 | , false // elimDup | 980 | , false // elimDup |
981 | , ci.WriteZone | ||
977 | ); | 982 | ); |
978 | } | 983 | } |
979 | 984 | ||
diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h index d1e4d24..4755678 100644 --- a/CPP/7zip/UI/FileManager/Panel.h +++ b/CPP/7zip/UI/FileManager/Panel.h | |||
@@ -244,6 +244,9 @@ struct CCopyToOptions | |||
244 | bool replaceAltStreamChars; | 244 | bool replaceAltStreamChars; |
245 | bool showErrorMessages; | 245 | bool showErrorMessages; |
246 | 246 | ||
247 | bool NeedRegistryZone; | ||
248 | NExtract::NZoneIdMode::EEnum ZoneIdMode; | ||
249 | |||
247 | UString folder; | 250 | UString folder; |
248 | 251 | ||
249 | UStringVector hashMethods; | 252 | UStringVector hashMethods; |
@@ -258,6 +261,8 @@ struct CCopyToOptions | |||
258 | includeAltStreams(true), | 261 | includeAltStreams(true), |
259 | replaceAltStreamChars(false), | 262 | replaceAltStreamChars(false), |
260 | showErrorMessages(false), | 263 | showErrorMessages(false), |
264 | NeedRegistryZone(true), | ||
265 | ZoneIdMode(NExtract::NZoneIdMode::kNone), | ||
261 | VirtFileSystemSpec(NULL), | 266 | VirtFileSystemSpec(NULL), |
262 | VirtFileSystem(NULL) | 267 | VirtFileSystem(NULL) |
263 | {} | 268 | {} |
diff --git a/CPP/7zip/UI/FileManager/PanelCopy.cpp b/CPP/7zip/UI/FileManager/PanelCopy.cpp index 7e1937c..2ea3e3b 100644 --- a/CPP/7zip/UI/FileManager/PanelCopy.cpp +++ b/CPP/7zip/UI/FileManager/PanelCopy.cpp | |||
@@ -4,6 +4,8 @@ | |||
4 | 4 | ||
5 | #include "../../../Common/MyException.h" | 5 | #include "../../../Common/MyException.h" |
6 | 6 | ||
7 | #include "../Common/ZipRegistry.h" | ||
8 | |||
7 | #include "../GUI/HashGUI.h" | 9 | #include "../GUI/HashGUI.h" |
8 | 10 | ||
9 | #include "ExtractCallback.h" | 11 | #include "ExtractCallback.h" |
@@ -70,6 +72,15 @@ HRESULT CPanelCopyThread::ProcessVirt() | |||
70 | 72 | ||
71 | HRESULT result2; | 73 | HRESULT result2; |
72 | 74 | ||
75 | { | ||
76 | CMyComPtr<IFolderSetZoneIdMode> setZoneMode; | ||
77 | FolderOperations.QueryInterface(IID_IFolderSetZoneIdMode, &setZoneMode); | ||
78 | if (setZoneMode) | ||
79 | { | ||
80 | RINOK(setZoneMode->SetZoneIdMode(options->ZoneIdMode)); | ||
81 | } | ||
82 | } | ||
83 | |||
73 | if (options->testMode) | 84 | if (options->testMode) |
74 | { | 85 | { |
75 | CMyComPtr<IArchiveFolder> archiveFolder; | 86 | CMyComPtr<IArchiveFolder> archiveFolder; |
@@ -126,6 +137,14 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &ind | |||
126 | UStringVector *messages, | 137 | UStringVector *messages, |
127 | bool &usePassword, UString &password) | 138 | bool &usePassword, UString &password) |
128 | { | 139 | { |
140 | if (options.NeedRegistryZone && !options.testMode) | ||
141 | { | ||
142 | CContextMenuInfo ci; | ||
143 | ci.Load(); | ||
144 | if (ci.WriteZone != (UInt32)(Int32)-1) | ||
145 | options.ZoneIdMode = (NExtract::NZoneIdMode::EEnum)(int)(Int32)ci.WriteZone; | ||
146 | } | ||
147 | |||
129 | if (IsHashFolder()) | 148 | if (IsHashFolder()) |
130 | { | 149 | { |
131 | if (!options.testMode) | 150 | if (!options.testMode) |
@@ -221,7 +240,7 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &ind | |||
221 | title = LangString(titleID); | 240 | title = LangString(titleID); |
222 | } | 241 | } |
223 | 242 | ||
224 | UString progressWindowTitle ("7-Zip"); // LangString(IDS_APP_TITLE); | 243 | const UString progressWindowTitle ("7-Zip"); // LangString(IDS_APP_TITLE); |
225 | 244 | ||
226 | extracter.MainWindow = GetParent(); | 245 | extracter.MainWindow = GetParent(); |
227 | extracter.MainTitle = progressWindowTitle; | 246 | extracter.MainTitle = progressWindowTitle; |
diff --git a/CPP/7zip/UI/FileManager/PanelCrc.cpp b/CPP/7zip/UI/FileManager/PanelCrc.cpp index 1d483ca..32948d8 100644 --- a/CPP/7zip/UI/FileManager/PanelCrc.cpp +++ b/CPP/7zip/UI/FileManager/PanelCrc.cpp | |||
@@ -351,6 +351,7 @@ HRESULT CApp::CalculateCrc2(const UString &methodName) | |||
351 | options.streamMode = true; | 351 | options.streamMode = true; |
352 | options.showErrorMessages = true; | 352 | options.showErrorMessages = true; |
353 | options.hashMethods.Add(methodName); | 353 | options.hashMethods.Add(methodName); |
354 | options.NeedRegistryZone = false; | ||
354 | 355 | ||
355 | UStringVector messages; | 356 | UStringVector messages; |
356 | return srcPanel.CopyTo(options, indices, &messages); | 357 | return srcPanel.CopyTo(options, indices, &messages); |
diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp index ba54491..17301b5 100644 --- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp +++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp | |||
@@ -1403,7 +1403,7 @@ static THREAD_FUNC_DECL MyThreadFunction(void *param) | |||
1403 | } | 1403 | } |
1404 | 1404 | ||
1405 | 1405 | ||
1406 | 1406 | /* | |
1407 | #if defined(_WIN32) && !defined(UNDER_CE) | 1407 | #if defined(_WIN32) && !defined(UNDER_CE) |
1408 | static const FChar * const k_ZoneId_StreamName = FTEXT(":Zone.Identifier"); | 1408 | static const FChar * const k_ZoneId_StreamName = FTEXT(":Zone.Identifier"); |
1409 | #endif | 1409 | #endif |
@@ -1441,6 +1441,7 @@ static bool WriteZoneFile(CFSTR fileName, const CByteBuffer &buf) | |||
1441 | } | 1441 | } |
1442 | 1442 | ||
1443 | #endif | 1443 | #endif |
1444 | */ | ||
1444 | 1445 | ||
1445 | /* | 1446 | /* |
1446 | class CBufSeqOutStream_WithFile: | 1447 | class CBufSeqOutStream_WithFile: |
@@ -1654,6 +1655,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo | |||
1654 | password = fl.Password; | 1655 | password = fl.Password; |
1655 | } | 1656 | } |
1656 | 1657 | ||
1658 | /* | ||
1657 | #if defined(_WIN32) && !defined(UNDER_CE) | 1659 | #if defined(_WIN32) && !defined(UNDER_CE) |
1658 | CByteBuffer zoneBuf; | 1660 | CByteBuffer zoneBuf; |
1659 | #ifndef _UNICODE | 1661 | #ifndef _UNICODE |
@@ -1666,16 +1668,25 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo | |||
1666 | ReadZoneFile(fl.FilePath + k_ZoneId_StreamName, zoneBuf); | 1668 | ReadZoneFile(fl.FilePath + k_ZoneId_StreamName, zoneBuf); |
1667 | } | 1669 | } |
1668 | #endif | 1670 | #endif |
1671 | */ | ||
1669 | 1672 | ||
1670 | 1673 | ||
1671 | CVirtFileSystem *virtFileSystemSpec = NULL; | 1674 | CVirtFileSystem *virtFileSystemSpec = NULL; |
1672 | CMyComPtr<ISequentialOutStream> virtFileSystem; | 1675 | CMyComPtr<ISequentialOutStream> virtFileSystem; |
1673 | 1676 | ||
1674 | bool isAltStream = IsItem_AltStream(index); | 1677 | const bool isAltStream = IsItem_AltStream(index); |
1675 | 1678 | ||
1676 | CCopyToOptions options; | 1679 | CCopyToOptions options; |
1677 | options.includeAltStreams = true; | 1680 | options.includeAltStreams = true; |
1678 | options.replaceAltStreamChars = isAltStream; | 1681 | options.replaceAltStreamChars = isAltStream; |
1682 | { | ||
1683 | // CContextMenuInfo ci; | ||
1684 | // ci.Load(); | ||
1685 | // if (ci.WriteZone != (UInt32)(Int32)-1) | ||
1686 | // we use kAll when we unpack just one file. | ||
1687 | options.ZoneIdMode = NExtract::NZoneIdMode::kAll; | ||
1688 | options.NeedRegistryZone = false; | ||
1689 | } | ||
1679 | 1690 | ||
1680 | if (tryAsArchive) | 1691 | if (tryAsArchive) |
1681 | { | 1692 | { |
@@ -1706,7 +1717,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo | |||
1706 | options.folder = fs2us(tempDirNorm); | 1717 | options.folder = fs2us(tempDirNorm); |
1707 | options.showErrorMessages = true; | 1718 | options.showErrorMessages = true; |
1708 | 1719 | ||
1709 | HRESULT result = CopyTo(options, indices, &messages, usePassword, password); | 1720 | const HRESULT result = CopyTo(options, indices, &messages, usePassword, password); |
1710 | 1721 | ||
1711 | if (_parentFolders.Size() > 0) | 1722 | if (_parentFolders.Size() > 0) |
1712 | { | 1723 | { |
@@ -1759,6 +1770,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo | |||
1759 | } | 1770 | } |
1760 | 1771 | ||
1761 | 1772 | ||
1773 | /* | ||
1762 | #if defined(_WIN32) && !defined(UNDER_CE) | 1774 | #if defined(_WIN32) && !defined(UNDER_CE) |
1763 | if (zoneBuf.Size() != 0) | 1775 | if (zoneBuf.Size() != 0) |
1764 | { | 1776 | { |
@@ -1768,6 +1780,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo | |||
1768 | } | 1780 | } |
1769 | } | 1781 | } |
1770 | #endif | 1782 | #endif |
1783 | */ | ||
1771 | 1784 | ||
1772 | 1785 | ||
1773 | if (tryAsArchive) | 1786 | if (tryAsArchive) |
diff --git a/CPP/7zip/UI/FileManager/PanelItems.cpp b/CPP/7zip/UI/FileManager/PanelItems.cpp index 33e4458..3cccf27 100644 --- a/CPP/7zip/UI/FileManager/PanelItems.cpp +++ b/CPP/7zip/UI/FileManager/PanelItems.cpp | |||
@@ -29,6 +29,7 @@ static bool GetColumnVisible(PROPID propID, bool isFsFolder) | |||
29 | switch (propID) | 29 | switch (propID) |
30 | { | 30 | { |
31 | case kpidATime: | 31 | case kpidATime: |
32 | case kpidChangeTime: | ||
32 | case kpidAttrib: | 33 | case kpidAttrib: |
33 | case kpidPackSize: | 34 | case kpidPackSize: |
34 | case kpidINode: | 35 | case kpidINode: |
@@ -56,6 +57,7 @@ static int GetColumnAlign(PROPID propID, VARTYPE varType) | |||
56 | case kpidCTime: | 57 | case kpidCTime: |
57 | case kpidATime: | 58 | case kpidATime: |
58 | case kpidMTime: | 59 | case kpidMTime: |
60 | case kpidChangeTime: | ||
59 | return LVCFMT_LEFT; | 61 | return LVCFMT_LEFT; |
60 | } | 62 | } |
61 | 63 | ||
@@ -201,7 +203,7 @@ HRESULT CPanel::InitColumns() | |||
201 | for (i = 0; i < _listViewInfo.Columns.Size(); i++) | 203 | for (i = 0; i < _listViewInfo.Columns.Size(); i++) |
202 | { | 204 | { |
203 | const CColumnInfo &columnInfo = _listViewInfo.Columns[i]; | 205 | const CColumnInfo &columnInfo = _listViewInfo.Columns[i]; |
204 | int index = _columns.FindItem_for_PropID(columnInfo.PropID); | 206 | const int index = _columns.FindItem_for_PropID(columnInfo.PropID); |
205 | if (index >= 0) | 207 | if (index >= 0) |
206 | { | 208 | { |
207 | CPropColumn &item = _columns[index]; | 209 | CPropColumn &item = _columns[index]; |
@@ -650,7 +652,7 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state) | |||
650 | relPath += name; | 652 | relPath += name; |
651 | if (relPath == state.FocusedName) | 653 | if (relPath == state.FocusedName) |
652 | cursorIndex = listViewItemCount; | 654 | cursorIndex = listViewItemCount; |
653 | if (state.SelectedNames.FindInSorted(relPath) >= 0) | 655 | if (state.SelectedNames.FindInSorted(relPath) != -1) |
654 | selected = true; | 656 | selected = true; |
655 | } | 657 | } |
656 | 658 | ||
diff --git a/CPP/7zip/UI/FileManager/PanelMenu.cpp b/CPP/7zip/UI/FileManager/PanelMenu.cpp index 1a09a8f..9e86951 100644 --- a/CPP/7zip/UI/FileManager/PanelMenu.cpp +++ b/CPP/7zip/UI/FileManager/PanelMenu.cpp | |||
@@ -111,7 +111,7 @@ static void AddPropertyString(PROPID propID, const wchar_t *nameBSTR, | |||
111 | val = ConvertSizeToString(v); | 111 | val = ConvertSizeToString(v); |
112 | } | 112 | } |
113 | else | 113 | else |
114 | ConvertPropertyToString2(val, prop, propID); | 114 | ConvertPropertyToString2(val, prop, propID, 9); // we send 9 - is ns precision |
115 | } | 115 | } |
116 | 116 | ||
117 | if (!val.IsEmpty()) | 117 | if (!val.IsEmpty()) |
diff --git a/CPP/7zip/UI/FileManager/PropertyName.rc b/CPP/7zip/UI/FileManager/PropertyName.rc index 5de5aee..e16c526 100644 --- a/CPP/7zip/UI/FileManager/PropertyName.rc +++ b/CPP/7zip/UI/FileManager/PropertyName.rc | |||
@@ -97,4 +97,11 @@ BEGIN | |||
97 | IDS_PROP_READ_ONLY "Read-only" | 97 | IDS_PROP_READ_ONLY "Read-only" |
98 | IDS_PROP_OUT_NAME "Out Name" | 98 | IDS_PROP_OUT_NAME "Out Name" |
99 | IDS_PROP_COPY_LINK "Copy Link" | 99 | IDS_PROP_COPY_LINK "Copy Link" |
100 | IDS_PROP_ARC_FILE_NAME "ArcFileName" | ||
101 | IDS_PROP_IS_HASH "IsHash" | ||
102 | IDS_PROP_CHANGE_TIME "Metadata Changed" | ||
103 | IDS_PROP_USER_ID "User ID" | ||
104 | IDS_PROP_GROUP_ID "Group ID" | ||
105 | IDS_PROP_DEVICE_MAJOR "Device Major" | ||
106 | IDS_PROP_DEVICE_MINOR "Device Minor" | ||
100 | END | 107 | END |
diff --git a/CPP/7zip/UI/FileManager/PropertyNameRes.h b/CPP/7zip/UI/FileManager/PropertyNameRes.h index 67f3390..e3d08db 100644 --- a/CPP/7zip/UI/FileManager/PropertyNameRes.h +++ b/CPP/7zip/UI/FileManager/PropertyNameRes.h | |||
@@ -93,3 +93,10 @@ | |||
93 | #define IDS_PROP_READ_ONLY 1093 | 93 | #define IDS_PROP_READ_ONLY 1093 |
94 | #define IDS_PROP_OUT_NAME 1094 | 94 | #define IDS_PROP_OUT_NAME 1094 |
95 | #define IDS_PROP_COPY_LINK 1095 | 95 | #define IDS_PROP_COPY_LINK 1095 |
96 | #define IDS_PROP_ARC_FILE_NAME 1096 | ||
97 | #define IDS_PROP_IS_HASH 1097 | ||
98 | #define IDS_PROP_CHANGE_TIME 1098 | ||
99 | #define IDS_PROP_USER_ID 1099 | ||
100 | #define IDS_PROP_GROUP_ID 1100 | ||
101 | #define IDS_PROP_DEVICE_MAJOR 1101 | ||
102 | #define IDS_PROP_DEVICE_MINOR 1102 | ||
diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp index 16a3585..25b9219 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.cpp +++ b/CPP/7zip/UI/GUI/CompressDialog.cpp | |||
@@ -16,6 +16,7 @@ | |||
16 | #include "../FileManager/BrowseDialog.h" | 16 | #include "../FileManager/BrowseDialog.h" |
17 | #include "../FileManager/FormatUtils.h" | 17 | #include "../FileManager/FormatUtils.h" |
18 | #include "../FileManager/HelpUtils.h" | 18 | #include "../FileManager/HelpUtils.h" |
19 | #include "../FileManager/PropertyName.h" | ||
19 | #include "../FileManager/SplitUtils.h" | 20 | #include "../FileManager/SplitUtils.h" |
20 | 21 | ||
21 | #include "../Explorer/MyMessages.h" | 22 | #include "../Explorer/MyMessages.h" |
@@ -36,6 +37,9 @@ extern bool g_IsNT; | |||
36 | #include "ExtractRes.h" | 37 | #include "ExtractRes.h" |
37 | 38 | ||
38 | #ifdef LANG | 39 | #ifdef LANG |
40 | |||
41 | // #define IDS_OPTIONS 2100 | ||
42 | |||
39 | static const UInt32 kLangIDs[] = | 43 | static const UInt32 kLangIDs[] = |
40 | { | 44 | { |
41 | IDT_COMPRESS_ARCHIVE, | 45 | IDT_COMPRESS_ARCHIVE, |
@@ -49,6 +53,8 @@ static const UInt32 kLangIDs[] = | |||
49 | IDT_COMPRESS_THREADS, | 53 | IDT_COMPRESS_THREADS, |
50 | IDT_COMPRESS_PARAMETERS, | 54 | IDT_COMPRESS_PARAMETERS, |
51 | 55 | ||
56 | IDB_COMPRESS_OPTIONS, // IDS_OPTIONS | ||
57 | |||
52 | IDG_COMPRESS_OPTIONS, | 58 | IDG_COMPRESS_OPTIONS, |
53 | IDX_COMPRESS_SFX, | 59 | IDX_COMPRESS_SFX, |
54 | IDX_COMPRESS_SHARED, | 60 | IDX_COMPRESS_SHARED, |
@@ -57,11 +63,6 @@ static const UInt32 kLangIDs[] = | |||
57 | IDT_COMPRESS_MEMORY, | 63 | IDT_COMPRESS_MEMORY, |
58 | IDT_COMPRESS_MEMORY_DE, | 64 | IDT_COMPRESS_MEMORY_DE, |
59 | 65 | ||
60 | IDX_COMPRESS_NT_SYM_LINKS, | ||
61 | IDX_COMPRESS_NT_HARD_LINKS, | ||
62 | IDX_COMPRESS_NT_ALT_STREAMS, | ||
63 | IDX_COMPRESS_NT_SECUR, | ||
64 | |||
65 | IDG_COMPRESS_ENCRYPTION, | 66 | IDG_COMPRESS_ENCRYPTION, |
66 | IDT_COMPRESS_ENCRYPTION_METHOD, | 67 | IDT_COMPRESS_ENCRYPTION_METHOD, |
67 | IDX_COMPRESS_ENCRYPT_FILE_NAMES, | 68 | IDX_COMPRESS_ENCRYPT_FILE_NAMES, |
@@ -71,7 +72,7 @@ static const UInt32 kLangIDs[] = | |||
71 | IDX_PASSWORD_SHOW, | 72 | IDX_PASSWORD_SHOW, |
72 | 73 | ||
73 | IDT_SPLIT_TO_VOLUMES, | 74 | IDT_SPLIT_TO_VOLUMES, |
74 | IDT_COMPRESS_PATH_MODE | 75 | IDT_COMPRESS_PATH_MODE, |
75 | }; | 76 | }; |
76 | #endif | 77 | #endif |
77 | 78 | ||
@@ -89,8 +90,6 @@ static const UInt32 kLzmaMaxDictSize = (UInt32)15 << 28; | |||
89 | 90 | ||
90 | static LPCSTR const kExeExt = ".exe"; | 91 | static LPCSTR const kExeExt = ".exe"; |
91 | 92 | ||
92 | #define k7zFormat "7z" | ||
93 | |||
94 | static const UInt32 g_Levels[] = | 93 | static const UInt32 g_Levels[] = |
95 | { | 94 | { |
96 | IDS_METHOD_STORE, | 95 | IDS_METHOD_STORE, |
@@ -119,6 +118,8 @@ enum EMethodID | |||
119 | kSha1, | 118 | kSha1, |
120 | kCrc32, | 119 | kCrc32, |
121 | kCrc64, | 120 | kCrc64, |
121 | kGnu, | ||
122 | kPosix | ||
122 | }; | 123 | }; |
123 | 124 | ||
124 | static LPCSTR const kMethodsNames[] = | 125 | static LPCSTR const kMethodsNames[] = |
@@ -135,6 +136,8 @@ static LPCSTR const kMethodsNames[] = | |||
135 | , "SHA1" | 136 | , "SHA1" |
136 | , "CRC32" | 137 | , "CRC32" |
137 | , "CRC64" | 138 | , "CRC64" |
139 | , "GNU" | ||
140 | , "POSIX" | ||
138 | }; | 141 | }; |
139 | 142 | ||
140 | static const EMethodID g_7zMethods[] = | 143 | static const EMethodID g_7zMethods[] = |
@@ -186,6 +189,12 @@ static const EMethodID g_SwfcMethods[] = | |||
186 | // kLZMA | 189 | // kLZMA |
187 | }; | 190 | }; |
188 | 191 | ||
192 | static const EMethodID g_TarMethods[] = | ||
193 | { | ||
194 | kGnu, | ||
195 | kPosix | ||
196 | }; | ||
197 | |||
189 | static const EMethodID g_HashMethods[] = | 198 | static const EMethodID g_HashMethods[] = |
190 | { | 199 | { |
191 | kSha256 | 200 | kSha256 |
@@ -202,6 +211,13 @@ static const UInt32 kFF_EncryptFileNames = 1 << 4; | |||
202 | static const UInt32 kFF_MemUse = 1 << 5; | 211 | static const UInt32 kFF_MemUse = 1 << 5; |
203 | static const UInt32 kFF_SFX = 1 << 6; | 212 | static const UInt32 kFF_SFX = 1 << 6; |
204 | 213 | ||
214 | /* | ||
215 | static const UInt32 kFF_Time_Win = 1 << 10; | ||
216 | static const UInt32 kFF_Time_Unix = 1 << 11; | ||
217 | static const UInt32 kFF_Time_DOS = 1 << 12; | ||
218 | static const UInt32 kFF_Time_1ns = 1 << 13; | ||
219 | */ | ||
220 | |||
205 | struct CFormatInfo | 221 | struct CFormatInfo |
206 | { | 222 | { |
207 | LPCSTR Name; | 223 | LPCSTR Name; |
@@ -233,23 +249,26 @@ static const CFormatInfo g_Formats[] = | |||
233 | kFF_MultiThread | kFF_MemUse | 249 | kFF_MultiThread | kFF_MemUse |
234 | }, | 250 | }, |
235 | { | 251 | { |
236 | k7zFormat, | 252 | "7z", |
237 | (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), | 253 | (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), |
238 | METHODS_PAIR(g_7zMethods), | 254 | METHODS_PAIR(g_7zMethods), |
239 | kFF_Filter | kFF_Solid | kFF_MultiThread | kFF_Encrypt | | 255 | kFF_Filter | kFF_Solid | kFF_MultiThread | kFF_Encrypt | |
240 | kFF_EncryptFileNames | kFF_MemUse | kFF_SFX | 256 | kFF_EncryptFileNames | kFF_MemUse | kFF_SFX |
257 | // | kFF_Time_Win | ||
241 | }, | 258 | }, |
242 | { | 259 | { |
243 | "Zip", | 260 | "Zip", |
244 | (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), | 261 | (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), |
245 | METHODS_PAIR(g_ZipMethods), | 262 | METHODS_PAIR(g_ZipMethods), |
246 | kFF_MultiThread | kFF_Encrypt | kFF_MemUse | 263 | kFF_MultiThread | kFF_Encrypt | kFF_MemUse |
264 | // | kFF_Time_Win | kFF_Time_Unix | kFF_Time_DOS | ||
247 | }, | 265 | }, |
248 | { | 266 | { |
249 | "GZip", | 267 | "GZip", |
250 | (1 << 1) | (1 << 5) | (1 << 7) | (1 << 9), | 268 | (1 << 1) | (1 << 5) | (1 << 7) | (1 << 9), |
251 | METHODS_PAIR(g_GZipMethods), | 269 | METHODS_PAIR(g_GZipMethods), |
252 | kFF_MemUse | 270 | kFF_MemUse |
271 | // | kFF_Time_Unix | ||
253 | }, | 272 | }, |
254 | { | 273 | { |
255 | "BZip2", | 274 | "BZip2", |
@@ -272,14 +291,15 @@ static const CFormatInfo g_Formats[] = | |||
272 | { | 291 | { |
273 | "Tar", | 292 | "Tar", |
274 | (1 << 0), | 293 | (1 << 0), |
275 | 0, NULL, | 294 | METHODS_PAIR(g_TarMethods), |
276 | 0 | 295 | // kFF_Time_Unix | kFF_Time_Win // | kFF_Time_1ns |
277 | }, | 296 | }, |
278 | { | 297 | { |
279 | "wim", | 298 | "wim", |
280 | (1 << 0), | 299 | (1 << 0), |
281 | 0, NULL, | 300 | 0, NULL, |
282 | 0 | 301 | 0 |
302 | // | kFF_Time_Win | ||
283 | }, | 303 | }, |
284 | { | 304 | { |
285 | "Hash", | 305 | "Hash", |
@@ -335,22 +355,6 @@ static const UInt32 k_PathMode_IDs[] = | |||
335 | }; | 355 | }; |
336 | 356 | ||
337 | void AddComboItems(NControl::CComboBox &combo, const UInt32 *langIDs, unsigned numItems, const int *values, int curVal); | 357 | void AddComboItems(NControl::CComboBox &combo, const UInt32 *langIDs, unsigned numItems, const int *values, int curVal); |
338 | bool GetBoolsVal(const CBoolPair &b1, const CBoolPair &b2); | ||
339 | |||
340 | void CCompressDialog::CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2) | ||
341 | { | ||
342 | CheckButton(id, GetBoolsVal(b1, b2)); | ||
343 | } | ||
344 | |||
345 | void CCompressDialog::GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2) | ||
346 | { | ||
347 | bool val = IsButtonCheckedBool(id); | ||
348 | bool oldVal = GetBoolsVal(b1, b2); | ||
349 | if (val != oldVal) | ||
350 | b1.Def = b2.Def = true; | ||
351 | b1.Val = b2.Val = val; | ||
352 | } | ||
353 | |||
354 | 358 | ||
355 | void CCompressDialog::SetMethods(const CObjectVector<CCodecInfoUser> &userCodecs) | 359 | void CCompressDialog::SetMethods(const CObjectVector<CCodecInfoUser> &userCodecs) |
356 | { | 360 | { |
@@ -375,12 +379,13 @@ void CCompressDialog::SetMethods(const CObjectVector<CCodecInfoUser> &userCodecs | |||
375 | } | 379 | } |
376 | } | 380 | } |
377 | 381 | ||
378 | 382 | ||
379 | bool CCompressDialog::OnInit() | 383 | bool CCompressDialog::OnInit() |
380 | { | 384 | { |
381 | #ifdef LANG | 385 | #ifdef LANG |
382 | LangSetWindowText(*this, IDD_COMPRESS); | 386 | LangSetWindowText(*this, IDD_COMPRESS); |
383 | LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); | 387 | LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); |
388 | // LangSetDlgItemText(*this, IDB_COMPRESS_OPTIONS, IDS_OPTIONS); // IDG_COMPRESS_OPTIONS | ||
384 | #endif | 389 | #endif |
385 | 390 | ||
386 | { | 391 | { |
@@ -435,11 +440,6 @@ bool CCompressDialog::OnInit() | |||
435 | CheckButton(IDX_PASSWORD_SHOW, m_RegistryInfo.ShowPassword); | 440 | CheckButton(IDX_PASSWORD_SHOW, m_RegistryInfo.ShowPassword); |
436 | CheckButton(IDX_COMPRESS_ENCRYPT_FILE_NAMES, m_RegistryInfo.EncryptHeaders); | 441 | CheckButton(IDX_COMPRESS_ENCRYPT_FILE_NAMES, m_RegistryInfo.EncryptHeaders); |
437 | 442 | ||
438 | CheckButton_TwoBools(IDX_COMPRESS_NT_SYM_LINKS, Info.SymLinks, m_RegistryInfo.SymLinks); | ||
439 | CheckButton_TwoBools(IDX_COMPRESS_NT_HARD_LINKS, Info.HardLinks, m_RegistryInfo.HardLinks); | ||
440 | CheckButton_TwoBools(IDX_COMPRESS_NT_ALT_STREAMS, Info.AltStreams, m_RegistryInfo.AltStreams); | ||
441 | CheckButton_TwoBools(IDX_COMPRESS_NT_SECUR, Info.NtSecurity, m_RegistryInfo.NtSecurity); | ||
442 | |||
443 | UpdatePasswordControl(); | 443 | UpdatePasswordControl(); |
444 | 444 | ||
445 | { | 445 | { |
@@ -490,7 +490,7 @@ bool CCompressDialog::OnInit() | |||
490 | CheckButton(IDX_COMPRESS_SHARED, Info.OpenShareForWrite); | 490 | CheckButton(IDX_COMPRESS_SHARED, Info.OpenShareForWrite); |
491 | CheckButton(IDX_COMPRESS_DEL, Info.DeleteAfterCompressing); | 491 | CheckButton(IDX_COMPRESS_DEL, Info.DeleteAfterCompressing); |
492 | 492 | ||
493 | FormatChanged(); | 493 | FormatChanged(false); // isChanged |
494 | 494 | ||
495 | // OnButtonSFX(); | 495 | // OnButtonSFX(); |
496 | 496 | ||
@@ -552,6 +552,13 @@ bool CCompressDialog::OnButtonClicked(int buttonID, HWND buttonHWND) | |||
552 | UpdatePasswordControl(); | 552 | UpdatePasswordControl(); |
553 | return true; | 553 | return true; |
554 | } | 554 | } |
555 | case IDB_COMPRESS_OPTIONS: | ||
556 | { | ||
557 | COptionsDialog dialog(this); | ||
558 | if (dialog.Create(*this) == IDOK) | ||
559 | ShowOptionsString(); | ||
560 | return true; | ||
561 | } | ||
555 | } | 562 | } |
556 | return CModalDialog::OnButtonClicked(buttonID, buttonHWND); | 563 | return CModalDialog::OnButtonClicked(buttonID, buttonHWND); |
557 | } | 564 | } |
@@ -588,8 +595,44 @@ void CCompressDialog::EnableMultiCombo(unsigned id) | |||
588 | EnableItem(id, enable); | 595 | EnableItem(id, enable); |
589 | } | 596 | } |
590 | 597 | ||
598 | static LRESULT ComboBox_AddStringAscii(NControl::CComboBox &cb, const char *s); | ||
599 | static void FormatOptions_To_String(const NCompression::CFormatOptions &fo, AString &s); | ||
591 | 600 | ||
592 | void CCompressDialog::FormatChanged() | 601 | static void Combine_Two_BoolPairs(const CBoolPair &b1, const CBoolPair &b2, CBool1 &res) |
602 | { | ||
603 | if (!b1.Def && b2.Def) | ||
604 | res.Val = b2.Val; | ||
605 | else | ||
606 | res.Val = b1.Val; | ||
607 | } | ||
608 | |||
609 | #define SET_GUI_BOOL(name) \ | ||
610 | Combine_Two_BoolPairs(Info. ## name, m_RegistryInfo. ## name, name) | ||
611 | |||
612 | |||
613 | static void Set_Final_BoolPairs( | ||
614 | const CBool1 &gui, | ||
615 | CBoolPair &cmd, | ||
616 | CBoolPair ®) | ||
617 | { | ||
618 | if (!cmd.Def) | ||
619 | { | ||
620 | reg.Val = gui.Val; | ||
621 | reg.Def = gui.Val; | ||
622 | } | ||
623 | if (gui.Supported) | ||
624 | { | ||
625 | cmd.Val = gui.Val; | ||
626 | cmd.Def = gui.Val; | ||
627 | } | ||
628 | else | ||
629 | cmd.Init(); | ||
630 | } | ||
631 | |||
632 | #define SET_FINAL_BOOL_PAIRS(name) \ | ||
633 | Set_Final_BoolPairs(name, Info. ## name, m_RegistryInfo. ## name) | ||
634 | |||
635 | void CCompressDialog::FormatChanged(bool isChanged) | ||
593 | { | 636 | { |
594 | SetLevel(); | 637 | SetLevel(); |
595 | SetSolidBlockSize(); | 638 | SetSolidBlockSize(); |
@@ -615,18 +658,26 @@ void CCompressDialog::FormatChanged() | |||
615 | CheckSFXControlsEnable(); | 658 | CheckSFXControlsEnable(); |
616 | 659 | ||
617 | { | 660 | { |
618 | const CArcInfoEx &ai = Get_ArcInfoEx(); | 661 | if (!isChanged) |
619 | 662 | { | |
620 | ShowItem_Bool(IDX_COMPRESS_NT_SYM_LINKS, ai.Flags_SymLinks()); | 663 | SET_GUI_BOOL (SymLinks); |
621 | ShowItem_Bool(IDX_COMPRESS_NT_HARD_LINKS, ai.Flags_HardLinks()); | 664 | SET_GUI_BOOL (HardLinks); |
622 | ShowItem_Bool(IDX_COMPRESS_NT_ALT_STREAMS, ai.Flags_AltStreams()); | 665 | SET_GUI_BOOL (AltStreams); |
623 | ShowItem_Bool(IDX_COMPRESS_NT_SECUR, ai.Flags_NtSecure()); | 666 | SET_GUI_BOOL (NtSecurity); |
667 | SET_GUI_BOOL (PreserveATime); | ||
668 | } | ||
624 | 669 | ||
625 | ShowItem_Bool(IDG_COMPRESS_NTFS, | 670 | PreserveATime.Supported = true; |
626 | ai.Flags_SymLinks() | 671 | |
627 | || ai.Flags_HardLinks() | 672 | { |
628 | || ai.Flags_AltStreams() | 673 | const CArcInfoEx &ai = Get_ArcInfoEx(); |
629 | || ai.Flags_NtSecure()); | 674 | SymLinks.Supported = ai.Flags_SymLinks(); |
675 | HardLinks.Supported = ai.Flags_HardLinks(); | ||
676 | AltStreams.Supported = ai.Flags_AltStreams(); | ||
677 | NtSecurity.Supported = ai.Flags_NtSecurity(); | ||
678 | } | ||
679 | |||
680 | ShowOptionsString(); | ||
630 | } | 681 | } |
631 | // CheckVolumeEnable(); | 682 | // CheckVolumeEnable(); |
632 | 683 | ||
@@ -821,7 +872,7 @@ void SetErrorMessage_MemUsage(UString &s, UInt64 reqSize, UInt64 ramSize, UInt64 | |||
821 | 872 | ||
822 | s.Add_LF(); | 873 | s.Add_LF(); |
823 | s.Add_LF(); | 874 | s.Add_LF(); |
824 | s += LangString(IDS_MEM_ERROR); | 875 | AddLangString(s, IDS_MEM_ERROR); |
825 | } | 876 | } |
826 | 877 | ||
827 | 878 | ||
@@ -933,17 +984,32 @@ void CCompressDialog::OnOK() | |||
933 | Info.EncryptHeaders = IsButtonCheckedBool(IDX_COMPRESS_ENCRYPT_FILE_NAMES); | 984 | Info.EncryptHeaders = IsButtonCheckedBool(IDX_COMPRESS_ENCRYPT_FILE_NAMES); |
934 | 985 | ||
935 | 986 | ||
936 | GetButton_Bools(IDX_COMPRESS_NT_SYM_LINKS, Info.SymLinks, m_RegistryInfo.SymLinks); | 987 | /* (Info) is for saving to registry: |
937 | GetButton_Bools(IDX_COMPRESS_NT_HARD_LINKS, Info.HardLinks, m_RegistryInfo.HardLinks); | 988 | (CBoolPair::Val) will be set as (false), if it was (false) |
938 | GetButton_Bools(IDX_COMPRESS_NT_ALT_STREAMS, Info.AltStreams, m_RegistryInfo.AltStreams); | 989 | in registry at dialog creation, and user didn't click checkbox. |
939 | GetButton_Bools(IDX_COMPRESS_NT_SECUR, Info.NtSecurity, m_RegistryInfo.NtSecurity); | 990 | in another case (CBoolPair::Val) will be set as (true) */ |
940 | 991 | ||
941 | { | 992 | { |
942 | const CArcInfoEx &ai = Get_ArcInfoEx(); | 993 | /* Info properties could be for another archive types. |
943 | if (!ai.Flags_SymLinks()) Info.SymLinks.Val = false; | 994 | so we disable unsupported properties in Info */ |
944 | if (!ai.Flags_HardLinks()) Info.HardLinks.Val = false; | 995 | // const CArcInfoEx &ai = Get_ArcInfoEx(); |
945 | if (!ai.Flags_AltStreams()) Info.AltStreams.Val = false; | 996 | |
946 | if (!ai.Flags_NtSecure()) Info.NtSecurity.Val = false; | 997 | SET_FINAL_BOOL_PAIRS (SymLinks); |
998 | SET_FINAL_BOOL_PAIRS (HardLinks); | ||
999 | SET_FINAL_BOOL_PAIRS (AltStreams); | ||
1000 | SET_FINAL_BOOL_PAIRS (NtSecurity); | ||
1001 | |||
1002 | SET_FINAL_BOOL_PAIRS (PreserveATime); | ||
1003 | } | ||
1004 | |||
1005 | { | ||
1006 | const NCompression::CFormatOptions &fo = Get_FormatOptions(); | ||
1007 | |||
1008 | Info.TimePrec = fo.TimePrec; | ||
1009 | Info.MTime = fo.MTime; | ||
1010 | Info.CTime = fo.CTime; | ||
1011 | Info.ATime = fo.ATime; | ||
1012 | Info.SetArcMTime = fo.SetArcMTime; | ||
947 | } | 1013 | } |
948 | 1014 | ||
949 | m_Params.GetText(Info.Options); | 1015 | m_Params.GetText(Info.Options); |
@@ -1031,7 +1097,7 @@ bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam) | |||
1031 | { | 1097 | { |
1032 | const bool isSFX = IsSFX(); | 1098 | const bool isSFX = IsSFX(); |
1033 | SaveOptionsInMem(); | 1099 | SaveOptionsInMem(); |
1034 | FormatChanged(); | 1100 | FormatChanged(true); // isChanged |
1035 | SetArchiveName2(isSFX); | 1101 | SetArchiveName2(isSFX); |
1036 | return true; | 1102 | return true; |
1037 | } | 1103 | } |
@@ -1057,6 +1123,7 @@ bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam) | |||
1057 | SetMemoryUsage(); | 1123 | SetMemoryUsage(); |
1058 | if (Get_ArcInfoEx().Flags_HashHandler()) | 1124 | if (Get_ArcInfoEx().Flags_HashHandler()) |
1059 | SetArchiveName2(false); | 1125 | SetArchiveName2(false); |
1126 | |||
1060 | return true; | 1127 | return true; |
1061 | } | 1128 | } |
1062 | 1129 | ||
@@ -1188,6 +1255,7 @@ void CCompressDialog::SetArchiveName(const UString &name) | |||
1188 | m_ArchivePath.SetText(fileName); | 1255 | m_ArchivePath.SetText(fileName); |
1189 | } | 1256 | } |
1190 | 1257 | ||
1258 | |||
1191 | int CCompressDialog::FindRegistryFormat(const UString &name) | 1259 | int CCompressDialog::FindRegistryFormat(const UString &name) |
1192 | { | 1260 | { |
1193 | FOR_VECTOR (i, m_RegistryInfo.Formats) | 1261 | FOR_VECTOR (i, m_RegistryInfo.Formats) |
@@ -1199,7 +1267,8 @@ int CCompressDialog::FindRegistryFormat(const UString &name) | |||
1199 | return -1; | 1267 | return -1; |
1200 | } | 1268 | } |
1201 | 1269 | ||
1202 | int CCompressDialog::FindRegistryFormatAlways(const UString &name) | 1270 | |
1271 | unsigned CCompressDialog::FindRegistryFormat_Always(const UString &name) | ||
1203 | { | 1272 | { |
1204 | int index = FindRegistryFormat(name); | 1273 | int index = FindRegistryFormat(name); |
1205 | if (index < 0) | 1274 | if (index < 0) |
@@ -1211,6 +1280,14 @@ int CCompressDialog::FindRegistryFormatAlways(const UString &name) | |||
1211 | return index; | 1280 | return index; |
1212 | } | 1281 | } |
1213 | 1282 | ||
1283 | |||
1284 | NCompression::CFormatOptions &CCompressDialog::Get_FormatOptions() | ||
1285 | { | ||
1286 | const CArcInfoEx &ai = Get_ArcInfoEx(); | ||
1287 | return m_RegistryInfo.Formats[FindRegistryFormat_Always(ai.Name)]; | ||
1288 | } | ||
1289 | |||
1290 | |||
1214 | int CCompressDialog::GetStaticFormatIndex() | 1291 | int CCompressDialog::GetStaticFormatIndex() |
1215 | { | 1292 | { |
1216 | const CArcInfoEx &ai = Get_ArcInfoEx(); | 1293 | const CArcInfoEx &ai = Get_ArcInfoEx(); |
@@ -1293,8 +1370,11 @@ void CCompressDialog::SetMethod2(int keepMethodId) | |||
1293 | const CArcInfoEx &ai = Get_ArcInfoEx(); | 1370 | const CArcInfoEx &ai = Get_ArcInfoEx(); |
1294 | if (GetLevel() == 0 && !ai.Flags_HashHandler()) | 1371 | if (GetLevel() == 0 && !ai.Flags_HashHandler()) |
1295 | { | 1372 | { |
1296 | MethodChanged(); | 1373 | if (!ai.Is_Tar()) |
1297 | return; | 1374 | { |
1375 | MethodChanged(); | ||
1376 | return; | ||
1377 | } | ||
1298 | } | 1378 | } |
1299 | UString defaultMethod; | 1379 | UString defaultMethod; |
1300 | { | 1380 | { |
@@ -1308,7 +1388,7 @@ void CCompressDialog::SetMethod2(int keepMethodId) | |||
1308 | const bool isSfx = IsSFX(); | 1388 | const bool isSfx = IsSFX(); |
1309 | bool weUseSameMethod = false; | 1389 | bool weUseSameMethod = false; |
1310 | 1390 | ||
1311 | const bool is7z = ai.Name.IsEqualTo_Ascii_NoCase("7z"); | 1391 | const bool is7z = ai.Is_7z(); |
1312 | 1392 | ||
1313 | for (unsigned m = 0;; m++) | 1393 | for (unsigned m = 0;; m++) |
1314 | { | 1394 | { |
@@ -1367,12 +1447,12 @@ void CCompressDialog::SetMethod2(int keepMethodId) | |||
1367 | 1447 | ||
1368 | bool CCompressDialog::IsZipFormat() | 1448 | bool CCompressDialog::IsZipFormat() |
1369 | { | 1449 | { |
1370 | return Get_ArcInfoEx().Name.IsEqualTo_Ascii_NoCase("zip"); | 1450 | return Get_ArcInfoEx().Is_Zip(); |
1371 | } | 1451 | } |
1372 | 1452 | ||
1373 | bool CCompressDialog::IsXzFormat() | 1453 | bool CCompressDialog::IsXzFormat() |
1374 | { | 1454 | { |
1375 | return Get_ArcInfoEx().Name.IsEqualTo_Ascii_NoCase("xz"); | 1455 | return Get_ArcInfoEx().Is_Xz(); |
1376 | } | 1456 | } |
1377 | 1457 | ||
1378 | void CCompressDialog::SetEncryptionMethod() | 1458 | void CCompressDialog::SetEncryptionMethod() |
@@ -1380,13 +1460,13 @@ void CCompressDialog::SetEncryptionMethod() | |||
1380 | _encryptionMethod.ResetContent(); | 1460 | _encryptionMethod.ResetContent(); |
1381 | _default_encryptionMethod_Index = -1; | 1461 | _default_encryptionMethod_Index = -1; |
1382 | const CArcInfoEx &ai = Get_ArcInfoEx(); | 1462 | const CArcInfoEx &ai = Get_ArcInfoEx(); |
1383 | if (ai.Name.IsEqualTo_Ascii_NoCase("7z")) | 1463 | if (ai.Is_7z()) |
1384 | { | 1464 | { |
1385 | ComboBox_AddStringAscii(_encryptionMethod, "AES-256"); | 1465 | ComboBox_AddStringAscii(_encryptionMethod, "AES-256"); |
1386 | _encryptionMethod.SetCurSel(0); | 1466 | _encryptionMethod.SetCurSel(0); |
1387 | _default_encryptionMethod_Index = 0; | 1467 | _default_encryptionMethod_Index = 0; |
1388 | } | 1468 | } |
1389 | else if (ai.Name.IsEqualTo_Ascii_NoCase("zip")) | 1469 | else if (ai.Is_Zip()) |
1390 | { | 1470 | { |
1391 | int index = FindRegistryFormat(ai.Name); | 1471 | int index = FindRegistryFormat(ai.Name); |
1392 | UString encryptionMethod; | 1472 | UString encryptionMethod; |
@@ -1929,7 +2009,7 @@ void CCompressDialog::SetSolidBlockSize2() | |||
1929 | } | 2009 | } |
1930 | } | 2010 | } |
1931 | 2011 | ||
1932 | const bool is7z = ai.Name.IsEqualTo_Ascii_NoCase("7z"); | 2012 | const bool is7z = ai.Is_7z(); |
1933 | 2013 | ||
1934 | const UInt64 cs = Get_Lzma2_ChunkSize(dict); | 2014 | const UInt64 cs = Get_Lzma2_ChunkSize(dict); |
1935 | 2015 | ||
@@ -2549,11 +2629,16 @@ void CCompressDialog::SetParams() | |||
2549 | 2629 | ||
2550 | void CCompressDialog::SaveOptionsInMem() | 2630 | void CCompressDialog::SaveOptionsInMem() |
2551 | { | 2631 | { |
2632 | /* these options are for (Info.FormatIndex). | ||
2633 | If it's called just after format changing, | ||
2634 | then it's format that was selected before format changing | ||
2635 | So we store previous format properties */ | ||
2636 | |||
2552 | m_Params.GetText(Info.Options); | 2637 | m_Params.GetText(Info.Options); |
2553 | Info.Options.Trim(); | 2638 | Info.Options.Trim(); |
2554 | 2639 | ||
2555 | const CArcInfoEx &ai = (*ArcFormats)[Info.FormatIndex]; | 2640 | const CArcInfoEx &ai = (*ArcFormats)[Info.FormatIndex]; |
2556 | const int index = FindRegistryFormatAlways(ai.Name); | 2641 | const unsigned index = FindRegistryFormat_Always(ai.Name); |
2557 | NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; | 2642 | NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; |
2558 | fo.Options = Info.Options; | 2643 | fo.Options = Info.Options; |
2559 | fo.Level = GetLevelSpec(); | 2644 | fo.Level = GetLevelSpec(); |
@@ -2587,7 +2672,512 @@ void CCompressDialog::SaveOptionsInMem() | |||
2587 | fo.MemUse = Get_MemUse_Spec(); | 2672 | fo.MemUse = Get_MemUse_Spec(); |
2588 | } | 2673 | } |
2589 | 2674 | ||
2675 | |||
2590 | unsigned CCompressDialog::GetFormatIndex() | 2676 | unsigned CCompressDialog::GetFormatIndex() |
2591 | { | 2677 | { |
2592 | return (unsigned)m_Format.GetItemData_of_CurSel(); | 2678 | return (unsigned)m_Format.GetItemData_of_CurSel(); |
2593 | } | 2679 | } |
2680 | |||
2681 | |||
2682 | |||
2683 | static void AddText_from_BoolPair(AString &s, const char *name, const CBoolPair &bp) | ||
2684 | { | ||
2685 | if (bp.Def) | ||
2686 | { | ||
2687 | s.Add_OptSpaced(name); | ||
2688 | if (!bp.Val) | ||
2689 | s += "-"; | ||
2690 | } | ||
2691 | /* | ||
2692 | else if (bp.Val) | ||
2693 | { | ||
2694 | s.Add_OptSpaced("["); | ||
2695 | s += name; | ||
2696 | s += "]"; | ||
2697 | } | ||
2698 | */ | ||
2699 | } | ||
2700 | |||
2701 | |||
2702 | static void AddText_from_Bool1(AString &s, const char *name, const CBool1 &b) | ||
2703 | { | ||
2704 | if (b.Supported && b.Val) | ||
2705 | s.Add_OptSpaced(name); | ||
2706 | } | ||
2707 | |||
2708 | |||
2709 | void CCompressDialog::ShowOptionsString() | ||
2710 | { | ||
2711 | NCompression::CFormatOptions &fo = Get_FormatOptions(); | ||
2712 | |||
2713 | AString s; | ||
2714 | if (fo.TimePrec != -1) | ||
2715 | { | ||
2716 | s.Add_OptSpaced("tp"); | ||
2717 | s.Add_UInt32(fo.TimePrec); | ||
2718 | } | ||
2719 | AddText_from_BoolPair(s, "tm", fo.MTime); | ||
2720 | AddText_from_BoolPair(s, "tc", fo.CTime); | ||
2721 | AddText_from_BoolPair(s, "ta", fo.ATime); | ||
2722 | AddText_from_BoolPair(s, "-stl", fo.SetArcMTime); | ||
2723 | |||
2724 | // const CArcInfoEx &ai = Get_ArcInfoEx(); | ||
2725 | AddText_from_Bool1(s, "SL", SymLinks); | ||
2726 | AddText_from_Bool1(s, "HL", HardLinks); | ||
2727 | AddText_from_Bool1(s, "AS", AltStreams); | ||
2728 | AddText_from_Bool1(s, "Sec", NtSecurity); | ||
2729 | |||
2730 | // AddText_from_Bool1(s, "Preserve", PreserveATime); | ||
2731 | |||
2732 | SetItemText(IDT_COMPRESS_OPTIONS, GetUnicodeString(s)); | ||
2733 | } | ||
2734 | |||
2735 | |||
2736 | |||
2737 | |||
2738 | |||
2739 | // ---------- OPTIONS ---------- | ||
2740 | |||
2741 | |||
2742 | void COptionsDialog::CheckButton_Bool1(UINT id, const CBool1 &b1) | ||
2743 | { | ||
2744 | CheckButton(id, b1.Val); | ||
2745 | } | ||
2746 | |||
2747 | void COptionsDialog::GetButton_Bool1(UINT id, CBool1 &b1) | ||
2748 | { | ||
2749 | b1.Val = IsButtonCheckedBool(id); | ||
2750 | } | ||
2751 | |||
2752 | |||
2753 | void COptionsDialog::CheckButton_BoolBox( | ||
2754 | bool supported, const CBoolPair &b2, CBoolBox &bb) | ||
2755 | { | ||
2756 | const bool isSet = b2.Def; | ||
2757 | const bool val = isSet ? b2.Val : bb.DefaultVal; | ||
2758 | |||
2759 | bb.IsSupported = supported; | ||
2760 | |||
2761 | CheckButton (bb.Set_Id, isSet); | ||
2762 | ShowItem_Bool (bb.Set_Id, supported); | ||
2763 | CheckButton (bb.Id, val); | ||
2764 | EnableItem (bb.Id, isSet); | ||
2765 | ShowItem_Bool (bb.Id, supported); | ||
2766 | } | ||
2767 | |||
2768 | void COptionsDialog::GetButton_BoolBox(CBoolBox &bb) | ||
2769 | { | ||
2770 | // we save value for invisible buttons too | ||
2771 | bb.BoolPair.Val = IsButtonCheckedBool (bb.Id); | ||
2772 | bb.BoolPair.Def = IsButtonCheckedBool (bb.Set_Id); | ||
2773 | } | ||
2774 | |||
2775 | |||
2776 | void COptionsDialog::Store_TimeBoxes() | ||
2777 | { | ||
2778 | TimePrec = GetPrecSpec(); | ||
2779 | GetButton_BoolBox (MTime); | ||
2780 | GetButton_BoolBox (CTime); | ||
2781 | GetButton_BoolBox (ATime); | ||
2782 | GetButton_BoolBox (ZTime); | ||
2783 | } | ||
2784 | |||
2785 | |||
2786 | UInt32 COptionsDialog::GetComboValue(NWindows::NControl::CComboBox &c, int defMax) | ||
2787 | { | ||
2788 | if (c.GetCount() <= defMax) | ||
2789 | return (UInt32)(Int32)-1; | ||
2790 | return (UInt32)c.GetItemData_of_CurSel(); | ||
2791 | } | ||
2792 | |||
2793 | static const unsigned kTimePrec_Win = 0; | ||
2794 | static const unsigned kTimePrec_Unix = 1; | ||
2795 | static const unsigned kTimePrec_DOS = 2; | ||
2796 | static const unsigned kTimePrec_1ns = 3; | ||
2797 | |||
2798 | static void AddTimeOption(UString &s, UInt32 val, const UString &unit, const char *sys = NULL) | ||
2799 | { | ||
2800 | // s += " : "; | ||
2801 | { | ||
2802 | AString s2; | ||
2803 | s2.Add_UInt32(val); | ||
2804 | s += s2; | ||
2805 | } | ||
2806 | s.Add_Space(); | ||
2807 | s += unit; | ||
2808 | if (sys) | ||
2809 | { | ||
2810 | s += " : "; | ||
2811 | s += sys; | ||
2812 | } | ||
2813 | } | ||
2814 | |||
2815 | int COptionsDialog::AddPrec(unsigned prec, bool isDefault) | ||
2816 | { | ||
2817 | UString s; | ||
2818 | UInt32 writePrec = prec; | ||
2819 | if (isDefault) | ||
2820 | { | ||
2821 | // s += "* "; | ||
2822 | // writePrec = (UInt32)(Int32)-1; | ||
2823 | } | ||
2824 | if (prec == kTimePrec_Win) AddTimeOption(s, 100, NsString, "Windows"); | ||
2825 | else if (prec == kTimePrec_Unix) AddTimeOption(s, 1, SecString, "Unix"); | ||
2826 | else if (prec == kTimePrec_DOS) AddTimeOption(s, 2, SecString, "DOS"); | ||
2827 | else if (prec == kTimePrec_1ns) AddTimeOption(s, 1, NsString, "Linux"); | ||
2828 | else if (prec == k_PropVar_TimePrec_Base) AddTimeOption(s, 1, SecString); | ||
2829 | else if (prec >= k_PropVar_TimePrec_Base) | ||
2830 | { | ||
2831 | UInt32 d = 1; | ||
2832 | for (unsigned i = prec; i < k_PropVar_TimePrec_Base + 9; i++) | ||
2833 | d *= 10; | ||
2834 | AddTimeOption(s, d, NsString); | ||
2835 | } | ||
2836 | else | ||
2837 | s.Add_UInt32(prec); | ||
2838 | const int index = (int)m_Prec.AddString(s); | ||
2839 | m_Prec.SetItemData(index, writePrec); | ||
2840 | return index; | ||
2841 | } | ||
2842 | |||
2843 | |||
2844 | void COptionsDialog::SetPrec() | ||
2845 | { | ||
2846 | // const CFormatInfo &fi = g_Formats[cd->GetStaticFormatIndex()]; | ||
2847 | const CArcInfoEx &ai = cd->Get_ArcInfoEx(); | ||
2848 | |||
2849 | // UInt32 flags = fi.Flags; | ||
2850 | |||
2851 | UInt32 flags = ai.Get_TimePrecFlags(); | ||
2852 | UInt32 defaultPrec = ai.Get_DefaultTimePrec(); | ||
2853 | if (defaultPrec != 0) | ||
2854 | flags |= ((UInt32)1 << defaultPrec); | ||
2855 | |||
2856 | // const NCompression::CFormatOptions &fo = cd->Get_FormatOptions(); | ||
2857 | |||
2858 | // unsigned defaultPrec = kTimePrec_Win; | ||
2859 | |||
2860 | if (ai.Is_GZip()) | ||
2861 | defaultPrec = kTimePrec_Unix; | ||
2862 | |||
2863 | { | ||
2864 | UString s; | ||
2865 | s += GetNameOfProperty(kpidType, L"type"); | ||
2866 | s += ": "; | ||
2867 | s += ai.Name; | ||
2868 | if (ai.Is_Tar()) | ||
2869 | { | ||
2870 | const int methodID = cd->GetMethodID(); | ||
2871 | |||
2872 | // for debug | ||
2873 | // defaultPrec = kTimePrec_Unix; | ||
2874 | // flags = (UInt32)1 << kTimePrec_Unix; | ||
2875 | |||
2876 | s += ":"; | ||
2877 | if (methodID >= 0 && (unsigned)methodID < ARRAY_SIZE(kMethodsNames)) | ||
2878 | s += kMethodsNames[methodID]; | ||
2879 | if (methodID == kPosix) | ||
2880 | { | ||
2881 | // for debug | ||
2882 | // flags |= (UInt32)1 << kTimePrec_Win; | ||
2883 | // flags |= (UInt32)1 << kTimePrec_1ns; | ||
2884 | } | ||
2885 | } | ||
2886 | else | ||
2887 | { | ||
2888 | // if (is_for_MethodChanging) return; | ||
2889 | } | ||
2890 | |||
2891 | SetItemText(IDT_COMPRESS_TIME_INFO, s); | ||
2892 | } | ||
2893 | |||
2894 | m_Prec.ResetContent(); | ||
2895 | _auto_Prec = defaultPrec; | ||
2896 | |||
2897 | unsigned selectedPrec = defaultPrec; | ||
2898 | { | ||
2899 | // if (TimePrec >= kTimePrec_Win && TimePrec <= kTimePrec_DOS) | ||
2900 | if ((Int32)TimePrec >= 0) | ||
2901 | selectedPrec = TimePrec; | ||
2902 | } | ||
2903 | |||
2904 | int curSel = -1; | ||
2905 | int defaultPrecIndex = -1; | ||
2906 | for (unsigned prec = 0; | ||
2907 | // prec <= k_PropVar_TimePrec_HighPrec; | ||
2908 | prec <= k_PropVar_TimePrec_1ns; | ||
2909 | prec++) | ||
2910 | { | ||
2911 | if (((flags >> prec) & 1) == 0) | ||
2912 | continue; | ||
2913 | const bool isDefault = (defaultPrec == prec); | ||
2914 | const int index = AddPrec(prec, isDefault); | ||
2915 | if (isDefault) | ||
2916 | defaultPrecIndex = index; | ||
2917 | if (selectedPrec == prec) | ||
2918 | curSel = index; | ||
2919 | } | ||
2920 | |||
2921 | if (curSel < 0 && selectedPrec > kTimePrec_DOS) | ||
2922 | curSel = AddPrec(selectedPrec, false); // isDefault | ||
2923 | if (curSel < 0) | ||
2924 | curSel = defaultPrecIndex; | ||
2925 | if (curSel >= 0) | ||
2926 | m_Prec.SetCurSel(curSel); | ||
2927 | |||
2928 | { | ||
2929 | const bool isSet = IsSet_TimePrec(); | ||
2930 | const int count = m_Prec.GetCount(); | ||
2931 | const bool showPrec = (count != 0); | ||
2932 | ShowItem_Bool(IDC_COMPRESS_TIME_PREC, showPrec); | ||
2933 | ShowItem_Bool(IDT_COMPRESS_TIME_PREC, showPrec); | ||
2934 | EnableItem(IDC_COMPRESS_TIME_PREC, isSet && (count > 1)); | ||
2935 | |||
2936 | CheckButton(IDX_COMPRESS_PREC_SET, isSet); | ||
2937 | const bool setIsSupported = isSet || (count > 1); | ||
2938 | EnableItem(IDX_COMPRESS_PREC_SET, setIsSupported); | ||
2939 | ShowItem_Bool(IDX_COMPRESS_PREC_SET, setIsSupported); | ||
2940 | } | ||
2941 | |||
2942 | SetTimeMAC(); | ||
2943 | } | ||
2944 | |||
2945 | |||
2946 | void COptionsDialog::SetTimeMAC() | ||
2947 | { | ||
2948 | const CArcInfoEx &ai = cd->Get_ArcInfoEx(); | ||
2949 | |||
2950 | const | ||
2951 | bool m_allow = ai.Flags_MTime(); | ||
2952 | bool c_allow = ai.Flags_CTime(); | ||
2953 | bool a_allow = ai.Flags_ATime(); | ||
2954 | |||
2955 | if (ai.Is_Tar()) | ||
2956 | { | ||
2957 | const int methodID = cd->GetMethodID(); | ||
2958 | c_allow = false; | ||
2959 | a_allow = false; | ||
2960 | if (methodID == kPosix) | ||
2961 | { | ||
2962 | // c_allow = true; // do we need it as change time ? | ||
2963 | a_allow = true; | ||
2964 | } | ||
2965 | } | ||
2966 | |||
2967 | if (ai.Is_Zip()) | ||
2968 | { | ||
2969 | // const int methodID = GetMethodID(); | ||
2970 | UInt32 prec = GetPrec(); | ||
2971 | if (prec == (UInt32)(Int32)-1) | ||
2972 | prec = _auto_Prec; | ||
2973 | if (prec != kTimePrec_Win) | ||
2974 | { | ||
2975 | c_allow = false; | ||
2976 | a_allow = false; | ||
2977 | } | ||
2978 | } | ||
2979 | |||
2980 | |||
2981 | /* | ||
2982 | MTime.DefaultVal = true; | ||
2983 | CTime.DefaultVal = false; | ||
2984 | ATime.DefaultVal = false; | ||
2985 | */ | ||
2986 | |||
2987 | MTime.DefaultVal = ai.Flags_MTime_Default(); | ||
2988 | CTime.DefaultVal = ai.Flags_CTime_Default(); | ||
2989 | ATime.DefaultVal = ai.Flags_ATime_Default(); | ||
2990 | |||
2991 | ZTime.DefaultVal = false; | ||
2992 | |||
2993 | const NCompression::CFormatOptions &fo = cd->Get_FormatOptions(); | ||
2994 | |||
2995 | CheckButton_BoolBox (m_allow, fo.MTime, MTime ); | ||
2996 | CheckButton_BoolBox (c_allow, fo.CTime, CTime ); | ||
2997 | CheckButton_BoolBox (a_allow, fo.ATime, ATime ); | ||
2998 | CheckButton_BoolBox (true, fo.SetArcMTime, ZTime); | ||
2999 | |||
3000 | if (m_allow && !fo.MTime.Def) | ||
3001 | { | ||
3002 | const bool isSingleFile = ai.Flags_KeepName(); | ||
3003 | if (!isSingleFile) | ||
3004 | { | ||
3005 | // we can hide changing checkboxes for MTime here: | ||
3006 | ShowItem_Bool (MTime.Set_Id, false); | ||
3007 | EnableItem (MTime.Id, false); | ||
3008 | } | ||
3009 | } | ||
3010 | // On_CheckBoxSet_Prec_Clicked(); | ||
3011 | // const bool isSingleFile = ai.Flags_KeepName(); | ||
3012 | // mtime for Gz can be | ||
3013 | } | ||
3014 | |||
3015 | |||
3016 | |||
3017 | void COptionsDialog::On_CheckBoxSet_Prec_Clicked() | ||
3018 | { | ||
3019 | const bool isSet = IsButtonCheckedBool(IDX_COMPRESS_PREC_SET); | ||
3020 | if (!isSet) | ||
3021 | { | ||
3022 | // We save current MAC boxes to memory before SetPrec() | ||
3023 | Store_TimeBoxes(); | ||
3024 | Reset_TimePrec(); | ||
3025 | SetPrec(); | ||
3026 | } | ||
3027 | EnableItem(IDC_COMPRESS_TIME_PREC, isSet); | ||
3028 | } | ||
3029 | |||
3030 | void COptionsDialog::On_CheckBoxSet_Clicked(const CBoolBox &bb) | ||
3031 | { | ||
3032 | const bool isSet = IsButtonCheckedBool(bb.Set_Id); | ||
3033 | if (!isSet) | ||
3034 | CheckButton(bb.Id, bb.DefaultVal); | ||
3035 | EnableItem(bb.Id, isSet); | ||
3036 | } | ||
3037 | |||
3038 | |||
3039 | |||
3040 | |||
3041 | #ifdef LANG | ||
3042 | static const UInt32 kLangIDs_Options[] = | ||
3043 | { | ||
3044 | IDX_COMPRESS_NT_SYM_LINKS, | ||
3045 | IDX_COMPRESS_NT_HARD_LINKS, | ||
3046 | IDX_COMPRESS_NT_ALT_STREAMS, | ||
3047 | IDX_COMPRESS_NT_SECUR, | ||
3048 | |||
3049 | IDG_COMPRESS_TIME, | ||
3050 | IDT_COMPRESS_TIME_PREC, | ||
3051 | IDX_COMPRESS_MTIME, | ||
3052 | IDX_COMPRESS_CTIME, | ||
3053 | IDX_COMPRESS_ATIME, | ||
3054 | IDX_COMPRESS_ZTIME, | ||
3055 | IDX_COMPRESS_PRESERVE_ATIME | ||
3056 | }; | ||
3057 | #endif | ||
3058 | |||
3059 | |||
3060 | bool COptionsDialog::OnInit() | ||
3061 | { | ||
3062 | #ifdef LANG | ||
3063 | LangSetWindowText(*this, IDB_COMPRESS_OPTIONS); // IDS_OPTIONS | ||
3064 | LangSetDlgItems(*this, kLangIDs_Options, ARRAY_SIZE(kLangIDs_Options)); | ||
3065 | // LangSetDlgItemText(*this, IDB_COMPRESS_TIME_DEFAULT, IDB_COMPRESS_TIME_DEFAULT); | ||
3066 | // LangSetDlgItemText(*this, IDX_COMPRESS_TIME_DEFAULT, IDX_COMPRESS_TIME_DEFAULT); | ||
3067 | #endif | ||
3068 | |||
3069 | LangString(IDS_COMPRESS_SEC, SecString); | ||
3070 | if (SecString.IsEmpty()) | ||
3071 | SecString = "sec"; | ||
3072 | LangString(IDS_COMPRESS_NS, NsString); | ||
3073 | if (NsString.IsEmpty()) | ||
3074 | NsString = "ns"; | ||
3075 | |||
3076 | { | ||
3077 | // const CArcInfoEx &ai = cd->Get_ArcInfoEx(); | ||
3078 | |||
3079 | ShowItem_Bool ( IDX_COMPRESS_NT_SYM_LINKS, cd->SymLinks.Supported); | ||
3080 | ShowItem_Bool ( IDX_COMPRESS_NT_HARD_LINKS, cd->HardLinks.Supported); | ||
3081 | ShowItem_Bool ( IDX_COMPRESS_NT_ALT_STREAMS, cd->AltStreams.Supported); | ||
3082 | ShowItem_Bool ( IDX_COMPRESS_NT_SECUR, cd->NtSecurity.Supported); | ||
3083 | |||
3084 | ShowItem_Bool ( IDG_COMPRESS_NTFS, | ||
3085 | cd->SymLinks.Supported | ||
3086 | || cd->HardLinks.Supported | ||
3087 | || cd->AltStreams.Supported | ||
3088 | || cd->NtSecurity.Supported); | ||
3089 | } | ||
3090 | |||
3091 | /* we read property from two sources: | ||
3092 | 1) command line : (Info) | ||
3093 | 2) registry : (m_RegistryInfo) | ||
3094 | (Info) has priority, if both are no defined */ | ||
3095 | |||
3096 | CheckButton_Bool1 ( IDX_COMPRESS_NT_SYM_LINKS, cd->SymLinks); | ||
3097 | CheckButton_Bool1 ( IDX_COMPRESS_NT_HARD_LINKS, cd->HardLinks); | ||
3098 | CheckButton_Bool1 ( IDX_COMPRESS_NT_ALT_STREAMS, cd->AltStreams); | ||
3099 | CheckButton_Bool1 ( IDX_COMPRESS_NT_SECUR, cd->NtSecurity); | ||
3100 | |||
3101 | CheckButton_Bool1 (IDX_COMPRESS_PRESERVE_ATIME, cd->PreserveATime); | ||
3102 | |||
3103 | m_Prec.Attach (GetItem(IDC_COMPRESS_TIME_PREC)); | ||
3104 | |||
3105 | MTime.SetIDs ( IDX_COMPRESS_MTIME, IDX_COMPRESS_MTIME_SET); | ||
3106 | CTime.SetIDs ( IDX_COMPRESS_CTIME, IDX_COMPRESS_CTIME_SET); | ||
3107 | ATime.SetIDs ( IDX_COMPRESS_ATIME, IDX_COMPRESS_ATIME_SET); | ||
3108 | ZTime.SetIDs ( IDX_COMPRESS_ZTIME, IDX_COMPRESS_ZTIME_SET); | ||
3109 | |||
3110 | { | ||
3111 | const NCompression::CFormatOptions &fo = cd->Get_FormatOptions(); | ||
3112 | TimePrec = fo.TimePrec; | ||
3113 | MTime.BoolPair = fo.MTime; | ||
3114 | CTime.BoolPair = fo.CTime; | ||
3115 | ATime.BoolPair = fo.ATime; | ||
3116 | ZTime.BoolPair = fo.SetArcMTime; | ||
3117 | } | ||
3118 | |||
3119 | SetPrec(); | ||
3120 | |||
3121 | NormalizePosition(); | ||
3122 | |||
3123 | return CModalDialog::OnInit(); | ||
3124 | } | ||
3125 | |||
3126 | |||
3127 | bool COptionsDialog::OnCommand(int code, int itemID, LPARAM lParam) | ||
3128 | { | ||
3129 | if (code == CBN_SELCHANGE) | ||
3130 | { | ||
3131 | switch (itemID) | ||
3132 | { | ||
3133 | case IDC_COMPRESS_TIME_PREC: | ||
3134 | { | ||
3135 | Store_TimeBoxes(); | ||
3136 | SetTimeMAC(); // for zip/tar | ||
3137 | return true; | ||
3138 | } | ||
3139 | } | ||
3140 | } | ||
3141 | return CModalDialog::OnCommand(code, itemID, lParam); | ||
3142 | } | ||
3143 | |||
3144 | |||
3145 | bool COptionsDialog::OnButtonClicked(int buttonID, HWND buttonHWND) | ||
3146 | { | ||
3147 | switch (buttonID) | ||
3148 | { | ||
3149 | case IDX_COMPRESS_PREC_SET: { On_CheckBoxSet_Prec_Clicked(); return true; } | ||
3150 | case IDX_COMPRESS_MTIME_SET: { On_CheckBoxSet_Clicked (MTime); return true; } | ||
3151 | case IDX_COMPRESS_CTIME_SET: { On_CheckBoxSet_Clicked (CTime); return true; } | ||
3152 | case IDX_COMPRESS_ATIME_SET: { On_CheckBoxSet_Clicked (ATime); return true; } | ||
3153 | case IDX_COMPRESS_ZTIME_SET: { On_CheckBoxSet_Clicked (ZTime); return true; } | ||
3154 | } | ||
3155 | return CModalDialog::OnButtonClicked(buttonID, buttonHWND); | ||
3156 | } | ||
3157 | |||
3158 | |||
3159 | void COptionsDialog::OnOK() | ||
3160 | { | ||
3161 | GetButton_Bool1 (IDX_COMPRESS_NT_SYM_LINKS, cd->SymLinks); | ||
3162 | GetButton_Bool1 (IDX_COMPRESS_NT_HARD_LINKS, cd->HardLinks); | ||
3163 | GetButton_Bool1 (IDX_COMPRESS_NT_ALT_STREAMS, cd->AltStreams); | ||
3164 | GetButton_Bool1 (IDX_COMPRESS_NT_SECUR, cd->NtSecurity); | ||
3165 | GetButton_Bool1 (IDX_COMPRESS_PRESERVE_ATIME, cd->PreserveATime); | ||
3166 | |||
3167 | Store_TimeBoxes(); | ||
3168 | { | ||
3169 | NCompression::CFormatOptions &fo = cd->Get_FormatOptions(); | ||
3170 | fo.TimePrec = TimePrec; | ||
3171 | fo.MTime = MTime.BoolPair; | ||
3172 | fo.CTime = CTime.BoolPair; | ||
3173 | fo.ATime = ATime.BoolPair; | ||
3174 | fo.SetArcMTime = ZTime.BoolPair; | ||
3175 | } | ||
3176 | |||
3177 | CModalDialog::OnOK(); | ||
3178 | } | ||
3179 | |||
3180 | void COptionsDialog::OnHelp() | ||
3181 | { | ||
3182 | ShowHelpWindow(kHelpTopic); | ||
3183 | } | ||
diff --git a/CPP/7zip/UI/GUI/CompressDialog.h b/CPP/7zip/UI/GUI/CompressDialog.h index 171d118..d4590c9 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.h +++ b/CPP/7zip/UI/GUI/CompressDialog.h | |||
@@ -59,6 +59,14 @@ namespace NCompressDialog | |||
59 | CBoolPair HardLinks; | 59 | CBoolPair HardLinks; |
60 | CBoolPair AltStreams; | 60 | CBoolPair AltStreams; |
61 | CBoolPair NtSecurity; | 61 | CBoolPair NtSecurity; |
62 | |||
63 | CBoolPair PreserveATime; | ||
64 | |||
65 | UInt32 TimePrec; | ||
66 | CBoolPair MTime; | ||
67 | CBoolPair CTime; | ||
68 | CBoolPair ATime; | ||
69 | CBoolPair SetArcMTime; | ||
62 | 70 | ||
63 | UString ArcPath; // in: Relative or abs ; out: Relative or abs | 71 | UString ArcPath; // in: Relative or abs ; out: Relative or abs |
64 | 72 | ||
@@ -89,11 +97,46 @@ namespace NCompressDialog | |||
89 | Method.Empty(); | 97 | Method.Empty(); |
90 | Options.Empty(); | 98 | Options.Empty(); |
91 | EncryptionMethod.Empty(); | 99 | EncryptionMethod.Empty(); |
100 | TimePrec = (UInt32)(Int32)(-1); | ||
92 | } | 101 | } |
93 | }; | 102 | }; |
94 | } | 103 | } |
95 | 104 | ||
96 | 105 | ||
106 | struct CBool1 | ||
107 | { | ||
108 | bool Val; | ||
109 | bool Supported; | ||
110 | |||
111 | CBool1(): Val(false), Supported(false) {} | ||
112 | |||
113 | void Init() | ||
114 | { | ||
115 | Val = false; | ||
116 | Supported = false; | ||
117 | } | ||
118 | |||
119 | void SetTrueTrue() | ||
120 | { | ||
121 | Val = true; | ||
122 | Supported = true; | ||
123 | } | ||
124 | |||
125 | void SetVal_as_Supported(bool val) | ||
126 | { | ||
127 | Val = val; | ||
128 | Supported = true; | ||
129 | } | ||
130 | |||
131 | /* | ||
132 | bool IsVal_True_and_Defined() const | ||
133 | { | ||
134 | return Def && Val; | ||
135 | } | ||
136 | */ | ||
137 | }; | ||
138 | |||
139 | |||
97 | class CCompressDialog: public NWindows::NControl::CModalDialog | 140 | class CCompressDialog: public NWindows::NControl::CModalDialog |
98 | { | 141 | { |
99 | NWindows::NControl::CComboBox m_ArchivePath; | 142 | NWindows::NControl::CComboBox m_ArchivePath; |
@@ -126,8 +169,6 @@ class CCompressDialog: public NWindows::NControl::CModalDialog | |||
126 | 169 | ||
127 | int _default_encryptionMethod_Index; | 170 | int _default_encryptionMethod_Index; |
128 | 171 | ||
129 | NCompression::CInfo m_RegistryInfo; | ||
130 | |||
131 | int m_PrevFormat; | 172 | int m_PrevFormat; |
132 | UString DirPrefix; | 173 | UString DirPrefix; |
133 | UString StartDirPrefix; | 174 | UString StartDirPrefix; |
@@ -137,23 +178,25 @@ class CCompressDialog: public NWindows::NControl::CModalDialog | |||
137 | UInt64 _ramSize_Reduced; // full for 64-bit and reduced for 32-bit | 178 | UInt64 _ramSize_Reduced; // full for 64-bit and reduced for 32-bit |
138 | UInt64 _ramUsage_Auto; | 179 | UInt64 _ramUsage_Auto; |
139 | 180 | ||
140 | void CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2); | 181 | public: |
141 | void GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2); | 182 | NCompression::CInfo m_RegistryInfo; |
183 | |||
184 | CBool1 SymLinks; | ||
185 | CBool1 HardLinks; | ||
186 | CBool1 AltStreams; | ||
187 | CBool1 NtSecurity; | ||
188 | CBool1 PreserveATime; | ||
142 | 189 | ||
143 | void SetArchiveName(const UString &name); | 190 | void SetArchiveName(const UString &name); |
144 | int FindRegistryFormat(const UString &name); | 191 | int FindRegistryFormat(const UString &name); |
145 | int FindRegistryFormatAlways(const UString &name); | 192 | unsigned FindRegistryFormat_Always(const UString &name); |
146 | 193 | ||
147 | const CArcInfoEx &Get_ArcInfoEx() | 194 | const CArcInfoEx &Get_ArcInfoEx() |
148 | { | 195 | { |
149 | return (*ArcFormats)[GetFormatIndex()]; | 196 | return (*ArcFormats)[GetFormatIndex()]; |
150 | } | 197 | } |
151 | 198 | ||
152 | NCompression::CFormatOptions &Get_FormatOptions() | 199 | NCompression::CFormatOptions &Get_FormatOptions(); |
153 | { | ||
154 | const CArcInfoEx &ai = Get_ArcInfoEx(); | ||
155 | return m_RegistryInfo.Formats[ FindRegistryFormatAlways(ai.Name) ]; | ||
156 | } | ||
157 | 200 | ||
158 | void CheckSFXNameChange(); | 201 | void CheckSFXNameChange(); |
159 | void SetArchiveName2(bool prevWasSFX); | 202 | void SetArchiveName2(bool prevWasSFX); |
@@ -237,6 +280,12 @@ class CCompressDialog: public NWindows::NControl::CModalDialog | |||
237 | 280 | ||
238 | UInt32 GetBlockSizeSpec() { return GetComboValue(m_Solid, 1); } | 281 | UInt32 GetBlockSizeSpec() { return GetComboValue(m_Solid, 1); } |
239 | 282 | ||
283 | /* | ||
284 | UInt32 GetPrecSpec() { return GetComboValue(m_Prec, 1); } | ||
285 | UInt32 GetPrec() { return GetComboValue(m_Prec, 0); } | ||
286 | */ | ||
287 | |||
288 | |||
240 | int AddOrder(UInt32 size); | 289 | int AddOrder(UInt32 size); |
241 | int AddOrder_Auto(); | 290 | int AddOrder_Auto(); |
242 | 291 | ||
@@ -271,6 +320,7 @@ class CCompressDialog: public NWindows::NControl::CModalDialog | |||
271 | void PrintMemUsage(UINT res, UInt64 value); | 320 | void PrintMemUsage(UINT res, UInt64 value); |
272 | void SetMemoryUsage(); | 321 | void SetMemoryUsage(); |
273 | void SetParams(); | 322 | void SetParams(); |
323 | |||
274 | void SaveOptionsInMem(); | 324 | void SaveOptionsInMem(); |
275 | 325 | ||
276 | void UpdatePasswordControl(); | 326 | void UpdatePasswordControl(); |
@@ -283,7 +333,7 @@ class CCompressDialog: public NWindows::NControl::CModalDialog | |||
283 | void CheckSFXControlsEnable(); | 333 | void CheckSFXControlsEnable(); |
284 | // void CheckVolumeEnable(); | 334 | // void CheckVolumeEnable(); |
285 | void EnableMultiCombo(unsigned id); | 335 | void EnableMultiCombo(unsigned id); |
286 | void FormatChanged(); | 336 | void FormatChanged(bool isChanged); |
287 | 337 | ||
288 | void OnButtonSetArchive(); | 338 | void OnButtonSetArchive(); |
289 | bool IsSFX(); | 339 | bool IsSFX(); |
@@ -300,6 +350,8 @@ class CCompressDialog: public NWindows::NControl::CModalDialog | |||
300 | MessageBoxW(*this, message, L"7-Zip", MB_ICONERROR); | 350 | MessageBoxW(*this, message, L"7-Zip", MB_ICONERROR); |
301 | } | 351 | } |
302 | 352 | ||
353 | void ShowOptionsString(); | ||
354 | |||
303 | public: | 355 | public: |
304 | const CObjectVector<CArcInfoEx> *ArcFormats; | 356 | const CObjectVector<CArcInfoEx> *ArcFormats; |
305 | CUIntVector ArcIndices; // can not be empty, must contain Info.FormatIndex, if Info.FormatIndex >= 0 | 357 | CUIntVector ArcIndices; // can not be empty, must contain Info.FormatIndex, if Info.FormatIndex >= 0 |
@@ -313,11 +365,103 @@ public: | |||
313 | 365 | ||
314 | INT_PTR Create(HWND wndParent = 0) | 366 | INT_PTR Create(HWND wndParent = 0) |
315 | { | 367 | { |
316 | BIG_DIALOG_SIZE(400, 304); | 368 | BIG_DIALOG_SIZE(400, 320); |
317 | return CModalDialog::Create(SIZED_DIALOG(IDD_COMPRESS), wndParent); | 369 | return CModalDialog::Create(SIZED_DIALOG(IDD_COMPRESS), wndParent); |
318 | } | 370 | } |
319 | 371 | ||
320 | CCompressDialog(): CurrentDirWasChanged(false) {}; | 372 | CCompressDialog(): CurrentDirWasChanged(false) {}; |
321 | }; | 373 | }; |
322 | 374 | ||
375 | |||
376 | |||
377 | |||
378 | class COptionsDialog: public NWindows::NControl::CModalDialog | ||
379 | { | ||
380 | struct CBoolBox | ||
381 | { | ||
382 | bool IsSupported; | ||
383 | bool DefaultVal; | ||
384 | CBoolPair BoolPair; | ||
385 | |||
386 | int Id; | ||
387 | int Set_Id; | ||
388 | |||
389 | void SetIDs(int id, int set_Id) | ||
390 | { | ||
391 | Id = id; | ||
392 | Set_Id = set_Id; | ||
393 | } | ||
394 | |||
395 | CBoolBox(): | ||
396 | IsSupported(false), | ||
397 | DefaultVal(false) | ||
398 | {} | ||
399 | }; | ||
400 | |||
401 | CCompressDialog *cd; | ||
402 | |||
403 | NWindows::NControl::CComboBox m_Prec; | ||
404 | |||
405 | UInt32 _auto_Prec; | ||
406 | UInt32 TimePrec; | ||
407 | |||
408 | void Reset_TimePrec() { TimePrec = (UInt32)(Int32)-1; } | ||
409 | bool IsSet_TimePrec() const { return TimePrec != (UInt32)(Int32)-1; } | ||
410 | |||
411 | CBoolBox MTime; | ||
412 | CBoolBox CTime; | ||
413 | CBoolBox ATime; | ||
414 | CBoolBox ZTime; | ||
415 | |||
416 | UString SecString; | ||
417 | UString NsString; | ||
418 | |||
419 | |||
420 | void CheckButton_Bool1(UINT id, const CBool1 &b1); | ||
421 | void GetButton_Bool1(UINT id, CBool1 &b1); | ||
422 | void CheckButton_BoolBox(bool supported, const CBoolPair &b2, CBoolBox &bb); | ||
423 | void GetButton_BoolBox(CBoolBox &bb); | ||
424 | |||
425 | void Store_TimeBoxes(); | ||
426 | |||
427 | UInt32 GetComboValue(NWindows::NControl::CComboBox &c, int defMax = 0); | ||
428 | UInt32 GetPrecSpec() | ||
429 | { | ||
430 | UInt32 prec = GetComboValue(m_Prec, 1); | ||
431 | if (prec == _auto_Prec) | ||
432 | prec = (UInt32)(Int32)-1; | ||
433 | return prec; | ||
434 | } | ||
435 | UInt32 GetPrec() { return GetComboValue(m_Prec, 0); } | ||
436 | |||
437 | // void OnButton_TimeDefault(); | ||
438 | int AddPrec(unsigned prec, bool isDefault); | ||
439 | void SetPrec(); | ||
440 | void SetTimeMAC(); | ||
441 | |||
442 | void On_CheckBoxSet_Prec_Clicked(); | ||
443 | void On_CheckBoxSet_Clicked(const CBoolBox &bb); | ||
444 | |||
445 | virtual bool OnInit(); | ||
446 | virtual bool OnCommand(int code, int itemID, LPARAM lParam); | ||
447 | virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); | ||
448 | virtual void OnOK(); | ||
449 | virtual void OnHelp(); | ||
450 | |||
451 | public: | ||
452 | |||
453 | INT_PTR Create(HWND wndParent = 0) | ||
454 | { | ||
455 | BIG_DIALOG_SIZE(240, 232); | ||
456 | return CModalDialog::Create(SIZED_DIALOG(IDD_COMPRESS_OPTIONS), wndParent); | ||
457 | } | ||
458 | |||
459 | COptionsDialog(CCompressDialog *cdLoc): | ||
460 | cd(cdLoc) | ||
461 | // , TimePrec(0) | ||
462 | { | ||
463 | Reset_TimePrec(); | ||
464 | }; | ||
465 | }; | ||
466 | |||
323 | #endif | 467 | #endif |
diff --git a/CPP/7zip/UI/GUI/CompressDialog.rc b/CPP/7zip/UI/GUI/CompressDialog.rc index 52c9546..d47a3ed 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.rc +++ b/CPP/7zip/UI/GUI/CompressDialog.rc | |||
@@ -2,7 +2,7 @@ | |||
2 | #include "../../GuiCommon.rc" | 2 | #include "../../GuiCommon.rc" |
3 | 3 | ||
4 | #define xc 400 | 4 | #define xc 400 |
5 | #define yc 354 | 5 | #define yc 320 |
6 | 6 | ||
7 | #undef gSize | 7 | #undef gSize |
8 | #undef gSpace | 8 | #undef gSpace |
@@ -20,10 +20,6 @@ | |||
20 | #define gSize 192 | 20 | #define gSize 192 |
21 | #define gSpace 24 | 21 | #define gSpace 24 |
22 | 22 | ||
23 | #define ntSize2 168 | ||
24 | #define ntSizeX (ntSize2 - m - m) | ||
25 | #define ntPosX m + m | ||
26 | #define ntPosY 292 | ||
27 | 23 | ||
28 | #define g1xs 88 | 24 | #define g1xs 88 |
29 | #define g0xs (gSize - g1xs) | 25 | #define g0xs (gSize - g1xs) |
@@ -99,18 +95,9 @@ BEGIN | |||
99 | LTEXT "Parameters:", IDT_COMPRESS_PARAMETERS, m, 256, gSize, 8 | 95 | LTEXT "Parameters:", IDT_COMPRESS_PARAMETERS, m, 256, gSize, 8 |
100 | EDITTEXT IDE_COMPRESS_PARAMETERS, m, 268, gSize, 14, ES_AUTOHSCROLL | 96 | EDITTEXT IDE_COMPRESS_PARAMETERS, m, 268, gSize, 14, ES_AUTOHSCROLL |
101 | 97 | ||
102 | 98 | PUSHBUTTON "Options", IDB_COMPRESS_OPTIONS, m, 292, bxs, bys | |
103 | GROUPBOX "NTFS", IDG_COMPRESS_NTFS, m, ntPosY, ntSize2, 68 | 99 | LTEXT "", IDT_COMPRESS_OPTIONS, m + bxs + m, 294, gSize - bxs - m, 16, SS_NOPREFIX |
104 | 100 | ||
105 | CONTROL "Store symbolic links", IDX_COMPRESS_NT_SYM_LINKS, MY_CHECKBOX, | ||
106 | ntPosX, ntPosY + 12, ntSizeX, 10 | ||
107 | CONTROL "Store hard links", IDX_COMPRESS_NT_HARD_LINKS, MY_CHECKBOX, | ||
108 | ntPosX, ntPosY + 26, ntSizeX, 10 | ||
109 | CONTROL "Store alternate data streams", IDX_COMPRESS_NT_ALT_STREAMS, MY_CHECKBOX, | ||
110 | ntPosX, ntPosY + 40, ntSizeX, 10 | ||
111 | CONTROL "Store file security", IDX_COMPRESS_NT_SECUR, MY_CHECKBOX, | ||
112 | ntPosX, ntPosY + 54, ntSizeX, 10 | ||
113 | |||
114 | 101 | ||
115 | LTEXT "&Update mode:", IDT_COMPRESS_UPDATE_MODE, g4x, 41, 80, 8 | 102 | LTEXT "&Update mode:", IDT_COMPRESS_UPDATE_MODE, g4x, 41, 80, 8 |
116 | COMBOBOX IDC_COMPRESS_UPDATE_MODE, g4x + 84, 39, g4xs - 84, 80, MY_COMBO | 103 | COMBOBOX IDC_COMPRESS_UPDATE_MODE, g4x + 84, 39, g4xs - 84, 80, MY_COMBO |
@@ -225,4 +212,10 @@ BEGIN | |||
225 | IDS_COMPRESS_SOLID "Solid" | 212 | IDS_COMPRESS_SOLID "Solid" |
226 | 213 | ||
227 | IDS_SPLIT_CONFIRM "Specified volume size: {0} bytes.\nAre you sure you want to split archive into such volumes?" | 214 | IDS_SPLIT_CONFIRM "Specified volume size: {0} bytes.\nAre you sure you want to split archive into such volumes?" |
215 | |||
216 | IDS_COMPRESS_SEC "sec" | ||
217 | IDS_COMPRESS_NS "ns" | ||
228 | END | 218 | END |
219 | |||
220 | |||
221 | #include "CompressOptionsDialog.rc" | ||
diff --git a/CPP/7zip/UI/GUI/CompressDialogRes.h b/CPP/7zip/UI/GUI/CompressDialogRes.h index 341b753..80b39be 100644 --- a/CPP/7zip/UI/GUI/CompressDialogRes.h +++ b/CPP/7zip/UI/GUI/CompressDialogRes.h | |||
@@ -1,5 +1,6 @@ | |||
1 | #define IDD_COMPRESS 4000 | 1 | #define IDD_COMPRESS 4000 |
2 | #define IDD_COMPRESS_2 14000 | 2 | #define IDD_COMPRESS_2 14000 |
3 | #define IDD_COMPRESS_OPTIONS 14001 | ||
3 | 4 | ||
4 | #define IDC_COMPRESS_ARCHIVE 100 | 5 | #define IDC_COMPRESS_ARCHIVE 100 |
5 | #define IDB_COMPRESS_SET_ARCHIVE 101 | 6 | #define IDB_COMPRESS_SET_ARCHIVE 101 |
@@ -28,6 +29,10 @@ | |||
28 | 29 | ||
29 | #define IDT_COMPRESS_ARCHIVE_FOLDER 130 | 30 | #define IDT_COMPRESS_ARCHIVE_FOLDER 130 |
30 | 31 | ||
32 | // #define IDB_COMPRESS_OPTIONS 140 | ||
33 | #define IDB_COMPRESS_OPTIONS 2100 | ||
34 | #define IDT_COMPRESS_OPTIONS 141 | ||
35 | |||
31 | #define IDT_COMPRESS_PATH_MODE 3410 | 36 | #define IDT_COMPRESS_PATH_MODE 3410 |
32 | 37 | ||
33 | #define IDT_PASSWORD_ENTER 3801 | 38 | #define IDT_PASSWORD_ENTER 3801 |
@@ -86,3 +91,31 @@ | |||
86 | #define IDT_SPLIT_TO_VOLUMES 7302 | 91 | #define IDT_SPLIT_TO_VOLUMES 7302 |
87 | #define IDS_INCORRECT_VOLUME_SIZE 7307 | 92 | #define IDS_INCORRECT_VOLUME_SIZE 7307 |
88 | #define IDS_SPLIT_CONFIRM 7308 | 93 | #define IDS_SPLIT_CONFIRM 7308 |
94 | |||
95 | |||
96 | // Options Dialog | ||
97 | |||
98 | #define IDG_COMPRESS_TIME 4080 | ||
99 | #define IDT_COMPRESS_TIME_PREC 4081 | ||
100 | #define IDX_COMPRESS_MTIME 4082 | ||
101 | #define IDX_COMPRESS_CTIME 4083 | ||
102 | #define IDX_COMPRESS_ATIME 4084 | ||
103 | #define IDX_COMPRESS_ZTIME 4085 | ||
104 | #define IDX_COMPRESS_PRESERVE_ATIME 4086 | ||
105 | |||
106 | #define IDS_COMPRESS_SEC 4090 | ||
107 | #define IDS_COMPRESS_NS 4091 | ||
108 | |||
109 | #define IDC_COMPRESS_TIME_PREC 190 | ||
110 | #define IDT_COMPRESS_TIME_INFO 191 | ||
111 | |||
112 | #define IDX_COMPRESS_PREC_SET 201 | ||
113 | #define IDX_COMPRESS_MTIME_SET 202 | ||
114 | #define IDX_COMPRESS_CTIME_SET 203 | ||
115 | #define IDX_COMPRESS_ATIME_SET 204 | ||
116 | #define IDX_COMPRESS_ZTIME_SET 205 | ||
117 | |||
118 | // #define IDX_COMPRESS_NT_SYM_LINKS_SET 210 | ||
119 | // #define IDX_COMPRESS_NT_HARD_LINKS_SET 211 | ||
120 | // #define IDX_COMPRESS_NT_ALT_STREAMS_SET 212 | ||
121 | // #define IDX_COMPRESS_NT_SECUR_SET 213 | ||
diff --git a/CPP/7zip/UI/GUI/CompressOptionsDialog.rc b/CPP/7zip/UI/GUI/CompressOptionsDialog.rc new file mode 100644 index 0000000..0578227 --- /dev/null +++ b/CPP/7zip/UI/GUI/CompressOptionsDialog.rc | |||
@@ -0,0 +1,76 @@ | |||
1 | #include "CompressDialogRes.h" | ||
2 | #include "../../GuiCommon.rc" | ||
3 | |||
4 | #define xc 240 | ||
5 | #define yc 232 | ||
6 | |||
7 | #define g5x m | ||
8 | #define g5x2 (g5x + m) | ||
9 | #define g5xs (xc) | ||
10 | #define g5xs2 (g5xs - m - m) | ||
11 | |||
12 | #define ntPosX g5x2 | ||
13 | #define ntPosY m | ||
14 | #define ntSizeX g5xs2 | ||
15 | #define precSizeX 76 | ||
16 | |||
17 | #define ntSizeY 72 | ||
18 | #define timePosY (ntPosY + ntSizeY + 20) | ||
19 | |||
20 | #define ceSize 18 | ||
21 | #define ceString ":" | ||
22 | |||
23 | |||
24 | IDD_COMPRESS_OPTIONS DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT | ||
25 | CAPTION "Options" | ||
26 | BEGIN | ||
27 | GROUPBOX "NTFS", IDG_COMPRESS_NTFS, g5x, ntPosY, g5xs, ntSizeY | ||
28 | |||
29 | CONTROL "Store symbolic links", IDX_COMPRESS_NT_SYM_LINKS, MY_CHECKBOX, | ||
30 | ntPosX, ntPosY + 12, ntSizeX, 10 | ||
31 | CONTROL "Store hard links", IDX_COMPRESS_NT_HARD_LINKS, MY_CHECKBOX, | ||
32 | ntPosX, ntPosY + 26, ntSizeX, 10 | ||
33 | CONTROL "Store alternate data streams", IDX_COMPRESS_NT_ALT_STREAMS, MY_CHECKBOX, | ||
34 | ntPosX, ntPosY + 40, ntSizeX, 10 | ||
35 | CONTROL "Store file security", IDX_COMPRESS_NT_SECUR, MY_CHECKBOX, | ||
36 | ntPosX, ntPosY + 54, ntSizeX, 10 | ||
37 | |||
38 | LTEXT "", IDT_COMPRESS_TIME_INFO, g5x, timePosY - 14, g5xs, 8 | ||
39 | |||
40 | |||
41 | GROUPBOX "Time", IDG_COMPRESS_TIME, g5x, timePosY, g5xs, 112 | ||
42 | |||
43 | // CONTROL "Default", IDX_COMPRESS_TIME_DEFAULT, MY_CHECKBOX, | ||
44 | // ntPosX, timePosY + 10, ntSizeX, 16 | ||
45 | |||
46 | CONTROL ceString, IDX_COMPRESS_PREC_SET, MY_CHECKBOX, ntPosX, timePosY + 14, ceSize, 10 | ||
47 | LTEXT "Timestamp precision:", IDT_COMPRESS_TIME_PREC, | ||
48 | ntPosX + ceSize, timePosY + 14, ntSizeX - precSizeX - ceSize, 8 | ||
49 | COMBOBOX IDC_COMPRESS_TIME_PREC, ntPosX + ntSizeX - precSizeX, timePosY + 12, precSizeX, 70, MY_COMBO | ||
50 | |||
51 | // PUSHBUTTON "Default", IDB_COMPRESS_TIME_DEFAULT, ntPosX + ntSizeX - bxs, timePosY + 22, bxs, bys, WS_GROUP | ||
52 | |||
53 | CONTROL ceString, IDX_COMPRESS_MTIME_SET, MY_CHECKBOX, ntPosX, timePosY + 28, ceSize, 10 | ||
54 | CONTROL "Store modification time", IDX_COMPRESS_MTIME, MY_CHECKBOX, | ||
55 | ntPosX + ceSize, timePosY + 28, ntSizeX - ceSize, 10 | ||
56 | |||
57 | CONTROL ceString, IDX_COMPRESS_CTIME_SET, MY_CHECKBOX, ntPosX, timePosY + 42, ceSize, 10 | ||
58 | CONTROL "Store creation time", IDX_COMPRESS_CTIME, MY_CHECKBOX, | ||
59 | ntPosX + ceSize, timePosY + 42, ntSizeX - ceSize, 10 | ||
60 | |||
61 | CONTROL ceString, IDX_COMPRESS_ATIME_SET, MY_CHECKBOX, ntPosX, timePosY + 56, ceSize, 10 | ||
62 | CONTROL "Store last access time", IDX_COMPRESS_ATIME, MY_CHECKBOX, | ||
63 | ntPosX + ceSize, timePosY + 56, ntSizeX - ceSize, 10 | ||
64 | |||
65 | CONTROL ceString, IDX_COMPRESS_ZTIME_SET, MY_CHECKBOX | BS_MULTILINE, ntPosX, timePosY + 72, ceSize, 16 | ||
66 | CONTROL "Set archive time to latest file time", IDX_COMPRESS_ZTIME, MY_CHECKBOX | BS_MULTILINE, | ||
67 | ntPosX + ceSize, timePosY + 72, ntSizeX - ceSize, 16 | ||
68 | |||
69 | CONTROL "Do not change source files last access time", IDX_COMPRESS_PRESERVE_ATIME, MY_CHECKBOX | BS_MULTILINE, | ||
70 | ntPosX, timePosY + 92, ntSizeX, 16 | ||
71 | |||
72 | |||
73 | DEFPUSHBUTTON "OK", IDOK, bx3, by, bxs, bys, WS_GROUP | ||
74 | PUSHBUTTON "Cancel", IDCANCEL, bx2, by, bxs, bys | ||
75 | PUSHBUTTON "Help", IDHELP, bx1, by, bxs, bys | ||
76 | END | ||
diff --git a/CPP/7zip/UI/GUI/GUI.cpp b/CPP/7zip/UI/GUI/GUI.cpp index 32a48e7..c977516 100644 --- a/CPP/7zip/UI/GUI/GUI.cpp +++ b/CPP/7zip/UI/GUI/GUI.cpp | |||
@@ -75,6 +75,8 @@ extern | |||
75 | bool g_LVN_ITEMACTIVATE_Support; | 75 | bool g_LVN_ITEMACTIVATE_Support; |
76 | bool g_LVN_ITEMACTIVATE_Support = true; | 76 | bool g_LVN_ITEMACTIVATE_Support = true; |
77 | 77 | ||
78 | DECLARE_AND_SET_CLIENT_VERSION_VAR | ||
79 | |||
78 | static void ErrorMessage(LPCWSTR message) | 80 | static void ErrorMessage(LPCWSTR message) |
79 | { | 81 | { |
80 | MessageBoxW(NULL, message, L"7-Zip", MB_ICONERROR | MB_OK); | 82 | MessageBoxW(NULL, message, L"7-Zip", MB_ICONERROR | MB_OK); |
@@ -135,7 +137,7 @@ static int Main2() | |||
135 | 137 | ||
136 | CREATE_CODECS_OBJECT | 138 | CREATE_CODECS_OBJECT |
137 | 139 | ||
138 | codecs->CaseSensitiveChange = options.CaseSensitiveChange; | 140 | codecs->CaseSensitive_Change = options.CaseSensitive_Change; |
139 | codecs->CaseSensitive = options.CaseSensitive; | 141 | codecs->CaseSensitive = options.CaseSensitive; |
140 | ThrowException_if_Error(codecs->Load()); | 142 | ThrowException_if_Error(codecs->Load()); |
141 | Codecs_AddHashArcHandler(codecs); | 143 | Codecs_AddHashArcHandler(codecs); |
diff --git a/CPP/7zip/UI/GUI/GUI.dsp b/CPP/7zip/UI/GUI/GUI.dsp index 53a2c92..b55a115 100644 --- a/CPP/7zip/UI/GUI/GUI.dsp +++ b/CPP/7zip/UI/GUI/GUI.dsp | |||
@@ -773,6 +773,10 @@ SOURCE=..\..\..\..\C\7zCrcOpt.c | |||
773 | # End Source File | 773 | # End Source File |
774 | # Begin Source File | 774 | # Begin Source File |
775 | 775 | ||
776 | SOURCE=..\..\..\..\C\7zTypes.h | ||
777 | # End Source File | ||
778 | # Begin Source File | ||
779 | |||
776 | SOURCE=..\..\..\..\C\Alloc.c | 780 | SOURCE=..\..\..\..\C\Alloc.c |
777 | # SUBTRACT CPP /YX /Yc /Yu | 781 | # SUBTRACT CPP /YX /Yc /Yu |
778 | # End Source File | 782 | # End Source File |
@@ -1211,5 +1215,17 @@ SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp | |||
1211 | SOURCE=..\..\Archive\Common\OutStreamWithCRC.h | 1215 | SOURCE=..\..\Archive\Common\OutStreamWithCRC.h |
1212 | # End Source File | 1216 | # End Source File |
1213 | # End Group | 1217 | # End Group |
1218 | # Begin Group "7-Zip" | ||
1219 | |||
1220 | # PROP Default_Filter "" | ||
1221 | # Begin Source File | ||
1222 | |||
1223 | SOURCE=..\..\Archive\IArchive.h | ||
1224 | # End Source File | ||
1225 | # Begin Source File | ||
1226 | |||
1227 | SOURCE=..\..\ICoder.h | ||
1228 | # End Source File | ||
1229 | # End Group | ||
1214 | # End Target | 1230 | # End Target |
1215 | # End Project | 1231 | # End Project |
diff --git a/CPP/7zip/UI/GUI/UpdateGUI.cpp b/CPP/7zip/UI/GUI/UpdateGUI.cpp index a3a1d88..2d04143 100644 --- a/CPP/7zip/UI/GUI/UpdateGUI.cpp +++ b/CPP/7zip/UI/GUI/UpdateGUI.cpp | |||
@@ -61,6 +61,53 @@ HRESULT CThreadUpdating::ProcessVirt() | |||
61 | return HRESULT_FROM_WIN32(ei.SystemError); | 61 | return HRESULT_FROM_WIN32(ei.SystemError); |
62 | } | 62 | } |
63 | 63 | ||
64 | |||
65 | // parse command line properties | ||
66 | |||
67 | static bool ParseProp_Time_BoolPair(const CProperty &prop, const char *name, CBoolPair &bp) | ||
68 | { | ||
69 | if (!prop.Name.IsPrefixedBy_Ascii_NoCase(name)) | ||
70 | return false; | ||
71 | const UString rem = prop.Name.Ptr((unsigned)strlen(name)); | ||
72 | UString val = prop.Value; | ||
73 | if (!rem.IsEmpty()) | ||
74 | { | ||
75 | if (!val.IsEmpty()) | ||
76 | return true; | ||
77 | val = rem; | ||
78 | } | ||
79 | bool res; | ||
80 | if (StringToBool(val, res)) | ||
81 | { | ||
82 | bp.Val = res; | ||
83 | bp.Def = true; | ||
84 | } | ||
85 | return true; | ||
86 | } | ||
87 | |||
88 | static void ParseProp( | ||
89 | const CProperty &prop, | ||
90 | NCompressDialog::CInfo &di) | ||
91 | { | ||
92 | if (ParseProp_Time_BoolPair(prop, "tm", di.MTime)) return; | ||
93 | if (ParseProp_Time_BoolPair(prop, "tc", di.CTime)) return; | ||
94 | if (ParseProp_Time_BoolPair(prop, "ta", di.ATime)) return; | ||
95 | } | ||
96 | |||
97 | static void ParseProperties( | ||
98 | const CObjectVector<CProperty> &properties, | ||
99 | NCompressDialog::CInfo &di) | ||
100 | { | ||
101 | FOR_VECTOR (i, properties) | ||
102 | { | ||
103 | ParseProp(properties[i], di); | ||
104 | } | ||
105 | } | ||
106 | |||
107 | |||
108 | |||
109 | |||
110 | |||
64 | static void AddProp_UString(CObjectVector<CProperty> &properties, const char *name, const UString &value) | 111 | static void AddProp_UString(CObjectVector<CProperty> &properties, const char *name, const UString &value) |
65 | { | 112 | { |
66 | CProperty prop; | 113 | CProperty prop; |
@@ -81,10 +128,31 @@ static void AddProp_bool(CObjectVector<CProperty> &properties, const char *name, | |||
81 | AddProp_UString(properties, name, UString(value ? "on": "off")); | 128 | AddProp_UString(properties, name, UString(value ? "on": "off")); |
82 | } | 129 | } |
83 | 130 | ||
84 | static bool IsThereMethodOverride(bool is7z, const UString &propertiesString) | 131 | |
132 | static void AddProp_BoolPair(CObjectVector<CProperty> &properties, | ||
133 | const char *name, const CBoolPair &bp) | ||
134 | { | ||
135 | if (bp.Def) | ||
136 | AddProp_bool(properties, name, bp.Val); | ||
137 | } | ||
138 | |||
139 | |||
140 | |||
141 | static void SplitOptionsToStrings(const UString &src, UStringVector &strings) | ||
142 | { | ||
143 | SplitString(src, strings); | ||
144 | FOR_VECTOR (i, strings) | ||
145 | { | ||
146 | UString &s = strings[i]; | ||
147 | if (s.Len() > 2 | ||
148 | && s[0] == '-' | ||
149 | && MyCharLower_Ascii(s[1]) == 'm') | ||
150 | s.DeleteFrontal(2); | ||
151 | } | ||
152 | } | ||
153 | |||
154 | static bool IsThereMethodOverride(bool is7z, const UStringVector &strings) | ||
85 | { | 155 | { |
86 | UStringVector strings; | ||
87 | SplitString(propertiesString, strings); | ||
88 | FOR_VECTOR (i, strings) | 156 | FOR_VECTOR (i, strings) |
89 | { | 157 | { |
90 | const UString &s = strings[i]; | 158 | const UString &s = strings[i]; |
@@ -106,17 +174,11 @@ static bool IsThereMethodOverride(bool is7z, const UString &propertiesString) | |||
106 | } | 174 | } |
107 | 175 | ||
108 | static void ParseAndAddPropertires(CObjectVector<CProperty> &properties, | 176 | static void ParseAndAddPropertires(CObjectVector<CProperty> &properties, |
109 | const UString &propertiesString) | 177 | const UStringVector &strings) |
110 | { | 178 | { |
111 | UStringVector strings; | ||
112 | SplitString(propertiesString, strings); | ||
113 | FOR_VECTOR (i, strings) | 179 | FOR_VECTOR (i, strings) |
114 | { | 180 | { |
115 | UString s = strings[i]; | 181 | const UString &s = strings[i]; |
116 | if (s.Len() > 2 | ||
117 | && s[0] == '-' | ||
118 | && MyCharLower_Ascii(s[1]) == 'm') | ||
119 | s.DeleteFrontal(2); | ||
120 | CProperty property; | 182 | CProperty property; |
121 | const int index = s.Find(L'='); | 183 | const int index = s.Find(L'='); |
122 | if (index < 0) | 184 | if (index < 0) |
@@ -142,58 +204,49 @@ static void AddProp_Size(CObjectVector<CProperty> &properties, const char *name, | |||
142 | 204 | ||
143 | static void SetOutProperties( | 205 | static void SetOutProperties( |
144 | CObjectVector<CProperty> &properties, | 206 | CObjectVector<CProperty> &properties, |
207 | const NCompressDialog::CInfo &di, | ||
145 | bool is7z, | 208 | bool is7z, |
146 | UInt32 level, | 209 | bool setMethod) |
147 | bool setMethod, | ||
148 | const UString &method, | ||
149 | UInt64 dict64, | ||
150 | bool orderMode, | ||
151 | UInt32 order, | ||
152 | bool solidIsSpecified, UInt64 solidBlockSize, | ||
153 | // bool multiThreadIsAllowed, | ||
154 | UInt32 numThreads, | ||
155 | const UString &encryptionMethod, | ||
156 | bool encryptHeadersIsAllowed, bool encryptHeaders, | ||
157 | const NCompression::CMemUse &memUse, | ||
158 | bool /* sfxMode */) | ||
159 | { | 210 | { |
160 | if (level != (UInt32)(Int32)-1) | 211 | if (di.Level != (UInt32)(Int32)-1) |
161 | AddProp_UInt32(properties, "x", (UInt32)level); | 212 | AddProp_UInt32(properties, "x", (UInt32)di.Level); |
162 | if (setMethod) | 213 | if (setMethod) |
163 | { | 214 | { |
164 | if (!method.IsEmpty()) | 215 | if (!di.Method.IsEmpty()) |
165 | AddProp_UString(properties, is7z ? "0": "m", method); | 216 | AddProp_UString(properties, is7z ? "0": "m", di.Method); |
166 | if (dict64 != (UInt64)(Int64)-1) | 217 | if (di.Dict64 != (UInt64)(Int64)-1) |
167 | { | 218 | { |
168 | AString name; | 219 | AString name; |
169 | if (is7z) | 220 | if (is7z) |
170 | name = "0"; | 221 | name = "0"; |
171 | name += (orderMode ? "mem" : "d"); | 222 | name += (di.OrderMode ? "mem" : "d"); |
172 | AddProp_Size(properties, name, dict64); | 223 | AddProp_Size(properties, name, di.Dict64); |
173 | } | 224 | } |
174 | if (order != (UInt32)(Int32)-1) | 225 | if (di.Order != (UInt32)(Int32)-1) |
175 | { | 226 | { |
176 | AString name; | 227 | AString name; |
177 | if (is7z) | 228 | if (is7z) |
178 | name = "0"; | 229 | name = "0"; |
179 | name += (orderMode ? "o" : "fb"); | 230 | name += (di.OrderMode ? "o" : "fb"); |
180 | AddProp_UInt32(properties, name, (UInt32)order); | 231 | AddProp_UInt32(properties, name, (UInt32)di.Order); |
181 | } | 232 | } |
182 | } | 233 | } |
183 | 234 | ||
184 | if (!encryptionMethod.IsEmpty()) | 235 | if (!di.EncryptionMethod.IsEmpty()) |
185 | AddProp_UString(properties, "em", encryptionMethod); | 236 | AddProp_UString(properties, "em", di.EncryptionMethod); |
186 | 237 | ||
187 | if (encryptHeadersIsAllowed) | 238 | if (di.EncryptHeadersIsAllowed) |
188 | AddProp_bool(properties, "he", encryptHeaders); | 239 | AddProp_bool(properties, "he", di.EncryptHeaders); |
189 | if (solidIsSpecified) | 240 | |
190 | AddProp_Size(properties, "s", solidBlockSize); | 241 | if (di.SolidIsSpecified) |
242 | AddProp_Size(properties, "s", di.SolidBlockSize); | ||
191 | 243 | ||
192 | if ( | 244 | if ( |
193 | // multiThreadIsAllowed && | 245 | // di.MultiThreadIsAllowed && |
194 | numThreads != (UInt32)(Int32)-1) | 246 | di.NumThreads != (UInt32)(Int32)-1) |
195 | AddProp_UInt32(properties, "mt", numThreads); | 247 | AddProp_UInt32(properties, "mt", di.NumThreads); |
196 | 248 | ||
249 | const NCompression::CMemUse &memUse = di.MemUsage; | ||
197 | if (memUse.IsDefined) | 250 | if (memUse.IsDefined) |
198 | { | 251 | { |
199 | const char *kMemUse = "memuse"; | 252 | const char *kMemUse = "memuse"; |
@@ -208,8 +261,16 @@ static void SetOutProperties( | |||
208 | else | 261 | else |
209 | AddProp_Size(properties, kMemUse, memUse.Val); | 262 | AddProp_Size(properties, kMemUse, memUse.Val); |
210 | } | 263 | } |
264 | |||
265 | AddProp_BoolPair(properties, "tm", di.MTime); | ||
266 | AddProp_BoolPair(properties, "tc", di.CTime); | ||
267 | AddProp_BoolPair(properties, "ta", di.ATime); | ||
268 | |||
269 | if (di.TimePrec != (UInt32)(Int32)-1) | ||
270 | AddProp_UInt32(properties, "tp", di.TimePrec); | ||
211 | } | 271 | } |
212 | 272 | ||
273 | |||
213 | struct C_UpdateMode_ToAction_Pair | 274 | struct C_UpdateMode_ToAction_Pair |
214 | { | 275 | { |
215 | NCompressDialog::NUpdateMode::EEnum UpdateMode; | 276 | NCompressDialog::NUpdateMode::EEnum UpdateMode; |
@@ -358,6 +419,10 @@ static HRESULT ShowDialog( | |||
358 | di.HardLinks = options.HardLinks; | 419 | di.HardLinks = options.HardLinks; |
359 | di.AltStreams = options.AltStreams; | 420 | di.AltStreams = options.AltStreams; |
360 | di.NtSecurity = options.NtSecurity; | 421 | di.NtSecurity = options.NtSecurity; |
422 | if (options.SetArcMTime) | ||
423 | di.SetArcMTime.SetTrueTrue(); | ||
424 | if (options.PreserveATime) | ||
425 | di.PreserveATime.SetTrueTrue(); | ||
361 | 426 | ||
362 | if (callback->PasswordIsDefined) | 427 | if (callback->PasswordIsDefined) |
363 | di.Password = callback->Password; | 428 | di.Password = callback->Password; |
@@ -373,6 +438,8 @@ static HRESULT ShowDialog( | |||
373 | di.UpdateMode = g_UpdateMode_Pairs[(unsigned)index].UpdateMode; | 438 | di.UpdateMode = g_UpdateMode_Pairs[(unsigned)index].UpdateMode; |
374 | } | 439 | } |
375 | 440 | ||
441 | ParseProperties(options.MethodMode.Properties, di); | ||
442 | |||
376 | if (dialog.Create(hwndParent) != IDOK) | 443 | if (dialog.Create(hwndParent) != IDOK) |
377 | return E_ABORT; | 444 | return E_ABORT; |
378 | 445 | ||
@@ -382,6 +449,9 @@ static HRESULT ShowDialog( | |||
382 | options.HardLinks = di.HardLinks; | 449 | options.HardLinks = di.HardLinks; |
383 | options.AltStreams = di.AltStreams; | 450 | options.AltStreams = di.AltStreams; |
384 | options.NtSecurity = di.NtSecurity; | 451 | options.NtSecurity = di.NtSecurity; |
452 | options.SetArcMTime = di.SetArcMTime.Val; | ||
453 | if (di.PreserveATime.Def) | ||
454 | options.PreserveATime = di.PreserveATime.Val; | ||
385 | 455 | ||
386 | #if defined(_WIN32) && !defined(UNDER_CE) | 456 | #if defined(_WIN32) && !defined(UNDER_CE) |
387 | curDirRestorer.NeedRestore = dialog.CurrentDirWasChanged; | 457 | curDirRestorer.NeedRestore = dialog.CurrentDirWasChanged; |
@@ -411,29 +481,21 @@ static HRESULT ShowDialog( | |||
411 | if (callback->PasswordIsDefined) | 481 | if (callback->PasswordIsDefined) |
412 | callback->Password = di.Password; | 482 | callback->Password = di.Password; |
413 | 483 | ||
484 | // we clear command line options, and fill options form Dialog | ||
414 | options.MethodMode.Properties.Clear(); | 485 | options.MethodMode.Properties.Clear(); |
415 | 486 | ||
416 | bool is7z = archiverInfo.Name.IsEqualTo_Ascii_NoCase("7z"); | 487 | const bool is7z = archiverInfo.Is_7z(); |
417 | bool methodOverride = IsThereMethodOverride(is7z, di.Options); | 488 | |
489 | UStringVector optionStrings; | ||
490 | SplitOptionsToStrings(di.Options, optionStrings); | ||
491 | const bool methodOverride = IsThereMethodOverride(is7z, optionStrings); | ||
418 | 492 | ||
419 | SetOutProperties( | 493 | SetOutProperties(options.MethodMode.Properties, di, |
420 | options.MethodMode.Properties, | ||
421 | is7z, | 494 | is7z, |
422 | di.Level, | 495 | !methodOverride); // setMethod |
423 | !methodOverride, | ||
424 | di.Method, | ||
425 | di.Dict64, | ||
426 | di.OrderMode, di.Order, | ||
427 | di.SolidIsSpecified, di.SolidBlockSize, | ||
428 | // di.MultiThreadIsAllowed, | ||
429 | di.NumThreads, | ||
430 | di.EncryptionMethod, | ||
431 | di.EncryptHeadersIsAllowed, di.EncryptHeaders, | ||
432 | di.MemUsage, | ||
433 | di.SFXMode); | ||
434 | 496 | ||
435 | options.OpenShareForWrite = di.OpenShareForWrite; | 497 | options.OpenShareForWrite = di.OpenShareForWrite; |
436 | ParseAndAddPropertires(options.MethodMode.Properties, di.Options); | 498 | ParseAndAddPropertires(options.MethodMode.Properties, optionStrings); |
437 | 499 | ||
438 | if (di.SFXMode) | 500 | if (di.SFXMode) |
439 | options.SfxMode = true; | 501 | options.SfxMode = true; |
diff --git a/CPP/Common/Common.h b/CPP/Common/Common.h index 8dac613..72db7a8 100644 --- a/CPP/Common/Common.h +++ b/CPP/Common/Common.h | |||
@@ -35,7 +35,7 @@ you can change this h file or h files included in this file. | |||
35 | So we can use MY_ARRAY_NEW macro instead of new[] operator. */ | 35 | So we can use MY_ARRAY_NEW macro instead of new[] operator. */ |
36 | 36 | ||
37 | #if defined(_MSC_VER) && (_MSC_VER == 1200) && !defined(_WIN64) | 37 | #if defined(_MSC_VER) && (_MSC_VER == 1200) && !defined(_WIN64) |
38 | #define MY_ARRAY_NEW(p, T, size) p = new T[(size > (unsigned)0xFFFFFFFF / sizeof(T)) ? (unsigned)0xFFFFFFFF / sizeof(T) : size]; | 38 | #define MY_ARRAY_NEW(p, T, size) p = new T[((size) > (unsigned)0xFFFFFFFF / sizeof(T)) ? (unsigned)0xFFFFFFFF / sizeof(T) : (size)]; |
39 | #else | 39 | #else |
40 | #define MY_ARRAY_NEW(p, T, size) p = new T[size]; | 40 | #define MY_ARRAY_NEW(p, T, size) p = new T[size]; |
41 | #endif | 41 | #endif |
diff --git a/CPP/Common/MyCom.h b/CPP/Common/MyCom.h index ce2f0dd..ff54278 100644 --- a/CPP/Common/MyCom.h +++ b/CPP/Common/MyCom.h | |||
@@ -67,6 +67,7 @@ public: | |||
67 | template <class Q> | 67 | template <class Q> |
68 | HRESULT QueryInterface(REFGUID iid, Q** pp) const throw() | 68 | HRESULT QueryInterface(REFGUID iid, Q** pp) const throw() |
69 | { | 69 | { |
70 | // if (*pp) throw 20220216; // for debug | ||
70 | return _p->QueryInterface(iid, (void**)pp); | 71 | return _p->QueryInterface(iid, (void**)pp); |
71 | } | 72 | } |
72 | }; | 73 | }; |
diff --git a/CPP/Common/MyLinux.h b/CPP/Common/MyLinux.h index 1a91899..98b453c 100644 --- a/CPP/Common/MyLinux.h +++ b/CPP/Common/MyLinux.h | |||
@@ -3,6 +3,18 @@ | |||
3 | #ifndef __MY_LIN_LINUX_H | 3 | #ifndef __MY_LIN_LINUX_H |
4 | #define __MY_LIN_LINUX_H | 4 | #define __MY_LIN_LINUX_H |
5 | 5 | ||
6 | // #include "../../C/7zTypes.h" | ||
7 | |||
8 | #define MY_LIN_DT_UNKNOWN 0 | ||
9 | #define MY_LIN_DT_FIFO 1 | ||
10 | #define MY_LIN_DT_CHR 2 | ||
11 | #define MY_LIN_DT_DIR 4 | ||
12 | #define MY_LIN_DT_BLK 6 | ||
13 | #define MY_LIN_DT_REG 8 | ||
14 | #define MY_LIN_DT_LNK 10 | ||
15 | #define MY_LIN_DT_SOCK 12 | ||
16 | #define MY_LIN_DT_WHT 14 | ||
17 | |||
6 | #define MY_LIN_S_IFMT 00170000 | 18 | #define MY_LIN_S_IFMT 00170000 |
7 | #define MY_LIN_S_IFSOCK 0140000 | 19 | #define MY_LIN_S_IFSOCK 0140000 |
8 | #define MY_LIN_S_IFLNK 0120000 | 20 | #define MY_LIN_S_IFLNK 0120000 |
@@ -39,4 +51,25 @@ | |||
39 | #define MY_LIN_S_IWOTH 00002 | 51 | #define MY_LIN_S_IWOTH 00002 |
40 | #define MY_LIN_S_IXOTH 00001 | 52 | #define MY_LIN_S_IXOTH 00001 |
41 | 53 | ||
54 | /* | ||
55 | // major/minor encoding for makedev(): MMMMMmmmmmmMMMmm: | ||
56 | |||
57 | inline UInt32 MY_dev_major(UInt64 dev) | ||
58 | { | ||
59 | return ((UInt32)(dev >> 8) & (UInt32)0xfff) | ((UInt32)(dev >> 32) & ~(UInt32)0xfff); | ||
60 | } | ||
61 | |||
62 | inline UInt32 MY_dev_minor(UInt64 dev) | ||
63 | { | ||
64 | return ((UInt32)(dev) & 0xff) | ((UInt32)(dev >> 12) & ~0xff); | ||
65 | } | ||
66 | |||
67 | inline UInt64 MY_dev_makedev(UInt32 __major, UInt32 __minor) | ||
68 | { | ||
69 | return (__minor & 0xff) | ((__major & 0xfff) << 8) | ||
70 | | ((UInt64) (__minor & ~0xff) << 12) | ||
71 | | ((UInt64) (__major & ~0xfff) << 32); | ||
72 | } | ||
73 | */ | ||
74 | |||
42 | #endif | 75 | #endif |
diff --git a/CPP/Common/MyString.cpp b/CPP/Common/MyString.cpp index db202f4..bf1638e 100644 --- a/CPP/Common/MyString.cpp +++ b/CPP/Common/MyString.cpp | |||
@@ -30,8 +30,8 @@ inline const char* MyStringGetNextCharPointer(const char *p) throw() | |||
30 | } | 30 | } |
31 | */ | 31 | */ |
32 | 32 | ||
33 | #define MY_STRING_NEW_char(_size_) MY_STRING_NEW(char, _size_) | 33 | #define MY_STRING_NEW_char(_size_) MY_STRING_NEW(char, (_size_)) |
34 | #define MY_STRING_NEW_wchar_t(_size_) MY_STRING_NEW(wchar_t, _size_) | 34 | #define MY_STRING_NEW_wchar_t(_size_) MY_STRING_NEW(wchar_t, (_size_)) |
35 | 35 | ||
36 | 36 | ||
37 | int FindCharPosInString(const char *s, char c) throw() | 37 | int FindCharPosInString(const char *s, char c) throw() |
@@ -190,8 +190,8 @@ bool IsString1PrefixedByString2(const char *s1, const char *s2) throw() | |||
190 | { | 190 | { |
191 | for (;;) | 191 | for (;;) |
192 | { | 192 | { |
193 | unsigned char c2 = (unsigned char)*s2++; if (c2 == 0) return true; | 193 | const unsigned char c2 = (unsigned char)*s2++; if (c2 == 0) return true; |
194 | unsigned char c1 = (unsigned char)*s1++; if (c1 != c2) return false; | 194 | const unsigned char c1 = (unsigned char)*s1++; if (c1 != c2) return false; |
195 | } | 195 | } |
196 | } | 196 | } |
197 | 197 | ||
@@ -199,8 +199,8 @@ bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw() | |||
199 | { | 199 | { |
200 | for (;;) | 200 | for (;;) |
201 | { | 201 | { |
202 | wchar_t c1 = *s1++; | 202 | const wchar_t c1 = *s1++; |
203 | wchar_t c2 = *s2++; | 203 | const wchar_t c2 = *s2++; |
204 | if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2)) return false; | 204 | if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2)) return false; |
205 | if (c1 == 0) return true; | 205 | if (c1 == 0) return true; |
206 | } | 206 | } |
@@ -213,10 +213,10 @@ bool AString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw() | |||
213 | const char *s1 = _chars; | 213 | const char *s1 = _chars; |
214 | for (;;) | 214 | for (;;) |
215 | { | 215 | { |
216 | char c2 = *s++; | 216 | const char c2 = *s++; |
217 | if (c2 == 0) | 217 | if (c2 == 0) |
218 | return true; | 218 | return true; |
219 | char c1 = *s1++; | 219 | const char c1 = *s1++; |
220 | if (MyCharLower_Ascii(c1) != | 220 | if (MyCharLower_Ascii(c1) != |
221 | MyCharLower_Ascii(c2)) | 221 | MyCharLower_Ascii(c2)) |
222 | return false; | 222 | return false; |
@@ -228,10 +228,10 @@ bool UString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw() | |||
228 | const wchar_t *s1 = _chars; | 228 | const wchar_t *s1 = _chars; |
229 | for (;;) | 229 | for (;;) |
230 | { | 230 | { |
231 | char c2 = *s++; | 231 | const char c2 = *s++; |
232 | if (c2 == 0) | 232 | if (c2 == 0) |
233 | return true; | 233 | return true; |
234 | wchar_t c1 = *s1++; | 234 | const wchar_t c1 = *s1++; |
235 | if (MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2)) | 235 | if (MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2)) |
236 | return false; | 236 | return false; |
237 | } | 237 | } |
@@ -241,7 +241,7 @@ bool StringsAreEqual_Ascii(const char *u, const char *a) throw() | |||
241 | { | 241 | { |
242 | for (;;) | 242 | for (;;) |
243 | { | 243 | { |
244 | char c = *a; | 244 | const char c = *a; |
245 | if (c != *u) | 245 | if (c != *u) |
246 | return false; | 246 | return false; |
247 | if (c == 0) | 247 | if (c == 0) |
@@ -255,7 +255,7 @@ bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw() | |||
255 | { | 255 | { |
256 | for (;;) | 256 | for (;;) |
257 | { | 257 | { |
258 | unsigned char c = (unsigned char)*a; | 258 | const unsigned char c = (unsigned char)*a; |
259 | if (c != *u) | 259 | if (c != *u) |
260 | return false; | 260 | return false; |
261 | if (c == 0) | 261 | if (c == 0) |
@@ -269,8 +269,8 @@ bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw() | |||
269 | { | 269 | { |
270 | for (;;) | 270 | for (;;) |
271 | { | 271 | { |
272 | char c1 = *s1++; | 272 | const char c1 = *s1++; |
273 | char c2 = *s2++; | 273 | const char c2 = *s2++; |
274 | if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2)) | 274 | if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2)) |
275 | return false; | 275 | return false; |
276 | if (c1 == 0) | 276 | if (c1 == 0) |
@@ -282,8 +282,8 @@ bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw() | |||
282 | { | 282 | { |
283 | for (;;) | 283 | for (;;) |
284 | { | 284 | { |
285 | wchar_t c1 = *s1++; | 285 | const wchar_t c1 = *s1++; |
286 | wchar_t c2 = *s2++; | 286 | const wchar_t c2 = *s2++; |
287 | if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2)) | 287 | if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2)) |
288 | return false; | 288 | return false; |
289 | if (c1 == 0) | 289 | if (c1 == 0) |
@@ -295,8 +295,8 @@ bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw() | |||
295 | { | 295 | { |
296 | for (;;) | 296 | for (;;) |
297 | { | 297 | { |
298 | wchar_t c1 = *s1++; | 298 | const wchar_t c1 = *s1++; |
299 | char c2 = *s2++; | 299 | const char c2 = *s2++; |
300 | if (c1 != (unsigned char)c2 && (c1 > 0x7F || MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2))) | 300 | if (c1 != (unsigned char)c2 && (c1 > 0x7F || MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2))) |
301 | return false; | 301 | return false; |
302 | if (c1 == 0) | 302 | if (c1 == 0) |
@@ -308,8 +308,8 @@ bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw() | |||
308 | { | 308 | { |
309 | for (;;) | 309 | for (;;) |
310 | { | 310 | { |
311 | wchar_t c2 = *s2++; if (c2 == 0) return true; | 311 | const wchar_t c2 = *s2++; if (c2 == 0) return true; |
312 | wchar_t c1 = *s1++; if (c1 != c2) return false; | 312 | const wchar_t c1 = *s1++; if (c1 != c2) return false; |
313 | } | 313 | } |
314 | } | 314 | } |
315 | 315 | ||
@@ -317,8 +317,8 @@ bool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw() | |||
317 | { | 317 | { |
318 | for (;;) | 318 | for (;;) |
319 | { | 319 | { |
320 | unsigned char c2 = (unsigned char)(*s2++); if (c2 == 0) return true; | 320 | const unsigned char c2 = (unsigned char)(*s2++); if (c2 == 0) return true; |
321 | wchar_t c1 = *s1++; if (c1 != c2) return false; | 321 | const wchar_t c1 = *s1++; if (c1 != c2) return false; |
322 | } | 322 | } |
323 | } | 323 | } |
324 | 324 | ||
@@ -326,8 +326,8 @@ bool IsString1PrefixedByString2_NoCase_Ascii(const char *s1, const char *s2) thr | |||
326 | { | 326 | { |
327 | for (;;) | 327 | for (;;) |
328 | { | 328 | { |
329 | char c2 = *s2++; if (c2 == 0) return true; | 329 | const char c2 = *s2++; if (c2 == 0) return true; |
330 | char c1 = *s1++; | 330 | const char c1 = *s1++; |
331 | if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2)) | 331 | if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2)) |
332 | return false; | 332 | return false; |
333 | } | 333 | } |
@@ -337,8 +337,8 @@ bool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *s1, const char *s2) | |||
337 | { | 337 | { |
338 | for (;;) | 338 | for (;;) |
339 | { | 339 | { |
340 | char c2 = *s2++; if (c2 == 0) return true; | 340 | const char c2 = *s2++; if (c2 == 0) return true; |
341 | wchar_t c1 = *s1++; | 341 | const wchar_t c1 = *s1++; |
342 | if (c1 != (unsigned char)c2 && MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2)) | 342 | if (c1 != (unsigned char)c2 && MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2)) |
343 | return false; | 343 | return false; |
344 | } | 344 | } |
@@ -348,8 +348,8 @@ bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) thr | |||
348 | { | 348 | { |
349 | for (;;) | 349 | for (;;) |
350 | { | 350 | { |
351 | wchar_t c2 = *s2++; if (c2 == 0) return true; | 351 | const wchar_t c2 = *s2++; if (c2 == 0) return true; |
352 | wchar_t c1 = *s1++; | 352 | const wchar_t c1 = *s1++; |
353 | if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2)) | 353 | if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2)) |
354 | return false; | 354 | return false; |
355 | } | 355 | } |
@@ -360,12 +360,12 @@ int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw() | |||
360 | { | 360 | { |
361 | for (;;) | 361 | for (;;) |
362 | { | 362 | { |
363 | wchar_t c1 = *s1++; | 363 | const wchar_t c1 = *s1++; |
364 | wchar_t c2 = *s2++; | 364 | const wchar_t c2 = *s2++; |
365 | if (c1 != c2) | 365 | if (c1 != c2) |
366 | { | 366 | { |
367 | wchar_t u1 = MyCharUpper(c1); | 367 | const wchar_t u1 = MyCharUpper(c1); |
368 | wchar_t u2 = MyCharUpper(c2); | 368 | const wchar_t u2 = MyCharUpper(c2); |
369 | if (u1 < u2) return -1; | 369 | if (u1 < u2) return -1; |
370 | if (u1 > u2) return 1; | 370 | if (u1 > u2) return 1; |
371 | } | 371 | } |
@@ -401,14 +401,13 @@ void AString::InsertSpace(unsigned &index, unsigned size) | |||
401 | MoveItems(index + size, index); | 401 | MoveItems(index + size, index); |
402 | } | 402 | } |
403 | 403 | ||
404 | #define k_Alloc_Len_Limit 0x40000000 | 404 | #define k_Alloc_Len_Limit (0x40000000 - 2) |
405 | 405 | ||
406 | void AString::ReAlloc(unsigned newLimit) | 406 | void AString::ReAlloc(unsigned newLimit) |
407 | { | 407 | { |
408 | if (newLimit < _len || newLimit >= k_Alloc_Len_Limit) throw 20130220; | 408 | // MY_STRING_REALLOC(_chars, char, (size_t)newLimit + 1, (size_t)_len + 1); |
409 | // MY_STRING_REALLOC(_chars, char, newLimit + 1, _len + 1); | 409 | char *newBuf = MY_STRING_NEW_char((size_t)newLimit + 1); |
410 | char *newBuf = MY_STRING_NEW_char(newLimit + 1); | 410 | memcpy(newBuf, _chars, (size_t)_len + 1); |
411 | memcpy(newBuf, _chars, (size_t)(_len + 1)); | ||
412 | MY_STRING_DELETE(_chars); | 411 | MY_STRING_DELETE(_chars); |
413 | _chars = newBuf; | 412 | _chars = newBuf; |
414 | _limit = newLimit; | 413 | _limit = newLimit; |
@@ -416,9 +415,9 @@ void AString::ReAlloc(unsigned newLimit) | |||
416 | 415 | ||
417 | void AString::ReAlloc2(unsigned newLimit) | 416 | void AString::ReAlloc2(unsigned newLimit) |
418 | { | 417 | { |
419 | if (newLimit >= k_Alloc_Len_Limit) throw 20130220; | 418 | if (newLimit > k_Alloc_Len_Limit) throw 20130220; |
420 | // MY_STRING_REALLOC(_chars, char, newLimit + 1, 0); | 419 | // MY_STRING_REALLOC(_chars, char, (size_t)newLimit + 1, 0); |
421 | char *newBuf = MY_STRING_NEW_char(newLimit + 1); | 420 | char *newBuf = MY_STRING_NEW_char((size_t)newLimit + 1); |
422 | newBuf[0] = 0; | 421 | newBuf[0] = 0; |
423 | MY_STRING_DELETE(_chars); | 422 | MY_STRING_DELETE(_chars); |
424 | _chars = newBuf; | 423 | _chars = newBuf; |
@@ -427,8 +426,8 @@ void AString::ReAlloc2(unsigned newLimit) | |||
427 | 426 | ||
428 | void AString::SetStartLen(unsigned len) | 427 | void AString::SetStartLen(unsigned len) |
429 | { | 428 | { |
430 | _chars = 0; | 429 | _chars = NULL; |
431 | _chars = MY_STRING_NEW_char(len + 1); | 430 | _chars = MY_STRING_NEW_char((size_t)len + 1); |
432 | _len = len; | 431 | _len = len; |
433 | _limit = len; | 432 | _limit = len; |
434 | } | 433 | } |
@@ -439,20 +438,30 @@ void AString::Grow_1() | |||
439 | next += next / 2; | 438 | next += next / 2; |
440 | next += 16; | 439 | next += 16; |
441 | next &= ~(unsigned)15; | 440 | next &= ~(unsigned)15; |
442 | ReAlloc(next - 1); | 441 | next--; |
442 | if (next < _len || next > k_Alloc_Len_Limit) | ||
443 | next = k_Alloc_Len_Limit; | ||
444 | if (next <= _len) | ||
445 | throw 20130220; | ||
446 | ReAlloc(next); | ||
447 | // Grow(1); | ||
443 | } | 448 | } |
444 | 449 | ||
445 | void AString::Grow(unsigned n) | 450 | void AString::Grow(unsigned n) |
446 | { | 451 | { |
447 | unsigned freeSize = _limit - _len; | 452 | const unsigned freeSize = _limit - _len; |
448 | if (n <= freeSize) | 453 | if (n <= freeSize) |
449 | return; | 454 | return; |
450 | |||
451 | unsigned next = _len + n; | 455 | unsigned next = _len + n; |
452 | next += next / 2; | 456 | next += next / 2; |
453 | next += 16; | 457 | next += 16; |
454 | next &= ~(unsigned)15; | 458 | next &= ~(unsigned)15; |
455 | ReAlloc(next - 1); | 459 | next--; |
460 | if (next < _len || next > k_Alloc_Len_Limit) | ||
461 | next = k_Alloc_Len_Limit; | ||
462 | if (next <= _len || next - _len < n) | ||
463 | throw 20130220; | ||
464 | ReAlloc(next); | ||
456 | } | 465 | } |
457 | 466 | ||
458 | AString::AString(unsigned num, const char *s) | 467 | AString::AString(unsigned num, const char *s) |
@@ -500,7 +509,7 @@ static const unsigned kStartStringCapacity = 4; | |||
500 | 509 | ||
501 | AString::AString() | 510 | AString::AString() |
502 | { | 511 | { |
503 | _chars = 0; | 512 | _chars = NULL; |
504 | _chars = MY_STRING_NEW_char(kStartStringCapacity); | 513 | _chars = MY_STRING_NEW_char(kStartStringCapacity); |
505 | _len = 0; | 514 | _len = 0; |
506 | _limit = kStartStringCapacity - 1; | 515 | _limit = kStartStringCapacity - 1; |
@@ -548,7 +557,7 @@ AString &AString::operator=(const char *s) | |||
548 | unsigned len = MyStringLen(s); | 557 | unsigned len = MyStringLen(s); |
549 | if (len > _limit) | 558 | if (len > _limit) |
550 | { | 559 | { |
551 | char *newBuf = MY_STRING_NEW_char(len + 1); | 560 | char *newBuf = MY_STRING_NEW_char((size_t)len + 1); |
552 | MY_STRING_DELETE(_chars); | 561 | MY_STRING_DELETE(_chars); |
553 | _chars = newBuf; | 562 | _chars = newBuf; |
554 | _limit = len; | 563 | _limit = len; |
@@ -565,7 +574,7 @@ AString &AString::operator=(const AString &s) | |||
565 | unsigned len = s._len; | 574 | unsigned len = s._len; |
566 | if (len > _limit) | 575 | if (len > _limit) |
567 | { | 576 | { |
568 | char *newBuf = MY_STRING_NEW_char(len + 1); | 577 | char *newBuf = MY_STRING_NEW_char((size_t)len + 1); |
569 | MY_STRING_DELETE(_chars); | 578 | MY_STRING_DELETE(_chars); |
570 | _chars = newBuf; | 579 | _chars = newBuf; |
571 | _limit = len; | 580 | _limit = len; |
@@ -590,7 +599,7 @@ void AString::SetFromWStr_if_Ascii(const wchar_t *s) | |||
590 | } | 599 | } |
591 | if (len > _limit) | 600 | if (len > _limit) |
592 | { | 601 | { |
593 | char *newBuf = MY_STRING_NEW_char(len + 1); | 602 | char *newBuf = MY_STRING_NEW_char((size_t)len + 1); |
594 | MY_STRING_DELETE(_chars); | 603 | MY_STRING_DELETE(_chars); |
595 | _chars = newBuf; | 604 | _chars = newBuf; |
596 | _limit = len; | 605 | _limit = len; |
@@ -614,7 +623,7 @@ void AString::SetFromBstr_if_Ascii(BSTR s) | |||
614 | } | 623 | } |
615 | if (len > _limit) | 624 | if (len > _limit) |
616 | { | 625 | { |
617 | char *newBuf = MY_STRING_NEW_char(len + 1); | 626 | char *newBuf = MY_STRING_NEW_char((size_t)len + 1); |
618 | MY_STRING_DELETE(_chars); | 627 | MY_STRING_DELETE(_chars); |
619 | _chars = newBuf; | 628 | _chars = newBuf; |
620 | _limit = len; | 629 | _limit = len; |
@@ -631,6 +640,7 @@ void AString::SetFromBstr_if_Ascii(BSTR s) | |||
631 | void AString::Add_Space() { operator+=(' '); } | 640 | void AString::Add_Space() { operator+=(' '); } |
632 | void AString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); } | 641 | void AString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); } |
633 | void AString::Add_LF() { operator+=('\n'); } | 642 | void AString::Add_LF() { operator+=('\n'); } |
643 | void AString::Add_Slash() { operator+=('/'); } | ||
634 | 644 | ||
635 | AString &AString::operator+=(const char *s) | 645 | AString &AString::operator+=(const char *s) |
636 | { | 646 | { |
@@ -667,11 +677,23 @@ void UString::Add_UInt64(UInt64 v) | |||
667 | _len = (unsigned)(ConvertUInt64ToString(v, _chars + _len) - _chars); | 677 | _len = (unsigned)(ConvertUInt64ToString(v, _chars + _len) - _chars); |
668 | } | 678 | } |
669 | 679 | ||
680 | void AString::AddFrom(const char *s, unsigned len) // no check | ||
681 | { | ||
682 | if (len != 0) | ||
683 | { | ||
684 | Grow(len); | ||
685 | memcpy(_chars + _len, s, len); | ||
686 | len += _len; | ||
687 | _chars[len] = 0; | ||
688 | _len = len; | ||
689 | } | ||
690 | } | ||
691 | |||
670 | void AString::SetFrom(const char *s, unsigned len) // no check | 692 | void AString::SetFrom(const char *s, unsigned len) // no check |
671 | { | 693 | { |
672 | if (len > _limit) | 694 | if (len > _limit) |
673 | { | 695 | { |
674 | char *newBuf = MY_STRING_NEW_char(len + 1); | 696 | char *newBuf = MY_STRING_NEW_char((size_t)len + 1); |
675 | MY_STRING_DELETE(_chars); | 697 | MY_STRING_DELETE(_chars); |
676 | _chars = newBuf; | 698 | _chars = newBuf; |
677 | _limit = len; | 699 | _limit = len; |
@@ -976,9 +998,8 @@ void UString::InsertSpace(unsigned index, unsigned size) | |||
976 | 998 | ||
977 | void UString::ReAlloc(unsigned newLimit) | 999 | void UString::ReAlloc(unsigned newLimit) |
978 | { | 1000 | { |
979 | if (newLimit < _len || newLimit >= k_Alloc_Len_Limit) throw 20130221; | 1001 | // MY_STRING_REALLOC(_chars, wchar_t, (size_t)newLimit + 1, (size_t)_len + 1); |
980 | // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, _len + 1); | 1002 | wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)newLimit + 1); |
981 | wchar_t *newBuf = MY_STRING_NEW_wchar_t(newLimit + 1); | ||
982 | wmemcpy(newBuf, _chars, _len + 1); | 1003 | wmemcpy(newBuf, _chars, _len + 1); |
983 | MY_STRING_DELETE(_chars); | 1004 | MY_STRING_DELETE(_chars); |
984 | _chars = newBuf; | 1005 | _chars = newBuf; |
@@ -987,9 +1008,9 @@ void UString::ReAlloc(unsigned newLimit) | |||
987 | 1008 | ||
988 | void UString::ReAlloc2(unsigned newLimit) | 1009 | void UString::ReAlloc2(unsigned newLimit) |
989 | { | 1010 | { |
990 | if (newLimit >= k_Alloc_Len_Limit) throw 20130221; | 1011 | if (newLimit > k_Alloc_Len_Limit) throw 20130221; |
991 | // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0); | 1012 | // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0); |
992 | wchar_t *newBuf = MY_STRING_NEW_wchar_t(newLimit + 1); | 1013 | wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)newLimit + 1); |
993 | newBuf[0] = 0; | 1014 | newBuf[0] = 0; |
994 | MY_STRING_DELETE(_chars); | 1015 | MY_STRING_DELETE(_chars); |
995 | _chars = newBuf; | 1016 | _chars = newBuf; |
@@ -999,7 +1020,7 @@ void UString::ReAlloc2(unsigned newLimit) | |||
999 | void UString::SetStartLen(unsigned len) | 1020 | void UString::SetStartLen(unsigned len) |
1000 | { | 1021 | { |
1001 | _chars = 0; | 1022 | _chars = 0; |
1002 | _chars = MY_STRING_NEW_wchar_t(len + 1); | 1023 | _chars = MY_STRING_NEW_wchar_t((size_t)len + 1); |
1003 | _len = len; | 1024 | _len = len; |
1004 | _limit = len; | 1025 | _limit = len; |
1005 | } | 1026 | } |
@@ -1010,19 +1031,28 @@ void UString::Grow_1() | |||
1010 | next += next / 2; | 1031 | next += next / 2; |
1011 | next += 16; | 1032 | next += 16; |
1012 | next &= ~(unsigned)15; | 1033 | next &= ~(unsigned)15; |
1013 | ReAlloc(next - 1); | 1034 | next--; |
1035 | if (next < _len || next > k_Alloc_Len_Limit) | ||
1036 | next = k_Alloc_Len_Limit; | ||
1037 | if (next <= _len) | ||
1038 | throw 20130220; | ||
1039 | ReAlloc(next); | ||
1014 | } | 1040 | } |
1015 | 1041 | ||
1016 | void UString::Grow(unsigned n) | 1042 | void UString::Grow(unsigned n) |
1017 | { | 1043 | { |
1018 | unsigned freeSize = _limit - _len; | 1044 | const unsigned freeSize = _limit - _len; |
1019 | if (n <= freeSize) | 1045 | if (n <= freeSize) |
1020 | return; | 1046 | return; |
1021 | |||
1022 | unsigned next = _len + n; | 1047 | unsigned next = _len + n; |
1023 | next += next / 2; | 1048 | next += next / 2; |
1024 | next += 16; | 1049 | next += 16; |
1025 | next &= ~(unsigned)15; | 1050 | next &= ~(unsigned)15; |
1051 | next--; | ||
1052 | if (next < _len || next > k_Alloc_Len_Limit) | ||
1053 | next = k_Alloc_Len_Limit; | ||
1054 | if (next <= _len || next - _len < n) | ||
1055 | throw 20130220; | ||
1026 | ReAlloc(next - 1); | 1056 | ReAlloc(next - 1); |
1027 | } | 1057 | } |
1028 | 1058 | ||
@@ -1149,7 +1179,7 @@ UString &UString::operator=(const wchar_t *s) | |||
1149 | unsigned len = MyStringLen(s); | 1179 | unsigned len = MyStringLen(s); |
1150 | if (len > _limit) | 1180 | if (len > _limit) |
1151 | { | 1181 | { |
1152 | wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); | 1182 | wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1); |
1153 | MY_STRING_DELETE(_chars); | 1183 | MY_STRING_DELETE(_chars); |
1154 | _chars = newBuf; | 1184 | _chars = newBuf; |
1155 | _limit = len; | 1185 | _limit = len; |
@@ -1166,7 +1196,7 @@ UString &UString::operator=(const UString &s) | |||
1166 | unsigned len = s._len; | 1196 | unsigned len = s._len; |
1167 | if (len > _limit) | 1197 | if (len > _limit) |
1168 | { | 1198 | { |
1169 | wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); | 1199 | wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1); |
1170 | MY_STRING_DELETE(_chars); | 1200 | MY_STRING_DELETE(_chars); |
1171 | _chars = newBuf; | 1201 | _chars = newBuf; |
1172 | _limit = len; | 1202 | _limit = len; |
@@ -1180,7 +1210,7 @@ void UString::SetFrom(const wchar_t *s, unsigned len) // no check | |||
1180 | { | 1210 | { |
1181 | if (len > _limit) | 1211 | if (len > _limit) |
1182 | { | 1212 | { |
1183 | wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); | 1213 | wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1); |
1184 | MY_STRING_DELETE(_chars); | 1214 | MY_STRING_DELETE(_chars); |
1185 | _chars = newBuf; | 1215 | _chars = newBuf; |
1186 | _limit = len; | 1216 | _limit = len; |
@@ -1218,7 +1248,7 @@ void UString::SetFromBstr(LPCOLESTR s) | |||
1218 | 1248 | ||
1219 | if (len > _limit) | 1249 | if (len > _limit) |
1220 | { | 1250 | { |
1221 | wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); | 1251 | wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1); |
1222 | MY_STRING_DELETE(_chars); | 1252 | MY_STRING_DELETE(_chars); |
1223 | _chars = newBuf; | 1253 | _chars = newBuf; |
1224 | _limit = len; | 1254 | _limit = len; |
@@ -1258,7 +1288,7 @@ UString &UString::operator=(const char *s) | |||
1258 | unsigned len = MyStringLen(s); | 1288 | unsigned len = MyStringLen(s); |
1259 | if (len > _limit) | 1289 | if (len > _limit) |
1260 | { | 1290 | { |
1261 | wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); | 1291 | wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1); |
1262 | MY_STRING_DELETE(_chars); | 1292 | MY_STRING_DELETE(_chars); |
1263 | _chars = newBuf; | 1293 | _chars = newBuf; |
1264 | _limit = len; | 1294 | _limit = len; |
@@ -1566,15 +1596,24 @@ void UString::DeleteFrontal(unsigned num) throw() | |||
1566 | 1596 | ||
1567 | void UString2::ReAlloc2(unsigned newLimit) | 1597 | void UString2::ReAlloc2(unsigned newLimit) |
1568 | { | 1598 | { |
1569 | if (newLimit >= k_Alloc_Len_Limit) throw 20130221; | 1599 | // wrong (_len) is allowed after this function |
1600 | if (newLimit > k_Alloc_Len_Limit) throw 20130221; | ||
1570 | // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0); | 1601 | // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0); |
1571 | _chars = MY_STRING_NEW_wchar_t(newLimit + 1); | 1602 | if (_chars) |
1603 | { | ||
1604 | MY_STRING_DELETE(_chars); | ||
1605 | _chars = NULL; | ||
1606 | // _len = 0; | ||
1607 | } | ||
1608 | _chars = MY_STRING_NEW_wchar_t((size_t)newLimit + 1); | ||
1609 | _chars[0] = 0; | ||
1610 | // _len = newLimit; | ||
1572 | } | 1611 | } |
1573 | 1612 | ||
1574 | void UString2::SetStartLen(unsigned len) | 1613 | void UString2::SetStartLen(unsigned len) |
1575 | { | 1614 | { |
1576 | _chars = 0; | 1615 | _chars = NULL; |
1577 | _chars = MY_STRING_NEW_wchar_t(len + 1); | 1616 | _chars = MY_STRING_NEW_wchar_t((size_t)len + 1); |
1578 | _len = len; | 1617 | _len = len; |
1579 | } | 1618 | } |
1580 | 1619 | ||
@@ -1591,7 +1630,7 @@ UString2::UString2(wchar_t c) | |||
1591 | 1630 | ||
1592 | UString2::UString2(const wchar_t *s) | 1631 | UString2::UString2(const wchar_t *s) |
1593 | { | 1632 | { |
1594 | unsigned len = MyStringLen(s); | 1633 | const unsigned len = MyStringLen(s); |
1595 | SetStartLen(len); | 1634 | SetStartLen(len); |
1596 | wmemcpy(_chars, s, len + 1); | 1635 | wmemcpy(_chars, s, len + 1); |
1597 | } | 1636 | } |
@@ -1628,7 +1667,7 @@ UString2 &UString2::operator=(const wchar_t *s) | |||
1628 | unsigned len = MyStringLen(s); | 1667 | unsigned len = MyStringLen(s); |
1629 | if (len > _len) | 1668 | if (len > _len) |
1630 | { | 1669 | { |
1631 | wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); | 1670 | wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1); |
1632 | if (_chars) | 1671 | if (_chars) |
1633 | MY_STRING_DELETE(_chars); | 1672 | MY_STRING_DELETE(_chars); |
1634 | _chars = newBuf; | 1673 | _chars = newBuf; |
@@ -1643,7 +1682,7 @@ void UString2::SetFromAscii(const char *s) | |||
1643 | unsigned len = MyStringLen(s); | 1682 | unsigned len = MyStringLen(s); |
1644 | if (len > _len) | 1683 | if (len > _len) |
1645 | { | 1684 | { |
1646 | wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); | 1685 | wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1); |
1647 | if (_chars) | 1686 | if (_chars) |
1648 | MY_STRING_DELETE(_chars); | 1687 | MY_STRING_DELETE(_chars); |
1649 | _chars = newBuf; | 1688 | _chars = newBuf; |
@@ -1662,7 +1701,7 @@ UString2 &UString2::operator=(const UString2 &s) | |||
1662 | unsigned len = s._len; | 1701 | unsigned len = s._len; |
1663 | if (len > _len) | 1702 | if (len > _len) |
1664 | { | 1703 | { |
1665 | wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); | 1704 | wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1); |
1666 | if (_chars) | 1705 | if (_chars) |
1667 | MY_STRING_DELETE(_chars); | 1706 | MY_STRING_DELETE(_chars); |
1668 | _chars = newBuf; | 1707 | _chars = newBuf; |
diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h index aa3c301..c777c8c 100644 --- a/CPP/Common/MyString.h +++ b/CPP/Common/MyString.h | |||
@@ -378,6 +378,7 @@ public: | |||
378 | void Add_Space_if_NotEmpty(); | 378 | void Add_Space_if_NotEmpty(); |
379 | void Add_OptSpaced(const char *s); | 379 | void Add_OptSpaced(const char *s); |
380 | void Add_LF(); | 380 | void Add_LF(); |
381 | void Add_Slash(); | ||
381 | void Add_PathSepar() { operator+=(CHAR_PATH_SEPARATOR); } | 382 | void Add_PathSepar() { operator+=(CHAR_PATH_SEPARATOR); } |
382 | 383 | ||
383 | AString &operator+=(const char *s); | 384 | AString &operator+=(const char *s); |
@@ -386,12 +387,12 @@ public: | |||
386 | void Add_UInt32(UInt32 v); | 387 | void Add_UInt32(UInt32 v); |
387 | void Add_UInt64(UInt64 v); | 388 | void Add_UInt64(UInt64 v); |
388 | 389 | ||
390 | void AddFrom(const char *s, unsigned len); // no check | ||
389 | void SetFrom(const char *s, unsigned len); // no check | 391 | void SetFrom(const char *s, unsigned len); // no check |
390 | void SetFrom_CalcLen(const char *s, unsigned len); | 392 | void SetFrom_CalcLen(const char *s, unsigned len); |
391 | 393 | ||
392 | AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); } | 394 | AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); } |
393 | AString Left(unsigned count) const { return AString(count, *this); } | 395 | AString Left(unsigned count) const { return AString(count, *this); } |
394 | |||
395 | // void MakeUpper() { MyStringUpper(_chars); } | 396 | // void MakeUpper() { MyStringUpper(_chars); } |
396 | // void MakeLower() { MyStringLower(_chars); } | 397 | // void MakeLower() { MyStringLower(_chars); } |
397 | void MakeLower_Ascii() { MyStringLower_Ascii(_chars); } | 398 | void MakeLower_Ascii() { MyStringLower_Ascii(_chars); } |
diff --git a/CPP/Common/MyVector.h b/CPP/Common/MyVector.h index c851234..3417a17 100644 --- a/CPP/Common/MyVector.h +++ b/CPP/Common/MyVector.h | |||
@@ -5,6 +5,8 @@ | |||
5 | 5 | ||
6 | #include <string.h> | 6 | #include <string.h> |
7 | 7 | ||
8 | const unsigned k_VectorSizeMax = ((unsigned)1 << 31) - 1; | ||
9 | |||
8 | template <class T> | 10 | template <class T> |
9 | class CRecordVector | 11 | class CRecordVector |
10 | { | 12 | { |
@@ -17,31 +19,41 @@ class CRecordVector | |||
17 | memmove(_items + destIndex, _items + srcIndex, (size_t)(_size - srcIndex) * sizeof(T)); | 19 | memmove(_items + destIndex, _items + srcIndex, (size_t)(_size - srcIndex) * sizeof(T)); |
18 | } | 20 | } |
19 | 21 | ||
20 | void ReserveOnePosition() | 22 | void ReAllocForNewCapacity(const unsigned newCapacity) |
21 | { | 23 | { |
22 | if (_size == _capacity) | 24 | T *p; |
23 | { | 25 | MY_ARRAY_NEW(p, T, newCapacity); |
24 | unsigned newCapacity = _capacity + (_capacity >> 2) + 1; | 26 | // p = new T[newCapacity]; |
25 | T *p; | 27 | if (_size != 0) |
26 | MY_ARRAY_NEW(p, T, newCapacity); | 28 | memcpy(p, _items, (size_t)_size * sizeof(T)); |
27 | // p = new T[newCapacity]; | 29 | delete []_items; |
28 | if (_size != 0) | 30 | _items = p; |
29 | memcpy(p, _items, (size_t)_size * sizeof(T)); | 31 | _capacity = newCapacity; |
30 | delete []_items; | ||
31 | _items = p; | ||
32 | _capacity = newCapacity; | ||
33 | } | ||
34 | } | 32 | } |
35 | 33 | ||
36 | public: | 34 | public: |
37 | 35 | ||
36 | void ReserveOnePosition() | ||
37 | { | ||
38 | if (_size != _capacity) | ||
39 | return; | ||
40 | if (_capacity >= k_VectorSizeMax) | ||
41 | throw 2021; | ||
42 | const unsigned rem = k_VectorSizeMax - _capacity; | ||
43 | unsigned add = (_capacity >> 2) + 1; | ||
44 | if (add > rem) | ||
45 | add = rem; | ||
46 | ReAllocForNewCapacity(_capacity + add); | ||
47 | } | ||
48 | |||
38 | CRecordVector(): _items(NULL), _size(0), _capacity(0) {} | 49 | CRecordVector(): _items(NULL), _size(0), _capacity(0) {} |
39 | 50 | ||
40 | CRecordVector(const CRecordVector &v): _items(0), _size(0), _capacity(0) | 51 | CRecordVector(const CRecordVector &v): _items(NULL), _size(0), _capacity(0) |
41 | { | 52 | { |
42 | unsigned size = v.Size(); | 53 | const unsigned size = v.Size(); |
43 | if (size != 0) | 54 | if (size != 0) |
44 | { | 55 | { |
56 | // MY_ARRAY_NEW(_items, T, size) | ||
45 | _items = new T[size]; | 57 | _items = new T[size]; |
46 | _size = size; | 58 | _size = size; |
47 | _capacity = size; | 59 | _capacity = size; |
@@ -66,22 +78,25 @@ public: | |||
66 | { | 78 | { |
67 | if (newCapacity > _capacity) | 79 | if (newCapacity > _capacity) |
68 | { | 80 | { |
69 | T *p; | 81 | if (newCapacity > k_VectorSizeMax) |
70 | MY_ARRAY_NEW(p, T, newCapacity); | 82 | throw 2021; |
71 | // p = new T[newCapacity]; | 83 | ReAllocForNewCapacity(newCapacity); |
72 | if (_size != 0) | ||
73 | memcpy(p, _items, (size_t)_size * sizeof(T)); | ||
74 | delete []_items; | ||
75 | _items = p; | ||
76 | _capacity = newCapacity; | ||
77 | } | 84 | } |
78 | } | 85 | } |
79 | 86 | ||
87 | void ChangeSize_KeepData(unsigned newSize) | ||
88 | { | ||
89 | Reserve(newSize); | ||
90 | _size = newSize; | ||
91 | } | ||
92 | |||
80 | void ClearAndReserve(unsigned newCapacity) | 93 | void ClearAndReserve(unsigned newCapacity) |
81 | { | 94 | { |
82 | Clear(); | 95 | Clear(); |
83 | if (newCapacity > _capacity) | 96 | if (newCapacity > _capacity) |
84 | { | 97 | { |
98 | if (newCapacity > k_VectorSizeMax) | ||
99 | throw 2021; | ||
85 | delete []_items; | 100 | delete []_items; |
86 | _items = NULL; | 101 | _items = NULL; |
87 | _capacity = 0; | 102 | _capacity = 0; |
@@ -97,22 +112,6 @@ public: | |||
97 | _size = newSize; | 112 | _size = newSize; |
98 | } | 113 | } |
99 | 114 | ||
100 | void ChangeSize_KeepData(unsigned newSize) | ||
101 | { | ||
102 | if (newSize > _capacity) | ||
103 | { | ||
104 | T *p; | ||
105 | MY_ARRAY_NEW(p, T, newSize) | ||
106 | // p = new T[newSize]; | ||
107 | if (_size != 0) | ||
108 | memcpy(p, _items, (size_t)_size * sizeof(T)); | ||
109 | delete []_items; | ||
110 | _items = p; | ||
111 | _capacity = newSize; | ||
112 | } | ||
113 | _size = newSize; | ||
114 | } | ||
115 | |||
116 | void ReserveDown() | 115 | void ReserveDown() |
117 | { | 116 | { |
118 | if (_size == _capacity) | 117 | if (_size == _capacity) |
@@ -120,6 +119,7 @@ public: | |||
120 | T *p = NULL; | 119 | T *p = NULL; |
121 | if (_size != 0) | 120 | if (_size != 0) |
122 | { | 121 | { |
122 | // MY_ARRAY_NEW(p, T, _size) | ||
123 | p = new T[_size]; | 123 | p = new T[_size]; |
124 | memcpy(p, _items, (size_t)_size * sizeof(T)); | 124 | memcpy(p, _items, (size_t)_size * sizeof(T)); |
125 | } | 125 | } |
@@ -178,7 +178,7 @@ public: | |||
178 | { | 178 | { |
179 | if (&v == this) | 179 | if (&v == this) |
180 | return *this; | 180 | return *this; |
181 | unsigned size = v.Size(); | 181 | const unsigned size = v.Size(); |
182 | if (size > _capacity) | 182 | if (size > _capacity) |
183 | { | 183 | { |
184 | delete []_items; | 184 | delete []_items; |
@@ -196,24 +196,45 @@ public: | |||
196 | 196 | ||
197 | CRecordVector& operator+=(const CRecordVector &v) | 197 | CRecordVector& operator+=(const CRecordVector &v) |
198 | { | 198 | { |
199 | unsigned size = v.Size(); | 199 | const unsigned size = v.Size(); |
200 | Reserve(_size + size); | ||
201 | if (size != 0) | 200 | if (size != 0) |
201 | { | ||
202 | if (_size >= k_VectorSizeMax || size > k_VectorSizeMax - _size) | ||
203 | throw 2021; | ||
204 | const unsigned newSize = _size + size; | ||
205 | Reserve(newSize); | ||
202 | memcpy(_items + _size, v._items, (size_t)size * sizeof(T)); | 206 | memcpy(_items + _size, v._items, (size_t)size * sizeof(T)); |
203 | _size += size; | 207 | _size = newSize; |
208 | } | ||
204 | return *this; | 209 | return *this; |
205 | } | 210 | } |
206 | 211 | ||
207 | unsigned Add(const T item) | 212 | unsigned Add(const T item) |
208 | { | 213 | { |
209 | ReserveOnePosition(); | 214 | ReserveOnePosition(); |
210 | _items[_size] = item; | 215 | const unsigned size = _size; |
211 | return _size++; | 216 | _size = size + 1; |
217 | _items[size] = item; | ||
218 | return size; | ||
219 | } | ||
220 | |||
221 | /* | ||
222 | unsigned Add2(const T &item) | ||
223 | { | ||
224 | ReserveOnePosition(); | ||
225 | const unsigned size = _size; | ||
226 | _size = size + 1; | ||
227 | _items[size] = item; | ||
228 | return size; | ||
212 | } | 229 | } |
230 | */ | ||
213 | 231 | ||
214 | void AddInReserved(const T item) | 232 | unsigned AddInReserved(const T item) |
215 | { | 233 | { |
216 | _items[_size++] = item; | 234 | const unsigned size = _size; |
235 | _size = size + 1; | ||
236 | _items[size] = item; | ||
237 | return size; | ||
217 | } | 238 | } |
218 | 239 | ||
219 | void Insert(unsigned index, const T item) | 240 | void Insert(unsigned index, const T item) |
@@ -224,6 +245,13 @@ public: | |||
224 | _size++; | 245 | _size++; |
225 | } | 246 | } |
226 | 247 | ||
248 | void InsertInReserved(unsigned index, const T item) | ||
249 | { | ||
250 | MoveItems(index + 1, index); | ||
251 | _items[index] = item; | ||
252 | _size++; | ||
253 | } | ||
254 | |||
227 | void MoveToFront(unsigned index) | 255 | void MoveToFront(unsigned index) |
228 | { | 256 | { |
229 | if (index != 0) | 257 | if (index != 0) |
@@ -254,7 +282,8 @@ public: | |||
254 | { | 282 | { |
255 | while (left != right) | 283 | while (left != right) |
256 | { | 284 | { |
257 | unsigned mid = (left + right) / 2; | 285 | // const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); |
286 | const unsigned mid = (left + right) / 2; | ||
258 | const T midVal = (*this)[mid]; | 287 | const T midVal = (*this)[mid]; |
259 | if (item == midVal) | 288 | if (item == midVal) |
260 | return (int)mid; | 289 | return (int)mid; |
@@ -270,9 +299,10 @@ public: | |||
270 | { | 299 | { |
271 | while (left != right) | 300 | while (left != right) |
272 | { | 301 | { |
273 | unsigned mid = (left + right) / 2; | 302 | // const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); |
303 | const unsigned mid = (left + right) / 2; | ||
274 | const T& midVal = (*this)[mid]; | 304 | const T& midVal = (*this)[mid]; |
275 | int comp = item.Compare(midVal); | 305 | const int comp = item.Compare(midVal); |
276 | if (comp == 0) | 306 | if (comp == 0) |
277 | return (int)mid; | 307 | return (int)mid; |
278 | if (comp < 0) | 308 | if (comp < 0) |
@@ -298,7 +328,8 @@ public: | |||
298 | unsigned left = 0, right = _size; | 328 | unsigned left = 0, right = _size; |
299 | while (left != right) | 329 | while (left != right) |
300 | { | 330 | { |
301 | unsigned mid = (left + right) / 2; | 331 | // const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); |
332 | const unsigned mid = (left + right) / 2; | ||
302 | const T midVal = (*this)[mid]; | 333 | const T midVal = (*this)[mid]; |
303 | if (item == midVal) | 334 | if (item == midVal) |
304 | return mid; | 335 | return mid; |
@@ -316,9 +347,10 @@ public: | |||
316 | unsigned left = 0, right = _size; | 347 | unsigned left = 0, right = _size; |
317 | while (left != right) | 348 | while (left != right) |
318 | { | 349 | { |
319 | unsigned mid = (left + right) / 2; | 350 | // const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); |
351 | const unsigned mid = (left + right) / 2; | ||
320 | const T& midVal = (*this)[mid]; | 352 | const T& midVal = (*this)[mid]; |
321 | int comp = item.Compare(midVal); | 353 | const int comp = item.Compare(midVal); |
322 | if (comp == 0) | 354 | if (comp == 0) |
323 | return mid; | 355 | return mid; |
324 | if (comp < 0) | 356 | if (comp < 0) |
@@ -431,29 +463,35 @@ public: | |||
431 | CObjectVector() {} | 463 | CObjectVector() {} |
432 | CObjectVector(const CObjectVector &v) | 464 | CObjectVector(const CObjectVector &v) |
433 | { | 465 | { |
434 | unsigned size = v.Size(); | 466 | const unsigned size = v.Size(); |
435 | _v.ConstructReserve(size); | 467 | _v.ConstructReserve(size); |
436 | for (unsigned i = 0; i < size; i++) | 468 | for (unsigned i = 0; i < size; i++) |
437 | _v.AddInReserved(new T(v[i])); | 469 | AddInReserved(v[i]); |
438 | } | 470 | } |
439 | CObjectVector& operator=(const CObjectVector &v) | 471 | CObjectVector& operator=(const CObjectVector &v) |
440 | { | 472 | { |
441 | if (&v == this) | 473 | if (&v == this) |
442 | return *this; | 474 | return *this; |
443 | Clear(); | 475 | Clear(); |
444 | unsigned size = v.Size(); | 476 | const unsigned size = v.Size(); |
445 | _v.Reserve(size); | 477 | _v.Reserve(size); |
446 | for (unsigned i = 0; i < size; i++) | 478 | for (unsigned i = 0; i < size; i++) |
447 | _v.AddInReserved(new T(v[i])); | 479 | AddInReserved(v[i]); |
448 | return *this; | 480 | return *this; |
449 | } | 481 | } |
450 | 482 | ||
451 | CObjectVector& operator+=(const CObjectVector &v) | 483 | CObjectVector& operator+=(const CObjectVector &v) |
452 | { | 484 | { |
453 | unsigned size = v.Size(); | 485 | const unsigned addSize = v.Size(); |
454 | _v.Reserve(Size() + size); | 486 | if (addSize != 0) |
455 | for (unsigned i = 0; i < size; i++) | 487 | { |
456 | _v.AddInReserved(new T(v[i])); | 488 | const unsigned size = Size(); |
489 | if (size >= k_VectorSizeMax || addSize > k_VectorSizeMax - size) | ||
490 | throw 2021; | ||
491 | _v.Reserve(size + addSize); | ||
492 | for (unsigned i = 0; i < addSize; i++) | ||
493 | AddInReserved(v[i]); | ||
494 | } | ||
457 | return *this; | 495 | return *this; |
458 | } | 496 | } |
459 | 497 | ||
@@ -466,14 +504,37 @@ public: | |||
466 | 504 | ||
467 | void MoveToFront(unsigned index) { _v.MoveToFront(index); } | 505 | void MoveToFront(unsigned index) { _v.MoveToFront(index); } |
468 | 506 | ||
469 | unsigned Add(const T& item) { return _v.Add(new T(item)); } | 507 | unsigned Add(const T& item) |
508 | { | ||
509 | _v.ReserveOnePosition(); | ||
510 | return AddInReserved(item); | ||
511 | } | ||
512 | |||
513 | unsigned AddInReserved(const T& item) | ||
514 | { | ||
515 | return _v.AddInReserved(new T(item)); | ||
516 | } | ||
517 | |||
518 | void ReserveOnePosition() | ||
519 | { | ||
520 | _v.ReserveOnePosition(); | ||
521 | } | ||
522 | |||
523 | unsigned AddInReserved_Ptr_of_new(T *ptr) | ||
524 | { | ||
525 | return _v.AddInReserved(ptr); | ||
526 | } | ||
527 | |||
528 | #define VECTOR_ADD_NEW_OBJECT(v, a) \ | ||
529 | (v).ReserveOnePosition(); \ | ||
530 | (v).AddInReserved_Ptr_of_new(new a); | ||
470 | 531 | ||
471 | void AddInReserved(const T& item) { _v.AddInReserved(new T(item)); } | ||
472 | 532 | ||
473 | T& AddNew() | 533 | T& AddNew() |
474 | { | 534 | { |
535 | _v.ReserveOnePosition(); | ||
475 | T *p = new T; | 536 | T *p = new T; |
476 | _v.Add(p); | 537 | _v.AddInReserved(p); |
477 | return *p; | 538 | return *p; |
478 | } | 539 | } |
479 | 540 | ||
@@ -484,12 +545,17 @@ public: | |||
484 | return *p; | 545 | return *p; |
485 | } | 546 | } |
486 | 547 | ||
487 | void Insert(unsigned index, const T& item) { _v.Insert(index, new T(item)); } | 548 | void Insert(unsigned index, const T& item) |
549 | { | ||
550 | _v.ReserveOnePosition(); | ||
551 | _v.InsertInReserved(index, new T(item)); | ||
552 | } | ||
488 | 553 | ||
489 | T& InsertNew(unsigned index) | 554 | T& InsertNew(unsigned index) |
490 | { | 555 | { |
556 | _v.ReserveOnePosition(); | ||
491 | T *p = new T; | 557 | T *p = new T; |
492 | _v.Insert(index, p); | 558 | _v.InsertInReserved(index, p); |
493 | return *p; | 559 | return *p; |
494 | } | 560 | } |
495 | 561 | ||
@@ -514,7 +580,7 @@ public: | |||
514 | 580 | ||
515 | void DeleteFrom(unsigned index) | 581 | void DeleteFrom(unsigned index) |
516 | { | 582 | { |
517 | unsigned size = _v.Size(); | 583 | const unsigned size = _v.Size(); |
518 | for (unsigned i = index; i < size; i++) | 584 | for (unsigned i = index; i < size; i++) |
519 | delete (T *)_v[i]; | 585 | delete (T *)_v[i]; |
520 | _v.DeleteFrom(index); | 586 | _v.DeleteFrom(index); |
@@ -564,9 +630,10 @@ public: | |||
564 | unsigned left = 0, right = Size(); | 630 | unsigned left = 0, right = Size(); |
565 | while (left != right) | 631 | while (left != right) |
566 | { | 632 | { |
567 | unsigned mid = (left + right) / 2; | 633 | // const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); |
634 | const unsigned mid = (left + right) / 2; | ||
568 | const T& midVal = (*this)[mid]; | 635 | const T& midVal = (*this)[mid]; |
569 | int comp = item.Compare(midVal); | 636 | const int comp = item.Compare(midVal); |
570 | if (comp == 0) | 637 | if (comp == 0) |
571 | return (int)mid; | 638 | return (int)mid; |
572 | if (comp < 0) | 639 | if (comp < 0) |
@@ -582,9 +649,10 @@ public: | |||
582 | unsigned left = 0, right = Size(); | 649 | unsigned left = 0, right = Size(); |
583 | while (left != right) | 650 | while (left != right) |
584 | { | 651 | { |
585 | unsigned mid = (left + right) / 2; | 652 | // const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); |
653 | const unsigned mid = (left + right) / 2; | ||
586 | const T& midVal = (*this)[mid]; | 654 | const T& midVal = (*this)[mid]; |
587 | int comp = item.Compare(midVal); | 655 | const int comp = item.Compare(midVal); |
588 | if (comp == 0) | 656 | if (comp == 0) |
589 | return mid; | 657 | return mid; |
590 | if (comp < 0) | 658 | if (comp < 0) |
@@ -602,9 +670,10 @@ public: | |||
602 | unsigned left = 0, right = Size(); | 670 | unsigned left = 0, right = Size(); |
603 | while (left != right) | 671 | while (left != right) |
604 | { | 672 | { |
605 | unsigned mid = (left + right) / 2; | 673 | // const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); |
674 | const unsigned mid = (left + right) / 2; | ||
606 | const T& midVal = (*this)[mid]; | 675 | const T& midVal = (*this)[mid]; |
607 | int comp = item.Compare(midVal); | 676 | const int comp = item.Compare(midVal); |
608 | if (comp == 0) | 677 | if (comp == 0) |
609 | { | 678 | { |
610 | right = mid + 1; | 679 | right = mid + 1; |
diff --git a/CPP/Common/MyWindows.h b/CPP/Common/MyWindows.h index 0664a5e..15db524 100644 --- a/CPP/Common/MyWindows.h +++ b/CPP/Common/MyWindows.h | |||
@@ -76,7 +76,6 @@ typedef struct _FILETIME | |||
76 | DWORD dwHighDateTime; | 76 | DWORD dwHighDateTime; |
77 | } FILETIME; | 77 | } FILETIME; |
78 | 78 | ||
79 | #define HRESULT LONG | ||
80 | #define SUCCEEDED(hr) ((HRESULT)(hr) >= 0) | 79 | #define SUCCEEDED(hr) ((HRESULT)(hr) >= 0) |
81 | #define FAILED(hr) ((HRESULT)(hr) < 0) | 80 | #define FAILED(hr) ((HRESULT)(hr) < 0) |
82 | typedef ULONG PROPID; | 81 | typedef ULONG PROPID; |
@@ -150,6 +149,7 @@ enum VARENUM | |||
150 | VT_VARIANT = 12, | 149 | VT_VARIANT = 12, |
151 | VT_UNKNOWN = 13, | 150 | VT_UNKNOWN = 13, |
152 | VT_DECIMAL = 14, | 151 | VT_DECIMAL = 14, |
152 | |||
153 | VT_I1 = 16, | 153 | VT_I1 = 16, |
154 | VT_UI1 = 17, | 154 | VT_UI1 = 17, |
155 | VT_UI2 = 18, | 155 | VT_UI2 = 18, |
diff --git a/CPP/Common/NewHandler.cpp b/CPP/Common/NewHandler.cpp index 7e5b1d4..65ef41d 100644 --- a/CPP/Common/NewHandler.cpp +++ b/CPP/Common/NewHandler.cpp | |||
@@ -97,19 +97,33 @@ const int kDebugSize = 1000000; | |||
97 | static void *a[kDebugSize]; | 97 | static void *a[kDebugSize]; |
98 | static int index = 0; | 98 | static int index = 0; |
99 | 99 | ||
100 | static bool wasInit = false; | ||
101 | static CRITICAL_SECTION cs; | ||
102 | |||
100 | static int numAllocs = 0; | 103 | static int numAllocs = 0; |
101 | void * __cdecl operator new(size_t size) | 104 | void * __cdecl operator new(size_t size) |
102 | { | 105 | { |
106 | if (!wasInit) | ||
107 | { | ||
108 | InitializeCriticalSection(&cs); | ||
109 | wasInit = true; | ||
110 | } | ||
111 | EnterCriticalSection(&cs); | ||
112 | |||
103 | numAllocs++; | 113 | numAllocs++; |
114 | int loc = numAllocs; | ||
104 | void *p = HeapAlloc(GetProcessHeap(), 0, size); | 115 | void *p = HeapAlloc(GetProcessHeap(), 0, size); |
116 | /* | ||
105 | if (index < kDebugSize) | 117 | if (index < kDebugSize) |
106 | { | 118 | { |
107 | a[index] = p; | 119 | a[index] = p; |
108 | index++; | 120 | index++; |
109 | } | 121 | } |
122 | */ | ||
123 | printf("Alloc %6d, size = %8u\n", loc, (unsigned)size); | ||
124 | LeaveCriticalSection(&cs); | ||
110 | if (p == 0) | 125 | if (p == 0) |
111 | throw CNewException(); | 126 | throw CNewException(); |
112 | printf("Alloc %6d, size = %8u\n", numAllocs, (unsigned)size); | ||
113 | return p; | 127 | return p; |
114 | } | 128 | } |
115 | 129 | ||
@@ -123,6 +137,7 @@ public: | |||
123 | } | 137 | } |
124 | ~CC() | 138 | ~CC() |
125 | { | 139 | { |
140 | printf("\nDestructor: %d\n", numAllocs); | ||
126 | for (int i = 0; i < kDebugSize; i++) | 141 | for (int i = 0; i < kDebugSize; i++) |
127 | if (a[i] != 0) | 142 | if (a[i] != 0) |
128 | return; | 143 | return; |
@@ -134,6 +149,7 @@ void __cdecl operator delete(void *p) | |||
134 | { | 149 | { |
135 | if (p == 0) | 150 | if (p == 0) |
136 | return; | 151 | return; |
152 | EnterCriticalSection(&cs); | ||
137 | /* | 153 | /* |
138 | for (int i = 0; i < index; i++) | 154 | for (int i = 0; i < index; i++) |
139 | if (a[i] == p) | 155 | if (a[i] == p) |
@@ -142,6 +158,7 @@ void __cdecl operator delete(void *p) | |||
142 | HeapFree(GetProcessHeap(), 0, p); | 158 | HeapFree(GetProcessHeap(), 0, p); |
143 | numAllocs--; | 159 | numAllocs--; |
144 | printf("Free %d\n", numAllocs); | 160 | printf("Free %d\n", numAllocs); |
161 | LeaveCriticalSection(&cs); | ||
145 | } | 162 | } |
146 | 163 | ||
147 | #endif | 164 | #endif |
diff --git a/CPP/Common/StringToInt.cpp b/CPP/Common/StringToInt.cpp index 839867a..bc4926e 100644 --- a/CPP/Common/StringToInt.cpp +++ b/CPP/Common/StringToInt.cpp | |||
@@ -26,6 +26,33 @@ CONVERT_STRING_TO_UINT_FUNC(UInt32, wchar_t, wchar_t) | |||
26 | CONVERT_STRING_TO_UINT_FUNC(UInt64, char, Byte) | 26 | CONVERT_STRING_TO_UINT_FUNC(UInt64, char, Byte) |
27 | CONVERT_STRING_TO_UINT_FUNC(UInt64, wchar_t, wchar_t) | 27 | CONVERT_STRING_TO_UINT_FUNC(UInt64, wchar_t, wchar_t) |
28 | 28 | ||
29 | /* | ||
30 | Int32 ConvertStringToInt32(const char *s, const char **end) throw() | ||
31 | { | ||
32 | if (end) | ||
33 | *end = s; | ||
34 | const char *s2 = s; | ||
35 | if (*s == '-') | ||
36 | s2++; | ||
37 | if (*s2 == 0) | ||
38 | return 0; | ||
39 | const char *end2; | ||
40 | UInt32 res = ConvertStringToUInt32(s2, &end2); | ||
41 | if (*s == '-') | ||
42 | { | ||
43 | if (res > ((UInt32)1 << (32 - 1))) | ||
44 | return 0; | ||
45 | } | ||
46 | else if ((res & ((UInt32)1 << (32 - 1))) != 0) | ||
47 | return 0; | ||
48 | if (end) | ||
49 | *end = end2; | ||
50 | if (*s == '-') | ||
51 | return -(Int32)res; | ||
52 | return (Int32)res; | ||
53 | } | ||
54 | */ | ||
55 | |||
29 | Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw() | 56 | Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw() |
30 | { | 57 | { |
31 | if (end) | 58 | if (end) |
diff --git a/CPP/Common/StringToInt.h b/CPP/Common/StringToInt.h index 5c5d7d7..4057e49 100644 --- a/CPP/Common/StringToInt.h +++ b/CPP/Common/StringToInt.h | |||
@@ -10,6 +10,7 @@ UInt64 ConvertStringToUInt64(const char *s, const char **end) throw(); | |||
10 | UInt32 ConvertStringToUInt32(const wchar_t *s, const wchar_t **end) throw(); | 10 | UInt32 ConvertStringToUInt32(const wchar_t *s, const wchar_t **end) throw(); |
11 | UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) throw(); | 11 | UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) throw(); |
12 | 12 | ||
13 | // Int32 ConvertStringToInt32(const char *s, const char **end) throw(); | ||
13 | Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw(); | 14 | Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw(); |
14 | 15 | ||
15 | UInt32 ConvertOctStringToUInt32(const char *s, const char **end) throw(); | 16 | UInt32 ConvertOctStringToUInt32(const char *s, const char **end) throw(); |
diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp index 8a33fc8..cce2638 100644 --- a/CPP/Windows/FileDir.cpp +++ b/CPP/Windows/FileDir.cpp | |||
@@ -17,7 +17,6 @@ | |||
17 | 17 | ||
18 | #include "../Common/StringConvert.h" | 18 | #include "../Common/StringConvert.h" |
19 | #include "../Common/C_FileIO.h" | 19 | #include "../Common/C_FileIO.h" |
20 | #include "TimeUtils.h" | ||
21 | #endif | 20 | #endif |
22 | 21 | ||
23 | #include "FileDir.h" | 22 | #include "FileDir.h" |
@@ -32,6 +31,30 @@ using namespace NWindows; | |||
32 | using namespace NFile; | 31 | using namespace NFile; |
33 | using namespace NName; | 32 | using namespace NName; |
34 | 33 | ||
34 | #ifndef _WIN32 | ||
35 | |||
36 | static bool FiTime_To_timespec(const CFiTime *ft, timespec &ts) | ||
37 | { | ||
38 | if (ft) | ||
39 | { | ||
40 | ts = *ft; | ||
41 | return true; | ||
42 | } | ||
43 | // else | ||
44 | { | ||
45 | ts.tv_sec = 0; | ||
46 | ts.tv_nsec = | ||
47 | #ifdef UTIME_OMIT | ||
48 | UTIME_OMIT; // -2 keep old timesptamp | ||
49 | #else | ||
50 | // UTIME_NOW; -1 // set to the current time | ||
51 | 0; | ||
52 | #endif | ||
53 | return false; | ||
54 | } | ||
55 | } | ||
56 | #endif | ||
57 | |||
35 | namespace NWindows { | 58 | namespace NWindows { |
36 | namespace NFile { | 59 | namespace NFile { |
37 | namespace NDir { | 60 | namespace NDir { |
@@ -86,7 +109,7 @@ bool GetSystemDir(FString &path) | |||
86 | #endif // UNDER_CE | 109 | #endif // UNDER_CE |
87 | 110 | ||
88 | 111 | ||
89 | bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) | 112 | bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) |
90 | { | 113 | { |
91 | #ifndef _UNICODE | 114 | #ifndef _UNICODE |
92 | if (!g_IsNT) | 115 | if (!g_IsNT) |
@@ -920,39 +943,11 @@ bool GetCurrentDir(FString &path) | |||
920 | // #define UTIME_OMIT -2 | 943 | // #define UTIME_OMIT -2 |
921 | #endif | 944 | #endif |
922 | 945 | ||
923 | static bool FILETME_To_timespec(const FILETIME *ft, timespec &ts) | ||
924 | { | ||
925 | if (ft) | ||
926 | { | ||
927 | const Int64 sec = NTime::FileTimeToUnixTime64(*ft); | ||
928 | // time_t is long | ||
929 | const time_t sec2 = (time_t)sec; | ||
930 | if (sec2 == sec) | ||
931 | { | ||
932 | ts.tv_sec = sec2; | ||
933 | const UInt64 winTime = (((UInt64)ft->dwHighDateTime) << 32) + ft->dwLowDateTime; | ||
934 | ts.tv_nsec = (long)((winTime % 10000000) * 100); | ||
935 | return true; | ||
936 | } | ||
937 | } | ||
938 | // else | ||
939 | { | ||
940 | ts.tv_sec = 0; | ||
941 | ts.tv_nsec = | ||
942 | #ifdef UTIME_OMIT | ||
943 | UTIME_OMIT; // keep old timesptamp | ||
944 | #else | ||
945 | // UTIME_NOW; // set to the current time | ||
946 | 0; | ||
947 | #endif | ||
948 | return false; | ||
949 | } | ||
950 | } | ||
951 | 946 | ||
952 | 947 | ||
953 | 948 | ||
954 | 949 | ||
955 | bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) | 950 | bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) |
956 | { | 951 | { |
957 | // need testing | 952 | // need testing |
958 | /* | 953 | /* |
@@ -998,12 +993,18 @@ bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const | |||
998 | UNUSED_VAR(cTime) | 993 | UNUSED_VAR(cTime) |
999 | 994 | ||
1000 | bool needChange; | 995 | bool needChange; |
1001 | needChange = FILETME_To_timespec(aTime, times[0]); | 996 | needChange = FiTime_To_timespec(aTime, times[0]); |
1002 | needChange |= FILETME_To_timespec(mTime, times[1]); | 997 | needChange |= FiTime_To_timespec(mTime, times[1]); |
998 | |||
999 | /* | ||
1000 | if (mTime) | ||
1001 | { | ||
1002 | printf("\n time = %ld.%9ld\n", mTime->tv_sec, mTime->tv_nsec); | ||
1003 | } | ||
1004 | */ | ||
1003 | 1005 | ||
1004 | if (!needChange) | 1006 | if (!needChange) |
1005 | return true; | 1007 | return true; |
1006 | |||
1007 | const int flags = 0; // follow link | 1008 | const int flags = 0; // follow link |
1008 | // = AT_SYMLINK_NOFOLLOW; // don't follow link | 1009 | // = AT_SYMLINK_NOFOLLOW; // don't follow link |
1009 | return utimensat(AT_FDCWD, path, times, flags) == 0; | 1010 | return utimensat(AT_FDCWD, path, times, flags) == 0; |
@@ -1039,6 +1040,10 @@ static C_umask g_umask; | |||
1039 | #define TRACE_chmod(s, mode) \ | 1040 | #define TRACE_chmod(s, mode) \ |
1040 | PRF(printf("\n chmod(%s, %o)\n", (const char *)path, (unsigned)(mode))); | 1041 | PRF(printf("\n chmod(%s, %o)\n", (const char *)path, (unsigned)(mode))); |
1041 | 1042 | ||
1043 | int my_chown(CFSTR path, uid_t owner, gid_t group) | ||
1044 | { | ||
1045 | return chown(path, owner, group); | ||
1046 | } | ||
1042 | 1047 | ||
1043 | bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) | 1048 | bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) |
1044 | { | 1049 | { |
diff --git a/CPP/Windows/FileDir.h b/CPP/Windows/FileDir.h index 6d6ddea..08281aa 100644 --- a/CPP/Windows/FileDir.h +++ b/CPP/Windows/FileDir.h | |||
@@ -14,7 +14,12 @@ namespace NDir { | |||
14 | bool GetWindowsDir(FString &path); | 14 | bool GetWindowsDir(FString &path); |
15 | bool GetSystemDir(FString &path); | 15 | bool GetSystemDir(FString &path); |
16 | 16 | ||
17 | bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); | 17 | /* |
18 | WIN32 API : SetFileTime() doesn't allow to set zero timestamps in file | ||
19 | but linux : allows unix time = 0 in filesystem | ||
20 | */ | ||
21 | |||
22 | bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime); | ||
18 | 23 | ||
19 | 24 | ||
20 | #ifdef _WIN32 | 25 | #ifdef _WIN32 |
@@ -27,6 +32,9 @@ bool SetFileAttrib(CFSTR path, DWORD attrib); | |||
27 | SetFileAttrib_PosixHighDetect() tries to detect posix field, and it extracts only attribute | 32 | SetFileAttrib_PosixHighDetect() tries to detect posix field, and it extracts only attribute |
28 | bits that are related to current system only. | 33 | bits that are related to current system only. |
29 | */ | 34 | */ |
35 | #else | ||
36 | |||
37 | int my_chown(CFSTR path, uid_t owner, gid_t group); | ||
30 | 38 | ||
31 | #endif | 39 | #endif |
32 | 40 | ||
diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp index 591f8df..c655759 100644 --- a/CPP/Windows/FileFind.cpp +++ b/CPP/Windows/FileFind.cpp | |||
@@ -7,6 +7,8 @@ | |||
7 | #ifndef _WIN32 | 7 | #ifndef _WIN32 |
8 | #include <fcntl.h> /* Definition of AT_* constants */ | 8 | #include <fcntl.h> /* Definition of AT_* constants */ |
9 | #include "TimeUtils.h" | 9 | #include "TimeUtils.h" |
10 | // for major | ||
11 | // #include <sys/sysmacros.h> | ||
10 | #endif | 12 | #endif |
11 | 13 | ||
12 | #include "FileFind.h" | 14 | #include "FileFind.h" |
@@ -62,24 +64,35 @@ bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, | |||
62 | 64 | ||
63 | namespace NFind { | 65 | namespace NFind { |
64 | 66 | ||
67 | /* | ||
68 | #ifdef _WIN32 | ||
65 | #define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0; | 69 | #define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0; |
70 | #else | ||
71 | #define MY_CLEAR_FILETIME(ft) ft.tv_sec = 0; ft.tv_nsec = 0; | ||
72 | #endif | ||
73 | */ | ||
66 | 74 | ||
67 | void CFileInfoBase::ClearBase() throw() | 75 | void CFileInfoBase::ClearBase() throw() |
68 | { | 76 | { |
69 | Size = 0; | 77 | Size = 0; |
70 | MY_CLEAR_FILETIME(CTime); | 78 | FiTime_Clear(CTime); |
71 | MY_CLEAR_FILETIME(ATime); | 79 | FiTime_Clear(ATime); |
72 | MY_CLEAR_FILETIME(MTime); | 80 | FiTime_Clear(MTime); |
81 | |||
82 | #ifdef _WIN32 | ||
73 | Attrib = 0; | 83 | Attrib = 0; |
74 | // ReparseTag = 0; | 84 | // ReparseTag = 0; |
75 | IsAltStream = false; | 85 | IsAltStream = false; |
76 | IsDevice = false; | 86 | IsDevice = false; |
77 | 87 | #else | |
78 | #ifndef _WIN32 | 88 | dev = 0; |
79 | ino = 0; | 89 | ino = 0; |
80 | nlink = 0; | ||
81 | mode = 0; | 90 | mode = 0; |
82 | #endif | 91 | nlink = 0; |
92 | uid = 0; | ||
93 | gid = 0; | ||
94 | rdev = 0; | ||
95 | #endif | ||
83 | } | 96 | } |
84 | 97 | ||
85 | bool CFileInfo::IsDots() const throw() | 98 | bool CFileInfo::IsDots() const throw() |
@@ -439,6 +452,20 @@ also we support paths that are not supported by FindFirstFile: | |||
439 | bool CFileInfo::Find(CFSTR path, bool followLink) | 452 | bool CFileInfo::Find(CFSTR path, bool followLink) |
440 | { | 453 | { |
441 | #ifdef SUPPORT_DEVICE_FILE | 454 | #ifdef SUPPORT_DEVICE_FILE |
455 | |||
456 | if (IS_PATH_SEPAR(path[0]) && | ||
457 | IS_PATH_SEPAR(path[1]) && | ||
458 | path[2] == '.' && | ||
459 | path[3] == 0) | ||
460 | { | ||
461 | // 22.00 : it's virtual directory for devices | ||
462 | // IsDevice = true; | ||
463 | ClearBase(); | ||
464 | Name = path + 2; | ||
465 | Attrib = FILE_ATTRIBUTE_DIRECTORY; | ||
466 | return true; | ||
467 | } | ||
468 | |||
442 | if (IsDevicePath(path)) | 469 | if (IsDevicePath(path)) |
443 | { | 470 | { |
444 | ClearBase(); | 471 | ClearBase(); |
@@ -469,7 +496,7 @@ bool CFileInfo::Find(CFSTR path, bool followLink) | |||
469 | 496 | ||
470 | #if defined(_WIN32) && !defined(UNDER_CE) | 497 | #if defined(_WIN32) && !defined(UNDER_CE) |
471 | 498 | ||
472 | int colonPos = FindAltStreamColon(path); | 499 | const int colonPos = FindAltStreamColon(path); |
473 | if (colonPos >= 0 && path[(unsigned)colonPos + 1] != 0) | 500 | if (colonPos >= 0 && path[(unsigned)colonPos + 1] != 0) |
474 | { | 501 | { |
475 | UString streamName = fs2us(path + (unsigned)colonPos); | 502 | UString streamName = fs2us(path + (unsigned)colonPos); |
@@ -635,7 +662,7 @@ bool CFileInfo::Find(CFSTR path, bool followLink) | |||
635 | return Fill_From_ByHandleFileInfo(path); | 662 | return Fill_From_ByHandleFileInfo(path); |
636 | } | 663 | } |
637 | 664 | ||
638 | bool CFileInfo::Fill_From_ByHandleFileInfo(CFSTR path) | 665 | bool CFileInfoBase::Fill_From_ByHandleFileInfo(CFSTR path) |
639 | { | 666 | { |
640 | BY_HANDLE_FILE_INFORMATION info; | 667 | BY_HANDLE_FILE_INFORMATION info; |
641 | if (!NIO::CFileBase::GetFileInformation(path, &info)) | 668 | if (!NIO::CFileBase::GetFileInformation(path, &info)) |
@@ -950,13 +977,6 @@ static const char *Get_Name_from_Path(CFSTR path) throw() | |||
950 | } | 977 | } |
951 | 978 | ||
952 | 979 | ||
953 | void timespec_To_FILETIME(const MY_ST_TIMESPEC &ts, FILETIME &ft) | ||
954 | { | ||
955 | UInt64 v = NTime::UnixTime64ToFileTime64(ts.tv_sec) + ((UInt64)ts.tv_nsec / 100); | ||
956 | ft.dwLowDateTime = (DWORD)v; | ||
957 | ft.dwHighDateTime = (DWORD)(v >> 32); | ||
958 | } | ||
959 | |||
960 | UInt32 Get_WinAttribPosix_From_PosixMode(UInt32 mode) | 980 | UInt32 Get_WinAttribPosix_From_PosixMode(UInt32 mode) |
961 | { | 981 | { |
962 | UInt32 attrib = S_ISDIR(mode) ? | 982 | UInt32 attrib = S_ISDIR(mode) ? |
@@ -984,7 +1004,7 @@ UInt32 Get_WinAttrib_From_stat(const struct stat &st) | |||
984 | 1004 | ||
985 | void CFileInfo::SetFrom_stat(const struct stat &st) | 1005 | void CFileInfo::SetFrom_stat(const struct stat &st) |
986 | { | 1006 | { |
987 | IsDevice = false; | 1007 | // IsDevice = false; |
988 | 1008 | ||
989 | if (S_ISDIR(st.st_mode)) | 1009 | if (S_ISDIR(st.st_mode)) |
990 | { | 1010 | { |
@@ -995,7 +1015,7 @@ void CFileInfo::SetFrom_stat(const struct stat &st) | |||
995 | Size = (UInt64)st.st_size; // for a symbolic link, size = size of filename | 1015 | Size = (UInt64)st.st_size; // for a symbolic link, size = size of filename |
996 | } | 1016 | } |
997 | 1017 | ||
998 | Attrib = Get_WinAttribPosix_From_PosixMode(st.st_mode); | 1018 | // Attrib = Get_WinAttribPosix_From_PosixMode(st.st_mode); |
999 | 1019 | ||
1000 | // NTime::UnixTimeToFileTime(st.st_ctime, CTime); | 1020 | // NTime::UnixTimeToFileTime(st.st_ctime, CTime); |
1001 | // NTime::UnixTimeToFileTime(st.st_mtime, MTime); | 1021 | // NTime::UnixTimeToFileTime(st.st_mtime, MTime); |
@@ -1010,27 +1030,89 @@ void CFileInfo::SetFrom_stat(const struct stat &st) | |||
1010 | */ | 1030 | */ |
1011 | // timespec_To_FILETIME(st.st_birthtimespec, CTime); | 1031 | // timespec_To_FILETIME(st.st_birthtimespec, CTime); |
1012 | // #else | 1032 | // #else |
1013 | timespec_To_FILETIME(st.st_ctimespec, CTime); | 1033 | // timespec_To_FILETIME(st.st_ctimespec, CTime); |
1014 | // #endif | 1034 | // #endif |
1015 | timespec_To_FILETIME(st.st_mtimespec, MTime); | 1035 | // timespec_To_FILETIME(st.st_mtimespec, MTime); |
1016 | timespec_To_FILETIME(st.st_atimespec, ATime); | 1036 | // timespec_To_FILETIME(st.st_atimespec, ATime); |
1037 | CTime = st.st_ctimespec; | ||
1038 | MTime = st.st_mtimespec; | ||
1039 | ATime = st.st_atimespec; | ||
1040 | |||
1017 | #else | 1041 | #else |
1018 | timespec_To_FILETIME(st.st_ctim, CTime); | 1042 | // timespec_To_FILETIME(st.st_ctim, CTime, &CTime_ns100); |
1019 | timespec_To_FILETIME(st.st_mtim, MTime); | 1043 | // timespec_To_FILETIME(st.st_mtim, MTime, &MTime_ns100); |
1020 | timespec_To_FILETIME(st.st_atim, ATime); | 1044 | // timespec_To_FILETIME(st.st_atim, ATime, &ATime_ns100); |
1045 | CTime = st.st_ctim; | ||
1046 | MTime = st.st_mtim; | ||
1047 | ATime = st.st_atim; | ||
1048 | |||
1021 | #endif | 1049 | #endif |
1022 | 1050 | ||
1023 | dev = st.st_dev; | 1051 | dev = st.st_dev; |
1024 | ino = st.st_ino; | 1052 | ino = st.st_ino; |
1025 | nlink = st.st_nlink; | ||
1026 | mode = st.st_mode; | 1053 | mode = st.st_mode; |
1054 | nlink = st.st_nlink; | ||
1055 | uid = st.st_uid; | ||
1056 | gid = st.st_gid; | ||
1057 | rdev = st.st_rdev; | ||
1058 | |||
1059 | /* | ||
1060 | printf("\n sizeof timespec = %d", (int)sizeof(timespec)); | ||
1061 | printf("\n sizeof st_rdev = %d", (int)sizeof(rdev)); | ||
1062 | printf("\n sizeof st_ino = %d", (int)sizeof(ino)); | ||
1063 | printf("\n sizeof mode_t = %d", (int)sizeof(mode_t)); | ||
1064 | printf("\n sizeof nlink_t = %d", (int)sizeof(nlink_t)); | ||
1065 | printf("\n sizeof uid_t = %d", (int)sizeof(uid_t)); | ||
1066 | printf("\n"); | ||
1067 | */ | ||
1068 | /* | ||
1069 | printf("\n st_rdev = %llx", (long long)rdev); | ||
1070 | printf("\n st_dev = %llx", (long long)dev); | ||
1071 | printf("\n dev : major = %5x minor = %5x", (unsigned)major(dev), (unsigned)minor(dev)); | ||
1072 | printf("\n st_ino = %lld", (long long)(ino)); | ||
1073 | printf("\n rdev : major = %5x minor = %5x", (unsigned)major(rdev), (unsigned)minor(rdev)); | ||
1074 | printf("\n size = %lld \n", (long long)(Size)); | ||
1075 | printf("\n"); | ||
1076 | */ | ||
1077 | } | ||
1078 | |||
1079 | /* | ||
1080 | int Uid_To_Uname(uid_t uid, AString &name) | ||
1081 | { | ||
1082 | name.Empty(); | ||
1083 | struct passwd *passwd; | ||
1084 | |||
1085 | if (uid != 0 && uid == cached_no_such_uid) | ||
1086 | { | ||
1087 | *uname = xstrdup (""); | ||
1088 | return; | ||
1089 | } | ||
1090 | |||
1091 | if (!cached_uname || uid != cached_uid) | ||
1092 | { | ||
1093 | passwd = getpwuid (uid); | ||
1094 | if (passwd) | ||
1095 | { | ||
1096 | cached_uid = uid; | ||
1097 | assign_string (&cached_uname, passwd->pw_name); | ||
1098 | } | ||
1099 | else | ||
1100 | { | ||
1101 | cached_no_such_uid = uid; | ||
1102 | *uname = xstrdup (""); | ||
1103 | return; | ||
1104 | } | ||
1105 | } | ||
1106 | *uname = xstrdup (cached_uname); | ||
1027 | } | 1107 | } |
1108 | */ | ||
1028 | 1109 | ||
1029 | bool CFileInfo::Find_DontFill_Name(CFSTR path, bool followLink) | 1110 | bool CFileInfo::Find_DontFill_Name(CFSTR path, bool followLink) |
1030 | { | 1111 | { |
1031 | struct stat st; | 1112 | struct stat st; |
1032 | if (MY__lstat(path, &st, followLink) != 0) | 1113 | if (MY__lstat(path, &st, followLink) != 0) |
1033 | return false; | 1114 | return false; |
1115 | // printf("\nFind_DontFill_Name : name=%s\n", path); | ||
1034 | SetFrom_stat(st); | 1116 | SetFrom_stat(st); |
1035 | return true; | 1117 | return true; |
1036 | } | 1118 | } |
@@ -1232,6 +1314,7 @@ bool CEnumerator::Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool f | |||
1232 | 1314 | ||
1233 | if (res != 0) | 1315 | if (res != 0) |
1234 | return false; | 1316 | return false; |
1317 | // printf("\nname=%s\n", de.Name.Ptr()); | ||
1235 | fileInfo.SetFrom_stat(st); | 1318 | fileInfo.SetFrom_stat(st); |
1236 | fileInfo.Name = de.Name; | 1319 | fileInfo.Name = de.Name; |
1237 | return true; | 1320 | return true; |
diff --git a/CPP/Windows/FileFind.h b/CPP/Windows/FileFind.h index 8f28ee3..fcfe02c 100644 --- a/CPP/Windows/FileFind.h +++ b/CPP/Windows/FileFind.h | |||
@@ -9,10 +9,14 @@ | |||
9 | #include <dirent.h> | 9 | #include <dirent.h> |
10 | #endif | 10 | #endif |
11 | 11 | ||
12 | #include "../Common/MyLinux.h" | ||
12 | #include "../Common/MyString.h" | 13 | #include "../Common/MyString.h" |
13 | #include "../Common/MyWindows.h" | 14 | #include "../Common/MyWindows.h" |
15 | |||
14 | #include "Defs.h" | 16 | #include "Defs.h" |
15 | 17 | ||
18 | #include "FileIO.h" | ||
19 | |||
16 | namespace NWindows { | 20 | namespace NWindows { |
17 | namespace NFile { | 21 | namespace NFile { |
18 | namespace NFind { | 22 | namespace NFind { |
@@ -32,6 +36,7 @@ bool DoesFileOrDirExist(CFSTR name); | |||
32 | 36 | ||
33 | DWORD GetFileAttrib(CFSTR path); | 37 | DWORD GetFileAttrib(CFSTR path); |
34 | 38 | ||
39 | #ifdef _WIN32 | ||
35 | 40 | ||
36 | namespace NAttributes | 41 | namespace NAttributes |
37 | { | 42 | { |
@@ -42,21 +47,38 @@ namespace NAttributes | |||
42 | inline bool IsArchived(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ARCHIVE) != 0; } | 47 | inline bool IsArchived(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ARCHIVE) != 0; } |
43 | inline bool IsCompressed(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_COMPRESSED) != 0; } | 48 | inline bool IsCompressed(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_COMPRESSED) != 0; } |
44 | inline bool IsEncrypted(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ENCRYPTED) != 0; } | 49 | inline bool IsEncrypted(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ENCRYPTED) != 0; } |
50 | |||
51 | inline UInt32 Get_PosixMode_From_WinAttrib(DWORD attrib) | ||
52 | { | ||
53 | UInt32 v = IsDir(attrib) ? MY_LIN_S_IFDIR : MY_LIN_S_IFREG; | ||
54 | /* 21.06: as WSL we allow write permissions (0222) for directories even for (FILE_ATTRIBUTE_READONLY). | ||
55 | So extracting at Linux will be allowed to write files inside (0777) directories. */ | ||
56 | v |= ((IsReadOnly(attrib) && !IsDir(attrib)) ? 0555 : 0777); | ||
57 | return v; | ||
58 | } | ||
45 | } | 59 | } |
46 | 60 | ||
61 | #else | ||
62 | |||
63 | UInt32 Get_WinAttribPosix_From_PosixMode(UInt32 mode); | ||
64 | |||
65 | #endif | ||
66 | |||
47 | class CFileInfoBase | 67 | class CFileInfoBase |
48 | { | 68 | { |
69 | #ifdef _WIN32 | ||
49 | bool MatchesMask(UINT32 mask) const { return ((Attrib & mask) != 0); } | 70 | bool MatchesMask(UINT32 mask) const { return ((Attrib & mask) != 0); } |
71 | #endif | ||
50 | public: | 72 | public: |
51 | UInt64 Size; | 73 | UInt64 Size; |
52 | FILETIME CTime; | 74 | CFiTime CTime; |
53 | FILETIME ATime; | 75 | CFiTime ATime; |
54 | FILETIME MTime; | 76 | CFiTime MTime; |
77 | #ifdef _WIN32 | ||
55 | DWORD Attrib; | 78 | DWORD Attrib; |
56 | bool IsAltStream; | 79 | bool IsAltStream; |
57 | bool IsDevice; | 80 | bool IsDevice; |
58 | 81 | ||
59 | #ifdef _WIN32 | ||
60 | /* | 82 | /* |
61 | #ifdef UNDER_CE | 83 | #ifdef UNDER_CE |
62 | DWORD ObjectID; | 84 | DWORD ObjectID; |
@@ -64,24 +86,25 @@ public: | |||
64 | UINT32 ReparseTag; | 86 | UINT32 ReparseTag; |
65 | #endif | 87 | #endif |
66 | */ | 88 | */ |
67 | #else | 89 | #else |
68 | dev_t dev; | 90 | dev_t dev; /* ID of device containing file */ |
69 | ino_t ino; | 91 | ino_t ino; |
70 | nlink_t nlink; | ||
71 | mode_t mode; | 92 | mode_t mode; |
93 | nlink_t nlink; | ||
94 | uid_t uid; /* user ID of owner */ | ||
95 | gid_t gid; /* group ID of owner */ | ||
96 | dev_t rdev; /* device ID (defined, if S_ISCHR(mode) || S_ISBLK(mode)) */ | ||
72 | // bool Use_lstat; | 97 | // bool Use_lstat; |
73 | #endif | 98 | #endif |
74 | 99 | ||
75 | CFileInfoBase() { ClearBase(); } | 100 | CFileInfoBase() { ClearBase(); } |
76 | void ClearBase() throw(); | 101 | void ClearBase() throw(); |
77 | 102 | ||
78 | void SetAsDir() | 103 | #ifdef _WIN32 |
79 | { | 104 | |
80 | Attrib = FILE_ATTRIBUTE_DIRECTORY; | 105 | bool Fill_From_ByHandleFileInfo(CFSTR path); |
81 | #ifndef _WIN32 | 106 | void SetAsDir() { Attrib = FILE_ATTRIBUTE_DIRECTORY; } // |= (FILE_ATTRIBUTE_UNIX_EXTENSION + (S_IFDIR << 16)); |
82 | Attrib |= (FILE_ATTRIBUTE_UNIX_EXTENSION + (S_IFDIR << 16)); | 107 | void SetAsFile() { Attrib = 0; } |
83 | #endif | ||
84 | } | ||
85 | 108 | ||
86 | bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); } | 109 | bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); } |
87 | bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); } | 110 | bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); } |
@@ -96,13 +119,33 @@ public: | |||
96 | bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); } | 119 | bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); } |
97 | bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); } | 120 | bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); } |
98 | 121 | ||
99 | #ifndef _WIN32 | 122 | UInt32 GetWinAttrib() const { return Attrib; } |
100 | bool IsPosixLink() const | 123 | UInt32 GetPosixAttrib() const |
101 | { | 124 | { |
102 | const UInt32 mod = Attrib >> 16; | 125 | return NAttributes::Get_PosixMode_From_WinAttrib(Attrib); |
103 | return S_ISLNK(mod); | ||
104 | } | 126 | } |
105 | #endif | 127 | bool Has_Attrib_ReparsePoint() const { return (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0; } |
128 | |||
129 | #else | ||
130 | |||
131 | UInt32 GetPosixAttrib() const { return mode; } | ||
132 | UInt32 GetWinAttrib() const { return Get_WinAttribPosix_From_PosixMode(mode); } | ||
133 | |||
134 | bool IsDir() const { return S_ISDIR(mode); } | ||
135 | void SetAsDir() { mode = S_IFDIR; } | ||
136 | void SetAsFile() { mode = S_IFREG; } | ||
137 | |||
138 | bool IsReadOnly() const | ||
139 | { | ||
140 | // does linux support writing to ReadOnly files? | ||
141 | if ((mode & 0222) == 0) // S_IWUSR in p7zip | ||
142 | return true; | ||
143 | return false; | ||
144 | } | ||
145 | |||
146 | bool IsPosixLink() const { return S_ISLNK(mode); } | ||
147 | |||
148 | #endif | ||
106 | 149 | ||
107 | bool IsOsSymLink() const | 150 | bool IsOsSymLink() const |
108 | { | 151 | { |
@@ -126,7 +169,7 @@ struct CFileInfo: public CFileInfoBase | |||
126 | bool Find_FollowLink(CFSTR path) { return Find(path, true); } | 169 | bool Find_FollowLink(CFSTR path) { return Find(path, true); } |
127 | 170 | ||
128 | #ifdef _WIN32 | 171 | #ifdef _WIN32 |
129 | bool Fill_From_ByHandleFileInfo(CFSTR path); | 172 | // bool Fill_From_ByHandleFileInfo(CFSTR path); |
130 | // bool FollowReparse(CFSTR path, bool isDir); | 173 | // bool FollowReparse(CFSTR path, bool isDir); |
131 | #else | 174 | #else |
132 | bool Find_DontFill_Name(CFSTR path, bool followLink = false); | 175 | bool Find_DontFill_Name(CFSTR path, bool followLink = false); |
@@ -287,16 +330,8 @@ inline UInt32 Get_WinAttrib_From_PosixMode(UInt32 mode) | |||
287 | } | 330 | } |
288 | */ | 331 | */ |
289 | 332 | ||
290 | UInt32 Get_WinAttribPosix_From_PosixMode(UInt32 mode); | ||
291 | |||
292 | // UInt32 Get_WinAttrib_From_stat(const struct stat &st); | 333 | // UInt32 Get_WinAttrib_From_stat(const struct stat &st); |
293 | #if defined(_AIX) | ||
294 | #define MY_ST_TIMESPEC st_timespec | ||
295 | #else | ||
296 | #define MY_ST_TIMESPEC timespec | ||
297 | #endif | ||
298 | 334 | ||
299 | void timespec_To_FILETIME(const MY_ST_TIMESPEC &ts, FILETIME &ft); | ||
300 | 335 | ||
301 | #endif // WIN32 | 336 | #endif // WIN32 |
302 | 337 | ||
diff --git a/CPP/Windows/FileIO.cpp b/CPP/Windows/FileIO.cpp index 2974b1b..e51b0eb 100644 --- a/CPP/Windows/FileIO.cpp +++ b/CPP/Windows/FileIO.cpp | |||
@@ -8,6 +8,14 @@ | |||
8 | 8 | ||
9 | // #include <stdio.h> | 9 | // #include <stdio.h> |
10 | 10 | ||
11 | /* | ||
12 | #ifndef _WIN32 | ||
13 | // for ioctl BLKGETSIZE64 | ||
14 | #include <sys/ioctl.h> | ||
15 | #include <linux/fs.h> | ||
16 | #endif | ||
17 | */ | ||
18 | |||
11 | #include "FileIO.h" | 19 | #include "FileIO.h" |
12 | #include "FileName.h" | 20 | #include "FileName.h" |
13 | 21 | ||
@@ -615,7 +623,7 @@ namespace NWindows { | |||
615 | namespace NFile { | 623 | namespace NFile { |
616 | 624 | ||
617 | namespace NDir { | 625 | namespace NDir { |
618 | bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); | 626 | bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime); |
619 | } | 627 | } |
620 | 628 | ||
621 | namespace NIO { | 629 | namespace NIO { |
@@ -629,6 +637,19 @@ bool CFileBase::OpenBinary(const char *name, int flags) | |||
629 | Close(); | 637 | Close(); |
630 | _handle = ::open(name, flags, 0666); | 638 | _handle = ::open(name, flags, 0666); |
631 | return _handle != -1; | 639 | return _handle != -1; |
640 | |||
641 | /* | ||
642 | if (_handle == -1) | ||
643 | return false; | ||
644 | if (IsString1PrefixedByString2(name, "/dev/")) | ||
645 | { | ||
646 | // /dev/sda | ||
647 | // IsDeviceFile = true; // for debug | ||
648 | // SizeDefined = false; | ||
649 | // SizeDefined = (GetDeviceSize_InBytes(Size) == 0); | ||
650 | } | ||
651 | return true; | ||
652 | */ | ||
632 | } | 653 | } |
633 | 654 | ||
634 | bool CFileBase::Close() | 655 | bool CFileBase::Close() |
@@ -638,6 +659,10 @@ bool CFileBase::Close() | |||
638 | if (close(_handle) != 0) | 659 | if (close(_handle) != 0) |
639 | return false; | 660 | return false; |
640 | _handle = -1; | 661 | _handle = -1; |
662 | /* | ||
663 | IsDeviceFile = false; | ||
664 | SizeDefined = false; | ||
665 | */ | ||
641 | return true; | 666 | return true; |
642 | } | 667 | } |
643 | 668 | ||
@@ -651,15 +676,35 @@ bool CFileBase::GetLength(UInt64 &length) const | |||
651 | const off_t lengthTemp = seek(0, SEEK_END); | 676 | const off_t lengthTemp = seek(0, SEEK_END); |
652 | seek(curPos, SEEK_SET); | 677 | seek(curPos, SEEK_SET); |
653 | length = (UInt64)lengthTemp; | 678 | length = (UInt64)lengthTemp; |
679 | |||
680 | /* | ||
681 | // 22.00: | ||
682 | if (lengthTemp == 1) | ||
683 | if (IsDeviceFile && SizeDefined) | ||
684 | { | ||
685 | length = Size; | ||
686 | return true; | ||
687 | } | ||
688 | */ | ||
689 | |||
654 | return (lengthTemp != -1); | 690 | return (lengthTemp != -1); |
655 | } | 691 | } |
656 | 692 | ||
657 | off_t CFileBase::seek(off_t distanceToMove, int moveMethod) const | 693 | off_t CFileBase::seek(off_t distanceToMove, int moveMethod) const |
658 | { | 694 | { |
695 | /* | ||
696 | if (IsDeviceFile && SizeDefined && moveMethod == SEEK_END) | ||
697 | { | ||
698 | printf("\n seek : IsDeviceFile moveMethod = %d distanceToMove = %ld\n", moveMethod, distanceToMove); | ||
699 | distanceToMove += Size; | ||
700 | moveMethod = SEEK_SET; | ||
701 | } | ||
702 | */ | ||
703 | |||
659 | // printf("\nCFileBase::seek() moveMethod = %d, distanceToMove = %lld", moveMethod, (long long)distanceToMove); | 704 | // printf("\nCFileBase::seek() moveMethod = %d, distanceToMove = %lld", moveMethod, (long long)distanceToMove); |
660 | // off_t res = ::lseek(_handle, distanceToMove, moveMethod); | 705 | // off_t res = ::lseek(_handle, distanceToMove, moveMethod); |
706 | // printf("\n lseek : moveMethod = %d distanceToMove = %ld\n", moveMethod, distanceToMove); | ||
661 | return ::lseek(_handle, distanceToMove, moveMethod); | 707 | return ::lseek(_handle, distanceToMove, moveMethod); |
662 | // printf(" res = %lld", (long long)res); | ||
663 | // return res; | 708 | // return res; |
664 | } | 709 | } |
665 | 710 | ||
@@ -694,6 +739,28 @@ bool CInFile::OpenShared(const char *name, bool) | |||
694 | return Open(name); | 739 | return Open(name); |
695 | } | 740 | } |
696 | 741 | ||
742 | |||
743 | /* | ||
744 | int CFileBase::my_ioctl_BLKGETSIZE64(unsigned long long *numBlocks) | ||
745 | { | ||
746 | // we can read "/sys/block/sda/size" "/sys/block/sda/sda1/size" - partition | ||
747 | // #include <linux/fs.h> | ||
748 | return ioctl(_handle, BLKGETSIZE64, numBlocks); | ||
749 | // in block size | ||
750 | } | ||
751 | |||
752 | int CFileBase::GetDeviceSize_InBytes(UInt64 &size) | ||
753 | { | ||
754 | size = 0; | ||
755 | unsigned long long numBlocks; | ||
756 | int res = my_ioctl_BLKGETSIZE64(&numBlocks); | ||
757 | if (res == 0) | ||
758 | size = numBlocks; // another blockSize s possible? | ||
759 | printf("\nGetDeviceSize_InBytes res = %d, size = %lld\n", res, (long long)size); | ||
760 | return res; | ||
761 | } | ||
762 | */ | ||
763 | |||
697 | /* | 764 | /* |
698 | On Linux (32-bit and 64-bit): | 765 | On Linux (32-bit and 64-bit): |
699 | read(), write() (and similar system calls) will transfer at most | 766 | read(), write() (and similar system calls) will transfer at most |
@@ -802,7 +869,7 @@ bool COutFile::Close() | |||
802 | return res; | 869 | return res; |
803 | } | 870 | } |
804 | 871 | ||
805 | bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw() | 872 | bool COutFile::SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw() |
806 | { | 873 | { |
807 | // On some OS (cygwin, MacOSX ...), you must close the file before updating times | 874 | // On some OS (cygwin, MacOSX ...), you must close the file before updating times |
808 | // return true; | 875 | // return true; |
@@ -811,9 +878,22 @@ bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILET | |||
811 | if (aTime) { ATime = *aTime; ATime_defined = true; } else ATime_defined = false; | 878 | if (aTime) { ATime = *aTime; ATime_defined = true; } else ATime_defined = false; |
812 | if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false; | 879 | if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false; |
813 | return true; | 880 | return true; |
881 | |||
882 | /* | ||
883 | struct timespec times[2]; | ||
884 | UNUSED_VAR(cTime) | ||
885 | if (!aTime && !mTime) | ||
886 | return true; | ||
887 | bool needChange; | ||
888 | needChange = FiTime_To_timespec(aTime, times[0]); | ||
889 | needChange |= FiTime_To_timespec(mTime, times[1]); | ||
890 | if (!needChange) | ||
891 | return true; | ||
892 | return futimens(_handle, times) == 0; | ||
893 | */ | ||
814 | } | 894 | } |
815 | 895 | ||
816 | bool COutFile::SetMTime(const FILETIME *mTime) throw() | 896 | bool COutFile::SetMTime(const CFiTime *mTime) throw() |
817 | { | 897 | { |
818 | if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false; | 898 | if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false; |
819 | return true; | 899 | return true; |
diff --git a/CPP/Windows/FileIO.h b/CPP/Windows/FileIO.h index 22998eb..8050965 100644 --- a/CPP/Windows/FileIO.h +++ b/CPP/Windows/FileIO.h | |||
@@ -30,6 +30,8 @@ | |||
30 | #include "../Common/MyString.h" | 30 | #include "../Common/MyString.h" |
31 | #include "../Common/MyBuffer.h" | 31 | #include "../Common/MyBuffer.h" |
32 | 32 | ||
33 | #include "../Windows/TimeUtils.h" | ||
34 | |||
33 | #include "Defs.h" | 35 | #include "Defs.h" |
34 | 36 | ||
35 | HRESULT GetLastError_noZero_HRESULT(); | 37 | HRESULT GetLastError_noZero_HRESULT(); |
@@ -94,6 +96,12 @@ struct CReparseAttr | |||
94 | UString GetPath() const; | 96 | UString GetPath() const; |
95 | }; | 97 | }; |
96 | 98 | ||
99 | #ifdef _WIN32 | ||
100 | #define CFiInfo BY_HANDLE_FILE_INFORMATION | ||
101 | #define ST_MTIME(st) (st).ftLastWriteTime | ||
102 | #else | ||
103 | #define CFiInfo stat | ||
104 | #endif | ||
97 | 105 | ||
98 | #ifdef _WIN32 | 106 | #ifdef _WIN32 |
99 | 107 | ||
@@ -142,6 +150,8 @@ public: | |||
142 | CFileBase(): _handle(INVALID_HANDLE_VALUE), PreserveATime(false) {}; | 150 | CFileBase(): _handle(INVALID_HANDLE_VALUE), PreserveATime(false) {}; |
143 | ~CFileBase() { Close(); } | 151 | ~CFileBase() { Close(); } |
144 | 152 | ||
153 | HANDLE GetHandle() const { return _handle; } | ||
154 | |||
145 | bool Close() throw(); | 155 | bool Close() throw(); |
146 | 156 | ||
147 | bool GetPosition(UInt64 &position) const throw(); | 157 | bool GetPosition(UInt64 &position) const throw(); |
@@ -213,6 +223,15 @@ public: | |||
213 | 223 | ||
214 | #ifndef UNDER_CE | 224 | #ifndef UNDER_CE |
215 | 225 | ||
226 | bool Open_for_ReadAttributes(CFSTR fileName) | ||
227 | { | ||
228 | return Create(fileName, FILE_READ_ATTRIBUTES, | ||
229 | FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, | ||
230 | OPEN_EXISTING, | ||
231 | FILE_FLAG_BACKUP_SEMANTICS); | ||
232 | // we must use (FILE_FLAG_BACKUP_SEMANTICS) to open handle of directory. | ||
233 | } | ||
234 | |||
216 | bool OpenReparse(CFSTR fileName) | 235 | bool OpenReparse(CFSTR fileName) |
217 | { | 236 | { |
218 | // 17.02 fix: to support Windows XP compatibility junctions: | 237 | // 17.02 fix: to support Windows XP compatibility junctions: |
@@ -240,8 +259,8 @@ public: | |||
240 | bool Create(CFSTR fileName, bool createAlways); | 259 | bool Create(CFSTR fileName, bool createAlways); |
241 | bool CreateAlways(CFSTR fileName, DWORD flagsAndAttributes); | 260 | bool CreateAlways(CFSTR fileName, DWORD flagsAndAttributes); |
242 | 261 | ||
243 | bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw(); | 262 | bool SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw(); |
244 | bool SetMTime(const FILETIME *mTime) throw(); | 263 | bool SetMTime(const CFiTime *mTime) throw(); |
245 | bool WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw(); | 264 | bool WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw(); |
246 | bool Write(const void *data, UInt32 size, UInt32 &processedSize) throw(); | 265 | bool Write(const void *data, UInt32 size, UInt32 &processedSize) throw(); |
247 | bool WriteFull(const void *data, size_t size) throw(); | 266 | bool WriteFull(const void *data, size_t size) throw(); |
@@ -270,6 +289,12 @@ class CFileBase | |||
270 | protected: | 289 | protected: |
271 | int _handle; | 290 | int _handle; |
272 | 291 | ||
292 | /* | ||
293 | bool IsDeviceFile; | ||
294 | bool SizeDefined; | ||
295 | UInt64 Size; // it can be larger than real available size | ||
296 | */ | ||
297 | |||
273 | bool OpenBinary(const char *name, int flags); | 298 | bool OpenBinary(const char *name, int flags); |
274 | public: | 299 | public: |
275 | bool PreserveATime; | 300 | bool PreserveATime; |
@@ -283,6 +308,11 @@ public: | |||
283 | off_t seekToCur() const throw(); | 308 | off_t seekToCur() const throw(); |
284 | // bool SeekToBegin() throw(); | 309 | // bool SeekToBegin() throw(); |
285 | int my_fstat(struct stat *st) const { return fstat(_handle, st); } | 310 | int my_fstat(struct stat *st) const { return fstat(_handle, st); } |
311 | /* | ||
312 | int my_ioctl_BLKGETSIZE64(unsigned long long *val); | ||
313 | int GetDeviceSize_InBytes(UInt64 &size); | ||
314 | void CalcDeviceSize(CFSTR s); | ||
315 | */ | ||
286 | }; | 316 | }; |
287 | 317 | ||
288 | class CInFile: public CFileBase | 318 | class CInFile: public CFileBase |
@@ -301,9 +331,9 @@ class COutFile: public CFileBase | |||
301 | bool ATime_defined; | 331 | bool ATime_defined; |
302 | bool MTime_defined; | 332 | bool MTime_defined; |
303 | 333 | ||
304 | FILETIME CTime; | 334 | CFiTime CTime; |
305 | FILETIME ATime; | 335 | CFiTime ATime; |
306 | FILETIME MTime; | 336 | CFiTime MTime; |
307 | 337 | ||
308 | AString Path; | 338 | AString Path; |
309 | ssize_t write_part(const void *data, size_t size) throw(); | 339 | ssize_t write_part(const void *data, size_t size) throw(); |
@@ -333,8 +363,8 @@ public: | |||
333 | { | 363 | { |
334 | return SetLength(length); | 364 | return SetLength(length); |
335 | } | 365 | } |
336 | bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw(); | 366 | bool SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw(); |
337 | bool SetMTime(const FILETIME *mTime) throw(); | 367 | bool SetMTime(const CFiTime *mTime) throw(); |
338 | }; | 368 | }; |
339 | 369 | ||
340 | } | 370 | } |
diff --git a/CPP/Windows/PropVariant.cpp b/CPP/Windows/PropVariant.cpp index 6e43c7b..2b17950 100644 --- a/CPP/Windows/PropVariant.cpp +++ b/CPP/Windows/PropVariant.cpp | |||
@@ -193,7 +193,7 @@ BSTR CPropVariant::AllocBstr(unsigned numChars) | |||
193 | } | 193 | } |
194 | 194 | ||
195 | #define SET_PROP_id_dest(id, dest) \ | 195 | #define SET_PROP_id_dest(id, dest) \ |
196 | if (vt != id) { InternalClear(); vt = id; } dest = value; | 196 | if (vt != id) { InternalClear(); vt = id; } dest = value; wReserved1 = 0; |
197 | 197 | ||
198 | void CPropVariant::Set_Int32(Int32 value) throw() | 198 | void CPropVariant::Set_Int32(Int32 value) throw() |
199 | { | 199 | { |
@@ -217,67 +217,83 @@ SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart) | |||
217 | // SET_PROP_FUNC(Int64, VT_I8, hVal.QuadPart) | 217 | // SET_PROP_FUNC(Int64, VT_I8, hVal.QuadPart) |
218 | SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime) | 218 | SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime) |
219 | 219 | ||
220 | #define CASE_SIMPLE_VT_VALUES \ | ||
221 | case VT_EMPTY: \ | ||
222 | case VT_BOOL: \ | ||
223 | case VT_FILETIME: \ | ||
224 | case VT_UI8: \ | ||
225 | case VT_UI4: \ | ||
226 | case VT_UI2: \ | ||
227 | case VT_UI1: \ | ||
228 | case VT_I8: \ | ||
229 | case VT_I4: \ | ||
230 | case VT_I2: \ | ||
231 | case VT_I1: \ | ||
232 | case VT_UINT: \ | ||
233 | case VT_INT: \ | ||
234 | case VT_NULL: \ | ||
235 | case VT_ERROR: \ | ||
236 | case VT_R4: \ | ||
237 | case VT_R8: \ | ||
238 | case VT_CY: \ | ||
239 | case VT_DATE: \ | ||
240 | |||
241 | |||
242 | /* | ||
243 | ::VariantClear() and ::VariantCopy() don't work, if (vt == VT_FILETIME) | ||
244 | So we handle VT_FILETIME and another simple types directly | ||
245 | we call system functions for VT_BSTR and for unknown typed | ||
246 | */ | ||
247 | |||
248 | CPropVariant::~CPropVariant() | ||
249 | { | ||
250 | switch ((unsigned)vt) | ||
251 | { | ||
252 | CASE_SIMPLE_VT_VALUES | ||
253 | // vt = VT_EMPTY; // it's optional | ||
254 | return; | ||
255 | } | ||
256 | ::VariantClear((tagVARIANT *)this); | ||
257 | } | ||
258 | |||
220 | HRESULT PropVariant_Clear(PROPVARIANT *prop) throw() | 259 | HRESULT PropVariant_Clear(PROPVARIANT *prop) throw() |
221 | { | 260 | { |
222 | switch (prop->vt) | 261 | switch ((unsigned)prop->vt) |
223 | { | 262 | { |
224 | case VT_EMPTY: | 263 | CASE_SIMPLE_VT_VALUES |
225 | case VT_UI1: | ||
226 | case VT_I1: | ||
227 | case VT_I2: | ||
228 | case VT_UI2: | ||
229 | case VT_BOOL: | ||
230 | case VT_I4: | ||
231 | case VT_UI4: | ||
232 | case VT_R4: | ||
233 | case VT_INT: | ||
234 | case VT_UINT: | ||
235 | case VT_ERROR: | ||
236 | case VT_FILETIME: | ||
237 | case VT_UI8: | ||
238 | case VT_R8: | ||
239 | case VT_CY: | ||
240 | case VT_DATE: | ||
241 | prop->vt = VT_EMPTY; | 264 | prop->vt = VT_EMPTY; |
242 | prop->wReserved1 = 0; | 265 | break; |
243 | prop->wReserved2 = 0; | 266 | default: |
244 | prop->wReserved3 = 0; | 267 | { |
245 | prop->uhVal.QuadPart = 0; | 268 | const HRESULT res = ::VariantClear((VARIANTARG *)prop); |
246 | return S_OK; | 269 | if (res != S_OK || prop->vt != VT_EMPTY) |
270 | return res; | ||
271 | break; | ||
272 | } | ||
247 | } | 273 | } |
248 | return ::VariantClear((VARIANTARG *)prop); | 274 | prop->wReserved1 = 0; |
249 | // return ::PropVariantClear(prop); | 275 | prop->wReserved2 = 0; |
250 | // PropVariantClear can clear VT_BLOB. | 276 | prop->wReserved3 = 0; |
277 | prop->uhVal.QuadPart = 0; | ||
278 | return S_OK; | ||
251 | } | 279 | } |
252 | 280 | ||
253 | HRESULT CPropVariant::Clear() throw() | 281 | HRESULT CPropVariant::Clear() throw() |
254 | { | 282 | { |
255 | if (vt == VT_EMPTY) | 283 | if (vt == VT_EMPTY) |
284 | { | ||
285 | wReserved1 = 0; | ||
256 | return S_OK; | 286 | return S_OK; |
287 | } | ||
257 | return PropVariant_Clear(this); | 288 | return PropVariant_Clear(this); |
258 | } | 289 | } |
259 | 290 | ||
260 | HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) throw() | 291 | HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) throw() |
261 | { | 292 | { |
262 | ::VariantClear((tagVARIANT *)this); | 293 | Clear(); |
263 | switch (pSrc->vt) | 294 | switch ((unsigned)pSrc->vt) |
264 | { | 295 | { |
265 | case VT_UI1: | 296 | CASE_SIMPLE_VT_VALUES |
266 | case VT_I1: | ||
267 | case VT_I2: | ||
268 | case VT_UI2: | ||
269 | case VT_BOOL: | ||
270 | case VT_I4: | ||
271 | case VT_UI4: | ||
272 | case VT_R4: | ||
273 | case VT_INT: | ||
274 | case VT_UINT: | ||
275 | case VT_ERROR: | ||
276 | case VT_FILETIME: | ||
277 | case VT_UI8: | ||
278 | case VT_R8: | ||
279 | case VT_CY: | ||
280 | case VT_DATE: | ||
281 | memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT)); | 297 | memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT)); |
282 | return S_OK; | 298 | return S_OK; |
283 | } | 299 | } |
@@ -287,12 +303,13 @@ HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) throw() | |||
287 | 303 | ||
288 | HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) throw() | 304 | HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) throw() |
289 | { | 305 | { |
290 | HRESULT hr = Clear(); | 306 | const HRESULT hr = Clear(); |
291 | if (FAILED(hr)) | 307 | if (FAILED(hr)) |
292 | return hr; | 308 | return hr; |
293 | // memcpy((PROPVARIANT *)this, pSrc, sizeof(PROPVARIANT)); | 309 | // memcpy((PROPVARIANT *)this, pSrc, sizeof(PROPVARIANT)); |
294 | *(PROPVARIANT *)this = *pSrc; | 310 | *(PROPVARIANT *)this = *pSrc; |
295 | pSrc->vt = VT_EMPTY; | 311 | pSrc->vt = VT_EMPTY; |
312 | pSrc->wReserved1 = 0; | ||
296 | return S_OK; | 313 | return S_OK; |
297 | } | 314 | } |
298 | 315 | ||
@@ -300,21 +317,25 @@ HRESULT CPropVariant::Detach(PROPVARIANT *pDest) throw() | |||
300 | { | 317 | { |
301 | if (pDest->vt != VT_EMPTY) | 318 | if (pDest->vt != VT_EMPTY) |
302 | { | 319 | { |
303 | HRESULT hr = PropVariant_Clear(pDest); | 320 | const HRESULT hr = PropVariant_Clear(pDest); |
304 | if (FAILED(hr)) | 321 | if (FAILED(hr)) |
305 | return hr; | 322 | return hr; |
306 | } | 323 | } |
307 | // memcpy(pDest, this, sizeof(PROPVARIANT)); | 324 | // memcpy(pDest, this, sizeof(PROPVARIANT)); |
308 | *pDest = *(PROPVARIANT *)this; | 325 | *pDest = *(PROPVARIANT *)this; |
309 | vt = VT_EMPTY; | 326 | vt = VT_EMPTY; |
327 | wReserved1 = 0; | ||
310 | return S_OK; | 328 | return S_OK; |
311 | } | 329 | } |
312 | 330 | ||
313 | HRESULT CPropVariant::InternalClear() throw() | 331 | HRESULT CPropVariant::InternalClear() throw() |
314 | { | 332 | { |
315 | if (vt == VT_EMPTY) | 333 | if (vt == VT_EMPTY) |
334 | { | ||
335 | wReserved1 = 0; | ||
316 | return S_OK; | 336 | return S_OK; |
317 | HRESULT hr = Clear(); | 337 | } |
338 | const HRESULT hr = Clear(); | ||
318 | if (FAILED(hr)) | 339 | if (FAILED(hr)) |
319 | { | 340 | { |
320 | vt = VT_ERROR; | 341 | vt = VT_ERROR; |
@@ -325,7 +346,7 @@ HRESULT CPropVariant::InternalClear() throw() | |||
325 | 346 | ||
326 | void CPropVariant::InternalCopy(const PROPVARIANT *pSrc) | 347 | void CPropVariant::InternalCopy(const PROPVARIANT *pSrc) |
327 | { | 348 | { |
328 | HRESULT hr = Copy(pSrc); | 349 | const HRESULT hr = Copy(pSrc); |
329 | if (FAILED(hr)) | 350 | if (FAILED(hr)) |
330 | { | 351 | { |
331 | if (hr == E_OUTOFMEMORY) | 352 | if (hr == E_OUTOFMEMORY) |
@@ -335,11 +356,12 @@ void CPropVariant::InternalCopy(const PROPVARIANT *pSrc) | |||
335 | } | 356 | } |
336 | } | 357 | } |
337 | 358 | ||
359 | |||
338 | int CPropVariant::Compare(const CPropVariant &a) throw() | 360 | int CPropVariant::Compare(const CPropVariant &a) throw() |
339 | { | 361 | { |
340 | if (vt != a.vt) | 362 | if (vt != a.vt) |
341 | return MyCompare(vt, a.vt); | 363 | return MyCompare(vt, a.vt); |
342 | switch (vt) | 364 | switch ((unsigned)vt) |
343 | { | 365 | { |
344 | case VT_EMPTY: return 0; | 366 | case VT_EMPTY: return 0; |
345 | // case VT_I1: return MyCompare(cVal, a.cVal); | 367 | // case VT_I1: return MyCompare(cVal, a.cVal); |
@@ -352,7 +374,15 @@ int CPropVariant::Compare(const CPropVariant &a) throw() | |||
352 | case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart); | 374 | case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart); |
353 | case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart); | 375 | case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart); |
354 | case VT_BOOL: return -MyCompare(boolVal, a.boolVal); | 376 | case VT_BOOL: return -MyCompare(boolVal, a.boolVal); |
355 | case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime); | 377 | case VT_FILETIME: |
378 | { | ||
379 | const int res = CompareFileTime(&filetime, &a.filetime); | ||
380 | if (res != 0) | ||
381 | return res; | ||
382 | const unsigned v1 = Get_Ns100(); | ||
383 | const unsigned v2 = a.Get_Ns100(); | ||
384 | return MyCompare(v1, v2); | ||
385 | } | ||
356 | case VT_BSTR: return 0; // Not implemented | 386 | case VT_BSTR: return 0; // Not implemented |
357 | default: return 0; | 387 | default: return 0; |
358 | } | 388 | } |
diff --git a/CPP/Windows/PropVariant.h b/CPP/Windows/PropVariant.h index 108bf6b..171402f 100644 --- a/CPP/Windows/PropVariant.h +++ b/CPP/Windows/PropVariant.h | |||
@@ -29,11 +29,14 @@ inline void PropVarEm_Set_UInt64(PROPVARIANT *p, UInt64 v) throw() | |||
29 | p->uhVal.QuadPart = v; | 29 | p->uhVal.QuadPart = v; |
30 | } | 30 | } |
31 | 31 | ||
32 | inline void PropVarEm_Set_FileTime64(PROPVARIANT *p, UInt64 v) throw() | 32 | inline void PropVarEm_Set_FileTime64_Prec(PROPVARIANT *p, UInt64 v, unsigned prec) throw() |
33 | { | 33 | { |
34 | p->vt = VT_FILETIME; | 34 | p->vt = VT_FILETIME; |
35 | p->filetime.dwLowDateTime = (DWORD)v; | 35 | p->filetime.dwLowDateTime = (DWORD)v; |
36 | p->filetime.dwHighDateTime = (DWORD)(v >> 32); | 36 | p->filetime.dwHighDateTime = (DWORD)(v >> 32); |
37 | p->wReserved1 = (WORD)prec; | ||
38 | p->wReserved2 = 0; | ||
39 | p->wReserved3 = 0; | ||
37 | } | 40 | } |
38 | 41 | ||
39 | inline void PropVarEm_Set_Bool(PROPVARIANT *p, bool b) throw() | 42 | inline void PropVarEm_Set_Bool(PROPVARIANT *p, bool b) throw() |
@@ -63,7 +66,51 @@ public: | |||
63 | // uhVal.QuadPart = 0; | 66 | // uhVal.QuadPart = 0; |
64 | bstrVal = 0; | 67 | bstrVal = 0; |
65 | } | 68 | } |
66 | ~CPropVariant() throw() { Clear(); } | 69 | |
70 | |||
71 | void Set_FtPrec(unsigned prec) | ||
72 | { | ||
73 | wReserved1 = (WORD)prec; | ||
74 | wReserved2 = 0; | ||
75 | wReserved3 = 0; | ||
76 | } | ||
77 | |||
78 | void SetAsTimeFrom_FT_Prec(const FILETIME &ft, unsigned prec) | ||
79 | { | ||
80 | operator=(ft); | ||
81 | Set_FtPrec(prec); | ||
82 | } | ||
83 | |||
84 | void SetAsTimeFrom_Ft64_Prec(UInt64 v, unsigned prec) | ||
85 | { | ||
86 | FILETIME ft; | ||
87 | ft.dwLowDateTime = (DWORD)(UInt32)v; | ||
88 | ft.dwHighDateTime = (DWORD)(UInt32)(v >> 32); | ||
89 | operator=(ft); | ||
90 | Set_FtPrec(prec); | ||
91 | } | ||
92 | |||
93 | void SetAsTimeFrom_FT_Prec_Ns100(const FILETIME &ft, unsigned prec, unsigned ns100) | ||
94 | { | ||
95 | operator=(ft); | ||
96 | wReserved1 = (WORD)prec; | ||
97 | wReserved2 = (WORD)ns100; | ||
98 | wReserved3 = 0; | ||
99 | } | ||
100 | |||
101 | unsigned Get_Ns100() const | ||
102 | { | ||
103 | const unsigned prec = wReserved1; | ||
104 | const unsigned ns100 = wReserved2; | ||
105 | if (prec == 0 | ||
106 | && prec <= k_PropVar_TimePrec_1ns | ||
107 | && ns100 < 100 | ||
108 | && wReserved3 == 0) | ||
109 | return ns100; | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | ~CPropVariant(); | ||
67 | CPropVariant(const PROPVARIANT &varSrc); | 114 | CPropVariant(const PROPVARIANT &varSrc); |
68 | CPropVariant(const CPropVariant &varSrc); | 115 | CPropVariant(const CPropVariant &varSrc); |
69 | CPropVariant(BSTR bstrSrc); | 116 | CPropVariant(BSTR bstrSrc); |
@@ -118,7 +165,6 @@ public: | |||
118 | 165 | ||
119 | HRESULT InternalClear() throw(); | 166 | HRESULT InternalClear() throw(); |
120 | void InternalCopy(const PROPVARIANT *pSrc); | 167 | void InternalCopy(const PROPVARIANT *pSrc); |
121 | |||
122 | int Compare(const CPropVariant &a) throw(); | 168 | int Compare(const CPropVariant &a) throw(); |
123 | }; | 169 | }; |
124 | 170 | ||
diff --git a/CPP/Windows/PropVariantConv.cpp b/CPP/Windows/PropVariantConv.cpp index b58d37e..3c9bbd1 100644 --- a/CPP/Windows/PropVariantConv.cpp +++ b/CPP/Windows/PropVariantConv.cpp | |||
@@ -9,7 +9,7 @@ | |||
9 | 9 | ||
10 | #define UINT_TO_STR_2(c, val) { s[0] = (c); s[1] = (char)('0' + (val) / 10); s[2] = (char)('0' + (val) % 10); s += 3; } | 10 | #define UINT_TO_STR_2(c, val) { s[0] = (c); s[1] = (char)('0' + (val) / 10); s[2] = (char)('0' + (val) % 10); s += 3; } |
11 | 11 | ||
12 | bool ConvertUtcFileTimeToString(const FILETIME &utc, char *s, int level) throw() | 12 | bool ConvertUtcFileTimeToString2(const FILETIME &utc, unsigned ns100, char *s, int level) throw() |
13 | { | 13 | { |
14 | *s = 0; | 14 | *s = 0; |
15 | FILETIME ft; | 15 | FILETIME ft; |
@@ -18,7 +18,10 @@ bool ConvertUtcFileTimeToString(const FILETIME &utc, char *s, int level) throw() | |||
18 | 18 | ||
19 | SYSTEMTIME st; | 19 | SYSTEMTIME st; |
20 | if (!BOOLToBool(FileTimeToSystemTime(&ft, &st))) | 20 | if (!BOOLToBool(FileTimeToSystemTime(&ft, &st))) |
21 | { | ||
22 | // win10 : that function doesn't work, if bit 63 of 64-bit FILETIME is set. | ||
21 | return false; | 23 | return false; |
24 | } | ||
22 | 25 | ||
23 | { | 26 | { |
24 | unsigned val = st.wYear; | 27 | unsigned val = st.wYear; |
@@ -71,6 +74,12 @@ bool ConvertUtcFileTimeToString(const FILETIME &utc, char *s, int level) throw() | |||
71 | numDigits = (unsigned)level; | 74 | numDigits = (unsigned)level; |
72 | s += numDigits; | 75 | s += numDigits; |
73 | } | 76 | } |
77 | if (level >= kTimestampPrintLevel_NTFS + 1) | ||
78 | { | ||
79 | *s++ = (char)('0' + (ns100 / 10)); | ||
80 | if (level >= kTimestampPrintLevel_NTFS + 2) | ||
81 | *s++ = (char)('0' + (ns100 % 10)); | ||
82 | } | ||
74 | } | 83 | } |
75 | } | 84 | } |
76 | } | 85 | } |
@@ -80,6 +89,25 @@ bool ConvertUtcFileTimeToString(const FILETIME &utc, char *s, int level) throw() | |||
80 | } | 89 | } |
81 | 90 | ||
82 | 91 | ||
92 | bool ConvertUtcFileTimeToString(const FILETIME &utc, char *s, int level) throw() | ||
93 | { | ||
94 | return ConvertUtcFileTimeToString2(utc, 0, s, level); | ||
95 | } | ||
96 | |||
97 | bool ConvertUtcFileTimeToString2(const FILETIME &ft, unsigned ns100, wchar_t *dest, int level) throw() | ||
98 | { | ||
99 | char s[32]; | ||
100 | bool res = ConvertUtcFileTimeToString2(ft, ns100, s, level); | ||
101 | for (unsigned i = 0;; i++) | ||
102 | { | ||
103 | Byte c = (Byte)s[i]; | ||
104 | dest[i] = c; | ||
105 | if (c == 0) | ||
106 | break; | ||
107 | } | ||
108 | return res; | ||
109 | } | ||
110 | |||
83 | bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *dest, int level) throw() | 111 | bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *dest, int level) throw() |
84 | { | 112 | { |
85 | char s[32]; | 113 | char s[32]; |
@@ -106,7 +134,19 @@ void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw( | |||
106 | case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return; | 134 | case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return; |
107 | case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return; | 135 | case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return; |
108 | case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return; | 136 | case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return; |
109 | case VT_FILETIME: ConvertUtcFileTimeToString(prop.filetime, dest); return; | 137 | case VT_FILETIME: |
138 | { | ||
139 | // const unsigned prec = prop.wReserved1; | ||
140 | int level = 0; | ||
141 | /* | ||
142 | if (prec == 0) | ||
143 | level = 7; | ||
144 | else if (prec > 16 && prec <= 16 + 9) | ||
145 | level = prec - 16; | ||
146 | */ | ||
147 | ConvertUtcFileTimeToString(prop.filetime, dest, level); | ||
148 | return; | ||
149 | } | ||
110 | // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return; | 150 | // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return; |
111 | case VT_I2: ConvertInt64ToString(prop.iVal, dest); return; | 151 | case VT_I2: ConvertInt64ToString(prop.iVal, dest); return; |
112 | case VT_I4: ConvertInt64ToString(prop.lVal, dest); return; | 152 | case VT_I4: ConvertInt64ToString(prop.lVal, dest); return; |
@@ -127,7 +167,19 @@ void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) thr | |||
127 | case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return; | 167 | case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return; |
128 | case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return; | 168 | case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return; |
129 | case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return; | 169 | case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return; |
130 | case VT_FILETIME: ConvertUtcFileTimeToString(prop.filetime, dest); return; | 170 | case VT_FILETIME: |
171 | { | ||
172 | // const unsigned prec = prop.wReserved1; | ||
173 | int level = 0; | ||
174 | /* | ||
175 | if (prec == 0) | ||
176 | level = 7; | ||
177 | else if (prec > 16 && prec <= 16 + 9) | ||
178 | level = prec - 16; | ||
179 | */ | ||
180 | ConvertUtcFileTimeToString(prop.filetime, dest, level); | ||
181 | return; | ||
182 | } | ||
131 | // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return; | 183 | // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return; |
132 | case VT_I2: ConvertInt64ToString(prop.iVal, dest); return; | 184 | case VT_I2: ConvertInt64ToString(prop.iVal, dest); return; |
133 | case VT_I4: ConvertInt64ToString(prop.lVal, dest); return; | 185 | case VT_I4: ConvertInt64ToString(prop.lVal, dest); return; |
diff --git a/CPP/Windows/PropVariantConv.h b/CPP/Windows/PropVariantConv.h index 390e0b8..6067784 100644 --- a/CPP/Windows/PropVariantConv.h +++ b/CPP/Windows/PropVariantConv.h | |||
@@ -10,11 +10,14 @@ | |||
10 | #define kTimestampPrintLevel_DAY -3 | 10 | #define kTimestampPrintLevel_DAY -3 |
11 | // #define kTimestampPrintLevel_HOUR -2 | 11 | // #define kTimestampPrintLevel_HOUR -2 |
12 | #define kTimestampPrintLevel_MIN -1 | 12 | #define kTimestampPrintLevel_MIN -1 |
13 | #define kTimestampPrintLevel_SEC 0 | 13 | #define kTimestampPrintLevel_SEC 0 |
14 | #define kTimestampPrintLevel_NTFS 7 | 14 | #define kTimestampPrintLevel_NTFS 7 |
15 | #define kTimestampPrintLevel_NS 9 | ||
15 | 16 | ||
16 | bool ConvertUtcFileTimeToString(const FILETIME &ft, char *s, int level = kTimestampPrintLevel_SEC) throw(); | 17 | bool ConvertUtcFileTimeToString(const FILETIME &ft, char *s, int level = kTimestampPrintLevel_SEC) throw(); |
17 | bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *s, int level = kTimestampPrintLevel_SEC) throw(); | 18 | bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *s, int level = kTimestampPrintLevel_SEC) throw(); |
19 | bool ConvertUtcFileTimeToString2(const FILETIME &ft, unsigned ns100, char *s, int level = kTimestampPrintLevel_SEC) throw(); | ||
20 | bool ConvertUtcFileTimeToString2(const FILETIME &ft, unsigned ns100, wchar_t *s, int level = kTimestampPrintLevel_SEC) throw(); | ||
18 | 21 | ||
19 | // provide at least 32 bytes for buffer including zero-end | 22 | // provide at least 32 bytes for buffer including zero-end |
20 | // don't send VT_BSTR to these functions | 23 | // don't send VT_BSTR to these functions |
diff --git a/CPP/Windows/SecurityUtils.cpp b/CPP/Windows/SecurityUtils.cpp index 640c90d..8a7f45c 100644 --- a/CPP/Windows/SecurityUtils.cpp +++ b/CPP/Windows/SecurityUtils.cpp | |||
@@ -2,8 +2,6 @@ | |||
2 | 2 | ||
3 | #include "StdAfx.h" | 3 | #include "StdAfx.h" |
4 | 4 | ||
5 | #include "../Common/MyString.h" | ||
6 | |||
7 | #include "SecurityUtils.h" | 5 | #include "SecurityUtils.h" |
8 | 6 | ||
9 | namespace NWindows { | 7 | namespace NWindows { |
diff --git a/CPP/Windows/TimeUtils.cpp b/CPP/Windows/TimeUtils.cpp index 1f1335f..77d2c51 100644 --- a/CPP/Windows/TimeUtils.cpp +++ b/CPP/Windows/TimeUtils.cpp | |||
@@ -22,7 +22,7 @@ static const UInt64 kUnixTimeOffset = | |||
22 | (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); | 22 | (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); |
23 | static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond; | 23 | static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond; |
24 | 24 | ||
25 | bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft) throw() | 25 | bool DosTime_To_FileTime(UInt32 dosTime, FILETIME &ft) throw() |
26 | { | 26 | { |
27 | #if defined(_WIN32) && !defined(UNDER_CE) | 27 | #if defined(_WIN32) && !defined(UNDER_CE) |
28 | return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &ft)); | 28 | return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &ft)); |
@@ -43,7 +43,7 @@ bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft) throw() | |||
43 | static const UInt32 kHighDosTime = 0xFF9FBF7D; | 43 | static const UInt32 kHighDosTime = 0xFF9FBF7D; |
44 | static const UInt32 kLowDosTime = 0x210000; | 44 | static const UInt32 kLowDosTime = 0x210000; |
45 | 45 | ||
46 | bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime) throw() | 46 | bool FileTime_To_DosTime(const FILETIME &ft, UInt32 &dosTime) throw() |
47 | { | 47 | { |
48 | #if defined(_WIN32) && !defined(UNDER_CE) | 48 | #if defined(_WIN32) && !defined(UNDER_CE) |
49 | 49 | ||
@@ -121,49 +121,86 @@ bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime) throw() | |||
121 | return true; | 121 | return true; |
122 | } | 122 | } |
123 | 123 | ||
124 | UInt64 UnixTimeToFileTime64(UInt32 unixTime) throw() | 124 | |
125 | bool UtcFileTime_To_LocalDosTime(const FILETIME &utc, UInt32 &dosTime) throw() | ||
126 | { | ||
127 | FILETIME loc = { 0, 0 }; | ||
128 | const UInt64 u1 = FILETIME_To_UInt64(utc); | ||
129 | const UInt64 kDelta = ((UInt64)1 << 41); // it's larger than quantums in 1 sec. | ||
130 | if (u1 >= kDelta) | ||
131 | { | ||
132 | if (!FileTimeToLocalFileTime(&utc, &loc)) | ||
133 | loc = utc; | ||
134 | else | ||
135 | { | ||
136 | const UInt64 u2 = FILETIME_To_UInt64(loc); | ||
137 | const UInt64 delta = u1 < u2 ? (u2 - u1) : (u1 - u2); | ||
138 | if (delta > kDelta) // if FileTimeToLocalFileTime() overflow, we use UTC time | ||
139 | loc = utc; | ||
140 | } | ||
141 | } | ||
142 | return FileTime_To_DosTime(loc, dosTime); | ||
143 | } | ||
144 | |||
145 | UInt64 UnixTime_To_FileTime64(UInt32 unixTime) throw() | ||
125 | { | 146 | { |
126 | return (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond; | 147 | return (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond; |
127 | } | 148 | } |
128 | 149 | ||
129 | void UnixTimeToFileTime(UInt32 unixTime, FILETIME &ft) throw() | 150 | void UnixTime_To_FileTime(UInt32 unixTime, FILETIME &ft) throw() |
130 | { | 151 | { |
131 | UInt64 v = UnixTimeToFileTime64(unixTime); | 152 | const UInt64 v = UnixTime_To_FileTime64(unixTime); |
132 | ft.dwLowDateTime = (DWORD)v; | 153 | ft.dwLowDateTime = (DWORD)v; |
133 | ft.dwHighDateTime = (DWORD)(v >> 32); | 154 | ft.dwHighDateTime = (DWORD)(v >> 32); |
134 | } | 155 | } |
135 | 156 | ||
136 | UInt64 UnixTime64ToFileTime64(Int64 unixTime) throw() | 157 | UInt64 UnixTime64_To_FileTime64(Int64 unixTime) throw() |
137 | { | 158 | { |
138 | return (UInt64)((Int64)kUnixTimeOffset + unixTime) * kNumTimeQuantumsInSecond; | 159 | return (UInt64)((Int64)kUnixTimeOffset + unixTime) * kNumTimeQuantumsInSecond; |
139 | } | 160 | } |
140 | 161 | ||
141 | bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &ft) throw() | 162 | |
163 | bool UnixTime64_To_FileTime64(Int64 unixTime, UInt64 &fileTime) throw() | ||
142 | { | 164 | { |
143 | if (unixTime > (Int64)(kNumSecondsInFileTime - kUnixTimeOffset)) | 165 | if (unixTime > (Int64)(kNumSecondsInFileTime - kUnixTimeOffset)) |
144 | { | 166 | { |
145 | ft.dwLowDateTime = ft.dwHighDateTime = (UInt32)(Int32)-1; | 167 | fileTime = (UInt64)(Int64)-1; |
146 | return false; | 168 | return false; |
147 | } | 169 | } |
148 | Int64 v = (Int64)kUnixTimeOffset + unixTime; | 170 | if (unixTime < -(Int64)kUnixTimeOffset) |
149 | if (v < 0) | ||
150 | { | 171 | { |
151 | ft.dwLowDateTime = ft.dwHighDateTime = 0; | 172 | fileTime = 0; |
152 | return false; | 173 | return false; |
153 | } | 174 | } |
154 | UInt64 v2 = (UInt64)v * kNumTimeQuantumsInSecond; | 175 | fileTime = UnixTime64_To_FileTime64(unixTime); |
155 | ft.dwLowDateTime = (DWORD)v2; | ||
156 | ft.dwHighDateTime = (DWORD)(v2 >> 32); | ||
157 | return true; | 176 | return true; |
158 | } | 177 | } |
159 | 178 | ||
160 | Int64 FileTimeToUnixTime64(const FILETIME &ft) throw() | 179 | |
180 | bool UnixTime64_To_FileTime(Int64 unixTime, FILETIME &ft) throw() | ||
161 | { | 181 | { |
162 | UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; | 182 | UInt64 v; |
183 | const bool res = UnixTime64_To_FileTime64(unixTime, v); | ||
184 | ft.dwLowDateTime = (DWORD)v; | ||
185 | ft.dwHighDateTime = (DWORD)(v >> 32); | ||
186 | return res; | ||
187 | } | ||
188 | |||
189 | |||
190 | Int64 FileTime_To_UnixTime64(const FILETIME &ft) throw() | ||
191 | { | ||
192 | const UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; | ||
193 | return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset; | ||
194 | } | ||
195 | |||
196 | Int64 FileTime_To_UnixTime64_and_Quantums(const FILETIME &ft, UInt32 &quantums) throw() | ||
197 | { | ||
198 | const UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; | ||
199 | quantums = (UInt32)(winTime % kNumTimeQuantumsInSecond); | ||
163 | return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset; | 200 | return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset; |
164 | } | 201 | } |
165 | 202 | ||
166 | bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime) throw() | 203 | bool FileTime_To_UnixTime(const FILETIME &ft, UInt32 &unixTime) throw() |
167 | { | 204 | { |
168 | UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; | 205 | UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; |
169 | winTime /= kNumTimeQuantumsInSecond; | 206 | winTime /= kNumTimeQuantumsInSecond; |
@@ -173,9 +210,9 @@ bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime) throw() | |||
173 | return false; | 210 | return false; |
174 | } | 211 | } |
175 | winTime -= kUnixTimeOffset; | 212 | winTime -= kUnixTimeOffset; |
176 | if (winTime > 0xFFFFFFFF) | 213 | if (winTime > (UInt32)0xFFFFFFFF) |
177 | { | 214 | { |
178 | unixTime = 0xFFFFFFFF; | 215 | unixTime = (UInt32)0xFFFFFFFF; |
179 | return false; | 216 | return false; |
180 | } | 217 | } |
181 | unixTime = (UInt32)winTime; | 218 | unixTime = (UInt32)winTime; |
@@ -202,12 +239,13 @@ bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, | |||
202 | return true; | 239 | return true; |
203 | } | 240 | } |
204 | 241 | ||
205 | void GetCurUtcFileTime(FILETIME &ft) throw() | 242 | |
243 | void GetCurUtc_FiTime(CFiTime &ft) throw() | ||
206 | { | 244 | { |
245 | #ifdef _WIN32 | ||
246 | |||
207 | // Both variants provide same low resolution on WinXP: about 15 ms. | 247 | // Both variants provide same low resolution on WinXP: about 15 ms. |
208 | // But GetSystemTimeAsFileTime is much faster. | 248 | // But GetSystemTimeAsFileTime is much faster. |
209 | #ifdef _WIN32 | ||
210 | |||
211 | #ifdef UNDER_CE | 249 | #ifdef UNDER_CE |
212 | SYSTEMTIME st; | 250 | SYSTEMTIME st; |
213 | GetSystemTime(&st); | 251 | GetSystemTime(&st); |
@@ -216,8 +254,22 @@ void GetCurUtcFileTime(FILETIME &ft) throw() | |||
216 | GetSystemTimeAsFileTime(&ft); | 254 | GetSystemTimeAsFileTime(&ft); |
217 | #endif | 255 | #endif |
218 | 256 | ||
219 | #else | 257 | #else |
220 | 258 | ||
259 | FiTime_Clear(ft); | ||
260 | struct timeval now; | ||
261 | if (gettimeofday(&now, 0 ) == 0) | ||
262 | { | ||
263 | ft.tv_sec = now.tv_sec; | ||
264 | ft.tv_nsec = now.tv_usec * 1000; | ||
265 | } | ||
266 | |||
267 | #endif | ||
268 | } | ||
269 | |||
270 | #ifndef _WIN32 | ||
271 | void GetCurUtcFileTime(FILETIME &ft) throw() | ||
272 | { | ||
221 | UInt64 v = 0; | 273 | UInt64 v = 0; |
222 | struct timeval now; | 274 | struct timeval now; |
223 | if (gettimeofday(&now, 0 ) == 0) | 275 | if (gettimeofday(&now, 0 ) == 0) |
@@ -227,8 +279,126 @@ void GetCurUtcFileTime(FILETIME &ft) throw() | |||
227 | } | 279 | } |
228 | ft.dwLowDateTime = (DWORD)v; | 280 | ft.dwLowDateTime = (DWORD)v; |
229 | ft.dwHighDateTime = (DWORD)(v >> 32); | 281 | ft.dwHighDateTime = (DWORD)(v >> 32); |
230 | |||
231 | #endif | ||
232 | } | 282 | } |
283 | #endif | ||
284 | |||
233 | 285 | ||
234 | }} | 286 | }} |
287 | |||
288 | |||
289 | #ifdef _WIN32 | ||
290 | |||
291 | /* | ||
292 | void FiTime_Normalize_With_Prec(CFiTime &ft, unsigned prec) | ||
293 | { | ||
294 | if (prec == k_PropVar_TimePrec_0 | ||
295 | || prec == k_PropVar_TimePrec_HighPrec | ||
296 | || prec >= k_PropVar_TimePrec_100ns) | ||
297 | return; | ||
298 | UInt64 v = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; | ||
299 | |||
300 | int numDigits = (int)prec - (int)k_PropVar_TimePrec_Base; | ||
301 | UInt32 d; | ||
302 | if (prec == k_PropVar_TimePrec_DOS) | ||
303 | { | ||
304 | // we round up as windows DosDateTimeToFileTime() | ||
305 | v += NWindows::NTime::kNumTimeQuantumsInSecond * 2 - 1; | ||
306 | d = NWindows::NTime::kNumTimeQuantumsInSecond * 2; | ||
307 | } | ||
308 | else | ||
309 | { | ||
310 | if (prec == k_PropVar_TimePrec_Unix) | ||
311 | numDigits = 0; | ||
312 | else if (numDigits < 0) | ||
313 | return; | ||
314 | d = 1; | ||
315 | for (unsigned k = numDigits; k < 7; k++) | ||
316 | d *= 10; | ||
317 | } | ||
318 | v /= d; | ||
319 | v *= d; | ||
320 | ft.dwLowDateTime = (DWORD)v; | ||
321 | ft.dwHighDateTime = (DWORD)(v >> 32); | ||
322 | } | ||
323 | */ | ||
324 | |||
325 | #else | ||
326 | |||
327 | /* | ||
328 | void FiTime_Normalize_With_Prec(CFiTime &ft, unsigned prec) | ||
329 | { | ||
330 | if (prec >= k_PropVar_TimePrec_1ns | ||
331 | || prec == k_PropVar_TimePrec_HighPrec) | ||
332 | return; | ||
333 | |||
334 | int numDigits = (int)prec - (int)k_PropVar_TimePrec_Base; | ||
335 | UInt32 d; | ||
336 | if (prec == k_PropVar_TimePrec_Unix || | ||
337 | prec == (int)k_PropVar_TimePrec_Base) | ||
338 | { | ||
339 | ft.tv_nsec = 0; | ||
340 | return; | ||
341 | } | ||
342 | if (prec == k_PropVar_TimePrec_DOS) | ||
343 | { | ||
344 | // we round up as windows DosDateTimeToFileTime() | ||
345 | const unsigned sec1 = (ft.tv_sec & 1); | ||
346 | if (ft.tv_nsec == 0 && sec1 == 0) | ||
347 | return; | ||
348 | ft.tv_nsec = 0; | ||
349 | ft.tv_sec += 2 - sec1; | ||
350 | return; | ||
351 | } | ||
352 | { | ||
353 | if (prec == k_PropVar_TimePrec_0 | ||
354 | || numDigits < 0) | ||
355 | numDigits = 7; | ||
356 | d = 1; | ||
357 | for (unsigned k = numDigits; k < 9; k++) | ||
358 | d *= 10; | ||
359 | ft.tv_nsec /= d; | ||
360 | ft.tv_nsec *= d; | ||
361 | } | ||
362 | } | ||
363 | */ | ||
364 | |||
365 | int Compare_FiTime(const CFiTime *a1, const CFiTime *a2) | ||
366 | { | ||
367 | if (a1->tv_sec < a2->tv_sec) return -1; | ||
368 | if (a1->tv_sec > a2->tv_sec) return 1; | ||
369 | if (a1->tv_nsec < a2->tv_nsec) return -1; | ||
370 | if (a1->tv_nsec > a2->tv_nsec) return 1; | ||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | bool FILETIME_To_timespec(const FILETIME &ft, timespec &ts) | ||
375 | { | ||
376 | UInt32 quantums; | ||
377 | const Int64 sec = NWindows::NTime::FileTime_To_UnixTime64_and_Quantums(ft, quantums); | ||
378 | // time_t is long | ||
379 | const time_t sec2 = (time_t)sec; | ||
380 | if (sec2 == sec) | ||
381 | { | ||
382 | ts.tv_sec = sec2; | ||
383 | ts.tv_nsec = (long)(quantums * 100); | ||
384 | return true; | ||
385 | } | ||
386 | return false; | ||
387 | } | ||
388 | |||
389 | void FiTime_To_FILETIME_ns100(const CFiTime &ts, FILETIME &ft, unsigned &ns100) | ||
390 | { | ||
391 | const UInt64 v = NWindows::NTime::UnixTime64_To_FileTime64(ts.tv_sec) + ((UInt64)ts.tv_nsec / 100); | ||
392 | ns100 = (unsigned)((UInt64)ts.tv_nsec % 100); | ||
393 | ft.dwLowDateTime = (DWORD)v; | ||
394 | ft.dwHighDateTime = (DWORD)(v >> 32); | ||
395 | } | ||
396 | |||
397 | void FiTime_To_FILETIME(const CFiTime &ts, FILETIME &ft) | ||
398 | { | ||
399 | const UInt64 v = NWindows::NTime::UnixTime64_To_FileTime64(ts.tv_sec) + ((UInt64)ts.tv_nsec / 100); | ||
400 | ft.dwLowDateTime = (DWORD)v; | ||
401 | ft.dwHighDateTime = (DWORD)(v >> 32); | ||
402 | } | ||
403 | |||
404 | #endif | ||
diff --git a/CPP/Windows/TimeUtils.h b/CPP/Windows/TimeUtils.h index d1d8c15..60ee739 100644 --- a/CPP/Windows/TimeUtils.h +++ b/CPP/Windows/TimeUtils.h | |||
@@ -5,28 +5,142 @@ | |||
5 | 5 | ||
6 | #include "../Common/MyTypes.h" | 6 | #include "../Common/MyTypes.h" |
7 | #include "../Common/MyWindows.h" | 7 | #include "../Common/MyWindows.h" |
8 | #include "PropVariant.h" | ||
9 | |||
10 | inline UInt64 FILETIME_To_UInt64(const FILETIME &ft) | ||
11 | { | ||
12 | return (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; | ||
13 | } | ||
14 | |||
15 | inline void FILETIME_Clear(FILETIME &ft) | ||
16 | { | ||
17 | ft.dwLowDateTime = 0; | ||
18 | ft.dwHighDateTime = 0; | ||
19 | } | ||
20 | |||
21 | inline bool FILETIME_IsZero(const FILETIME &ft) | ||
22 | { | ||
23 | return (ft.dwHighDateTime == 0 && ft.dwLowDateTime == 0); | ||
24 | } | ||
25 | |||
26 | |||
27 | #ifdef _WIN32 | ||
28 | #define CFiTime FILETIME | ||
29 | #define Compare_FiTime ::CompareFileTime | ||
30 | inline void FiTime_To_FILETIME(const CFiTime &ts, FILETIME &ft) | ||
31 | { | ||
32 | ft = ts; | ||
33 | } | ||
34 | /* | ||
35 | inline void FILETIME_To_FiTime(const FILETIME &ft, CFiTime &ts) | ||
36 | { | ||
37 | ts = ft; | ||
38 | } | ||
39 | */ | ||
40 | inline void FiTime_Clear(CFiTime &ft) | ||
41 | { | ||
42 | ft.dwLowDateTime = 0; | ||
43 | ft.dwHighDateTime = 0; | ||
44 | } | ||
45 | #else | ||
46 | |||
47 | #include <sys/stat.h> | ||
48 | |||
49 | #if defined(_AIX) | ||
50 | #define CFiTime st_timespec | ||
51 | #else | ||
52 | #define CFiTime timespec | ||
53 | #endif | ||
54 | int Compare_FiTime(const CFiTime *a1, const CFiTime *a2); | ||
55 | bool FILETIME_To_timespec(const FILETIME &ft, CFiTime &ts); | ||
56 | void FiTime_To_FILETIME(const CFiTime &ts, FILETIME &ft); | ||
57 | void FiTime_To_FILETIME_ns100(const CFiTime &ts, FILETIME &ft, unsigned &ns100); | ||
58 | inline void FiTime_Clear(CFiTime &ft) | ||
59 | { | ||
60 | ft.tv_sec = 0; | ||
61 | ft.tv_nsec = 0; | ||
62 | } | ||
63 | |||
64 | #ifdef __APPLE__ | ||
65 | #define ST_MTIME(st) st.st_mtimespec | ||
66 | #define ST_ATIME(st) st.st_atimespec | ||
67 | #define ST_CTIME(st) st.st_ctimespec | ||
68 | #else | ||
69 | #define ST_MTIME(st) st.st_mtim | ||
70 | #define ST_ATIME(st) st.st_atim | ||
71 | #define ST_CTIME(st) st.st_ctim | ||
72 | #endif | ||
73 | |||
74 | #endif | ||
75 | |||
76 | // void FiTime_Normalize_With_Prec(CFiTime &ft, unsigned prec); | ||
8 | 77 | ||
9 | namespace NWindows { | 78 | namespace NWindows { |
10 | namespace NTime { | 79 | namespace NTime { |
11 | 80 | ||
12 | bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime) throw(); | 81 | bool DosTime_To_FileTime(UInt32 dosTime, FILETIME &fileTime) throw(); |
13 | bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime) throw(); | 82 | bool UtcFileTime_To_LocalDosTime(const FILETIME &utc, UInt32 &dosTime) throw(); |
83 | bool FileTime_To_DosTime(const FILETIME &fileTime, UInt32 &dosTime) throw(); | ||
14 | 84 | ||
15 | // UInt32 Unix Time : for dates 1970-2106 | 85 | // UInt32 Unix Time : for dates 1970-2106 |
16 | UInt64 UnixTimeToFileTime64(UInt32 unixTime) throw(); | 86 | UInt64 UnixTime_To_FileTime64(UInt32 unixTime) throw(); |
17 | void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime) throw(); | 87 | void UnixTime_To_FileTime(UInt32 unixTime, FILETIME &fileTime) throw(); |
18 | 88 | ||
19 | // Int64 Unix Time : negative values for dates before 1970 | 89 | // Int64 Unix Time : negative values for dates before 1970 |
20 | UInt64 UnixTime64ToFileTime64(Int64 unixTime) throw(); | 90 | UInt64 UnixTime64_To_FileTime64(Int64 unixTime) throw(); // no check |
21 | bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &fileTime) throw(); | 91 | bool UnixTime64_To_FileTime64(Int64 unixTime, UInt64 &fileTime) throw(); |
92 | bool UnixTime64_To_FileTime(Int64 unixTime, FILETIME &fileTime) throw(); | ||
22 | 93 | ||
23 | bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime) throw(); | 94 | Int64 FileTime64_To_UnixTime64(UInt64 ft64) throw(); |
24 | Int64 FileTimeToUnixTime64(const FILETIME &ft) throw(); | 95 | bool FileTime_To_UnixTime(const FILETIME &fileTime, UInt32 &unixTime) throw(); |
96 | Int64 FileTime_To_UnixTime64(const FILETIME &ft) throw(); | ||
97 | Int64 FileTime_To_UnixTime64_and_Quantums(const FILETIME &ft, UInt32 &quantums) throw(); | ||
25 | 98 | ||
26 | bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, | 99 | bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, |
27 | unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw(); | 100 | unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw(); |
101 | |||
102 | void GetCurUtc_FiTime(CFiTime &ft) throw(); | ||
103 | #ifdef _WIN32 | ||
104 | #define GetCurUtcFileTime GetCurUtc_FiTime | ||
105 | #else | ||
28 | void GetCurUtcFileTime(FILETIME &ft) throw(); | 106 | void GetCurUtcFileTime(FILETIME &ft) throw(); |
107 | #endif | ||
29 | 108 | ||
30 | }} | 109 | }} |
31 | 110 | ||
111 | inline void PropVariant_SetFrom_UnixTime(NWindows::NCOM::CPropVariant &prop, UInt32 unixTime) | ||
112 | { | ||
113 | FILETIME ft; | ||
114 | NWindows::NTime::UnixTime_To_FileTime(unixTime, ft); | ||
115 | prop.SetAsTimeFrom_FT_Prec(ft, k_PropVar_TimePrec_Unix); | ||
116 | } | ||
117 | |||
118 | inline void PropVariant_SetFrom_NtfsTime(NWindows::NCOM::CPropVariant &prop, const FILETIME &ft) | ||
119 | { | ||
120 | prop.SetAsTimeFrom_FT_Prec(ft, k_PropVar_TimePrec_100ns); | ||
121 | } | ||
122 | |||
123 | inline void PropVariant_SetFrom_FiTime(NWindows::NCOM::CPropVariant &prop, const CFiTime &fts) | ||
124 | { | ||
125 | #ifdef _WIN32 | ||
126 | PropVariant_SetFrom_NtfsTime(prop, fts); | ||
127 | #else | ||
128 | unsigned ns100; | ||
129 | FILETIME ft; | ||
130 | FiTime_To_FILETIME_ns100(fts, ft, ns100); | ||
131 | prop.SetAsTimeFrom_FT_Prec_Ns100(ft, k_PropVar_TimePrec_1ns, ns100); | ||
132 | #endif | ||
133 | } | ||
134 | |||
135 | inline bool PropVariant_SetFrom_DosTime(NWindows::NCOM::CPropVariant &prop, UInt32 dosTime) | ||
136 | { | ||
137 | FILETIME localFileTime, utc; | ||
138 | if (!NWindows::NTime::DosTime_To_FileTime(dosTime, localFileTime)) | ||
139 | return false; | ||
140 | if (!LocalFileTimeToFileTime(&localFileTime, &utc)) | ||
141 | return false; | ||
142 | prop.SetAsTimeFrom_FT_Prec(utc, k_PropVar_TimePrec_DOS); | ||
143 | return true; | ||
144 | } | ||
145 | |||
32 | #endif | 146 | #endif |
diff --git a/DOC/7zip.wxs b/DOC/7zip.wxs index fdc63ce..c7a61b4 100644 --- a/DOC/7zip.wxs +++ b/DOC/7zip.wxs | |||
@@ -1,7 +1,7 @@ | |||
1 | <?xml version="1.0"?> | 1 | <?xml version="1.0"?> |
2 | 2 | ||
3 | <?define VerMajor = "21" ?> | 3 | <?define VerMajor = "22" ?> |
4 | <?define VerMinor = "07" ?> | 4 | <?define VerMinor = "00" ?> |
5 | <?define VerBuild = "00" ?> | 5 | <?define VerBuild = "00" ?> |
6 | <?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?> | 6 | <?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?> |
7 | <?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?> | 7 | <?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?> |
diff --git a/DOC/src-history.txt b/DOC/src-history.txt index 0b54fe3..f546c4e 100644 --- a/DOC/src-history.txt +++ b/DOC/src-history.txt | |||
@@ -1,6 +1,12 @@ | |||
1 | HISTORY of the 7-Zip source code | 1 | HISTORY of the 7-Zip source code |
2 | -------------------------------- | 2 | -------------------------------- |
3 | 3 | ||
4 | 22.00 2022-06-16 | ||
5 | ------------------------- | ||
6 | - 7-Zip interfaces now support high precision (1 ns) timestamps with reserved | ||
7 | fields of tagPROPVARIANT (VT_FILETIME). | ||
8 | |||
9 | |||
4 | 21.07 2021-12-26 | 10 | 21.07 2021-12-26 |
5 | ------------------------- | 11 | ------------------------- |
6 | - The sorting order of files in archives was slightly changed to be more consistent | 12 | - The sorting order of files in archives was slightly changed to be more consistent |