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 13 namespace NArchive { 14 namespace N7z { 15 16 HRESULT 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 26 HRESULT 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 37 static void SetUInt32(Byte *p, UInt32 d) 38 { 39 for (int i = 0; i < 4; i++, d >>= 8) 40 p[i] = (Byte)d; 41 } 42 43 static void SetUInt64(Byte *p, UInt64 d) 44 { 45 for (int i = 0; i < 8; i++, d >>= 8) 46 p[i] = (Byte)d; 47 } 48 49 HRESULT 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 60 HRESULT 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 77 HRESULT 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 116 void COutArchive::Close() 117 { 118 SeqStream.Release(); 119 Stream.Release(); 120 } 121 122 HRESULT 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 133 UInt64 COutArchive::GetPos() const 134 { 135 if (_countMode) 136 return _countSize; 137 if (_writeToStream) 138 return _outByte.GetProcessedSize(); 139 return _outByte2.GetPos(); 140 } 141 142 void 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 155 void 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 168 void COutArchive::WriteUInt32(UInt32 value) 169 { 170 for (int i = 0; i < 4; i++) 171 { 172 WriteByte((Byte)value); 173 value >>= 8; 174 } 175 } 176 177 void COutArchive::WriteUInt64(UInt64 value) 178 { 179 for (int i = 0; i < 8; i++) 180 { 181 WriteByte((Byte)value); 182 value >>= 8; 183 } 184 } 185 186 void 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 209 static 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 219 UInt32 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 237 UInt64 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 253 void COutArchive::WriteFolder(const CFolder &folder) 254 { 255 WriteNumber(folder.Coders.Size()); 256 unsigned i; 257 258 for (i = 0; i < folder.Coders.Size(); i++) 259 { 260 const CCoderInfo &coder = folder.Coders[i]; 261 { 262 UInt64 id = coder.MethodID; 263 unsigned idSize; 264 for (idSize = 1; idSize < sizeof(id); idSize++) 265 if ((id >> (8 * idSize)) == 0) 266 break; 267 idSize &= 0xF; 268 Byte temp[16]; 269 for (unsigned t = idSize; t != 0; t--, id >>= 8) 270 temp[t] = (Byte)(id & 0xFF); 271 272 Byte b = (Byte)(idSize); 273 bool isComplex = !coder.IsSimpleCoder(); 274 b |= (isComplex ? 0x10 : 0); 275 276 size_t propsSize = coder.Props.Size(); 277 b |= ((propsSize != 0) ? 0x20 : 0); 278 temp[0] = b; 279 WriteBytes(temp, idSize + 1); 280 if (isComplex) 281 { 282 WriteNumber(coder.NumStreams); 283 WriteNumber(1); // NumOutStreams; 284 } 285 if (propsSize == 0) 286 continue; 287 WriteNumber(propsSize); 288 WriteBytes(coder.Props, propsSize); 289 } 290 } 291 292 for (i = 0; i < folder.Bonds.Size(); i++) 293 { 294 const CBond &bond = folder.Bonds[i]; 295 WriteNumber(bond.PackIndex); 296 WriteNumber(bond.UnpackIndex); 297 } 298 299 if (folder.PackStreams.Size() > 1) 300 for (i = 0; i < folder.PackStreams.Size(); i++) 301 WriteNumber(folder.PackStreams[i]); 302 } 303 304 void COutArchive::WriteBoolVector(const CBoolVector &boolVector) 305 { 306 Byte b = 0; 307 Byte mask = 0x80; 308 FOR_VECTOR (i, boolVector) 309 { 310 if (boolVector[i]) 311 b |= mask; 312 mask >>= 1; 313 if (mask == 0) 314 { 315 WriteByte(b); 316 mask = 0x80; 317 b = 0; 318 } 319 } 320 if (mask != 0x80) 321 WriteByte(b); 322 } 323 324 static inline unsigned Bv_GetSizeInBytes(const CBoolVector &v) { return ((unsigned)v.Size() + 7) / 8; } 325 326 void COutArchive::WritePropBoolVector(Byte id, const CBoolVector &boolVector) 327 { 328 WriteByte(id); 329 WriteNumber(Bv_GetSizeInBytes(boolVector)); 330 WriteBoolVector(boolVector); 331 } 332 333 void COutArchive::WriteHashDigests(const CUInt32DefVector &digests) 334 { 335 unsigned numDefined = 0; 336 unsigned i; 337 for (i = 0; i < digests.Defs.Size(); i++) 338 if (digests.Defs[i]) 339 numDefined++; 340 if (numDefined == 0) 341 return; 342 343 WriteByte(NID::kCRC); 344 if (numDefined == digests.Defs.Size()) 345 WriteByte(1); 346 else 347 { 348 WriteByte(0); 349 WriteBoolVector(digests.Defs); 350 } 351 for (i = 0; i < digests.Defs.Size(); i++) 352 if (digests.Defs[i]) 353 WriteUInt32(digests.Vals[i]); 354 } 355 356 void COutArchive::WritePackInfo( 357 UInt64 dataOffset, 358 const CRecordVector<UInt64> &packSizes, 359 const CUInt32DefVector &packCRCs) 360 { 361 if (packSizes.IsEmpty()) 362 return; 363 WriteByte(NID::kPackInfo); 364 WriteNumber(dataOffset); 365 WriteNumber(packSizes.Size()); 366 WriteByte(NID::kSize); 367 FOR_VECTOR (i, packSizes) 368 WriteNumber(packSizes[i]); 369 370 WriteHashDigests(packCRCs); 371 372 WriteByte(NID::kEnd); 373 } 374 375 void COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders, const COutFolders &outFolders) 376 { 377 if (folders.IsEmpty()) 378 return; 379 380 WriteByte(NID::kUnpackInfo); 381 382 WriteByte(NID::kFolder); 383 WriteNumber(folders.Size()); 384 { 385 WriteByte(0); 386 FOR_VECTOR (i, folders) 387 WriteFolder(folders[i]); 388 } 389 390 WriteByte(NID::kCodersUnpackSize); 391 FOR_VECTOR (i, outFolders.CoderUnpackSizes) 392 WriteNumber(outFolders.CoderUnpackSizes[i]); 393 394 WriteHashDigests(outFolders.FolderUnpackCRCs); 395 396 WriteByte(NID::kEnd); 397 } 398 399 void COutArchive::WriteSubStreamsInfo(const CObjectVector<CFolder> &folders, 400 const COutFolders &outFolders, 401 const CRecordVector<UInt64> &unpackSizes, 402 const CUInt32DefVector &digests) 403 { 404 const CRecordVector<CNum> &numUnpackStreamsInFolders = outFolders.NumUnpackStreamsVector; 405 WriteByte(NID::kSubStreamsInfo); 406 407 unsigned i; 408 for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) 409 if (numUnpackStreamsInFolders[i] != 1) 410 { 411 WriteByte(NID::kNumUnpackStream); 412 for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) 413 WriteNumber(numUnpackStreamsInFolders[i]); 414 break; 415 } 416 417 for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) 418 if (numUnpackStreamsInFolders[i] > 1) 419 { 420 WriteByte(NID::kSize); 421 CNum index = 0; 422 for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) 423 { 424 CNum num = numUnpackStreamsInFolders[i]; 425 for (CNum j = 0; j < num; j++) 426 { 427 if (j + 1 != num) 428 WriteNumber(unpackSizes[index]); 429 index++; 430 } 431 } 432 break; 433 } 434 435 CUInt32DefVector digests2; 436 437 unsigned digestIndex = 0; 438 for (i = 0; i < folders.Size(); i++) 439 { 440 unsigned numSubStreams = (unsigned)numUnpackStreamsInFolders[i]; 441 if (numSubStreams == 1 && outFolders.FolderUnpackCRCs.ValidAndDefined(i)) 442 digestIndex++; 443 else 444 for (unsigned j = 0; j < numSubStreams; j++, digestIndex++) 445 { 446 digests2.Defs.Add(digests.Defs[digestIndex]); 447 digests2.Vals.Add(digests.Vals[digestIndex]); 448 } 449 } 450 WriteHashDigests(digests2); 451 WriteByte(NID::kEnd); 452 } 453 454 // 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field. 455 456 void COutArchive::SkipAlign(unsigned pos, unsigned alignSize) 457 { 458 if (!_useAlign) 459 return; 460 pos += (unsigned)GetPos(); 461 pos &= (alignSize - 1); 462 if (pos == 0) 463 return; 464 unsigned skip = alignSize - pos; 465 if (skip < 2) 466 skip += alignSize; 467 skip -= 2; 468 WriteByte(NID::kDummy); 469 WriteByte((Byte)skip); 470 for (unsigned i = 0; i < skip; i++) 471 WriteByte(0); 472 } 473 474 void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSize) 475 { 476 const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v); 477 const UInt64 dataSize = (UInt64)numDefined * itemSize + bvSize + 2; 478 SkipAlign(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSize); 479 480 WriteByte(type); 481 WriteNumber(dataSize); 482 if (numDefined == v.Size()) 483 WriteByte(1); 484 else 485 { 486 WriteByte(0); 487 WriteBoolVector(v); 488 } 489 WriteByte(0); 490 } 491 492 void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type) 493 { 494 unsigned numDefined = 0; 495 496 unsigned i; 497 for (i = 0; i < v.Defs.Size(); i++) 498 if (v.Defs[i]) 499 numDefined++; 500 501 if (numDefined == 0) 502 return; 503 504 WriteAlignedBoolHeader(v.Defs, numDefined, type, 8); 505 506 for (i = 0; i < v.Defs.Size(); i++) 507 if (v.Defs[i]) 508 WriteUInt64(v.Vals[i]); 509 } 510 511 HRESULT COutArchive::EncodeStream( 512 DECL_EXTERNAL_CODECS_LOC_VARS 513 CEncoder &encoder, const CByteBuffer &data, 514 CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders) 515 { 516 CBufInStream *streamSpec = new CBufInStream; 517 CMyComPtr<ISequentialInStream> stream = streamSpec; 518 streamSpec->Init(data, data.Size()); 519 outFolders.FolderUnpackCRCs.Defs.Add(true); 520 outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size())); 521 // outFolders.NumUnpackStreamsVector.Add(1); 522 UInt64 dataSize64 = data.Size(); 523 UInt64 unpackSize; 524 RINOK(encoder.Encode( 525 EXTERNAL_CODECS_LOC_VARS 526 stream, 527 // NULL, 528 &dataSize64, 529 folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL)) 530 return S_OK; 531 } 532 533 void COutArchive::WriteHeader( 534 const CArchiveDatabaseOut &db, 535 // const CHeaderOptions &headerOptions, 536 UInt64 &headerOffset) 537 { 538 /* 539 bool thereIsSecure = (db.SecureBuf.Size() != 0); 540 */ 541 _useAlign = true; 542 543 { 544 UInt64 packSize = 0; 545 FOR_VECTOR (i, db.PackSizes) 546 packSize += db.PackSizes[i]; 547 headerOffset = packSize; 548 } 549 550 551 WriteByte(NID::kHeader); 552 553 // Archive Properties 554 555 if (db.Folders.Size() > 0) 556 { 557 WriteByte(NID::kMainStreamsInfo); 558 WritePackInfo(0, db.PackSizes, db.PackCRCs); 559 WriteUnpackInfo(db.Folders, (const COutFolders &)db); 560 561 CRecordVector<UInt64> unpackSizes; 562 CUInt32DefVector digests; 563 FOR_VECTOR (i, db.Files) 564 { 565 const CFileItem &file = db.Files[i]; 566 if (!file.HasStream) 567 continue; 568 unpackSizes.Add(file.Size); 569 digests.Defs.Add(file.CrcDefined); 570 digests.Vals.Add(file.Crc); 571 } 572 573 WriteSubStreamsInfo(db.Folders, (const COutFolders &)db, unpackSizes, digests); 574 WriteByte(NID::kEnd); 575 } 576 577 if (db.Files.IsEmpty()) 578 { 579 WriteByte(NID::kEnd); 580 return; 581 } 582 583 WriteByte(NID::kFilesInfo); 584 WriteNumber(db.Files.Size()); 585 586 { 587 /* ---------- Empty Streams ---------- */ 588 CBoolVector emptyStreamVector; 589 emptyStreamVector.ClearAndSetSize(db.Files.Size()); 590 unsigned numEmptyStreams = 0; 591 { 592 FOR_VECTOR (i, db.Files) 593 if (db.Files[i].HasStream) 594 emptyStreamVector[i] = false; 595 else 596 { 597 emptyStreamVector[i] = true; 598 numEmptyStreams++; 599 } 600 } 601 602 if (numEmptyStreams != 0) 603 { 604 WritePropBoolVector(NID::kEmptyStream, emptyStreamVector); 605 606 CBoolVector emptyFileVector, antiVector; 607 emptyFileVector.ClearAndSetSize(numEmptyStreams); 608 antiVector.ClearAndSetSize(numEmptyStreams); 609 bool thereAreEmptyFiles = false, thereAreAntiItems = false; 610 unsigned cur = 0; 611 612 FOR_VECTOR (i, db.Files) 613 { 614 const CFileItem &file = db.Files[i]; 615 if (file.HasStream) 616 continue; 617 emptyFileVector[cur] = !file.IsDir; 618 if (!file.IsDir) 619 thereAreEmptyFiles = true; 620 bool isAnti = db.IsItemAnti(i); 621 antiVector[cur] = isAnti; 622 if (isAnti) 623 thereAreAntiItems = true; 624 cur++; 625 } 626 627 if (thereAreEmptyFiles) 628 WritePropBoolVector(NID::kEmptyFile, emptyFileVector); 629 if (thereAreAntiItems) 630 WritePropBoolVector(NID::kAnti, antiVector); 631 } 632 } 633 634 635 { 636 /* ---------- Names ---------- */ 637 638 unsigned numDefined = 0; 639 size_t namesDataSize = 0; 640 FOR_VECTOR (i, db.Files) 641 { 642 const UString &name = db.Names[i]; 643 if (!name.IsEmpty()) 644 numDefined++; 645 namesDataSize += (name.Len() + 1) * 2; 646 } 647 648 if (numDefined > 0) 649 { 650 namesDataSize++; 651 SkipAlign(2 + GetBigNumberSize(namesDataSize), 16); 652 653 WriteByte(NID::kName); 654 WriteNumber(namesDataSize); 655 WriteByte(0); 656 FOR_VECTOR (i, db.Files) 657 { 658 const UString &name = db.Names[i]; 659 for (unsigned t = 0; t <= name.Len(); t++) 660 { 661 wchar_t c = name[t]; 662 WriteByte((Byte)c); 663 WriteByte((Byte)(c >> 8)); 664 } 665 } 666 } 667 } 668 669 /* if (headerOptions.WriteCTime) */ WriteUInt64DefVector(db.CTime, NID::kCTime); 670 /* if (headerOptions.WriteATime) */ WriteUInt64DefVector(db.ATime, NID::kATime); 671 /* if (headerOptions.WriteMTime) */ WriteUInt64DefVector(db.MTime, NID::kMTime); 672 WriteUInt64DefVector(db.StartPos, NID::kStartPos); 673 674 { 675 /* ---------- Write Attrib ---------- */ 676 CBoolVector boolVector; 677 boolVector.ClearAndSetSize(db.Files.Size()); 678 unsigned numDefined = 0; 679 680 { 681 FOR_VECTOR (i, db.Files) 682 { 683 bool defined = db.Files[i].AttribDefined; 684 boolVector[i] = defined; 685 if (defined) 686 numDefined++; 687 } 688 } 689 690 if (numDefined != 0) 691 { 692 WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttrib, 4); 693 FOR_VECTOR (i, db.Files) 694 { 695 const CFileItem &file = db.Files[i]; 696 if (file.AttribDefined) 697 WriteUInt32(file.Attrib); 698 } 699 } 700 } 701 702 /* 703 { 704 // ---------- Write IsAux ---------- 705 unsigned numAux = 0; 706 const CBoolVector &isAux = db.IsAux; 707 for (i = 0; i < isAux.Size(); i++) 708 if (isAux[i]) 709 numAux++; 710 if (numAux > 0) 711 { 712 const unsigned bvSize = Bv_GetSizeInBytes(isAux); 713 WriteByte(NID::kIsAux); 714 WriteNumber(bvSize); 715 WriteBoolVector(isAux); 716 } 717 } 718 719 { 720 // ---------- Write Parent ---------- 721 CBoolVector boolVector; 722 boolVector.Reserve(db.Files.Size()); 723 unsigned numIsDir = 0; 724 unsigned numParentLinks = 0; 725 for (i = 0; i < db.Files.Size(); i++) 726 { 727 const CFileItem &file = db.Files[i]; 728 bool defined = !file.IsAltStream; 729 boolVector.Add(defined); 730 if (defined) 731 numIsDir++; 732 if (file.Parent >= 0) 733 numParentLinks++; 734 } 735 if (numParentLinks > 0) 736 { 737 // WriteAlignedBoolHeader(boolVector, numDefined, NID::kParent, 4); 738 const unsigned bvSize = (numIsDir == boolVector.Size()) ? 0 : Bv_GetSizeInBytes(boolVector); 739 const UInt64 dataSize = (UInt64)db.Files.Size() * 4 + bvSize + 1; 740 SkipAlign(2 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), 4); 741 742 WriteByte(NID::kParent); 743 WriteNumber(dataSize); 744 if (numIsDir == boolVector.Size()) 745 WriteByte(1); 746 else 747 { 748 WriteByte(0); 749 WriteBoolVector(boolVector); 750 } 751 for (i = 0; i < db.Files.Size(); i++) 752 { 753 const CFileItem &file = db.Files[i]; 754 // if (file.Parent >= 0) 755 WriteUInt32(file.Parent); 756 } 757 } 758 } 759 760 if (thereIsSecure) 761 { 762 UInt64 secureDataSize = 1 + 4 + 763 db.SecureBuf.Size() + 764 db.SecureSizes.Size() * 4; 765 // secureDataSize += db.SecureIDs.Size() * 4; 766 for (i = 0; i < db.SecureIDs.Size(); i++) 767 secureDataSize += GetBigNumberSize(db.SecureIDs[i]); 768 SkipAlign(2 + GetBigNumberSize(secureDataSize), 4); 769 WriteByte(NID::kNtSecure); 770 WriteNumber(secureDataSize); 771 WriteByte(0); 772 WriteUInt32(db.SecureSizes.Size()); 773 for (i = 0; i < db.SecureSizes.Size(); i++) 774 WriteUInt32(db.SecureSizes[i]); 775 WriteBytes(db.SecureBuf, db.SecureBuf.Size()); 776 for (i = 0; i < db.SecureIDs.Size(); i++) 777 { 778 WriteNumber(db.SecureIDs[i]); 779 // WriteUInt32(db.SecureIDs[i]); 780 } 781 } 782 */ 783 784 WriteByte(NID::kEnd); // for files 785 WriteByte(NID::kEnd); // for headers 786 } 787 788 HRESULT COutArchive::WriteDatabase( 789 DECL_EXTERNAL_CODECS_LOC_VARS 790 const CArchiveDatabaseOut &db, 791 const CCompressionMethodMode *options, 792 const CHeaderOptions &headerOptions) 793 { 794 if (!db.CheckNumFiles()) 795 return E_FAIL; 796 797 UInt64 headerOffset; 798 UInt32 headerCRC; 799 UInt64 headerSize; 800 if (db.IsEmpty()) 801 { 802 headerSize = 0; 803 headerOffset = 0; 804 headerCRC = CrcCalc(0, 0); 805 } 806 else 807 { 808 bool encodeHeaders = false; 809 if (options != 0) 810 if (options->IsEmpty()) 811 options = 0; 812 if (options != 0) 813 if (options->PasswordIsDefined || headerOptions.CompressMainHeader) 814 encodeHeaders = true; 815 816 _outByte.SetStream(SeqStream); 817 _outByte.Init(); 818 _crc = CRC_INIT_VAL; 819 _countMode = encodeHeaders; 820 _writeToStream = true; 821 _countSize = 0; 822 WriteHeader(db, /* headerOptions, */ headerOffset); 823 824 if (encodeHeaders) 825 { 826 CByteBuffer buf(_countSize); 827 _outByte2.Init((Byte *)buf, _countSize); 828 829 _countMode = false; 830 _writeToStream = false; 831 WriteHeader(db, /* headerOptions, */ headerOffset); 832 833 if (_countSize != _outByte2.GetPos()) 834 return E_FAIL; 835 836 CCompressionMethodMode encryptOptions; 837 encryptOptions.PasswordIsDefined = options->PasswordIsDefined; 838 encryptOptions.Password = options->Password; 839 CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions); 840 CRecordVector<UInt64> packSizes; 841 CObjectVector<CFolder> folders; 842 COutFolders outFolders; 843 844 RINOK(EncodeStream( 845 EXTERNAL_CODECS_LOC_VARS 846 encoder, buf, 847 packSizes, folders, outFolders)); 848 849 _writeToStream = true; 850 851 if (folders.Size() == 0) 852 throw 1; 853 854 WriteID(NID::kEncodedHeader); 855 WritePackInfo(headerOffset, packSizes, CUInt32DefVector()); 856 WriteUnpackInfo(folders, outFolders); 857 WriteByte(NID::kEnd); 858 FOR_VECTOR (i, packSizes) 859 headerOffset += packSizes[i]; 860 } 861 RINOK(_outByte.Flush()); 862 headerCRC = CRC_GET_DIGEST(_crc); 863 headerSize = _outByte.GetProcessedSize(); 864 } 865 #ifdef _7Z_VOL 866 if (_endMarker) 867 { 868 CFinishHeader h; 869 h.NextHeaderSize = headerSize; 870 h.NextHeaderCRC = headerCRC; 871 h.NextHeaderOffset = 872 UInt64(0) - (headerSize + 873 4 + kFinishHeaderSize); 874 h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset; 875 h.AdditionalStartBlockSize = 0; 876 RINOK(WriteFinishHeader(h)); 877 return WriteFinishSignature(); 878 } 879 else 880 #endif 881 { 882 CStartHeader h; 883 h.NextHeaderSize = headerSize; 884 h.NextHeaderCRC = headerCRC; 885 h.NextHeaderOffset = headerOffset; 886 RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL)); 887 return WriteStartHeader(h); 888 } 889 } 890 891 void CUInt64DefVector::SetItem(unsigned index, bool defined, UInt64 value) 892 { 893 while (index >= Defs.Size()) 894 Defs.Add(false); 895 Defs[index] = defined; 896 if (!defined) 897 return; 898 while (index >= Vals.Size()) 899 Vals.Add(0); 900 Vals[index] = value; 901 } 902 903 void CArchiveDatabaseOut::AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name) 904 { 905 unsigned index = Files.Size(); 906 CTime.SetItem(index, file2.CTimeDefined, file2.CTime); 907 ATime.SetItem(index, file2.ATimeDefined, file2.ATime); 908 MTime.SetItem(index, file2.MTimeDefined, file2.MTime); 909 StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos); 910 SetItem_Anti(index, file2.IsAnti); 911 // SetItem_Aux(index, file2.IsAux); 912 Names.Add(name); 913 Files.Add(file); 914 } 915 916 }} 917