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 unsigned BoolVector_CountSum(const CBoolVector &v); 334 335 void COutArchive::WriteHashDigests(const CUInt32DefVector &digests) 336 { 337 const unsigned numDefined = BoolVector_CountSum(digests.Defs); 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 350 for (unsigned i = 0; i < digests.Defs.Size(); i++) 351 if (digests.Defs[i]) 352 WriteUInt32(digests.Vals[i]); 353 } 354 355 void COutArchive::WritePackInfo( 356 UInt64 dataOffset, 357 const CRecordVector<UInt64> &packSizes, 358 const CUInt32DefVector &packCRCs) 359 { 360 if (packSizes.IsEmpty()) 361 return; 362 WriteByte(NID::kPackInfo); 363 WriteNumber(dataOffset); 364 WriteNumber(packSizes.Size()); 365 WriteByte(NID::kSize); 366 FOR_VECTOR (i, packSizes) 367 WriteNumber(packSizes[i]); 368 369 WriteHashDigests(packCRCs); 370 371 WriteByte(NID::kEnd); 372 } 373 374 void COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders, const COutFolders &outFolders) 375 { 376 if (folders.IsEmpty()) 377 return; 378 379 WriteByte(NID::kUnpackInfo); 380 381 WriteByte(NID::kFolder); 382 WriteNumber(folders.Size()); 383 { 384 WriteByte(0); 385 FOR_VECTOR (i, folders) 386 WriteFolder(folders[i]); 387 } 388 389 WriteByte(NID::kCodersUnpackSize); 390 FOR_VECTOR (i, outFolders.CoderUnpackSizes) 391 WriteNumber(outFolders.CoderUnpackSizes[i]); 392 393 WriteHashDigests(outFolders.FolderUnpackCRCs); 394 395 WriteByte(NID::kEnd); 396 } 397 398 void COutArchive::WriteSubStreamsInfo(const CObjectVector<CFolder> &folders, 399 const COutFolders &outFolders, 400 const CRecordVector<UInt64> &unpackSizes, 401 const CUInt32DefVector &digests) 402 { 403 const CRecordVector<CNum> &numUnpackStreamsInFolders = outFolders.NumUnpackStreamsVector; 404 WriteByte(NID::kSubStreamsInfo); 405 406 unsigned i; 407 for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) 408 if (numUnpackStreamsInFolders[i] != 1) 409 { 410 WriteByte(NID::kNumUnpackStream); 411 for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) 412 WriteNumber(numUnpackStreamsInFolders[i]); 413 break; 414 } 415 416 for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) 417 if (numUnpackStreamsInFolders[i] > 1) 418 { 419 WriteByte(NID::kSize); 420 CNum index = 0; 421 for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) 422 { 423 CNum num = numUnpackStreamsInFolders[i]; 424 for (CNum j = 0; j < num; j++) 425 { 426 if (j + 1 != num) 427 WriteNumber(unpackSizes[index]); 428 index++; 429 } 430 } 431 break; 432 } 433 434 CUInt32DefVector digests2; 435 436 unsigned digestIndex = 0; 437 for (i = 0; i < folders.Size(); i++) 438 { 439 unsigned numSubStreams = (unsigned)numUnpackStreamsInFolders[i]; 440 if (numSubStreams == 1 && outFolders.FolderUnpackCRCs.ValidAndDefined(i)) 441 digestIndex++; 442 else 443 for (unsigned j = 0; j < numSubStreams; j++, digestIndex++) 444 { 445 digests2.Defs.Add(digests.Defs[digestIndex]); 446 digests2.Vals.Add(digests.Vals[digestIndex]); 447 } 448 } 449 WriteHashDigests(digests2); 450 WriteByte(NID::kEnd); 451 } 452 453 // 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field. 454 455 void COutArchive::SkipToAligned(unsigned pos, unsigned alignShifts) 456 { 457 if (!_useAlign) 458 return; 459 460 const unsigned alignSize = (unsigned)1 << alignShifts; 461 pos += (unsigned)GetPos(); 462 pos &= (alignSize - 1); 463 if (pos == 0) 464 return; 465 unsigned skip = alignSize - pos; 466 if (skip < 2) 467 skip += alignSize; 468 skip -= 2; 469 WriteByte(NID::kDummy); 470 WriteByte((Byte)skip); 471 for (unsigned i = 0; i < skip; i++) 472 WriteByte(0); 473 } 474 475 void COutArchive::WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts) 476 { 477 const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v); 478 const UInt64 dataSize = ((UInt64)numDefined << itemSizeShifts) + bvSize + 2; 479 SkipToAligned(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSizeShifts); 480 481 WriteByte(type); 482 WriteNumber(dataSize); 483 if (numDefined == v.Size()) 484 WriteByte(1); 485 else 486 { 487 WriteByte(0); 488 WriteBoolVector(v); 489 } 490 WriteByte(0); // 0 means no switching to external stream 491 } 492 493 void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type) 494 { 495 const unsigned numDefined = BoolVector_CountSum(v.Defs); 496 if (numDefined == 0) 497 return; 498 499 WriteAlignedBools(v.Defs, numDefined, type, 3); 500 501 for (unsigned i = 0; i < v.Defs.Size(); i++) 502 if (v.Defs[i]) 503 WriteUInt64(v.Vals[i]); 504 } 505 506 HRESULT COutArchive::EncodeStream( 507 DECL_EXTERNAL_CODECS_LOC_VARS 508 CEncoder &encoder, const CByteBuffer &data, 509 CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders) 510 { 511 CBufInStream *streamSpec = new CBufInStream; 512 CMyComPtr<ISequentialInStream> stream = streamSpec; 513 streamSpec->Init(data, data.Size()); 514 outFolders.FolderUnpackCRCs.Defs.Add(true); 515 outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size())); 516 // outFolders.NumUnpackStreamsVector.Add(1); 517 UInt64 dataSize64 = data.Size(); 518 UInt64 unpackSize = data.Size(); 519 RINOK(encoder.Encode( 520 EXTERNAL_CODECS_LOC_VARS 521 stream, 522 // NULL, 523 &dataSize64, 524 folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL)) 525 return S_OK; 526 } 527 528 void 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 { 539 UInt64 packSize = 0; 540 FOR_VECTOR (i, db.PackSizes) 541 packSize += db.PackSizes[i]; 542 headerOffset = packSize; 543 } 544 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_VECTOR (i, db.Files) 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 { 587 FOR_VECTOR (i, db.Files) 588 if (db.Files[i].HasStream) 589 emptyStreamVector[i] = false; 590 else 591 { 592 emptyStreamVector[i] = true; 593 numEmptyStreams++; 594 } 595 } 596 597 if (numEmptyStreams != 0) 598 { 599 WritePropBoolVector(NID::kEmptyStream, emptyStreamVector); 600 601 CBoolVector emptyFileVector, antiVector; 602 emptyFileVector.ClearAndSetSize(numEmptyStreams); 603 antiVector.ClearAndSetSize(numEmptyStreams); 604 bool thereAreEmptyFiles = false, thereAreAntiItems = false; 605 unsigned cur = 0; 606 607 FOR_VECTOR (i, db.Files) 608 { 609 const CFileItem &file = db.Files[i]; 610 if (file.HasStream) 611 continue; 612 emptyFileVector[cur] = !file.IsDir; 613 if (!file.IsDir) 614 thereAreEmptyFiles = true; 615 bool isAnti = db.IsItemAnti(i); 616 antiVector[cur] = isAnti; 617 if (isAnti) 618 thereAreAntiItems = true; 619 cur++; 620 } 621 622 if (thereAreEmptyFiles) 623 WritePropBoolVector(NID::kEmptyFile, emptyFileVector); 624 if (thereAreAntiItems) 625 WritePropBoolVector(NID::kAnti, antiVector); 626 } 627 } 628 629 630 { 631 /* ---------- Names ---------- */ 632 633 unsigned numDefined = 0; 634 size_t namesDataSize = 0; 635 FOR_VECTOR (i, db.Files) 636 { 637 const UString &name = db.Names[i]; 638 if (!name.IsEmpty()) 639 numDefined++; 640 namesDataSize += (name.Len() + 1) * 2; 641 } 642 643 if (numDefined > 0) 644 { 645 namesDataSize++; 646 SkipToAligned(2 + GetBigNumberSize(namesDataSize), 4); 647 648 WriteByte(NID::kName); 649 WriteNumber(namesDataSize); 650 WriteByte(0); 651 FOR_VECTOR (i, db.Files) 652 { 653 const UString &name = db.Names[i]; 654 for (unsigned t = 0; t <= name.Len(); t++) 655 { 656 wchar_t c = name[t]; 657 WriteByte((Byte)c); 658 WriteByte((Byte)(c >> 8)); 659 } 660 } 661 } 662 } 663 664 /* if (headerOptions.WriteCTime) */ WriteUInt64DefVector(db.CTime, NID::kCTime); 665 /* if (headerOptions.WriteATime) */ WriteUInt64DefVector(db.ATime, NID::kATime); 666 /* if (headerOptions.WriteMTime) */ WriteUInt64DefVector(db.MTime, NID::kMTime); 667 WriteUInt64DefVector(db.StartPos, NID::kStartPos); 668 669 { 670 /* ---------- Write Attrib ---------- */ 671 const unsigned numDefined = BoolVector_CountSum(db.Attrib.Defs); 672 673 if (numDefined != 0) 674 { 675 WriteAlignedBools(db.Attrib.Defs, numDefined, NID::kWinAttrib, 2); 676 FOR_VECTOR (i, db.Attrib.Defs) 677 { 678 if (db.Attrib.Defs[i]) 679 WriteUInt32(db.Attrib.Vals[i]); 680 } 681 } 682 } 683 684 /* 685 { 686 // ---------- Write IsAux ---------- 687 if (BoolVector_CountSum(db.IsAux) != 0) 688 WritePropBoolVector(NID::kIsAux, db.IsAux); 689 } 690 691 { 692 // ---------- Write Parent ---------- 693 CBoolVector boolVector; 694 boolVector.Reserve(db.Files.Size()); 695 unsigned numIsDir = 0; 696 unsigned numParentLinks = 0; 697 for (i = 0; i < db.Files.Size(); i++) 698 { 699 const CFileItem &file = db.Files[i]; 700 bool defined = !file.IsAltStream; 701 boolVector.Add(defined); 702 if (defined) 703 numIsDir++; 704 if (file.Parent >= 0) 705 numParentLinks++; 706 } 707 if (numParentLinks > 0) 708 { 709 // WriteAlignedBools(boolVector, numDefined, NID::kParent, 2); 710 const unsigned bvSize = (numIsDir == boolVector.Size()) ? 0 : Bv_GetSizeInBytes(boolVector); 711 const UInt64 dataSize = (UInt64)db.Files.Size() * 4 + bvSize + 1; 712 SkipToAligned(2 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), 2); 713 714 WriteByte(NID::kParent); 715 WriteNumber(dataSize); 716 if (numIsDir == boolVector.Size()) 717 WriteByte(1); 718 else 719 { 720 WriteByte(0); 721 WriteBoolVector(boolVector); 722 } 723 for (i = 0; i < db.Files.Size(); i++) 724 { 725 const CFileItem &file = db.Files[i]; 726 // if (file.Parent >= 0) 727 WriteUInt32(file.Parent); 728 } 729 } 730 } 731 732 if (thereIsSecure) 733 { 734 UInt64 secureDataSize = 1 + 4 + 735 db.SecureBuf.Size() + 736 db.SecureSizes.Size() * 4; 737 // secureDataSize += db.SecureIDs.Size() * 4; 738 for (i = 0; i < db.SecureIDs.Size(); i++) 739 secureDataSize += GetBigNumberSize(db.SecureIDs[i]); 740 SkipToAligned(2 + GetBigNumberSize(secureDataSize), 2); 741 WriteByte(NID::kNtSecure); 742 WriteNumber(secureDataSize); 743 WriteByte(0); 744 WriteUInt32(db.SecureSizes.Size()); 745 for (i = 0; i < db.SecureSizes.Size(); i++) 746 WriteUInt32(db.SecureSizes[i]); 747 WriteBytes(db.SecureBuf, db.SecureBuf.Size()); 748 for (i = 0; i < db.SecureIDs.Size(); i++) 749 { 750 WriteNumber(db.SecureIDs[i]); 751 // WriteUInt32(db.SecureIDs[i]); 752 } 753 } 754 */ 755 756 WriteByte(NID::kEnd); // for files 757 WriteByte(NID::kEnd); // for headers 758 } 759 760 HRESULT COutArchive::WriteDatabase( 761 DECL_EXTERNAL_CODECS_LOC_VARS 762 const CArchiveDatabaseOut &db, 763 const CCompressionMethodMode *options, 764 const CHeaderOptions &headerOptions) 765 { 766 if (!db.CheckNumFiles()) 767 return E_FAIL; 768 769 UInt64 headerOffset; 770 UInt32 headerCRC; 771 UInt64 headerSize; 772 if (db.IsEmpty()) 773 { 774 headerSize = 0; 775 headerOffset = 0; 776 headerCRC = CrcCalc(0, 0); 777 } 778 else 779 { 780 bool encodeHeaders = false; 781 if (options != 0) 782 if (options->IsEmpty()) 783 options = 0; 784 if (options != 0) 785 if (options->PasswordIsDefined || headerOptions.CompressMainHeader) 786 encodeHeaders = true; 787 788 _outByte.SetStream(SeqStream); 789 _outByte.Init(); 790 _crc = CRC_INIT_VAL; 791 _countMode = encodeHeaders; 792 _writeToStream = true; 793 _countSize = 0; 794 WriteHeader(db, /* headerOptions, */ headerOffset); 795 796 if (encodeHeaders) 797 { 798 CByteBuffer buf(_countSize); 799 _outByte2.Init((Byte *)buf, _countSize); 800 801 _countMode = false; 802 _writeToStream = false; 803 WriteHeader(db, /* headerOptions, */ headerOffset); 804 805 if (_countSize != _outByte2.GetPos()) 806 return E_FAIL; 807 808 CCompressionMethodMode encryptOptions; 809 encryptOptions.PasswordIsDefined = options->PasswordIsDefined; 810 encryptOptions.Password = options->Password; 811 CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions); 812 CRecordVector<UInt64> packSizes; 813 CObjectVector<CFolder> folders; 814 COutFolders outFolders; 815 816 RINOK(EncodeStream( 817 EXTERNAL_CODECS_LOC_VARS 818 encoder, buf, 819 packSizes, folders, outFolders)); 820 821 _writeToStream = true; 822 823 if (folders.Size() == 0) 824 throw 1; 825 826 WriteID(NID::kEncodedHeader); 827 WritePackInfo(headerOffset, packSizes, CUInt32DefVector()); 828 WriteUnpackInfo(folders, outFolders); 829 WriteByte(NID::kEnd); 830 FOR_VECTOR (i, packSizes) 831 headerOffset += packSizes[i]; 832 } 833 RINOK(_outByte.Flush()); 834 headerCRC = CRC_GET_DIGEST(_crc); 835 headerSize = _outByte.GetProcessedSize(); 836 } 837 #ifdef _7Z_VOL 838 if (_endMarker) 839 { 840 CFinishHeader h; 841 h.NextHeaderSize = headerSize; 842 h.NextHeaderCRC = headerCRC; 843 h.NextHeaderOffset = 844 UInt64(0) - (headerSize + 845 4 + kFinishHeaderSize); 846 h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset; 847 h.AdditionalStartBlockSize = 0; 848 RINOK(WriteFinishHeader(h)); 849 return WriteFinishSignature(); 850 } 851 else 852 #endif 853 { 854 CStartHeader h; 855 h.NextHeaderSize = headerSize; 856 h.NextHeaderCRC = headerCRC; 857 h.NextHeaderOffset = headerOffset; 858 RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL)); 859 return WriteStartHeader(h); 860 } 861 } 862 863 void CUInt32DefVector::SetItem(unsigned index, bool defined, UInt32 value) 864 { 865 while (index >= Defs.Size()) 866 Defs.Add(false); 867 Defs[index] = defined; 868 if (!defined) 869 return; 870 while (index >= Vals.Size()) 871 Vals.Add(0); 872 Vals[index] = value; 873 } 874 875 void CUInt64DefVector::SetItem(unsigned index, bool defined, UInt64 value) 876 { 877 while (index >= Defs.Size()) 878 Defs.Add(false); 879 Defs[index] = defined; 880 if (!defined) 881 return; 882 while (index >= Vals.Size()) 883 Vals.Add(0); 884 Vals[index] = value; 885 } 886 887 void CArchiveDatabaseOut::AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name) 888 { 889 unsigned index = Files.Size(); 890 CTime.SetItem(index, file2.CTimeDefined, file2.CTime); 891 ATime.SetItem(index, file2.ATimeDefined, file2.ATime); 892 MTime.SetItem(index, file2.MTimeDefined, file2.MTime); 893 StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos); 894 Attrib.SetItem(index, file2.AttribDefined, file2.Attrib); 895 SetItem_Anti(index, file2.IsAnti); 896 // SetItem_Aux(index, file2.IsAux); 897 Names.Add(name); 898 Files.Add(file); 899 } 900 901 }} 902