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: 23 CWriteBufferLoc(): _size(0), _pos(0) {} 24 void Init(Byte *data, size_t size) 25 { 26 _data = data; 27 _size = size; 28 _pos = 0; 29 } 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 } 37 void WriteByte(Byte b) 38 { 39 if (_size == _pos) 40 throw 1; 41 _data[_pos++] = b; 42 } 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 55 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 79 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 97 void OutFoldersClear() 98 { 99 FolderUnpackCRCs.Clear(); 100 NumUnpackStreamsVector.Clear(); 101 CoderUnpackSizes.Clear(); 102 } 103 104 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 141 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 163 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 184 bool IsEmpty() const 185 { 186 return ( 187 PackSizes.IsEmpty() && 188 NumUnpackStreamsVector.IsEmpty() && 189 Folders.IsEmpty() && 190 Files.IsEmpty()); 191 } 192 193 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 204 bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); } 205 // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); } 206 207 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 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); 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); 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 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