5 #include "../../../../C/7zCrc.h"
\r
7 #include "../../../Common/AutoPtr.h"
\r
9 #include "../../Common/StreamObjects.h"
\r
13 static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size)
\r
17 UInt32 curSize = (UInt32)MyMin(size, (size_t)0xFFFFFFFF);
\r
18 UInt32 processedSize;
\r
19 RINOK(stream->Write(data, curSize, &processedSize));
\r
20 if (processedSize == 0)
\r
22 data = (const void *)((const Byte *)data + processedSize);
\r
23 size -= processedSize;
\r
28 namespace NArchive {
\r
31 HRESULT COutArchive::WriteDirect(const void *data, UInt32 size)
\r
33 return ::WriteBytes(SeqStream, data, size);
\r
36 HRESULT COutArchive::WriteSignature()
\r
39 memcpy(buf, kSignature, kSignatureSize);
\r
40 buf[kSignatureSize] = kMajorVersion;
\r
41 buf[kSignatureSize + 1] = 3;
\r
42 return WriteDirect(buf, 8);
\r
46 HRESULT COutArchive::WriteFinishSignature()
\r
48 RINOK(WriteDirect(kFinishSignature, kSignatureSize));
\r
50 av.Major = kMajorVersion;
\r
52 RINOK(WriteDirectByte(av.Major));
\r
53 return WriteDirectByte(av.Minor);
\r
57 static void SetUInt32(Byte *p, UInt32 d)
\r
59 for (int i = 0; i < 4; i++, d >>= 8)
\r
63 static void SetUInt64(Byte *p, UInt64 d)
\r
65 for (int i = 0; i < 8; i++, d >>= 8)
\r
69 HRESULT COutArchive::WriteStartHeader(const CStartHeader &h)
\r
72 SetUInt64(buf + 4, h.NextHeaderOffset);
\r
73 SetUInt64(buf + 12, h.NextHeaderSize);
\r
74 SetUInt32(buf + 20, h.NextHeaderCRC);
\r
75 SetUInt32(buf, CrcCalc(buf + 4, 20));
\r
76 return WriteDirect(buf, 24);
\r
80 HRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h)
\r
83 crc.UpdateUInt64(h.NextHeaderOffset);
\r
84 crc.UpdateUInt64(h.NextHeaderSize);
\r
85 crc.UpdateUInt32(h.NextHeaderCRC);
\r
86 crc.UpdateUInt64(h.ArchiveStartOffset);
\r
87 crc.UpdateUInt64(h.AdditionalStartBlockSize);
\r
88 RINOK(WriteDirectUInt32(crc.GetDigest()));
\r
89 RINOK(WriteDirectUInt64(h.NextHeaderOffset));
\r
90 RINOK(WriteDirectUInt64(h.NextHeaderSize));
\r
91 RINOK(WriteDirectUInt32(h.NextHeaderCRC));
\r
92 RINOK(WriteDirectUInt64(h.ArchiveStartOffset));
\r
93 return WriteDirectUInt64(h.AdditionalStartBlockSize);
\r
97 HRESULT COutArchive::Create(ISequentialOutStream *stream, bool endMarker)
\r
101 // endMarker = false;
\r
102 _endMarker = endMarker;
\r
104 SeqStream = stream;
\r
107 SeqStream.QueryInterface(IID_IOutStream, &Stream);
\r
111 // endMarker = true;
\r
119 sh.NextHeaderOffset = (UInt32)(Int32)-1;
\r
120 sh.NextHeaderSize = (UInt32)(Int32)-1;
\r
121 sh.NextHeaderCRC = 0;
\r
122 WriteStartHeader(sh);
\r
130 RINOK(WriteSignature());
\r
131 RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_prefixHeaderPos));
\r
136 void COutArchive::Close()
\r
138 SeqStream.Release();
\r
142 HRESULT COutArchive::SkipPrefixArchiveHeader()
\r
148 return Stream->Seek(24, STREAM_SEEK_CUR, NULL);
\r
151 UInt64 COutArchive::GetPos() const
\r
155 if (_writeToStream)
\r
156 return _outByte.GetProcessedSize();
\r
157 return _outByte2.GetPos();
\r
160 void COutArchive::WriteBytes(const void *data, size_t size)
\r
163 _countSize += size;
\r
164 else if (_writeToStream)
\r
166 _outByte.WriteBytes(data, size);
\r
167 _crc = CrcUpdate(_crc, data, size);
\r
170 _outByte2.WriteBytes(data, size);
\r
173 void COutArchive::WriteByte(Byte b)
\r
177 else if (_writeToStream)
\r
179 _outByte.WriteByte(b);
\r
180 _crc = CRC_UPDATE_BYTE(_crc, b);
\r
183 _outByte2.WriteByte(b);
\r
186 void COutArchive::WriteUInt32(UInt32 value)
\r
188 for (int i = 0; i < 4; i++)
\r
190 WriteByte((Byte)value);
\r
195 void COutArchive::WriteUInt64(UInt64 value)
\r
197 for (int i = 0; i < 8; i++)
\r
199 WriteByte((Byte)value);
\r
204 void COutArchive::WriteNumber(UInt64 value)
\r
206 Byte firstByte = 0;
\r
209 for (i = 0; i < 8; i++)
\r
211 if (value < ((UInt64(1) << ( 7 * (i + 1)))))
\r
213 firstByte |= Byte(value >> (8 * i));
\r
219 WriteByte(firstByte);
\r
222 WriteByte((Byte)value);
\r
227 static UInt32 GetBigNumberSize(UInt64 value)
\r
230 for (i = 1; i < 9; i++)
\r
231 if (value < (((UInt64)1 << (i * 7))))
\r
237 UInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool props)
\r
239 UInt32 result = GetBigNumberSize(dataSize) * 2 + 41;
\r
240 if (nameLength != 0)
\r
242 nameLength = (nameLength + 1) * 2;
\r
243 result += nameLength + GetBigNumberSize(nameLength) + 2;
\r
251 result += kSignatureSize + 2 + kFinishHeaderSize;
\r
255 UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props)
\r
257 UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props);
\r
259 if (volSize > headersSizeBase)
\r
260 testSize = volSize - headersSizeBase;
\r
263 UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, props);
\r
264 UInt64 pureSize = 1;
\r
265 if (volSize > headersSize)
\r
266 pureSize = volSize - headersSize;
\r
271 void COutArchive::WriteFolder(const CFolder &folder)
\r
273 WriteNumber(folder.Coders.Size());
\r
275 for (i = 0; i < folder.Coders.Size(); i++)
\r
277 const CCoderInfo &coder = folder.Coders[i];
\r
279 size_t propsSize = coder.Props.GetCapacity();
\r
281 UInt64 id = coder.MethodID;
\r
283 for (idSize = 1; idSize < sizeof(id); idSize++)
\r
284 if ((id >> (8 * idSize)) == 0)
\r
287 for (int t = idSize - 1; t >= 0 ; t--, id >>= 8)
\r
288 longID[t] = (Byte)(id & 0xFF);
\r
290 b = (Byte)(idSize & 0xF);
\r
291 bool isComplex = !coder.IsSimpleCoder();
\r
292 b |= (isComplex ? 0x10 : 0);
\r
293 b |= ((propsSize != 0) ? 0x20 : 0 );
\r
295 WriteBytes(longID, idSize);
\r
298 WriteNumber(coder.NumInStreams);
\r
299 WriteNumber(coder.NumOutStreams);
\r
301 if (propsSize == 0)
\r
303 WriteNumber(propsSize);
\r
304 WriteBytes(coder.Props, propsSize);
\r
307 for (i = 0; i < folder.BindPairs.Size(); i++)
\r
309 const CBindPair &bindPair = folder.BindPairs[i];
\r
310 WriteNumber(bindPair.InIndex);
\r
311 WriteNumber(bindPair.OutIndex);
\r
313 if (folder.PackStreams.Size() > 1)
\r
314 for (i = 0; i < folder.PackStreams.Size(); i++)
\r
316 WriteNumber(folder.PackStreams[i]);
\r
320 void COutArchive::WriteBoolVector(const CBoolVector &boolVector)
\r
324 for (int i = 0; i < boolVector.Size(); i++)
\r
341 void COutArchive::WriteHashDigests(
\r
342 const CRecordVector<bool> &digestsDefined,
\r
343 const CRecordVector<UInt32> &digests)
\r
345 int numDefined = 0;
\r
347 for (i = 0; i < digestsDefined.Size(); i++)
\r
348 if (digestsDefined[i])
\r
350 if (numDefined == 0)
\r
353 WriteByte(NID::kCRC);
\r
354 if (numDefined == digestsDefined.Size())
\r
359 WriteBoolVector(digestsDefined);
\r
361 for (i = 0; i < digests.Size(); i++)
\r
362 if (digestsDefined[i])
\r
363 WriteUInt32(digests[i]);
\r
366 void COutArchive::WritePackInfo(
\r
368 const CRecordVector<UInt64> &packSizes,
\r
369 const CRecordVector<bool> &packCRCsDefined,
\r
370 const CRecordVector<UInt32> &packCRCs)
\r
372 if (packSizes.IsEmpty())
\r
374 WriteByte(NID::kPackInfo);
\r
375 WriteNumber(dataOffset);
\r
376 WriteNumber(packSizes.Size());
\r
377 WriteByte(NID::kSize);
\r
378 for (int i = 0; i < packSizes.Size(); i++)
\r
379 WriteNumber(packSizes[i]);
\r
381 WriteHashDigests(packCRCsDefined, packCRCs);
\r
383 WriteByte(NID::kEnd);
\r
386 void COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders)
\r
388 if (folders.IsEmpty())
\r
391 WriteByte(NID::kUnpackInfo);
\r
393 WriteByte(NID::kFolder);
\r
394 WriteNumber(folders.Size());
\r
397 for (int i = 0; i < folders.Size(); i++)
\r
398 WriteFolder(folders[i]);
\r
401 WriteByte(NID::kCodersUnpackSize);
\r
403 for (i = 0; i < folders.Size(); i++)
\r
405 const CFolder &folder = folders[i];
\r
406 for (int j = 0; j < folder.UnpackSizes.Size(); j++)
\r
407 WriteNumber(folder.UnpackSizes[j]);
\r
410 CRecordVector<bool> unpackCRCsDefined;
\r
411 CRecordVector<UInt32> unpackCRCs;
\r
412 for (i = 0; i < folders.Size(); i++)
\r
414 const CFolder &folder = folders[i];
\r
415 unpackCRCsDefined.Add(folder.UnpackCRCDefined);
\r
416 unpackCRCs.Add(folder.UnpackCRC);
\r
418 WriteHashDigests(unpackCRCsDefined, unpackCRCs);
\r
420 WriteByte(NID::kEnd);
\r
423 void COutArchive::WriteSubStreamsInfo(
\r
424 const CObjectVector<CFolder> &folders,
\r
425 const CRecordVector<CNum> &numUnpackStreamsInFolders,
\r
426 const CRecordVector<UInt64> &unpackSizes,
\r
427 const CRecordVector<bool> &digestsDefined,
\r
428 const CRecordVector<UInt32> &digests)
\r
430 WriteByte(NID::kSubStreamsInfo);
\r
433 for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
\r
435 if (numUnpackStreamsInFolders[i] != 1)
\r
437 WriteByte(NID::kNumUnpackStream);
\r
438 for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
\r
439 WriteNumber(numUnpackStreamsInFolders[i]);
\r
445 bool needFlag = true;
\r
447 for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
\r
448 for (CNum j = 0; j < numUnpackStreamsInFolders[i]; j++)
\r
450 if (j + 1 != numUnpackStreamsInFolders[i])
\r
453 WriteByte(NID::kSize);
\r
455 WriteNumber(unpackSizes[index]);
\r
460 CRecordVector<bool> digestsDefined2;
\r
461 CRecordVector<UInt32> digests2;
\r
463 int digestIndex = 0;
\r
464 for (i = 0; i < folders.Size(); i++)
\r
466 int numSubStreams = (int)numUnpackStreamsInFolders[i];
\r
467 if (numSubStreams == 1 && folders[i].UnpackCRCDefined)
\r
470 for (int j = 0; j < numSubStreams; j++, digestIndex++)
\r
472 digestsDefined2.Add(digestsDefined[digestIndex]);
\r
473 digests2.Add(digests[digestIndex]);
\r
476 WriteHashDigests(digestsDefined2, digests2);
\r
477 WriteByte(NID::kEnd);
\r
480 void COutArchive::SkipAlign(unsigned /* pos */, unsigned /* alignSize */)
\r
486 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field.
\r
488 void COutArchive::SkipAlign(unsigned pos, unsigned alignSize)
\r
490 pos += (unsigned)GetPos();
\r
491 pos &= (alignSize - 1);
\r
494 unsigned skip = alignSize - pos;
\r
498 WriteByte(NID::kDummy);
\r
499 WriteByte((Byte)skip);
\r
500 for (unsigned i = 0; i < skip; i++)
\r
505 static inline unsigned Bv_GetSizeInBytes(const CBoolVector &v) { return ((unsigned)v.Size() + 7) / 8; }
\r
507 void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize)
\r
509 const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v);
\r
510 const UInt64 dataSize = (UInt64)numDefined * itemSize + bvSize + 2;
\r
511 SkipAlign(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSize);
\r
514 WriteNumber(dataSize);
\r
515 if (numDefined == v.Size())
\r
520 WriteBoolVector(v);
\r
525 void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type)
\r
527 int numDefined = 0;
\r
530 for (i = 0; i < v.Defined.Size(); i++)
\r
534 if (numDefined == 0)
\r
537 WriteAlignedBoolHeader(v.Defined, numDefined, type, 8);
\r
539 for (i = 0; i < v.Defined.Size(); i++)
\r
541 WriteUInt64(v.Values[i]);
\r
544 HRESULT COutArchive::EncodeStream(
\r
545 DECL_EXTERNAL_CODECS_LOC_VARS
\r
546 CEncoder &encoder, const CByteBuffer &data,
\r
547 CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders)
\r
549 CBufInStream *streamSpec = new CBufInStream;
\r
550 CMyComPtr<ISequentialInStream> stream = streamSpec;
\r
551 streamSpec->Init(data, data.GetCapacity());
\r
552 CFolder folderItem;
\r
553 folderItem.UnpackCRCDefined = true;
\r
554 folderItem.UnpackCRC = CrcCalc(data, data.GetCapacity());
\r
555 UInt64 dataSize64 = data.GetCapacity();
\r
556 RINOK(encoder.Encode(
\r
557 EXTERNAL_CODECS_LOC_VARS
\r
558 stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL))
\r
559 folders.Add(folderItem);
\r
563 void COutArchive::WriteHeader(
\r
564 const CArchiveDatabase &db,
\r
565 const CHeaderOptions &headerOptions,
\r
566 UInt64 &headerOffset)
\r
570 UInt64 packedSize = 0;
\r
571 for (i = 0; i < db.PackSizes.Size(); i++)
\r
572 packedSize += db.PackSizes[i];
\r
574 headerOffset = packedSize;
\r
576 WriteByte(NID::kHeader);
\r
578 // Archive Properties
\r
580 if (db.Folders.Size() > 0)
\r
582 WriteByte(NID::kMainStreamsInfo);
\r
583 WritePackInfo(0, db.PackSizes,
\r
584 db.PackCRCsDefined,
\r
587 WriteUnpackInfo(db.Folders);
\r
589 CRecordVector<UInt64> unpackSizes;
\r
590 CRecordVector<bool> digestsDefined;
\r
591 CRecordVector<UInt32> digests;
\r
592 for (i = 0; i < db.Files.Size(); i++)
\r
594 const CFileItem &file = db.Files[i];
\r
595 if (!file.HasStream)
\r
597 unpackSizes.Add(file.Size);
\r
598 digestsDefined.Add(file.CrcDefined);
\r
599 digests.Add(file.Crc);
\r
602 WriteSubStreamsInfo(
\r
604 db.NumUnpackStreamsVector,
\r
608 WriteByte(NID::kEnd);
\r
611 if (db.Files.IsEmpty())
\r
613 WriteByte(NID::kEnd);
\r
617 WriteByte(NID::kFilesInfo);
\r
618 WriteNumber(db.Files.Size());
\r
621 /* ---------- Empty Streams ---------- */
\r
622 CBoolVector emptyStreamVector;
\r
623 emptyStreamVector.Reserve(db.Files.Size());
\r
624 int numEmptyStreams = 0;
\r
625 for (i = 0; i < db.Files.Size(); i++)
\r
626 if (db.Files[i].HasStream)
\r
627 emptyStreamVector.Add(false);
\r
630 emptyStreamVector.Add(true);
\r
633 if (numEmptyStreams > 0)
\r
635 WriteByte(NID::kEmptyStream);
\r
636 WriteNumber(Bv_GetSizeInBytes(emptyStreamVector));
\r
637 WriteBoolVector(emptyStreamVector);
\r
639 CBoolVector emptyFileVector, antiVector;
\r
640 emptyFileVector.Reserve(numEmptyStreams);
\r
641 antiVector.Reserve(numEmptyStreams);
\r
642 CNum numEmptyFiles = 0, numAntiItems = 0;
\r
643 for (i = 0; i < db.Files.Size(); i++)
\r
645 const CFileItem &file = db.Files[i];
\r
646 if (!file.HasStream)
\r
648 emptyFileVector.Add(!file.IsDir);
\r
651 bool isAnti = db.IsItemAnti(i);
\r
652 antiVector.Add(isAnti);
\r
658 if (numEmptyFiles > 0)
\r
660 WriteByte(NID::kEmptyFile);
\r
661 WriteNumber(Bv_GetSizeInBytes(emptyFileVector));
\r
662 WriteBoolVector(emptyFileVector);
\r
665 if (numAntiItems > 0)
\r
667 WriteByte(NID::kAnti);
\r
668 WriteNumber(Bv_GetSizeInBytes(antiVector));
\r
669 WriteBoolVector(antiVector);
\r
676 /* ---------- Names ---------- */
\r
678 int numDefined = 0;
\r
679 size_t namesDataSize = 0;
\r
680 for (int i = 0; i < db.Files.Size(); i++)
\r
682 const UString &name = db.Files[i].Name;
\r
683 if (!name.IsEmpty())
\r
685 namesDataSize += (name.Length() + 1) * 2;
\r
688 if (numDefined > 0)
\r
691 SkipAlign(2 + GetBigNumberSize(namesDataSize), 2);
\r
693 WriteByte(NID::kName);
\r
694 WriteNumber(namesDataSize);
\r
696 for (int i = 0; i < db.Files.Size(); i++)
\r
698 const UString &name = db.Files[i].Name;
\r
699 for (int t = 0; t <= name.Length(); t++)
\r
701 wchar_t c = name[t];
\r
702 WriteByte((Byte)c);
\r
703 WriteByte((Byte)(c >> 8));
\r
709 if (headerOptions.WriteCTime) WriteUInt64DefVector(db.CTime, NID::kCTime);
\r
710 if (headerOptions.WriteATime) WriteUInt64DefVector(db.ATime, NID::kATime);
\r
711 if (headerOptions.WriteMTime) WriteUInt64DefVector(db.MTime, NID::kMTime);
\r
712 WriteUInt64DefVector(db.StartPos, NID::kStartPos);
\r
715 /* ---------- Write Attrib ---------- */
\r
716 CBoolVector boolVector;
\r
717 boolVector.Reserve(db.Files.Size());
\r
718 int numDefined = 0;
\r
719 for (i = 0; i < db.Files.Size(); i++)
\r
721 bool defined = db.Files[i].AttribDefined;
\r
722 boolVector.Add(defined);
\r
726 if (numDefined > 0)
\r
728 WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttributes, 4);
\r
729 for (i = 0; i < db.Files.Size(); i++)
\r
731 const CFileItem &file = db.Files[i];
\r
732 if (file.AttribDefined)
\r
733 WriteUInt32(file.Attrib);
\r
738 WriteByte(NID::kEnd); // for files
\r
739 WriteByte(NID::kEnd); // for headers
\r
742 HRESULT COutArchive::WriteDatabase(
\r
743 DECL_EXTERNAL_CODECS_LOC_VARS
\r
744 const CArchiveDatabase &db,
\r
745 const CCompressionMethodMode *options,
\r
746 const CHeaderOptions &headerOptions)
\r
748 if (!db.CheckNumFiles())
\r
751 UInt64 headerOffset;
\r
758 headerCRC = CrcCalc(0, 0);
\r
762 bool encodeHeaders = false;
\r
764 if (options->IsEmpty())
\r
767 if (options->PasswordIsDefined || headerOptions.CompressMainHeader)
\r
768 encodeHeaders = true;
\r
770 _outByte.SetStream(SeqStream);
\r
772 _crc = CRC_INIT_VAL;
\r
773 _countMode = encodeHeaders;
\r
774 _writeToStream = true;
\r
776 WriteHeader(db, headerOptions, headerOffset);
\r
781 buf.SetCapacity(_countSize);
\r
782 _outByte2.Init((Byte *)buf, _countSize);
\r
784 _countMode = false;
\r
785 _writeToStream = false;
\r
786 WriteHeader(db, headerOptions, headerOffset);
\r
788 if (_countSize != _outByte2.GetPos())
\r
791 CCompressionMethodMode encryptOptions;
\r
792 encryptOptions.PasswordIsDefined = options->PasswordIsDefined;
\r
793 encryptOptions.Password = options->Password;
\r
794 CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions);
\r
795 CRecordVector<UInt64> packSizes;
\r
796 CObjectVector<CFolder> folders;
\r
797 RINOK(EncodeStream(
\r
798 EXTERNAL_CODECS_LOC_VARS
\r
800 packSizes, folders));
\r
802 _writeToStream = true;
\r
804 if (folders.Size() == 0)
\r
807 WriteID(NID::kEncodedHeader);
\r
808 WritePackInfo(headerOffset, packSizes,
\r
809 CRecordVector<bool>(), CRecordVector<UInt32>());
\r
810 WriteUnpackInfo(folders);
\r
811 WriteByte(NID::kEnd);
\r
812 for (int i = 0; i < packSizes.Size(); i++)
\r
813 headerOffset += packSizes[i];
\r
815 RINOK(_outByte.Flush());
\r
816 headerCRC = CRC_GET_DIGEST(_crc);
\r
817 headerSize = _outByte.GetProcessedSize();
\r
823 h.NextHeaderSize = headerSize;
\r
824 h.NextHeaderCRC = headerCRC;
\r
825 h.NextHeaderOffset =
\r
826 UInt64(0) - (headerSize +
\r
827 4 + kFinishHeaderSize);
\r
828 h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset;
\r
829 h.AdditionalStartBlockSize = 0;
\r
830 RINOK(WriteFinishHeader(h));
\r
831 return WriteFinishSignature();
\r
837 h.NextHeaderSize = headerSize;
\r
838 h.NextHeaderCRC = headerCRC;
\r
839 h.NextHeaderOffset = headerOffset;
\r
840 RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL));
\r
841 return WriteStartHeader(h);
\r
845 void CArchiveDatabase::GetFile(int index, CFileItem &file, CFileItem2 &file2) const
\r
847 file = Files[index];
\r
848 file2.CTimeDefined = CTime.GetItem(index, file2.CTime);
\r
849 file2.ATimeDefined = ATime.GetItem(index, file2.ATime);
\r
850 file2.MTimeDefined = MTime.GetItem(index, file2.MTime);
\r
851 file2.StartPosDefined = StartPos.GetItem(index, file2.StartPos);
\r
852 file2.IsAnti = IsItemAnti(index);
\r
855 void CArchiveDatabase::AddFile(const CFileItem &file, const CFileItem2 &file2)
\r
857 int index = Files.Size();
\r
858 CTime.SetItem(index, file2.CTimeDefined, file2.CTime);
\r
859 ATime.SetItem(index, file2.ATimeDefined, file2.ATime);
\r
860 MTime.SetItem(index, file2.MTimeDefined, file2.MTime);
\r
861 StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos);
\r
862 SetItemAnti(index, file2.IsAnti);
\r