tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

7zOut.cpp (23100B)


      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 }}