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

Side by Side Diff: third_party/lzma/v4_65/files/CPP/7zip/Archive/7z/7zOut.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 // 7zOut.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../../Common/AutoPtr.h"
6 #include "../../Common/StreamObjects.h"
7
8 #include "7zOut.h"
9
10 extern "C"
11 {
12 #include "../../../../C/7zCrc.h"
13 }
14
15 static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size)
16 {
17 while (size > 0)
18 {
19 UInt32 curSize = (UInt32)MyMin(size, (size_t)0xFFFFFFFF);
20 UInt32 processedSize;
21 RINOK(stream->Write(data, curSize, &processedSize));
22 if (processedSize == 0)
23 return E_FAIL;
24 data = (const void *)((const Byte *)data + processedSize);
25 size -= processedSize;
26 }
27 return S_OK;
28 }
29
30 namespace NArchive {
31 namespace N7z {
32
33 HRESULT COutArchive::WriteDirect(const void *data, UInt32 size)
34 {
35 return ::WriteBytes(SeqStream, data, size);
36 }
37
38 HRESULT COutArchive::WriteSignature()
39 {
40 Byte buf[8];
41 memcpy(buf, kSignature, kSignatureSize);
42 buf[kSignatureSize] = kMajorVersion;
43 buf[kSignatureSize + 1] = 3;
44 return WriteDirect(buf, 8);
45 }
46
47 #ifdef _7Z_VOL
48 HRESULT COutArchive::WriteFinishSignature()
49 {
50 RINOK(WriteDirect(kFinishSignature, kSignatureSize));
51 CArchiveVersion av;
52 av.Major = kMajorVersion;
53 av.Minor = 2;
54 RINOK(WriteDirectByte(av.Major));
55 return WriteDirectByte(av.Minor);
56 }
57 #endif
58
59 static void SetUInt32(Byte *p, UInt32 d)
60 {
61 for (int i = 0; i < 4; i++, d >>= 8)
62 p[i] = (Byte)d;
63 }
64
65 static void SetUInt64(Byte *p, UInt64 d)
66 {
67 for (int i = 0; i < 8; i++, d >>= 8)
68 p[i] = (Byte)d;
69 }
70
71 HRESULT COutArchive::WriteStartHeader(const CStartHeader &h)
72 {
73 Byte buf[24];
74 SetUInt64(buf + 4, h.NextHeaderOffset);
75 SetUInt64(buf + 12, h.NextHeaderSize);
76 SetUInt32(buf + 20, h.NextHeaderCRC);
77 SetUInt32(buf, CrcCalc(buf + 4, 20));
78 return WriteDirect(buf, 24);
79 }
80
81 #ifdef _7Z_VOL
82 HRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h)
83 {
84 CCRC crc;
85 crc.UpdateUInt64(h.NextHeaderOffset);
86 crc.UpdateUInt64(h.NextHeaderSize);
87 crc.UpdateUInt32(h.NextHeaderCRC);
88 crc.UpdateUInt64(h.ArchiveStartOffset);
89 crc.UpdateUInt64(h.AdditionalStartBlockSize);
90 RINOK(WriteDirectUInt32(crc.GetDigest()));
91 RINOK(WriteDirectUInt64(h.NextHeaderOffset));
92 RINOK(WriteDirectUInt64(h.NextHeaderSize));
93 RINOK(WriteDirectUInt32(h.NextHeaderCRC));
94 RINOK(WriteDirectUInt64(h.ArchiveStartOffset));
95 return WriteDirectUInt64(h.AdditionalStartBlockSize);
96 }
97 #endif
98
99 HRESULT COutArchive::Create(ISequentialOutStream *stream, bool endMarker)
100 {
101 Close();
102 #ifdef _7Z_VOL
103 // endMarker = false;
104 _endMarker = endMarker;
105 #endif
106 SeqStream = stream;
107 if (!endMarker)
108 {
109 SeqStream.QueryInterface(IID_IOutStream, &Stream);
110 if (!Stream)
111 {
112 return E_NOTIMPL;
113 // endMarker = true;
114 }
115 }
116 #ifdef _7Z_VOL
117 if (endMarker)
118 {
119 /*
120 CStartHeader sh;
121 sh.NextHeaderOffset = (UInt32)(Int32)-1;
122 sh.NextHeaderSize = (UInt32)(Int32)-1;
123 sh.NextHeaderCRC = 0;
124 WriteStartHeader(sh);
125 */
126 }
127 else
128 #endif
129 {
130 if (!Stream)
131 return E_FAIL;
132 RINOK(WriteSignature());
133 RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_prefixHeaderPos));
134 }
135 return S_OK;
136 }
137
138 void COutArchive::Close()
139 {
140 SeqStream.Release();
141 Stream.Release();
142 }
143
144 HRESULT COutArchive::SkeepPrefixArchiveHeader()
145 {
146 #ifdef _7Z_VOL
147 if (_endMarker)
148 return S_OK;
149 #endif
150 return Stream->Seek(24, STREAM_SEEK_CUR, NULL);
151 }
152
153 UInt64 COutArchive::GetPos() const
154 {
155 if (_countMode)
156 return _countSize;
157 if (_writeToStream)
158 return _outByte.GetProcessedSize();
159 return _outByte2.GetPos();
160 }
161
162 void COutArchive::WriteBytes(const void *data, size_t size)
163 {
164 if (_countMode)
165 _countSize += size;
166 else if (_writeToStream)
167 {
168 _outByte.WriteBytes(data, size);
169 _crc = CrcUpdate(_crc, data, size);
170 }
171 else
172 _outByte2.WriteBytes(data, size);
173 }
174
175 void COutArchive::WriteByte(Byte b)
176 {
177 if (_countMode)
178 _countSize++;
179 else if (_writeToStream)
180 {
181 _outByte.WriteByte(b);
182 _crc = CRC_UPDATE_BYTE(_crc, b);
183 }
184 else
185 _outByte2.WriteByte(b);
186 }
187
188 void COutArchive::WriteUInt32(UInt32 value)
189 {
190 for (int i = 0; i < 4; i++)
191 {
192 WriteByte((Byte)value);
193 value >>= 8;
194 }
195 }
196
197 void COutArchive::WriteUInt64(UInt64 value)
198 {
199 for (int i = 0; i < 8; i++)
200 {
201 WriteByte((Byte)value);
202 value >>= 8;
203 }
204 }
205
206 void COutArchive::WriteNumber(UInt64 value)
207 {
208 Byte firstByte = 0;
209 Byte mask = 0x80;
210 int i;
211 for (i = 0; i < 8; i++)
212 {
213 if (value < ((UInt64(1) << ( 7 * (i + 1)))))
214 {
215 firstByte |= Byte(value >> (8 * i));
216 break;
217 }
218 firstByte |= mask;
219 mask >>= 1;
220 }
221 WriteByte(firstByte);
222 for (;i > 0; i--)
223 {
224 WriteByte((Byte)value);
225 value >>= 8;
226 }
227 }
228
229 static UInt32 GetBigNumberSize(UInt64 value)
230 {
231 int i;
232 for (i = 1; i < 9; i++)
233 if (value < (((UInt64)1 << (i * 7))))
234 break;
235 return i;
236 }
237
238 #ifdef _7Z_VOL
239 UInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool prop s)
240 {
241 UInt32 result = GetBigNumberSize(dataSize) * 2 + 41;
242 if (nameLength != 0)
243 {
244 nameLength = (nameLength + 1) * 2;
245 result += nameLength + GetBigNumberSize(nameLength) + 2;
246 }
247 if (props)
248 {
249 result += 20;
250 }
251 if (result >= 128)
252 result++;
253 result += kSignatureSize + 2 + kFinishHeaderSize;
254 return result;
255 }
256
257 UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props)
258 {
259 UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props);
260 int testSize;
261 if (volSize > headersSizeBase)
262 testSize = volSize - headersSizeBase;
263 else
264 testSize = 1;
265 UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, prop s);
266 UInt64 pureSize = 1;
267 if (volSize > headersSize)
268 pureSize = volSize - headersSize;
269 return pureSize;
270 }
271 #endif
272
273 void COutArchive::WriteFolder(const CFolder &folder)
274 {
275 WriteNumber(folder.Coders.Size());
276 int i;
277 for (i = 0; i < folder.Coders.Size(); i++)
278 {
279 const CCoderInfo &coder = folder.Coders[i];
280 {
281 size_t propsSize = coder.Props.GetCapacity();
282
283 UInt64 id = coder.MethodID;
284 int idSize;
285 for (idSize = 1; idSize < sizeof(id); idSize++)
286 if ((id >> (8 * idSize)) == 0)
287 break;
288 BYTE longID[15];
289 for (int t = idSize - 1; t >= 0 ; t--, id >>= 8)
290 longID[t] = (Byte)(id & 0xFF);
291 Byte b;
292 b = (Byte)(idSize & 0xF);
293 bool isComplex = !coder.IsSimpleCoder();
294 b |= (isComplex ? 0x10 : 0);
295 b |= ((propsSize != 0) ? 0x20 : 0 );
296 WriteByte(b);
297 WriteBytes(longID, idSize);
298 if (isComplex)
299 {
300 WriteNumber(coder.NumInStreams);
301 WriteNumber(coder.NumOutStreams);
302 }
303 if (propsSize == 0)
304 continue;
305 WriteNumber(propsSize);
306 WriteBytes(coder.Props, propsSize);
307 }
308 }
309 for (i = 0; i < folder.BindPairs.Size(); i++)
310 {
311 const CBindPair &bindPair = folder.BindPairs[i];
312 WriteNumber(bindPair.InIndex);
313 WriteNumber(bindPair.OutIndex);
314 }
315 if (folder.PackStreams.Size() > 1)
316 for (i = 0; i < folder.PackStreams.Size(); i++)
317 {
318 WriteNumber(folder.PackStreams[i]);
319 }
320 }
321
322 void COutArchive::WriteBoolVector(const CBoolVector &boolVector)
323 {
324 Byte b = 0;
325 Byte mask = 0x80;
326 for (int i = 0; i < boolVector.Size(); i++)
327 {
328 if (boolVector[i])
329 b |= mask;
330 mask >>= 1;
331 if (mask == 0)
332 {
333 WriteByte(b);
334 mask = 0x80;
335 b = 0;
336 }
337 }
338 if (mask != 0x80)
339 WriteByte(b);
340 }
341
342
343 void COutArchive::WriteHashDigests(
344 const CRecordVector<bool> &digestsDefined,
345 const CRecordVector<UInt32> &digests)
346 {
347 int numDefined = 0;
348 int i;
349 for (i = 0; i < digestsDefined.Size(); i++)
350 if (digestsDefined[i])
351 numDefined++;
352 if (numDefined == 0)
353 return;
354
355 WriteByte(NID::kCRC);
356 if (numDefined == digestsDefined.Size())
357 WriteByte(1);
358 else
359 {
360 WriteByte(0);
361 WriteBoolVector(digestsDefined);
362 }
363 for (i = 0; i < digests.Size(); i++)
364 if (digestsDefined[i])
365 WriteUInt32(digests[i]);
366 }
367
368 void COutArchive::WritePackInfo(
369 UInt64 dataOffset,
370 const CRecordVector<UInt64> &packSizes,
371 const CRecordVector<bool> &packCRCsDefined,
372 const CRecordVector<UInt32> &packCRCs)
373 {
374 if (packSizes.IsEmpty())
375 return;
376 WriteByte(NID::kPackInfo);
377 WriteNumber(dataOffset);
378 WriteNumber(packSizes.Size());
379 WriteByte(NID::kSize);
380 for (int i = 0; i < packSizes.Size(); i++)
381 WriteNumber(packSizes[i]);
382
383 WriteHashDigests(packCRCsDefined, packCRCs);
384
385 WriteByte(NID::kEnd);
386 }
387
388 void COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders)
389 {
390 if (folders.IsEmpty())
391 return;
392
393 WriteByte(NID::kUnpackInfo);
394
395 WriteByte(NID::kFolder);
396 WriteNumber(folders.Size());
397 {
398 WriteByte(0);
399 for (int i = 0; i < folders.Size(); i++)
400 WriteFolder(folders[i]);
401 }
402
403 WriteByte(NID::kCodersUnpackSize);
404 int i;
405 for (i = 0; i < folders.Size(); i++)
406 {
407 const CFolder &folder = folders[i];
408 for (int j = 0; j < folder.UnpackSizes.Size(); j++)
409 WriteNumber(folder.UnpackSizes[j]);
410 }
411
412 CRecordVector<bool> unpackCRCsDefined;
413 CRecordVector<UInt32> unpackCRCs;
414 for (i = 0; i < folders.Size(); i++)
415 {
416 const CFolder &folder = folders[i];
417 unpackCRCsDefined.Add(folder.UnpackCRCDefined);
418 unpackCRCs.Add(folder.UnpackCRC);
419 }
420 WriteHashDigests(unpackCRCsDefined, unpackCRCs);
421
422 WriteByte(NID::kEnd);
423 }
424
425 void COutArchive::WriteSubStreamsInfo(
426 const CObjectVector<CFolder> &folders,
427 const CRecordVector<CNum> &numUnpackStreamsInFolders,
428 const CRecordVector<UInt64> &unpackSizes,
429 const CRecordVector<bool> &digestsDefined,
430 const CRecordVector<UInt32> &digests)
431 {
432 WriteByte(NID::kSubStreamsInfo);
433
434 int i;
435 for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
436 {
437 if (numUnpackStreamsInFolders[i] != 1)
438 {
439 WriteByte(NID::kNumUnpackStream);
440 for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
441 WriteNumber(numUnpackStreamsInFolders[i]);
442 break;
443 }
444 }
445
446
447 bool needFlag = true;
448 CNum index = 0;
449 for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
450 for (CNum j = 0; j < numUnpackStreamsInFolders[i]; j++)
451 {
452 if (j + 1 != numUnpackStreamsInFolders[i])
453 {
454 if (needFlag)
455 WriteByte(NID::kSize);
456 needFlag = false;
457 WriteNumber(unpackSizes[index]);
458 }
459 index++;
460 }
461
462 CRecordVector<bool> digestsDefined2;
463 CRecordVector<UInt32> digests2;
464
465 int digestIndex = 0;
466 for (i = 0; i < folders.Size(); i++)
467 {
468 int numSubStreams = (int)numUnpackStreamsInFolders[i];
469 if (numSubStreams == 1 && folders[i].UnpackCRCDefined)
470 digestIndex++;
471 else
472 for (int j = 0; j < numSubStreams; j++, digestIndex++)
473 {
474 digestsDefined2.Add(digestsDefined[digestIndex]);
475 digests2.Add(digests[digestIndex]);
476 }
477 }
478 WriteHashDigests(digestsDefined2, digests2);
479 WriteByte(NID::kEnd);
480 }
481
482 void COutArchive::SkipAlign(unsigned /* pos */, unsigned /* alignSize */)
483 {
484 return;
485 }
486
487 /*
488 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field.
489
490 void COutArchive::SkipAlign(unsigned pos, unsigned alignSize)
491 {
492 pos += (unsigned)GetPos();
493 pos &= (alignSize - 1);
494 if (pos == 0)
495 return;
496 unsigned skip = alignSize - pos;
497 if (skip < 2)
498 skip += alignSize;
499 skip -= 2;
500 WriteByte(NID::kDummy);
501 WriteByte((Byte)skip);
502 for (unsigned i = 0; i < skip; i++)
503 WriteByte(0);
504 }
505 */
506
507 void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, B yte type, unsigned itemSize)
508 {
509 const UInt64 bvSize = (numDefined == v.Size()) ? 0 : (v.Size() + 7) / 8;
510 const UInt64 dataSize = (UInt64)numDefined * itemSize + bvSize + 2;
511 SkipAlign(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSiz e);
512
513 WriteByte(type);
514 WriteNumber(dataSize);
515 if (numDefined == v.Size())
516 WriteByte(1);
517 else
518 {
519 WriteByte(0);
520 WriteBoolVector(v);
521 }
522 WriteByte(0);
523 }
524
525 void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type)
526 {
527 int numDefined = 0;
528
529 int i;
530 for (i = 0; i < v.Defined.Size(); i++)
531 if (v.Defined[i])
532 numDefined++;
533
534 if (numDefined == 0)
535 return;
536
537 WriteAlignedBoolHeader(v.Defined, numDefined, type, 8);
538
539 for (i = 0; i < v.Defined.Size(); i++)
540 if (v.Defined[i])
541 WriteUInt64(v.Values[i]);
542 }
543
544 HRESULT COutArchive::EncodeStream(
545 DECL_EXTERNAL_CODECS_LOC_VARS
546 CEncoder &encoder, const Byte *data, size_t dataSize,
547 CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders)
548 {
549 CSequentialInStreamImp *streamSpec = new CSequentialInStreamImp;
550 CMyComPtr<ISequentialInStream> stream = streamSpec;
551 streamSpec->Init(data, dataSize);
552 CFolder folderItem;
553 folderItem.UnpackCRCDefined = true;
554 folderItem.UnpackCRC = CrcCalc(data, dataSize);
555 UInt64 dataSize64 = dataSize;
556 RINOK(encoder.Encode(
557 EXTERNAL_CODECS_LOC_VARS
558 stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL))
559 folders.Add(folderItem);
560 return S_OK;
561 }
562
563 HRESULT COutArchive::EncodeStream(
564 DECL_EXTERNAL_CODECS_LOC_VARS
565 CEncoder &encoder, const CByteBuffer &data,
566 CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders)
567 {
568 return EncodeStream(
569 EXTERNAL_CODECS_LOC_VARS
570 encoder, data, data.GetCapacity(), packSizes, folders);
571 }
572
573 void COutArchive::WriteHeader(
574 const CArchiveDatabase &db,
575 const CHeaderOptions &headerOptions,
576 UInt64 &headerOffset)
577 {
578 int i;
579
580 UInt64 packedSize = 0;
581 for (i = 0; i < db.PackSizes.Size(); i++)
582 packedSize += db.PackSizes[i];
583
584 headerOffset = packedSize;
585
586 WriteByte(NID::kHeader);
587
588 // Archive Properties
589
590 if (db.Folders.Size() > 0)
591 {
592 WriteByte(NID::kMainStreamsInfo);
593 WritePackInfo(0, db.PackSizes,
594 db.PackCRCsDefined,
595 db.PackCRCs);
596
597 WriteUnpackInfo(db.Folders);
598
599 CRecordVector<UInt64> unpackSizes;
600 CRecordVector<bool> digestsDefined;
601 CRecordVector<UInt32> digests;
602 for (i = 0; i < db.Files.Size(); i++)
603 {
604 const CFileItem &file = db.Files[i];
605 if (!file.HasStream)
606 continue;
607 unpackSizes.Add(file.Size);
608 digestsDefined.Add(file.CrcDefined);
609 digests.Add(file.Crc);
610 }
611
612 WriteSubStreamsInfo(
613 db.Folders,
614 db.NumUnpackStreamsVector,
615 unpackSizes,
616 digestsDefined,
617 digests);
618 WriteByte(NID::kEnd);
619 }
620
621 if (db.Files.IsEmpty())
622 {
623 WriteByte(NID::kEnd);
624 return;
625 }
626
627 WriteByte(NID::kFilesInfo);
628 WriteNumber(db.Files.Size());
629
630 {
631 /* ---------- Empty Streams ---------- */
632 CBoolVector emptyStreamVector;
633 emptyStreamVector.Reserve(db.Files.Size());
634 int numEmptyStreams = 0;
635 for (i = 0; i < db.Files.Size(); i++)
636 if (db.Files[i].HasStream)
637 emptyStreamVector.Add(false);
638 else
639 {
640 emptyStreamVector.Add(true);
641 numEmptyStreams++;
642 }
643 if (numEmptyStreams > 0)
644 {
645 WriteByte(NID::kEmptyStream);
646 WriteNumber((emptyStreamVector.Size() + 7) / 8);
647 WriteBoolVector(emptyStreamVector);
648
649 CBoolVector emptyFileVector, antiVector;
650 emptyFileVector.Reserve(numEmptyStreams);
651 antiVector.Reserve(numEmptyStreams);
652 CNum numEmptyFiles = 0, numAntiItems = 0;
653 for (i = 0; i < db.Files.Size(); i++)
654 {
655 const CFileItem &file = db.Files[i];
656 if (!file.HasStream)
657 {
658 emptyFileVector.Add(!file.IsDir);
659 if (!file.IsDir)
660 numEmptyFiles++;
661 bool isAnti = db.IsItemAnti(i);
662 antiVector.Add(isAnti);
663 if (isAnti)
664 numAntiItems++;
665 }
666 }
667
668 if (numEmptyFiles > 0)
669 {
670 WriteByte(NID::kEmptyFile);
671 WriteNumber((emptyFileVector.Size() + 7) / 8);
672 WriteBoolVector(emptyFileVector);
673 }
674
675 if (numAntiItems > 0)
676 {
677 WriteByte(NID::kAnti);
678 WriteNumber((antiVector.Size() + 7) / 8);
679 WriteBoolVector(antiVector);
680 }
681 }
682 }
683
684
685 {
686 /* ---------- Names ---------- */
687
688 int numDefined = 0;
689 size_t namesDataSize = 0;
690 for (int i = 0; i < db.Files.Size(); i++)
691 {
692 const UString &name = db.Files[i].Name;
693 if (!name.IsEmpty())
694 numDefined++;
695 namesDataSize += (name.Length() + 1) * 2;
696 }
697
698 if (numDefined > 0)
699 {
700 namesDataSize++;
701 SkipAlign(2 + GetBigNumberSize(namesDataSize), 2);
702
703 WriteByte(NID::kName);
704 WriteNumber(namesDataSize);
705 WriteByte(0);
706 for (int i = 0; i < db.Files.Size(); i++)
707 {
708 const UString &name = db.Files[i].Name;
709 for (int t = 0; t <= name.Length(); t++)
710 {
711 wchar_t c = name[t];
712 WriteByte((Byte)c);
713 WriteByte((Byte)(c >> 8));
714 }
715 }
716 }
717 }
718
719 if (headerOptions.WriteCTime) WriteUInt64DefVector(db.CTime, NID::kCTime);
720 if (headerOptions.WriteATime) WriteUInt64DefVector(db.ATime, NID::kATime);
721 if (headerOptions.WriteMTime) WriteUInt64DefVector(db.MTime, NID::kMTime);
722 WriteUInt64DefVector(db.StartPos, NID::kStartPos);
723
724 {
725 /* ---------- Write Attrib ---------- */
726 CBoolVector boolVector;
727 boolVector.Reserve(db.Files.Size());
728 int numDefined = 0;
729 for (i = 0; i < db.Files.Size(); i++)
730 {
731 bool defined = db.Files[i].AttribDefined;
732 boolVector.Add(defined);
733 if (defined)
734 numDefined++;
735 }
736 if (numDefined > 0)
737 {
738 WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttributes, 4);
739 for (i = 0; i < db.Files.Size(); i++)
740 {
741 const CFileItem &file = db.Files[i];
742 if (file.AttribDefined)
743 WriteUInt32(file.Attrib);
744 }
745 }
746 }
747
748 WriteByte(NID::kEnd); // for files
749 WriteByte(NID::kEnd); // for headers
750 }
751
752 HRESULT COutArchive::WriteDatabase(
753 DECL_EXTERNAL_CODECS_LOC_VARS
754 const CArchiveDatabase &db,
755 const CCompressionMethodMode *options,
756 const CHeaderOptions &headerOptions)
757 {
758 if (!db.CheckNumFiles())
759 return E_FAIL;
760
761 UInt64 headerOffset;
762 UInt32 headerCRC;
763 UInt64 headerSize;
764 if (db.IsEmpty())
765 {
766 headerSize = 0;
767 headerOffset = 0;
768 headerCRC = CrcCalc(0, 0);
769 }
770 else
771 {
772 bool encodeHeaders = false;
773 if (options != 0)
774 if (options->IsEmpty())
775 options = 0;
776 if (options != 0)
777 if (options->PasswordIsDefined || headerOptions.CompressMainHeader)
778 encodeHeaders = true;
779
780 _outByte.SetStream(SeqStream);
781 _outByte.Init();
782 _crc = CRC_INIT_VAL;
783 _countMode = encodeHeaders;
784 _writeToStream = true;
785 _countSize = 0;
786 WriteHeader(db, headerOptions, headerOffset);
787
788 if (encodeHeaders)
789 {
790 CByteBuffer buf;
791 buf.SetCapacity(_countSize);
792 _outByte2.Init((Byte *)buf, _countSize);
793
794 _countMode = false;
795 _writeToStream = false;
796 WriteHeader(db, headerOptions, headerOffset);
797
798 if (_countSize != _outByte2.GetPos())
799 return E_FAIL;
800
801 CCompressionMethodMode encryptOptions;
802 encryptOptions.PasswordIsDefined = options->PasswordIsDefined;
803 encryptOptions.Password = options->Password;
804 CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOpti ons);
805 CRecordVector<UInt64> packSizes;
806 CObjectVector<CFolder> folders;
807 RINOK(EncodeStream(
808 EXTERNAL_CODECS_LOC_VARS
809 encoder, (const Byte *)buf,
810 _countSize, packSizes, folders));
811
812 _writeToStream = true;
813
814 if (folders.Size() == 0)
815 throw 1;
816
817 WriteID(NID::kEncodedHeader);
818 WritePackInfo(headerOffset, packSizes,
819 CRecordVector<bool>(), CRecordVector<UInt32>());
820 WriteUnpackInfo(folders);
821 WriteByte(NID::kEnd);
822 for (int i = 0; i < packSizes.Size(); i++)
823 headerOffset += packSizes[i];
824 }
825 RINOK(_outByte.Flush());
826 headerCRC = CRC_GET_DIGEST(_crc);
827 headerSize = _outByte.GetProcessedSize();
828 }
829 #ifdef _7Z_VOL
830 if (_endMarker)
831 {
832 CFinishHeader h;
833 h.NextHeaderSize = headerSize;
834 h.NextHeaderCRC = headerCRC;
835 h.NextHeaderOffset =
836 UInt64(0) - (headerSize +
837 4 + kFinishHeaderSize);
838 h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset;
839 h.AdditionalStartBlockSize = 0;
840 RINOK(WriteFinishHeader(h));
841 return WriteFinishSignature();
842 }
843 else
844 #endif
845 {
846 CStartHeader h;
847 h.NextHeaderSize = headerSize;
848 h.NextHeaderCRC = headerCRC;
849 h.NextHeaderOffset = headerOffset;
850 RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL));
851 return WriteStartHeader(h);
852 }
853 }
854
855 void CArchiveDatabase::GetFile(int index, CFileItem &file, CFileItem2 &file2) co nst
856 {
857 file = Files[index];
858 file2.CTimeDefined = CTime.GetItem(index, file2.CTime);
859 file2.ATimeDefined = ATime.GetItem(index, file2.ATime);
860 file2.MTimeDefined = MTime.GetItem(index, file2.MTime);
861 file2.StartPosDefined = StartPos.GetItem(index, file2.StartPos);
862 file2.IsAnti = IsItemAnti(index);
863 }
864
865 void CArchiveDatabase::AddFile(const CFileItem &file, const CFileItem2 &file2)
866 {
867 int index = Files.Size();
868 CTime.SetItem(index, file2.CTimeDefined, file2.CTime);
869 ATime.SetItem(index, file2.ATimeDefined, file2.ATime);
870 MTime.SetItem(index, file2.MTimeDefined, file2.MTime);
871 StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos);
872 SetItemAnti(index, file2.IsAnti);
873 Files.Add(file);
874 }
875
876 }}
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698