1*f6dc9357SAndroid Build Coastguard Worker // ZipOut.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/7zCrc.h"
6*f6dc9357SAndroid Build Coastguard Worker
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/TimeUtils.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/OffsetStream.h"
9*f6dc9357SAndroid Build Coastguard Worker
10*f6dc9357SAndroid Build Coastguard Worker #include "ZipOut.h"
11*f6dc9357SAndroid Build Coastguard Worker
12*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
13*f6dc9357SAndroid Build Coastguard Worker namespace NZip {
14*f6dc9357SAndroid Build Coastguard Worker
ClearRestriction()15*f6dc9357SAndroid Build Coastguard Worker HRESULT COutArchive::ClearRestriction()
16*f6dc9357SAndroid Build Coastguard Worker {
17*f6dc9357SAndroid Build Coastguard Worker if (SetRestriction)
18*f6dc9357SAndroid Build Coastguard Worker return SetRestriction->SetRestriction(0, 0);
19*f6dc9357SAndroid Build Coastguard Worker return S_OK;
20*f6dc9357SAndroid Build Coastguard Worker }
21*f6dc9357SAndroid Build Coastguard Worker
SetRestrictionFromCurrent()22*f6dc9357SAndroid Build Coastguard Worker HRESULT COutArchive::SetRestrictionFromCurrent()
23*f6dc9357SAndroid Build Coastguard Worker {
24*f6dc9357SAndroid Build Coastguard Worker if (SetRestriction)
25*f6dc9357SAndroid Build Coastguard Worker return SetRestriction->SetRestriction(m_Base + m_CurPos, (UInt64)(Int64)-1);
26*f6dc9357SAndroid Build Coastguard Worker return S_OK;
27*f6dc9357SAndroid Build Coastguard Worker }
28*f6dc9357SAndroid Build Coastguard Worker
Create(IOutStream * outStream)29*f6dc9357SAndroid Build Coastguard Worker HRESULT COutArchive::Create(IOutStream *outStream)
30*f6dc9357SAndroid Build Coastguard Worker {
31*f6dc9357SAndroid Build Coastguard Worker m_CurPos = 0;
32*f6dc9357SAndroid Build Coastguard Worker if (!m_OutBuffer.Create(1 << 16))
33*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
34*f6dc9357SAndroid Build Coastguard Worker m_Stream = outStream;
35*f6dc9357SAndroid Build Coastguard Worker m_OutBuffer.SetStream(outStream);
36*f6dc9357SAndroid Build Coastguard Worker m_OutBuffer.Init();
37*f6dc9357SAndroid Build Coastguard Worker
38*f6dc9357SAndroid Build Coastguard Worker return m_Stream->Seek(0, STREAM_SEEK_CUR, &m_Base);
39*f6dc9357SAndroid Build Coastguard Worker }
40*f6dc9357SAndroid Build Coastguard Worker
SeekToCurPos()41*f6dc9357SAndroid Build Coastguard Worker void COutArchive::SeekToCurPos()
42*f6dc9357SAndroid Build Coastguard Worker {
43*f6dc9357SAndroid Build Coastguard Worker HRESULT res = m_Stream->Seek((Int64)(m_Base + m_CurPos), STREAM_SEEK_SET, NULL);
44*f6dc9357SAndroid Build Coastguard Worker if (res != S_OK)
45*f6dc9357SAndroid Build Coastguard Worker throw CSystemException(res);
46*f6dc9357SAndroid Build Coastguard Worker }
47*f6dc9357SAndroid Build Coastguard Worker
48*f6dc9357SAndroid Build Coastguard Worker #define DOES_NEED_ZIP64(v) (v >= (UInt32)0xFFFFFFFF)
49*f6dc9357SAndroid Build Coastguard Worker // #define DOES_NEED_ZIP64(v) (v >= 0)
50*f6dc9357SAndroid Build Coastguard Worker
51*f6dc9357SAndroid Build Coastguard Worker
WriteBytes(const void * data,size_t size)52*f6dc9357SAndroid Build Coastguard Worker void COutArchive::WriteBytes(const void *data, size_t size)
53*f6dc9357SAndroid Build Coastguard Worker {
54*f6dc9357SAndroid Build Coastguard Worker m_OutBuffer.WriteBytes(data, size);
55*f6dc9357SAndroid Build Coastguard Worker m_CurPos += size;
56*f6dc9357SAndroid Build Coastguard Worker }
57*f6dc9357SAndroid Build Coastguard Worker
Write8(Byte b)58*f6dc9357SAndroid Build Coastguard Worker void COutArchive::Write8(Byte b)
59*f6dc9357SAndroid Build Coastguard Worker {
60*f6dc9357SAndroid Build Coastguard Worker m_OutBuffer.WriteByte(b);
61*f6dc9357SAndroid Build Coastguard Worker m_CurPos++;
62*f6dc9357SAndroid Build Coastguard Worker }
63*f6dc9357SAndroid Build Coastguard Worker
Write16(UInt16 val)64*f6dc9357SAndroid Build Coastguard Worker void COutArchive::Write16(UInt16 val)
65*f6dc9357SAndroid Build Coastguard Worker {
66*f6dc9357SAndroid Build Coastguard Worker Write8((Byte)val);
67*f6dc9357SAndroid Build Coastguard Worker Write8((Byte)(val >> 8));
68*f6dc9357SAndroid Build Coastguard Worker }
69*f6dc9357SAndroid Build Coastguard Worker
Write32(UInt32 val)70*f6dc9357SAndroid Build Coastguard Worker void COutArchive::Write32(UInt32 val)
71*f6dc9357SAndroid Build Coastguard Worker {
72*f6dc9357SAndroid Build Coastguard Worker for (int i = 0; i < 4; i++)
73*f6dc9357SAndroid Build Coastguard Worker {
74*f6dc9357SAndroid Build Coastguard Worker Write8((Byte)val);
75*f6dc9357SAndroid Build Coastguard Worker val >>= 8;
76*f6dc9357SAndroid Build Coastguard Worker }
77*f6dc9357SAndroid Build Coastguard Worker }
78*f6dc9357SAndroid Build Coastguard Worker
Write64(UInt64 val)79*f6dc9357SAndroid Build Coastguard Worker void COutArchive::Write64(UInt64 val)
80*f6dc9357SAndroid Build Coastguard Worker {
81*f6dc9357SAndroid Build Coastguard Worker for (int i = 0; i < 8; i++)
82*f6dc9357SAndroid Build Coastguard Worker {
83*f6dc9357SAndroid Build Coastguard Worker Write8((Byte)val);
84*f6dc9357SAndroid Build Coastguard Worker val >>= 8;
85*f6dc9357SAndroid Build Coastguard Worker }
86*f6dc9357SAndroid Build Coastguard Worker }
87*f6dc9357SAndroid Build Coastguard Worker
WriteExtra(const CExtraBlock & extra)88*f6dc9357SAndroid Build Coastguard Worker void COutArchive::WriteExtra(const CExtraBlock &extra)
89*f6dc9357SAndroid Build Coastguard Worker {
90*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, extra.SubBlocks)
91*f6dc9357SAndroid Build Coastguard Worker {
92*f6dc9357SAndroid Build Coastguard Worker const CExtraSubBlock &subBlock = extra.SubBlocks[i];
93*f6dc9357SAndroid Build Coastguard Worker Write16((UInt16)subBlock.ID);
94*f6dc9357SAndroid Build Coastguard Worker Write16((UInt16)subBlock.Data.Size());
95*f6dc9357SAndroid Build Coastguard Worker WriteBytes(subBlock.Data, (UInt16)subBlock.Data.Size());
96*f6dc9357SAndroid Build Coastguard Worker }
97*f6dc9357SAndroid Build Coastguard Worker }
98*f6dc9357SAndroid Build Coastguard Worker
WriteCommonItemInfo(const CLocalItem & item,bool isZip64)99*f6dc9357SAndroid Build Coastguard Worker void COutArchive::WriteCommonItemInfo(const CLocalItem &item, bool isZip64)
100*f6dc9357SAndroid Build Coastguard Worker {
101*f6dc9357SAndroid Build Coastguard Worker {
102*f6dc9357SAndroid Build Coastguard Worker Byte ver = item.ExtractVersion.Version;
103*f6dc9357SAndroid Build Coastguard Worker if (isZip64 && ver < NFileHeader::NCompressionMethod::kExtractVersion_Zip64)
104*f6dc9357SAndroid Build Coastguard Worker ver = NFileHeader::NCompressionMethod::kExtractVersion_Zip64;
105*f6dc9357SAndroid Build Coastguard Worker Write8(ver);
106*f6dc9357SAndroid Build Coastguard Worker }
107*f6dc9357SAndroid Build Coastguard Worker Write8(item.ExtractVersion.HostOS);
108*f6dc9357SAndroid Build Coastguard Worker Write16(item.Flags);
109*f6dc9357SAndroid Build Coastguard Worker Write16(item.Method);
110*f6dc9357SAndroid Build Coastguard Worker Write32(item.Time);
111*f6dc9357SAndroid Build Coastguard Worker }
112*f6dc9357SAndroid Build Coastguard Worker
113*f6dc9357SAndroid Build Coastguard Worker
114*f6dc9357SAndroid Build Coastguard Worker #define WRITE_32_VAL_SPEC(_v_, _isZip64_) Write32((_isZip64_) ? 0xFFFFFFFF : (UInt32)(_v_));
115*f6dc9357SAndroid Build Coastguard Worker
116*f6dc9357SAndroid Build Coastguard Worker
WriteUtfName(const CItemOut & item)117*f6dc9357SAndroid Build Coastguard Worker void COutArchive::WriteUtfName(const CItemOut &item)
118*f6dc9357SAndroid Build Coastguard Worker {
119*f6dc9357SAndroid Build Coastguard Worker if (item.Name_Utf.Size() == 0)
120*f6dc9357SAndroid Build Coastguard Worker return;
121*f6dc9357SAndroid Build Coastguard Worker Write16(NFileHeader::NExtraID::kIzUnicodeName);
122*f6dc9357SAndroid Build Coastguard Worker Write16((UInt16)(5 + item.Name_Utf.Size()));
123*f6dc9357SAndroid Build Coastguard Worker Write8(1); // (1 = version) of that extra field
124*f6dc9357SAndroid Build Coastguard Worker Write32(CrcCalc(item.Name.Ptr(), item.Name.Len()));
125*f6dc9357SAndroid Build Coastguard Worker WriteBytes(item.Name_Utf, (UInt16)item.Name_Utf.Size());
126*f6dc9357SAndroid Build Coastguard Worker }
127*f6dc9357SAndroid Build Coastguard Worker
128*f6dc9357SAndroid Build Coastguard Worker
129*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_Ntfs_ExtraSize = 4 + 2 + 2 + (3 * 8);
130*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_UnixTime_ExtraSize = 1 + (1 * 4);
131*f6dc9357SAndroid Build Coastguard Worker
WriteTimeExtra(const CItemOut & item,bool writeNtfs)132*f6dc9357SAndroid Build Coastguard Worker void COutArchive::WriteTimeExtra(const CItemOut &item, bool writeNtfs)
133*f6dc9357SAndroid Build Coastguard Worker {
134*f6dc9357SAndroid Build Coastguard Worker if (writeNtfs)
135*f6dc9357SAndroid Build Coastguard Worker {
136*f6dc9357SAndroid Build Coastguard Worker // windows explorer ignores that extra
137*f6dc9357SAndroid Build Coastguard Worker Write16(NFileHeader::NExtraID::kNTFS);
138*f6dc9357SAndroid Build Coastguard Worker Write16(k_Ntfs_ExtraSize);
139*f6dc9357SAndroid Build Coastguard Worker Write32(0); // reserved
140*f6dc9357SAndroid Build Coastguard Worker Write16(NFileHeader::NNtfsExtra::kTagTime);
141*f6dc9357SAndroid Build Coastguard Worker Write16(8 * 3);
142*f6dc9357SAndroid Build Coastguard Worker WriteNtfsTime(item.Ntfs_MTime);
143*f6dc9357SAndroid Build Coastguard Worker WriteNtfsTime(item.Ntfs_ATime);
144*f6dc9357SAndroid Build Coastguard Worker WriteNtfsTime(item.Ntfs_CTime);
145*f6dc9357SAndroid Build Coastguard Worker }
146*f6dc9357SAndroid Build Coastguard Worker
147*f6dc9357SAndroid Build Coastguard Worker if (item.Write_UnixTime)
148*f6dc9357SAndroid Build Coastguard Worker {
149*f6dc9357SAndroid Build Coastguard Worker // windows explorer ignores that extra
150*f6dc9357SAndroid Build Coastguard Worker // by specification : should we write to local header also?
151*f6dc9357SAndroid Build Coastguard Worker Write16(NFileHeader::NExtraID::kUnixTime);
152*f6dc9357SAndroid Build Coastguard Worker Write16(k_UnixTime_ExtraSize);
153*f6dc9357SAndroid Build Coastguard Worker const Byte flags = (Byte)((unsigned)1 << NFileHeader::NUnixTime::kMTime);
154*f6dc9357SAndroid Build Coastguard Worker Write8(flags);
155*f6dc9357SAndroid Build Coastguard Worker UInt32 unixTime;
156*f6dc9357SAndroid Build Coastguard Worker NWindows::NTime::FileTime_To_UnixTime(item.Ntfs_MTime, unixTime);
157*f6dc9357SAndroid Build Coastguard Worker Write32(unixTime);
158*f6dc9357SAndroid Build Coastguard Worker }
159*f6dc9357SAndroid Build Coastguard Worker }
160*f6dc9357SAndroid Build Coastguard Worker
161*f6dc9357SAndroid Build Coastguard Worker
WriteLocalHeader(CItemOut & item,bool needCheck)162*f6dc9357SAndroid Build Coastguard Worker void COutArchive::WriteLocalHeader(CItemOut &item, bool needCheck)
163*f6dc9357SAndroid Build Coastguard Worker {
164*f6dc9357SAndroid Build Coastguard Worker m_LocalHeaderPos = m_CurPos;
165*f6dc9357SAndroid Build Coastguard Worker item.LocalHeaderPos = m_CurPos;
166*f6dc9357SAndroid Build Coastguard Worker
167*f6dc9357SAndroid Build Coastguard Worker bool isZip64 =
168*f6dc9357SAndroid Build Coastguard Worker DOES_NEED_ZIP64(item.PackSize) ||
169*f6dc9357SAndroid Build Coastguard Worker DOES_NEED_ZIP64(item.Size);
170*f6dc9357SAndroid Build Coastguard Worker
171*f6dc9357SAndroid Build Coastguard Worker if (needCheck && m_IsZip64)
172*f6dc9357SAndroid Build Coastguard Worker isZip64 = true;
173*f6dc9357SAndroid Build Coastguard Worker
174*f6dc9357SAndroid Build Coastguard Worker // Why don't we write NTFS timestamps to local header?
175*f6dc9357SAndroid Build Coastguard Worker // Probably we want to reduce size of archive?
176*f6dc9357SAndroid Build Coastguard Worker const bool writeNtfs = false; // do not write NTFS timestamp to local header
177*f6dc9357SAndroid Build Coastguard Worker // const bool writeNtfs = item.Write_NtfsTime; // write NTFS time to local header
178*f6dc9357SAndroid Build Coastguard Worker const UInt32 localExtraSize = (UInt32)(
179*f6dc9357SAndroid Build Coastguard Worker (isZip64 ? (4 + 8 + 8): 0)
180*f6dc9357SAndroid Build Coastguard Worker + (writeNtfs ? 4 + k_Ntfs_ExtraSize : 0)
181*f6dc9357SAndroid Build Coastguard Worker + (item.Write_UnixTime ? 4 + k_UnixTime_ExtraSize : 0)
182*f6dc9357SAndroid Build Coastguard Worker + item.Get_UtfName_ExtraSize()
183*f6dc9357SAndroid Build Coastguard Worker + item.LocalExtra.GetSize());
184*f6dc9357SAndroid Build Coastguard Worker if ((UInt16)localExtraSize != localExtraSize)
185*f6dc9357SAndroid Build Coastguard Worker throw CSystemException(E_FAIL);
186*f6dc9357SAndroid Build Coastguard Worker if (needCheck && m_ExtraSize != localExtraSize)
187*f6dc9357SAndroid Build Coastguard Worker throw CSystemException(E_FAIL);
188*f6dc9357SAndroid Build Coastguard Worker
189*f6dc9357SAndroid Build Coastguard Worker m_IsZip64 = isZip64;
190*f6dc9357SAndroid Build Coastguard Worker m_ExtraSize = localExtraSize;
191*f6dc9357SAndroid Build Coastguard Worker
192*f6dc9357SAndroid Build Coastguard Worker item.LocalExtra.IsZip64 = isZip64;
193*f6dc9357SAndroid Build Coastguard Worker
194*f6dc9357SAndroid Build Coastguard Worker Write32(NSignature::kLocalFileHeader);
195*f6dc9357SAndroid Build Coastguard Worker
196*f6dc9357SAndroid Build Coastguard Worker WriteCommonItemInfo(item, isZip64);
197*f6dc9357SAndroid Build Coastguard Worker
198*f6dc9357SAndroid Build Coastguard Worker Write32(item.HasDescriptor() ? 0 : item.Crc);
199*f6dc9357SAndroid Build Coastguard Worker
200*f6dc9357SAndroid Build Coastguard Worker UInt64 packSize = item.PackSize;
201*f6dc9357SAndroid Build Coastguard Worker UInt64 size = item.Size;
202*f6dc9357SAndroid Build Coastguard Worker
203*f6dc9357SAndroid Build Coastguard Worker if (item.HasDescriptor())
204*f6dc9357SAndroid Build Coastguard Worker {
205*f6dc9357SAndroid Build Coastguard Worker packSize = 0;
206*f6dc9357SAndroid Build Coastguard Worker size = 0;
207*f6dc9357SAndroid Build Coastguard Worker }
208*f6dc9357SAndroid Build Coastguard Worker
209*f6dc9357SAndroid Build Coastguard Worker WRITE_32_VAL_SPEC(packSize, isZip64)
210*f6dc9357SAndroid Build Coastguard Worker WRITE_32_VAL_SPEC(size, isZip64)
211*f6dc9357SAndroid Build Coastguard Worker
212*f6dc9357SAndroid Build Coastguard Worker Write16((UInt16)item.Name.Len());
213*f6dc9357SAndroid Build Coastguard Worker
214*f6dc9357SAndroid Build Coastguard Worker Write16((UInt16)localExtraSize);
215*f6dc9357SAndroid Build Coastguard Worker
216*f6dc9357SAndroid Build Coastguard Worker WriteBytes((const char *)item.Name, (UInt16)item.Name.Len());
217*f6dc9357SAndroid Build Coastguard Worker
218*f6dc9357SAndroid Build Coastguard Worker if (isZip64)
219*f6dc9357SAndroid Build Coastguard Worker {
220*f6dc9357SAndroid Build Coastguard Worker Write16(NFileHeader::NExtraID::kZip64);
221*f6dc9357SAndroid Build Coastguard Worker Write16(8 + 8);
222*f6dc9357SAndroid Build Coastguard Worker Write64(size);
223*f6dc9357SAndroid Build Coastguard Worker Write64(packSize);
224*f6dc9357SAndroid Build Coastguard Worker }
225*f6dc9357SAndroid Build Coastguard Worker
226*f6dc9357SAndroid Build Coastguard Worker WriteTimeExtra(item, writeNtfs);
227*f6dc9357SAndroid Build Coastguard Worker
228*f6dc9357SAndroid Build Coastguard Worker WriteUtfName(item);
229*f6dc9357SAndroid Build Coastguard Worker
230*f6dc9357SAndroid Build Coastguard Worker WriteExtra(item.LocalExtra);
231*f6dc9357SAndroid Build Coastguard Worker
232*f6dc9357SAndroid Build Coastguard Worker const UInt32 localFileHeaderSize = (UInt32)(m_CurPos - m_LocalHeaderPos);
233*f6dc9357SAndroid Build Coastguard Worker if (needCheck && m_LocalFileHeaderSize != localFileHeaderSize)
234*f6dc9357SAndroid Build Coastguard Worker throw CSystemException(E_FAIL);
235*f6dc9357SAndroid Build Coastguard Worker m_LocalFileHeaderSize = localFileHeaderSize;
236*f6dc9357SAndroid Build Coastguard Worker
237*f6dc9357SAndroid Build Coastguard Worker m_OutBuffer.FlushWithCheck();
238*f6dc9357SAndroid Build Coastguard Worker }
239*f6dc9357SAndroid Build Coastguard Worker
240*f6dc9357SAndroid Build Coastguard Worker
WriteLocalHeader_Replace(CItemOut & item)241*f6dc9357SAndroid Build Coastguard Worker void COutArchive::WriteLocalHeader_Replace(CItemOut &item)
242*f6dc9357SAndroid Build Coastguard Worker {
243*f6dc9357SAndroid Build Coastguard Worker m_CurPos = m_LocalHeaderPos + m_LocalFileHeaderSize + item.PackSize;
244*f6dc9357SAndroid Build Coastguard Worker
245*f6dc9357SAndroid Build Coastguard Worker if (item.HasDescriptor())
246*f6dc9357SAndroid Build Coastguard Worker {
247*f6dc9357SAndroid Build Coastguard Worker WriteDescriptor(item);
248*f6dc9357SAndroid Build Coastguard Worker m_OutBuffer.FlushWithCheck();
249*f6dc9357SAndroid Build Coastguard Worker return;
250*f6dc9357SAndroid Build Coastguard Worker // we don't replace local header, if we write Descriptor.
251*f6dc9357SAndroid Build Coastguard Worker // so local header with Descriptor flag must be written to local header before.
252*f6dc9357SAndroid Build Coastguard Worker }
253*f6dc9357SAndroid Build Coastguard Worker
254*f6dc9357SAndroid Build Coastguard Worker const UInt64 nextPos = m_CurPos;
255*f6dc9357SAndroid Build Coastguard Worker m_CurPos = m_LocalHeaderPos;
256*f6dc9357SAndroid Build Coastguard Worker SeekToCurPos();
257*f6dc9357SAndroid Build Coastguard Worker WriteLocalHeader(item, true);
258*f6dc9357SAndroid Build Coastguard Worker m_CurPos = nextPos;
259*f6dc9357SAndroid Build Coastguard Worker SeekToCurPos();
260*f6dc9357SAndroid Build Coastguard Worker }
261*f6dc9357SAndroid Build Coastguard Worker
262*f6dc9357SAndroid Build Coastguard Worker
WriteDescriptor(const CItemOut & item)263*f6dc9357SAndroid Build Coastguard Worker void COutArchive::WriteDescriptor(const CItemOut &item)
264*f6dc9357SAndroid Build Coastguard Worker {
265*f6dc9357SAndroid Build Coastguard Worker Byte buf[kDataDescriptorSize64];
266*f6dc9357SAndroid Build Coastguard Worker SetUi32(buf, NSignature::kDataDescriptor)
267*f6dc9357SAndroid Build Coastguard Worker SetUi32(buf + 4, item.Crc)
268*f6dc9357SAndroid Build Coastguard Worker unsigned descriptorSize;
269*f6dc9357SAndroid Build Coastguard Worker if (m_IsZip64)
270*f6dc9357SAndroid Build Coastguard Worker {
271*f6dc9357SAndroid Build Coastguard Worker SetUi64(buf + 8, item.PackSize)
272*f6dc9357SAndroid Build Coastguard Worker SetUi64(buf + 16, item.Size)
273*f6dc9357SAndroid Build Coastguard Worker descriptorSize = kDataDescriptorSize64;
274*f6dc9357SAndroid Build Coastguard Worker }
275*f6dc9357SAndroid Build Coastguard Worker else
276*f6dc9357SAndroid Build Coastguard Worker {
277*f6dc9357SAndroid Build Coastguard Worker SetUi32(buf + 8, (UInt32)item.PackSize)
278*f6dc9357SAndroid Build Coastguard Worker SetUi32(buf + 12, (UInt32)item.Size)
279*f6dc9357SAndroid Build Coastguard Worker descriptorSize = kDataDescriptorSize32;
280*f6dc9357SAndroid Build Coastguard Worker }
281*f6dc9357SAndroid Build Coastguard Worker WriteBytes(buf, descriptorSize);
282*f6dc9357SAndroid Build Coastguard Worker }
283*f6dc9357SAndroid Build Coastguard Worker
284*f6dc9357SAndroid Build Coastguard Worker
285*f6dc9357SAndroid Build Coastguard Worker
WriteCentralHeader(const CItemOut & item)286*f6dc9357SAndroid Build Coastguard Worker void COutArchive::WriteCentralHeader(const CItemOut &item)
287*f6dc9357SAndroid Build Coastguard Worker {
288*f6dc9357SAndroid Build Coastguard Worker const bool isUnPack64 = DOES_NEED_ZIP64(item.Size);
289*f6dc9357SAndroid Build Coastguard Worker const bool isPack64 = DOES_NEED_ZIP64(item.PackSize);
290*f6dc9357SAndroid Build Coastguard Worker const bool isPosition64 = DOES_NEED_ZIP64(item.LocalHeaderPos);
291*f6dc9357SAndroid Build Coastguard Worker const bool isZip64 = isPack64 || isUnPack64 || isPosition64;
292*f6dc9357SAndroid Build Coastguard Worker
293*f6dc9357SAndroid Build Coastguard Worker Write32(NSignature::kCentralFileHeader);
294*f6dc9357SAndroid Build Coastguard Worker Write8(item.MadeByVersion.Version);
295*f6dc9357SAndroid Build Coastguard Worker Write8(item.MadeByVersion.HostOS);
296*f6dc9357SAndroid Build Coastguard Worker
297*f6dc9357SAndroid Build Coastguard Worker WriteCommonItemInfo(item, isZip64);
298*f6dc9357SAndroid Build Coastguard Worker Write32(item.Crc);
299*f6dc9357SAndroid Build Coastguard Worker
300*f6dc9357SAndroid Build Coastguard Worker WRITE_32_VAL_SPEC(item.PackSize, isPack64)
301*f6dc9357SAndroid Build Coastguard Worker WRITE_32_VAL_SPEC(item.Size, isUnPack64)
302*f6dc9357SAndroid Build Coastguard Worker
303*f6dc9357SAndroid Build Coastguard Worker Write16((UInt16)item.Name.Len());
304*f6dc9357SAndroid Build Coastguard Worker
305*f6dc9357SAndroid Build Coastguard Worker const UInt16 zip64ExtraSize = (UInt16)((isUnPack64 ? 8: 0) + (isPack64 ? 8: 0) + (isPosition64 ? 8: 0));
306*f6dc9357SAndroid Build Coastguard Worker const bool writeNtfs = item.Write_NtfsTime;
307*f6dc9357SAndroid Build Coastguard Worker const size_t centralExtraSize =
308*f6dc9357SAndroid Build Coastguard Worker (isZip64 ? 4 + zip64ExtraSize : 0)
309*f6dc9357SAndroid Build Coastguard Worker + (writeNtfs ? 4 + k_Ntfs_ExtraSize : 0)
310*f6dc9357SAndroid Build Coastguard Worker + (item.Write_UnixTime ? 4 + k_UnixTime_ExtraSize : 0)
311*f6dc9357SAndroid Build Coastguard Worker + item.Get_UtfName_ExtraSize()
312*f6dc9357SAndroid Build Coastguard Worker + item.CentralExtra.GetSize();
313*f6dc9357SAndroid Build Coastguard Worker
314*f6dc9357SAndroid Build Coastguard Worker const UInt16 centralExtraSize16 = (UInt16)centralExtraSize;
315*f6dc9357SAndroid Build Coastguard Worker if (centralExtraSize16 != centralExtraSize)
316*f6dc9357SAndroid Build Coastguard Worker throw CSystemException(E_FAIL);
317*f6dc9357SAndroid Build Coastguard Worker
318*f6dc9357SAndroid Build Coastguard Worker Write16(centralExtraSize16);
319*f6dc9357SAndroid Build Coastguard Worker
320*f6dc9357SAndroid Build Coastguard Worker const UInt16 commentSize = (UInt16)item.Comment.Size();
321*f6dc9357SAndroid Build Coastguard Worker
322*f6dc9357SAndroid Build Coastguard Worker Write16(commentSize);
323*f6dc9357SAndroid Build Coastguard Worker Write16(0); // DiskNumberStart
324*f6dc9357SAndroid Build Coastguard Worker Write16(item.InternalAttrib);
325*f6dc9357SAndroid Build Coastguard Worker Write32(item.ExternalAttrib);
326*f6dc9357SAndroid Build Coastguard Worker WRITE_32_VAL_SPEC(item.LocalHeaderPos, isPosition64)
327*f6dc9357SAndroid Build Coastguard Worker WriteBytes((const char *)item.Name, item.Name.Len());
328*f6dc9357SAndroid Build Coastguard Worker
329*f6dc9357SAndroid Build Coastguard Worker if (isZip64)
330*f6dc9357SAndroid Build Coastguard Worker {
331*f6dc9357SAndroid Build Coastguard Worker Write16(NFileHeader::NExtraID::kZip64);
332*f6dc9357SAndroid Build Coastguard Worker Write16(zip64ExtraSize);
333*f6dc9357SAndroid Build Coastguard Worker if (isUnPack64)
334*f6dc9357SAndroid Build Coastguard Worker Write64(item.Size);
335*f6dc9357SAndroid Build Coastguard Worker if (isPack64)
336*f6dc9357SAndroid Build Coastguard Worker Write64(item.PackSize);
337*f6dc9357SAndroid Build Coastguard Worker if (isPosition64)
338*f6dc9357SAndroid Build Coastguard Worker Write64(item.LocalHeaderPos);
339*f6dc9357SAndroid Build Coastguard Worker }
340*f6dc9357SAndroid Build Coastguard Worker
341*f6dc9357SAndroid Build Coastguard Worker WriteTimeExtra(item, writeNtfs);
342*f6dc9357SAndroid Build Coastguard Worker WriteUtfName(item);
343*f6dc9357SAndroid Build Coastguard Worker
344*f6dc9357SAndroid Build Coastguard Worker WriteExtra(item.CentralExtra);
345*f6dc9357SAndroid Build Coastguard Worker if (commentSize != 0)
346*f6dc9357SAndroid Build Coastguard Worker WriteBytes(item.Comment, commentSize);
347*f6dc9357SAndroid Build Coastguard Worker }
348*f6dc9357SAndroid Build Coastguard Worker
WriteCentralDir(const CObjectVector<CItemOut> & items,const CByteBuffer * comment)349*f6dc9357SAndroid Build Coastguard Worker HRESULT COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const CByteBuffer *comment)
350*f6dc9357SAndroid Build Coastguard Worker {
351*f6dc9357SAndroid Build Coastguard Worker RINOK(ClearRestriction())
352*f6dc9357SAndroid Build Coastguard Worker
353*f6dc9357SAndroid Build Coastguard Worker const UInt64 cdOffset = GetCurPos();
354*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, items)
355*f6dc9357SAndroid Build Coastguard Worker WriteCentralHeader(items[i]);
356*f6dc9357SAndroid Build Coastguard Worker const UInt64 cd64EndOffset = GetCurPos();
357*f6dc9357SAndroid Build Coastguard Worker const UInt64 cdSize = cd64EndOffset - cdOffset;
358*f6dc9357SAndroid Build Coastguard Worker const bool cdOffset64 = DOES_NEED_ZIP64(cdOffset);
359*f6dc9357SAndroid Build Coastguard Worker const bool cdSize64 = DOES_NEED_ZIP64(cdSize);
360*f6dc9357SAndroid Build Coastguard Worker const bool items64 = items.Size() >= 0xFFFF;
361*f6dc9357SAndroid Build Coastguard Worker const bool isZip64 = (cdOffset64 || cdSize64 || items64);
362*f6dc9357SAndroid Build Coastguard Worker
363*f6dc9357SAndroid Build Coastguard Worker // isZip64 = true; // to test Zip64
364*f6dc9357SAndroid Build Coastguard Worker
365*f6dc9357SAndroid Build Coastguard Worker if (isZip64)
366*f6dc9357SAndroid Build Coastguard Worker {
367*f6dc9357SAndroid Build Coastguard Worker Write32(NSignature::kEcd64);
368*f6dc9357SAndroid Build Coastguard Worker Write64(kEcd64_MainSize);
369*f6dc9357SAndroid Build Coastguard Worker
370*f6dc9357SAndroid Build Coastguard Worker // to test extra block:
371*f6dc9357SAndroid Build Coastguard Worker // const UInt32 extraSize = 1 << 26;
372*f6dc9357SAndroid Build Coastguard Worker // Write64(kEcd64_MainSize + extraSize);
373*f6dc9357SAndroid Build Coastguard Worker
374*f6dc9357SAndroid Build Coastguard Worker Write16(45); // made by version
375*f6dc9357SAndroid Build Coastguard Worker Write16(45); // extract version
376*f6dc9357SAndroid Build Coastguard Worker Write32(0); // ThisDiskNumber
377*f6dc9357SAndroid Build Coastguard Worker Write32(0); // StartCentralDirectoryDiskNumber
378*f6dc9357SAndroid Build Coastguard Worker Write64((UInt64)items.Size());
379*f6dc9357SAndroid Build Coastguard Worker Write64((UInt64)items.Size());
380*f6dc9357SAndroid Build Coastguard Worker Write64((UInt64)cdSize);
381*f6dc9357SAndroid Build Coastguard Worker Write64((UInt64)cdOffset);
382*f6dc9357SAndroid Build Coastguard Worker
383*f6dc9357SAndroid Build Coastguard Worker // for (UInt32 iii = 0; iii < extraSize; iii++) Write8(1);
384*f6dc9357SAndroid Build Coastguard Worker
385*f6dc9357SAndroid Build Coastguard Worker Write32(NSignature::kEcd64Locator);
386*f6dc9357SAndroid Build Coastguard Worker Write32(0); // number of the disk with the start of the zip64 end of central directory
387*f6dc9357SAndroid Build Coastguard Worker Write64(cd64EndOffset);
388*f6dc9357SAndroid Build Coastguard Worker Write32(1); // total number of disks
389*f6dc9357SAndroid Build Coastguard Worker }
390*f6dc9357SAndroid Build Coastguard Worker
391*f6dc9357SAndroid Build Coastguard Worker Write32(NSignature::kEcd);
392*f6dc9357SAndroid Build Coastguard Worker Write16(0); // ThisDiskNumber
393*f6dc9357SAndroid Build Coastguard Worker Write16(0); // StartCentralDirectoryDiskNumber
394*f6dc9357SAndroid Build Coastguard Worker Write16((UInt16)(items64 ? 0xFFFF: items.Size()));
395*f6dc9357SAndroid Build Coastguard Worker Write16((UInt16)(items64 ? 0xFFFF: items.Size()));
396*f6dc9357SAndroid Build Coastguard Worker
397*f6dc9357SAndroid Build Coastguard Worker WRITE_32_VAL_SPEC(cdSize, cdSize64)
398*f6dc9357SAndroid Build Coastguard Worker WRITE_32_VAL_SPEC(cdOffset, cdOffset64)
399*f6dc9357SAndroid Build Coastguard Worker
400*f6dc9357SAndroid Build Coastguard Worker const UInt16 commentSize = (UInt16)(comment ? comment->Size() : 0);
401*f6dc9357SAndroid Build Coastguard Worker Write16((UInt16)commentSize);
402*f6dc9357SAndroid Build Coastguard Worker if (commentSize != 0)
403*f6dc9357SAndroid Build Coastguard Worker WriteBytes((const Byte *)*comment, commentSize);
404*f6dc9357SAndroid Build Coastguard Worker m_OutBuffer.FlushWithCheck();
405*f6dc9357SAndroid Build Coastguard Worker return S_OK;
406*f6dc9357SAndroid Build Coastguard Worker }
407*f6dc9357SAndroid Build Coastguard Worker
CreateStreamForCompressing(CMyComPtr<IOutStream> & outStream)408*f6dc9357SAndroid Build Coastguard Worker void COutArchive::CreateStreamForCompressing(CMyComPtr<IOutStream> &outStream)
409*f6dc9357SAndroid Build Coastguard Worker {
410*f6dc9357SAndroid Build Coastguard Worker COffsetOutStream *streamSpec = new COffsetOutStream;
411*f6dc9357SAndroid Build Coastguard Worker outStream = streamSpec;
412*f6dc9357SAndroid Build Coastguard Worker streamSpec->Init(m_Stream, m_Base + m_CurPos);
413*f6dc9357SAndroid Build Coastguard Worker }
414*f6dc9357SAndroid Build Coastguard Worker
CreateStreamForCopying(CMyComPtr<ISequentialOutStream> & outStream)415*f6dc9357SAndroid Build Coastguard Worker void COutArchive::CreateStreamForCopying(CMyComPtr<ISequentialOutStream> &outStream)
416*f6dc9357SAndroid Build Coastguard Worker {
417*f6dc9357SAndroid Build Coastguard Worker outStream = m_Stream;
418*f6dc9357SAndroid Build Coastguard Worker }
419*f6dc9357SAndroid Build Coastguard Worker
420*f6dc9357SAndroid Build Coastguard Worker }}
421