1 // 7zOut.h
2 
3 #ifndef ZIP7_INC_7Z_OUT_H
4 #define ZIP7_INC_7Z_OUT_H
5 
6 #include "7zCompressionMode.h"
7 #include "7zEncode.h"
8 #include "7zHeader.h"
9 #include "7zItem.h"
10 
11 #include "../../Common/OutBuffer.h"
12 #include "../../Common/StreamUtils.h"
13 
14 namespace NArchive {
15 namespace N7z {
16 
17 const unsigned k_StartHeadersRewriteSize = 32;
18 
19 class CWriteBufferLoc
20 {
21   Byte *_data;
22   size_t _size;
23   size_t _pos;
24 public:
CWriteBufferLoc()25   CWriteBufferLoc(): _size(0), _pos(0) {}
Init(Byte *data, size_t size)26   void Init(Byte *data, size_t size)
27   {
28     _data = data;
29     _size = size;
30     _pos = 0;
31   }
WriteBytes(const void *data, size_t size)32   void WriteBytes(const void *data, size_t size)
33   {
34     if (size == 0)
35       return;
36     if (size > _size - _pos)
37       throw 1;
38     memcpy(_data + _pos, data, size);
39     _pos += size;
40   }
WriteByte(Byte b)41   void WriteByte(Byte b)
42   {
43     if (_size == _pos)
44       throw 1;
45     _data[_pos++] = b;
46   }
GetPos() const47   size_t GetPos() const { return _pos; }
48 };
49 
50 
51 struct CHeaderOptions
52 {
53   bool CompressMainHeader;
54   /*
55   bool WriteCTime;
56   bool WriteATime;
57   bool WriteMTime;
58   */
59 
CHeaderOptionsNArchive::N7z::CHeaderOptions60   CHeaderOptions():
61       CompressMainHeader(true)
62       /*
63       , WriteCTime(false)
64       , WriteATime(false)
65       , WriteMTime(true)
66       */
67       {}
68 };
69 
70 
71 struct CFileItem2
72 {
73   UInt64 CTime;
74   UInt64 ATime;
75   UInt64 MTime;
76   UInt64 StartPos;
77   UInt32 Attrib;
78 
79   bool CTimeDefined;
80   bool ATimeDefined;
81   bool MTimeDefined;
82   bool StartPosDefined;
83   bool AttribDefined;
84   bool IsAnti;
85   // bool IsAux;
86 
87   /*
88   void Init()
89   {
90     CTimeDefined = false;
91     ATimeDefined = false;
92     MTimeDefined = false;
93     StartPosDefined = false;
94     AttribDefined = false;
95     IsAnti = false;
96     // IsAux = false;
97   }
98   */
99 };
100 
101 
102 struct COutFolders
103 {
104   CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only.
105 
106   CRecordVector<CNum> NumUnpackStreamsVector;
107   CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders
108 
OutFoldersClearNArchive::N7z::COutFolders109   void OutFoldersClear()
110   {
111     FolderUnpackCRCs.Clear();
112     NumUnpackStreamsVector.Clear();
113     CoderUnpackSizes.Clear();
114   }
115 
OutFoldersReserveDownNArchive::N7z::COutFolders116   void OutFoldersReserveDown()
117   {
118     FolderUnpackCRCs.ReserveDown();
119     NumUnpackStreamsVector.ReserveDown();
120     CoderUnpackSizes.ReserveDown();
121   }
122 };
123 
124 
125 struct CArchiveDatabaseOut: public COutFolders
126 {
127   CRecordVector<UInt64> PackSizes;
128   CUInt32DefVector PackCRCs;
129   CObjectVector<CFolder> Folders;
130 
131   CRecordVector<CFileItem> Files;
132   UStringVector Names;
133   CUInt64DefVector CTime;
134   CUInt64DefVector ATime;
135   CUInt64DefVector MTime;
136   CUInt64DefVector StartPos;
137   CUInt32DefVector Attrib;
138   CBoolVector IsAnti;
139 
140   /*
141   CBoolVector IsAux;
142 
143   CByteBuffer SecureBuf;
144   CRecordVector<UInt32> SecureSizes;
145   CRecordVector<UInt32> SecureIDs;
146 
147   void ClearSecure()
148   {
149     SecureBuf.Free();
150     SecureSizes.Clear();
151     SecureIDs.Clear();
152   }
153   */
154 
ClearNArchive::N7z::CArchiveDatabaseOut155   void Clear()
156   {
157     OutFoldersClear();
158 
159     PackSizes.Clear();
160     PackCRCs.Clear();
161     Folders.Clear();
162 
163     Files.Clear();
164     Names.Clear();
165     CTime.Clear();
166     ATime.Clear();
167     MTime.Clear();
168     StartPos.Clear();
169     Attrib.Clear();
170     IsAnti.Clear();
171 
172     /*
173     IsAux.Clear();
174     ClearSecure();
175     */
176   }
177 
ReserveDownNArchive::N7z::CArchiveDatabaseOut178   void ReserveDown()
179   {
180     OutFoldersReserveDown();
181 
182     PackSizes.ReserveDown();
183     PackCRCs.ReserveDown();
184     Folders.ReserveDown();
185 
186     Files.ReserveDown();
187     Names.ReserveDown();
188     CTime.ReserveDown();
189     ATime.ReserveDown();
190     MTime.ReserveDown();
191     StartPos.ReserveDown();
192     Attrib.ReserveDown();
193     IsAnti.ReserveDown();
194 
195     /*
196     IsAux.ReserveDown();
197     */
198   }
199 
IsEmptyNArchive::N7z::CArchiveDatabaseOut200   bool IsEmpty() const
201   {
202     return (
203       PackSizes.IsEmpty() &&
204       NumUnpackStreamsVector.IsEmpty() &&
205       Folders.IsEmpty() &&
206       Files.IsEmpty());
207   }
208 
CheckNumFilesNArchive::N7z::CArchiveDatabaseOut209   bool CheckNumFiles() const
210   {
211     unsigned size = Files.Size();
212     return (
213            CTime.CheckSize(size)
214         && ATime.CheckSize(size)
215         && MTime.CheckSize(size)
216         && StartPos.CheckSize(size)
217         && Attrib.CheckSize(size)
218         && (size == IsAnti.Size() || IsAnti.Size() == 0));
219   }
220 
IsItemAntiNArchive::N7z::CArchiveDatabaseOut221   bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); }
222   // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); }
223 
SetItem_AntiNArchive::N7z::CArchiveDatabaseOut224   void SetItem_Anti(unsigned index, bool isAnti)
225   {
226     while (index >= IsAnti.Size())
227       IsAnti.Add(false);
228     IsAnti[index] = isAnti;
229   }
230   /*
231   void SetItem_Aux(unsigned index, bool isAux)
232   {
233     while (index >= IsAux.Size())
234       IsAux.Add(false);
235     IsAux[index] = isAux;
236   }
237   */
238 
239   void AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name);
240 };
241 
242 
243 class COutArchive
244 {
WriteDirect(const void *data, UInt32 size)245   HRESULT WriteDirect(const void *data, UInt32 size) { return WriteStream(SeqStream, data, size); }
246 
247   UInt64 GetPos() const;
248   void WriteBytes(const void *data, size_t size);
WriteBytes(const CByteBuffer &data)249   void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.Size()); }
250   void WriteByte(Byte b);
251   void WriteUInt32(UInt32 value);
252   void WriteUInt64(UInt64 value);
253   void WriteNumber(UInt64 value);
WriteID(UInt64 value)254   void WriteID(UInt64 value) { WriteNumber(value); }
255 
256   void WriteFolder(const CFolder &folder);
257   HRESULT WriteFileHeader(const CFileItem &itemInfo);
258   void WriteBoolVector(const CBoolVector &boolVector);
259   void WritePropBoolVector(Byte id, const CBoolVector &boolVector);
260 
261   void WriteHashDigests(const CUInt32DefVector &digests);
262 
263   void WritePackInfo(
264       UInt64 dataOffset,
265       const CRecordVector<UInt64> &packSizes,
266       const CUInt32DefVector &packCRCs);
267 
268   void WriteUnpackInfo(
269       const CObjectVector<CFolder> &folders,
270       const COutFolders &outFolders);
271 
272   void WriteSubStreamsInfo(
273       const CObjectVector<CFolder> &folders,
274       const COutFolders &outFolders,
275       const CRecordVector<UInt64> &unpackSizes,
276       const CUInt32DefVector &digests);
277 
278   void SkipToAligned(unsigned pos, unsigned alignShifts);
279   void WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts);
280   void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type);
281 
282   HRESULT EncodeStream(
283       DECL_EXTERNAL_CODECS_LOC_VARS
284       CEncoder &encoder, const CByteBuffer &data,
285       CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders);
286   void WriteHeader(
287       const CArchiveDatabaseOut &db,
288       // const CHeaderOptions &headerOptions,
289       UInt64 &headerOffset);
290 
291   bool _countMode;
292   bool _writeToStream;
293   bool _useAlign;
294   #ifdef Z7_7Z_VOL
295   bool _endMarker;
296   #endif
297   UInt32 _crc;
298   size_t _countSize;
299   CWriteBufferLoc _outByte2;
300   COutBuffer _outByte;
301   UInt64 _signatureHeaderPos;
302   CMyComPtr<IOutStream> Stream;
303 
304   #ifdef Z7_7Z_VOL
305   HRESULT WriteFinishSignature();
306   HRESULT WriteFinishHeader(const CFinishHeader &h);
307   #endif
308   HRESULT WriteStartHeader(const CStartHeader &h);
309 
310 public:
311   CMyComPtr<ISequentialOutStream> SeqStream;
312 
COutArchive()313   COutArchive() { _outByte.Create(1 << 16); }
314   HRESULT Create_and_WriteStartPrefix(ISequentialOutStream *stream /* , bool endMarker */);
315   void Close();
316   HRESULT WriteDatabase(
317       DECL_EXTERNAL_CODECS_LOC_VARS
318       const CArchiveDatabaseOut &db,
319       const CCompressionMethodMode *options,
320       const CHeaderOptions &headerOptions);
321 
322   #ifdef Z7_7Z_VOL
323   static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false);
324   static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false);
325   #endif
326 };
327 
328 }}
329 
330 #endif
331