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