1*f6dc9357SAndroid Build Coastguard Worker // WimHandlerOut.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 "../../../Common/ComTry.h"
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/IntToString.h"
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/MyBuffer2.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/StringToInt.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/UTFConvert.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/Wildcard.h"
11*f6dc9357SAndroid Build Coastguard Worker
12*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/PropVariant.h"
13*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/TimeUtils.h"
14*f6dc9357SAndroid Build Coastguard Worker
15*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/LimitedStreams.h"
16*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ProgressUtils.h"
17*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamUtils.h"
18*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/UniqBlocks.h"
19*f6dc9357SAndroid Build Coastguard Worker
20*f6dc9357SAndroid Build Coastguard Worker #include "../../Crypto/RandGen.h"
21*f6dc9357SAndroid Build Coastguard Worker #include "../../Crypto/Sha1Cls.h"
22*f6dc9357SAndroid Build Coastguard Worker
23*f6dc9357SAndroid Build Coastguard Worker #include "../Common/OutStreamWithSha1.h"
24*f6dc9357SAndroid Build Coastguard Worker
25*f6dc9357SAndroid Build Coastguard Worker #include "WimHandler.h"
26*f6dc9357SAndroid Build Coastguard Worker
27*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
28*f6dc9357SAndroid Build Coastguard Worker
29*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
30*f6dc9357SAndroid Build Coastguard Worker namespace NWim {
31*f6dc9357SAndroid Build Coastguard Worker
32*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_NumSubVectors_Bits = 12; // must be <= 16
33*f6dc9357SAndroid Build Coastguard Worker
34*f6dc9357SAndroid Build Coastguard Worker struct CSortedIndex
35*f6dc9357SAndroid Build Coastguard Worker {
36*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CUIntVector> Vectors;
37*f6dc9357SAndroid Build Coastguard Worker
CSortedIndexNArchive::NWim::CSortedIndex38*f6dc9357SAndroid Build Coastguard Worker CSortedIndex()
39*f6dc9357SAndroid Build Coastguard Worker {
40*f6dc9357SAndroid Build Coastguard Worker const unsigned k_NumSubVectors = 1 << k_NumSubVectors_Bits;
41*f6dc9357SAndroid Build Coastguard Worker Vectors.ClearAndReserve(k_NumSubVectors);
42*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < k_NumSubVectors; i++)
43*f6dc9357SAndroid Build Coastguard Worker Vectors.AddNew();
44*f6dc9357SAndroid Build Coastguard Worker }
45*f6dc9357SAndroid Build Coastguard Worker };
46*f6dc9357SAndroid Build Coastguard Worker
AddUniqHash(const CStreamInfo * streams,CSortedIndex & sorted2,const Byte * h,int streamIndexForInsert)47*f6dc9357SAndroid Build Coastguard Worker static int AddUniqHash(const CStreamInfo *streams, CSortedIndex &sorted2, const Byte *h, int streamIndexForInsert)
48*f6dc9357SAndroid Build Coastguard Worker {
49*f6dc9357SAndroid Build Coastguard Worker const unsigned hash = (((unsigned)h[0] << 8) | (unsigned)h[1]) >> (16 - k_NumSubVectors_Bits);
50*f6dc9357SAndroid Build Coastguard Worker CUIntVector &sorted = sorted2.Vectors[hash];
51*f6dc9357SAndroid Build Coastguard Worker unsigned left = 0, right = sorted.Size();
52*f6dc9357SAndroid Build Coastguard Worker while (left != right)
53*f6dc9357SAndroid Build Coastguard Worker {
54*f6dc9357SAndroid Build Coastguard Worker const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
55*f6dc9357SAndroid Build Coastguard Worker const unsigned index = sorted[mid];
56*f6dc9357SAndroid Build Coastguard Worker const Byte *hash2 = streams[index].Hash;
57*f6dc9357SAndroid Build Coastguard Worker
58*f6dc9357SAndroid Build Coastguard Worker unsigned i;
59*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < kHashSize; i++)
60*f6dc9357SAndroid Build Coastguard Worker if (h[i] != hash2[i])
61*f6dc9357SAndroid Build Coastguard Worker break;
62*f6dc9357SAndroid Build Coastguard Worker
63*f6dc9357SAndroid Build Coastguard Worker if (i == kHashSize)
64*f6dc9357SAndroid Build Coastguard Worker return (int)index;
65*f6dc9357SAndroid Build Coastguard Worker
66*f6dc9357SAndroid Build Coastguard Worker if (h[i] < hash2[i])
67*f6dc9357SAndroid Build Coastguard Worker right = mid;
68*f6dc9357SAndroid Build Coastguard Worker else
69*f6dc9357SAndroid Build Coastguard Worker left = mid + 1;
70*f6dc9357SAndroid Build Coastguard Worker }
71*f6dc9357SAndroid Build Coastguard Worker
72*f6dc9357SAndroid Build Coastguard Worker if (streamIndexForInsert != -1)
73*f6dc9357SAndroid Build Coastguard Worker sorted.Insert(left, (unsigned)streamIndexForInsert);
74*f6dc9357SAndroid Build Coastguard Worker
75*f6dc9357SAndroid Build Coastguard Worker return -1;
76*f6dc9357SAndroid Build Coastguard Worker }
77*f6dc9357SAndroid Build Coastguard Worker
78*f6dc9357SAndroid Build Coastguard Worker
79*f6dc9357SAndroid Build Coastguard Worker struct CAltStream
80*f6dc9357SAndroid Build Coastguard Worker {
81*f6dc9357SAndroid Build Coastguard Worker int UpdateIndex;
82*f6dc9357SAndroid Build Coastguard Worker int HashIndex;
83*f6dc9357SAndroid Build Coastguard Worker UInt64 Size;
84*f6dc9357SAndroid Build Coastguard Worker UString Name;
85*f6dc9357SAndroid Build Coastguard Worker bool Skip;
86*f6dc9357SAndroid Build Coastguard Worker
CAltStreamNArchive::NWim::CAltStream87*f6dc9357SAndroid Build Coastguard Worker CAltStream(): UpdateIndex(-1), HashIndex(-1), Skip(false) {}
88*f6dc9357SAndroid Build Coastguard Worker };
89*f6dc9357SAndroid Build Coastguard Worker
90*f6dc9357SAndroid Build Coastguard Worker
91*f6dc9357SAndroid Build Coastguard Worker struct CMetaItem
92*f6dc9357SAndroid Build Coastguard Worker {
93*f6dc9357SAndroid Build Coastguard Worker int UpdateIndex;
94*f6dc9357SAndroid Build Coastguard Worker int HashIndex;
95*f6dc9357SAndroid Build Coastguard Worker
96*f6dc9357SAndroid Build Coastguard Worker UInt64 Size;
97*f6dc9357SAndroid Build Coastguard Worker FILETIME CTime;
98*f6dc9357SAndroid Build Coastguard Worker FILETIME ATime;
99*f6dc9357SAndroid Build Coastguard Worker FILETIME MTime;
100*f6dc9357SAndroid Build Coastguard Worker UInt64 FileID;
101*f6dc9357SAndroid Build Coastguard Worker UInt64 VolID;
102*f6dc9357SAndroid Build Coastguard Worker
103*f6dc9357SAndroid Build Coastguard Worker UString Name;
104*f6dc9357SAndroid Build Coastguard Worker UString ShortName;
105*f6dc9357SAndroid Build Coastguard Worker
106*f6dc9357SAndroid Build Coastguard Worker UInt32 Attrib;
107*f6dc9357SAndroid Build Coastguard Worker int SecurityId; // -1: means no secutity ID
108*f6dc9357SAndroid Build Coastguard Worker bool IsDir;
109*f6dc9357SAndroid Build Coastguard Worker bool Skip;
110*f6dc9357SAndroid Build Coastguard Worker unsigned NumSkipAltStreams;
111*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CAltStream> AltStreams;
112*f6dc9357SAndroid Build Coastguard Worker
113*f6dc9357SAndroid Build Coastguard Worker CByteBuffer Reparse;
114*f6dc9357SAndroid Build Coastguard Worker
GetNumAltStreamsNArchive::NWim::CMetaItem115*f6dc9357SAndroid Build Coastguard Worker unsigned GetNumAltStreams() const { return AltStreams.Size() - NumSkipAltStreams; }
CMetaItemNArchive::NWim::CMetaItem116*f6dc9357SAndroid Build Coastguard Worker CMetaItem():
117*f6dc9357SAndroid Build Coastguard Worker UpdateIndex(-1)
118*f6dc9357SAndroid Build Coastguard Worker , HashIndex(-1)
119*f6dc9357SAndroid Build Coastguard Worker , Size(0)
120*f6dc9357SAndroid Build Coastguard Worker , FileID(0)
121*f6dc9357SAndroid Build Coastguard Worker , VolID(0)
122*f6dc9357SAndroid Build Coastguard Worker , Attrib(0)
123*f6dc9357SAndroid Build Coastguard Worker , SecurityId(-1)
124*f6dc9357SAndroid Build Coastguard Worker , IsDir(false)
125*f6dc9357SAndroid Build Coastguard Worker , Skip(false)
126*f6dc9357SAndroid Build Coastguard Worker , NumSkipAltStreams(0)
127*f6dc9357SAndroid Build Coastguard Worker {
128*f6dc9357SAndroid Build Coastguard Worker FILETIME_Clear(CTime);
129*f6dc9357SAndroid Build Coastguard Worker FILETIME_Clear(ATime);
130*f6dc9357SAndroid Build Coastguard Worker FILETIME_Clear(MTime);
131*f6dc9357SAndroid Build Coastguard Worker }
132*f6dc9357SAndroid Build Coastguard Worker };
133*f6dc9357SAndroid Build Coastguard Worker
134*f6dc9357SAndroid Build Coastguard Worker
Compare_HardLink_MetaItems(const CMetaItem & a1,const CMetaItem & a2)135*f6dc9357SAndroid Build Coastguard Worker static int Compare_HardLink_MetaItems(const CMetaItem &a1, const CMetaItem &a2)
136*f6dc9357SAndroid Build Coastguard Worker {
137*f6dc9357SAndroid Build Coastguard Worker if (a1.VolID < a2.VolID) return -1;
138*f6dc9357SAndroid Build Coastguard Worker if (a1.VolID > a2.VolID) return 1;
139*f6dc9357SAndroid Build Coastguard Worker if (a1.FileID < a2.FileID) return -1;
140*f6dc9357SAndroid Build Coastguard Worker if (a1.FileID > a2.FileID) return 1;
141*f6dc9357SAndroid Build Coastguard Worker if (a1.Size < a2.Size) return -1;
142*f6dc9357SAndroid Build Coastguard Worker if (a1.Size > a2.Size) return 1;
143*f6dc9357SAndroid Build Coastguard Worker return ::CompareFileTime(&a1.MTime, &a2.MTime);
144*f6dc9357SAndroid Build Coastguard Worker }
145*f6dc9357SAndroid Build Coastguard Worker
146*f6dc9357SAndroid Build Coastguard Worker
AddToHardLinkList(const CObjectVector<CMetaItem> & metaItems,unsigned indexOfItem,CUIntVector & indexes)147*f6dc9357SAndroid Build Coastguard Worker static int AddToHardLinkList(const CObjectVector<CMetaItem> &metaItems, unsigned indexOfItem, CUIntVector &indexes)
148*f6dc9357SAndroid Build Coastguard Worker {
149*f6dc9357SAndroid Build Coastguard Worker const CMetaItem &mi = metaItems[indexOfItem];
150*f6dc9357SAndroid Build Coastguard Worker unsigned left = 0, right = indexes.Size();
151*f6dc9357SAndroid Build Coastguard Worker while (left != right)
152*f6dc9357SAndroid Build Coastguard Worker {
153*f6dc9357SAndroid Build Coastguard Worker const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
154*f6dc9357SAndroid Build Coastguard Worker const unsigned index = indexes[mid];
155*f6dc9357SAndroid Build Coastguard Worker const int comp = Compare_HardLink_MetaItems(mi, metaItems[index]);
156*f6dc9357SAndroid Build Coastguard Worker if (comp == 0)
157*f6dc9357SAndroid Build Coastguard Worker return (int)index;
158*f6dc9357SAndroid Build Coastguard Worker if (comp < 0)
159*f6dc9357SAndroid Build Coastguard Worker right = mid;
160*f6dc9357SAndroid Build Coastguard Worker else
161*f6dc9357SAndroid Build Coastguard Worker left = mid + 1;
162*f6dc9357SAndroid Build Coastguard Worker }
163*f6dc9357SAndroid Build Coastguard Worker indexes.Insert(left, indexOfItem);
164*f6dc9357SAndroid Build Coastguard Worker return -1;
165*f6dc9357SAndroid Build Coastguard Worker }
166*f6dc9357SAndroid Build Coastguard Worker
167*f6dc9357SAndroid Build Coastguard Worker
168*f6dc9357SAndroid Build Coastguard Worker struct CUpdateItem
169*f6dc9357SAndroid Build Coastguard Worker {
170*f6dc9357SAndroid Build Coastguard Worker unsigned CallbackIndex; // index in callback
171*f6dc9357SAndroid Build Coastguard Worker
172*f6dc9357SAndroid Build Coastguard Worker int MetaIndex; // index in in MetaItems[]
173*f6dc9357SAndroid Build Coastguard Worker
174*f6dc9357SAndroid Build Coastguard Worker int AltStreamIndex; // index in CMetaItem::AltStreams vector
175*f6dc9357SAndroid Build Coastguard Worker // -1: if not alt stream?
176*f6dc9357SAndroid Build Coastguard Worker
177*f6dc9357SAndroid Build Coastguard Worker int InArcIndex; // >= 0, if we use OLD Data
178*f6dc9357SAndroid Build Coastguard Worker // -1, if we use NEW Data
179*f6dc9357SAndroid Build Coastguard Worker
CUpdateItemNArchive::NWim::CUpdateItem180*f6dc9357SAndroid Build Coastguard Worker CUpdateItem(): MetaIndex(-1), AltStreamIndex(-1), InArcIndex(-1) {}
181*f6dc9357SAndroid Build Coastguard Worker };
182*f6dc9357SAndroid Build Coastguard Worker
183*f6dc9357SAndroid Build Coastguard Worker
184*f6dc9357SAndroid Build Coastguard Worker struct CDir
185*f6dc9357SAndroid Build Coastguard Worker {
186*f6dc9357SAndroid Build Coastguard Worker int MetaIndex;
187*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CDir> Dirs;
188*f6dc9357SAndroid Build Coastguard Worker CUIntVector Files; // indexes in MetaItems[]
189*f6dc9357SAndroid Build Coastguard Worker
CDirNArchive::NWim::CDir190*f6dc9357SAndroid Build Coastguard Worker CDir(): MetaIndex(-1) {}
191*f6dc9357SAndroid Build Coastguard Worker unsigned GetNumDirs() const;
192*f6dc9357SAndroid Build Coastguard Worker unsigned GetNumFiles() const;
193*f6dc9357SAndroid Build Coastguard Worker UInt64 GetTotalSize(const CObjectVector<CMetaItem> &metaItems) const;
194*f6dc9357SAndroid Build Coastguard Worker bool FindDir(const CObjectVector<CMetaItem> &items, const UString &name, unsigned &index);
195*f6dc9357SAndroid Build Coastguard Worker };
196*f6dc9357SAndroid Build Coastguard Worker
197*f6dc9357SAndroid Build Coastguard Worker /* imagex counts Junctions as files (not as dirs).
198*f6dc9357SAndroid Build Coastguard Worker We suppose that it's not correct */
199*f6dc9357SAndroid Build Coastguard Worker
GetNumDirs() const200*f6dc9357SAndroid Build Coastguard Worker unsigned CDir::GetNumDirs() const
201*f6dc9357SAndroid Build Coastguard Worker {
202*f6dc9357SAndroid Build Coastguard Worker unsigned num = Dirs.Size();
203*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, Dirs)
204*f6dc9357SAndroid Build Coastguard Worker num += Dirs[i].GetNumDirs();
205*f6dc9357SAndroid Build Coastguard Worker return num;
206*f6dc9357SAndroid Build Coastguard Worker }
207*f6dc9357SAndroid Build Coastguard Worker
GetNumFiles() const208*f6dc9357SAndroid Build Coastguard Worker unsigned CDir::GetNumFiles() const
209*f6dc9357SAndroid Build Coastguard Worker {
210*f6dc9357SAndroid Build Coastguard Worker unsigned num = Files.Size();
211*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, Dirs)
212*f6dc9357SAndroid Build Coastguard Worker num += Dirs[i].GetNumFiles();
213*f6dc9357SAndroid Build Coastguard Worker return num;
214*f6dc9357SAndroid Build Coastguard Worker }
215*f6dc9357SAndroid Build Coastguard Worker
GetTotalSize(const CObjectVector<CMetaItem> & metaItems) const216*f6dc9357SAndroid Build Coastguard Worker UInt64 CDir::GetTotalSize(const CObjectVector<CMetaItem> &metaItems) const
217*f6dc9357SAndroid Build Coastguard Worker {
218*f6dc9357SAndroid Build Coastguard Worker UInt64 sum = 0;
219*f6dc9357SAndroid Build Coastguard Worker unsigned i;
220*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < Files.Size(); i++)
221*f6dc9357SAndroid Build Coastguard Worker sum += metaItems[Files[i]].Size;
222*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < Dirs.Size(); i++)
223*f6dc9357SAndroid Build Coastguard Worker sum += Dirs[i].GetTotalSize(metaItems);
224*f6dc9357SAndroid Build Coastguard Worker return sum;
225*f6dc9357SAndroid Build Coastguard Worker }
226*f6dc9357SAndroid Build Coastguard Worker
FindDir(const CObjectVector<CMetaItem> & items,const UString & name,unsigned & index)227*f6dc9357SAndroid Build Coastguard Worker bool CDir::FindDir(const CObjectVector<CMetaItem> &items, const UString &name, unsigned &index)
228*f6dc9357SAndroid Build Coastguard Worker {
229*f6dc9357SAndroid Build Coastguard Worker unsigned left = 0, right = Dirs.Size();
230*f6dc9357SAndroid Build Coastguard Worker while (left != right)
231*f6dc9357SAndroid Build Coastguard Worker {
232*f6dc9357SAndroid Build Coastguard Worker const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
233*f6dc9357SAndroid Build Coastguard Worker const int comp = CompareFileNames(name, items[Dirs[mid].MetaIndex].Name);
234*f6dc9357SAndroid Build Coastguard Worker if (comp == 0)
235*f6dc9357SAndroid Build Coastguard Worker {
236*f6dc9357SAndroid Build Coastguard Worker index = mid;
237*f6dc9357SAndroid Build Coastguard Worker return true;
238*f6dc9357SAndroid Build Coastguard Worker }
239*f6dc9357SAndroid Build Coastguard Worker if (comp < 0)
240*f6dc9357SAndroid Build Coastguard Worker right = mid;
241*f6dc9357SAndroid Build Coastguard Worker else
242*f6dc9357SAndroid Build Coastguard Worker left = mid + 1;
243*f6dc9357SAndroid Build Coastguard Worker }
244*f6dc9357SAndroid Build Coastguard Worker index = left;
245*f6dc9357SAndroid Build Coastguard Worker return false;
246*f6dc9357SAndroid Build Coastguard Worker }
247*f6dc9357SAndroid Build Coastguard Worker
248*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::GetFileTimeType (UInt32 * type))249*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *type))
250*f6dc9357SAndroid Build Coastguard Worker {
251*f6dc9357SAndroid Build Coastguard Worker *type = NFileTimeType::kWindows;
252*f6dc9357SAndroid Build Coastguard Worker return S_OK;
253*f6dc9357SAndroid Build Coastguard Worker }
254*f6dc9357SAndroid Build Coastguard Worker
255*f6dc9357SAndroid Build Coastguard Worker
GetOutProperty(IArchiveUpdateCallback * callback,UInt32 callbackIndex,Int32 arcIndex,PROPID propID,PROPVARIANT * value)256*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::GetOutProperty(IArchiveUpdateCallback *callback, UInt32 callbackIndex, Int32 arcIndex, PROPID propID, PROPVARIANT *value)
257*f6dc9357SAndroid Build Coastguard Worker {
258*f6dc9357SAndroid Build Coastguard Worker if (arcIndex != -1)
259*f6dc9357SAndroid Build Coastguard Worker return GetProperty((UInt32)arcIndex, propID, value);
260*f6dc9357SAndroid Build Coastguard Worker return callback->GetProperty(callbackIndex, propID, value);
261*f6dc9357SAndroid Build Coastguard Worker }
262*f6dc9357SAndroid Build Coastguard Worker
263*f6dc9357SAndroid Build Coastguard Worker
GetTime(IArchiveUpdateCallback * callback,UInt32 callbackIndex,Int32 arcIndex,PROPID propID,FILETIME & ft)264*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::GetTime(IArchiveUpdateCallback *callback, UInt32 callbackIndex, Int32 arcIndex, PROPID propID, FILETIME &ft)
265*f6dc9357SAndroid Build Coastguard Worker {
266*f6dc9357SAndroid Build Coastguard Worker ft.dwLowDateTime = ft.dwHighDateTime = 0;
267*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
268*f6dc9357SAndroid Build Coastguard Worker RINOK(GetOutProperty(callback, callbackIndex, arcIndex, propID, &prop))
269*f6dc9357SAndroid Build Coastguard Worker if (prop.vt == VT_FILETIME)
270*f6dc9357SAndroid Build Coastguard Worker ft = prop.filetime;
271*f6dc9357SAndroid Build Coastguard Worker else if (prop.vt != VT_EMPTY)
272*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
273*f6dc9357SAndroid Build Coastguard Worker return S_OK;
274*f6dc9357SAndroid Build Coastguard Worker }
275*f6dc9357SAndroid Build Coastguard Worker
276*f6dc9357SAndroid Build Coastguard Worker
GetRootTime(IArchiveGetRootProps * callback,IArchiveGetRootProps * arcRoot,PROPID propID,FILETIME & ft)277*f6dc9357SAndroid Build Coastguard Worker static HRESULT GetRootTime(
278*f6dc9357SAndroid Build Coastguard Worker IArchiveGetRootProps *callback,
279*f6dc9357SAndroid Build Coastguard Worker IArchiveGetRootProps *arcRoot,
280*f6dc9357SAndroid Build Coastguard Worker PROPID propID, FILETIME &ft)
281*f6dc9357SAndroid Build Coastguard Worker {
282*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
283*f6dc9357SAndroid Build Coastguard Worker if (callback)
284*f6dc9357SAndroid Build Coastguard Worker {
285*f6dc9357SAndroid Build Coastguard Worker RINOK(callback->GetRootProp(propID, &prop))
286*f6dc9357SAndroid Build Coastguard Worker if (prop.vt == VT_FILETIME)
287*f6dc9357SAndroid Build Coastguard Worker {
288*f6dc9357SAndroid Build Coastguard Worker ft = prop.filetime;
289*f6dc9357SAndroid Build Coastguard Worker return S_OK;
290*f6dc9357SAndroid Build Coastguard Worker }
291*f6dc9357SAndroid Build Coastguard Worker if (prop.vt != VT_EMPTY)
292*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
293*f6dc9357SAndroid Build Coastguard Worker }
294*f6dc9357SAndroid Build Coastguard Worker if (arcRoot)
295*f6dc9357SAndroid Build Coastguard Worker {
296*f6dc9357SAndroid Build Coastguard Worker RINOK(arcRoot->GetRootProp(propID, &prop))
297*f6dc9357SAndroid Build Coastguard Worker if (prop.vt == VT_FILETIME)
298*f6dc9357SAndroid Build Coastguard Worker {
299*f6dc9357SAndroid Build Coastguard Worker ft = prop.filetime;
300*f6dc9357SAndroid Build Coastguard Worker return S_OK;
301*f6dc9357SAndroid Build Coastguard Worker }
302*f6dc9357SAndroid Build Coastguard Worker if (prop.vt != VT_EMPTY)
303*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
304*f6dc9357SAndroid Build Coastguard Worker }
305*f6dc9357SAndroid Build Coastguard Worker return S_OK;
306*f6dc9357SAndroid Build Coastguard Worker }
307*f6dc9357SAndroid Build Coastguard Worker
308*f6dc9357SAndroid Build Coastguard Worker #define Set16(p, d) SetUi16(p, d)
309*f6dc9357SAndroid Build Coastguard Worker #define Set32(p, d) SetUi32(p, d)
310*f6dc9357SAndroid Build Coastguard Worker #define Set64(p, d) SetUi64(p, d)
311*f6dc9357SAndroid Build Coastguard Worker
WriteTo(Byte * p) const312*f6dc9357SAndroid Build Coastguard Worker void CResource::WriteTo(Byte *p) const
313*f6dc9357SAndroid Build Coastguard Worker {
314*f6dc9357SAndroid Build Coastguard Worker Set64(p, PackSize)
315*f6dc9357SAndroid Build Coastguard Worker p[7] = Flags;
316*f6dc9357SAndroid Build Coastguard Worker Set64(p + 8, Offset)
317*f6dc9357SAndroid Build Coastguard Worker Set64(p + 16, UnpackSize)
318*f6dc9357SAndroid Build Coastguard Worker }
319*f6dc9357SAndroid Build Coastguard Worker
320*f6dc9357SAndroid Build Coastguard Worker
WriteTo(Byte * p) const321*f6dc9357SAndroid Build Coastguard Worker void CHeader::WriteTo(Byte *p) const
322*f6dc9357SAndroid Build Coastguard Worker {
323*f6dc9357SAndroid Build Coastguard Worker memcpy(p, kSignature, kSignatureSize);
324*f6dc9357SAndroid Build Coastguard Worker Set32(p + 8, kHeaderSizeMax)
325*f6dc9357SAndroid Build Coastguard Worker Set32(p + 0xC, Version)
326*f6dc9357SAndroid Build Coastguard Worker Set32(p + 0x10, Flags)
327*f6dc9357SAndroid Build Coastguard Worker Set32(p + 0x14, ChunkSize)
328*f6dc9357SAndroid Build Coastguard Worker memcpy(p + 0x18, Guid, 16);
329*f6dc9357SAndroid Build Coastguard Worker Set16(p + 0x28, PartNumber)
330*f6dc9357SAndroid Build Coastguard Worker Set16(p + 0x2A, NumParts)
331*f6dc9357SAndroid Build Coastguard Worker Set32(p + 0x2C, NumImages)
332*f6dc9357SAndroid Build Coastguard Worker OffsetResource.WriteTo(p + 0x30);
333*f6dc9357SAndroid Build Coastguard Worker XmlResource.WriteTo(p + 0x48);
334*f6dc9357SAndroid Build Coastguard Worker MetadataResource.WriteTo(p + 0x60);
335*f6dc9357SAndroid Build Coastguard Worker IntegrityResource.WriteTo(p + 0x7C);
336*f6dc9357SAndroid Build Coastguard Worker Set32(p + 0x78, BootIndex)
337*f6dc9357SAndroid Build Coastguard Worker memset(p + 0x94, 0, 60);
338*f6dc9357SAndroid Build Coastguard Worker }
339*f6dc9357SAndroid Build Coastguard Worker
340*f6dc9357SAndroid Build Coastguard Worker
WriteTo(Byte * p) const341*f6dc9357SAndroid Build Coastguard Worker void CStreamInfo::WriteTo(Byte *p) const
342*f6dc9357SAndroid Build Coastguard Worker {
343*f6dc9357SAndroid Build Coastguard Worker Resource.WriteTo(p);
344*f6dc9357SAndroid Build Coastguard Worker Set16(p + 0x18, PartNumber)
345*f6dc9357SAndroid Build Coastguard Worker Set32(p + 0x1A, RefCount)
346*f6dc9357SAndroid Build Coastguard Worker memcpy(p + 0x1E, Hash, kHashSize);
347*f6dc9357SAndroid Build Coastguard Worker }
348*f6dc9357SAndroid Build Coastguard Worker
349*f6dc9357SAndroid Build Coastguard Worker
SetFileTimeToMem(Byte * p,const FILETIME & ft)350*f6dc9357SAndroid Build Coastguard Worker static void SetFileTimeToMem(Byte *p, const FILETIME &ft)
351*f6dc9357SAndroid Build Coastguard Worker {
352*f6dc9357SAndroid Build Coastguard Worker Set32(p, ft.dwLowDateTime)
353*f6dc9357SAndroid Build Coastguard Worker Set32(p + 4, ft.dwHighDateTime)
354*f6dc9357SAndroid Build Coastguard Worker }
355*f6dc9357SAndroid Build Coastguard Worker
WriteItem_Dummy(const CMetaItem & item)356*f6dc9357SAndroid Build Coastguard Worker static size_t WriteItem_Dummy(const CMetaItem &item)
357*f6dc9357SAndroid Build Coastguard Worker {
358*f6dc9357SAndroid Build Coastguard Worker if (item.Skip)
359*f6dc9357SAndroid Build Coastguard Worker return 0;
360*f6dc9357SAndroid Build Coastguard Worker unsigned fileNameLen = item.Name.Len() * 2;
361*f6dc9357SAndroid Build Coastguard Worker // we write fileNameLen + 2 + 2 to be same as original WIM.
362*f6dc9357SAndroid Build Coastguard Worker unsigned fileNameLen2 = (fileNameLen == 0 ? 0 : fileNameLen + 2);
363*f6dc9357SAndroid Build Coastguard Worker
364*f6dc9357SAndroid Build Coastguard Worker const unsigned shortNameLen = item.ShortName.Len() * 2;
365*f6dc9357SAndroid Build Coastguard Worker const unsigned shortNameLen2 = (shortNameLen == 0 ? 2 : shortNameLen + 4);
366*f6dc9357SAndroid Build Coastguard Worker
367*f6dc9357SAndroid Build Coastguard Worker size_t totalLen = ((kDirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~(unsigned)7);
368*f6dc9357SAndroid Build Coastguard Worker if (item.GetNumAltStreams() != 0)
369*f6dc9357SAndroid Build Coastguard Worker {
370*f6dc9357SAndroid Build Coastguard Worker if (!item.IsDir)
371*f6dc9357SAndroid Build Coastguard Worker {
372*f6dc9357SAndroid Build Coastguard Worker const UInt32 curLen = (((0x26 + 0) + 6) & ~(unsigned)7);
373*f6dc9357SAndroid Build Coastguard Worker totalLen += curLen;
374*f6dc9357SAndroid Build Coastguard Worker }
375*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, item.AltStreams)
376*f6dc9357SAndroid Build Coastguard Worker {
377*f6dc9357SAndroid Build Coastguard Worker const CAltStream &ss = item.AltStreams[i];
378*f6dc9357SAndroid Build Coastguard Worker if (ss.Skip)
379*f6dc9357SAndroid Build Coastguard Worker continue;
380*f6dc9357SAndroid Build Coastguard Worker fileNameLen = ss.Name.Len() * 2;
381*f6dc9357SAndroid Build Coastguard Worker fileNameLen2 = (fileNameLen == 0 ? 0 : fileNameLen + 2 + 2);
382*f6dc9357SAndroid Build Coastguard Worker const UInt32 curLen = (((0x26 + fileNameLen2) + 6) & ~(unsigned)7);
383*f6dc9357SAndroid Build Coastguard Worker totalLen += curLen;
384*f6dc9357SAndroid Build Coastguard Worker }
385*f6dc9357SAndroid Build Coastguard Worker }
386*f6dc9357SAndroid Build Coastguard Worker return totalLen;
387*f6dc9357SAndroid Build Coastguard Worker }
388*f6dc9357SAndroid Build Coastguard Worker
389*f6dc9357SAndroid Build Coastguard Worker
WriteItem(const CStreamInfo * streams,const CMetaItem & item,Byte * p)390*f6dc9357SAndroid Build Coastguard Worker static size_t WriteItem(const CStreamInfo *streams, const CMetaItem &item, Byte *p)
391*f6dc9357SAndroid Build Coastguard Worker {
392*f6dc9357SAndroid Build Coastguard Worker if (item.Skip)
393*f6dc9357SAndroid Build Coastguard Worker return 0;
394*f6dc9357SAndroid Build Coastguard Worker unsigned fileNameLen = item.Name.Len() * 2;
395*f6dc9357SAndroid Build Coastguard Worker unsigned fileNameLen2 = (fileNameLen == 0 ? 0 : fileNameLen + 2);
396*f6dc9357SAndroid Build Coastguard Worker unsigned shortNameLen = item.ShortName.Len() * 2;
397*f6dc9357SAndroid Build Coastguard Worker unsigned shortNameLen2 = (shortNameLen == 0 ? 2 : shortNameLen + 4);
398*f6dc9357SAndroid Build Coastguard Worker
399*f6dc9357SAndroid Build Coastguard Worker size_t totalLen = ((kDirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~(unsigned)7);
400*f6dc9357SAndroid Build Coastguard Worker
401*f6dc9357SAndroid Build Coastguard Worker memset(p, 0, totalLen);
402*f6dc9357SAndroid Build Coastguard Worker Set64(p, totalLen)
403*f6dc9357SAndroid Build Coastguard Worker Set64(p + 8, item.Attrib)
404*f6dc9357SAndroid Build Coastguard Worker Set32(p + 0xC, (UInt32)(Int32)item.SecurityId)
405*f6dc9357SAndroid Build Coastguard Worker SetFileTimeToMem(p + 0x28, item.CTime);
406*f6dc9357SAndroid Build Coastguard Worker SetFileTimeToMem(p + 0x30, item.ATime);
407*f6dc9357SAndroid Build Coastguard Worker SetFileTimeToMem(p + 0x38, item.MTime);
408*f6dc9357SAndroid Build Coastguard Worker
409*f6dc9357SAndroid Build Coastguard Worker /* WIM format probably doesn't support hard links to symbolic links.
410*f6dc9357SAndroid Build Coastguard Worker In these cases it just stores symbolic links (REPARSE TAGS).
411*f6dc9357SAndroid Build Coastguard Worker Check it in new versions of WIM software form MS !!!
412*f6dc9357SAndroid Build Coastguard Worker We also follow that scheme */
413*f6dc9357SAndroid Build Coastguard Worker
414*f6dc9357SAndroid Build Coastguard Worker if (item.Reparse.Size() != 0)
415*f6dc9357SAndroid Build Coastguard Worker {
416*f6dc9357SAndroid Build Coastguard Worker UInt32 tag = GetUi32(item.Reparse);
417*f6dc9357SAndroid Build Coastguard Worker Set32(p + 0x58, tag)
418*f6dc9357SAndroid Build Coastguard Worker // Set32(p + 0x5C, 0); // probably it's always ZERO
419*f6dc9357SAndroid Build Coastguard Worker }
420*f6dc9357SAndroid Build Coastguard Worker else if (item.FileID != 0)
421*f6dc9357SAndroid Build Coastguard Worker {
422*f6dc9357SAndroid Build Coastguard Worker Set64(p + 0x58, item.FileID)
423*f6dc9357SAndroid Build Coastguard Worker }
424*f6dc9357SAndroid Build Coastguard Worker
425*f6dc9357SAndroid Build Coastguard Worker Set16(p + 0x62, (UInt16)shortNameLen)
426*f6dc9357SAndroid Build Coastguard Worker Set16(p + 0x64, (UInt16)fileNameLen)
427*f6dc9357SAndroid Build Coastguard Worker unsigned i;
428*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i * 2 < fileNameLen; i++)
429*f6dc9357SAndroid Build Coastguard Worker Set16(p + kDirRecordSize + i * 2, (UInt16)item.Name[i])
430*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i * 2 < shortNameLen; i++)
431*f6dc9357SAndroid Build Coastguard Worker Set16(p + kDirRecordSize + fileNameLen2 + i * 2, (UInt16)item.ShortName[i])
432*f6dc9357SAndroid Build Coastguard Worker
433*f6dc9357SAndroid Build Coastguard Worker if (item.GetNumAltStreams() == 0)
434*f6dc9357SAndroid Build Coastguard Worker {
435*f6dc9357SAndroid Build Coastguard Worker if (item.HashIndex >= 0)
436*f6dc9357SAndroid Build Coastguard Worker memcpy(p + 0x40, streams[item.HashIndex].Hash, kHashSize);
437*f6dc9357SAndroid Build Coastguard Worker }
438*f6dc9357SAndroid Build Coastguard Worker else
439*f6dc9357SAndroid Build Coastguard Worker {
440*f6dc9357SAndroid Build Coastguard Worker Set16(p + 0x60, (UInt16)(item.GetNumAltStreams() + (item.IsDir ? 0 : 1)))
441*f6dc9357SAndroid Build Coastguard Worker p += totalLen;
442*f6dc9357SAndroid Build Coastguard Worker
443*f6dc9357SAndroid Build Coastguard Worker if (!item.IsDir)
444*f6dc9357SAndroid Build Coastguard Worker {
445*f6dc9357SAndroid Build Coastguard Worker const UInt32 curLen = (((0x26 + 0) + 6) & ~(unsigned)7);
446*f6dc9357SAndroid Build Coastguard Worker memset(p, 0, curLen);
447*f6dc9357SAndroid Build Coastguard Worker Set64(p, curLen)
448*f6dc9357SAndroid Build Coastguard Worker if (item.HashIndex >= 0)
449*f6dc9357SAndroid Build Coastguard Worker memcpy(p + 0x10, streams[item.HashIndex].Hash, kHashSize);
450*f6dc9357SAndroid Build Coastguard Worker totalLen += curLen;
451*f6dc9357SAndroid Build Coastguard Worker p += curLen;
452*f6dc9357SAndroid Build Coastguard Worker }
453*f6dc9357SAndroid Build Coastguard Worker
454*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (si, item.AltStreams)
455*f6dc9357SAndroid Build Coastguard Worker {
456*f6dc9357SAndroid Build Coastguard Worker const CAltStream &ss = item.AltStreams[si];
457*f6dc9357SAndroid Build Coastguard Worker if (ss.Skip)
458*f6dc9357SAndroid Build Coastguard Worker continue;
459*f6dc9357SAndroid Build Coastguard Worker
460*f6dc9357SAndroid Build Coastguard Worker fileNameLen = ss.Name.Len() * 2;
461*f6dc9357SAndroid Build Coastguard Worker fileNameLen2 = (fileNameLen == 0 ? 0 : fileNameLen + 2 + 2);
462*f6dc9357SAndroid Build Coastguard Worker UInt32 curLen = (((0x26 + fileNameLen2) + 6) & ~(unsigned)7);
463*f6dc9357SAndroid Build Coastguard Worker memset(p, 0, curLen);
464*f6dc9357SAndroid Build Coastguard Worker
465*f6dc9357SAndroid Build Coastguard Worker Set64(p, curLen)
466*f6dc9357SAndroid Build Coastguard Worker if (ss.HashIndex >= 0)
467*f6dc9357SAndroid Build Coastguard Worker memcpy(p + 0x10, streams[ss.HashIndex].Hash, kHashSize);
468*f6dc9357SAndroid Build Coastguard Worker Set16(p + 0x24, (UInt16)fileNameLen)
469*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i * 2 < fileNameLen; i++)
470*f6dc9357SAndroid Build Coastguard Worker Set16(p + 0x26 + i * 2, (UInt16)ss.Name[i])
471*f6dc9357SAndroid Build Coastguard Worker totalLen += curLen;
472*f6dc9357SAndroid Build Coastguard Worker p += curLen;
473*f6dc9357SAndroid Build Coastguard Worker }
474*f6dc9357SAndroid Build Coastguard Worker }
475*f6dc9357SAndroid Build Coastguard Worker
476*f6dc9357SAndroid Build Coastguard Worker return totalLen;
477*f6dc9357SAndroid Build Coastguard Worker }
478*f6dc9357SAndroid Build Coastguard Worker
479*f6dc9357SAndroid Build Coastguard Worker
480*f6dc9357SAndroid Build Coastguard Worker struct CDb
481*f6dc9357SAndroid Build Coastguard Worker {
482*f6dc9357SAndroid Build Coastguard Worker CMetaItem DefaultDirItem;
483*f6dc9357SAndroid Build Coastguard Worker const CStreamInfo *Hashes;
484*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CMetaItem> MetaItems;
485*f6dc9357SAndroid Build Coastguard Worker CRecordVector<CUpdateItem> UpdateItems;
486*f6dc9357SAndroid Build Coastguard Worker CUIntVector UpdateIndexes; /* indexes in UpdateItems in order of writing data streams
487*f6dc9357SAndroid Build Coastguard Worker to disk (the order of tree items). */
488*f6dc9357SAndroid Build Coastguard Worker
489*f6dc9357SAndroid Build Coastguard Worker size_t WriteTree_Dummy(const CDir &tree) const;
490*f6dc9357SAndroid Build Coastguard Worker void WriteTree(const CDir &tree, Byte *dest, size_t &pos) const;
491*f6dc9357SAndroid Build Coastguard Worker void WriteOrderList(const CDir &tree);
492*f6dc9357SAndroid Build Coastguard Worker };
493*f6dc9357SAndroid Build Coastguard Worker
494*f6dc9357SAndroid Build Coastguard Worker
WriteTree_Dummy(const CDir & tree) const495*f6dc9357SAndroid Build Coastguard Worker size_t CDb::WriteTree_Dummy(const CDir &tree) const
496*f6dc9357SAndroid Build Coastguard Worker {
497*f6dc9357SAndroid Build Coastguard Worker unsigned i;
498*f6dc9357SAndroid Build Coastguard Worker size_t pos = 0;
499*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < tree.Files.Size(); i++)
500*f6dc9357SAndroid Build Coastguard Worker pos += WriteItem_Dummy(MetaItems[tree.Files[i]]);
501*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < tree.Dirs.Size(); i++)
502*f6dc9357SAndroid Build Coastguard Worker {
503*f6dc9357SAndroid Build Coastguard Worker const CDir &subDir = tree.Dirs[i];
504*f6dc9357SAndroid Build Coastguard Worker pos += WriteItem_Dummy(MetaItems[subDir.MetaIndex]);
505*f6dc9357SAndroid Build Coastguard Worker pos += WriteTree_Dummy(subDir);
506*f6dc9357SAndroid Build Coastguard Worker }
507*f6dc9357SAndroid Build Coastguard Worker return pos + 8;
508*f6dc9357SAndroid Build Coastguard Worker }
509*f6dc9357SAndroid Build Coastguard Worker
510*f6dc9357SAndroid Build Coastguard Worker
WriteTree(const CDir & tree,Byte * dest,size_t & pos) const511*f6dc9357SAndroid Build Coastguard Worker void CDb::WriteTree(const CDir &tree, Byte *dest, size_t &pos) const
512*f6dc9357SAndroid Build Coastguard Worker {
513*f6dc9357SAndroid Build Coastguard Worker unsigned i;
514*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < tree.Files.Size(); i++)
515*f6dc9357SAndroid Build Coastguard Worker pos += WriteItem(Hashes, MetaItems[tree.Files[i]], dest + pos);
516*f6dc9357SAndroid Build Coastguard Worker
517*f6dc9357SAndroid Build Coastguard Worker size_t posStart = pos;
518*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < tree.Dirs.Size(); i++)
519*f6dc9357SAndroid Build Coastguard Worker pos += WriteItem_Dummy(MetaItems[tree.Dirs[i].MetaIndex]);
520*f6dc9357SAndroid Build Coastguard Worker
521*f6dc9357SAndroid Build Coastguard Worker Set64(dest + pos, 0)
522*f6dc9357SAndroid Build Coastguard Worker
523*f6dc9357SAndroid Build Coastguard Worker pos += 8;
524*f6dc9357SAndroid Build Coastguard Worker
525*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < tree.Dirs.Size(); i++)
526*f6dc9357SAndroid Build Coastguard Worker {
527*f6dc9357SAndroid Build Coastguard Worker const CDir &subDir = tree.Dirs[i];
528*f6dc9357SAndroid Build Coastguard Worker const CMetaItem &metaItem = MetaItems[subDir.MetaIndex];
529*f6dc9357SAndroid Build Coastguard Worker bool needCreateTree = (metaItem.Reparse.Size() == 0)
530*f6dc9357SAndroid Build Coastguard Worker || !subDir.Files.IsEmpty()
531*f6dc9357SAndroid Build Coastguard Worker || !subDir.Dirs.IsEmpty();
532*f6dc9357SAndroid Build Coastguard Worker size_t len = WriteItem(Hashes, metaItem, dest + posStart);
533*f6dc9357SAndroid Build Coastguard Worker posStart += len;
534*f6dc9357SAndroid Build Coastguard Worker if (needCreateTree)
535*f6dc9357SAndroid Build Coastguard Worker {
536*f6dc9357SAndroid Build Coastguard Worker Set64(dest + posStart - len + 0x10, pos) // subdirOffset
537*f6dc9357SAndroid Build Coastguard Worker WriteTree(subDir, dest, pos);
538*f6dc9357SAndroid Build Coastguard Worker }
539*f6dc9357SAndroid Build Coastguard Worker }
540*f6dc9357SAndroid Build Coastguard Worker }
541*f6dc9357SAndroid Build Coastguard Worker
542*f6dc9357SAndroid Build Coastguard Worker
WriteOrderList(const CDir & tree)543*f6dc9357SAndroid Build Coastguard Worker void CDb::WriteOrderList(const CDir &tree)
544*f6dc9357SAndroid Build Coastguard Worker {
545*f6dc9357SAndroid Build Coastguard Worker if (tree.MetaIndex >= 0)
546*f6dc9357SAndroid Build Coastguard Worker {
547*f6dc9357SAndroid Build Coastguard Worker const CMetaItem &mi = MetaItems[tree.MetaIndex];
548*f6dc9357SAndroid Build Coastguard Worker if (mi.UpdateIndex >= 0)
549*f6dc9357SAndroid Build Coastguard Worker UpdateIndexes.Add((unsigned)mi.UpdateIndex);
550*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (si, mi.AltStreams)
551*f6dc9357SAndroid Build Coastguard Worker UpdateIndexes.Add((unsigned)mi.AltStreams[si].UpdateIndex);
552*f6dc9357SAndroid Build Coastguard Worker }
553*f6dc9357SAndroid Build Coastguard Worker
554*f6dc9357SAndroid Build Coastguard Worker unsigned i;
555*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < tree.Files.Size(); i++)
556*f6dc9357SAndroid Build Coastguard Worker {
557*f6dc9357SAndroid Build Coastguard Worker const CMetaItem &mi = MetaItems[tree.Files[i]];
558*f6dc9357SAndroid Build Coastguard Worker UpdateIndexes.Add((unsigned)mi.UpdateIndex);
559*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (si, mi.AltStreams)
560*f6dc9357SAndroid Build Coastguard Worker UpdateIndexes.Add((unsigned)mi.AltStreams[si].UpdateIndex);
561*f6dc9357SAndroid Build Coastguard Worker }
562*f6dc9357SAndroid Build Coastguard Worker
563*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < tree.Dirs.Size(); i++)
564*f6dc9357SAndroid Build Coastguard Worker WriteOrderList(tree.Dirs[i]);
565*f6dc9357SAndroid Build Coastguard Worker }
566*f6dc9357SAndroid Build Coastguard Worker
567*f6dc9357SAndroid Build Coastguard Worker
AddTag_ToString(AString & s,const char * name,const char * value)568*f6dc9357SAndroid Build Coastguard Worker static void AddTag_ToString(AString &s, const char *name, const char *value)
569*f6dc9357SAndroid Build Coastguard Worker {
570*f6dc9357SAndroid Build Coastguard Worker s.Add_Char('<');
571*f6dc9357SAndroid Build Coastguard Worker s += name;
572*f6dc9357SAndroid Build Coastguard Worker s.Add_Char('>');
573*f6dc9357SAndroid Build Coastguard Worker s += value;
574*f6dc9357SAndroid Build Coastguard Worker s.Add_Char('<');
575*f6dc9357SAndroid Build Coastguard Worker s.Add_Slash();
576*f6dc9357SAndroid Build Coastguard Worker s += name;
577*f6dc9357SAndroid Build Coastguard Worker s.Add_Char('>');
578*f6dc9357SAndroid Build Coastguard Worker }
579*f6dc9357SAndroid Build Coastguard Worker
580*f6dc9357SAndroid Build Coastguard Worker
AddTagUInt64_ToString(AString & s,const char * name,UInt64 value)581*f6dc9357SAndroid Build Coastguard Worker static void AddTagUInt64_ToString(AString &s, const char *name, UInt64 value)
582*f6dc9357SAndroid Build Coastguard Worker {
583*f6dc9357SAndroid Build Coastguard Worker char temp[32];
584*f6dc9357SAndroid Build Coastguard Worker ConvertUInt64ToString(value, temp);
585*f6dc9357SAndroid Build Coastguard Worker AddTag_ToString(s, name, temp);
586*f6dc9357SAndroid Build Coastguard Worker }
587*f6dc9357SAndroid Build Coastguard Worker
588*f6dc9357SAndroid Build Coastguard Worker
AddUniqueTag(CXmlItem & parentItem,const char * name)589*f6dc9357SAndroid Build Coastguard Worker static CXmlItem &AddUniqueTag(CXmlItem &parentItem, const char *name)
590*f6dc9357SAndroid Build Coastguard Worker {
591*f6dc9357SAndroid Build Coastguard Worker const int index = parentItem.FindSubTag(name);
592*f6dc9357SAndroid Build Coastguard Worker if (index < 0)
593*f6dc9357SAndroid Build Coastguard Worker {
594*f6dc9357SAndroid Build Coastguard Worker CXmlItem &subItem = parentItem.SubItems.AddNew();
595*f6dc9357SAndroid Build Coastguard Worker subItem.IsTag = true;
596*f6dc9357SAndroid Build Coastguard Worker subItem.Name = name;
597*f6dc9357SAndroid Build Coastguard Worker return subItem;
598*f6dc9357SAndroid Build Coastguard Worker }
599*f6dc9357SAndroid Build Coastguard Worker CXmlItem &subItem = parentItem.SubItems[index];
600*f6dc9357SAndroid Build Coastguard Worker subItem.SubItems.Clear();
601*f6dc9357SAndroid Build Coastguard Worker return subItem;
602*f6dc9357SAndroid Build Coastguard Worker }
603*f6dc9357SAndroid Build Coastguard Worker
604*f6dc9357SAndroid Build Coastguard Worker
AddTag_UInt64_2(CXmlItem & item,UInt64 value)605*f6dc9357SAndroid Build Coastguard Worker static void AddTag_UInt64_2(CXmlItem &item, UInt64 value)
606*f6dc9357SAndroid Build Coastguard Worker {
607*f6dc9357SAndroid Build Coastguard Worker CXmlItem &subItem = item.SubItems.AddNew();
608*f6dc9357SAndroid Build Coastguard Worker subItem.IsTag = false;
609*f6dc9357SAndroid Build Coastguard Worker char temp[32];
610*f6dc9357SAndroid Build Coastguard Worker ConvertUInt64ToString(value, temp);
611*f6dc9357SAndroid Build Coastguard Worker subItem.Name = temp;
612*f6dc9357SAndroid Build Coastguard Worker }
613*f6dc9357SAndroid Build Coastguard Worker
614*f6dc9357SAndroid Build Coastguard Worker
AddTag_UInt64(CXmlItem & parentItem,const char * name,UInt64 value)615*f6dc9357SAndroid Build Coastguard Worker static void AddTag_UInt64(CXmlItem &parentItem, const char *name, UInt64 value)
616*f6dc9357SAndroid Build Coastguard Worker {
617*f6dc9357SAndroid Build Coastguard Worker AddTag_UInt64_2(AddUniqueTag(parentItem, name), value);
618*f6dc9357SAndroid Build Coastguard Worker }
619*f6dc9357SAndroid Build Coastguard Worker
620*f6dc9357SAndroid Build Coastguard Worker
AddTag_Hex(CXmlItem & item,const char * name,UInt32 value)621*f6dc9357SAndroid Build Coastguard Worker static void AddTag_Hex(CXmlItem &item, const char *name, UInt32 value)
622*f6dc9357SAndroid Build Coastguard Worker {
623*f6dc9357SAndroid Build Coastguard Worker item.IsTag = true;
624*f6dc9357SAndroid Build Coastguard Worker item.Name = name;
625*f6dc9357SAndroid Build Coastguard Worker char temp[16];
626*f6dc9357SAndroid Build Coastguard Worker temp[0] = '0';
627*f6dc9357SAndroid Build Coastguard Worker temp[1] = 'x';
628*f6dc9357SAndroid Build Coastguard Worker ConvertUInt32ToHex8Digits(value, temp + 2);
629*f6dc9357SAndroid Build Coastguard Worker CXmlItem &subItem = item.SubItems.AddNew();
630*f6dc9357SAndroid Build Coastguard Worker subItem.IsTag = false;
631*f6dc9357SAndroid Build Coastguard Worker subItem.Name = temp;
632*f6dc9357SAndroid Build Coastguard Worker }
633*f6dc9357SAndroid Build Coastguard Worker
634*f6dc9357SAndroid Build Coastguard Worker
AddTag_Time_2(CXmlItem & item,const FILETIME & ft)635*f6dc9357SAndroid Build Coastguard Worker static void AddTag_Time_2(CXmlItem &item, const FILETIME &ft)
636*f6dc9357SAndroid Build Coastguard Worker {
637*f6dc9357SAndroid Build Coastguard Worker AddTag_Hex(item.SubItems.AddNew(), "HIGHPART", ft.dwHighDateTime);
638*f6dc9357SAndroid Build Coastguard Worker AddTag_Hex(item.SubItems.AddNew(), "LOWPART", ft.dwLowDateTime);
639*f6dc9357SAndroid Build Coastguard Worker }
640*f6dc9357SAndroid Build Coastguard Worker
641*f6dc9357SAndroid Build Coastguard Worker
AddTag_Time(CXmlItem & parentItem,const char * name,const FILETIME & ft)642*f6dc9357SAndroid Build Coastguard Worker static void AddTag_Time(CXmlItem &parentItem, const char *name, const FILETIME &ft)
643*f6dc9357SAndroid Build Coastguard Worker {
644*f6dc9357SAndroid Build Coastguard Worker AddTag_Time_2(AddUniqueTag(parentItem, name), ft);
645*f6dc9357SAndroid Build Coastguard Worker }
646*f6dc9357SAndroid Build Coastguard Worker
647*f6dc9357SAndroid Build Coastguard Worker
AddTag_String_IfEmpty(CXmlItem & parentItem,const char * name,const char * value)648*f6dc9357SAndroid Build Coastguard Worker static void AddTag_String_IfEmpty(CXmlItem &parentItem, const char *name, const char *value)
649*f6dc9357SAndroid Build Coastguard Worker {
650*f6dc9357SAndroid Build Coastguard Worker if (parentItem.FindSubTag(name) >= 0)
651*f6dc9357SAndroid Build Coastguard Worker return;
652*f6dc9357SAndroid Build Coastguard Worker CXmlItem &tag = parentItem.SubItems.AddNew();
653*f6dc9357SAndroid Build Coastguard Worker tag.IsTag = true;
654*f6dc9357SAndroid Build Coastguard Worker tag.Name = name;
655*f6dc9357SAndroid Build Coastguard Worker CXmlItem &subItem = tag.SubItems.AddNew();
656*f6dc9357SAndroid Build Coastguard Worker subItem.IsTag = false;
657*f6dc9357SAndroid Build Coastguard Worker subItem.Name = value;
658*f6dc9357SAndroid Build Coastguard Worker }
659*f6dc9357SAndroid Build Coastguard Worker
660*f6dc9357SAndroid Build Coastguard Worker
SetDefaultFields(bool useLZX)661*f6dc9357SAndroid Build Coastguard Worker void CHeader::SetDefaultFields(bool useLZX)
662*f6dc9357SAndroid Build Coastguard Worker {
663*f6dc9357SAndroid Build Coastguard Worker Version = k_Version_NonSolid;
664*f6dc9357SAndroid Build Coastguard Worker Flags = NHeaderFlags::kReparsePointFixup;
665*f6dc9357SAndroid Build Coastguard Worker ChunkSize = 0;
666*f6dc9357SAndroid Build Coastguard Worker if (useLZX)
667*f6dc9357SAndroid Build Coastguard Worker {
668*f6dc9357SAndroid Build Coastguard Worker Flags |= NHeaderFlags::kCompression | NHeaderFlags::kLZX;
669*f6dc9357SAndroid Build Coastguard Worker ChunkSize = kChunkSize;
670*f6dc9357SAndroid Build Coastguard Worker ChunkSizeBits = kChunkSizeBits;
671*f6dc9357SAndroid Build Coastguard Worker }
672*f6dc9357SAndroid Build Coastguard Worker MY_RAND_GEN(Guid, 16);
673*f6dc9357SAndroid Build Coastguard Worker PartNumber = 1;
674*f6dc9357SAndroid Build Coastguard Worker NumParts = 1;
675*f6dc9357SAndroid Build Coastguard Worker NumImages = 1;
676*f6dc9357SAndroid Build Coastguard Worker BootIndex = 0;
677*f6dc9357SAndroid Build Coastguard Worker OffsetResource.Clear();
678*f6dc9357SAndroid Build Coastguard Worker XmlResource.Clear();
679*f6dc9357SAndroid Build Coastguard Worker MetadataResource.Clear();
680*f6dc9357SAndroid Build Coastguard Worker IntegrityResource.Clear();
681*f6dc9357SAndroid Build Coastguard Worker }
682*f6dc9357SAndroid Build Coastguard Worker
683*f6dc9357SAndroid Build Coastguard Worker
AddTrees(CObjectVector<CDir> & trees,CObjectVector<CMetaItem> & metaItems,const CMetaItem & ri,int curTreeIndex)684*f6dc9357SAndroid Build Coastguard Worker static void AddTrees(CObjectVector<CDir> &trees, CObjectVector<CMetaItem> &metaItems, const CMetaItem &ri, int curTreeIndex)
685*f6dc9357SAndroid Build Coastguard Worker {
686*f6dc9357SAndroid Build Coastguard Worker while (curTreeIndex >= (int)trees.Size())
687*f6dc9357SAndroid Build Coastguard Worker trees.AddNew().Dirs.AddNew().MetaIndex = (int)metaItems.Add(ri);
688*f6dc9357SAndroid Build Coastguard Worker }
689*f6dc9357SAndroid Build Coastguard Worker
690*f6dc9357SAndroid Build Coastguard Worker
691*f6dc9357SAndroid Build Coastguard Worker #define IS_LETTER_CHAR(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
692*f6dc9357SAndroid Build Coastguard Worker
693*f6dc9357SAndroid Build Coastguard Worker
694*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::UpdateItems (ISequentialOutStream * outSeqStream,UInt32 numItems,IArchiveUpdateCallback * callback))695*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 numItems, IArchiveUpdateCallback *callback))
696*f6dc9357SAndroid Build Coastguard Worker {
697*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
698*f6dc9357SAndroid Build Coastguard Worker
699*f6dc9357SAndroid Build Coastguard Worker if (!IsUpdateSupported())
700*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
701*f6dc9357SAndroid Build Coastguard Worker
702*f6dc9357SAndroid Build Coastguard Worker bool isUpdate = (_volumes.Size() != 0);
703*f6dc9357SAndroid Build Coastguard Worker int defaultImageIndex = _defaultImageNumber - 1;
704*f6dc9357SAndroid Build Coastguard Worker bool showImageNumber;
705*f6dc9357SAndroid Build Coastguard Worker
706*f6dc9357SAndroid Build Coastguard Worker if (isUpdate)
707*f6dc9357SAndroid Build Coastguard Worker {
708*f6dc9357SAndroid Build Coastguard Worker showImageNumber = _showImageNumber;
709*f6dc9357SAndroid Build Coastguard Worker if (!showImageNumber)
710*f6dc9357SAndroid Build Coastguard Worker defaultImageIndex = _db.IndexOfUserImage;
711*f6dc9357SAndroid Build Coastguard Worker }
712*f6dc9357SAndroid Build Coastguard Worker else
713*f6dc9357SAndroid Build Coastguard Worker {
714*f6dc9357SAndroid Build Coastguard Worker showImageNumber = (_set_use_ShowImageNumber && _set_showImageNumber);
715*f6dc9357SAndroid Build Coastguard Worker if (!showImageNumber)
716*f6dc9357SAndroid Build Coastguard Worker defaultImageIndex = 0;
717*f6dc9357SAndroid Build Coastguard Worker }
718*f6dc9357SAndroid Build Coastguard Worker
719*f6dc9357SAndroid Build Coastguard Worker if (defaultImageIndex >= kNumImagesMaxUpdate)
720*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
721*f6dc9357SAndroid Build Coastguard Worker
722*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IOutStream> outStream;
723*f6dc9357SAndroid Build Coastguard Worker RINOK(outSeqStream->QueryInterface(IID_IOutStream, (void **)&outStream))
724*f6dc9357SAndroid Build Coastguard Worker if (!outStream)
725*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
726*f6dc9357SAndroid Build Coastguard Worker if (!callback)
727*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
728*f6dc9357SAndroid Build Coastguard Worker
729*f6dc9357SAndroid Build Coastguard Worker CDb db;
730*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CDir> trees;
731*f6dc9357SAndroid Build Coastguard Worker
732*f6dc9357SAndroid Build Coastguard Worker CMetaItem ri; // default DIR item
733*f6dc9357SAndroid Build Coastguard Worker FILETIME ftCur;
734*f6dc9357SAndroid Build Coastguard Worker NTime::GetCurUtcFileTime(ftCur);
735*f6dc9357SAndroid Build Coastguard Worker // ri.MTime = ri.ATime = ri.CTime = ftCur;
736*f6dc9357SAndroid Build Coastguard Worker ri.Attrib = FILE_ATTRIBUTE_DIRECTORY;
737*f6dc9357SAndroid Build Coastguard Worker ri.IsDir = true;
738*f6dc9357SAndroid Build Coastguard Worker
739*f6dc9357SAndroid Build Coastguard Worker
740*f6dc9357SAndroid Build Coastguard Worker // ---------- Detect changed images ----------
741*f6dc9357SAndroid Build Coastguard Worker
742*f6dc9357SAndroid Build Coastguard Worker unsigned i;
743*f6dc9357SAndroid Build Coastguard Worker CBoolVector isChangedImage;
744*f6dc9357SAndroid Build Coastguard Worker {
745*f6dc9357SAndroid Build Coastguard Worker CUIntVector numUnchangedItemsInImage;
746*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < _db.Images.Size(); i++)
747*f6dc9357SAndroid Build Coastguard Worker {
748*f6dc9357SAndroid Build Coastguard Worker numUnchangedItemsInImage.Add(0);
749*f6dc9357SAndroid Build Coastguard Worker isChangedImage.Add(false);
750*f6dc9357SAndroid Build Coastguard Worker }
751*f6dc9357SAndroid Build Coastguard Worker
752*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numItems; i++)
753*f6dc9357SAndroid Build Coastguard Worker {
754*f6dc9357SAndroid Build Coastguard Worker UInt32 indexInArchive;
755*f6dc9357SAndroid Build Coastguard Worker Int32 newData, newProps;
756*f6dc9357SAndroid Build Coastguard Worker RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive))
757*f6dc9357SAndroid Build Coastguard Worker if (newProps == 0)
758*f6dc9357SAndroid Build Coastguard Worker {
759*f6dc9357SAndroid Build Coastguard Worker if (indexInArchive >= _db.SortedItems.Size())
760*f6dc9357SAndroid Build Coastguard Worker continue;
761*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _db.Items[_db.SortedItems[indexInArchive]];
762*f6dc9357SAndroid Build Coastguard Worker if (newData == 0)
763*f6dc9357SAndroid Build Coastguard Worker {
764*f6dc9357SAndroid Build Coastguard Worker if (item.ImageIndex >= 0)
765*f6dc9357SAndroid Build Coastguard Worker numUnchangedItemsInImage[item.ImageIndex]++;
766*f6dc9357SAndroid Build Coastguard Worker }
767*f6dc9357SAndroid Build Coastguard Worker else
768*f6dc9357SAndroid Build Coastguard Worker {
769*f6dc9357SAndroid Build Coastguard Worker // oldProps & newData. Current version of 7-Zip doesn't use it
770*f6dc9357SAndroid Build Coastguard Worker if (item.ImageIndex >= 0)
771*f6dc9357SAndroid Build Coastguard Worker isChangedImage[item.ImageIndex] = true;
772*f6dc9357SAndroid Build Coastguard Worker }
773*f6dc9357SAndroid Build Coastguard Worker }
774*f6dc9357SAndroid Build Coastguard Worker else if (!showImageNumber)
775*f6dc9357SAndroid Build Coastguard Worker {
776*f6dc9357SAndroid Build Coastguard Worker if (defaultImageIndex >= 0 && defaultImageIndex < (int)isChangedImage.Size())
777*f6dc9357SAndroid Build Coastguard Worker isChangedImage[defaultImageIndex] = true;
778*f6dc9357SAndroid Build Coastguard Worker }
779*f6dc9357SAndroid Build Coastguard Worker else
780*f6dc9357SAndroid Build Coastguard Worker {
781*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
782*f6dc9357SAndroid Build Coastguard Worker RINOK(callback->GetProperty(i, kpidPath, &prop))
783*f6dc9357SAndroid Build Coastguard Worker
784*f6dc9357SAndroid Build Coastguard Worker if (prop.vt != VT_BSTR)
785*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
786*f6dc9357SAndroid Build Coastguard Worker const wchar_t *path = prop.bstrVal;
787*f6dc9357SAndroid Build Coastguard Worker if (!path)
788*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
789*f6dc9357SAndroid Build Coastguard Worker
790*f6dc9357SAndroid Build Coastguard Worker const wchar_t *end;
791*f6dc9357SAndroid Build Coastguard Worker UInt64 val = ConvertStringToUInt64(path, &end);
792*f6dc9357SAndroid Build Coastguard Worker if (end == path)
793*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
794*f6dc9357SAndroid Build Coastguard Worker if (val == 0 || val > kNumImagesMaxUpdate)
795*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
796*f6dc9357SAndroid Build Coastguard Worker wchar_t c = *end;
797*f6dc9357SAndroid Build Coastguard Worker if (c != 0 && c != ':' && c != L'/' && c != WCHAR_PATH_SEPARATOR)
798*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
799*f6dc9357SAndroid Build Coastguard Worker unsigned imageIndex = (unsigned)val - 1;
800*f6dc9357SAndroid Build Coastguard Worker if (imageIndex < _db.Images.Size())
801*f6dc9357SAndroid Build Coastguard Worker isChangedImage[imageIndex] = true;
802*f6dc9357SAndroid Build Coastguard Worker if (_defaultImageNumber > 0 && val != (unsigned)_defaultImageNumber)
803*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
804*f6dc9357SAndroid Build Coastguard Worker }
805*f6dc9357SAndroid Build Coastguard Worker }
806*f6dc9357SAndroid Build Coastguard Worker
807*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < _db.Images.Size(); i++)
808*f6dc9357SAndroid Build Coastguard Worker if (!isChangedImage[i])
809*f6dc9357SAndroid Build Coastguard Worker isChangedImage[i] = _db.GetNumUserItemsInImage(i) != numUnchangedItemsInImage[i];
810*f6dc9357SAndroid Build Coastguard Worker }
811*f6dc9357SAndroid Build Coastguard Worker
812*f6dc9357SAndroid Build Coastguard Worker if (defaultImageIndex >= 0)
813*f6dc9357SAndroid Build Coastguard Worker {
814*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < _db.Images.Size(); i++)
815*f6dc9357SAndroid Build Coastguard Worker if ((int)i != defaultImageIndex)
816*f6dc9357SAndroid Build Coastguard Worker isChangedImage[i] = false;
817*f6dc9357SAndroid Build Coastguard Worker }
818*f6dc9357SAndroid Build Coastguard Worker
819*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IArchiveGetRawProps> getRawProps;
820*f6dc9357SAndroid Build Coastguard Worker callback->QueryInterface(IID_IArchiveGetRawProps, (void **)&getRawProps);
821*f6dc9357SAndroid Build Coastguard Worker
822*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IArchiveGetRootProps> getRootProps;
823*f6dc9357SAndroid Build Coastguard Worker callback->QueryInterface(IID_IArchiveGetRootProps, (void **)&getRootProps);
824*f6dc9357SAndroid Build Coastguard Worker
825*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CUniqBlocks> secureBlocks;
826*f6dc9357SAndroid Build Coastguard Worker
827*f6dc9357SAndroid Build Coastguard Worker if (!showImageNumber && (getRootProps || isUpdate) &&
828*f6dc9357SAndroid Build Coastguard Worker (
829*f6dc9357SAndroid Build Coastguard Worker defaultImageIndex >= (int)isChangedImage.Size()
830*f6dc9357SAndroid Build Coastguard Worker || defaultImageIndex < 0 // test it
831*f6dc9357SAndroid Build Coastguard Worker || isChangedImage[defaultImageIndex]
832*f6dc9357SAndroid Build Coastguard Worker ))
833*f6dc9357SAndroid Build Coastguard Worker {
834*f6dc9357SAndroid Build Coastguard Worker // Fill Root Item: Metadata and security
835*f6dc9357SAndroid Build Coastguard Worker CMetaItem rootItem = ri;
836*f6dc9357SAndroid Build Coastguard Worker {
837*f6dc9357SAndroid Build Coastguard Worker const void *data = NULL;
838*f6dc9357SAndroid Build Coastguard Worker UInt32 dataSize = 0;
839*f6dc9357SAndroid Build Coastguard Worker UInt32 propType = 0;
840*f6dc9357SAndroid Build Coastguard Worker if (getRootProps)
841*f6dc9357SAndroid Build Coastguard Worker {
842*f6dc9357SAndroid Build Coastguard Worker RINOK(getRootProps->GetRootRawProp(kpidNtSecure, &data, &dataSize, &propType))
843*f6dc9357SAndroid Build Coastguard Worker }
844*f6dc9357SAndroid Build Coastguard Worker if (dataSize == 0 && isUpdate)
845*f6dc9357SAndroid Build Coastguard Worker {
846*f6dc9357SAndroid Build Coastguard Worker RINOK(GetRootRawProp(kpidNtSecure, &data, &dataSize, &propType))
847*f6dc9357SAndroid Build Coastguard Worker }
848*f6dc9357SAndroid Build Coastguard Worker if (dataSize != 0)
849*f6dc9357SAndroid Build Coastguard Worker {
850*f6dc9357SAndroid Build Coastguard Worker if (propType != NPropDataType::kRaw)
851*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
852*f6dc9357SAndroid Build Coastguard Worker while (defaultImageIndex >= (int)secureBlocks.Size())
853*f6dc9357SAndroid Build Coastguard Worker secureBlocks.AddNew();
854*f6dc9357SAndroid Build Coastguard Worker CUniqBlocks &secUniqBlocks = secureBlocks[defaultImageIndex];
855*f6dc9357SAndroid Build Coastguard Worker rootItem.SecurityId = (int)secUniqBlocks.AddUniq((const Byte *)data, dataSize);
856*f6dc9357SAndroid Build Coastguard Worker }
857*f6dc9357SAndroid Build Coastguard Worker }
858*f6dc9357SAndroid Build Coastguard Worker
859*f6dc9357SAndroid Build Coastguard Worker IArchiveGetRootProps *thisGetRoot = isUpdate ? this : NULL;
860*f6dc9357SAndroid Build Coastguard Worker
861*f6dc9357SAndroid Build Coastguard Worker if (_timeOptions.Write_CTime.Val) RINOK(GetRootTime(getRootProps, thisGetRoot, kpidCTime, rootItem.CTime))
862*f6dc9357SAndroid Build Coastguard Worker if (_timeOptions.Write_ATime.Val) RINOK(GetRootTime(getRootProps, thisGetRoot, kpidATime, rootItem.ATime))
863*f6dc9357SAndroid Build Coastguard Worker if (_timeOptions.Write_MTime.Val) RINOK(GetRootTime(getRootProps, thisGetRoot, kpidMTime, rootItem.MTime))
864*f6dc9357SAndroid Build Coastguard Worker
865*f6dc9357SAndroid Build Coastguard Worker {
866*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
867*f6dc9357SAndroid Build Coastguard Worker if (getRootProps)
868*f6dc9357SAndroid Build Coastguard Worker {
869*f6dc9357SAndroid Build Coastguard Worker RINOK(getRootProps->GetRootProp(kpidAttrib, &prop))
870*f6dc9357SAndroid Build Coastguard Worker if (prop.vt == VT_UI4)
871*f6dc9357SAndroid Build Coastguard Worker rootItem.Attrib = prop.ulVal;
872*f6dc9357SAndroid Build Coastguard Worker else if (prop.vt != VT_EMPTY)
873*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
874*f6dc9357SAndroid Build Coastguard Worker }
875*f6dc9357SAndroid Build Coastguard Worker if (prop.vt == VT_EMPTY && thisGetRoot)
876*f6dc9357SAndroid Build Coastguard Worker {
877*f6dc9357SAndroid Build Coastguard Worker RINOK(GetRootProp(kpidAttrib, &prop))
878*f6dc9357SAndroid Build Coastguard Worker if (prop.vt == VT_UI4)
879*f6dc9357SAndroid Build Coastguard Worker rootItem.Attrib = prop.ulVal;
880*f6dc9357SAndroid Build Coastguard Worker else if (prop.vt != VT_EMPTY)
881*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
882*f6dc9357SAndroid Build Coastguard Worker }
883*f6dc9357SAndroid Build Coastguard Worker rootItem.Attrib |= FILE_ATTRIBUTE_DIRECTORY;
884*f6dc9357SAndroid Build Coastguard Worker }
885*f6dc9357SAndroid Build Coastguard Worker
886*f6dc9357SAndroid Build Coastguard Worker AddTrees(trees, db.MetaItems, ri, defaultImageIndex);
887*f6dc9357SAndroid Build Coastguard Worker db.MetaItems[trees[defaultImageIndex].Dirs[0].MetaIndex] = rootItem;
888*f6dc9357SAndroid Build Coastguard Worker }
889*f6dc9357SAndroid Build Coastguard Worker
890*f6dc9357SAndroid Build Coastguard Worker // ---------- Request Metadata for changed items ----------
891*f6dc9357SAndroid Build Coastguard Worker
892*f6dc9357SAndroid Build Coastguard Worker UString fileName;
893*f6dc9357SAndroid Build Coastguard Worker
894*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numItems; i++)
895*f6dc9357SAndroid Build Coastguard Worker {
896*f6dc9357SAndroid Build Coastguard Worker CUpdateItem ui;
897*f6dc9357SAndroid Build Coastguard Worker UInt32 indexInArchive;
898*f6dc9357SAndroid Build Coastguard Worker Int32 newData, newProps;
899*f6dc9357SAndroid Build Coastguard Worker RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive))
900*f6dc9357SAndroid Build Coastguard Worker
901*f6dc9357SAndroid Build Coastguard Worker if (newData == 0 || newProps == 0)
902*f6dc9357SAndroid Build Coastguard Worker {
903*f6dc9357SAndroid Build Coastguard Worker if (indexInArchive >= _db.SortedItems.Size())
904*f6dc9357SAndroid Build Coastguard Worker continue;
905*f6dc9357SAndroid Build Coastguard Worker
906*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _db.Items[_db.SortedItems[indexInArchive]];
907*f6dc9357SAndroid Build Coastguard Worker
908*f6dc9357SAndroid Build Coastguard Worker if (item.ImageIndex >= 0)
909*f6dc9357SAndroid Build Coastguard Worker {
910*f6dc9357SAndroid Build Coastguard Worker if (!isChangedImage[item.ImageIndex])
911*f6dc9357SAndroid Build Coastguard Worker {
912*f6dc9357SAndroid Build Coastguard Worker if (newData == 0 && newProps == 0)
913*f6dc9357SAndroid Build Coastguard Worker continue;
914*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
915*f6dc9357SAndroid Build Coastguard Worker }
916*f6dc9357SAndroid Build Coastguard Worker }
917*f6dc9357SAndroid Build Coastguard Worker else
918*f6dc9357SAndroid Build Coastguard Worker {
919*f6dc9357SAndroid Build Coastguard Worker // if deleted item was not renamed, we just skip it
920*f6dc9357SAndroid Build Coastguard Worker if (newProps == 0)
921*f6dc9357SAndroid Build Coastguard Worker continue;
922*f6dc9357SAndroid Build Coastguard Worker if (item.StreamIndex >= 0)
923*f6dc9357SAndroid Build Coastguard Worker {
924*f6dc9357SAndroid Build Coastguard Worker // we don't support property change for SolidBig streams
925*f6dc9357SAndroid Build Coastguard Worker if (_db.DataStreams[item.StreamIndex].Resource.IsSolidBig())
926*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
927*f6dc9357SAndroid Build Coastguard Worker }
928*f6dc9357SAndroid Build Coastguard Worker }
929*f6dc9357SAndroid Build Coastguard Worker
930*f6dc9357SAndroid Build Coastguard Worker if (newData == 0)
931*f6dc9357SAndroid Build Coastguard Worker ui.InArcIndex = (Int32)indexInArchive;
932*f6dc9357SAndroid Build Coastguard Worker }
933*f6dc9357SAndroid Build Coastguard Worker
934*f6dc9357SAndroid Build Coastguard Worker // we set arcIndex only if we must use old props
935*f6dc9357SAndroid Build Coastguard Worker const Int32 arcIndex = (newProps ? -1 : (Int32)indexInArchive);
936*f6dc9357SAndroid Build Coastguard Worker
937*f6dc9357SAndroid Build Coastguard Worker bool isDir = false;
938*f6dc9357SAndroid Build Coastguard Worker {
939*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
940*f6dc9357SAndroid Build Coastguard Worker RINOK(GetOutProperty(callback, i, arcIndex, kpidIsDir, &prop))
941*f6dc9357SAndroid Build Coastguard Worker if (prop.vt == VT_BOOL)
942*f6dc9357SAndroid Build Coastguard Worker isDir = (prop.boolVal != VARIANT_FALSE);
943*f6dc9357SAndroid Build Coastguard Worker else if (prop.vt != VT_EMPTY)
944*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
945*f6dc9357SAndroid Build Coastguard Worker }
946*f6dc9357SAndroid Build Coastguard Worker
947*f6dc9357SAndroid Build Coastguard Worker bool isAltStream = false;
948*f6dc9357SAndroid Build Coastguard Worker {
949*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
950*f6dc9357SAndroid Build Coastguard Worker RINOK(GetOutProperty(callback, i, arcIndex, kpidIsAltStream, &prop))
951*f6dc9357SAndroid Build Coastguard Worker if (prop.vt == VT_BOOL)
952*f6dc9357SAndroid Build Coastguard Worker isAltStream = (prop.boolVal != VARIANT_FALSE);
953*f6dc9357SAndroid Build Coastguard Worker else if (prop.vt != VT_EMPTY)
954*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
955*f6dc9357SAndroid Build Coastguard Worker }
956*f6dc9357SAndroid Build Coastguard Worker
957*f6dc9357SAndroid Build Coastguard Worker if (isDir && isAltStream)
958*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
959*f6dc9357SAndroid Build Coastguard Worker
960*f6dc9357SAndroid Build Coastguard Worker UInt64 size = 0;
961*f6dc9357SAndroid Build Coastguard Worker UInt64 iNode = 0;
962*f6dc9357SAndroid Build Coastguard Worker
963*f6dc9357SAndroid Build Coastguard Worker if (!isDir)
964*f6dc9357SAndroid Build Coastguard Worker {
965*f6dc9357SAndroid Build Coastguard Worker if (!newData)
966*f6dc9357SAndroid Build Coastguard Worker {
967*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
968*f6dc9357SAndroid Build Coastguard Worker GetProperty(indexInArchive, kpidINode, &prop);
969*f6dc9357SAndroid Build Coastguard Worker if (prop.vt == VT_UI8)
970*f6dc9357SAndroid Build Coastguard Worker iNode = prop.uhVal.QuadPart;
971*f6dc9357SAndroid Build Coastguard Worker }
972*f6dc9357SAndroid Build Coastguard Worker
973*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
974*f6dc9357SAndroid Build Coastguard Worker
975*f6dc9357SAndroid Build Coastguard Worker if (newData)
976*f6dc9357SAndroid Build Coastguard Worker {
977*f6dc9357SAndroid Build Coastguard Worker RINOK(callback->GetProperty(i, kpidSize, &prop))
978*f6dc9357SAndroid Build Coastguard Worker }
979*f6dc9357SAndroid Build Coastguard Worker else
980*f6dc9357SAndroid Build Coastguard Worker {
981*f6dc9357SAndroid Build Coastguard Worker RINOK(GetProperty(indexInArchive, kpidSize, &prop))
982*f6dc9357SAndroid Build Coastguard Worker }
983*f6dc9357SAndroid Build Coastguard Worker
984*f6dc9357SAndroid Build Coastguard Worker if (prop.vt == VT_UI8)
985*f6dc9357SAndroid Build Coastguard Worker size = prop.uhVal.QuadPart;
986*f6dc9357SAndroid Build Coastguard Worker else if (prop.vt != VT_EMPTY)
987*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
988*f6dc9357SAndroid Build Coastguard Worker }
989*f6dc9357SAndroid Build Coastguard Worker
990*f6dc9357SAndroid Build Coastguard Worker {
991*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant propPath;
992*f6dc9357SAndroid Build Coastguard Worker const wchar_t *path = NULL;
993*f6dc9357SAndroid Build Coastguard Worker RINOK(GetOutProperty(callback, i, arcIndex, kpidPath, &propPath))
994*f6dc9357SAndroid Build Coastguard Worker if (propPath.vt == VT_BSTR)
995*f6dc9357SAndroid Build Coastguard Worker path = propPath.bstrVal;
996*f6dc9357SAndroid Build Coastguard Worker else if (propPath.vt != VT_EMPTY)
997*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
998*f6dc9357SAndroid Build Coastguard Worker
999*f6dc9357SAndroid Build Coastguard Worker if (!path)
1000*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1001*f6dc9357SAndroid Build Coastguard Worker
1002*f6dc9357SAndroid Build Coastguard Worker CDir *curItem = NULL;
1003*f6dc9357SAndroid Build Coastguard Worker bool isRootImageDir = false;
1004*f6dc9357SAndroid Build Coastguard Worker fileName.Empty();
1005*f6dc9357SAndroid Build Coastguard Worker
1006*f6dc9357SAndroid Build Coastguard Worker int imageIndex;
1007*f6dc9357SAndroid Build Coastguard Worker
1008*f6dc9357SAndroid Build Coastguard Worker if (!showImageNumber)
1009*f6dc9357SAndroid Build Coastguard Worker {
1010*f6dc9357SAndroid Build Coastguard Worker imageIndex = defaultImageIndex;
1011*f6dc9357SAndroid Build Coastguard Worker AddTrees(trees, db.MetaItems, ri, imageIndex);
1012*f6dc9357SAndroid Build Coastguard Worker curItem = &trees[imageIndex].Dirs[0];
1013*f6dc9357SAndroid Build Coastguard Worker }
1014*f6dc9357SAndroid Build Coastguard Worker else
1015*f6dc9357SAndroid Build Coastguard Worker {
1016*f6dc9357SAndroid Build Coastguard Worker const wchar_t *end;
1017*f6dc9357SAndroid Build Coastguard Worker UInt64 val = ConvertStringToUInt64(path, &end);
1018*f6dc9357SAndroid Build Coastguard Worker if (end == path)
1019*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1020*f6dc9357SAndroid Build Coastguard Worker if (val == 0 || val > kNumImagesMaxUpdate)
1021*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1022*f6dc9357SAndroid Build Coastguard Worker
1023*f6dc9357SAndroid Build Coastguard Worker imageIndex = (int)val - 1;
1024*f6dc9357SAndroid Build Coastguard Worker if (imageIndex < (int)isChangedImage.Size())
1025*f6dc9357SAndroid Build Coastguard Worker if (!isChangedImage[imageIndex])
1026*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
1027*f6dc9357SAndroid Build Coastguard Worker
1028*f6dc9357SAndroid Build Coastguard Worker AddTrees(trees, db.MetaItems, ri, imageIndex);
1029*f6dc9357SAndroid Build Coastguard Worker curItem = &trees[imageIndex].Dirs[0];
1030*f6dc9357SAndroid Build Coastguard Worker wchar_t c = *end;
1031*f6dc9357SAndroid Build Coastguard Worker
1032*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
1033*f6dc9357SAndroid Build Coastguard Worker {
1034*f6dc9357SAndroid Build Coastguard Worker if (!isDir || isAltStream)
1035*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1036*f6dc9357SAndroid Build Coastguard Worker ui.MetaIndex = curItem->MetaIndex;
1037*f6dc9357SAndroid Build Coastguard Worker isRootImageDir = true;
1038*f6dc9357SAndroid Build Coastguard Worker }
1039*f6dc9357SAndroid Build Coastguard Worker else if (c == ':')
1040*f6dc9357SAndroid Build Coastguard Worker {
1041*f6dc9357SAndroid Build Coastguard Worker if (isDir || !isAltStream)
1042*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1043*f6dc9357SAndroid Build Coastguard Worker ui.MetaIndex = curItem->MetaIndex;
1044*f6dc9357SAndroid Build Coastguard Worker CAltStream ss;
1045*f6dc9357SAndroid Build Coastguard Worker ss.Size = size;
1046*f6dc9357SAndroid Build Coastguard Worker ss.Name = end + 1;
1047*f6dc9357SAndroid Build Coastguard Worker ss.UpdateIndex = (int)db.UpdateItems.Size();
1048*f6dc9357SAndroid Build Coastguard Worker ui.AltStreamIndex = (int)db.MetaItems[ui.MetaIndex].AltStreams.Add(ss);
1049*f6dc9357SAndroid Build Coastguard Worker }
1050*f6dc9357SAndroid Build Coastguard Worker else if (c == WCHAR_PATH_SEPARATOR || c == L'/')
1051*f6dc9357SAndroid Build Coastguard Worker {
1052*f6dc9357SAndroid Build Coastguard Worker path = end + 1;
1053*f6dc9357SAndroid Build Coastguard Worker if (*path == 0)
1054*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1055*f6dc9357SAndroid Build Coastguard Worker }
1056*f6dc9357SAndroid Build Coastguard Worker else
1057*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1058*f6dc9357SAndroid Build Coastguard Worker }
1059*f6dc9357SAndroid Build Coastguard Worker
1060*f6dc9357SAndroid Build Coastguard Worker if (ui.MetaIndex < 0)
1061*f6dc9357SAndroid Build Coastguard Worker {
1062*f6dc9357SAndroid Build Coastguard Worker for (;;)
1063*f6dc9357SAndroid Build Coastguard Worker {
1064*f6dc9357SAndroid Build Coastguard Worker const wchar_t c = *path++;
1065*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
1066*f6dc9357SAndroid Build Coastguard Worker break;
1067*f6dc9357SAndroid Build Coastguard Worker if (c == WCHAR_PATH_SEPARATOR || c == L'/')
1068*f6dc9357SAndroid Build Coastguard Worker {
1069*f6dc9357SAndroid Build Coastguard Worker unsigned indexOfDir;
1070*f6dc9357SAndroid Build Coastguard Worker if (!curItem->FindDir(db.MetaItems, fileName, indexOfDir))
1071*f6dc9357SAndroid Build Coastguard Worker {
1072*f6dc9357SAndroid Build Coastguard Worker CDir &dir = curItem->Dirs.InsertNew(indexOfDir);
1073*f6dc9357SAndroid Build Coastguard Worker dir.MetaIndex = (int)db.MetaItems.Add(ri);
1074*f6dc9357SAndroid Build Coastguard Worker db.MetaItems.Back().Name = fileName;
1075*f6dc9357SAndroid Build Coastguard Worker }
1076*f6dc9357SAndroid Build Coastguard Worker curItem = &curItem->Dirs[indexOfDir];
1077*f6dc9357SAndroid Build Coastguard Worker fileName.Empty();
1078*f6dc9357SAndroid Build Coastguard Worker }
1079*f6dc9357SAndroid Build Coastguard Worker else
1080*f6dc9357SAndroid Build Coastguard Worker {
1081*f6dc9357SAndroid Build Coastguard Worker /*
1082*f6dc9357SAndroid Build Coastguard Worker #if WCHAR_MAX > 0xffff
1083*f6dc9357SAndroid Build Coastguard Worker if (c >= 0x10000)
1084*f6dc9357SAndroid Build Coastguard Worker {
1085*f6dc9357SAndroid Build Coastguard Worker c -= 0x10000;
1086*f6dc9357SAndroid Build Coastguard Worker
1087*f6dc9357SAndroid Build Coastguard Worker if (c < (1 << 20))
1088*f6dc9357SAndroid Build Coastguard Worker {
1089*f6dc9357SAndroid Build Coastguard Worker wchar_t c0 = 0xd800 + ((c >> 10) & 0x3FF);
1090*f6dc9357SAndroid Build Coastguard Worker fileName += c0;
1091*f6dc9357SAndroid Build Coastguard Worker c = 0xdc00 + (c & 0x3FF);
1092*f6dc9357SAndroid Build Coastguard Worker }
1093*f6dc9357SAndroid Build Coastguard Worker else
1094*f6dc9357SAndroid Build Coastguard Worker c = '_'; // we change character unsupported by UTF16
1095*f6dc9357SAndroid Build Coastguard Worker }
1096*f6dc9357SAndroid Build Coastguard Worker #endif
1097*f6dc9357SAndroid Build Coastguard Worker */
1098*f6dc9357SAndroid Build Coastguard Worker
1099*f6dc9357SAndroid Build Coastguard Worker fileName += c;
1100*f6dc9357SAndroid Build Coastguard Worker }
1101*f6dc9357SAndroid Build Coastguard Worker }
1102*f6dc9357SAndroid Build Coastguard Worker
1103*f6dc9357SAndroid Build Coastguard Worker if (isAltStream)
1104*f6dc9357SAndroid Build Coastguard Worker {
1105*f6dc9357SAndroid Build Coastguard Worker int colonPos = fileName.Find(L':');
1106*f6dc9357SAndroid Build Coastguard Worker if (colonPos < 0)
1107*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1108*f6dc9357SAndroid Build Coastguard Worker
1109*f6dc9357SAndroid Build Coastguard Worker // we want to support cases of c::substream, where c: is drive name
1110*f6dc9357SAndroid Build Coastguard Worker if (colonPos == 1 && fileName[2] == L':' && IS_LETTER_CHAR(fileName[0]))
1111*f6dc9357SAndroid Build Coastguard Worker colonPos = 2;
1112*f6dc9357SAndroid Build Coastguard Worker const UString mainName = fileName.Left((unsigned)colonPos);
1113*f6dc9357SAndroid Build Coastguard Worker unsigned indexOfDir;
1114*f6dc9357SAndroid Build Coastguard Worker
1115*f6dc9357SAndroid Build Coastguard Worker if (mainName.IsEmpty())
1116*f6dc9357SAndroid Build Coastguard Worker ui.MetaIndex = curItem->MetaIndex;
1117*f6dc9357SAndroid Build Coastguard Worker else if (curItem->FindDir(db.MetaItems, mainName, indexOfDir))
1118*f6dc9357SAndroid Build Coastguard Worker ui.MetaIndex = curItem->Dirs[indexOfDir].MetaIndex;
1119*f6dc9357SAndroid Build Coastguard Worker else
1120*f6dc9357SAndroid Build Coastguard Worker {
1121*f6dc9357SAndroid Build Coastguard Worker for (int j = (int)curItem->Files.Size() - 1; j >= 0; j--)
1122*f6dc9357SAndroid Build Coastguard Worker {
1123*f6dc9357SAndroid Build Coastguard Worker const unsigned metaIndex = curItem->Files[j];
1124*f6dc9357SAndroid Build Coastguard Worker const CMetaItem &mi = db.MetaItems[metaIndex];
1125*f6dc9357SAndroid Build Coastguard Worker if (CompareFileNames(mainName, mi.Name) == 0)
1126*f6dc9357SAndroid Build Coastguard Worker {
1127*f6dc9357SAndroid Build Coastguard Worker ui.MetaIndex = (int)metaIndex;
1128*f6dc9357SAndroid Build Coastguard Worker break;
1129*f6dc9357SAndroid Build Coastguard Worker }
1130*f6dc9357SAndroid Build Coastguard Worker }
1131*f6dc9357SAndroid Build Coastguard Worker }
1132*f6dc9357SAndroid Build Coastguard Worker
1133*f6dc9357SAndroid Build Coastguard Worker if (ui.MetaIndex >= 0)
1134*f6dc9357SAndroid Build Coastguard Worker {
1135*f6dc9357SAndroid Build Coastguard Worker CAltStream ss;
1136*f6dc9357SAndroid Build Coastguard Worker ss.Size = size;
1137*f6dc9357SAndroid Build Coastguard Worker ss.Name = fileName.Ptr(colonPos + 1);
1138*f6dc9357SAndroid Build Coastguard Worker ss.UpdateIndex = (int)db.UpdateItems.Size();
1139*f6dc9357SAndroid Build Coastguard Worker ui.AltStreamIndex = (int)db.MetaItems[ui.MetaIndex].AltStreams.Add(ss);
1140*f6dc9357SAndroid Build Coastguard Worker }
1141*f6dc9357SAndroid Build Coastguard Worker }
1142*f6dc9357SAndroid Build Coastguard Worker }
1143*f6dc9357SAndroid Build Coastguard Worker
1144*f6dc9357SAndroid Build Coastguard Worker
1145*f6dc9357SAndroid Build Coastguard Worker if (ui.MetaIndex < 0 || isRootImageDir)
1146*f6dc9357SAndroid Build Coastguard Worker {
1147*f6dc9357SAndroid Build Coastguard Worker if (!isRootImageDir)
1148*f6dc9357SAndroid Build Coastguard Worker {
1149*f6dc9357SAndroid Build Coastguard Worker ui.MetaIndex = (int)db.MetaItems.Size();
1150*f6dc9357SAndroid Build Coastguard Worker db.MetaItems.AddNew();
1151*f6dc9357SAndroid Build Coastguard Worker }
1152*f6dc9357SAndroid Build Coastguard Worker
1153*f6dc9357SAndroid Build Coastguard Worker CMetaItem &mi = db.MetaItems[ui.MetaIndex];
1154*f6dc9357SAndroid Build Coastguard Worker mi.Size = size;
1155*f6dc9357SAndroid Build Coastguard Worker mi.IsDir = isDir;
1156*f6dc9357SAndroid Build Coastguard Worker mi.Name = fileName;
1157*f6dc9357SAndroid Build Coastguard Worker mi.UpdateIndex = (int)db.UpdateItems.Size();
1158*f6dc9357SAndroid Build Coastguard Worker {
1159*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
1160*f6dc9357SAndroid Build Coastguard Worker RINOK(GetOutProperty(callback, i, arcIndex, kpidAttrib, &prop))
1161*f6dc9357SAndroid Build Coastguard Worker if (prop.vt == VT_EMPTY)
1162*f6dc9357SAndroid Build Coastguard Worker mi.Attrib = 0;
1163*f6dc9357SAndroid Build Coastguard Worker else if (prop.vt == VT_UI4)
1164*f6dc9357SAndroid Build Coastguard Worker mi.Attrib = prop.ulVal;
1165*f6dc9357SAndroid Build Coastguard Worker else
1166*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1167*f6dc9357SAndroid Build Coastguard Worker if (isDir)
1168*f6dc9357SAndroid Build Coastguard Worker mi.Attrib |= FILE_ATTRIBUTE_DIRECTORY;
1169*f6dc9357SAndroid Build Coastguard Worker }
1170*f6dc9357SAndroid Build Coastguard Worker
1171*f6dc9357SAndroid Build Coastguard Worker if (arcIndex != -1 || _timeOptions.Write_CTime.Val)
1172*f6dc9357SAndroid Build Coastguard Worker RINOK(GetTime(callback, i, arcIndex, kpidCTime, mi.CTime))
1173*f6dc9357SAndroid Build Coastguard Worker if (arcIndex != -1 || _timeOptions.Write_ATime.Val)
1174*f6dc9357SAndroid Build Coastguard Worker RINOK(GetTime(callback, i, arcIndex, kpidATime, mi.ATime))
1175*f6dc9357SAndroid Build Coastguard Worker if (arcIndex != -1 || _timeOptions.Write_MTime.Val)
1176*f6dc9357SAndroid Build Coastguard Worker RINOK(GetTime(callback, i, arcIndex, kpidMTime, mi.MTime))
1177*f6dc9357SAndroid Build Coastguard Worker
1178*f6dc9357SAndroid Build Coastguard Worker {
1179*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
1180*f6dc9357SAndroid Build Coastguard Worker RINOK(GetOutProperty(callback, i, arcIndex, kpidShortName, &prop))
1181*f6dc9357SAndroid Build Coastguard Worker if (prop.vt == VT_BSTR)
1182*f6dc9357SAndroid Build Coastguard Worker mi.ShortName.SetFromBstr(prop.bstrVal);
1183*f6dc9357SAndroid Build Coastguard Worker else if (prop.vt != VT_EMPTY)
1184*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1185*f6dc9357SAndroid Build Coastguard Worker }
1186*f6dc9357SAndroid Build Coastguard Worker
1187*f6dc9357SAndroid Build Coastguard Worker while (imageIndex >= (int)secureBlocks.Size())
1188*f6dc9357SAndroid Build Coastguard Worker secureBlocks.AddNew();
1189*f6dc9357SAndroid Build Coastguard Worker
1190*f6dc9357SAndroid Build Coastguard Worker if (!isAltStream && (getRawProps || arcIndex >= 0))
1191*f6dc9357SAndroid Build Coastguard Worker {
1192*f6dc9357SAndroid Build Coastguard Worker CUniqBlocks &secUniqBlocks = secureBlocks[imageIndex];
1193*f6dc9357SAndroid Build Coastguard Worker const void *data;
1194*f6dc9357SAndroid Build Coastguard Worker UInt32 dataSize;
1195*f6dc9357SAndroid Build Coastguard Worker UInt32 propType;
1196*f6dc9357SAndroid Build Coastguard Worker
1197*f6dc9357SAndroid Build Coastguard Worker data = NULL;
1198*f6dc9357SAndroid Build Coastguard Worker dataSize = 0;
1199*f6dc9357SAndroid Build Coastguard Worker propType = 0;
1200*f6dc9357SAndroid Build Coastguard Worker
1201*f6dc9357SAndroid Build Coastguard Worker if (arcIndex >= 0)
1202*f6dc9357SAndroid Build Coastguard Worker {
1203*f6dc9357SAndroid Build Coastguard Worker GetRawProp((UInt32)arcIndex, kpidNtSecure, &data, &dataSize, &propType);
1204*f6dc9357SAndroid Build Coastguard Worker }
1205*f6dc9357SAndroid Build Coastguard Worker else
1206*f6dc9357SAndroid Build Coastguard Worker {
1207*f6dc9357SAndroid Build Coastguard Worker getRawProps->GetRawProp(i, kpidNtSecure, &data, &dataSize, &propType);
1208*f6dc9357SAndroid Build Coastguard Worker }
1209*f6dc9357SAndroid Build Coastguard Worker
1210*f6dc9357SAndroid Build Coastguard Worker if (dataSize != 0)
1211*f6dc9357SAndroid Build Coastguard Worker {
1212*f6dc9357SAndroid Build Coastguard Worker if (propType != NPropDataType::kRaw)
1213*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
1214*f6dc9357SAndroid Build Coastguard Worker mi.SecurityId = (int)secUniqBlocks.AddUniq((const Byte *)data, dataSize);
1215*f6dc9357SAndroid Build Coastguard Worker }
1216*f6dc9357SAndroid Build Coastguard Worker
1217*f6dc9357SAndroid Build Coastguard Worker data = NULL;
1218*f6dc9357SAndroid Build Coastguard Worker dataSize = 0;
1219*f6dc9357SAndroid Build Coastguard Worker propType = 0;
1220*f6dc9357SAndroid Build Coastguard Worker
1221*f6dc9357SAndroid Build Coastguard Worker if (arcIndex >= 0)
1222*f6dc9357SAndroid Build Coastguard Worker {
1223*f6dc9357SAndroid Build Coastguard Worker GetRawProp((UInt32)arcIndex, kpidNtReparse, &data, &dataSize, &propType);
1224*f6dc9357SAndroid Build Coastguard Worker }
1225*f6dc9357SAndroid Build Coastguard Worker else
1226*f6dc9357SAndroid Build Coastguard Worker {
1227*f6dc9357SAndroid Build Coastguard Worker getRawProps->GetRawProp(i, kpidNtReparse, &data, &dataSize, &propType);
1228*f6dc9357SAndroid Build Coastguard Worker }
1229*f6dc9357SAndroid Build Coastguard Worker
1230*f6dc9357SAndroid Build Coastguard Worker if (dataSize != 0)
1231*f6dc9357SAndroid Build Coastguard Worker {
1232*f6dc9357SAndroid Build Coastguard Worker if (propType != NPropDataType::kRaw)
1233*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
1234*f6dc9357SAndroid Build Coastguard Worker mi.Reparse.CopyFrom((const Byte *)data, dataSize);
1235*f6dc9357SAndroid Build Coastguard Worker }
1236*f6dc9357SAndroid Build Coastguard Worker }
1237*f6dc9357SAndroid Build Coastguard Worker
1238*f6dc9357SAndroid Build Coastguard Worker if (!isRootImageDir)
1239*f6dc9357SAndroid Build Coastguard Worker {
1240*f6dc9357SAndroid Build Coastguard Worker if (isDir)
1241*f6dc9357SAndroid Build Coastguard Worker {
1242*f6dc9357SAndroid Build Coastguard Worker unsigned indexOfDir;
1243*f6dc9357SAndroid Build Coastguard Worker if (curItem->FindDir(db.MetaItems, fileName, indexOfDir))
1244*f6dc9357SAndroid Build Coastguard Worker curItem->Dirs[indexOfDir].MetaIndex = ui.MetaIndex;
1245*f6dc9357SAndroid Build Coastguard Worker else
1246*f6dc9357SAndroid Build Coastguard Worker curItem->Dirs.InsertNew(indexOfDir).MetaIndex = ui.MetaIndex;
1247*f6dc9357SAndroid Build Coastguard Worker }
1248*f6dc9357SAndroid Build Coastguard Worker else
1249*f6dc9357SAndroid Build Coastguard Worker curItem->Files.Add((unsigned)ui.MetaIndex);
1250*f6dc9357SAndroid Build Coastguard Worker }
1251*f6dc9357SAndroid Build Coastguard Worker }
1252*f6dc9357SAndroid Build Coastguard Worker
1253*f6dc9357SAndroid Build Coastguard Worker }
1254*f6dc9357SAndroid Build Coastguard Worker
1255*f6dc9357SAndroid Build Coastguard Worker if (iNode != 0 && ui.MetaIndex >= 0 && ui.AltStreamIndex < 0)
1256*f6dc9357SAndroid Build Coastguard Worker db.MetaItems[ui.MetaIndex].FileID = iNode;
1257*f6dc9357SAndroid Build Coastguard Worker
1258*f6dc9357SAndroid Build Coastguard Worker ui.CallbackIndex = i;
1259*f6dc9357SAndroid Build Coastguard Worker db.UpdateItems.Add(ui);
1260*f6dc9357SAndroid Build Coastguard Worker }
1261*f6dc9357SAndroid Build Coastguard Worker
1262*f6dc9357SAndroid Build Coastguard Worker unsigned numNewImages = trees.Size();
1263*f6dc9357SAndroid Build Coastguard Worker for (i = numNewImages; i < isChangedImage.Size(); i++)
1264*f6dc9357SAndroid Build Coastguard Worker if (!isChangedImage[i])
1265*f6dc9357SAndroid Build Coastguard Worker numNewImages = i + 1;
1266*f6dc9357SAndroid Build Coastguard Worker
1267*f6dc9357SAndroid Build Coastguard Worker AddTrees(trees, db.MetaItems, ri, (int)numNewImages - 1);
1268*f6dc9357SAndroid Build Coastguard Worker
1269*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < trees.Size(); i++)
1270*f6dc9357SAndroid Build Coastguard Worker if (i >= isChangedImage.Size() || isChangedImage[i])
1271*f6dc9357SAndroid Build Coastguard Worker db.WriteOrderList(trees[i]);
1272*f6dc9357SAndroid Build Coastguard Worker
1273*f6dc9357SAndroid Build Coastguard Worker
1274*f6dc9357SAndroid Build Coastguard Worker UInt64 complexity = 0;
1275*f6dc9357SAndroid Build Coastguard Worker
1276*f6dc9357SAndroid Build Coastguard Worker unsigned numDataStreams = _db.DataStreams.Size();
1277*f6dc9357SAndroid Build Coastguard Worker CUIntArr streamsRefs(numDataStreams);
1278*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numDataStreams; i++)
1279*f6dc9357SAndroid Build Coastguard Worker streamsRefs[i] = 0;
1280*f6dc9357SAndroid Build Coastguard Worker
1281*f6dc9357SAndroid Build Coastguard Worker // ---------- Calculate Streams Refs Counts in unchanged images
1282*f6dc9357SAndroid Build Coastguard Worker
1283*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < _db.Images.Size(); i++)
1284*f6dc9357SAndroid Build Coastguard Worker {
1285*f6dc9357SAndroid Build Coastguard Worker if (isChangedImage[i])
1286*f6dc9357SAndroid Build Coastguard Worker continue;
1287*f6dc9357SAndroid Build Coastguard Worker complexity += _db.MetaStreams[i].Resource.PackSize;
1288*f6dc9357SAndroid Build Coastguard Worker const CImage &image = _db.Images[i];
1289*f6dc9357SAndroid Build Coastguard Worker unsigned endItem = image.StartItem + image.NumItems;
1290*f6dc9357SAndroid Build Coastguard Worker for (unsigned k = image.StartItem; k < endItem; k++)
1291*f6dc9357SAndroid Build Coastguard Worker {
1292*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _db.Items[k];
1293*f6dc9357SAndroid Build Coastguard Worker if (item.StreamIndex >= 0)
1294*f6dc9357SAndroid Build Coastguard Worker streamsRefs[(unsigned)item.StreamIndex]++;
1295*f6dc9357SAndroid Build Coastguard Worker }
1296*f6dc9357SAndroid Build Coastguard Worker }
1297*f6dc9357SAndroid Build Coastguard Worker
1298*f6dc9357SAndroid Build Coastguard Worker
1299*f6dc9357SAndroid Build Coastguard Worker // ---------- Update Streams Refs Counts in changed images
1300*f6dc9357SAndroid Build Coastguard Worker
1301*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < db.UpdateIndexes.Size(); i++)
1302*f6dc9357SAndroid Build Coastguard Worker {
1303*f6dc9357SAndroid Build Coastguard Worker const CUpdateItem &ui = db.UpdateItems[db.UpdateIndexes[i]];
1304*f6dc9357SAndroid Build Coastguard Worker
1305*f6dc9357SAndroid Build Coastguard Worker if (ui.InArcIndex >= 0)
1306*f6dc9357SAndroid Build Coastguard Worker {
1307*f6dc9357SAndroid Build Coastguard Worker if ((unsigned)ui.InArcIndex >= _db.SortedItems.Size())
1308*f6dc9357SAndroid Build Coastguard Worker continue;
1309*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _db.Items[_db.SortedItems[ui.InArcIndex]];
1310*f6dc9357SAndroid Build Coastguard Worker if (item.StreamIndex >= 0)
1311*f6dc9357SAndroid Build Coastguard Worker streamsRefs[(unsigned)item.StreamIndex]++;
1312*f6dc9357SAndroid Build Coastguard Worker }
1313*f6dc9357SAndroid Build Coastguard Worker else
1314*f6dc9357SAndroid Build Coastguard Worker {
1315*f6dc9357SAndroid Build Coastguard Worker const CMetaItem &mi = db.MetaItems[ui.MetaIndex];
1316*f6dc9357SAndroid Build Coastguard Worker UInt64 size;
1317*f6dc9357SAndroid Build Coastguard Worker if (ui.AltStreamIndex < 0)
1318*f6dc9357SAndroid Build Coastguard Worker size = mi.Size;
1319*f6dc9357SAndroid Build Coastguard Worker else
1320*f6dc9357SAndroid Build Coastguard Worker size = mi.AltStreams[ui.AltStreamIndex].Size;
1321*f6dc9357SAndroid Build Coastguard Worker complexity += size;
1322*f6dc9357SAndroid Build Coastguard Worker }
1323*f6dc9357SAndroid Build Coastguard Worker }
1324*f6dc9357SAndroid Build Coastguard Worker
1325*f6dc9357SAndroid Build Coastguard Worker // Clear ref counts for SolidBig streams
1326*f6dc9357SAndroid Build Coastguard Worker
1327*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < _db.DataStreams.Size(); i++)
1328*f6dc9357SAndroid Build Coastguard Worker if (_db.DataStreams[i].Resource.IsSolidBig())
1329*f6dc9357SAndroid Build Coastguard Worker streamsRefs[i] = 0;
1330*f6dc9357SAndroid Build Coastguard Worker
1331*f6dc9357SAndroid Build Coastguard Worker // Set ref counts for SolidBig streams
1332*f6dc9357SAndroid Build Coastguard Worker
1333*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < _db.DataStreams.Size(); i++)
1334*f6dc9357SAndroid Build Coastguard Worker if (streamsRefs[i] != 0)
1335*f6dc9357SAndroid Build Coastguard Worker {
1336*f6dc9357SAndroid Build Coastguard Worker const CResource &rs = _db.DataStreams[i].Resource;
1337*f6dc9357SAndroid Build Coastguard Worker if (rs.IsSolidSmall())
1338*f6dc9357SAndroid Build Coastguard Worker streamsRefs[_db.Solids[rs.SolidIndex].StreamIndex] = 1;
1339*f6dc9357SAndroid Build Coastguard Worker }
1340*f6dc9357SAndroid Build Coastguard Worker
1341*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < _db.DataStreams.Size(); i++)
1342*f6dc9357SAndroid Build Coastguard Worker if (streamsRefs[i] != 0)
1343*f6dc9357SAndroid Build Coastguard Worker {
1344*f6dc9357SAndroid Build Coastguard Worker const CResource &rs = _db.DataStreams[i].Resource;
1345*f6dc9357SAndroid Build Coastguard Worker if (!rs.IsSolidSmall())
1346*f6dc9357SAndroid Build Coastguard Worker complexity += rs.PackSize;
1347*f6dc9357SAndroid Build Coastguard Worker }
1348*f6dc9357SAndroid Build Coastguard Worker
1349*f6dc9357SAndroid Build Coastguard Worker RINOK(callback->SetTotal(complexity))
1350*f6dc9357SAndroid Build Coastguard Worker UInt64 totalComplexity = complexity;
1351*f6dc9357SAndroid Build Coastguard Worker
1352*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1353*f6dc9357SAndroid Build Coastguard Worker lps->Init(callback, true);
1354*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
1355*f6dc9357SAndroid Build Coastguard Worker
1356*f6dc9357SAndroid Build Coastguard Worker complexity = 0;
1357*f6dc9357SAndroid Build Coastguard Worker
1358*f6dc9357SAndroid Build Coastguard Worker // bool useResourceCompression = false;
1359*f6dc9357SAndroid Build Coastguard Worker // use useResourceCompression only if CHeader::Flags compression is also set
1360*f6dc9357SAndroid Build Coastguard Worker
1361*f6dc9357SAndroid Build Coastguard Worker CHeader header;
1362*f6dc9357SAndroid Build Coastguard Worker header.SetDefaultFields(false);
1363*f6dc9357SAndroid Build Coastguard Worker
1364*f6dc9357SAndroid Build Coastguard Worker if (isUpdate)
1365*f6dc9357SAndroid Build Coastguard Worker {
1366*f6dc9357SAndroid Build Coastguard Worker const CHeader &srcHeader = _volumes[1].Header;
1367*f6dc9357SAndroid Build Coastguard Worker header.Flags = srcHeader.Flags;
1368*f6dc9357SAndroid Build Coastguard Worker header.Version = srcHeader.Version;
1369*f6dc9357SAndroid Build Coastguard Worker header.ChunkSize = srcHeader.ChunkSize;
1370*f6dc9357SAndroid Build Coastguard Worker header.ChunkSizeBits = srcHeader.ChunkSizeBits;
1371*f6dc9357SAndroid Build Coastguard Worker }
1372*f6dc9357SAndroid Build Coastguard Worker
1373*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IStreamSetRestriction> setRestriction;
1374*f6dc9357SAndroid Build Coastguard Worker outSeqStream->QueryInterface(IID_IStreamSetRestriction, (void **)&setRestriction);
1375*f6dc9357SAndroid Build Coastguard Worker if (setRestriction)
1376*f6dc9357SAndroid Build Coastguard Worker RINOK(setRestriction->SetRestriction(0, kHeaderSizeMax))
1377*f6dc9357SAndroid Build Coastguard Worker
1378*f6dc9357SAndroid Build Coastguard Worker {
1379*f6dc9357SAndroid Build Coastguard Worker Byte buf[kHeaderSizeMax];
1380*f6dc9357SAndroid Build Coastguard Worker header.WriteTo(buf);
1381*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteStream(outStream, buf, kHeaderSizeMax))
1382*f6dc9357SAndroid Build Coastguard Worker }
1383*f6dc9357SAndroid Build Coastguard Worker
1384*f6dc9357SAndroid Build Coastguard Worker UInt64 curPos = kHeaderSizeMax;
1385*f6dc9357SAndroid Build Coastguard Worker
1386*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialInStream, CInStreamWithSha1> inShaStream;
1387*f6dc9357SAndroid Build Coastguard Worker
1388*f6dc9357SAndroid Build Coastguard Worker CLimitedSequentialInStream *inStreamLimitedSpec = NULL;
1389*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> inStreamLimited;
1390*f6dc9357SAndroid Build Coastguard Worker if (_volumes.Size() == 2)
1391*f6dc9357SAndroid Build Coastguard Worker {
1392*f6dc9357SAndroid Build Coastguard Worker inStreamLimitedSpec = new CLimitedSequentialInStream;
1393*f6dc9357SAndroid Build Coastguard Worker inStreamLimited = inStreamLimitedSpec;
1394*f6dc9357SAndroid Build Coastguard Worker inStreamLimitedSpec->SetStream(_volumes[1].Stream);
1395*f6dc9357SAndroid Build Coastguard Worker }
1396*f6dc9357SAndroid Build Coastguard Worker
1397*f6dc9357SAndroid Build Coastguard Worker
1398*f6dc9357SAndroid Build Coastguard Worker CRecordVector<CStreamInfo> streams;
1399*f6dc9357SAndroid Build Coastguard Worker CSortedIndex sortedHashes; // indexes to streams, sorted by SHA1
1400*f6dc9357SAndroid Build Coastguard Worker
1401*f6dc9357SAndroid Build Coastguard Worker // ---------- Copy unchanged data streams ----------
1402*f6dc9357SAndroid Build Coastguard Worker
1403*f6dc9357SAndroid Build Coastguard Worker UInt64 solidRunOffset = 0;
1404*f6dc9357SAndroid Build Coastguard Worker UInt64 curSolidSize = 0;
1405*f6dc9357SAndroid Build Coastguard Worker
1406*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < _db.DataStreams.Size(); i++)
1407*f6dc9357SAndroid Build Coastguard Worker {
1408*f6dc9357SAndroid Build Coastguard Worker const CStreamInfo &siOld = _db.DataStreams[i];
1409*f6dc9357SAndroid Build Coastguard Worker const CResource &rs = siOld.Resource;
1410*f6dc9357SAndroid Build Coastguard Worker
1411*f6dc9357SAndroid Build Coastguard Worker const unsigned numRefs = streamsRefs[i];
1412*f6dc9357SAndroid Build Coastguard Worker
1413*f6dc9357SAndroid Build Coastguard Worker if (numRefs == 0)
1414*f6dc9357SAndroid Build Coastguard Worker {
1415*f6dc9357SAndroid Build Coastguard Worker if (!rs.IsSolidSmall())
1416*f6dc9357SAndroid Build Coastguard Worker continue;
1417*f6dc9357SAndroid Build Coastguard Worker if (streamsRefs[_db.Solids[rs.SolidIndex].StreamIndex] == 0)
1418*f6dc9357SAndroid Build Coastguard Worker continue;
1419*f6dc9357SAndroid Build Coastguard Worker }
1420*f6dc9357SAndroid Build Coastguard Worker
1421*f6dc9357SAndroid Build Coastguard Worker lps->InSize = lps->OutSize = complexity;
1422*f6dc9357SAndroid Build Coastguard Worker RINOK(lps->SetCur())
1423*f6dc9357SAndroid Build Coastguard Worker
1424*f6dc9357SAndroid Build Coastguard Worker const unsigned streamIndex = streams.Size();
1425*f6dc9357SAndroid Build Coastguard Worker CStreamInfo s;
1426*f6dc9357SAndroid Build Coastguard Worker s.Resource = rs;
1427*f6dc9357SAndroid Build Coastguard Worker s.PartNumber = 1;
1428*f6dc9357SAndroid Build Coastguard Worker s.RefCount = numRefs;
1429*f6dc9357SAndroid Build Coastguard Worker
1430*f6dc9357SAndroid Build Coastguard Worker memcpy(s.Hash, siOld.Hash, kHashSize);
1431*f6dc9357SAndroid Build Coastguard Worker
1432*f6dc9357SAndroid Build Coastguard Worker if (rs.IsSolid())
1433*f6dc9357SAndroid Build Coastguard Worker {
1434*f6dc9357SAndroid Build Coastguard Worker CSolid &ss = _db.Solids[rs.SolidIndex];
1435*f6dc9357SAndroid Build Coastguard Worker if (rs.IsSolidSmall())
1436*f6dc9357SAndroid Build Coastguard Worker {
1437*f6dc9357SAndroid Build Coastguard Worker UInt64 oldOffset = ss.SolidOffset;
1438*f6dc9357SAndroid Build Coastguard Worker if (rs.Offset < oldOffset)
1439*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
1440*f6dc9357SAndroid Build Coastguard Worker UInt64 relatOffset = rs.Offset - oldOffset;
1441*f6dc9357SAndroid Build Coastguard Worker s.Resource.Offset = solidRunOffset + relatOffset;
1442*f6dc9357SAndroid Build Coastguard Worker }
1443*f6dc9357SAndroid Build Coastguard Worker else
1444*f6dc9357SAndroid Build Coastguard Worker {
1445*f6dc9357SAndroid Build Coastguard Worker // IsSolidBig
1446*f6dc9357SAndroid Build Coastguard Worker solidRunOffset += curSolidSize;
1447*f6dc9357SAndroid Build Coastguard Worker curSolidSize = ss.UnpackSize;
1448*f6dc9357SAndroid Build Coastguard Worker }
1449*f6dc9357SAndroid Build Coastguard Worker }
1450*f6dc9357SAndroid Build Coastguard Worker else
1451*f6dc9357SAndroid Build Coastguard Worker {
1452*f6dc9357SAndroid Build Coastguard Worker solidRunOffset = 0;
1453*f6dc9357SAndroid Build Coastguard Worker curSolidSize = 0;
1454*f6dc9357SAndroid Build Coastguard Worker }
1455*f6dc9357SAndroid Build Coastguard Worker
1456*f6dc9357SAndroid Build Coastguard Worker if (!rs.IsSolid() || rs.IsSolidSmall())
1457*f6dc9357SAndroid Build Coastguard Worker {
1458*f6dc9357SAndroid Build Coastguard Worker const int find = AddUniqHash(streams.ConstData(), sortedHashes, siOld.Hash, (int)streamIndex);
1459*f6dc9357SAndroid Build Coastguard Worker if (find != -1)
1460*f6dc9357SAndroid Build Coastguard Worker return E_FAIL; // two streams with same SHA-1
1461*f6dc9357SAndroid Build Coastguard Worker }
1462*f6dc9357SAndroid Build Coastguard Worker
1463*f6dc9357SAndroid Build Coastguard Worker if (!rs.IsSolid() || rs.IsSolidBig())
1464*f6dc9357SAndroid Build Coastguard Worker {
1465*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(_volumes[siOld.PartNumber].Stream, rs.Offset))
1466*f6dc9357SAndroid Build Coastguard Worker inStreamLimitedSpec->Init(rs.PackSize);
1467*f6dc9357SAndroid Build Coastguard Worker RINOK(copyCoder.Interface()->Code(inStreamLimited, outStream, NULL, NULL, lps))
1468*f6dc9357SAndroid Build Coastguard Worker if (copyCoder->TotalSize != rs.PackSize)
1469*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
1470*f6dc9357SAndroid Build Coastguard Worker s.Resource.Offset = curPos;
1471*f6dc9357SAndroid Build Coastguard Worker curPos += rs.PackSize;
1472*f6dc9357SAndroid Build Coastguard Worker lps->ProgressOffset += rs.PackSize;
1473*f6dc9357SAndroid Build Coastguard Worker }
1474*f6dc9357SAndroid Build Coastguard Worker
1475*f6dc9357SAndroid Build Coastguard Worker streams.Add(s);
1476*f6dc9357SAndroid Build Coastguard Worker }
1477*f6dc9357SAndroid Build Coastguard Worker
1478*f6dc9357SAndroid Build Coastguard Worker
1479*f6dc9357SAndroid Build Coastguard Worker // ---------- Write new items ----------
1480*f6dc9357SAndroid Build Coastguard Worker
1481*f6dc9357SAndroid Build Coastguard Worker CUIntVector hlIndexes; // sorted indexes for hard link items
1482*f6dc9357SAndroid Build Coastguard Worker
1483*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < db.UpdateIndexes.Size(); i++)
1484*f6dc9357SAndroid Build Coastguard Worker {
1485*f6dc9357SAndroid Build Coastguard Worker lps->InSize = lps->OutSize = complexity;
1486*f6dc9357SAndroid Build Coastguard Worker RINOK(lps->SetCur())
1487*f6dc9357SAndroid Build Coastguard Worker const CUpdateItem &ui = db.UpdateItems[db.UpdateIndexes[i]];
1488*f6dc9357SAndroid Build Coastguard Worker CMetaItem &mi = db.MetaItems[ui.MetaIndex];
1489*f6dc9357SAndroid Build Coastguard Worker UInt64 size = 0;
1490*f6dc9357SAndroid Build Coastguard Worker
1491*f6dc9357SAndroid Build Coastguard Worker if (ui.AltStreamIndex >= 0)
1492*f6dc9357SAndroid Build Coastguard Worker {
1493*f6dc9357SAndroid Build Coastguard Worker if (mi.Skip)
1494*f6dc9357SAndroid Build Coastguard Worker continue;
1495*f6dc9357SAndroid Build Coastguard Worker size = mi.AltStreams[ui.AltStreamIndex].Size;
1496*f6dc9357SAndroid Build Coastguard Worker }
1497*f6dc9357SAndroid Build Coastguard Worker else
1498*f6dc9357SAndroid Build Coastguard Worker {
1499*f6dc9357SAndroid Build Coastguard Worker size = mi.Size;
1500*f6dc9357SAndroid Build Coastguard Worker if (mi.IsDir)
1501*f6dc9357SAndroid Build Coastguard Worker {
1502*f6dc9357SAndroid Build Coastguard Worker // we support LINK files here
1503*f6dc9357SAndroid Build Coastguard Worker if (mi.Reparse.Size() == 0)
1504*f6dc9357SAndroid Build Coastguard Worker continue;
1505*f6dc9357SAndroid Build Coastguard Worker }
1506*f6dc9357SAndroid Build Coastguard Worker }
1507*f6dc9357SAndroid Build Coastguard Worker
1508*f6dc9357SAndroid Build Coastguard Worker if (ui.InArcIndex >= 0)
1509*f6dc9357SAndroid Build Coastguard Worker {
1510*f6dc9357SAndroid Build Coastguard Worker // data streams with OLD Data were written already
1511*f6dc9357SAndroid Build Coastguard Worker // we just need to find HashIndex in hashes.
1512*f6dc9357SAndroid Build Coastguard Worker
1513*f6dc9357SAndroid Build Coastguard Worker if ((unsigned)ui.InArcIndex >= _db.SortedItems.Size())
1514*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
1515*f6dc9357SAndroid Build Coastguard Worker
1516*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _db.Items[_db.SortedItems[ui.InArcIndex]];
1517*f6dc9357SAndroid Build Coastguard Worker
1518*f6dc9357SAndroid Build Coastguard Worker if (item.StreamIndex < 0)
1519*f6dc9357SAndroid Build Coastguard Worker {
1520*f6dc9357SAndroid Build Coastguard Worker if (size == 0)
1521*f6dc9357SAndroid Build Coastguard Worker continue;
1522*f6dc9357SAndroid Build Coastguard Worker // if (_db.ItemHasStream(item))
1523*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
1524*f6dc9357SAndroid Build Coastguard Worker }
1525*f6dc9357SAndroid Build Coastguard Worker
1526*f6dc9357SAndroid Build Coastguard Worker // We support empty file (size = 0, but with stream and SHA-1) from old archive
1527*f6dc9357SAndroid Build Coastguard Worker
1528*f6dc9357SAndroid Build Coastguard Worker const CStreamInfo &siOld = _db.DataStreams[item.StreamIndex];
1529*f6dc9357SAndroid Build Coastguard Worker
1530*f6dc9357SAndroid Build Coastguard Worker const int index = AddUniqHash(streams.ConstData(), sortedHashes, siOld.Hash, -1);
1531*f6dc9357SAndroid Build Coastguard Worker // we must have written that stream already
1532*f6dc9357SAndroid Build Coastguard Worker if (index == -1)
1533*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
1534*f6dc9357SAndroid Build Coastguard Worker
1535*f6dc9357SAndroid Build Coastguard Worker if (ui.AltStreamIndex < 0)
1536*f6dc9357SAndroid Build Coastguard Worker mi.HashIndex = index;
1537*f6dc9357SAndroid Build Coastguard Worker else
1538*f6dc9357SAndroid Build Coastguard Worker mi.AltStreams[ui.AltStreamIndex].HashIndex = index;
1539*f6dc9357SAndroid Build Coastguard Worker
1540*f6dc9357SAndroid Build Coastguard Worker continue;
1541*f6dc9357SAndroid Build Coastguard Worker }
1542*f6dc9357SAndroid Build Coastguard Worker
1543*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> fileInStream;
1544*f6dc9357SAndroid Build Coastguard Worker HRESULT res = callback->GetStream(ui.CallbackIndex, &fileInStream);
1545*f6dc9357SAndroid Build Coastguard Worker
1546*f6dc9357SAndroid Build Coastguard Worker if (res == S_FALSE)
1547*f6dc9357SAndroid Build Coastguard Worker {
1548*f6dc9357SAndroid Build Coastguard Worker if (ui.AltStreamIndex >= 0)
1549*f6dc9357SAndroid Build Coastguard Worker {
1550*f6dc9357SAndroid Build Coastguard Worker mi.NumSkipAltStreams++;
1551*f6dc9357SAndroid Build Coastguard Worker mi.AltStreams[ui.AltStreamIndex].Skip = true;
1552*f6dc9357SAndroid Build Coastguard Worker }
1553*f6dc9357SAndroid Build Coastguard Worker else
1554*f6dc9357SAndroid Build Coastguard Worker mi.Skip = true;
1555*f6dc9357SAndroid Build Coastguard Worker }
1556*f6dc9357SAndroid Build Coastguard Worker else
1557*f6dc9357SAndroid Build Coastguard Worker {
1558*f6dc9357SAndroid Build Coastguard Worker RINOK(res)
1559*f6dc9357SAndroid Build Coastguard Worker
1560*f6dc9357SAndroid Build Coastguard Worker int miIndex = -1;
1561*f6dc9357SAndroid Build Coastguard Worker
1562*f6dc9357SAndroid Build Coastguard Worker if (!fileInStream)
1563*f6dc9357SAndroid Build Coastguard Worker {
1564*f6dc9357SAndroid Build Coastguard Worker if (!mi.IsDir)
1565*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1566*f6dc9357SAndroid Build Coastguard Worker }
1567*f6dc9357SAndroid Build Coastguard Worker else if (ui.AltStreamIndex < 0)
1568*f6dc9357SAndroid Build Coastguard Worker {
1569*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IStreamGetProps2> getProps2;
1570*f6dc9357SAndroid Build Coastguard Worker fileInStream->QueryInterface(IID_IStreamGetProps2, (void **)&getProps2);
1571*f6dc9357SAndroid Build Coastguard Worker if (getProps2)
1572*f6dc9357SAndroid Build Coastguard Worker {
1573*f6dc9357SAndroid Build Coastguard Worker CStreamFileProps props;
1574*f6dc9357SAndroid Build Coastguard Worker if (getProps2->GetProps2(&props) == S_OK)
1575*f6dc9357SAndroid Build Coastguard Worker {
1576*f6dc9357SAndroid Build Coastguard Worker mi.Attrib = props.Attrib;
1577*f6dc9357SAndroid Build Coastguard Worker if (_timeOptions.Write_CTime.Val) mi.CTime = props.CTime;
1578*f6dc9357SAndroid Build Coastguard Worker if (_timeOptions.Write_ATime.Val) mi.ATime = props.ATime;
1579*f6dc9357SAndroid Build Coastguard Worker if (_timeOptions.Write_MTime.Val) mi.MTime = props.MTime;
1580*f6dc9357SAndroid Build Coastguard Worker mi.FileID = props.FileID_Low;
1581*f6dc9357SAndroid Build Coastguard Worker if (props.NumLinks <= 1)
1582*f6dc9357SAndroid Build Coastguard Worker mi.FileID = 0;
1583*f6dc9357SAndroid Build Coastguard Worker mi.VolID = props.VolID;
1584*f6dc9357SAndroid Build Coastguard Worker if (mi.FileID != 0)
1585*f6dc9357SAndroid Build Coastguard Worker miIndex = AddToHardLinkList(db.MetaItems, (unsigned)ui.MetaIndex, hlIndexes);
1586*f6dc9357SAndroid Build Coastguard Worker
1587*f6dc9357SAndroid Build Coastguard Worker if (props.Size != size && props.Size != (UInt64)(Int64)-1)
1588*f6dc9357SAndroid Build Coastguard Worker {
1589*f6dc9357SAndroid Build Coastguard Worker const Int64 delta = (Int64)props.Size - (Int64)size;
1590*f6dc9357SAndroid Build Coastguard Worker const Int64 newComplexity = (Int64)totalComplexity + delta;
1591*f6dc9357SAndroid Build Coastguard Worker if (newComplexity > 0)
1592*f6dc9357SAndroid Build Coastguard Worker {
1593*f6dc9357SAndroid Build Coastguard Worker totalComplexity = (UInt64)newComplexity;
1594*f6dc9357SAndroid Build Coastguard Worker callback->SetTotal(totalComplexity);
1595*f6dc9357SAndroid Build Coastguard Worker }
1596*f6dc9357SAndroid Build Coastguard Worker mi.Size = props.Size;
1597*f6dc9357SAndroid Build Coastguard Worker size = props.Size;
1598*f6dc9357SAndroid Build Coastguard Worker }
1599*f6dc9357SAndroid Build Coastguard Worker }
1600*f6dc9357SAndroid Build Coastguard Worker }
1601*f6dc9357SAndroid Build Coastguard Worker }
1602*f6dc9357SAndroid Build Coastguard Worker
1603*f6dc9357SAndroid Build Coastguard Worker if (miIndex >= 0)
1604*f6dc9357SAndroid Build Coastguard Worker {
1605*f6dc9357SAndroid Build Coastguard Worker mi.HashIndex = db.MetaItems[miIndex].HashIndex;
1606*f6dc9357SAndroid Build Coastguard Worker if (mi.HashIndex >= 0)
1607*f6dc9357SAndroid Build Coastguard Worker streams[mi.HashIndex].RefCount++;
1608*f6dc9357SAndroid Build Coastguard Worker // fix for future: maybe we need to check also that real size is equal to size from IStreamGetProps2
1609*f6dc9357SAndroid Build Coastguard Worker }
1610*f6dc9357SAndroid Build Coastguard Worker else if (ui.AltStreamIndex < 0 && mi.Reparse.Size() != 0)
1611*f6dc9357SAndroid Build Coastguard Worker {
1612*f6dc9357SAndroid Build Coastguard Worker if (mi.Reparse.Size() < 8)
1613*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
1614*f6dc9357SAndroid Build Coastguard Worker NCrypto::NSha1::CContext sha1;
1615*f6dc9357SAndroid Build Coastguard Worker sha1.Init();
1616*f6dc9357SAndroid Build Coastguard Worker const size_t packSize = mi.Reparse.Size() - 8;
1617*f6dc9357SAndroid Build Coastguard Worker sha1.Update((const Byte *)mi.Reparse + 8, packSize);
1618*f6dc9357SAndroid Build Coastguard Worker Byte hash[kHashSize];
1619*f6dc9357SAndroid Build Coastguard Worker sha1.Final(hash);
1620*f6dc9357SAndroid Build Coastguard Worker
1621*f6dc9357SAndroid Build Coastguard Worker int index = AddUniqHash(streams.ConstData(), sortedHashes, hash, (int)streams.Size());
1622*f6dc9357SAndroid Build Coastguard Worker
1623*f6dc9357SAndroid Build Coastguard Worker if (index != -1)
1624*f6dc9357SAndroid Build Coastguard Worker streams[index].RefCount++;
1625*f6dc9357SAndroid Build Coastguard Worker else
1626*f6dc9357SAndroid Build Coastguard Worker {
1627*f6dc9357SAndroid Build Coastguard Worker index = (int)streams.Size();
1628*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteStream(outStream, (const Byte *)mi.Reparse + 8, packSize))
1629*f6dc9357SAndroid Build Coastguard Worker CStreamInfo s;
1630*f6dc9357SAndroid Build Coastguard Worker s.Resource.PackSize = packSize;
1631*f6dc9357SAndroid Build Coastguard Worker s.Resource.Offset = curPos;
1632*f6dc9357SAndroid Build Coastguard Worker s.Resource.UnpackSize = packSize;
1633*f6dc9357SAndroid Build Coastguard Worker s.Resource.Flags = 0; // check it
1634*f6dc9357SAndroid Build Coastguard Worker /*
1635*f6dc9357SAndroid Build Coastguard Worker if (useResourceCompression)
1636*f6dc9357SAndroid Build Coastguard Worker s.Resource.Flags = NResourceFlags::Compressed;
1637*f6dc9357SAndroid Build Coastguard Worker */
1638*f6dc9357SAndroid Build Coastguard Worker s.PartNumber = 1;
1639*f6dc9357SAndroid Build Coastguard Worker s.RefCount = 1;
1640*f6dc9357SAndroid Build Coastguard Worker memcpy(s.Hash, hash, kHashSize);
1641*f6dc9357SAndroid Build Coastguard Worker curPos += packSize;
1642*f6dc9357SAndroid Build Coastguard Worker
1643*f6dc9357SAndroid Build Coastguard Worker streams.Add(s);
1644*f6dc9357SAndroid Build Coastguard Worker }
1645*f6dc9357SAndroid Build Coastguard Worker
1646*f6dc9357SAndroid Build Coastguard Worker mi.HashIndex = index;
1647*f6dc9357SAndroid Build Coastguard Worker }
1648*f6dc9357SAndroid Build Coastguard Worker else
1649*f6dc9357SAndroid Build Coastguard Worker {
1650*f6dc9357SAndroid Build Coastguard Worker inShaStream->SetStream(fileInStream);
1651*f6dc9357SAndroid Build Coastguard Worker
1652*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> inSeekStream;
1653*f6dc9357SAndroid Build Coastguard Worker fileInStream.QueryInterface(IID_IInStream, (void **)&inSeekStream);
1654*f6dc9357SAndroid Build Coastguard Worker
1655*f6dc9357SAndroid Build Coastguard Worker fileInStream.Release();
1656*f6dc9357SAndroid Build Coastguard Worker inShaStream->Init();
1657*f6dc9357SAndroid Build Coastguard Worker UInt64 offsetBlockSize = 0;
1658*f6dc9357SAndroid Build Coastguard Worker /*
1659*f6dc9357SAndroid Build Coastguard Worker if (useResourceCompression)
1660*f6dc9357SAndroid Build Coastguard Worker {
1661*f6dc9357SAndroid Build Coastguard Worker for (UInt64 t = kChunkSize; t < size; t += kChunkSize)
1662*f6dc9357SAndroid Build Coastguard Worker {
1663*f6dc9357SAndroid Build Coastguard Worker Byte buf[8];
1664*f6dc9357SAndroid Build Coastguard Worker SetUi32(buf, (UInt32)t);
1665*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteStream(outStream, buf, 4));
1666*f6dc9357SAndroid Build Coastguard Worker offsetBlockSize += 4;
1667*f6dc9357SAndroid Build Coastguard Worker }
1668*f6dc9357SAndroid Build Coastguard Worker }
1669*f6dc9357SAndroid Build Coastguard Worker */
1670*f6dc9357SAndroid Build Coastguard Worker
1671*f6dc9357SAndroid Build Coastguard Worker // 22.02: we use additional read-only pass to calculate SHA-1
1672*f6dc9357SAndroid Build Coastguard Worker bool needWritePass = true;
1673*f6dc9357SAndroid Build Coastguard Worker int index = -1;
1674*f6dc9357SAndroid Build Coastguard Worker
1675*f6dc9357SAndroid Build Coastguard Worker if (inSeekStream /* && !sortedHashes.IsEmpty() */)
1676*f6dc9357SAndroid Build Coastguard Worker {
1677*f6dc9357SAndroid Build Coastguard Worker RINOK(copyCoder.Interface()->Code(inShaStream, NULL, NULL, NULL, lps))
1678*f6dc9357SAndroid Build Coastguard Worker size = copyCoder->TotalSize;
1679*f6dc9357SAndroid Build Coastguard Worker if (size == 0)
1680*f6dc9357SAndroid Build Coastguard Worker needWritePass = false;
1681*f6dc9357SAndroid Build Coastguard Worker else
1682*f6dc9357SAndroid Build Coastguard Worker {
1683*f6dc9357SAndroid Build Coastguard Worker Byte hash[kHashSize];
1684*f6dc9357SAndroid Build Coastguard Worker inShaStream->Final(hash);
1685*f6dc9357SAndroid Build Coastguard Worker
1686*f6dc9357SAndroid Build Coastguard Worker index = AddUniqHash(streams.ConstData(), sortedHashes, hash, -1);
1687*f6dc9357SAndroid Build Coastguard Worker if (index != -1)
1688*f6dc9357SAndroid Build Coastguard Worker {
1689*f6dc9357SAndroid Build Coastguard Worker streams[index].RefCount++;
1690*f6dc9357SAndroid Build Coastguard Worker needWritePass = false;
1691*f6dc9357SAndroid Build Coastguard Worker }
1692*f6dc9357SAndroid Build Coastguard Worker else
1693*f6dc9357SAndroid Build Coastguard Worker {
1694*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekToBegin(inSeekStream))
1695*f6dc9357SAndroid Build Coastguard Worker inShaStream->Init();
1696*f6dc9357SAndroid Build Coastguard Worker }
1697*f6dc9357SAndroid Build Coastguard Worker }
1698*f6dc9357SAndroid Build Coastguard Worker }
1699*f6dc9357SAndroid Build Coastguard Worker
1700*f6dc9357SAndroid Build Coastguard Worker if (needWritePass)
1701*f6dc9357SAndroid Build Coastguard Worker {
1702*f6dc9357SAndroid Build Coastguard Worker RINOK(copyCoder.Interface()->Code(inShaStream, outStream, NULL, NULL, lps))
1703*f6dc9357SAndroid Build Coastguard Worker size = copyCoder->TotalSize;
1704*f6dc9357SAndroid Build Coastguard Worker }
1705*f6dc9357SAndroid Build Coastguard Worker
1706*f6dc9357SAndroid Build Coastguard Worker if (size != 0)
1707*f6dc9357SAndroid Build Coastguard Worker {
1708*f6dc9357SAndroid Build Coastguard Worker if (needWritePass)
1709*f6dc9357SAndroid Build Coastguard Worker {
1710*f6dc9357SAndroid Build Coastguard Worker Byte hash[kHashSize];
1711*f6dc9357SAndroid Build Coastguard Worker const UInt64 packSize = offsetBlockSize + size;
1712*f6dc9357SAndroid Build Coastguard Worker inShaStream->Final(hash);
1713*f6dc9357SAndroid Build Coastguard Worker
1714*f6dc9357SAndroid Build Coastguard Worker index = AddUniqHash(streams.ConstData(), sortedHashes, hash, (int)streams.Size());
1715*f6dc9357SAndroid Build Coastguard Worker
1716*f6dc9357SAndroid Build Coastguard Worker if (index != -1)
1717*f6dc9357SAndroid Build Coastguard Worker {
1718*f6dc9357SAndroid Build Coastguard Worker streams[index].RefCount++;
1719*f6dc9357SAndroid Build Coastguard Worker outStream->Seek(-(Int64)packSize, STREAM_SEEK_CUR, &curPos);
1720*f6dc9357SAndroid Build Coastguard Worker outStream->SetSize(curPos);
1721*f6dc9357SAndroid Build Coastguard Worker }
1722*f6dc9357SAndroid Build Coastguard Worker else
1723*f6dc9357SAndroid Build Coastguard Worker {
1724*f6dc9357SAndroid Build Coastguard Worker index = (int)streams.Size();
1725*f6dc9357SAndroid Build Coastguard Worker CStreamInfo s;
1726*f6dc9357SAndroid Build Coastguard Worker s.Resource.PackSize = packSize;
1727*f6dc9357SAndroid Build Coastguard Worker s.Resource.Offset = curPos;
1728*f6dc9357SAndroid Build Coastguard Worker s.Resource.UnpackSize = size;
1729*f6dc9357SAndroid Build Coastguard Worker s.Resource.Flags = 0;
1730*f6dc9357SAndroid Build Coastguard Worker /*
1731*f6dc9357SAndroid Build Coastguard Worker if (useResourceCompression)
1732*f6dc9357SAndroid Build Coastguard Worker s.Resource.Flags = NResourceFlags::Compressed;
1733*f6dc9357SAndroid Build Coastguard Worker */
1734*f6dc9357SAndroid Build Coastguard Worker s.PartNumber = 1;
1735*f6dc9357SAndroid Build Coastguard Worker s.RefCount = 1;
1736*f6dc9357SAndroid Build Coastguard Worker memcpy(s.Hash, hash, kHashSize);
1737*f6dc9357SAndroid Build Coastguard Worker curPos += packSize;
1738*f6dc9357SAndroid Build Coastguard Worker
1739*f6dc9357SAndroid Build Coastguard Worker streams.Add(s);
1740*f6dc9357SAndroid Build Coastguard Worker }
1741*f6dc9357SAndroid Build Coastguard Worker } // needWritePass
1742*f6dc9357SAndroid Build Coastguard Worker if (ui.AltStreamIndex < 0)
1743*f6dc9357SAndroid Build Coastguard Worker mi.HashIndex = index;
1744*f6dc9357SAndroid Build Coastguard Worker else
1745*f6dc9357SAndroid Build Coastguard Worker mi.AltStreams[ui.AltStreamIndex].HashIndex = index;
1746*f6dc9357SAndroid Build Coastguard Worker } // (size != 0)
1747*f6dc9357SAndroid Build Coastguard Worker }
1748*f6dc9357SAndroid Build Coastguard Worker }
1749*f6dc9357SAndroid Build Coastguard Worker fileInStream.Release();
1750*f6dc9357SAndroid Build Coastguard Worker complexity += size;
1751*f6dc9357SAndroid Build Coastguard Worker RINOK(callback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK))
1752*f6dc9357SAndroid Build Coastguard Worker }
1753*f6dc9357SAndroid Build Coastguard Worker
1754*f6dc9357SAndroid Build Coastguard Worker while (secureBlocks.Size() < numNewImages)
1755*f6dc9357SAndroid Build Coastguard Worker secureBlocks.AddNew();
1756*f6dc9357SAndroid Build Coastguard Worker
1757*f6dc9357SAndroid Build Coastguard Worker
1758*f6dc9357SAndroid Build Coastguard Worker
1759*f6dc9357SAndroid Build Coastguard Worker // ---------- Write Images ----------
1760*f6dc9357SAndroid Build Coastguard Worker
1761*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numNewImages; i++)
1762*f6dc9357SAndroid Build Coastguard Worker {
1763*f6dc9357SAndroid Build Coastguard Worker lps->InSize = lps->OutSize = complexity;
1764*f6dc9357SAndroid Build Coastguard Worker RINOK(lps->SetCur())
1765*f6dc9357SAndroid Build Coastguard Worker if (i < isChangedImage.Size() && !isChangedImage[i])
1766*f6dc9357SAndroid Build Coastguard Worker {
1767*f6dc9357SAndroid Build Coastguard Worker CStreamInfo s = _db.MetaStreams[i];
1768*f6dc9357SAndroid Build Coastguard Worker
1769*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(_volumes[1].Stream, s.Resource.Offset))
1770*f6dc9357SAndroid Build Coastguard Worker inStreamLimitedSpec->Init(s.Resource.PackSize);
1771*f6dc9357SAndroid Build Coastguard Worker RINOK(copyCoder.Interface()->Code(inStreamLimited, outStream, NULL, NULL, lps))
1772*f6dc9357SAndroid Build Coastguard Worker if (copyCoder->TotalSize != s.Resource.PackSize)
1773*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
1774*f6dc9357SAndroid Build Coastguard Worker
1775*f6dc9357SAndroid Build Coastguard Worker s.Resource.Offset = curPos;
1776*f6dc9357SAndroid Build Coastguard Worker s.PartNumber = 1;
1777*f6dc9357SAndroid Build Coastguard Worker s.RefCount = 1;
1778*f6dc9357SAndroid Build Coastguard Worker streams.Add(s);
1779*f6dc9357SAndroid Build Coastguard Worker
1780*f6dc9357SAndroid Build Coastguard Worker if (_bootIndex != 0 && _bootIndex == (UInt32)i + 1)
1781*f6dc9357SAndroid Build Coastguard Worker {
1782*f6dc9357SAndroid Build Coastguard Worker header.MetadataResource = s.Resource;
1783*f6dc9357SAndroid Build Coastguard Worker header.BootIndex = _bootIndex;
1784*f6dc9357SAndroid Build Coastguard Worker }
1785*f6dc9357SAndroid Build Coastguard Worker
1786*f6dc9357SAndroid Build Coastguard Worker lps->ProgressOffset += s.Resource.PackSize;
1787*f6dc9357SAndroid Build Coastguard Worker curPos += s.Resource.PackSize;
1788*f6dc9357SAndroid Build Coastguard Worker // printf("\nWrite old image %x\n", i + 1);
1789*f6dc9357SAndroid Build Coastguard Worker continue;
1790*f6dc9357SAndroid Build Coastguard Worker }
1791*f6dc9357SAndroid Build Coastguard Worker
1792*f6dc9357SAndroid Build Coastguard Worker const CDir &tree = trees[i];
1793*f6dc9357SAndroid Build Coastguard Worker const UInt32 kSecuritySize = 8;
1794*f6dc9357SAndroid Build Coastguard Worker
1795*f6dc9357SAndroid Build Coastguard Worker size_t pos = kSecuritySize;
1796*f6dc9357SAndroid Build Coastguard Worker
1797*f6dc9357SAndroid Build Coastguard Worker const CUniqBlocks &secUniqBlocks = secureBlocks[i];
1798*f6dc9357SAndroid Build Coastguard Worker const CObjectVector<CByteBuffer> &secBufs = secUniqBlocks.Bufs;
1799*f6dc9357SAndroid Build Coastguard Worker pos += (size_t)secUniqBlocks.GetTotalSizeInBytes();
1800*f6dc9357SAndroid Build Coastguard Worker pos += secBufs.Size() * 8;
1801*f6dc9357SAndroid Build Coastguard Worker pos = (pos + 7) & ~(size_t)7;
1802*f6dc9357SAndroid Build Coastguard Worker
1803*f6dc9357SAndroid Build Coastguard Worker db.DefaultDirItem = ri;
1804*f6dc9357SAndroid Build Coastguard Worker pos += db.WriteTree_Dummy(tree);
1805*f6dc9357SAndroid Build Coastguard Worker
1806*f6dc9357SAndroid Build Coastguard Worker CByteArr meta(pos);
1807*f6dc9357SAndroid Build Coastguard Worker
1808*f6dc9357SAndroid Build Coastguard Worker Set32((Byte *)meta + 4, secBufs.Size()) // num security entries
1809*f6dc9357SAndroid Build Coastguard Worker pos = kSecuritySize;
1810*f6dc9357SAndroid Build Coastguard Worker
1811*f6dc9357SAndroid Build Coastguard Worker if (secBufs.Size() == 0)
1812*f6dc9357SAndroid Build Coastguard Worker {
1813*f6dc9357SAndroid Build Coastguard Worker // we can write 0 here only if there is no security data, imageX does it,
1814*f6dc9357SAndroid Build Coastguard Worker // but some programs expect size = 8
1815*f6dc9357SAndroid Build Coastguard Worker Set32((Byte *)meta, 8) // size of security data
1816*f6dc9357SAndroid Build Coastguard Worker // Set32((Byte *)meta, 0);
1817*f6dc9357SAndroid Build Coastguard Worker }
1818*f6dc9357SAndroid Build Coastguard Worker else
1819*f6dc9357SAndroid Build Coastguard Worker {
1820*f6dc9357SAndroid Build Coastguard Worker unsigned k;
1821*f6dc9357SAndroid Build Coastguard Worker for (k = 0; k < secBufs.Size(); k++, pos += 8)
1822*f6dc9357SAndroid Build Coastguard Worker {
1823*f6dc9357SAndroid Build Coastguard Worker Set64(meta + pos, secBufs[k].Size())
1824*f6dc9357SAndroid Build Coastguard Worker }
1825*f6dc9357SAndroid Build Coastguard Worker for (k = 0; k < secBufs.Size(); k++)
1826*f6dc9357SAndroid Build Coastguard Worker {
1827*f6dc9357SAndroid Build Coastguard Worker const CByteBuffer &buf = secBufs[k];
1828*f6dc9357SAndroid Build Coastguard Worker size_t size = buf.Size();
1829*f6dc9357SAndroid Build Coastguard Worker if (size != 0)
1830*f6dc9357SAndroid Build Coastguard Worker {
1831*f6dc9357SAndroid Build Coastguard Worker memcpy(meta + pos, buf, size);
1832*f6dc9357SAndroid Build Coastguard Worker pos += size;
1833*f6dc9357SAndroid Build Coastguard Worker }
1834*f6dc9357SAndroid Build Coastguard Worker }
1835*f6dc9357SAndroid Build Coastguard Worker while ((pos & 7) != 0)
1836*f6dc9357SAndroid Build Coastguard Worker meta[pos++] = 0;
1837*f6dc9357SAndroid Build Coastguard Worker Set32((Byte *)meta, (UInt32)pos) // size of security data
1838*f6dc9357SAndroid Build Coastguard Worker }
1839*f6dc9357SAndroid Build Coastguard Worker
1840*f6dc9357SAndroid Build Coastguard Worker db.Hashes = streams.ConstData();
1841*f6dc9357SAndroid Build Coastguard Worker db.WriteTree(tree, (Byte *)meta, pos);
1842*f6dc9357SAndroid Build Coastguard Worker
1843*f6dc9357SAndroid Build Coastguard Worker {
1844*f6dc9357SAndroid Build Coastguard Worker NCrypto::NSha1::CContext sha;
1845*f6dc9357SAndroid Build Coastguard Worker sha.Init();
1846*f6dc9357SAndroid Build Coastguard Worker sha.Update((const Byte *)meta, pos);
1847*f6dc9357SAndroid Build Coastguard Worker
1848*f6dc9357SAndroid Build Coastguard Worker Byte digest[kHashSize];
1849*f6dc9357SAndroid Build Coastguard Worker sha.Final(digest);
1850*f6dc9357SAndroid Build Coastguard Worker
1851*f6dc9357SAndroid Build Coastguard Worker CStreamInfo s;
1852*f6dc9357SAndroid Build Coastguard Worker s.Resource.PackSize = pos;
1853*f6dc9357SAndroid Build Coastguard Worker s.Resource.Offset = curPos;
1854*f6dc9357SAndroid Build Coastguard Worker s.Resource.UnpackSize = pos;
1855*f6dc9357SAndroid Build Coastguard Worker s.Resource.Flags = NResourceFlags::kMetadata;
1856*f6dc9357SAndroid Build Coastguard Worker s.PartNumber = 1;
1857*f6dc9357SAndroid Build Coastguard Worker s.RefCount = 1;
1858*f6dc9357SAndroid Build Coastguard Worker memcpy(s.Hash, digest, kHashSize);
1859*f6dc9357SAndroid Build Coastguard Worker streams.Add(s);
1860*f6dc9357SAndroid Build Coastguard Worker
1861*f6dc9357SAndroid Build Coastguard Worker if (_bootIndex != 0 && _bootIndex == (UInt32)i + 1)
1862*f6dc9357SAndroid Build Coastguard Worker {
1863*f6dc9357SAndroid Build Coastguard Worker header.MetadataResource = s.Resource;
1864*f6dc9357SAndroid Build Coastguard Worker header.BootIndex = _bootIndex;
1865*f6dc9357SAndroid Build Coastguard Worker }
1866*f6dc9357SAndroid Build Coastguard Worker
1867*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteStream(outStream, (const Byte *)meta, pos))
1868*f6dc9357SAndroid Build Coastguard Worker meta.Free();
1869*f6dc9357SAndroid Build Coastguard Worker curPos += pos;
1870*f6dc9357SAndroid Build Coastguard Worker }
1871*f6dc9357SAndroid Build Coastguard Worker }
1872*f6dc9357SAndroid Build Coastguard Worker
1873*f6dc9357SAndroid Build Coastguard Worker lps->InSize = lps->OutSize = complexity;
1874*f6dc9357SAndroid Build Coastguard Worker RINOK(lps->SetCur())
1875*f6dc9357SAndroid Build Coastguard Worker
1876*f6dc9357SAndroid Build Coastguard Worker header.OffsetResource.UnpackSize = header.OffsetResource.PackSize = (UInt64)streams.Size() * kStreamInfoSize;
1877*f6dc9357SAndroid Build Coastguard Worker header.OffsetResource.Offset = curPos;
1878*f6dc9357SAndroid Build Coastguard Worker header.OffsetResource.Flags = NResourceFlags::kMetadata;
1879*f6dc9357SAndroid Build Coastguard Worker
1880*f6dc9357SAndroid Build Coastguard Worker
1881*f6dc9357SAndroid Build Coastguard Worker
1882*f6dc9357SAndroid Build Coastguard Worker // ---------- Write Streams Info Tables ----------
1883*f6dc9357SAndroid Build Coastguard Worker
1884*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < streams.Size(); i++)
1885*f6dc9357SAndroid Build Coastguard Worker {
1886*f6dc9357SAndroid Build Coastguard Worker Byte buf[kStreamInfoSize];
1887*f6dc9357SAndroid Build Coastguard Worker streams[i].WriteTo(buf);
1888*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteStream(outStream, buf, kStreamInfoSize))
1889*f6dc9357SAndroid Build Coastguard Worker curPos += kStreamInfoSize;
1890*f6dc9357SAndroid Build Coastguard Worker }
1891*f6dc9357SAndroid Build Coastguard Worker
1892*f6dc9357SAndroid Build Coastguard Worker AString xml ("<WIM>");
1893*f6dc9357SAndroid Build Coastguard Worker AddTagUInt64_ToString(xml, "TOTALBYTES", curPos);
1894*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < trees.Size(); i++)
1895*f6dc9357SAndroid Build Coastguard Worker {
1896*f6dc9357SAndroid Build Coastguard Worker const CDir &tree = trees[i];
1897*f6dc9357SAndroid Build Coastguard Worker
1898*f6dc9357SAndroid Build Coastguard Worker CXmlItem item;
1899*f6dc9357SAndroid Build Coastguard Worker if (_xmls.Size() == 1)
1900*f6dc9357SAndroid Build Coastguard Worker {
1901*f6dc9357SAndroid Build Coastguard Worker const CWimXml &_oldXml = _xmls[0];
1902*f6dc9357SAndroid Build Coastguard Worker if (i < _oldXml.Images.Size())
1903*f6dc9357SAndroid Build Coastguard Worker {
1904*f6dc9357SAndroid Build Coastguard Worker // int ttt = _oldXml.Images[i].ItemIndexInXml;
1905*f6dc9357SAndroid Build Coastguard Worker item = _oldXml.Xml.Root.SubItems[_oldXml.Images[i].ItemIndexInXml];
1906*f6dc9357SAndroid Build Coastguard Worker }
1907*f6dc9357SAndroid Build Coastguard Worker }
1908*f6dc9357SAndroid Build Coastguard Worker if (i >= isChangedImage.Size() || isChangedImage[i])
1909*f6dc9357SAndroid Build Coastguard Worker {
1910*f6dc9357SAndroid Build Coastguard Worker char temp[16];
1911*f6dc9357SAndroid Build Coastguard Worker if (item.Name.IsEmpty())
1912*f6dc9357SAndroid Build Coastguard Worker {
1913*f6dc9357SAndroid Build Coastguard Worker ConvertUInt32ToString(i + 1, temp);
1914*f6dc9357SAndroid Build Coastguard Worker item.Name = "IMAGE";
1915*f6dc9357SAndroid Build Coastguard Worker item.IsTag = true;
1916*f6dc9357SAndroid Build Coastguard Worker CXmlProp &prop = item.Props.AddNew();
1917*f6dc9357SAndroid Build Coastguard Worker prop.Name = "INDEX";
1918*f6dc9357SAndroid Build Coastguard Worker prop.Value = temp;
1919*f6dc9357SAndroid Build Coastguard Worker }
1920*f6dc9357SAndroid Build Coastguard Worker
1921*f6dc9357SAndroid Build Coastguard Worker AddTag_String_IfEmpty(item, "NAME", temp);
1922*f6dc9357SAndroid Build Coastguard Worker AddTag_UInt64(item, "DIRCOUNT", tree.GetNumDirs() - 1);
1923*f6dc9357SAndroid Build Coastguard Worker AddTag_UInt64(item, "FILECOUNT", tree.GetNumFiles());
1924*f6dc9357SAndroid Build Coastguard Worker AddTag_UInt64(item, "TOTALBYTES", tree.GetTotalSize(db.MetaItems));
1925*f6dc9357SAndroid Build Coastguard Worker
1926*f6dc9357SAndroid Build Coastguard Worker AddTag_Time(item, "CREATIONTIME", ftCur);
1927*f6dc9357SAndroid Build Coastguard Worker AddTag_Time(item, "LASTMODIFICATIONTIME", ftCur);
1928*f6dc9357SAndroid Build Coastguard Worker }
1929*f6dc9357SAndroid Build Coastguard Worker
1930*f6dc9357SAndroid Build Coastguard Worker item.AppendTo(xml);
1931*f6dc9357SAndroid Build Coastguard Worker }
1932*f6dc9357SAndroid Build Coastguard Worker xml += "</WIM>";
1933*f6dc9357SAndroid Build Coastguard Worker
1934*f6dc9357SAndroid Build Coastguard Worker size_t xmlSize;
1935*f6dc9357SAndroid Build Coastguard Worker {
1936*f6dc9357SAndroid Build Coastguard Worker UString utf16;
1937*f6dc9357SAndroid Build Coastguard Worker if (!ConvertUTF8ToUnicode(xml, utf16))
1938*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1939*f6dc9357SAndroid Build Coastguard Worker xmlSize = ((size_t)utf16.Len() + 1) * 2;
1940*f6dc9357SAndroid Build Coastguard Worker
1941*f6dc9357SAndroid Build Coastguard Worker CByteArr xmlBuf(xmlSize);
1942*f6dc9357SAndroid Build Coastguard Worker Set16((Byte *)xmlBuf, 0xFEFF)
1943*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < (unsigned)utf16.Len(); i++)
1944*f6dc9357SAndroid Build Coastguard Worker {
1945*f6dc9357SAndroid Build Coastguard Worker Set16((Byte *)xmlBuf + 2 + (size_t)i * 2, (UInt16)utf16[i])
1946*f6dc9357SAndroid Build Coastguard Worker }
1947*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteStream(outStream, (const Byte *)xmlBuf, xmlSize))
1948*f6dc9357SAndroid Build Coastguard Worker }
1949*f6dc9357SAndroid Build Coastguard Worker
1950*f6dc9357SAndroid Build Coastguard Worker header.XmlResource.UnpackSize =
1951*f6dc9357SAndroid Build Coastguard Worker header.XmlResource.PackSize = xmlSize;
1952*f6dc9357SAndroid Build Coastguard Worker header.XmlResource.Offset = curPos;
1953*f6dc9357SAndroid Build Coastguard Worker header.XmlResource.Flags = NResourceFlags::kMetadata;
1954*f6dc9357SAndroid Build Coastguard Worker
1955*f6dc9357SAndroid Build Coastguard Worker outStream->Seek(0, STREAM_SEEK_SET, NULL);
1956*f6dc9357SAndroid Build Coastguard Worker header.NumImages = trees.Size();
1957*f6dc9357SAndroid Build Coastguard Worker {
1958*f6dc9357SAndroid Build Coastguard Worker Byte buf[kHeaderSizeMax];
1959*f6dc9357SAndroid Build Coastguard Worker header.WriteTo(buf);
1960*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteStream(outStream, buf, kHeaderSizeMax))
1961*f6dc9357SAndroid Build Coastguard Worker }
1962*f6dc9357SAndroid Build Coastguard Worker
1963*f6dc9357SAndroid Build Coastguard Worker if (setRestriction)
1964*f6dc9357SAndroid Build Coastguard Worker RINOK(setRestriction->SetRestriction(0, 0))
1965*f6dc9357SAndroid Build Coastguard Worker
1966*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1967*f6dc9357SAndroid Build Coastguard Worker
1968*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
1969*f6dc9357SAndroid Build Coastguard Worker }
1970*f6dc9357SAndroid Build Coastguard Worker
1971*f6dc9357SAndroid Build Coastguard Worker }}
1972