| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026 |
- // 7zOut.cpp
- #include "StdAfx.h"
- #include "../../../Common/AutoPtr.h"
- #include "../../Common/StreamObjects.h"
- #include "7zOut.h"
- extern "C"
- {
- #include "../../../../C/7zCrc.h"
- }
- static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size)
- {
- while (size > 0)
- {
- UInt32 curSize = (UInt32)MyMin(size, (size_t)0xFFFFFFFF);
- UInt32 processedSize;
- RINOK(stream->Write(data, curSize, &processedSize));
- if(processedSize == 0)
- return E_FAIL;
- data = (const void *)((const Byte *)data + processedSize);
- size -= processedSize;
- }
- return S_OK;
- }
- namespace NArchive {
- namespace N7z {
- HRESULT COutArchive::WriteDirect(const void *data, UInt32 size)
- {
- return ::WriteBytes(SeqStream, data, size);
- }
- UInt32 CrcUpdateUInt32(UInt32 crc, UInt32 value)
- {
- for (int i = 0; i < 4; i++, value >>= 8)
- crc = CRC_UPDATE_BYTE(crc, (Byte)value);
- return crc;
- }
- UInt32 CrcUpdateUInt64(UInt32 crc, UInt64 value)
- {
- for (int i = 0; i < 8; i++, value >>= 8)
- crc = CRC_UPDATE_BYTE(crc, (Byte)value);
- return crc;
- }
- HRESULT COutArchive::WriteDirectUInt32(UInt32 value)
- {
- for (int i = 0; i < 4; i++)
- {
- RINOK(WriteDirectByte((Byte)value));
- value >>= 8;
- }
- return S_OK;
- }
- HRESULT COutArchive::WriteDirectUInt64(UInt64 value)
- {
- for (int i = 0; i < 8; i++)
- {
- RINOK(WriteDirectByte((Byte)value));
- value >>= 8;
- }
- return S_OK;
- }
- HRESULT COutArchive::WriteSignature()
- {
- RINOK(WriteDirect(kSignature, kSignatureSize));
- RINOK(WriteDirectByte(kMajorVersion));
- return WriteDirectByte(2);
- }
- #ifdef _7Z_VOL
- HRESULT COutArchive::WriteFinishSignature()
- {
- RINOK(WriteDirect(kFinishSignature, kSignatureSize));
- CArchiveVersion av;
- av.Major = kMajorVersion;
- av.Minor = 2;
- RINOK(WriteDirectByte(av.Major));
- return WriteDirectByte(av.Minor);
- }
- #endif
- HRESULT COutArchive::WriteStartHeader(const CStartHeader &h)
- {
- UInt32 crc = CRC_INIT_VAL;
- crc = CrcUpdateUInt64(crc, h.NextHeaderOffset);
- crc = CrcUpdateUInt64(crc, h.NextHeaderSize);
- crc = CrcUpdateUInt32(crc, h.NextHeaderCRC);
- RINOK(WriteDirectUInt32(CRC_GET_DIGEST(crc)));
- RINOK(WriteDirectUInt64(h.NextHeaderOffset));
- RINOK(WriteDirectUInt64(h.NextHeaderSize));
- return WriteDirectUInt32(h.NextHeaderCRC);
- }
- #ifdef _7Z_VOL
- HRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h)
- {
- CCRC crc;
- crc.UpdateUInt64(h.NextHeaderOffset);
- crc.UpdateUInt64(h.NextHeaderSize);
- crc.UpdateUInt32(h.NextHeaderCRC);
- crc.UpdateUInt64(h.ArchiveStartOffset);
- crc.UpdateUInt64(h.AdditionalStartBlockSize);
- RINOK(WriteDirectUInt32(crc.GetDigest()));
- RINOK(WriteDirectUInt64(h.NextHeaderOffset));
- RINOK(WriteDirectUInt64(h.NextHeaderSize));
- RINOK(WriteDirectUInt32(h.NextHeaderCRC));
- RINOK(WriteDirectUInt64(h.ArchiveStartOffset));
- return WriteDirectUInt64(h.AdditionalStartBlockSize);
- }
- #endif
- HRESULT COutArchive::Create(ISequentialOutStream *stream, bool endMarker)
- {
- Close();
- #ifdef _7Z_VOL
- // endMarker = false;
- _endMarker = endMarker;
- #endif
- SeqStream = stream;
- if (!endMarker)
- {
- SeqStream.QueryInterface(IID_IOutStream, &Stream);
- if (!Stream)
- {
- return E_NOTIMPL;
- // endMarker = true;
- }
- }
- #ifdef _7Z_VOL
- if (endMarker)
- {
- /*
- CStartHeader sh;
- sh.NextHeaderOffset = (UInt32)(Int32)-1;
- sh.NextHeaderSize = (UInt32)(Int32)-1;
- sh.NextHeaderCRC = 0;
- WriteStartHeader(sh);
- */
- }
- else
- #endif
- {
- if (!Stream)
- return E_FAIL;
- RINOK(WriteSignature());
- RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_prefixHeaderPos));
- }
- return S_OK;
- }
- void COutArchive::Close()
- {
- SeqStream.Release();
- Stream.Release();
- }
- HRESULT COutArchive::SkeepPrefixArchiveHeader()
- {
- #ifdef _7Z_VOL
- if (_endMarker)
- return S_OK;
- #endif
- return Stream->Seek(24, STREAM_SEEK_CUR, NULL);
- }
- HRESULT COutArchive::WriteBytes(const void *data, size_t size)
- {
- if (_mainMode)
- {
- if (_dynamicMode)
- _dynamicBuffer.Write(data, size);
- else
- _outByte.WriteBytes(data, size);
- _crc = CrcUpdate(_crc, data, size);
- }
- else
- {
- if (_countMode)
- _countSize += size;
- else
- RINOK(_outByte2.Write(data, size));
- }
- return S_OK;
- }
- HRESULT COutArchive::WriteBytes(const CByteBuffer &data)
- {
- return WriteBytes(data, data.GetCapacity());
- }
- HRESULT COutArchive::WriteByte(Byte b)
- {
- return WriteBytes(&b, 1);
- }
- HRESULT COutArchive::WriteUInt32(UInt32 value)
- {
- for (int i = 0; i < 4; i++)
- {
- RINOK(WriteByte((Byte)value));
- value >>= 8;
- }
- return S_OK;
- }
- HRESULT COutArchive::WriteNumber(UInt64 value)
- {
- Byte firstByte = 0;
- Byte mask = 0x80;
- int i;
- for (i = 0; i < 8; i++)
- {
- if (value < ((UInt64(1) << ( 7 * (i + 1)))))
- {
- firstByte |= Byte(value >> (8 * i));
- break;
- }
- firstByte |= mask;
- mask >>= 1;
- }
- RINOK(WriteByte(firstByte));
- for (;i > 0; i--)
- {
- RINOK(WriteByte((Byte)value));
- value >>= 8;
- }
- return S_OK;
- }
- #ifdef _7Z_VOL
- static UInt32 GetBigNumberSize(UInt64 value)
- {
- int i;
- for (i = 0; i < 8; i++)
- if (value < ((UInt64(1) << ( 7 * (i + 1)))))
- break;
- return 1 + i;
- }
- UInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool props)
- {
- UInt32 result = GetBigNumberSize(dataSize) * 2 + 41;
- if (nameLength != 0)
- {
- nameLength = (nameLength + 1) * 2;
- result += nameLength + GetBigNumberSize(nameLength) + 2;
- }
- if (props)
- {
- result += 20;
- }
- if (result >= 128)
- result++;
- result += kSignatureSize + 2 + kFinishHeaderSize;
- return result;
- }
- UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props)
- {
- UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props);
- int testSize;
- if (volSize > headersSizeBase)
- testSize = volSize - headersSizeBase;
- else
- testSize = 1;
- UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, props);
- UInt64 pureSize = 1;
- if (volSize > headersSize)
- pureSize = volSize - headersSize;
- return pureSize;
- }
- #endif
- HRESULT COutArchive::WriteFolder(const CFolder &folder)
- {
- RINOK(WriteNumber(folder.Coders.Size()));
- int i;
- for (i = 0; i < folder.Coders.Size(); i++)
- {
- const CCoderInfo &coder = folder.Coders[i];
- {
- size_t propertiesSize = coder.Properties.GetCapacity();
-
- UInt64 id = coder.MethodID;
- int idSize;
- for (idSize = 1; idSize < sizeof(id); idSize++)
- if ((id >> (8 * idSize)) == 0)
- break;
- BYTE longID[15];
- for (int t = idSize - 1; t >= 0 ; t--, id >>= 8)
- longID[t] = (Byte)(id & 0xFF);
- Byte b;
- b = (Byte)(idSize & 0xF);
- bool isComplex = !coder.IsSimpleCoder();
- b |= (isComplex ? 0x10 : 0);
- b |= ((propertiesSize != 0) ? 0x20 : 0 );
- RINOK(WriteByte(b));
- RINOK(WriteBytes(longID, idSize));
- if (isComplex)
- {
- RINOK(WriteNumber(coder.NumInStreams));
- RINOK(WriteNumber(coder.NumOutStreams));
- }
- if (propertiesSize == 0)
- continue;
- RINOK(WriteNumber(propertiesSize));
- RINOK(WriteBytes(coder.Properties, propertiesSize));
- }
- }
- for (i = 0; i < folder.BindPairs.Size(); i++)
- {
- const CBindPair &bindPair = folder.BindPairs[i];
- RINOK(WriteNumber(bindPair.InIndex));
- RINOK(WriteNumber(bindPair.OutIndex));
- }
- if (folder.PackStreams.Size() > 1)
- for (i = 0; i < folder.PackStreams.Size(); i++)
- {
- RINOK(WriteNumber(folder.PackStreams[i]));
- }
- return S_OK;
- }
- HRESULT COutArchive::WriteBoolVector(const CBoolVector &boolVector)
- {
- Byte b = 0;
- Byte mask = 0x80;
- for(int i = 0; i < boolVector.Size(); i++)
- {
- if (boolVector[i])
- b |= mask;
- mask >>= 1;
- if (mask == 0)
- {
- RINOK(WriteByte(b));
- mask = 0x80;
- b = 0;
- }
- }
- if (mask != 0x80)
- {
- RINOK(WriteByte(b));
- }
- return S_OK;
- }
- HRESULT COutArchive::WriteHashDigests(
- const CRecordVector<bool> &digestsDefined,
- const CRecordVector<UInt32> &digests)
- {
- int numDefined = 0;
- int i;
- for(i = 0; i < digestsDefined.Size(); i++)
- if (digestsDefined[i])
- numDefined++;
- if (numDefined == 0)
- return S_OK;
- RINOK(WriteByte(NID::kCRC));
- if (numDefined == digestsDefined.Size())
- {
- RINOK(WriteByte(1));
- }
- else
- {
- RINOK(WriteByte(0));
- RINOK(WriteBoolVector(digestsDefined));
- }
- for(i = 0; i < digests.Size(); i++)
- {
- if(digestsDefined[i])
- RINOK(WriteUInt32(digests[i]));
- }
- return S_OK;
- }
- HRESULT COutArchive::WritePackInfo(
- UInt64 dataOffset,
- const CRecordVector<UInt64> &packSizes,
- const CRecordVector<bool> &packCRCsDefined,
- const CRecordVector<UInt32> &packCRCs)
- {
- if (packSizes.IsEmpty())
- return S_OK;
- RINOK(WriteByte(NID::kPackInfo));
- RINOK(WriteNumber(dataOffset));
- RINOK(WriteNumber(packSizes.Size()));
- RINOK(WriteByte(NID::kSize));
- for(int i = 0; i < packSizes.Size(); i++)
- RINOK(WriteNumber(packSizes[i]));
- RINOK(WriteHashDigests(packCRCsDefined, packCRCs));
-
- return WriteByte(NID::kEnd);
- }
- HRESULT COutArchive::WriteUnPackInfo(const CObjectVector<CFolder> &folders)
- {
- if (folders.IsEmpty())
- return S_OK;
- RINOK(WriteByte(NID::kUnPackInfo));
- RINOK(WriteByte(NID::kFolder));
- RINOK(WriteNumber(folders.Size()));
- {
- RINOK(WriteByte(0));
- for(int i = 0; i < folders.Size(); i++)
- RINOK(WriteFolder(folders[i]));
- }
-
- RINOK(WriteByte(NID::kCodersUnPackSize));
- int i;
- for(i = 0; i < folders.Size(); i++)
- {
- const CFolder &folder = folders[i];
- for (int j = 0; j < folder.UnPackSizes.Size(); j++)
- RINOK(WriteNumber(folder.UnPackSizes[j]));
- }
- CRecordVector<bool> unPackCRCsDefined;
- CRecordVector<UInt32> unPackCRCs;
- for(i = 0; i < folders.Size(); i++)
- {
- const CFolder &folder = folders[i];
- unPackCRCsDefined.Add(folder.UnPackCRCDefined);
- unPackCRCs.Add(folder.UnPackCRC);
- }
- RINOK(WriteHashDigests(unPackCRCsDefined, unPackCRCs));
- return WriteByte(NID::kEnd);
- }
- HRESULT COutArchive::WriteSubStreamsInfo(
- const CObjectVector<CFolder> &folders,
- const CRecordVector<CNum> &numUnPackStreamsInFolders,
- const CRecordVector<UInt64> &unPackSizes,
- const CRecordVector<bool> &digestsDefined,
- const CRecordVector<UInt32> &digests)
- {
- RINOK(WriteByte(NID::kSubStreamsInfo));
- int i;
- for(i = 0; i < numUnPackStreamsInFolders.Size(); i++)
- {
- if (numUnPackStreamsInFolders[i] != 1)
- {
- RINOK(WriteByte(NID::kNumUnPackStream));
- for(i = 0; i < numUnPackStreamsInFolders.Size(); i++)
- RINOK(WriteNumber(numUnPackStreamsInFolders[i]));
- break;
- }
- }
-
- bool needFlag = true;
- CNum index = 0;
- for(i = 0; i < numUnPackStreamsInFolders.Size(); i++)
- for (CNum j = 0; j < numUnPackStreamsInFolders[i]; j++)
- {
- if (j + 1 != numUnPackStreamsInFolders[i])
- {
- if (needFlag)
- RINOK(WriteByte(NID::kSize));
- needFlag = false;
- RINOK(WriteNumber(unPackSizes[index]));
- }
- index++;
- }
- CRecordVector<bool> digestsDefined2;
- CRecordVector<UInt32> digests2;
- int digestIndex = 0;
- for (i = 0; i < folders.Size(); i++)
- {
- int numSubStreams = (int)numUnPackStreamsInFolders[i];
- if (numSubStreams == 1 && folders[i].UnPackCRCDefined)
- digestIndex++;
- else
- for (int j = 0; j < numSubStreams; j++, digestIndex++)
- {
- digestsDefined2.Add(digestsDefined[digestIndex]);
- digests2.Add(digests[digestIndex]);
- }
- }
- RINOK(WriteHashDigests(digestsDefined2, digests2));
- return WriteByte(NID::kEnd);
- }
- HRESULT COutArchive::WriteTime(
- const CObjectVector<CFileItem> &files, Byte type)
- {
- /////////////////////////////////////////////////
- // CreationTime
- CBoolVector boolVector;
- boolVector.Reserve(files.Size());
- bool thereAreDefined = false;
- bool allDefined = true;
- int i;
- for(i = 0; i < files.Size(); i++)
- {
- const CFileItem &item = files[i];
- bool defined;
- switch(type)
- {
- case NID::kCreationTime:
- defined = item.IsCreationTimeDefined;
- break;
- case NID::kLastWriteTime:
- defined = item.IsLastWriteTimeDefined;
- break;
- case NID::kLastAccessTime:
- defined = item.IsLastAccessTimeDefined;
- break;
- default:
- throw 1;
- }
- boolVector.Add(defined);
- thereAreDefined = (thereAreDefined || defined);
- allDefined = (allDefined && defined);
- }
- if (!thereAreDefined)
- return S_OK;
- RINOK(WriteByte(type));
- size_t dataSize = 1 + 1;
- dataSize += files.Size() * 8;
- if (allDefined)
- {
- RINOK(WriteNumber(dataSize));
- WriteByte(1);
- }
- else
- {
- RINOK(WriteNumber(1 + (boolVector.Size() + 7) / 8 + dataSize));
- WriteByte(0);
- RINOK(WriteBoolVector(boolVector));
- }
- RINOK(WriteByte(0));
- for(i = 0; i < files.Size(); i++)
- {
- if (boolVector[i])
- {
- const CFileItem &item = files[i];
- CArchiveFileTime timeValue;
- timeValue.dwLowDateTime = 0;
- timeValue.dwHighDateTime = 0;
- switch(type)
- {
- case NID::kCreationTime:
- timeValue = item.CreationTime;
- break;
- case NID::kLastWriteTime:
- timeValue = item.LastWriteTime;
- break;
- case NID::kLastAccessTime:
- timeValue = item.LastAccessTime;
- break;
- }
- RINOK(WriteUInt32(timeValue.dwLowDateTime));
- RINOK(WriteUInt32(timeValue.dwHighDateTime));
- }
- }
- return S_OK;
- }
- HRESULT COutArchive::EncodeStream(
- DECL_EXTERNAL_CODECS_LOC_VARS
- CEncoder &encoder, const Byte *data, size_t dataSize,
- CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders)
- {
- CSequentialInStreamImp *streamSpec = new CSequentialInStreamImp;
- CMyComPtr<ISequentialInStream> stream = streamSpec;
- streamSpec->Init(data, dataSize);
- CFolder folderItem;
- folderItem.UnPackCRCDefined = true;
- folderItem.UnPackCRC = CrcCalc(data, dataSize);
- UInt64 dataSize64 = dataSize;
- RINOK(encoder.Encode(
- EXTERNAL_CODECS_LOC_VARS
- stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL))
- folders.Add(folderItem);
- return S_OK;
- }
- HRESULT COutArchive::EncodeStream(
- DECL_EXTERNAL_CODECS_LOC_VARS
- CEncoder &encoder, const CByteBuffer &data,
- CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders)
- {
- return EncodeStream(
- EXTERNAL_CODECS_LOC_VARS
- encoder, data, data.GetCapacity(), packSizes, folders);
- }
- static void WriteUInt32ToBuffer(Byte *data, UInt32 value)
- {
- for (int i = 0; i < 4; i++)
- {
- *data++ = (Byte)value;
- value >>= 8;
- }
- }
- static void WriteUInt64ToBuffer(Byte *data, UInt64 value)
- {
- for (int i = 0; i < 8; i++)
- {
- *data++ = (Byte)value;
- value >>= 8;
- }
- }
- HRESULT COutArchive::WriteHeader(
- const CArchiveDatabase &database,
- const CHeaderOptions &headerOptions,
- UInt64 &headerOffset)
- {
- int i;
-
- /////////////////////////////////
- // Names
- CNum numDefinedNames = 0;
- size_t namesDataSize = 0;
- for(i = 0; i < database.Files.Size(); i++)
- {
- const UString &name = database.Files[i].Name;
- if (!name.IsEmpty())
- numDefinedNames++;
- namesDataSize += (name.Length() + 1) * 2;
- }
- CByteBuffer namesData;
- if (numDefinedNames > 0)
- {
- namesData.SetCapacity((size_t)namesDataSize);
- size_t pos = 0;
- for(int i = 0; i < database.Files.Size(); i++)
- {
- const UString &name = database.Files[i].Name;
- for (int t = 0; t < name.Length(); t++)
- {
- wchar_t c = name[t];
- namesData[pos++] = Byte(c);
- namesData[pos++] = Byte(c >> 8);
- }
- namesData[pos++] = 0;
- namesData[pos++] = 0;
- }
- }
- /////////////////////////////////
- // Write Attributes
- CBoolVector attributesBoolVector;
- attributesBoolVector.Reserve(database.Files.Size());
- int numDefinedAttributes = 0;
- for(i = 0; i < database.Files.Size(); i++)
- {
- bool defined = database.Files[i].AreAttributesDefined;
- attributesBoolVector.Add(defined);
- if (defined)
- numDefinedAttributes++;
- }
- CByteBuffer attributesData;
- if (numDefinedAttributes > 0)
- {
- attributesData.SetCapacity(numDefinedAttributes * 4);
- size_t pos = 0;
- for(i = 0; i < database.Files.Size(); i++)
- {
- const CFileItem &file = database.Files[i];
- if (file.AreAttributesDefined)
- {
- WriteUInt32ToBuffer(attributesData + pos, file.Attributes);
- pos += 4;
- }
- }
- }
- /////////////////////////////////
- // Write StartPos
- CBoolVector startsBoolVector;
- startsBoolVector.Reserve(database.Files.Size());
- int numDefinedStarts = 0;
- for(i = 0; i < database.Files.Size(); i++)
- {
- bool defined = database.Files[i].IsStartPosDefined;
- startsBoolVector.Add(defined);
- if (defined)
- numDefinedStarts++;
- }
- CByteBuffer startsData;
- if (numDefinedStarts > 0)
- {
- startsData.SetCapacity(numDefinedStarts * 8);
- size_t pos = 0;
- for(i = 0; i < database.Files.Size(); i++)
- {
- const CFileItem &file = database.Files[i];
- if (file.IsStartPosDefined)
- {
- WriteUInt64ToBuffer(startsData + pos, file.StartPos);
- pos += 8;
- }
- }
- }
-
- /////////////////////////////////
- // Write Last Write Time
- // /*
- CNum numDefinedLastWriteTimes = 0;
- for(i = 0; i < database.Files.Size(); i++)
- if (database.Files[i].IsLastWriteTimeDefined)
- numDefinedLastWriteTimes++;
- if (numDefinedLastWriteTimes > 0)
- {
- CByteBuffer lastWriteTimeData;
- lastWriteTimeData.SetCapacity(numDefinedLastWriteTimes * 8);
- size_t pos = 0;
- for(i = 0; i < database.Files.Size(); i++)
- {
- const CFileItem &file = database.Files[i];
- if (file.IsLastWriteTimeDefined)
- {
- WriteUInt32ToBuffer(lastWriteTimeData + pos, file.LastWriteTime.dwLowDateTime);
- pos += 4;
- WriteUInt32ToBuffer(lastWriteTimeData + pos, file.LastWriteTime.dwHighDateTime);
- pos += 4;
- }
- }
- }
- // */
-
- UInt64 packedSize = 0;
- for(i = 0; i < database.PackSizes.Size(); i++)
- packedSize += database.PackSizes[i];
- headerOffset = packedSize;
- _mainMode = true;
- _outByte.SetStream(SeqStream);
- _outByte.Init();
- _crc = CRC_INIT_VAL;
- RINOK(WriteByte(NID::kHeader));
- // Archive Properties
- if (database.Folders.Size() > 0)
- {
- RINOK(WriteByte(NID::kMainStreamsInfo));
- RINOK(WritePackInfo(0, database.PackSizes,
- database.PackCRCsDefined,
- database.PackCRCs));
- RINOK(WriteUnPackInfo(database.Folders));
- CRecordVector<UInt64> unPackSizes;
- CRecordVector<bool> digestsDefined;
- CRecordVector<UInt32> digests;
- for (i = 0; i < database.Files.Size(); i++)
- {
- const CFileItem &file = database.Files[i];
- if (!file.HasStream)
- continue;
- unPackSizes.Add(file.UnPackSize);
- digestsDefined.Add(file.IsFileCRCDefined);
- digests.Add(file.FileCRC);
- }
- RINOK(WriteSubStreamsInfo(
- database.Folders,
- database.NumUnPackStreamsVector,
- unPackSizes,
- digestsDefined,
- digests));
- RINOK(WriteByte(NID::kEnd));
- }
- if (database.Files.IsEmpty())
- {
- RINOK(WriteByte(NID::kEnd));
- return _outByte.Flush();
- }
- RINOK(WriteByte(NID::kFilesInfo));
- RINOK(WriteNumber(database.Files.Size()));
- CBoolVector emptyStreamVector;
- emptyStreamVector.Reserve(database.Files.Size());
- int numEmptyStreams = 0;
- for(i = 0; i < database.Files.Size(); i++)
- if (database.Files[i].HasStream)
- emptyStreamVector.Add(false);
- else
- {
- emptyStreamVector.Add(true);
- numEmptyStreams++;
- }
- if (numEmptyStreams > 0)
- {
- RINOK(WriteByte(NID::kEmptyStream));
- RINOK(WriteNumber((emptyStreamVector.Size() + 7) / 8));
- RINOK(WriteBoolVector(emptyStreamVector));
- CBoolVector emptyFileVector, antiVector;
- emptyFileVector.Reserve(numEmptyStreams);
- antiVector.Reserve(numEmptyStreams);
- CNum numEmptyFiles = 0, numAntiItems = 0;
- for(i = 0; i < database.Files.Size(); i++)
- {
- const CFileItem &file = database.Files[i];
- if (!file.HasStream)
- {
- emptyFileVector.Add(!file.IsDirectory);
- if (!file.IsDirectory)
- numEmptyFiles++;
- antiVector.Add(file.IsAnti);
- if (file.IsAnti)
- numAntiItems++;
- }
- }
- if (numEmptyFiles > 0)
- {
- RINOK(WriteByte(NID::kEmptyFile));
- RINOK(WriteNumber((emptyFileVector.Size() + 7) / 8));
- RINOK(WriteBoolVector(emptyFileVector));
- }
- if (numAntiItems > 0)
- {
- RINOK(WriteByte(NID::kAnti));
- RINOK(WriteNumber((antiVector.Size() + 7) / 8));
- RINOK(WriteBoolVector(antiVector));
- }
- }
- if (numDefinedNames > 0)
- {
- /////////////////////////////////////////////////
- RINOK(WriteByte(NID::kName));
- {
- RINOK(WriteNumber(1 + namesData.GetCapacity()));
- RINOK(WriteByte(0));
- RINOK(WriteBytes(namesData));
- }
- }
- if (headerOptions.WriteCreated)
- {
- RINOK(WriteTime(database.Files, NID::kCreationTime));
- }
- if (headerOptions.WriteModified)
- {
- RINOK(WriteTime(database.Files, NID::kLastWriteTime));
- }
- if (headerOptions.WriteAccessed)
- {
- RINOK(WriteTime(database.Files, NID::kLastAccessTime));
- }
- if (numDefinedAttributes > 0)
- {
- RINOK(WriteByte(NID::kWinAttributes));
- size_t size = 2;
- if (numDefinedAttributes != database.Files.Size())
- size += (attributesBoolVector.Size() + 7) / 8 + 1;
- size += attributesData.GetCapacity();
- RINOK(WriteNumber(size));
- if (numDefinedAttributes == database.Files.Size())
- {
- RINOK(WriteByte(1));
- }
- else
- {
- RINOK(WriteByte(0));
- RINOK(WriteBoolVector(attributesBoolVector));
- }
- {
- RINOK(WriteByte(0));
- RINOK(WriteBytes(attributesData));
- }
- }
- if (numDefinedStarts > 0)
- {
- RINOK(WriteByte(NID::kStartPos));
- size_t size = 2;
- if (numDefinedStarts != database.Files.Size())
- size += (startsBoolVector.Size() + 7) / 8 + 1;
- size += startsData.GetCapacity();
- RINOK(WriteNumber(size));
- if (numDefinedStarts == database.Files.Size())
- {
- RINOK(WriteByte(1));
- }
- else
- {
- RINOK(WriteByte(0));
- RINOK(WriteBoolVector(startsBoolVector));
- }
- {
- RINOK(WriteByte(0));
- RINOK(WriteBytes(startsData));
- }
- }
- RINOK(WriteByte(NID::kEnd)); // for files
- RINOK(WriteByte(NID::kEnd)); // for headers
- return _outByte.Flush();
- }
- HRESULT COutArchive::WriteDatabase(
- DECL_EXTERNAL_CODECS_LOC_VARS
- const CArchiveDatabase &database,
- const CCompressionMethodMode *options,
- const CHeaderOptions &headerOptions)
- {
- UInt64 headerOffset;
- UInt32 headerCRC;
- UInt64 headerSize;
- if (database.IsEmpty())
- {
- headerSize = 0;
- headerOffset = 0;
- headerCRC = CrcCalc(0, 0);
- }
- else
- {
- _dynamicBuffer.Init();
- _dynamicMode = false;
- if (options != 0)
- if (options->IsEmpty())
- options = 0;
- if (options != 0)
- if (options->PasswordIsDefined || headerOptions.CompressMainHeader)
- _dynamicMode = true;
- RINOK(WriteHeader(database, headerOptions, headerOffset));
- if (_dynamicMode)
- {
- CCompressionMethodMode encryptOptions;
- encryptOptions.PasswordIsDefined = options->PasswordIsDefined;
- encryptOptions.Password = options->Password;
- CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions);
- CRecordVector<UInt64> packSizes;
- CObjectVector<CFolder> folders;
- RINOK(EncodeStream(
- EXTERNAL_CODECS_LOC_VARS
- encoder, _dynamicBuffer,
- _dynamicBuffer.GetSize(), packSizes, folders));
- _dynamicMode = false;
- _mainMode = true;
-
- _outByte.SetStream(SeqStream);
- _outByte.Init();
- _crc = CRC_INIT_VAL;
-
- if (folders.Size() == 0)
- throw 1;
- RINOK(WriteID(NID::kEncodedHeader));
- RINOK(WritePackInfo(headerOffset, packSizes,
- CRecordVector<bool>(), CRecordVector<UInt32>()));
- RINOK(WriteUnPackInfo(folders));
- RINOK(WriteByte(NID::kEnd));
- for (int i = 0; i < packSizes.Size(); i++)
- headerOffset += packSizes[i];
- RINOK(_outByte.Flush());
- }
- headerCRC = CRC_GET_DIGEST(_crc);
- headerSize = _outByte.GetProcessedSize();
- }
- #ifdef _7Z_VOL
- if (_endMarker)
- {
- CFinishHeader h;
- h.NextHeaderSize = headerSize;
- h.NextHeaderCRC = headerCRC;
- h.NextHeaderOffset =
- UInt64(0) - (headerSize +
- 4 + kFinishHeaderSize);
- h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset;
- h.AdditionalStartBlockSize = 0;
- RINOK(WriteFinishHeader(h));
- return WriteFinishSignature();
- }
- else
- #endif
- {
- CStartHeader h;
- h.NextHeaderSize = headerSize;
- h.NextHeaderCRC = headerCRC;
- h.NextHeaderOffset = headerOffset;
- RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL));
- return WriteStartHeader(h);
- }
- }
- }}
|