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