aboutsummaryrefslogtreecommitdiff
path: root/CPP/7zip/Archive/7z/7zUpdate.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--CPP/7zip/Archive/7z/7zUpdate.cpp307
1 files changed, 192 insertions, 115 deletions
diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp
index 4e9ea5d..d374a00 100644
--- a/CPP/7zip/Archive/7z/7zUpdate.cpp
+++ b/CPP/7zip/Archive/7z/7zUpdate.cpp
@@ -33,7 +33,7 @@ struct CFilterMode
33 UInt32 Id; 33 UInt32 Id;
34 UInt32 Delta; // required File Size alignment, if Id is not k_Delta. 34 UInt32 Delta; // required File Size alignment, if Id is not k_Delta.
35 // (Delta == 0) means unknown alignment 35 // (Delta == 0) means unknown alignment
36 UInt32 Offset; // for k_ARM64 36 UInt32 Offset; // for k_ARM64 / k_RISCV
37 // UInt32 AlignSizeOpt; // for k_ARM64 37 // UInt32 AlignSizeOpt; // for k_ARM64
38 38
39 CFilterMode(): 39 CFilterMode():
@@ -59,7 +59,7 @@ struct CFilterMode
59 Delta = 16; 59 Delta = 16;
60 else if (Id == k_ARM64 || Id == k_ARM || Id == k_PPC || Id == k_SPARC) 60 else if (Id == k_ARM64 || Id == k_ARM || Id == k_PPC || Id == k_SPARC)
61 Delta = 4; 61 Delta = 4;
62 else if (Id == k_ARMT) 62 else if (Id == k_ARMT || Id == k_RISCV)
63 Delta = 2; 63 Delta = 2;
64 else if (Id == k_BCJ || Id == k_BCJ2) 64 else if (Id == k_BCJ || Id == k_BCJ2)
65 Delta = 1; // do we need it? 65 Delta = 1; // do we need it?
@@ -95,7 +95,9 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode)
95 return 0; 95 return 0;
96 p += 4; 96 p += 4;
97 97
98 switch (GetUi16(p)) 98 const unsigned machine = GetUi16(p);
99
100 switch (machine)
99 { 101 {
100 case 0x014C: 102 case 0x014C:
101 case 0x8664: filterId = k_X86; break; 103 case 0x8664: filterId = k_X86; break;
@@ -112,11 +114,16 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode)
112 case 0x01C2: filterId = k_ARM; break; // WinCE new 114 case 0x01C2: filterId = k_ARM; break; // WinCE new
113 case 0x01C4: filterId = k_ARMT; break; // WinRT 115 case 0x01C4: filterId = k_ARMT; break; // WinRT
114 116
117 case 0x5032: // RISCV32
118 case 0x5064: // RISCV64
119 // case 0x5128: // RISCV128
120 filterId = k_RISCV; break;
121
115 case 0x0200: filterId = k_IA64; break; 122 case 0x0200: filterId = k_IA64; break;
116 default: return 0; 123 default: return 0;
117 } 124 }
118 125
119 // const UInt32 numSections = GetUi16(p + 2); 126 const UInt32 numSections = GetUi16(p + 2);
120 optHeaderSize = GetUi16(p + 16); 127 optHeaderSize = GetUi16(p + 16);
121 if (optHeaderSize > (1 << 10)) 128 if (optHeaderSize > (1 << 10))
122 return 0; 129 return 0;
@@ -132,34 +139,49 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode)
132 return 0; 139 return 0;
133 } 140 }
134 141
135 /*
136 // Windows exe file sizes are not aligned for 4 KiB. 142 // Windows exe file sizes are not aligned for 4 KiB.
137 // So we can't use (CFilterMode::Offset != 0) in solid archives. 143 // So we can't use (CFilterMode::Offset != 0) in solid archives.
138 // So we just don't set Offset here. 144 // So we just don't set Offset here.
139#define NUM_SCAN_SECTIONS_MAX (1 << 6) 145#define NUM_SCAN_SECTIONS_MAX (1 << 6)
140#define EXE_SECTION_OFFSET_MAX (1 << 27) 146// #define EXE_SECTION_OFFSET_MAX (1 << 27)
141#define EXE_SECTION_SIZE_MIN (1 << 8) 147// #define EXE_SECTION_SIZE_MIN (1 << 8)
142#define EXE_SECTION_SIZE_MAX (1 << 27) 148// #define EXE_SECTION_SIZE_MAX (1 << 27)
143#define PE_SectHeaderSize 40 149#define PE_SectHeaderSize 40
144#define PE_SECT_EXECUTE 0x20000000 150// #define PE_SECT_EXECUTE 0x20000000
145 151
152/*
146 if (numSections > NUM_SCAN_SECTIONS_MAX) 153 if (numSections > NUM_SCAN_SECTIONS_MAX)
147 return 0; 154 return 0;
155*/
148 156
157 if ((size_t)(p - buf) + optHeaderSize <= size)
158 {
149 p += optHeaderSize; 159 p += optHeaderSize;
160/*
150 // UInt32 numExeSections = 0; 161 // UInt32 numExeSections = 0;
151 // bool execute_finded = false; 162 // bool execute_finded = false;
152 // UInt32 sect_va = 0; 163 // UInt32 sect_va = 0;
153 // UInt32 sect_size = 0; 164 // UInt32 sect_size = 0;
154 // UInt32 sect_offset = 0; 165 // UInt32 sect_offset = 0;
155 166*/
167 if (numSections <= NUM_SCAN_SECTIONS_MAX)
168 if (machine == 0x8664)
156 for (UInt32 i = 0; i < numSections 169 for (UInt32 i = 0; i < numSections
157 // && numExeSections < numSectionsMax
158 ; i++, p += PE_SectHeaderSize) 170 ; i++, p += PE_SectHeaderSize)
159 { 171 {
160 UInt32 characts, rawSize, offset; 172 // UInt32 characts, rawSize, offset;
161 if ((UInt32)(p - buf) + PE_SectHeaderSize > size) 173 if ((UInt32)(p - buf) + PE_SectHeaderSize > size)
162 return 0; 174 {
175 // return 0;
176 break;
177 }
178 if (memcmp(p, ".a64xrm", 8) == 0)
179 {
180 // ARM64EC
181 filterId = k_ARM64;
182 break;
183 }
184/*
163 rawSize = GetUi32(p + 16); 185 rawSize = GetUi32(p + 16);
164 offset = GetUi32(p + 20); 186 offset = GetUi32(p + 20);
165 characts = GetUi32(p + 36); 187 characts = GetUi32(p + 36);
@@ -178,8 +200,11 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode)
178 break; 200 break;
179 } 201 }
180 } 202 }
203*/
204 }
181 } 205 }
182 206
207 /*
183 filterMode->Offset = 0; 208 filterMode->Offset = 0;
184 if (filterId == k_ARM64) 209 if (filterId == k_ARM64)
185 { 210 {
@@ -243,8 +268,9 @@ static int Parse_ELF(const Byte *buf, size_t size, CFilterMode *filterMode)
243 case 43: filterId = k_SPARC; break; 268 case 43: filterId = k_SPARC; break;
244 case 20: 269 case 20:
245 case 21: if (!be) return 0; filterId = k_PPC; break; 270 case 21: if (!be) return 0; filterId = k_PPC; break;
246 case 40: if ( be) return 0; filterId = k_ARM; break; 271 case 40: if (be) return 0; filterId = k_ARM; break;
247 case 183: if (be) return 0; filterId = k_ARM64; break; 272 case 183: if (be) return 0; filterId = k_ARM64; break;
273 case 243: if (be) return 0; filterId = k_RISCV; break;
248 274
249 /* Some IA-64 ELF executables have size that is not aligned for 16 bytes. 275 /* Some IA-64 ELF executables have size that is not aligned for 16 bytes.
250 So we don't use IA-64 filter for IA-64 ELF */ 276 So we don't use IA-64 filter for IA-64 ELF */
@@ -482,6 +508,7 @@ static inline bool IsExeFilter(CMethodId m)
482 switch (m) 508 switch (m)
483 { 509 {
484 case k_ARM64: 510 case k_ARM64:
511 case k_RISCV:
485 case k_BCJ: 512 case k_BCJ:
486 case k_BCJ2: 513 case k_BCJ2:
487 case k_ARM: 514 case k_ARM:
@@ -490,6 +517,7 @@ static inline bool IsExeFilter(CMethodId m)
490 case k_SPARC: 517 case k_SPARC:
491 case k_IA64: 518 case k_IA64:
492 return true; 519 return true;
520 default: break;
493 } 521 }
494 return false; 522 return false;
495} 523}
@@ -521,7 +549,8 @@ static unsigned Get_FilterGroup_for_Folder(
521 if (m.Id == k_BCJ2) 549 if (m.Id == k_BCJ2)
522 m.Id = k_BCJ; 550 m.Id = k_BCJ;
523 m.SetDelta(); 551 m.SetDelta();
524 if (m.Id == k_ARM64) 552 if (m.Id == k_ARM64 ||
553 m.Id == k_RISCV)
525 if (coder.Props.Size() == 4) 554 if (coder.Props.Size() == 4)
526 m.Offset = GetUi32(coder.Props); 555 m.Offset = GetUi32(coder.Props);
527 } 556 }
@@ -537,15 +566,12 @@ static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream,
537 UInt64 position, UInt64 size, ICompressProgressInfo *progress) 566 UInt64 position, UInt64 size, ICompressProgressInfo *progress)
538{ 567{
539 RINOK(InStream_SeekSet(inStream, position)) 568 RINOK(InStream_SeekSet(inStream, position))
540 CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; 569 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> streamSpec;
541 CMyComPtr<ISequentialInStream> inStreamLimited(streamSpec);
542 streamSpec->SetStream(inStream); 570 streamSpec->SetStream(inStream);
543 streamSpec->Init(size); 571 streamSpec->Init(size);
544 572 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
545 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; 573 RINOK(copyCoder.Interface()->Code(streamSpec, outStream, NULL, NULL, progress))
546 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; 574 return (copyCoder->TotalSize == size ? S_OK : E_FAIL);
547 RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress))
548 return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL);
549} 575}
550 576
551/* 577/*
@@ -759,9 +785,9 @@ struct CRefItem
759 { 785 {
760 if (sortByType) 786 if (sortByType)
761 { 787 {
762 int slashPos = ui.Name.ReverseFind_PathSepar(); 788 const int slashPos = ui.Name.ReverseFind_PathSepar();
763 NamePos = (unsigned)(slashPos + 1); 789 NamePos = (unsigned)(slashPos + 1);
764 int dotPos = ui.Name.ReverseFind_Dot(); 790 const int dotPos = ui.Name.ReverseFind_Dot();
765 if (dotPos <= slashPos) 791 if (dotPos <= slashPos)
766 ExtensionPos = ui.Name.Len(); 792 ExtensionPos = ui.Name.Len();
767 else 793 else
@@ -772,7 +798,7 @@ struct CRefItem
772 AString s; 798 AString s;
773 for (unsigned pos = ExtensionPos;; pos++) 799 for (unsigned pos = ExtensionPos;; pos++)
774 { 800 {
775 wchar_t c = ui.Name[pos]; 801 const wchar_t c = ui.Name[pos];
776 if (c >= 0x80) 802 if (c >= 0x80)
777 break; 803 break;
778 if (c == 0) 804 if (c == 0)
@@ -780,7 +806,7 @@ struct CRefItem
780 ExtensionIndex = GetExtIndex(s); 806 ExtensionIndex = GetExtIndex(s);
781 break; 807 break;
782 } 808 }
783 s += (char)MyCharLower_Ascii((char)c); 809 s.Add_Char((char)MyCharLower_Ascii((char)c));
784 } 810 }
785 } 811 }
786 } 812 }
@@ -1123,6 +1149,12 @@ HRESULT CAnalysis::GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMo
1123 #ifdef MY_CPU_ARM64 1149 #ifdef MY_CPU_ARM64
1124 filterModeTemp.Id = k_ARM64; 1150 filterModeTemp.Id = k_ARM64;
1125 #endif 1151 #endif
1152 #ifdef MY_CPU_RISCV
1153 filterModeTemp.Id = k_RISCV;
1154 #endif
1155 #ifdef MY_CPU_SPARC
1156 filterModeTemp.Id = k_SPARC;
1157 #endif
1126 parseRes = true; 1158 parseRes = true;
1127 } 1159 }
1128 1160
@@ -1172,6 +1204,8 @@ static inline void GetMethodFull(UInt64 methodID, UInt32 numStreams, CMethodFull
1172 m.NumStreams = numStreams; 1204 m.NumStreams = numStreams;
1173} 1205}
1174 1206
1207
1208// we add bond for mode.Methods[0] that is filter
1175static HRESULT AddBondForFilter(CCompressionMethodMode &mode) 1209static HRESULT AddBondForFilter(CCompressionMethodMode &mode)
1176{ 1210{
1177 for (unsigned c = 1; c < mode.Methods.Size(); c++) 1211 for (unsigned c = 1; c < mode.Methods.Size(); c++)
@@ -1189,16 +1223,19 @@ static HRESULT AddBondForFilter(CCompressionMethodMode &mode)
1189 return E_INVALIDARG; 1223 return E_INVALIDARG;
1190} 1224}
1191 1225
1192static HRESULT AddFilterBond(CCompressionMethodMode &mode) 1226/*
1227static HRESULT AddBondForFilter_if_ThereAreBonds(CCompressionMethodMode &mode)
1193{ 1228{
1194 if (!mode.Bonds.IsEmpty()) 1229 if (!mode.Bonds.IsEmpty())
1195 return AddBondForFilter(mode); 1230 return AddBondForFilter(mode);
1196 return S_OK; 1231 return S_OK;
1197} 1232}
1233*/
1198 1234
1199static HRESULT AddBcj2Methods(CCompressionMethodMode &mode) 1235static HRESULT AddBcj2Methods(CCompressionMethodMode &mode)
1200{ 1236{
1201 // mode.Methods[0] must be k_BCJ2 method ! 1237 // mode.Methods[0] must be k_BCJ2 method !
1238 // mode.Methods[1] : we expect that there is at least one method after BCJ2
1202 1239
1203 CMethodFull m; 1240 CMethodFull m;
1204 GetMethodFull(k_LZMA, 1, m); 1241 GetMethodFull(k_LZMA, 1, m);
@@ -1210,7 +1247,7 @@ static HRESULT AddBcj2Methods(CCompressionMethodMode &mode)
1210 m.AddProp32(NCoderPropID::kLitContextBits, 0); 1247 m.AddProp32(NCoderPropID::kLitContextBits, 0);
1211 // m.AddProp_Ascii(NCoderPropID::kMatchFinder, "BT2"); 1248 // m.AddProp_Ascii(NCoderPropID::kMatchFinder, "BT2");
1212 1249
1213 unsigned methodIndex = mode.Methods.Size(); 1250 const unsigned methodIndex = mode.Methods.Size();
1214 1251
1215 if (mode.Bonds.IsEmpty()) 1252 if (mode.Bonds.IsEmpty())
1216 { 1253 {
@@ -1229,109 +1266,140 @@ static HRESULT AddBcj2Methods(CCompressionMethodMode &mode)
1229 1266
1230 RINOK(AddBondForFilter(mode)) 1267 RINOK(AddBondForFilter(mode))
1231 CBond2 bond; 1268 CBond2 bond;
1232 bond.OutCoder = 0; 1269 bond.OutCoder = 0; // index of BCJ2 coder
1233 bond.InCoder = methodIndex; bond.OutStream = 1; mode.Bonds.Add(bond); 1270 bond.InCoder = methodIndex; bond.OutStream = 1; mode.Bonds.Add(bond);
1234 bond.InCoder = methodIndex + 1; bond.OutStream = 2; mode.Bonds.Add(bond); 1271 bond.InCoder = methodIndex + 1; bond.OutStream = 2; mode.Bonds.Add(bond);
1235 return S_OK; 1272 return S_OK;
1236} 1273}
1237 1274
1275
1238static HRESULT MakeExeMethod(CCompressionMethodMode &mode, 1276static HRESULT MakeExeMethod(CCompressionMethodMode &mode,
1239 const CFilterMode &filterMode, /* bool addFilter, */ bool bcj2Filter) 1277 const CFilterMode &filterMode,
1278 const bool bcj2_IsAllowed,
1279 const CUIntVector &disabledFilterIDs)
1240{ 1280{
1241 if (mode.Filter_was_Inserted) 1281 if (mode.Filter_was_Inserted)
1242 { 1282 {
1283 // filter was inserted, but bond for that filter was not added still.
1243 const CMethodFull &m = mode.Methods[0]; 1284 const CMethodFull &m = mode.Methods[0];
1244 const CMethodId id = m.Id; 1285 if (m.Id == k_BCJ2)
1245 if (id == k_BCJ2)
1246 return AddBcj2Methods(mode); 1286 return AddBcj2Methods(mode);
1247 if (!m.IsSimpleCoder()) 1287 if (!m.IsSimpleCoder())
1248 return E_NOTIMPL; 1288 return E_NOTIMPL;
1249 // if (Bonds.IsEmpty()) we can create bonds later 1289 if (mode.Bonds.IsEmpty())
1250 return AddFilterBond(mode); 1290 return S_OK;
1291 return AddBondForFilter(mode);
1251 } 1292 }
1252 1293
1253 if (filterMode.Id == 0) 1294 if (filterMode.Id == 0)
1254 return S_OK; 1295 return S_OK;
1255 1296
1256 CMethodFull &m = mode.Methods.InsertNew(0); 1297 unsigned nextCoder;
1257 1298
1258 { 1299 const bool useBcj2 = bcj2_IsAllowed
1259 FOR_VECTOR (k, mode.Bonds) 1300 && Is86Filter(filterMode.Id)
1260 { 1301 && disabledFilterIDs.FindInSorted(k_BCJ2) < 0;
1261 CBond2 &bond = mode.Bonds[k];
1262 bond.InCoder++;
1263 bond.OutCoder++;
1264 }
1265 }
1266 1302
1267 HRESULT res; 1303 if (!useBcj2 && disabledFilterIDs.FindInSorted(filterMode.Id) >= 0)
1268
1269 if (bcj2Filter && Is86Filter(filterMode.Id))
1270 { 1304 {
1271 GetMethodFull(k_BCJ2, 4, m); 1305 // required filter is disabled,
1272 res = AddBcj2Methods(mode); 1306 // but we still can use information about data alignment.
1307#if 0 // 1 for debug
1308 // we can return here, if we want default lzma properties
1309 return S_OK;
1310#else
1311 // we will try to change lzma/lzma2 properties
1312 nextCoder = 0;
1313 if (!mode.Bonds.IsEmpty())
1314 for (unsigned c = 0;; c++)
1315 {
1316 if (c == mode.Methods.Size())
1317 return S_OK;
1318 if (!mode.IsThereBond_to_Coder(c))
1319 {
1320 nextCoder = c;
1321 break;
1322 }
1323 }
1324#endif
1273 } 1325 }
1274 else 1326 else
1275 { 1327 {
1328 // we insert new filter method:
1329 CMethodFull &m = mode.Methods.InsertNew(0); // 0 == index of new inserted item
1330 {
1331 // we move all coder indexes in bonds up for 1 position:
1332 FOR_VECTOR (k, mode.Bonds)
1333 {
1334 CBond2 &bond = mode.Bonds[k];
1335 bond.InCoder++;
1336 bond.OutCoder++;
1337 }
1338 }
1339 if (useBcj2)
1340 {
1341 GetMethodFull(k_BCJ2, 4, m);
1342 return AddBcj2Methods(mode);
1343 }
1344
1276 GetMethodFull(filterMode.Id, 1, m); 1345 GetMethodFull(filterMode.Id, 1, m);
1346
1277 if (filterMode.Id == k_Delta) 1347 if (filterMode.Id == k_Delta)
1278 m.AddProp32(NCoderPropID::kDefaultProp, filterMode.Delta); 1348 m.AddProp32(NCoderPropID::kDefaultProp, filterMode.Delta);
1279 else if (filterMode.Id == k_ARM64) 1349 else if (filterMode.Id == k_ARM64
1350 || filterMode.Id == k_RISCV)
1280 { 1351 {
1281 // if (filterMode.Offset != 0) 1352 // if (filterMode.Offset != 0)
1282 m.AddProp32( 1353 m.AddProp32(
1283 NCoderPropID::kDefaultProp, 1354 NCoderPropID::kDefaultProp,
1284 // NCoderPropID::kBranchOffset, 1355 // NCoderPropID::kBranchOffset,
1285 filterMode.Offset); 1356 filterMode.Offset);
1286 } 1357 }
1287 res = AddFilterBond(mode); 1358
1288 1359 nextCoder = 1;
1289 int alignBits = -1; 1360 if (!mode.Bonds.IsEmpty())
1290 { 1361 {
1291 const UInt32 delta = filterMode.Delta; 1362 RINOK(AddBondForFilter(mode))
1292 if (delta == 0 || delta > 16) 1363 nextCoder = mode.Bonds.Back().InCoder;
1293 {
1294 // if (delta == 0) alignBits = GetAlignForFilterMethod(filterMode.Id);
1295 }
1296 else if ((delta & ((1 << 4) - 1)) == 0) alignBits = 4;
1297 else if ((delta & ((1 << 3) - 1)) == 0) alignBits = 3;
1298 else if ((delta & ((1 << 2) - 1)) == 0) alignBits = 2;
1299 else if ((delta & ((1 << 1) - 1)) == 0) alignBits = 1;
1300 // else alignBits = 0;
1301 /* alignBits=0 is default mode for lzma/lzma2.
1302 So we don't set alignBits=0 here. */
1303 } 1364 }
1304 if (res == S_OK && alignBits > 0) 1365 }
1366
1367 if (nextCoder >= mode.Methods.Size())
1368 {
1369 // we don't expect that case, if there was non-filter method.
1370 // but we return S_OK to support filter-only case.
1371 return S_OK;
1372 }
1373
1374 int alignBits = -1;
1375 {
1376 const UInt32 delta = filterMode.Delta;
1377 if (delta == 0 || delta > 16)
1305 { 1378 {
1306 unsigned nextCoder = 1; 1379 // if (delta == 0) alignBits = GetAlignForFilterMethod(filterMode.Id);
1307 if (!mode.Bonds.IsEmpty())
1308 {
1309 nextCoder = mode.Bonds.Back().InCoder;
1310 }
1311 if (nextCoder < mode.Methods.Size())
1312 {
1313 CMethodFull &nextMethod = mode.Methods[nextCoder];
1314 if (nextMethod.Id == k_LZMA || nextMethod.Id == k_LZMA2)
1315 {
1316 if (!nextMethod.Are_Lzma_Model_Props_Defined())
1317 {
1318 if (alignBits != 0)
1319 {
1320 if (alignBits > 2 || filterMode.Id == k_Delta)
1321 nextMethod.AddProp32(NCoderPropID::kPosStateBits, (unsigned)alignBits);
1322 unsigned lc = 0;
1323 if (alignBits < 3)
1324 lc = (unsigned)(3 - alignBits);
1325 nextMethod.AddProp32(NCoderPropID::kLitContextBits, lc);
1326 nextMethod.AddProp32(NCoderPropID::kLitPosBits, (unsigned)alignBits);
1327 }
1328 }
1329 }
1330 }
1331 } 1380 }
1381 else if ((delta & ((1 << 4) - 1)) == 0) alignBits = 4;
1382 else if ((delta & ((1 << 3) - 1)) == 0) alignBits = 3;
1383 else if ((delta & ((1 << 2) - 1)) == 0) alignBits = 2;
1384 else if ((delta & ((1 << 1) - 1)) == 0) alignBits = 1;
1385 // else alignBits = 0;
1386 /* alignBits=0 is default mode for lzma/lzma2.
1387 So we don't set alignBits=0 here. */
1332 } 1388 }
1333 1389 if (alignBits <= 0)
1334 return res; 1390 return S_OK;
1391 // (alignBits > 0)
1392 CMethodFull &nextMethod = mode.Methods[nextCoder];
1393 if (nextMethod.Id == k_LZMA || nextMethod.Id == k_LZMA2)
1394 if (!nextMethod.Are_Lzma_Model_Props_Defined())
1395 {
1396 if (alignBits > 2 || filterMode.Id == k_Delta)
1397 nextMethod.AddProp32(NCoderPropID::kPosStateBits, (unsigned)alignBits);
1398 const unsigned lc = (alignBits < 3) ? (unsigned)(3 - alignBits) : 0u;
1399 nextMethod.AddProp32(NCoderPropID::kLitContextBits, lc);
1400 nextMethod.AddProp32(NCoderPropID::kLitPosBits, (unsigned)alignBits);
1401 }
1402 return S_OK;
1335} 1403}
1336 1404
1337 1405
@@ -1859,6 +1927,7 @@ HRESULT Update(
1859 1927
1860 CIntArr fileIndexToUpdateIndexMap; 1928 CIntArr fileIndexToUpdateIndexMap;
1861 UInt64 complexity = 0; 1929 UInt64 complexity = 0;
1930 bool isThere_UnknownSize = false;
1862 UInt64 inSizeForReduce2 = 0; 1931 UInt64 inSizeForReduce2 = 0;
1863 1932
1864 #ifndef Z7_NO_CRYPTO 1933 #ifndef Z7_NO_CRYPTO
@@ -1971,28 +2040,36 @@ HRESULT Update(
1971 2040
1972 UInt64 inSizeForReduce = 0; 2041 UInt64 inSizeForReduce = 0;
1973 { 2042 {
1974 bool isSolid = (numSolidFiles > 1 && options.NumSolidBytes != 0); 2043 const bool isSolid = (numSolidFiles > 1 && options.NumSolidBytes != 0);
1975 FOR_VECTOR (i, updateItems) 2044 FOR_VECTOR (i, updateItems)
1976 { 2045 {
1977 const CUpdateItem &ui = updateItems[i]; 2046 const CUpdateItem &ui = updateItems[i];
1978 if (ui.NewData) 2047 if (ui.NewData)
1979 { 2048 {
1980 complexity += ui.Size; 2049 if (ui.Size == (UInt64)(Int64)-1)
1981 if (isSolid) 2050 isThere_UnknownSize = true;
1982 inSizeForReduce += ui.Size; 2051 else
1983 else if (inSizeForReduce < ui.Size) 2052 {
1984 inSizeForReduce = ui.Size; 2053 complexity += ui.Size;
2054 if (isSolid)
2055 inSizeForReduce += ui.Size;
2056 else if (inSizeForReduce < ui.Size)
2057 inSizeForReduce = ui.Size;
2058 }
1985 } 2059 }
1986 } 2060 }
1987 } 2061 }
1988 2062
2063 if (isThere_UnknownSize)
2064 inSizeForReduce = (UInt64)(Int64)-1;
2065 else
2066 RINOK(updateCallback->SetTotal(complexity))
2067
1989 if (inSizeForReduce < inSizeForReduce2) 2068 if (inSizeForReduce < inSizeForReduce2)
1990 inSizeForReduce = inSizeForReduce2; 2069 inSizeForReduce = inSizeForReduce2;
1991 2070
1992 RINOK(updateCallback->SetTotal(complexity))
1993 2071
1994 CLocalProgress *lps = new CLocalProgress; 2072 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1995 CMyComPtr<ICompressProgressInfo> progress = lps;
1996 lps->Init(updateCallback, true); 2073 lps->Init(updateCallback, true);
1997 2074
1998 #ifndef Z7_ST 2075 #ifndef Z7_ST
@@ -2232,12 +2309,13 @@ HRESULT Update(
2232 CCompressionMethodMode method = *options.Method; 2309 CCompressionMethodMode method = *options.Method;
2233 { 2310 {
2234 const HRESULT res = MakeExeMethod(method, filterMode, 2311 const HRESULT res = MakeExeMethod(method, filterMode,
2312 // bcj2_IsAllowed:
2235 #ifdef Z7_ST 2313 #ifdef Z7_ST
2236 false 2314 false
2237 #else 2315 #else
2238 options.MaxFilter && options.MultiThreadMixer 2316 options.MaxFilter && options.MultiThreadMixer
2239 #endif 2317 #endif
2240 ); 2318 , options.DisabledFilterIDs);
2241 2319
2242 RINOK(res) 2320 RINOK(res)
2243 } 2321 }
@@ -2299,7 +2377,7 @@ HRESULT Update(
2299 2377
2300 const UInt64 packSize = db->GetFolderFullPackSize(folderIndex); 2378 const UInt64 packSize = db->GetFolderFullPackSize(folderIndex);
2301 RINOK(WriteRange(inStream, archive.SeqStream, 2379 RINOK(WriteRange(inStream, archive.SeqStream,
2302 db->GetFolderStreamPos(folderIndex, 0), packSize, progress)) 2380 db->GetFolderStreamPos(folderIndex, 0), packSize, lps))
2303 lps->ProgressOffset += packSize; 2381 lps->ProgressOffset += packSize;
2304 2382
2305 const unsigned folderIndex_New = newDatabase.Folders.Size(); 2383 const unsigned folderIndex_New = newDatabase.Folders.Size();
@@ -2321,7 +2399,7 @@ HRESULT Update(
2321 size_t indexStart = db->FoToCoderUnpackSizes[folderIndex]; 2399 size_t indexStart = db->FoToCoderUnpackSizes[folderIndex];
2322 const size_t indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1]; 2400 const size_t indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1];
2323 for (; indexStart < indexEnd; indexStart++) 2401 for (; indexStart < indexEnd; indexStart++)
2324 newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes[indexStart]); 2402 newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes.ConstData()[indexStart]);
2325 } 2403 }
2326 else 2404 else
2327 { 2405 {
@@ -2481,7 +2559,7 @@ HRESULT Update(
2481 sizeToEncode, // expectedDataSize 2559 sizeToEncode, // expectedDataSize
2482 newDatabase.Folders.AddNew(), 2560 newDatabase.Folders.AddNew(),
2483 // newDatabase.CoderUnpackSizes, curUnpackSize, 2561 // newDatabase.CoderUnpackSizes, curUnpackSize,
2484 archive.SeqStream, newDatabase.PackSizes, progress); 2562 archive.SeqStream, newDatabase.PackSizes, lps);
2485 2563
2486 if (encodeRes == k_My_HRESULT_CRC_ERROR) 2564 if (encodeRes == k_My_HRESULT_CRC_ERROR)
2487 return E_FAIL; 2565 return E_FAIL;
@@ -2680,8 +2758,7 @@ HRESULT Update(
2680 */ 2758 */
2681 2759
2682 2760
2683 CFolderInStream *inStreamSpec = new CFolderInStream; 2761 CMyComPtr2_Create<ISequentialInStream, CFolderInStream> inStreamSpec; // solidInStream;
2684 CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec);
2685 2762
2686 // inStreamSpec->_reportArcProp = reportArcProp; 2763 // inStreamSpec->_reportArcProp = reportArcProp;
2687 2764
@@ -2702,13 +2779,13 @@ HRESULT Update(
2702 2779
2703 RINOK(encoder.Encode1( 2780 RINOK(encoder.Encode1(
2704 EXTERNAL_CODECS_LOC_VARS 2781 EXTERNAL_CODECS_LOC_VARS
2705 solidInStream, 2782 inStreamSpec,
2706 // NULL, 2783 // NULL,
2707 &inSizeForReduce, 2784 &inSizeForReduce,
2708 expectedDataSize, // expected size 2785 expectedDataSize, // expected size
2709 newDatabase.Folders.AddNew(), 2786 newDatabase.Folders.AddNew(),
2710 // newDatabase.CoderUnpackSizes, curFolderUnpackSize, 2787 // newDatabase.CoderUnpackSizes, curFolderUnpackSize,
2711 archive.SeqStream, newDatabase.PackSizes, progress)) 2788 archive.SeqStream, newDatabase.PackSizes, lps))
2712 2789
2713 if (!inStreamSpec->WasFinished()) 2790 if (!inStreamSpec->WasFinished())
2714 return E_FAIL; 2791 return E_FAIL;
@@ -2970,7 +3047,7 @@ HRESULT Update(
2970 if (newDatabase.NumUnpackStreamsVector.Size() != numFolders 3047 if (newDatabase.NumUnpackStreamsVector.Size() != numFolders
2971 || newDatabase.FolderUnpackCRCs.Defs.Size() > numFolders) 3048 || newDatabase.FolderUnpackCRCs.Defs.Size() > numFolders)
2972 return E_FAIL; 3049 return E_FAIL;
2973 newDatabase.FolderUnpackCRCs.if_NonEmpty_FillResedue_with_false(numFolders); 3050 newDatabase.FolderUnpackCRCs.if_NonEmpty_FillResidue_with_false(numFolders);
2974 } 3051 }
2975 3052
2976 updateItems.ClearAndFree(); 3053 updateItems.ClearAndFree();