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