Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: third_party/lzma/v4_65/files/CPP/7zip/Archive/7z/7zUpdate.cpp

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // 7zUpdate.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../Common/LimitedStreams.h"
6 #include "../../Common/ProgressUtils.h"
7
8 #include "../../Compress/CopyCoder.h"
9
10 #include "../Common/ItemNameUtils.h"
11
12 #include "7zEncode.h"
13 #include "7zFolderInStream.h"
14 #include "7zHandler.h"
15 #include "7zOut.h"
16 #include "7zUpdate.h"
17
18 namespace NArchive {
19 namespace N7z {
20
21 static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2";
22 static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20;
23 static const UInt32 kAlgorithmForBCJ2_LZMA = 1;
24 static const UInt32 kNumFastBytesForBCJ2_LZMA = 64;
25
26 static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream,
27 UInt64 position, UInt64 size, ICompressProgressInfo *progress)
28 {
29 RINOK(inStream->Seek(position, STREAM_SEEK_SET, 0));
30 CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
31 CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec);
32 streamSpec->SetStream(inStream);
33 streamSpec->Init(size);
34
35 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
36 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
37 RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress));
38 return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL);
39 }
40
41 static int GetReverseSlashPos(const UString &name)
42 {
43 int slashPos = name.ReverseFind(L'/');
44 #ifdef _WIN32
45 int slash1Pos = name.ReverseFind(L'\\');
46 slashPos = MyMax(slashPos, slash1Pos);
47 #endif
48 return slashPos;
49 }
50
51 int CUpdateItem::GetExtensionPos() const
52 {
53 int slashPos = GetReverseSlashPos(Name);
54 int dotPos = Name.ReverseFind(L'.');
55 if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0))
56 return Name.Length();
57 return dotPos + 1;
58 }
59
60 UString CUpdateItem::GetExtension() const
61 {
62 return Name.Mid(GetExtensionPos());
63 }
64
65 #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
66
67 static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2)
68 {
69 size_t c1 = a1.GetCapacity();
70 size_t c2 = a2.GetCapacity();
71 RINOZ(MyCompare(c1, c2));
72 for (size_t i = 0; i < c1; i++)
73 RINOZ(MyCompare(a1[i], a2[i]));
74 return 0;
75 }
76
77 static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2)
78 {
79 RINOZ(MyCompare(c1.NumInStreams, c2.NumInStreams));
80 RINOZ(MyCompare(c1.NumOutStreams, c2.NumOutStreams));
81 RINOZ(MyCompare(c1.MethodID, c2.MethodID));
82 return CompareBuffers(c1.Props, c2.Props);
83 }
84
85 static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2)
86 {
87 RINOZ(MyCompare(b1.InIndex, b2.InIndex));
88 return MyCompare(b1.OutIndex, b2.OutIndex);
89 }
90
91 static int CompareFolders(const CFolder &f1, const CFolder &f2)
92 {
93 int s1 = f1.Coders.Size();
94 int s2 = f2.Coders.Size();
95 RINOZ(MyCompare(s1, s2));
96 int i;
97 for (i = 0; i < s1; i++)
98 RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i]));
99 s1 = f1.BindPairs.Size();
100 s2 = f2.BindPairs.Size();
101 RINOZ(MyCompare(s1, s2));
102 for (i = 0; i < s1; i++)
103 RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i]));
104 return 0;
105 }
106
107 static int CompareFiles(const CFileItem &f1, const CFileItem &f2)
108 {
109 return MyStringCompareNoCase(f1.Name, f2.Name);
110 }
111
112 static int CompareFolderRefs(const int *p1, const int *p2, void *param)
113 {
114 int i1 = *p1;
115 int i2 = *p2;
116 const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)param;
117 RINOZ(CompareFolders(
118 db.Folders[i1],
119 db.Folders[i2]));
120 RINOZ(MyCompare(
121 db.NumUnpackStreamsVector[i1],
122 db.NumUnpackStreamsVector[i2]));
123 if (db.NumUnpackStreamsVector[i1] == 0)
124 return 0;
125 return CompareFiles(
126 db.Files[db.FolderStartFileIndex[i1]],
127 db.Files[db.FolderStartFileIndex[i2]]);
128 }
129
130 ////////////////////////////////////////////////////////////
131
132 static int CompareEmptyItems(const int *p1, const int *p2, void *param)
133 {
134 const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateI tem> *)param;
135 const CUpdateItem &u1 = updateItems[*p1];
136 const CUpdateItem &u2 = updateItems[*p2];
137 if (u1.IsDir != u2.IsDir)
138 return (u1.IsDir) ? 1 : -1;
139 if (u1.IsDir)
140 {
141 if (u1.IsAnti != u2.IsAnti)
142 return (u1.IsAnti ? 1 : -1);
143 int n = MyStringCompareNoCase(u1.Name, u2.Name);
144 return -n;
145 }
146 if (u1.IsAnti != u2.IsAnti)
147 return (u1.IsAnti ? 1 : -1);
148 return MyStringCompareNoCase(u1.Name, u2.Name);
149 }
150
151 static const char *g_Exts =
152 " lzma 7z ace arc arj bz bz2 deb lzo lzx gz pak rpm sit tgz tbz tbz2 tgz cab h a lha lzh rar zoo"
153 " zip jar ear war msi"
154 " 3gp avi mov mpeg mpg mpe wmv"
155 " aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav "
156 " swf "
157 " chm hxi hxs"
158 " gif jpeg jpg jp2 png tiff bmp ico psd psp"
159 " awg ps eps cgm dxf svg vrml wmf emf ai md"
160 " cad dwg pps key sxi"
161 " max 3ds"
162 " iso bin nrg mdf img pdi tar cpio xpi"
163 " vfd vhd vud vmc vsv"
164 " vmdk dsk nvram vmem vmsd vmsn vmss vmtm"
165 " inl inc idl acf asa h hpp hxx c cpp cxx rc java cs pas bas vb cls ctl frm dl g def"
166 " f77 f f90 f95"
167 " asm sql manifest dep "
168 " mak clw csproj vcproj sln dsp dsw "
169 " class "
170 " bat cmd"
171 " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi j sp shtml"
172 " awk sed hta js php php3 php4 php5 phptml pl pm py pyo rb sh tcl vbs"
173 " text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw pp t pdf"
174 " sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf"
175 " abw afp cwk lwp wpd wps wpt wrf wri"
176 " abf afm bdf fon mgf otf pcf pfa snf ttf"
177 " dbf mdb nsf ntf wdb db fdb gdb"
178 " exe dll ocx vbx sfx sys tlb awx com obj lib out o so "
179 " pdb pch idb ncb opt";
180
181 int GetExtIndex(const char *ext)
182 {
183 int extIndex = 1;
184 const char *p = g_Exts;
185 for (;;)
186 {
187 char c = *p++;
188 if (c == 0)
189 return extIndex;
190 if (c == ' ')
191 continue;
192 int pos = 0;
193 for (;;)
194 {
195 char c2 = ext[pos++];
196 if (c2 == 0 && (c == 0 || c == ' '))
197 return extIndex;
198 if (c != c2)
199 break;
200 c = *p++;
201 }
202 extIndex++;
203 for (;;)
204 {
205 if (c == 0)
206 return extIndex;
207 if (c == ' ')
208 break;
209 c = *p++;
210 }
211 }
212 }
213
214 struct CRefItem
215 {
216 const CUpdateItem *UpdateItem;
217 UInt32 Index;
218 UInt32 ExtensionPos;
219 UInt32 NamePos;
220 int ExtensionIndex;
221 CRefItem(UInt32 index, const CUpdateItem &ui, bool sortByType):
222 UpdateItem(&ui),
223 Index(index),
224 ExtensionPos(0),
225 NamePos(0),
226 ExtensionIndex(0)
227 {
228 if (sortByType)
229 {
230 int slashPos = GetReverseSlashPos(ui.Name);
231 NamePos = ((slashPos >= 0) ? (slashPos + 1) : 0);
232 int dotPos = ui.Name.ReverseFind(L'.');
233 if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0))
234 ExtensionPos = ui.Name.Length();
235 else
236 {
237 ExtensionPos = dotPos + 1;
238 UString us = ui.Name.Mid(ExtensionPos);
239 if (!us.IsEmpty())
240 {
241 us.MakeLower();
242 int i;
243 AString s;
244 for (i = 0; i < us.Length(); i++)
245 {
246 wchar_t c = us[i];
247 if (c >= 0x80)
248 break;
249 s += (char)c;
250 }
251 if (i == us.Length())
252 ExtensionIndex = GetExtIndex(s);
253 else
254 ExtensionIndex = 0;
255 }
256 }
257 }
258 }
259 };
260
261 static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *para m)
262 {
263 const CRefItem &a1 = *p1;
264 const CRefItem &a2 = *p2;
265 const CUpdateItem &u1 = *a1.UpdateItem;
266 const CUpdateItem &u2 = *a2.UpdateItem;
267 int n;
268 if (u1.IsDir != u2.IsDir)
269 return (u1.IsDir) ? 1 : -1;
270 if (u1.IsDir)
271 {
272 if (u1.IsAnti != u2.IsAnti)
273 return (u1.IsAnti ? 1 : -1);
274 n = MyStringCompareNoCase(u1.Name, u2.Name);
275 return -n;
276 }
277 bool sortByType = *(bool *)param;
278 if (sortByType)
279 {
280 RINOZ(MyCompare(a1.ExtensionIndex, a2.ExtensionIndex))
281 RINOZ(MyStringCompareNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.Extensio nPos));
282 RINOZ(MyStringCompareNoCase(u1.Name + a1.NamePos, u2.Name + a2.NamePos));
283 if (!u1.MTimeDefined && u2.MTimeDefined) return 1;
284 if (u1.MTimeDefined && !u2.MTimeDefined) return -1;
285 if (u1.MTimeDefined && u2.MTimeDefined) RINOZ(MyCompare(u1.MTime, u2.MTime)) ;
286 RINOZ(MyCompare(u1.Size, u2.Size))
287 }
288 return MyStringCompareNoCase(u1.Name, u2.Name);
289 }
290
291 struct CSolidGroup
292 {
293 CCompressionMethodMode Method;
294 CRecordVector<UInt32> Indices;
295 };
296
297 static wchar_t *g_ExeExts[] =
298 {
299 L"dll",
300 L"exe",
301 L"ocx",
302 L"sfx",
303 L"sys"
304 };
305
306 static bool IsExeFile(const UString &ext)
307 {
308 for (int i = 0; i < sizeof(g_ExeExts) / sizeof(g_ExeExts[0]); i++)
309 if (ext.CompareNoCase(g_ExeExts[i]) == 0)
310 return true;
311 return false;
312 }
313
314 static const UInt64 k_LZMA = 0x030101;
315 static const UInt64 k_BCJ = 0x03030103;
316 static const UInt64 k_BCJ2 = 0x0303011B;
317
318 static bool GetMethodFull(UInt64 methodID,
319 UInt32 numInStreams, CMethodFull &methodResult)
320 {
321 methodResult.Id = methodID;
322 methodResult.NumInStreams = numInStreams;
323 methodResult.NumOutStreams = 1;
324 return true;
325 }
326
327 static bool MakeExeMethod(const CCompressionMethodMode &method,
328 bool bcj2Filter, CCompressionMethodMode &exeMethod)
329 {
330 exeMethod = method;
331 if (bcj2Filter)
332 {
333 CMethodFull methodFull;
334 if (!GetMethodFull(k_BCJ2, 4, methodFull))
335 return false;
336 exeMethod.Methods.Insert(0, methodFull);
337 if (!GetMethodFull(k_LZMA, 1, methodFull))
338 return false;
339 {
340 CProp prop;
341 prop.Id = NCoderPropID::kAlgorithm;
342 prop.Value = kAlgorithmForBCJ2_LZMA;
343 methodFull.Props.Add(prop);
344 }
345 {
346 CProp prop;
347 prop.Id = NCoderPropID::kMatchFinder;
348 prop.Value = kMatchFinderForBCJ2_LZMA;
349 methodFull.Props.Add(prop);
350 }
351 {
352 CProp prop;
353 prop.Id = NCoderPropID::kDictionarySize;
354 prop.Value = kDictionaryForBCJ2_LZMA;
355 methodFull.Props.Add(prop);
356 }
357 {
358 CProp prop;
359 prop.Id = NCoderPropID::kNumFastBytes;
360 prop.Value = kNumFastBytesForBCJ2_LZMA;
361 methodFull.Props.Add(prop);
362 }
363
364 exeMethod.Methods.Add(methodFull);
365 exeMethod.Methods.Add(methodFull);
366 CBind bind;
367
368 bind.OutCoder = 0;
369 bind.InStream = 0;
370
371 bind.InCoder = 1;
372 bind.OutStream = 0;
373 exeMethod.Binds.Add(bind);
374
375 bind.InCoder = 2;
376 bind.OutStream = 1;
377 exeMethod.Binds.Add(bind);
378
379 bind.InCoder = 3;
380 bind.OutStream = 2;
381 exeMethod.Binds.Add(bind);
382 }
383 else
384 {
385 CMethodFull methodFull;
386 if (!GetMethodFull(k_BCJ, 1, methodFull))
387 return false;
388 exeMethod.Methods.Insert(0, methodFull);
389 CBind bind;
390 bind.OutCoder = 0;
391 bind.InStream = 0;
392 bind.InCoder = 1;
393 bind.OutStream = 0;
394 exeMethod.Binds.Add(bind);
395 }
396 return true;
397 }
398
399 static void SplitFilesToGroups(
400 const CCompressionMethodMode &method,
401 bool useFilters, bool maxFilter,
402 const CObjectVector<CUpdateItem> &updateItems,
403 CObjectVector<CSolidGroup> &groups)
404 {
405 if (method.Methods.Size() != 1 || method.Binds.Size() != 0)
406 useFilters = false;
407 groups.Clear();
408 groups.Add(CSolidGroup());
409 groups.Add(CSolidGroup());
410 CSolidGroup &generalGroup = groups[0];
411 CSolidGroup &exeGroup = groups[1];
412 generalGroup.Method = method;
413 int i;
414 for (i = 0; i < updateItems.Size(); i++)
415 {
416 const CUpdateItem &ui = updateItems[i];
417 if (!ui.NewData)
418 continue;
419 if (!ui.HasStream())
420 continue;
421 if (useFilters)
422 {
423 const UString name = ui.Name;
424 int dotPos = name.ReverseFind(L'.');
425 if (dotPos >= 0)
426 {
427 UString ext = name.Mid(dotPos + 1);
428 if (IsExeFile(ext))
429 {
430 exeGroup.Indices.Add(i);
431 continue;
432 }
433 }
434 }
435 generalGroup.Indices.Add(i);
436 }
437 if (exeGroup.Indices.Size() > 0)
438 if (!MakeExeMethod(method, maxFilter, exeGroup.Method))
439 exeGroup.Method = method;
440 for (i = 0; i < groups.Size();)
441 if (groups[i].Indices.Size() == 0)
442 groups.Delete(i);
443 else
444 i++;
445 }
446
447 static void FromUpdateItemToFileItem(const CUpdateItem &ui,
448 CFileItem &file, CFileItem2 &file2)
449 {
450 file.Name = NItemName::MakeLegalName(ui.Name);
451 if (ui.AttribDefined)
452 file.SetAttrib(ui.Attrib);
453
454 file2.CTime = ui.CTime; file2.CTimeDefined = ui.CTimeDefined;
455 file2.ATime = ui.ATime; file2.ATimeDefined = ui.ATimeDefined;
456 file2.MTime = ui.MTime; file2.MTimeDefined = ui.MTimeDefined;
457 file2.IsAnti = ui.IsAnti;
458 file2.StartPosDefined = false;
459
460 file.Size = ui.Size;
461 file.IsDir = ui.IsDir;
462 file.HasStream = ui.HasStream();
463 }
464
465 static HRESULT Update2(
466 DECL_EXTERNAL_CODECS_LOC_VARS
467 IInStream *inStream,
468 const CArchiveDatabaseEx *db,
469 const CObjectVector<CUpdateItem> &updateItems,
470 COutArchive &archive,
471 CArchiveDatabase &newDatabase,
472 ISequentialOutStream *seqOutStream,
473 IArchiveUpdateCallback *updateCallback,
474 const CUpdateOptions &options)
475 {
476 UInt64 numSolidFiles = options.NumSolidFiles;
477 if (numSolidFiles == 0)
478 numSolidFiles = 1;
479 /*
480 CMyComPtr<IOutStream> outStream;
481 RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream));
482 if (!outStream)
483 return E_NOTIMPL;
484 */
485
486 UInt64 startBlockSize = db != 0 ? db->ArchiveInfo.StartPosition: 0;
487 if (startBlockSize > 0 && !options.RemoveSfxBlock)
488 {
489 RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL));
490 }
491
492 CRecordVector<int> fileIndexToUpdateIndexMap;
493 if (db != 0)
494 {
495 fileIndexToUpdateIndexMap.Reserve(db->Files.Size());
496 for (int i = 0; i < db->Files.Size(); i++)
497 fileIndexToUpdateIndexMap.Add(-1);
498 }
499 int i;
500 for(i = 0; i < updateItems.Size(); i++)
501 {
502 int index = updateItems[i].IndexInArchive;
503 if (index != -1)
504 fileIndexToUpdateIndexMap[index] = i;
505 }
506
507 CRecordVector<int> folderRefs;
508 if (db != 0)
509 {
510 for(i = 0; i < db->Folders.Size(); i++)
511 {
512 CNum indexInFolder = 0;
513 CNum numCopyItems = 0;
514 CNum numUnpackStreams = db->NumUnpackStreamsVector[i];
515 for (CNum fileIndex = db->FolderStartFileIndex[i];
516 indexInFolder < numUnpackStreams; fileIndex++)
517 {
518 if (db->Files[fileIndex].HasStream)
519 {
520 indexInFolder++;
521 int updateIndex = fileIndexToUpdateIndexMap[fileIndex];
522 if (updateIndex >= 0)
523 if (!updateItems[updateIndex].NewData)
524 numCopyItems++;
525 }
526 }
527 if (numCopyItems != numUnpackStreams && numCopyItems != 0)
528 return E_NOTIMPL; // It needs repacking !!!
529 if (numCopyItems > 0)
530 folderRefs.Add(i);
531 }
532 folderRefs.Sort(CompareFolderRefs, (void *)db);
533 }
534
535 ////////////////////////////
536
537 RINOK(archive.Create(seqOutStream, false));
538 RINOK(archive.SkeepPrefixArchiveHeader());
539 UInt64 complexity = 0;
540 for(i = 0; i < folderRefs.Size(); i++)
541 complexity += db->GetFolderFullPackSize(folderRefs[i]);
542 UInt64 inSizeForReduce = 0;
543 for(i = 0; i < updateItems.Size(); i++)
544 {
545 const CUpdateItem &ui = updateItems[i];
546 if (ui.NewData)
547 {
548 complexity += ui.Size;
549 if (numSolidFiles == 1)
550 {
551 if (ui.Size > inSizeForReduce)
552 inSizeForReduce = ui.Size;
553 }
554 else
555 inSizeForReduce += ui.Size;
556 }
557 }
558 RINOK(updateCallback->SetTotal(complexity));
559 complexity = 0;
560 RINOK(updateCallback->SetCompleted(&complexity));
561
562
563 CLocalProgress *lps = new CLocalProgress;
564 CMyComPtr<ICompressProgressInfo> progress = lps;
565 lps->Init(updateCallback, true);
566
567 /////////////////////////////////////////
568 // Write Copy Items
569
570 for(i = 0; i < folderRefs.Size(); i++)
571 {
572 int folderIndex = folderRefs[i];
573
574 lps->ProgressOffset = complexity;
575 UInt64 packSize = db->GetFolderFullPackSize(folderIndex);
576 RINOK(WriteRange(inStream, archive.SeqStream,
577 db->GetFolderStreamPos(folderIndex, 0), packSize, progress));
578 complexity += packSize;
579
580 const CFolder &folder = db->Folders[folderIndex];
581 CNum startIndex = db->FolderStartPackStreamIndex[folderIndex];
582 for (int j = 0; j < folder.PackStreams.Size(); j++)
583 {
584 newDatabase.PackSizes.Add(db->PackSizes[startIndex + j]);
585 // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]);
586 // newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]);
587 }
588 newDatabase.Folders.Add(folder);
589
590 CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];
591 newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams);
592
593 CNum indexInFolder = 0;
594 for (CNum fi = db->FolderStartFileIndex[folderIndex];
595 indexInFolder < numUnpackStreams; fi++)
596 {
597 CFileItem file;
598 CFileItem2 file2;
599 db->GetFile(fi, file, file2);
600 if (file.HasStream)
601 {
602 indexInFolder++;
603 int updateIndex = fileIndexToUpdateIndexMap[fi];
604 if (updateIndex >= 0)
605 {
606 const CUpdateItem &ui = updateItems[updateIndex];
607 if (ui.NewProperties)
608 {
609 CFileItem uf;
610 FromUpdateItemToFileItem(ui, uf, file2);
611 uf.Size = file.Size;
612 uf.Crc = file.Crc;
613 uf.CrcDefined = file.CrcDefined;
614 uf.HasStream = file.HasStream;
615 file = uf;
616 }
617 }
618 newDatabase.AddFile(file, file2);
619 }
620 }
621 }
622
623 folderRefs.ClearAndFree();
624 fileIndexToUpdateIndexMap.ClearAndFree();
625
626 /////////////////////////////////////////
627 // Compress New Files
628
629 CObjectVector<CSolidGroup> groups;
630 SplitFilesToGroups(*options.Method, options.UseFilters, options.MaxFilter,
631 updateItems, groups);
632
633 const UInt32 kMinReduceSize = (1 << 16);
634 if (inSizeForReduce < kMinReduceSize)
635 inSizeForReduce = kMinReduceSize;
636
637 for (int groupIndex = 0; groupIndex < groups.Size(); groupIndex++)
638 {
639 const CSolidGroup &group = groups[groupIndex];
640 int numFiles = group.Indices.Size();
641 if (numFiles == 0)
642 continue;
643 CRecordVector<CRefItem> refItems;
644 refItems.Reserve(numFiles);
645 bool sortByType = (numSolidFiles > 1);
646 for (i = 0; i < numFiles; i++)
647 refItems.Add(CRefItem(group.Indices[i], updateItems[group.Indices[i]], sor tByType));
648 refItems.Sort(CompareUpdateItems, (void *)&sortByType);
649
650 CRecordVector<UInt32> indices;
651 indices.Reserve(numFiles);
652
653 for (i = 0; i < numFiles; i++)
654 {
655 UInt32 index = refItems[i].Index;
656 indices.Add(index);
657 /*
658 const CUpdateItem &ui = updateItems[index];
659 CFileItem file;
660 if (ui.NewProperties)
661 FromUpdateItemToFileItem(ui, file);
662 else
663 file = db.Files[ui.IndexInArchive];
664 if (file.IsAnti || file.IsDir)
665 return E_FAIL;
666 newDatabase.Files.Add(file);
667 */
668 }
669
670 CEncoder encoder(group.Method);
671
672 for (i = 0; i < numFiles;)
673 {
674 UInt64 totalSize = 0;
675 int numSubFiles;
676 UString prevExtension;
677 for (numSubFiles = 0; i + numSubFiles < numFiles &&
678 numSubFiles < numSolidFiles; numSubFiles++)
679 {
680 const CUpdateItem &ui = updateItems[indices[i + numSubFiles]];
681 totalSize += ui.Size;
682 if (totalSize > options.NumSolidBytes)
683 break;
684 if (options.SolidExtension)
685 {
686 UString ext = ui.GetExtension();
687 if (numSubFiles == 0)
688 prevExtension = ext;
689 else
690 if (ext.CompareNoCase(prevExtension) != 0)
691 break;
692 }
693 }
694 if (numSubFiles < 1)
695 numSubFiles = 1;
696
697 CFolderInStream *inStreamSpec = new CFolderInStream;
698 CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec);
699 inStreamSpec->Init(updateCallback, &indices[i], numSubFiles);
700
701 CFolder folderItem;
702
703 int startPackIndex = newDatabase.PackSizes.Size();
704 RINOK(encoder.Encode(
705 EXTERNAL_CODECS_LOC_VARS
706 solidInStream, NULL, &inSizeForReduce, folderItem,
707 archive.SeqStream, newDatabase.PackSizes, progress));
708
709 for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)
710 lps->OutSize += newDatabase.PackSizes[startPackIndex];
711
712 lps->InSize += folderItem.GetUnpackSize();
713 // for()
714 // newDatabase.PackCRCsDefined.Add(false);
715 // newDatabase.PackCRCs.Add(0);
716
717 newDatabase.Folders.Add(folderItem);
718
719 CNum numUnpackStreams = 0;
720 for (int subIndex = 0; subIndex < numSubFiles; subIndex++)
721 {
722 const CUpdateItem &ui = updateItems[indices[i + subIndex]];
723 CFileItem file;
724 CFileItem2 file2;
725 if (ui.NewProperties)
726 FromUpdateItemToFileItem(ui, file, file2);
727 else
728 db->GetFile(ui.IndexInArchive, file, file2);
729 if (file2.IsAnti || file.IsDir)
730 return E_FAIL;
731
732 /*
733 CFileItem &file = newDatabase.Files[
734 startFileIndexInDatabase + i + subIndex];
735 */
736 if (!inStreamSpec->Processed[subIndex])
737 {
738 continue;
739 // file.Name += L".locked";
740 }
741
742 file.Crc = inStreamSpec->CRCs[subIndex];
743 file.Size = inStreamSpec->Sizes[subIndex];
744 if (file.Size != 0)
745 {
746 file.CrcDefined = true;
747 file.HasStream = true;
748 numUnpackStreams++;
749 }
750 else
751 {
752 file.CrcDefined = false;
753 file.HasStream = false;
754 }
755 newDatabase.AddFile(file, file2);
756 }
757 // numUnpackStreams = 0 is very bad case for locked files
758 // v3.13 doesn't understand it.
759 newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams);
760 i += numSubFiles;
761 }
762 }
763
764 groups.ClearAndFree();
765
766 {
767 /////////////////////////////////////////
768 // Write Empty Files & Folders
769
770 CRecordVector<int> emptyRefs;
771 for(i = 0; i < updateItems.Size(); i++)
772 {
773 const CUpdateItem &ui = updateItems[i];
774 if (ui.NewData)
775 {
776 if (ui.HasStream())
777 continue;
778 }
779 else
780 if (ui.IndexInArchive != -1)
781 if (db->Files[ui.IndexInArchive].HasStream)
782 continue;
783 emptyRefs.Add(i);
784 }
785 emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems);
786 for (i = 0; i < emptyRefs.Size(); i++)
787 {
788 const CUpdateItem &ui = updateItems[emptyRefs[i]];
789 CFileItem file;
790 CFileItem2 file2;
791 if (ui.NewProperties)
792 FromUpdateItemToFileItem(ui, file, file2);
793 else
794 db->GetFile(ui.IndexInArchive, file, file2);
795 newDatabase.AddFile(file, file2);
796 }
797 }
798
799 newDatabase.ReserveDown();
800 return S_OK;
801 }
802
803 HRESULT Update(
804 DECL_EXTERNAL_CODECS_LOC_VARS
805 IInStream *inStream,
806 const CArchiveDatabaseEx *db,
807 const CObjectVector<CUpdateItem> &updateItems,
808 COutArchive &archive,
809 CArchiveDatabase &newDatabase,
810 ISequentialOutStream *seqOutStream,
811 IArchiveUpdateCallback *updateCallback,
812 const CUpdateOptions &options)
813 {
814 return Update2(
815 EXTERNAL_CODECS_LOC_VARS
816 inStream, db, updateItems,
817 archive, newDatabase, seqOutStream, updateCallback, options);
818 }
819
820 }}
OLDNEW
« no previous file with comments | « third_party/lzma/v4_65/files/CPP/7zip/Archive/7z/7zUpdate.h ('k') | third_party/lzma/v4_65/files/CPP/7zip/Archive/7z/StdAfx.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698