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 == 0) 33 return; 34 if (size > _size - _pos) 35 throw 1; 36 memcpy(_data + _pos, data, size); 37 _pos += size; 38 } WriteByte(Byte b)39 void WriteByte(Byte b) 40 { 41 if (_size == _pos) 42 throw 1; 43 _data[_pos++] = b; 44 } GetPos()45 size_t GetPos() const { return _pos; } 46 }; 47 48 49 struct CHeaderOptions 50 { 51 bool CompressMainHeader; 52 /* 53 bool WriteCTime; 54 bool WriteATime; 55 bool WriteMTime; 56 */ 57 CHeaderOptionsCHeaderOptions58 CHeaderOptions(): 59 CompressMainHeader(true) 60 /* 61 , WriteCTime(false) 62 , WriteATime(false) 63 , WriteMTime(true) 64 */ 65 {} 66 }; 67 68 69 struct CFileItem2 70 { 71 UInt64 CTime; 72 UInt64 ATime; 73 UInt64 MTime; 74 UInt64 StartPos; 75 UInt32 Attrib; 76 77 bool CTimeDefined; 78 bool ATimeDefined; 79 bool MTimeDefined; 80 bool StartPosDefined; 81 bool AttribDefined; 82 bool IsAnti; 83 // bool IsAux; 84 85 /* 86 void Init() 87 { 88 CTimeDefined = false; 89 ATimeDefined = false; 90 MTimeDefined = false; 91 StartPosDefined = false; 92 AttribDefined = false; 93 IsAnti = false; 94 // IsAux = false; 95 } 96 */ 97 }; 98 99 100 struct COutFolders 101 { 102 CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only. 103 104 CRecordVector<CNum> NumUnpackStreamsVector; 105 CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders 106 OutFoldersClearCOutFolders107 void OutFoldersClear() 108 { 109 FolderUnpackCRCs.Clear(); 110 NumUnpackStreamsVector.Clear(); 111 CoderUnpackSizes.Clear(); 112 } 113 OutFoldersReserveDownCOutFolders114 void OutFoldersReserveDown() 115 { 116 FolderUnpackCRCs.ReserveDown(); 117 NumUnpackStreamsVector.ReserveDown(); 118 CoderUnpackSizes.ReserveDown(); 119 } 120 }; 121 122 123 struct CArchiveDatabaseOut: public COutFolders 124 { 125 CRecordVector<UInt64> PackSizes; 126 CUInt32DefVector PackCRCs; 127 CObjectVector<CFolder> Folders; 128 129 CRecordVector<CFileItem> Files; 130 UStringVector Names; 131 CUInt64DefVector CTime; 132 CUInt64DefVector ATime; 133 CUInt64DefVector MTime; 134 CUInt64DefVector StartPos; 135 CUInt32DefVector Attrib; 136 CBoolVector IsAnti; 137 138 /* 139 CBoolVector IsAux; 140 141 CByteBuffer SecureBuf; 142 CRecordVector<UInt32> SecureSizes; 143 CRecordVector<UInt32> SecureIDs; 144 145 void ClearSecure() 146 { 147 SecureBuf.Free(); 148 SecureSizes.Clear(); 149 SecureIDs.Clear(); 150 } 151 */ 152 ClearCArchiveDatabaseOut153 void Clear() 154 { 155 OutFoldersClear(); 156 157 PackSizes.Clear(); 158 PackCRCs.Clear(); 159 Folders.Clear(); 160 161 Files.Clear(); 162 Names.Clear(); 163 CTime.Clear(); 164 ATime.Clear(); 165 MTime.Clear(); 166 StartPos.Clear(); 167 Attrib.Clear(); 168 IsAnti.Clear(); 169 170 /* 171 IsAux.Clear(); 172 ClearSecure(); 173 */ 174 } 175 ReserveDownCArchiveDatabaseOut176 void ReserveDown() 177 { 178 OutFoldersReserveDown(); 179 180 PackSizes.ReserveDown(); 181 PackCRCs.ReserveDown(); 182 Folders.ReserveDown(); 183 184 Files.ReserveDown(); 185 Names.ReserveDown(); 186 CTime.ReserveDown(); 187 ATime.ReserveDown(); 188 MTime.ReserveDown(); 189 StartPos.ReserveDown(); 190 Attrib.ReserveDown(); 191 IsAnti.ReserveDown(); 192 193 /* 194 IsAux.ReserveDown(); 195 */ 196 } 197 IsEmptyCArchiveDatabaseOut198 bool IsEmpty() const 199 { 200 return ( 201 PackSizes.IsEmpty() && 202 NumUnpackStreamsVector.IsEmpty() && 203 Folders.IsEmpty() && 204 Files.IsEmpty()); 205 } 206 CheckNumFilesCArchiveDatabaseOut207 bool CheckNumFiles() const 208 { 209 unsigned size = Files.Size(); 210 return ( 211 CTime.CheckSize(size) 212 && ATime.CheckSize(size) 213 && MTime.CheckSize(size) 214 && StartPos.CheckSize(size) 215 && Attrib.CheckSize(size) 216 && (size == IsAnti.Size() || IsAnti.Size() == 0)); 217 } 218 IsItemAntiCArchiveDatabaseOut219 bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); } 220 // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); } 221 SetItem_AntiCArchiveDatabaseOut222 void SetItem_Anti(unsigned index, bool isAnti) 223 { 224 while (index >= IsAnti.Size()) 225 IsAnti.Add(false); 226 IsAnti[index] = isAnti; 227 } 228 /* 229 void SetItem_Aux(unsigned index, bool isAux) 230 { 231 while (index >= IsAux.Size()) 232 IsAux.Add(false); 233 IsAux[index] = isAux; 234 } 235 */ 236 237 void AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name); 238 }; 239 240 241 class COutArchive 242 { 243 UInt64 _prefixHeaderPos; 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 size_t _countSize; 294 UInt32 _crc; 295 COutBuffer _outByte; 296 CWriteBufferLoc _outByte2; 297 298 #ifdef _7Z_VOL 299 bool _endMarker; 300 #endif 301 302 bool _useAlign; 303 304 HRESULT WriteSignature(); 305 #ifdef _7Z_VOL 306 HRESULT WriteFinishSignature(); 307 #endif 308 HRESULT WriteStartHeader(const CStartHeader &h); 309 #ifdef _7Z_VOL 310 HRESULT WriteFinishHeader(const CFinishHeader &h); 311 #endif 312 CMyComPtr<IOutStream> Stream; 313 public: 314 COutArchive()315 COutArchive() { _outByte.Create(1 << 16); } 316 CMyComPtr<ISequentialOutStream> SeqStream; 317 HRESULT Create(ISequentialOutStream *stream, bool endMarker); 318 void Close(); 319 HRESULT SkipPrefixArchiveHeader(); 320 HRESULT WriteDatabase( 321 DECL_EXTERNAL_CODECS_LOC_VARS 322 const CArchiveDatabaseOut &db, 323 const CCompressionMethodMode *options, 324 const CHeaderOptions &headerOptions); 325 326 #ifdef _7Z_VOL 327 static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false); 328 static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false); 329 #endif 330 331 }; 332 333 }} 334 335 #endif 336