1*f6dc9357SAndroid Build Coastguard Worker // TarIn.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/CpuArch.h"
6*f6dc9357SAndroid Build Coastguard Worker
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/StringToInt.h"
8*f6dc9357SAndroid Build Coastguard Worker
9*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamUtils.h"
10*f6dc9357SAndroid Build Coastguard Worker
11*f6dc9357SAndroid Build Coastguard Worker #include "../IArchive.h"
12*f6dc9357SAndroid Build Coastguard Worker
13*f6dc9357SAndroid Build Coastguard Worker #include "TarIn.h"
14*f6dc9357SAndroid Build Coastguard Worker
15*f6dc9357SAndroid Build Coastguard Worker #define NUM_UNROLL_BYTES (8 * 4)
16*f6dc9357SAndroid Build Coastguard Worker
17*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE static bool IsBufNonZero(const void *data, size_t size);
IsBufNonZero(const void * data,size_t size)18*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE static bool IsBufNonZero(const void *data, size_t size)
19*f6dc9357SAndroid Build Coastguard Worker {
20*f6dc9357SAndroid Build Coastguard Worker const Byte *p = (const Byte *)data;
21*f6dc9357SAndroid Build Coastguard Worker
22*f6dc9357SAndroid Build Coastguard Worker for (; size != 0 && ((unsigned)(ptrdiff_t)p & (NUM_UNROLL_BYTES - 1)) != 0; size--)
23*f6dc9357SAndroid Build Coastguard Worker if (*p++ != 0)
24*f6dc9357SAndroid Build Coastguard Worker return true;
25*f6dc9357SAndroid Build Coastguard Worker
26*f6dc9357SAndroid Build Coastguard Worker if (size >= NUM_UNROLL_BYTES)
27*f6dc9357SAndroid Build Coastguard Worker {
28*f6dc9357SAndroid Build Coastguard Worker const Byte *lim = p + size;
29*f6dc9357SAndroid Build Coastguard Worker size &= (NUM_UNROLL_BYTES - 1);
30*f6dc9357SAndroid Build Coastguard Worker lim -= size;
31*f6dc9357SAndroid Build Coastguard Worker do
32*f6dc9357SAndroid Build Coastguard Worker {
33*f6dc9357SAndroid Build Coastguard Worker if (*(const UInt64 *)(const void *)(p ) != 0) return true;
34*f6dc9357SAndroid Build Coastguard Worker if (*(const UInt64 *)(const void *)(p + 8 * 1) != 0) return true;
35*f6dc9357SAndroid Build Coastguard Worker if (*(const UInt64 *)(const void *)(p + 8 * 2) != 0) return true;
36*f6dc9357SAndroid Build Coastguard Worker if (*(const UInt64 *)(const void *)(p + 8 * 3) != 0) return true;
37*f6dc9357SAndroid Build Coastguard Worker // if (*(const UInt32 *)(const void *)(p ) != 0) return true;
38*f6dc9357SAndroid Build Coastguard Worker // if (*(const UInt32 *)(const void *)(p + 4 * 1) != 0) return true;
39*f6dc9357SAndroid Build Coastguard Worker // if (*(const UInt32 *)(const void *)(p + 4 * 2) != 0) return true;
40*f6dc9357SAndroid Build Coastguard Worker // if (*(const UInt32 *)(const void *)(p + 4 * 3) != 0) return true;
41*f6dc9357SAndroid Build Coastguard Worker p += NUM_UNROLL_BYTES;
42*f6dc9357SAndroid Build Coastguard Worker }
43*f6dc9357SAndroid Build Coastguard Worker while (p != lim);
44*f6dc9357SAndroid Build Coastguard Worker }
45*f6dc9357SAndroid Build Coastguard Worker
46*f6dc9357SAndroid Build Coastguard Worker for (; size != 0; size--)
47*f6dc9357SAndroid Build Coastguard Worker if (*p++ != 0)
48*f6dc9357SAndroid Build Coastguard Worker return true;
49*f6dc9357SAndroid Build Coastguard Worker
50*f6dc9357SAndroid Build Coastguard Worker return false;
51*f6dc9357SAndroid Build Coastguard Worker }
52*f6dc9357SAndroid Build Coastguard Worker
53*f6dc9357SAndroid Build Coastguard Worker
54*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
55*f6dc9357SAndroid Build Coastguard Worker namespace NTar {
56*f6dc9357SAndroid Build Coastguard Worker
MyStrNCpy(char * dest,const char * src,unsigned size)57*f6dc9357SAndroid Build Coastguard Worker static void MyStrNCpy(char *dest, const char *src, unsigned size)
58*f6dc9357SAndroid Build Coastguard Worker {
59*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < size; i++)
60*f6dc9357SAndroid Build Coastguard Worker {
61*f6dc9357SAndroid Build Coastguard Worker char c = src[i];
62*f6dc9357SAndroid Build Coastguard Worker dest[i] = c;
63*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
64*f6dc9357SAndroid Build Coastguard Worker break;
65*f6dc9357SAndroid Build Coastguard Worker }
66*f6dc9357SAndroid Build Coastguard Worker }
67*f6dc9357SAndroid Build Coastguard Worker
OctalToNumber(const char * srcString,unsigned size,UInt64 & res,bool allowEmpty=false)68*f6dc9357SAndroid Build Coastguard Worker static bool OctalToNumber(const char *srcString, unsigned size, UInt64 &res, bool allowEmpty = false)
69*f6dc9357SAndroid Build Coastguard Worker {
70*f6dc9357SAndroid Build Coastguard Worker res = 0;
71*f6dc9357SAndroid Build Coastguard Worker char sz[32];
72*f6dc9357SAndroid Build Coastguard Worker MyStrNCpy(sz, srcString, size);
73*f6dc9357SAndroid Build Coastguard Worker sz[size] = 0;
74*f6dc9357SAndroid Build Coastguard Worker const char *end;
75*f6dc9357SAndroid Build Coastguard Worker unsigned i;
76*f6dc9357SAndroid Build Coastguard Worker for (i = 0; sz[i] == ' '; i++);
77*f6dc9357SAndroid Build Coastguard Worker if (sz[i] == 0)
78*f6dc9357SAndroid Build Coastguard Worker return allowEmpty;
79*f6dc9357SAndroid Build Coastguard Worker res = ConvertOctStringToUInt64(sz + i, &end);
80*f6dc9357SAndroid Build Coastguard Worker return (*end == ' ' || *end == 0);
81*f6dc9357SAndroid Build Coastguard Worker }
82*f6dc9357SAndroid Build Coastguard Worker
OctalToNumber32(const char * srcString,UInt32 & res,bool allowEmpty=false)83*f6dc9357SAndroid Build Coastguard Worker static bool OctalToNumber32(const char *srcString, UInt32 &res, bool allowEmpty = false)
84*f6dc9357SAndroid Build Coastguard Worker {
85*f6dc9357SAndroid Build Coastguard Worker const unsigned kSize = 8;
86*f6dc9357SAndroid Build Coastguard Worker UInt64 res64;
87*f6dc9357SAndroid Build Coastguard Worker if (!OctalToNumber(srcString, kSize, res64, allowEmpty))
88*f6dc9357SAndroid Build Coastguard Worker return false;
89*f6dc9357SAndroid Build Coastguard Worker res = (UInt32)res64;
90*f6dc9357SAndroid Build Coastguard Worker return (res64 <= 0xFFFFFFFF);
91*f6dc9357SAndroid Build Coastguard Worker }
92*f6dc9357SAndroid Build Coastguard Worker
93*f6dc9357SAndroid Build Coastguard Worker #define RIF(x) { if (!(x)) return S_OK; }
94*f6dc9357SAndroid Build Coastguard Worker
ReadString(const char * s,unsigned size,AString & result)95*f6dc9357SAndroid Build Coastguard Worker static void ReadString(const char *s, unsigned size, AString &result)
96*f6dc9357SAndroid Build Coastguard Worker {
97*f6dc9357SAndroid Build Coastguard Worker result.SetFrom_CalcLen(s, size);
98*f6dc9357SAndroid Build Coastguard Worker }
99*f6dc9357SAndroid Build Coastguard Worker
ParseInt64(const char * p,Int64 & val,bool & isBin)100*f6dc9357SAndroid Build Coastguard Worker static bool ParseInt64(const char *p, Int64 &val, bool &isBin)
101*f6dc9357SAndroid Build Coastguard Worker {
102*f6dc9357SAndroid Build Coastguard Worker const UInt32 h = GetBe32(p);
103*f6dc9357SAndroid Build Coastguard Worker val = (Int64)GetBe64(p + 4);
104*f6dc9357SAndroid Build Coastguard Worker isBin = true;
105*f6dc9357SAndroid Build Coastguard Worker if (h == (UInt32)1 << 31)
106*f6dc9357SAndroid Build Coastguard Worker return ((val >> 63) & 1) == 0;
107*f6dc9357SAndroid Build Coastguard Worker if (h == (UInt32)(Int32)-1)
108*f6dc9357SAndroid Build Coastguard Worker return ((val >> 63) & 1) != 0;
109*f6dc9357SAndroid Build Coastguard Worker isBin = false;
110*f6dc9357SAndroid Build Coastguard Worker UInt64 u;
111*f6dc9357SAndroid Build Coastguard Worker const bool res = OctalToNumber(p, 12, u);
112*f6dc9357SAndroid Build Coastguard Worker val = (Int64)u;
113*f6dc9357SAndroid Build Coastguard Worker return res;
114*f6dc9357SAndroid Build Coastguard Worker }
115*f6dc9357SAndroid Build Coastguard Worker
ParseInt64_MTime(const char * p,Int64 & val,bool & isBin)116*f6dc9357SAndroid Build Coastguard Worker static bool ParseInt64_MTime(const char *p, Int64 &val, bool &isBin)
117*f6dc9357SAndroid Build Coastguard Worker {
118*f6dc9357SAndroid Build Coastguard Worker // rare case tar : ZEROs in Docker-Windows TARs
119*f6dc9357SAndroid Build Coastguard Worker // rare case tar : spaces
120*f6dc9357SAndroid Build Coastguard Worker isBin = false;
121*f6dc9357SAndroid Build Coastguard Worker if (GetUi32(p) != 0)
122*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < 12; i++)
123*f6dc9357SAndroid Build Coastguard Worker if (p[i] != ' ')
124*f6dc9357SAndroid Build Coastguard Worker return ParseInt64(p, val, isBin);
125*f6dc9357SAndroid Build Coastguard Worker val = 0;
126*f6dc9357SAndroid Build Coastguard Worker return true;
127*f6dc9357SAndroid Build Coastguard Worker }
128*f6dc9357SAndroid Build Coastguard Worker
ParseSize(const char * p,UInt64 & val,bool & isBin)129*f6dc9357SAndroid Build Coastguard Worker static bool ParseSize(const char *p, UInt64 &val, bool &isBin)
130*f6dc9357SAndroid Build Coastguard Worker {
131*f6dc9357SAndroid Build Coastguard Worker if (GetBe32(p) == (UInt32)1 << 31)
132*f6dc9357SAndroid Build Coastguard Worker {
133*f6dc9357SAndroid Build Coastguard Worker // GNU extension
134*f6dc9357SAndroid Build Coastguard Worker isBin = true;
135*f6dc9357SAndroid Build Coastguard Worker val = GetBe64(p + 4);
136*f6dc9357SAndroid Build Coastguard Worker return ((val >> 63) & 1) == 0;
137*f6dc9357SAndroid Build Coastguard Worker }
138*f6dc9357SAndroid Build Coastguard Worker isBin = false;
139*f6dc9357SAndroid Build Coastguard Worker return OctalToNumber(p, 12, val,
140*f6dc9357SAndroid Build Coastguard Worker true // 20.03: allow empty size for 'V' Label entry
141*f6dc9357SAndroid Build Coastguard Worker );
142*f6dc9357SAndroid Build Coastguard Worker }
143*f6dc9357SAndroid Build Coastguard Worker
ParseSize(const char * p,UInt64 & val)144*f6dc9357SAndroid Build Coastguard Worker static bool ParseSize(const char *p, UInt64 &val)
145*f6dc9357SAndroid Build Coastguard Worker {
146*f6dc9357SAndroid Build Coastguard Worker bool isBin;
147*f6dc9357SAndroid Build Coastguard Worker return ParseSize(p, val, isBin);
148*f6dc9357SAndroid Build Coastguard Worker }
149*f6dc9357SAndroid Build Coastguard Worker
150*f6dc9357SAndroid Build Coastguard Worker #define CHECK(x) { if (!(x)) return k_IsArc_Res_NO; }
151*f6dc9357SAndroid Build Coastguard Worker
IsArc_Tar(const Byte * p2,size_t size)152*f6dc9357SAndroid Build Coastguard Worker API_FUNC_IsArc IsArc_Tar(const Byte *p2, size_t size)
153*f6dc9357SAndroid Build Coastguard Worker {
154*f6dc9357SAndroid Build Coastguard Worker if (size < NFileHeader::kRecordSize)
155*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NEED_MORE;
156*f6dc9357SAndroid Build Coastguard Worker
157*f6dc9357SAndroid Build Coastguard Worker const char *p = (const char *)p2;
158*f6dc9357SAndroid Build Coastguard Worker p += NFileHeader::kNameSize;
159*f6dc9357SAndroid Build Coastguard Worker
160*f6dc9357SAndroid Build Coastguard Worker UInt32 mode;
161*f6dc9357SAndroid Build Coastguard Worker // we allow empty Mode value for LongName prefix items
162*f6dc9357SAndroid Build Coastguard Worker CHECK(OctalToNumber32(p, mode, true)) p += 8;
163*f6dc9357SAndroid Build Coastguard Worker
164*f6dc9357SAndroid Build Coastguard Worker // if (!OctalToNumber32(p, item.UID)) item.UID = 0;
165*f6dc9357SAndroid Build Coastguard Worker p += 8;
166*f6dc9357SAndroid Build Coastguard Worker // if (!OctalToNumber32(p, item.GID)) item.GID = 0;
167*f6dc9357SAndroid Build Coastguard Worker p += 8;
168*f6dc9357SAndroid Build Coastguard Worker
169*f6dc9357SAndroid Build Coastguard Worker UInt64 packSize;
170*f6dc9357SAndroid Build Coastguard Worker Int64 time;
171*f6dc9357SAndroid Build Coastguard Worker UInt32 checkSum;
172*f6dc9357SAndroid Build Coastguard Worker bool isBin;
173*f6dc9357SAndroid Build Coastguard Worker CHECK(ParseSize(p, packSize, isBin)) p += 12;
174*f6dc9357SAndroid Build Coastguard Worker CHECK(ParseInt64_MTime(p, time, isBin)) p += 12;
175*f6dc9357SAndroid Build Coastguard Worker CHECK(OctalToNumber32(p, checkSum))
176*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_YES;
177*f6dc9357SAndroid Build Coastguard Worker }
178*f6dc9357SAndroid Build Coastguard Worker
179*f6dc9357SAndroid Build Coastguard Worker
GetNextItemReal(CItemEx & item)180*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchive::GetNextItemReal(CItemEx &item)
181*f6dc9357SAndroid Build Coastguard Worker {
182*f6dc9357SAndroid Build Coastguard Worker char buf[NFileHeader::kRecordSize];
183*f6dc9357SAndroid Build Coastguard Worker
184*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_OK;
185*f6dc9357SAndroid Build Coastguard Worker filled = false;
186*f6dc9357SAndroid Build Coastguard Worker
187*f6dc9357SAndroid Build Coastguard Worker bool thereAreEmptyRecords = false;
188*f6dc9357SAndroid Build Coastguard Worker for (;;)
189*f6dc9357SAndroid Build Coastguard Worker {
190*f6dc9357SAndroid Build Coastguard Worker size_t processedSize = NFileHeader::kRecordSize;
191*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream(SeqStream, buf, &processedSize))
192*f6dc9357SAndroid Build Coastguard Worker if (processedSize == 0)
193*f6dc9357SAndroid Build Coastguard Worker {
194*f6dc9357SAndroid Build Coastguard Worker if (!thereAreEmptyRecords)
195*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_UnexpectedEnd; // "There are no trailing zero-filled records";
196*f6dc9357SAndroid Build Coastguard Worker return S_OK;
197*f6dc9357SAndroid Build Coastguard Worker }
198*f6dc9357SAndroid Build Coastguard Worker if (processedSize != NFileHeader::kRecordSize)
199*f6dc9357SAndroid Build Coastguard Worker {
200*f6dc9357SAndroid Build Coastguard Worker if (!thereAreEmptyRecords)
201*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_UnexpectedEnd; // error = "There is no correct record at the end of archive";
202*f6dc9357SAndroid Build Coastguard Worker else
203*f6dc9357SAndroid Build Coastguard Worker {
204*f6dc9357SAndroid Build Coastguard Worker /*
205*f6dc9357SAndroid Build Coastguard Worker if (IsEmptyData(buf, processedSize))
206*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_UnexpectedEnd;
207*f6dc9357SAndroid Build Coastguard Worker else
208*f6dc9357SAndroid Build Coastguard Worker {
209*f6dc9357SAndroid Build Coastguard Worker // extraReadSize = processedSize;
210*f6dc9357SAndroid Build Coastguard Worker // error = k_ErrorType_Corrupted; // some data after the end tail zeros
211*f6dc9357SAndroid Build Coastguard Worker }
212*f6dc9357SAndroid Build Coastguard Worker */
213*f6dc9357SAndroid Build Coastguard Worker }
214*f6dc9357SAndroid Build Coastguard Worker
215*f6dc9357SAndroid Build Coastguard Worker return S_OK;
216*f6dc9357SAndroid Build Coastguard Worker }
217*f6dc9357SAndroid Build Coastguard Worker if (IsBufNonZero(buf, NFileHeader::kRecordSize))
218*f6dc9357SAndroid Build Coastguard Worker break;
219*f6dc9357SAndroid Build Coastguard Worker item.HeaderSize += NFileHeader::kRecordSize;
220*f6dc9357SAndroid Build Coastguard Worker thereAreEmptyRecords = true;
221*f6dc9357SAndroid Build Coastguard Worker if (OpenCallback)
222*f6dc9357SAndroid Build Coastguard Worker {
223*f6dc9357SAndroid Build Coastguard Worker RINOK(Progress(item, 0))
224*f6dc9357SAndroid Build Coastguard Worker }
225*f6dc9357SAndroid Build Coastguard Worker }
226*f6dc9357SAndroid Build Coastguard Worker if (thereAreEmptyRecords)
227*f6dc9357SAndroid Build Coastguard Worker {
228*f6dc9357SAndroid Build Coastguard Worker // error = "There are data after end of archive";
229*f6dc9357SAndroid Build Coastguard Worker return S_OK;
230*f6dc9357SAndroid Build Coastguard Worker }
231*f6dc9357SAndroid Build Coastguard Worker
232*f6dc9357SAndroid Build Coastguard Worker char *p = buf;
233*f6dc9357SAndroid Build Coastguard Worker
234*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_Corrupted;
235*f6dc9357SAndroid Build Coastguard Worker
236*f6dc9357SAndroid Build Coastguard Worker // ReadString(p, NFileHeader::kNameSize, item.Name);
237*f6dc9357SAndroid Build Coastguard Worker p += NFileHeader::kNameSize;
238*f6dc9357SAndroid Build Coastguard Worker
239*f6dc9357SAndroid Build Coastguard Worker /*
240*f6dc9357SAndroid Build Coastguard Worker item.Name_CouldBeReduced =
241*f6dc9357SAndroid Build Coastguard Worker (item.Name.Len() == NFileHeader::kNameSize ||
242*f6dc9357SAndroid Build Coastguard Worker item.Name.Len() == NFileHeader::kNameSize - 1);
243*f6dc9357SAndroid Build Coastguard Worker */
244*f6dc9357SAndroid Build Coastguard Worker
245*f6dc9357SAndroid Build Coastguard Worker // we allow empty Mode value for LongName prefix items
246*f6dc9357SAndroid Build Coastguard Worker RIF(OctalToNumber32(p, item.Mode, true)) p += 8;
247*f6dc9357SAndroid Build Coastguard Worker
248*f6dc9357SAndroid Build Coastguard Worker if (!OctalToNumber32(p, item.UID)) { item.UID = 0; } p += 8;
249*f6dc9357SAndroid Build Coastguard Worker if (!OctalToNumber32(p, item.GID)) { item.GID = 0; } p += 8;
250*f6dc9357SAndroid Build Coastguard Worker
251*f6dc9357SAndroid Build Coastguard Worker RIF(ParseSize(p, item.PackSize, item.PackSize_IsBin))
252*f6dc9357SAndroid Build Coastguard Worker item.Size = item.PackSize;
253*f6dc9357SAndroid Build Coastguard Worker item.Size_IsBin = item.PackSize_IsBin;
254*f6dc9357SAndroid Build Coastguard Worker p += 12;
255*f6dc9357SAndroid Build Coastguard Worker RIF(ParseInt64_MTime(p, item.MTime, item.MTime_IsBin)) p += 12;
256*f6dc9357SAndroid Build Coastguard Worker
257*f6dc9357SAndroid Build Coastguard Worker UInt32 checkSum;
258*f6dc9357SAndroid Build Coastguard Worker RIF(OctalToNumber32(p, checkSum))
259*f6dc9357SAndroid Build Coastguard Worker memset(p, ' ', 8); p += 8;
260*f6dc9357SAndroid Build Coastguard Worker
261*f6dc9357SAndroid Build Coastguard Worker item.LinkFlag = *p++;
262*f6dc9357SAndroid Build Coastguard Worker
263*f6dc9357SAndroid Build Coastguard Worker ReadString(p, NFileHeader::kNameSize, item.LinkName); p += NFileHeader::kNameSize;
264*f6dc9357SAndroid Build Coastguard Worker
265*f6dc9357SAndroid Build Coastguard Worker /*
266*f6dc9357SAndroid Build Coastguard Worker item.LinkName_CouldBeReduced =
267*f6dc9357SAndroid Build Coastguard Worker (item.LinkName.Len() == NFileHeader::kNameSize ||
268*f6dc9357SAndroid Build Coastguard Worker item.LinkName.Len() == NFileHeader::kNameSize - 1);
269*f6dc9357SAndroid Build Coastguard Worker */
270*f6dc9357SAndroid Build Coastguard Worker
271*f6dc9357SAndroid Build Coastguard Worker memcpy(item.Magic, p, 8); p += 8;
272*f6dc9357SAndroid Build Coastguard Worker
273*f6dc9357SAndroid Build Coastguard Worker ReadString(p, NFileHeader::kUserNameSize, item.User); p += NFileHeader::kUserNameSize;
274*f6dc9357SAndroid Build Coastguard Worker ReadString(p, NFileHeader::kGroupNameSize, item.Group); p += NFileHeader::kGroupNameSize;
275*f6dc9357SAndroid Build Coastguard Worker
276*f6dc9357SAndroid Build Coastguard Worker item.DeviceMajor_Defined = (p[0] != 0); if (item.DeviceMajor_Defined) { RIF(OctalToNumber32(p, item.DeviceMajor)) } p += 8;
277*f6dc9357SAndroid Build Coastguard Worker item.DeviceMinor_Defined = (p[0] != 0); if (item.DeviceMinor_Defined) { RIF(OctalToNumber32(p, item.DeviceMinor)) } p += 8;
278*f6dc9357SAndroid Build Coastguard Worker
279*f6dc9357SAndroid Build Coastguard Worker if (p[0] != 0
280*f6dc9357SAndroid Build Coastguard Worker && item.IsMagic_ustar_5chars()
281*f6dc9357SAndroid Build Coastguard Worker && (item.LinkFlag != 'L' ))
282*f6dc9357SAndroid Build Coastguard Worker {
283*f6dc9357SAndroid Build Coastguard Worker item.Prefix_WasUsed = true;
284*f6dc9357SAndroid Build Coastguard Worker ReadString(p, NFileHeader::kPrefixSize, item.Name);
285*f6dc9357SAndroid Build Coastguard Worker item.Name.Add_Slash();
286*f6dc9357SAndroid Build Coastguard Worker unsigned i;
287*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < NFileHeader::kNameSize; i++)
288*f6dc9357SAndroid Build Coastguard Worker if (buf[i] == 0)
289*f6dc9357SAndroid Build Coastguard Worker break;
290*f6dc9357SAndroid Build Coastguard Worker item.Name.AddFrom(buf, i);
291*f6dc9357SAndroid Build Coastguard Worker }
292*f6dc9357SAndroid Build Coastguard Worker else
293*f6dc9357SAndroid Build Coastguard Worker ReadString(buf, NFileHeader::kNameSize, item.Name);
294*f6dc9357SAndroid Build Coastguard Worker
295*f6dc9357SAndroid Build Coastguard Worker p += NFileHeader::kPrefixSize;
296*f6dc9357SAndroid Build Coastguard Worker
297*f6dc9357SAndroid Build Coastguard Worker if (item.LinkFlag == NFileHeader::NLinkFlag::kHardLink)
298*f6dc9357SAndroid Build Coastguard Worker {
299*f6dc9357SAndroid Build Coastguard Worker item.PackSize = 0;
300*f6dc9357SAndroid Build Coastguard Worker item.Size = 0;
301*f6dc9357SAndroid Build Coastguard Worker }
302*f6dc9357SAndroid Build Coastguard Worker
303*f6dc9357SAndroid Build Coastguard Worker if (item.LinkFlag == NFileHeader::NLinkFlag::kDirectory)
304*f6dc9357SAndroid Build Coastguard Worker {
305*f6dc9357SAndroid Build Coastguard Worker // GNU tar ignores Size field, if LinkFlag is kDirectory
306*f6dc9357SAndroid Build Coastguard Worker // 21.02 : we set PackSize = 0 to be more compatible with GNU tar
307*f6dc9357SAndroid Build Coastguard Worker item.PackSize = 0;
308*f6dc9357SAndroid Build Coastguard Worker // item.Size = 0;
309*f6dc9357SAndroid Build Coastguard Worker }
310*f6dc9357SAndroid Build Coastguard Worker
311*f6dc9357SAndroid Build Coastguard Worker /*
312*f6dc9357SAndroid Build Coastguard Worker TAR standard requires sum of unsigned byte values.
313*f6dc9357SAndroid Build Coastguard Worker But some old TAR programs use sum of signed byte values.
314*f6dc9357SAndroid Build Coastguard Worker So we check both values.
315*f6dc9357SAndroid Build Coastguard Worker */
316*f6dc9357SAndroid Build Coastguard Worker // for (int y = 0; y < 100; y++) // for debug
317*f6dc9357SAndroid Build Coastguard Worker {
318*f6dc9357SAndroid Build Coastguard Worker UInt32 sum0 = 0;
319*f6dc9357SAndroid Build Coastguard Worker {
320*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < NFileHeader::kRecordSize; i++)
321*f6dc9357SAndroid Build Coastguard Worker sum0 += (Byte)buf[i];
322*f6dc9357SAndroid Build Coastguard Worker }
323*f6dc9357SAndroid Build Coastguard Worker if (sum0 != checkSum)
324*f6dc9357SAndroid Build Coastguard Worker {
325*f6dc9357SAndroid Build Coastguard Worker Int32 sum = 0;
326*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < NFileHeader::kRecordSize; i++)
327*f6dc9357SAndroid Build Coastguard Worker sum += (signed char)buf[i];
328*f6dc9357SAndroid Build Coastguard Worker if ((UInt32)sum != checkSum)
329*f6dc9357SAndroid Build Coastguard Worker return S_OK;
330*f6dc9357SAndroid Build Coastguard Worker item.IsSignedChecksum = true;
331*f6dc9357SAndroid Build Coastguard Worker }
332*f6dc9357SAndroid Build Coastguard Worker }
333*f6dc9357SAndroid Build Coastguard Worker
334*f6dc9357SAndroid Build Coastguard Worker item.HeaderSize += NFileHeader::kRecordSize;
335*f6dc9357SAndroid Build Coastguard Worker
336*f6dc9357SAndroid Build Coastguard Worker if (item.LinkFlag == NFileHeader::NLinkFlag::kSparse)
337*f6dc9357SAndroid Build Coastguard Worker {
338*f6dc9357SAndroid Build Coastguard Worker Byte isExtended = (Byte)buf[482];
339*f6dc9357SAndroid Build Coastguard Worker if (isExtended != 0 && isExtended != 1)
340*f6dc9357SAndroid Build Coastguard Worker return S_OK;
341*f6dc9357SAndroid Build Coastguard Worker RIF(ParseSize(buf + 483, item.Size, item.Size_IsBin))
342*f6dc9357SAndroid Build Coastguard Worker UInt64 min = 0;
343*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < 4; i++)
344*f6dc9357SAndroid Build Coastguard Worker {
345*f6dc9357SAndroid Build Coastguard Worker p = buf + 386 + 24 * i;
346*f6dc9357SAndroid Build Coastguard Worker if (GetBe32(p) == 0)
347*f6dc9357SAndroid Build Coastguard Worker {
348*f6dc9357SAndroid Build Coastguard Worker if (isExtended != 0)
349*f6dc9357SAndroid Build Coastguard Worker return S_OK;
350*f6dc9357SAndroid Build Coastguard Worker break;
351*f6dc9357SAndroid Build Coastguard Worker }
352*f6dc9357SAndroid Build Coastguard Worker CSparseBlock sb;
353*f6dc9357SAndroid Build Coastguard Worker RIF(ParseSize(p, sb.Offset))
354*f6dc9357SAndroid Build Coastguard Worker RIF(ParseSize(p + 12, sb.Size))
355*f6dc9357SAndroid Build Coastguard Worker item.SparseBlocks.Add(sb);
356*f6dc9357SAndroid Build Coastguard Worker if (sb.Offset < min || sb.Offset > item.Size)
357*f6dc9357SAndroid Build Coastguard Worker return S_OK;
358*f6dc9357SAndroid Build Coastguard Worker if ((sb.Offset & 0x1FF) != 0 || (sb.Size & 0x1FF) != 0)
359*f6dc9357SAndroid Build Coastguard Worker return S_OK;
360*f6dc9357SAndroid Build Coastguard Worker min = sb.Offset + sb.Size;
361*f6dc9357SAndroid Build Coastguard Worker if (min < sb.Offset)
362*f6dc9357SAndroid Build Coastguard Worker return S_OK;
363*f6dc9357SAndroid Build Coastguard Worker }
364*f6dc9357SAndroid Build Coastguard Worker if (min > item.Size)
365*f6dc9357SAndroid Build Coastguard Worker return S_OK;
366*f6dc9357SAndroid Build Coastguard Worker
367*f6dc9357SAndroid Build Coastguard Worker while (isExtended != 0)
368*f6dc9357SAndroid Build Coastguard Worker {
369*f6dc9357SAndroid Build Coastguard Worker size_t processedSize = NFileHeader::kRecordSize;
370*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream(SeqStream, buf, &processedSize))
371*f6dc9357SAndroid Build Coastguard Worker if (processedSize != NFileHeader::kRecordSize)
372*f6dc9357SAndroid Build Coastguard Worker {
373*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_UnexpectedEnd;
374*f6dc9357SAndroid Build Coastguard Worker return S_OK;
375*f6dc9357SAndroid Build Coastguard Worker }
376*f6dc9357SAndroid Build Coastguard Worker
377*f6dc9357SAndroid Build Coastguard Worker item.HeaderSize += NFileHeader::kRecordSize;
378*f6dc9357SAndroid Build Coastguard Worker
379*f6dc9357SAndroid Build Coastguard Worker if (OpenCallback)
380*f6dc9357SAndroid Build Coastguard Worker {
381*f6dc9357SAndroid Build Coastguard Worker RINOK(Progress(item, 0))
382*f6dc9357SAndroid Build Coastguard Worker }
383*f6dc9357SAndroid Build Coastguard Worker
384*f6dc9357SAndroid Build Coastguard Worker isExtended = (Byte)buf[21 * 24];
385*f6dc9357SAndroid Build Coastguard Worker if (isExtended != 0 && isExtended != 1)
386*f6dc9357SAndroid Build Coastguard Worker return S_OK;
387*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < 21; i++)
388*f6dc9357SAndroid Build Coastguard Worker {
389*f6dc9357SAndroid Build Coastguard Worker p = buf + 24 * i;
390*f6dc9357SAndroid Build Coastguard Worker if (GetBe32(p) == 0)
391*f6dc9357SAndroid Build Coastguard Worker {
392*f6dc9357SAndroid Build Coastguard Worker if (isExtended != 0)
393*f6dc9357SAndroid Build Coastguard Worker return S_OK;
394*f6dc9357SAndroid Build Coastguard Worker break;
395*f6dc9357SAndroid Build Coastguard Worker }
396*f6dc9357SAndroid Build Coastguard Worker CSparseBlock sb;
397*f6dc9357SAndroid Build Coastguard Worker RIF(ParseSize(p, sb.Offset))
398*f6dc9357SAndroid Build Coastguard Worker RIF(ParseSize(p + 12, sb.Size))
399*f6dc9357SAndroid Build Coastguard Worker item.SparseBlocks.Add(sb);
400*f6dc9357SAndroid Build Coastguard Worker if (sb.Offset < min || sb.Offset > item.Size)
401*f6dc9357SAndroid Build Coastguard Worker return S_OK;
402*f6dc9357SAndroid Build Coastguard Worker if ((sb.Offset & 0x1FF) != 0 || (sb.Size & 0x1FF) != 0)
403*f6dc9357SAndroid Build Coastguard Worker return S_OK;
404*f6dc9357SAndroid Build Coastguard Worker min = sb.Offset + sb.Size;
405*f6dc9357SAndroid Build Coastguard Worker if (min < sb.Offset)
406*f6dc9357SAndroid Build Coastguard Worker return S_OK;
407*f6dc9357SAndroid Build Coastguard Worker }
408*f6dc9357SAndroid Build Coastguard Worker }
409*f6dc9357SAndroid Build Coastguard Worker if (min > item.Size)
410*f6dc9357SAndroid Build Coastguard Worker return S_OK;
411*f6dc9357SAndroid Build Coastguard Worker }
412*f6dc9357SAndroid Build Coastguard Worker
413*f6dc9357SAndroid Build Coastguard Worker if (item.PackSize >= (UInt64)1 << 63)
414*f6dc9357SAndroid Build Coastguard Worker return S_OK;
415*f6dc9357SAndroid Build Coastguard Worker
416*f6dc9357SAndroid Build Coastguard Worker filled = true;
417*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_OK;
418*f6dc9357SAndroid Build Coastguard Worker return S_OK;
419*f6dc9357SAndroid Build Coastguard Worker }
420*f6dc9357SAndroid Build Coastguard Worker
421*f6dc9357SAndroid Build Coastguard Worker
Progress(const CItemEx & item,UInt64 posOffset)422*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchive::Progress(const CItemEx &item, UInt64 posOffset)
423*f6dc9357SAndroid Build Coastguard Worker {
424*f6dc9357SAndroid Build Coastguard Worker const UInt64 pos = item.Get_DataPos() + posOffset;
425*f6dc9357SAndroid Build Coastguard Worker if (NumFiles - NumFiles_Prev < (1 << 16)
426*f6dc9357SAndroid Build Coastguard Worker // && NumRecords - NumRecords_Prev < (1 << 16)
427*f6dc9357SAndroid Build Coastguard Worker && pos - Pos_Prev < ((UInt32)1 << 28))
428*f6dc9357SAndroid Build Coastguard Worker return S_OK;
429*f6dc9357SAndroid Build Coastguard Worker {
430*f6dc9357SAndroid Build Coastguard Worker Pos_Prev = pos;
431*f6dc9357SAndroid Build Coastguard Worker NumFiles_Prev = NumFiles;
432*f6dc9357SAndroid Build Coastguard Worker // NumRecords_Prev = NumRecords;
433*f6dc9357SAndroid Build Coastguard Worker // Sleep(100); // for debug
434*f6dc9357SAndroid Build Coastguard Worker return OpenCallback->SetCompleted(&NumFiles, &pos);
435*f6dc9357SAndroid Build Coastguard Worker }
436*f6dc9357SAndroid Build Coastguard Worker }
437*f6dc9357SAndroid Build Coastguard Worker
438*f6dc9357SAndroid Build Coastguard Worker
ReadDataToBuffer(const CItemEx & item,CTempBuffer & tb,size_t stringLimit)439*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchive::ReadDataToBuffer(const CItemEx &item,
440*f6dc9357SAndroid Build Coastguard Worker CTempBuffer &tb, size_t stringLimit)
441*f6dc9357SAndroid Build Coastguard Worker {
442*f6dc9357SAndroid Build Coastguard Worker tb.Init();
443*f6dc9357SAndroid Build Coastguard Worker UInt64 packSize = item.Get_PackSize_Aligned();
444*f6dc9357SAndroid Build Coastguard Worker if (packSize == 0)
445*f6dc9357SAndroid Build Coastguard Worker return S_OK;
446*f6dc9357SAndroid Build Coastguard Worker
447*f6dc9357SAndroid Build Coastguard Worker UInt64 pos;
448*f6dc9357SAndroid Build Coastguard Worker
449*f6dc9357SAndroid Build Coastguard Worker {
450*f6dc9357SAndroid Build Coastguard Worker size_t size = stringLimit;
451*f6dc9357SAndroid Build Coastguard Worker if (size > packSize)
452*f6dc9357SAndroid Build Coastguard Worker size = (size_t)packSize;
453*f6dc9357SAndroid Build Coastguard Worker tb.Buffer.AllocAtLeast(size);
454*f6dc9357SAndroid Build Coastguard Worker size_t processedSize = size;
455*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = ReadStream(SeqStream, tb.Buffer, &processedSize);
456*f6dc9357SAndroid Build Coastguard Worker pos = processedSize;
457*f6dc9357SAndroid Build Coastguard Worker if (processedSize != size)
458*f6dc9357SAndroid Build Coastguard Worker {
459*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_UnexpectedEnd;
460*f6dc9357SAndroid Build Coastguard Worker return res;
461*f6dc9357SAndroid Build Coastguard Worker }
462*f6dc9357SAndroid Build Coastguard Worker RINOK(res)
463*f6dc9357SAndroid Build Coastguard Worker
464*f6dc9357SAndroid Build Coastguard Worker packSize -= size;
465*f6dc9357SAndroid Build Coastguard Worker
466*f6dc9357SAndroid Build Coastguard Worker size_t i;
467*f6dc9357SAndroid Build Coastguard Worker const Byte *p = tb.Buffer;
468*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < size; i++)
469*f6dc9357SAndroid Build Coastguard Worker if (p[i] == 0)
470*f6dc9357SAndroid Build Coastguard Worker break;
471*f6dc9357SAndroid Build Coastguard Worker if (i >= item.PackSize)
472*f6dc9357SAndroid Build Coastguard Worker tb.StringSize_IsConfirmed = true;
473*f6dc9357SAndroid Build Coastguard Worker if (i > item.PackSize)
474*f6dc9357SAndroid Build Coastguard Worker {
475*f6dc9357SAndroid Build Coastguard Worker tb.StringSize = (size_t)item.PackSize;
476*f6dc9357SAndroid Build Coastguard Worker tb.IsNonZeroTail = true;
477*f6dc9357SAndroid Build Coastguard Worker }
478*f6dc9357SAndroid Build Coastguard Worker else
479*f6dc9357SAndroid Build Coastguard Worker {
480*f6dc9357SAndroid Build Coastguard Worker tb.StringSize = i;
481*f6dc9357SAndroid Build Coastguard Worker if (i != size)
482*f6dc9357SAndroid Build Coastguard Worker {
483*f6dc9357SAndroid Build Coastguard Worker tb.StringSize_IsConfirmed = true;
484*f6dc9357SAndroid Build Coastguard Worker if (IsBufNonZero(p + i, size - i))
485*f6dc9357SAndroid Build Coastguard Worker tb.IsNonZeroTail = true;
486*f6dc9357SAndroid Build Coastguard Worker }
487*f6dc9357SAndroid Build Coastguard Worker }
488*f6dc9357SAndroid Build Coastguard Worker
489*f6dc9357SAndroid Build Coastguard Worker if (packSize == 0)
490*f6dc9357SAndroid Build Coastguard Worker return S_OK;
491*f6dc9357SAndroid Build Coastguard Worker }
492*f6dc9357SAndroid Build Coastguard Worker
493*f6dc9357SAndroid Build Coastguard Worker if (InStream)
494*f6dc9357SAndroid Build Coastguard Worker {
495*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream->Seek((Int64)packSize, STREAM_SEEK_CUR, NULL))
496*f6dc9357SAndroid Build Coastguard Worker return S_OK;
497*f6dc9357SAndroid Build Coastguard Worker }
498*f6dc9357SAndroid Build Coastguard Worker const unsigned kBufSize = 1 << 15;
499*f6dc9357SAndroid Build Coastguard Worker Buffer.AllocAtLeast(kBufSize);
500*f6dc9357SAndroid Build Coastguard Worker
501*f6dc9357SAndroid Build Coastguard Worker do
502*f6dc9357SAndroid Build Coastguard Worker {
503*f6dc9357SAndroid Build Coastguard Worker if (OpenCallback)
504*f6dc9357SAndroid Build Coastguard Worker {
505*f6dc9357SAndroid Build Coastguard Worker RINOK(Progress(item, pos))
506*f6dc9357SAndroid Build Coastguard Worker }
507*f6dc9357SAndroid Build Coastguard Worker
508*f6dc9357SAndroid Build Coastguard Worker unsigned size = kBufSize;
509*f6dc9357SAndroid Build Coastguard Worker if (size > packSize)
510*f6dc9357SAndroid Build Coastguard Worker size = (unsigned)packSize;
511*f6dc9357SAndroid Build Coastguard Worker size_t processedSize = size;
512*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = ReadStream(SeqStream, Buffer, &processedSize);
513*f6dc9357SAndroid Build Coastguard Worker if (processedSize != size)
514*f6dc9357SAndroid Build Coastguard Worker {
515*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_UnexpectedEnd;
516*f6dc9357SAndroid Build Coastguard Worker return res;
517*f6dc9357SAndroid Build Coastguard Worker }
518*f6dc9357SAndroid Build Coastguard Worker if (!tb.IsNonZeroTail)
519*f6dc9357SAndroid Build Coastguard Worker {
520*f6dc9357SAndroid Build Coastguard Worker if (IsBufNonZero(Buffer, size))
521*f6dc9357SAndroid Build Coastguard Worker tb.IsNonZeroTail = true;
522*f6dc9357SAndroid Build Coastguard Worker }
523*f6dc9357SAndroid Build Coastguard Worker packSize -= size;
524*f6dc9357SAndroid Build Coastguard Worker pos += size;
525*f6dc9357SAndroid Build Coastguard Worker }
526*f6dc9357SAndroid Build Coastguard Worker while (packSize != 0);
527*f6dc9357SAndroid Build Coastguard Worker return S_OK;
528*f6dc9357SAndroid Build Coastguard Worker }
529*f6dc9357SAndroid Build Coastguard Worker
530*f6dc9357SAndroid Build Coastguard Worker
531*f6dc9357SAndroid Build Coastguard Worker
532*f6dc9357SAndroid Build Coastguard Worker struct CPaxInfo: public CPaxTimes
533*f6dc9357SAndroid Build Coastguard Worker {
534*f6dc9357SAndroid Build Coastguard Worker bool DoubleTagError;
535*f6dc9357SAndroid Build Coastguard Worker bool TagParsingError;
536*f6dc9357SAndroid Build Coastguard Worker bool UnknownLines_Overflow;
537*f6dc9357SAndroid Build Coastguard Worker bool Size_Defined;
538*f6dc9357SAndroid Build Coastguard Worker bool UID_Defined;
539*f6dc9357SAndroid Build Coastguard Worker bool GID_Defined;
540*f6dc9357SAndroid Build Coastguard Worker bool Path_Defined;
541*f6dc9357SAndroid Build Coastguard Worker bool Link_Defined;
542*f6dc9357SAndroid Build Coastguard Worker bool User_Defined;
543*f6dc9357SAndroid Build Coastguard Worker bool Group_Defined;
544*f6dc9357SAndroid Build Coastguard Worker bool SCHILY_fflags_Defined;
545*f6dc9357SAndroid Build Coastguard Worker
546*f6dc9357SAndroid Build Coastguard Worker UInt64 Size;
547*f6dc9357SAndroid Build Coastguard Worker UInt32 UID;
548*f6dc9357SAndroid Build Coastguard Worker UInt32 GID;
549*f6dc9357SAndroid Build Coastguard Worker
550*f6dc9357SAndroid Build Coastguard Worker AString Path;
551*f6dc9357SAndroid Build Coastguard Worker AString Link;
552*f6dc9357SAndroid Build Coastguard Worker AString User;
553*f6dc9357SAndroid Build Coastguard Worker AString Group;
554*f6dc9357SAndroid Build Coastguard Worker AString UnknownLines;
555*f6dc9357SAndroid Build Coastguard Worker AString SCHILY_fflags;
556*f6dc9357SAndroid Build Coastguard Worker
ParseIDNArchive::NTar::CPaxInfo557*f6dc9357SAndroid Build Coastguard Worker bool ParseID(const AString &val, bool &defined, UInt32 &res)
558*f6dc9357SAndroid Build Coastguard Worker {
559*f6dc9357SAndroid Build Coastguard Worker if (defined)
560*f6dc9357SAndroid Build Coastguard Worker DoubleTagError = true;
561*f6dc9357SAndroid Build Coastguard Worker if (val.IsEmpty())
562*f6dc9357SAndroid Build Coastguard Worker return false;
563*f6dc9357SAndroid Build Coastguard Worker const char *end2;
564*f6dc9357SAndroid Build Coastguard Worker res = ConvertStringToUInt32(val.Ptr(), &end2);
565*f6dc9357SAndroid Build Coastguard Worker if (*end2 != 0)
566*f6dc9357SAndroid Build Coastguard Worker return false;
567*f6dc9357SAndroid Build Coastguard Worker defined = true;
568*f6dc9357SAndroid Build Coastguard Worker return true;
569*f6dc9357SAndroid Build Coastguard Worker }
570*f6dc9357SAndroid Build Coastguard Worker
571*f6dc9357SAndroid Build Coastguard Worker bool ParsePax(const CTempBuffer &tb, bool isFile);
572*f6dc9357SAndroid Build Coastguard Worker };
573*f6dc9357SAndroid Build Coastguard Worker
574*f6dc9357SAndroid Build Coastguard Worker
ParsePaxTime(const AString & src,CPaxTime & pt,bool & doubleTagError)575*f6dc9357SAndroid Build Coastguard Worker static bool ParsePaxTime(const AString &src, CPaxTime &pt, bool &doubleTagError)
576*f6dc9357SAndroid Build Coastguard Worker {
577*f6dc9357SAndroid Build Coastguard Worker if (pt.IsDefined())
578*f6dc9357SAndroid Build Coastguard Worker doubleTagError = true;
579*f6dc9357SAndroid Build Coastguard Worker pt.Clear();
580*f6dc9357SAndroid Build Coastguard Worker const char *s = src.Ptr();
581*f6dc9357SAndroid Build Coastguard Worker bool isNegative = false;
582*f6dc9357SAndroid Build Coastguard Worker if (*s == '-')
583*f6dc9357SAndroid Build Coastguard Worker {
584*f6dc9357SAndroid Build Coastguard Worker isNegative = true;
585*f6dc9357SAndroid Build Coastguard Worker s++;
586*f6dc9357SAndroid Build Coastguard Worker }
587*f6dc9357SAndroid Build Coastguard Worker const char *end;
588*f6dc9357SAndroid Build Coastguard Worker {
589*f6dc9357SAndroid Build Coastguard Worker UInt64 sec = ConvertStringToUInt64(s, &end);
590*f6dc9357SAndroid Build Coastguard Worker if (s == end)
591*f6dc9357SAndroid Build Coastguard Worker return false;
592*f6dc9357SAndroid Build Coastguard Worker if (sec >= ((UInt64)1 << 63))
593*f6dc9357SAndroid Build Coastguard Worker return false;
594*f6dc9357SAndroid Build Coastguard Worker if (isNegative)
595*f6dc9357SAndroid Build Coastguard Worker sec = (UInt64)-(Int64)sec;
596*f6dc9357SAndroid Build Coastguard Worker pt.Sec = (Int64)sec;
597*f6dc9357SAndroid Build Coastguard Worker }
598*f6dc9357SAndroid Build Coastguard Worker if (*end == 0)
599*f6dc9357SAndroid Build Coastguard Worker {
600*f6dc9357SAndroid Build Coastguard Worker pt.Ns = 0;
601*f6dc9357SAndroid Build Coastguard Worker pt.NumDigits = 0;
602*f6dc9357SAndroid Build Coastguard Worker return true;
603*f6dc9357SAndroid Build Coastguard Worker }
604*f6dc9357SAndroid Build Coastguard Worker if (*end != '.')
605*f6dc9357SAndroid Build Coastguard Worker return false;
606*f6dc9357SAndroid Build Coastguard Worker s = end + 1;
607*f6dc9357SAndroid Build Coastguard Worker
608*f6dc9357SAndroid Build Coastguard Worker UInt32 ns = 0;
609*f6dc9357SAndroid Build Coastguard Worker unsigned i;
610*f6dc9357SAndroid Build Coastguard Worker const unsigned kNsDigits = 9;
611*f6dc9357SAndroid Build Coastguard Worker for (i = 0;; i++)
612*f6dc9357SAndroid Build Coastguard Worker {
613*f6dc9357SAndroid Build Coastguard Worker const char c = s[i];
614*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
615*f6dc9357SAndroid Build Coastguard Worker break;
616*f6dc9357SAndroid Build Coastguard Worker if (c < '0' || c > '9')
617*f6dc9357SAndroid Build Coastguard Worker return false;
618*f6dc9357SAndroid Build Coastguard Worker // we ignore digits after 9 digits as GNU TAR
619*f6dc9357SAndroid Build Coastguard Worker if (i < kNsDigits)
620*f6dc9357SAndroid Build Coastguard Worker {
621*f6dc9357SAndroid Build Coastguard Worker ns *= 10;
622*f6dc9357SAndroid Build Coastguard Worker ns += (unsigned)(c - '0');
623*f6dc9357SAndroid Build Coastguard Worker }
624*f6dc9357SAndroid Build Coastguard Worker }
625*f6dc9357SAndroid Build Coastguard Worker pt.NumDigits = (int)(i < kNsDigits ? i : kNsDigits);
626*f6dc9357SAndroid Build Coastguard Worker while (i < kNsDigits)
627*f6dc9357SAndroid Build Coastguard Worker {
628*f6dc9357SAndroid Build Coastguard Worker ns *= 10;
629*f6dc9357SAndroid Build Coastguard Worker i++;
630*f6dc9357SAndroid Build Coastguard Worker }
631*f6dc9357SAndroid Build Coastguard Worker if (isNegative && ns != 0)
632*f6dc9357SAndroid Build Coastguard Worker {
633*f6dc9357SAndroid Build Coastguard Worker pt.Sec--;
634*f6dc9357SAndroid Build Coastguard Worker ns = (UInt32)1000 * 1000 * 1000 - ns;
635*f6dc9357SAndroid Build Coastguard Worker }
636*f6dc9357SAndroid Build Coastguard Worker pt.Ns = ns;
637*f6dc9357SAndroid Build Coastguard Worker return true;
638*f6dc9357SAndroid Build Coastguard Worker }
639*f6dc9357SAndroid Build Coastguard Worker
640*f6dc9357SAndroid Build Coastguard Worker
ParsePax(const CTempBuffer & tb,bool isFile)641*f6dc9357SAndroid Build Coastguard Worker bool CPaxInfo::ParsePax(const CTempBuffer &tb, bool isFile)
642*f6dc9357SAndroid Build Coastguard Worker {
643*f6dc9357SAndroid Build Coastguard Worker DoubleTagError = false;
644*f6dc9357SAndroid Build Coastguard Worker TagParsingError = false;
645*f6dc9357SAndroid Build Coastguard Worker UnknownLines_Overflow = false;
646*f6dc9357SAndroid Build Coastguard Worker Size_Defined = false;
647*f6dc9357SAndroid Build Coastguard Worker UID_Defined = false;
648*f6dc9357SAndroid Build Coastguard Worker GID_Defined = false;
649*f6dc9357SAndroid Build Coastguard Worker Path_Defined = false;
650*f6dc9357SAndroid Build Coastguard Worker Link_Defined = false;
651*f6dc9357SAndroid Build Coastguard Worker User_Defined = false;
652*f6dc9357SAndroid Build Coastguard Worker Group_Defined = false;
653*f6dc9357SAndroid Build Coastguard Worker SCHILY_fflags_Defined = false;
654*f6dc9357SAndroid Build Coastguard Worker
655*f6dc9357SAndroid Build Coastguard Worker // CPaxTimes::Clear();
656*f6dc9357SAndroid Build Coastguard Worker
657*f6dc9357SAndroid Build Coastguard Worker const char *s = (const char *)(const void *)(const Byte *)tb.Buffer;
658*f6dc9357SAndroid Build Coastguard Worker size_t rem = tb.StringSize;
659*f6dc9357SAndroid Build Coastguard Worker
660*f6dc9357SAndroid Build Coastguard Worker Clear();
661*f6dc9357SAndroid Build Coastguard Worker
662*f6dc9357SAndroid Build Coastguard Worker AString name, val;
663*f6dc9357SAndroid Build Coastguard Worker
664*f6dc9357SAndroid Build Coastguard Worker while (rem != 0)
665*f6dc9357SAndroid Build Coastguard Worker {
666*f6dc9357SAndroid Build Coastguard Worker unsigned i;
667*f6dc9357SAndroid Build Coastguard Worker for (i = 0;; i++)
668*f6dc9357SAndroid Build Coastguard Worker {
669*f6dc9357SAndroid Build Coastguard Worker if (i > 24 || i >= rem) // we use limitation for size of (size) field
670*f6dc9357SAndroid Build Coastguard Worker return false;
671*f6dc9357SAndroid Build Coastguard Worker if (s[i] == ' ')
672*f6dc9357SAndroid Build Coastguard Worker break;
673*f6dc9357SAndroid Build Coastguard Worker }
674*f6dc9357SAndroid Build Coastguard Worker if (i == 0)
675*f6dc9357SAndroid Build Coastguard Worker return false;
676*f6dc9357SAndroid Build Coastguard Worker const char *end;
677*f6dc9357SAndroid Build Coastguard Worker const UInt32 size = ConvertStringToUInt32(s, &end);
678*f6dc9357SAndroid Build Coastguard Worker const unsigned offset = (unsigned)(end - s) + 1;
679*f6dc9357SAndroid Build Coastguard Worker if (size > rem
680*f6dc9357SAndroid Build Coastguard Worker || size <= offset + 1
681*f6dc9357SAndroid Build Coastguard Worker || offset != i + 1
682*f6dc9357SAndroid Build Coastguard Worker || s[size - 1] != '\n')
683*f6dc9357SAndroid Build Coastguard Worker return false;
684*f6dc9357SAndroid Build Coastguard Worker
685*f6dc9357SAndroid Build Coastguard Worker for (i = offset; i < size; i++)
686*f6dc9357SAndroid Build Coastguard Worker if (s[i] == 0)
687*f6dc9357SAndroid Build Coastguard Worker return false;
688*f6dc9357SAndroid Build Coastguard Worker
689*f6dc9357SAndroid Build Coastguard Worker for (i = offset; i < size - 1; i++)
690*f6dc9357SAndroid Build Coastguard Worker if (s[i] == '=')
691*f6dc9357SAndroid Build Coastguard Worker break;
692*f6dc9357SAndroid Build Coastguard Worker if (i == size - 1)
693*f6dc9357SAndroid Build Coastguard Worker return false;
694*f6dc9357SAndroid Build Coastguard Worker
695*f6dc9357SAndroid Build Coastguard Worker name.SetFrom(s + offset, i - offset);
696*f6dc9357SAndroid Build Coastguard Worker val.SetFrom(s + i + 1, (unsigned)(size - 1 - (i + 1)));
697*f6dc9357SAndroid Build Coastguard Worker
698*f6dc9357SAndroid Build Coastguard Worker bool parsed = false;
699*f6dc9357SAndroid Build Coastguard Worker if (isFile)
700*f6dc9357SAndroid Build Coastguard Worker {
701*f6dc9357SAndroid Build Coastguard Worker bool isDetectedName = true;
702*f6dc9357SAndroid Build Coastguard Worker // only lower case (name) is supported
703*f6dc9357SAndroid Build Coastguard Worker if (name.IsEqualTo("path"))
704*f6dc9357SAndroid Build Coastguard Worker {
705*f6dc9357SAndroid Build Coastguard Worker if (Path_Defined)
706*f6dc9357SAndroid Build Coastguard Worker DoubleTagError = true;
707*f6dc9357SAndroid Build Coastguard Worker Path = val;
708*f6dc9357SAndroid Build Coastguard Worker Path_Defined = true;
709*f6dc9357SAndroid Build Coastguard Worker parsed = true;
710*f6dc9357SAndroid Build Coastguard Worker }
711*f6dc9357SAndroid Build Coastguard Worker else if (name.IsEqualTo("linkpath"))
712*f6dc9357SAndroid Build Coastguard Worker {
713*f6dc9357SAndroid Build Coastguard Worker if (Link_Defined)
714*f6dc9357SAndroid Build Coastguard Worker DoubleTagError = true;
715*f6dc9357SAndroid Build Coastguard Worker Link = val;
716*f6dc9357SAndroid Build Coastguard Worker Link_Defined = true;
717*f6dc9357SAndroid Build Coastguard Worker parsed = true;
718*f6dc9357SAndroid Build Coastguard Worker }
719*f6dc9357SAndroid Build Coastguard Worker else if (name.IsEqualTo("uname"))
720*f6dc9357SAndroid Build Coastguard Worker {
721*f6dc9357SAndroid Build Coastguard Worker if (User_Defined)
722*f6dc9357SAndroid Build Coastguard Worker DoubleTagError = true;
723*f6dc9357SAndroid Build Coastguard Worker User = val;
724*f6dc9357SAndroid Build Coastguard Worker User_Defined = true;
725*f6dc9357SAndroid Build Coastguard Worker parsed = true;
726*f6dc9357SAndroid Build Coastguard Worker }
727*f6dc9357SAndroid Build Coastguard Worker else if (name.IsEqualTo("gname"))
728*f6dc9357SAndroid Build Coastguard Worker {
729*f6dc9357SAndroid Build Coastguard Worker if (Group_Defined)
730*f6dc9357SAndroid Build Coastguard Worker DoubleTagError = true;
731*f6dc9357SAndroid Build Coastguard Worker Group = val;
732*f6dc9357SAndroid Build Coastguard Worker Group_Defined = true;
733*f6dc9357SAndroid Build Coastguard Worker parsed = true;
734*f6dc9357SAndroid Build Coastguard Worker }
735*f6dc9357SAndroid Build Coastguard Worker else if (name.IsEqualTo("uid"))
736*f6dc9357SAndroid Build Coastguard Worker {
737*f6dc9357SAndroid Build Coastguard Worker parsed = ParseID(val, UID_Defined, UID);
738*f6dc9357SAndroid Build Coastguard Worker }
739*f6dc9357SAndroid Build Coastguard Worker else if (name.IsEqualTo("gid"))
740*f6dc9357SAndroid Build Coastguard Worker {
741*f6dc9357SAndroid Build Coastguard Worker parsed = ParseID(val, GID_Defined, GID);
742*f6dc9357SAndroid Build Coastguard Worker }
743*f6dc9357SAndroid Build Coastguard Worker else if (name.IsEqualTo("size"))
744*f6dc9357SAndroid Build Coastguard Worker {
745*f6dc9357SAndroid Build Coastguard Worker if (Size_Defined)
746*f6dc9357SAndroid Build Coastguard Worker DoubleTagError = true;
747*f6dc9357SAndroid Build Coastguard Worker Size_Defined = false;
748*f6dc9357SAndroid Build Coastguard Worker if (!val.IsEmpty())
749*f6dc9357SAndroid Build Coastguard Worker {
750*f6dc9357SAndroid Build Coastguard Worker const char *end2;
751*f6dc9357SAndroid Build Coastguard Worker Size = ConvertStringToUInt64(val.Ptr(), &end2);
752*f6dc9357SAndroid Build Coastguard Worker if (*end2 == 0)
753*f6dc9357SAndroid Build Coastguard Worker {
754*f6dc9357SAndroid Build Coastguard Worker Size_Defined = true;
755*f6dc9357SAndroid Build Coastguard Worker parsed = true;
756*f6dc9357SAndroid Build Coastguard Worker }
757*f6dc9357SAndroid Build Coastguard Worker }
758*f6dc9357SAndroid Build Coastguard Worker }
759*f6dc9357SAndroid Build Coastguard Worker else if (name.IsEqualTo("mtime"))
760*f6dc9357SAndroid Build Coastguard Worker { parsed = ParsePaxTime(val, MTime, DoubleTagError); }
761*f6dc9357SAndroid Build Coastguard Worker else if (name.IsEqualTo("atime"))
762*f6dc9357SAndroid Build Coastguard Worker { parsed = ParsePaxTime(val, ATime, DoubleTagError); }
763*f6dc9357SAndroid Build Coastguard Worker else if (name.IsEqualTo("ctime"))
764*f6dc9357SAndroid Build Coastguard Worker { parsed = ParsePaxTime(val, CTime, DoubleTagError); }
765*f6dc9357SAndroid Build Coastguard Worker else if (name.IsEqualTo("SCHILY.fflags"))
766*f6dc9357SAndroid Build Coastguard Worker {
767*f6dc9357SAndroid Build Coastguard Worker if (SCHILY_fflags_Defined)
768*f6dc9357SAndroid Build Coastguard Worker DoubleTagError = true;
769*f6dc9357SAndroid Build Coastguard Worker SCHILY_fflags = val;
770*f6dc9357SAndroid Build Coastguard Worker SCHILY_fflags_Defined = true;
771*f6dc9357SAndroid Build Coastguard Worker parsed = true;
772*f6dc9357SAndroid Build Coastguard Worker }
773*f6dc9357SAndroid Build Coastguard Worker else
774*f6dc9357SAndroid Build Coastguard Worker isDetectedName = false;
775*f6dc9357SAndroid Build Coastguard Worker if (isDetectedName && !parsed)
776*f6dc9357SAndroid Build Coastguard Worker TagParsingError = true;
777*f6dc9357SAndroid Build Coastguard Worker }
778*f6dc9357SAndroid Build Coastguard Worker if (!parsed)
779*f6dc9357SAndroid Build Coastguard Worker {
780*f6dc9357SAndroid Build Coastguard Worker if (!UnknownLines_Overflow)
781*f6dc9357SAndroid Build Coastguard Worker {
782*f6dc9357SAndroid Build Coastguard Worker const unsigned addSize = size - offset;
783*f6dc9357SAndroid Build Coastguard Worker if (UnknownLines.Len() + addSize < (1 << 16))
784*f6dc9357SAndroid Build Coastguard Worker UnknownLines.AddFrom(s + offset, addSize);
785*f6dc9357SAndroid Build Coastguard Worker else
786*f6dc9357SAndroid Build Coastguard Worker UnknownLines_Overflow = true;
787*f6dc9357SAndroid Build Coastguard Worker }
788*f6dc9357SAndroid Build Coastguard Worker }
789*f6dc9357SAndroid Build Coastguard Worker
790*f6dc9357SAndroid Build Coastguard Worker s += size;
791*f6dc9357SAndroid Build Coastguard Worker rem -= size;
792*f6dc9357SAndroid Build Coastguard Worker }
793*f6dc9357SAndroid Build Coastguard Worker return true;
794*f6dc9357SAndroid Build Coastguard Worker }
795*f6dc9357SAndroid Build Coastguard Worker
796*f6dc9357SAndroid Build Coastguard Worker
ReadItem2(CItemEx & item)797*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchive::ReadItem2(CItemEx &item)
798*f6dc9357SAndroid Build Coastguard Worker {
799*f6dc9357SAndroid Build Coastguard Worker // CItem
800*f6dc9357SAndroid Build Coastguard Worker
801*f6dc9357SAndroid Build Coastguard Worker item.SparseBlocks.Clear();
802*f6dc9357SAndroid Build Coastguard Worker item.PaxTimes.Clear();
803*f6dc9357SAndroid Build Coastguard Worker
804*f6dc9357SAndroid Build Coastguard Worker // CItemEx
805*f6dc9357SAndroid Build Coastguard Worker
806*f6dc9357SAndroid Build Coastguard Worker item.HeaderSize = 0;
807*f6dc9357SAndroid Build Coastguard Worker item.Num_Pax_Records = 0;
808*f6dc9357SAndroid Build Coastguard Worker
809*f6dc9357SAndroid Build Coastguard Worker item.LongName_WasUsed = false;
810*f6dc9357SAndroid Build Coastguard Worker item.LongName_WasUsed_2 = false;
811*f6dc9357SAndroid Build Coastguard Worker
812*f6dc9357SAndroid Build Coastguard Worker item.LongLink_WasUsed = false;
813*f6dc9357SAndroid Build Coastguard Worker item.LongLink_WasUsed_2 = false;
814*f6dc9357SAndroid Build Coastguard Worker
815*f6dc9357SAndroid Build Coastguard Worker item.HeaderError = false;
816*f6dc9357SAndroid Build Coastguard Worker item.IsSignedChecksum = false;
817*f6dc9357SAndroid Build Coastguard Worker item.Prefix_WasUsed = false;
818*f6dc9357SAndroid Build Coastguard Worker
819*f6dc9357SAndroid Build Coastguard Worker item.Pax_Error = false;
820*f6dc9357SAndroid Build Coastguard Worker item.Pax_Overflow = false;
821*f6dc9357SAndroid Build Coastguard Worker item.pax_path_WasUsed = false;
822*f6dc9357SAndroid Build Coastguard Worker item.pax_link_WasUsed = false;
823*f6dc9357SAndroid Build Coastguard Worker item.pax_size_WasUsed = false;
824*f6dc9357SAndroid Build Coastguard Worker
825*f6dc9357SAndroid Build Coastguard Worker item.PaxExtra.Clear();
826*f6dc9357SAndroid Build Coastguard Worker item.SCHILY_fflags.Empty();
827*f6dc9357SAndroid Build Coastguard Worker
828*f6dc9357SAndroid Build Coastguard Worker item.EncodingCharacts.Clear();
829*f6dc9357SAndroid Build Coastguard Worker
830*f6dc9357SAndroid Build Coastguard Worker // CArchive temp variable
831*f6dc9357SAndroid Build Coastguard Worker
832*f6dc9357SAndroid Build Coastguard Worker NameBuf.Init();
833*f6dc9357SAndroid Build Coastguard Worker LinkBuf.Init();
834*f6dc9357SAndroid Build Coastguard Worker PaxBuf.Init();
835*f6dc9357SAndroid Build Coastguard Worker PaxBuf_global.Init();
836*f6dc9357SAndroid Build Coastguard Worker
837*f6dc9357SAndroid Build Coastguard Worker UInt64 numExtraRecords = 0;
838*f6dc9357SAndroid Build Coastguard Worker
839*f6dc9357SAndroid Build Coastguard Worker for (;;)
840*f6dc9357SAndroid Build Coastguard Worker {
841*f6dc9357SAndroid Build Coastguard Worker if (OpenCallback)
842*f6dc9357SAndroid Build Coastguard Worker {
843*f6dc9357SAndroid Build Coastguard Worker RINOK(Progress(item, 0))
844*f6dc9357SAndroid Build Coastguard Worker }
845*f6dc9357SAndroid Build Coastguard Worker
846*f6dc9357SAndroid Build Coastguard Worker RINOK(GetNextItemReal(item))
847*f6dc9357SAndroid Build Coastguard Worker
848*f6dc9357SAndroid Build Coastguard Worker // NumRecords++;
849*f6dc9357SAndroid Build Coastguard Worker
850*f6dc9357SAndroid Build Coastguard Worker if (!filled)
851*f6dc9357SAndroid Build Coastguard Worker {
852*f6dc9357SAndroid Build Coastguard Worker if (error == k_ErrorType_OK)
853*f6dc9357SAndroid Build Coastguard Worker if (numExtraRecords != 0
854*f6dc9357SAndroid Build Coastguard Worker || item.LongName_WasUsed
855*f6dc9357SAndroid Build Coastguard Worker || item.LongLink_WasUsed
856*f6dc9357SAndroid Build Coastguard Worker || item.Num_Pax_Records != 0)
857*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_Corrupted;
858*f6dc9357SAndroid Build Coastguard Worker return S_OK;
859*f6dc9357SAndroid Build Coastguard Worker }
860*f6dc9357SAndroid Build Coastguard Worker if (error != k_ErrorType_OK)
861*f6dc9357SAndroid Build Coastguard Worker return S_OK;
862*f6dc9357SAndroid Build Coastguard Worker
863*f6dc9357SAndroid Build Coastguard Worker numExtraRecords++;
864*f6dc9357SAndroid Build Coastguard Worker
865*f6dc9357SAndroid Build Coastguard Worker const char lf = item.LinkFlag;
866*f6dc9357SAndroid Build Coastguard Worker if (lf == NFileHeader::NLinkFlag::kGnu_LongName ||
867*f6dc9357SAndroid Build Coastguard Worker lf == NFileHeader::NLinkFlag::kGnu_LongLink)
868*f6dc9357SAndroid Build Coastguard Worker {
869*f6dc9357SAndroid Build Coastguard Worker // GNU tar ignores item.Name after LinkFlag test
870*f6dc9357SAndroid Build Coastguard Worker // 22.00 : now we also ignore item.Name here
871*f6dc9357SAndroid Build Coastguard Worker /*
872*f6dc9357SAndroid Build Coastguard Worker if (item.Name != NFileHeader::kLongLink &&
873*f6dc9357SAndroid Build Coastguard Worker item.Name != NFileHeader::kLongLink2)
874*f6dc9357SAndroid Build Coastguard Worker {
875*f6dc9357SAndroid Build Coastguard Worker break;
876*f6dc9357SAndroid Build Coastguard Worker // return S_OK;
877*f6dc9357SAndroid Build Coastguard Worker }
878*f6dc9357SAndroid Build Coastguard Worker */
879*f6dc9357SAndroid Build Coastguard Worker
880*f6dc9357SAndroid Build Coastguard Worker CTempBuffer *tb =
881*f6dc9357SAndroid Build Coastguard Worker lf == NFileHeader::NLinkFlag::kGnu_LongName ?
882*f6dc9357SAndroid Build Coastguard Worker &NameBuf :
883*f6dc9357SAndroid Build Coastguard Worker &LinkBuf;
884*f6dc9357SAndroid Build Coastguard Worker
885*f6dc9357SAndroid Build Coastguard Worker /*
886*f6dc9357SAndroid Build Coastguard Worker if (item.PackSize > (1 << 29))
887*f6dc9357SAndroid Build Coastguard Worker {
888*f6dc9357SAndroid Build Coastguard Worker // break;
889*f6dc9357SAndroid Build Coastguard Worker return S_OK;
890*f6dc9357SAndroid Build Coastguard Worker }
891*f6dc9357SAndroid Build Coastguard Worker */
892*f6dc9357SAndroid Build Coastguard Worker
893*f6dc9357SAndroid Build Coastguard Worker const unsigned kLongNameSizeMax = (unsigned)1 << 14;
894*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadDataToBuffer(item, *tb, kLongNameSizeMax))
895*f6dc9357SAndroid Build Coastguard Worker if (error != k_ErrorType_OK)
896*f6dc9357SAndroid Build Coastguard Worker return S_OK;
897*f6dc9357SAndroid Build Coastguard Worker
898*f6dc9357SAndroid Build Coastguard Worker if (lf == NFileHeader::NLinkFlag::kGnu_LongName)
899*f6dc9357SAndroid Build Coastguard Worker {
900*f6dc9357SAndroid Build Coastguard Worker item.LongName_WasUsed_2 =
901*f6dc9357SAndroid Build Coastguard Worker item.LongName_WasUsed;
902*f6dc9357SAndroid Build Coastguard Worker item.LongName_WasUsed = true;
903*f6dc9357SAndroid Build Coastguard Worker }
904*f6dc9357SAndroid Build Coastguard Worker else
905*f6dc9357SAndroid Build Coastguard Worker {
906*f6dc9357SAndroid Build Coastguard Worker item.LongLink_WasUsed_2 =
907*f6dc9357SAndroid Build Coastguard Worker item.LongLink_WasUsed;
908*f6dc9357SAndroid Build Coastguard Worker item.LongLink_WasUsed = true;
909*f6dc9357SAndroid Build Coastguard Worker }
910*f6dc9357SAndroid Build Coastguard Worker
911*f6dc9357SAndroid Build Coastguard Worker if (!tb->StringSize_IsConfirmed)
912*f6dc9357SAndroid Build Coastguard Worker tb->StringSize = 0;
913*f6dc9357SAndroid Build Coastguard Worker item.HeaderSize += item.Get_PackSize_Aligned();
914*f6dc9357SAndroid Build Coastguard Worker if (tb->StringSize == 0 ||
915*f6dc9357SAndroid Build Coastguard Worker tb->StringSize + 1 != item.PackSize)
916*f6dc9357SAndroid Build Coastguard Worker item.HeaderError = true;
917*f6dc9357SAndroid Build Coastguard Worker if (tb->IsNonZeroTail)
918*f6dc9357SAndroid Build Coastguard Worker item.HeaderError = true;
919*f6dc9357SAndroid Build Coastguard Worker continue;
920*f6dc9357SAndroid Build Coastguard Worker }
921*f6dc9357SAndroid Build Coastguard Worker
922*f6dc9357SAndroid Build Coastguard Worker if (lf == NFileHeader::NLinkFlag::kGlobal ||
923*f6dc9357SAndroid Build Coastguard Worker lf == NFileHeader::NLinkFlag::kPax ||
924*f6dc9357SAndroid Build Coastguard Worker lf == NFileHeader::NLinkFlag::kPax_2)
925*f6dc9357SAndroid Build Coastguard Worker {
926*f6dc9357SAndroid Build Coastguard Worker // GNU tar ignores item.Name after LinkFlag test
927*f6dc9357SAndroid Build Coastguard Worker // 22.00 : now we also ignore item.Name here
928*f6dc9357SAndroid Build Coastguard Worker /*
929*f6dc9357SAndroid Build Coastguard Worker if (item.PackSize > (UInt32)1 << 26)
930*f6dc9357SAndroid Build Coastguard Worker {
931*f6dc9357SAndroid Build Coastguard Worker break; // we don't want big PaxBuf files
932*f6dc9357SAndroid Build Coastguard Worker // return S_OK;
933*f6dc9357SAndroid Build Coastguard Worker }
934*f6dc9357SAndroid Build Coastguard Worker */
935*f6dc9357SAndroid Build Coastguard Worker const unsigned kParsingPaxSizeMax = (unsigned)1 << 26;
936*f6dc9357SAndroid Build Coastguard Worker
937*f6dc9357SAndroid Build Coastguard Worker const bool isStartHeader = (item.HeaderSize == NFileHeader::kRecordSize);
938*f6dc9357SAndroid Build Coastguard Worker
939*f6dc9357SAndroid Build Coastguard Worker CTempBuffer *tb = (lf == NFileHeader::NLinkFlag::kGlobal ? &PaxBuf_global : &PaxBuf);
940*f6dc9357SAndroid Build Coastguard Worker
941*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadDataToBuffer(item, *tb, kParsingPaxSizeMax))
942*f6dc9357SAndroid Build Coastguard Worker if (error != k_ErrorType_OK)
943*f6dc9357SAndroid Build Coastguard Worker return S_OK;
944*f6dc9357SAndroid Build Coastguard Worker
945*f6dc9357SAndroid Build Coastguard Worker item.HeaderSize += item.Get_PackSize_Aligned();
946*f6dc9357SAndroid Build Coastguard Worker
947*f6dc9357SAndroid Build Coastguard Worker if (tb->StringSize != item.PackSize
948*f6dc9357SAndroid Build Coastguard Worker || tb->StringSize == 0
949*f6dc9357SAndroid Build Coastguard Worker || tb->IsNonZeroTail)
950*f6dc9357SAndroid Build Coastguard Worker item.Pax_Error = true;
951*f6dc9357SAndroid Build Coastguard Worker
952*f6dc9357SAndroid Build Coastguard Worker item.Num_Pax_Records++;
953*f6dc9357SAndroid Build Coastguard Worker if (lf != NFileHeader::NLinkFlag::kGlobal)
954*f6dc9357SAndroid Build Coastguard Worker {
955*f6dc9357SAndroid Build Coastguard Worker item.PaxExtra.RecordPath = item.Name;
956*f6dc9357SAndroid Build Coastguard Worker continue;
957*f6dc9357SAndroid Build Coastguard Worker }
958*f6dc9357SAndroid Build Coastguard Worker // break; // for debug
959*f6dc9357SAndroid Build Coastguard Worker {
960*f6dc9357SAndroid Build Coastguard Worker if (PaxGlobal_Defined)
961*f6dc9357SAndroid Build Coastguard Worker _is_PaxGlobal_Error = true;
962*f6dc9357SAndroid Build Coastguard Worker CPaxInfo paxInfo;
963*f6dc9357SAndroid Build Coastguard Worker if (paxInfo.ParsePax(PaxBuf_global, false))
964*f6dc9357SAndroid Build Coastguard Worker {
965*f6dc9357SAndroid Build Coastguard Worker PaxGlobal.RawLines = paxInfo.UnknownLines;
966*f6dc9357SAndroid Build Coastguard Worker PaxGlobal.RecordPath = item.Name;
967*f6dc9357SAndroid Build Coastguard Worker PaxGlobal_Defined = true;
968*f6dc9357SAndroid Build Coastguard Worker }
969*f6dc9357SAndroid Build Coastguard Worker else
970*f6dc9357SAndroid Build Coastguard Worker _is_PaxGlobal_Error = true;
971*f6dc9357SAndroid Build Coastguard Worker
972*f6dc9357SAndroid Build Coastguard Worker if (isStartHeader
973*f6dc9357SAndroid Build Coastguard Worker && item.Num_Pax_Records == 1
974*f6dc9357SAndroid Build Coastguard Worker && numExtraRecords == 1)
975*f6dc9357SAndroid Build Coastguard Worker {
976*f6dc9357SAndroid Build Coastguard Worker // we skip global pax header info after parsing
977*f6dc9357SAndroid Build Coastguard Worker item.HeaderPos += item.HeaderSize;
978*f6dc9357SAndroid Build Coastguard Worker item.HeaderSize = 0;
979*f6dc9357SAndroid Build Coastguard Worker item.Num_Pax_Records = 0;
980*f6dc9357SAndroid Build Coastguard Worker numExtraRecords = 0;
981*f6dc9357SAndroid Build Coastguard Worker }
982*f6dc9357SAndroid Build Coastguard Worker else
983*f6dc9357SAndroid Build Coastguard Worker _is_PaxGlobal_Error = true;
984*f6dc9357SAndroid Build Coastguard Worker }
985*f6dc9357SAndroid Build Coastguard Worker continue;
986*f6dc9357SAndroid Build Coastguard Worker }
987*f6dc9357SAndroid Build Coastguard Worker
988*f6dc9357SAndroid Build Coastguard Worker /*
989*f6dc9357SAndroid Build Coastguard Worker if (lf == NFileHeader::NLinkFlag::kDumpDir ||
990*f6dc9357SAndroid Build Coastguard Worker lf == NFileHeader::NLinkFlag::kSparse)
991*f6dc9357SAndroid Build Coastguard Worker {
992*f6dc9357SAndroid Build Coastguard Worker // GNU Extensions to the Archive Format
993*f6dc9357SAndroid Build Coastguard Worker break;
994*f6dc9357SAndroid Build Coastguard Worker }
995*f6dc9357SAndroid Build Coastguard Worker if (lf > '7' || (lf < '0' && lf != 0))
996*f6dc9357SAndroid Build Coastguard Worker {
997*f6dc9357SAndroid Build Coastguard Worker break;
998*f6dc9357SAndroid Build Coastguard Worker // return S_OK;
999*f6dc9357SAndroid Build Coastguard Worker }
1000*f6dc9357SAndroid Build Coastguard Worker */
1001*f6dc9357SAndroid Build Coastguard Worker break;
1002*f6dc9357SAndroid Build Coastguard Worker }
1003*f6dc9357SAndroid Build Coastguard Worker
1004*f6dc9357SAndroid Build Coastguard Worker // we still use name from main header, if long_name is bad
1005*f6dc9357SAndroid Build Coastguard Worker if (item.LongName_WasUsed && NameBuf.StringSize != 0)
1006*f6dc9357SAndroid Build Coastguard Worker {
1007*f6dc9357SAndroid Build Coastguard Worker NameBuf.CopyToString(item.Name);
1008*f6dc9357SAndroid Build Coastguard Worker // item.Name_CouldBeReduced = false;
1009*f6dc9357SAndroid Build Coastguard Worker }
1010*f6dc9357SAndroid Build Coastguard Worker
1011*f6dc9357SAndroid Build Coastguard Worker if (item.LongLink_WasUsed)
1012*f6dc9357SAndroid Build Coastguard Worker {
1013*f6dc9357SAndroid Build Coastguard Worker // we use empty link, if long_link is bad
1014*f6dc9357SAndroid Build Coastguard Worker LinkBuf.CopyToString(item.LinkName);
1015*f6dc9357SAndroid Build Coastguard Worker // item.LinkName_CouldBeReduced = false;
1016*f6dc9357SAndroid Build Coastguard Worker }
1017*f6dc9357SAndroid Build Coastguard Worker
1018*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_OK;
1019*f6dc9357SAndroid Build Coastguard Worker
1020*f6dc9357SAndroid Build Coastguard Worker if (PaxBuf.StringSize != 0)
1021*f6dc9357SAndroid Build Coastguard Worker {
1022*f6dc9357SAndroid Build Coastguard Worker CPaxInfo paxInfo;
1023*f6dc9357SAndroid Build Coastguard Worker if (!paxInfo.ParsePax(PaxBuf, true))
1024*f6dc9357SAndroid Build Coastguard Worker item.Pax_Error = true;
1025*f6dc9357SAndroid Build Coastguard Worker else
1026*f6dc9357SAndroid Build Coastguard Worker {
1027*f6dc9357SAndroid Build Coastguard Worker if (paxInfo.Path_Defined) // if (!paxInfo.Path.IsEmpty())
1028*f6dc9357SAndroid Build Coastguard Worker {
1029*f6dc9357SAndroid Build Coastguard Worker item.Name = paxInfo.Path;
1030*f6dc9357SAndroid Build Coastguard Worker item.pax_path_WasUsed = true;
1031*f6dc9357SAndroid Build Coastguard Worker }
1032*f6dc9357SAndroid Build Coastguard Worker if (paxInfo.Link_Defined) // (!paxInfo.Link.IsEmpty())
1033*f6dc9357SAndroid Build Coastguard Worker {
1034*f6dc9357SAndroid Build Coastguard Worker item.LinkName = paxInfo.Link;
1035*f6dc9357SAndroid Build Coastguard Worker item.pax_link_WasUsed = true;
1036*f6dc9357SAndroid Build Coastguard Worker }
1037*f6dc9357SAndroid Build Coastguard Worker if (paxInfo.User_Defined)
1038*f6dc9357SAndroid Build Coastguard Worker {
1039*f6dc9357SAndroid Build Coastguard Worker item.User = paxInfo.User;
1040*f6dc9357SAndroid Build Coastguard Worker // item.pax_uname_WasUsed = true;
1041*f6dc9357SAndroid Build Coastguard Worker }
1042*f6dc9357SAndroid Build Coastguard Worker if (paxInfo.Group_Defined)
1043*f6dc9357SAndroid Build Coastguard Worker {
1044*f6dc9357SAndroid Build Coastguard Worker item.Group = paxInfo.Group;
1045*f6dc9357SAndroid Build Coastguard Worker // item.pax_gname_WasUsed = true;
1046*f6dc9357SAndroid Build Coastguard Worker }
1047*f6dc9357SAndroid Build Coastguard Worker if (paxInfo.SCHILY_fflags_Defined)
1048*f6dc9357SAndroid Build Coastguard Worker {
1049*f6dc9357SAndroid Build Coastguard Worker item.SCHILY_fflags = paxInfo.SCHILY_fflags;
1050*f6dc9357SAndroid Build Coastguard Worker // item.SCHILY_fflags_WasUsed = true;
1051*f6dc9357SAndroid Build Coastguard Worker }
1052*f6dc9357SAndroid Build Coastguard Worker if (paxInfo.UID_Defined)
1053*f6dc9357SAndroid Build Coastguard Worker {
1054*f6dc9357SAndroid Build Coastguard Worker item.UID = (UInt32)paxInfo.UID;
1055*f6dc9357SAndroid Build Coastguard Worker }
1056*f6dc9357SAndroid Build Coastguard Worker if (paxInfo.GID_Defined)
1057*f6dc9357SAndroid Build Coastguard Worker {
1058*f6dc9357SAndroid Build Coastguard Worker item.GID = (UInt32)paxInfo.GID;
1059*f6dc9357SAndroid Build Coastguard Worker }
1060*f6dc9357SAndroid Build Coastguard Worker
1061*f6dc9357SAndroid Build Coastguard Worker if (paxInfo.Size_Defined)
1062*f6dc9357SAndroid Build Coastguard Worker {
1063*f6dc9357SAndroid Build Coastguard Worker const UInt64 piSize = paxInfo.Size;
1064*f6dc9357SAndroid Build Coastguard Worker // GNU TAR ignores (item.Size) in that case
1065*f6dc9357SAndroid Build Coastguard Worker if (item.Size != 0 && item.Size != piSize)
1066*f6dc9357SAndroid Build Coastguard Worker item.Pax_Error = true;
1067*f6dc9357SAndroid Build Coastguard Worker item.Size = piSize;
1068*f6dc9357SAndroid Build Coastguard Worker item.PackSize = piSize;
1069*f6dc9357SAndroid Build Coastguard Worker item.pax_size_WasUsed = true;
1070*f6dc9357SAndroid Build Coastguard Worker }
1071*f6dc9357SAndroid Build Coastguard Worker
1072*f6dc9357SAndroid Build Coastguard Worker item.PaxTimes = paxInfo;
1073*f6dc9357SAndroid Build Coastguard Worker item.PaxExtra.RawLines = paxInfo.UnknownLines;
1074*f6dc9357SAndroid Build Coastguard Worker if (paxInfo.UnknownLines_Overflow)
1075*f6dc9357SAndroid Build Coastguard Worker item.Pax_Overflow = true;
1076*f6dc9357SAndroid Build Coastguard Worker if (paxInfo.TagParsingError)
1077*f6dc9357SAndroid Build Coastguard Worker item.Pax_Error = true;
1078*f6dc9357SAndroid Build Coastguard Worker if (paxInfo.DoubleTagError)
1079*f6dc9357SAndroid Build Coastguard Worker item.Pax_Error = true;
1080*f6dc9357SAndroid Build Coastguard Worker }
1081*f6dc9357SAndroid Build Coastguard Worker }
1082*f6dc9357SAndroid Build Coastguard Worker
1083*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1084*f6dc9357SAndroid Build Coastguard Worker }
1085*f6dc9357SAndroid Build Coastguard Worker
1086*f6dc9357SAndroid Build Coastguard Worker
1087*f6dc9357SAndroid Build Coastguard Worker
ReadItem(CItemEx & item)1088*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchive::ReadItem(CItemEx &item)
1089*f6dc9357SAndroid Build Coastguard Worker {
1090*f6dc9357SAndroid Build Coastguard Worker item.HeaderPos = _phySize;
1091*f6dc9357SAndroid Build Coastguard Worker
1092*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = ReadItem2(item);
1093*f6dc9357SAndroid Build Coastguard Worker
1094*f6dc9357SAndroid Build Coastguard Worker /*
1095*f6dc9357SAndroid Build Coastguard Worker if (error == k_ErrorType_Warning)
1096*f6dc9357SAndroid Build Coastguard Worker _is_Warning = true;
1097*f6dc9357SAndroid Build Coastguard Worker else
1098*f6dc9357SAndroid Build Coastguard Worker */
1099*f6dc9357SAndroid Build Coastguard Worker
1100*f6dc9357SAndroid Build Coastguard Worker if (error != k_ErrorType_OK)
1101*f6dc9357SAndroid Build Coastguard Worker _error = error;
1102*f6dc9357SAndroid Build Coastguard Worker
1103*f6dc9357SAndroid Build Coastguard Worker RINOK(res)
1104*f6dc9357SAndroid Build Coastguard Worker
1105*f6dc9357SAndroid Build Coastguard Worker if (filled)
1106*f6dc9357SAndroid Build Coastguard Worker {
1107*f6dc9357SAndroid Build Coastguard Worker if (item.IsMagic_GNU())
1108*f6dc9357SAndroid Build Coastguard Worker _are_Gnu = true;
1109*f6dc9357SAndroid Build Coastguard Worker else if (item.IsMagic_Posix_ustar_00())
1110*f6dc9357SAndroid Build Coastguard Worker _are_Posix = true;
1111*f6dc9357SAndroid Build Coastguard Worker
1112*f6dc9357SAndroid Build Coastguard Worker if (item.Num_Pax_Records != 0)
1113*f6dc9357SAndroid Build Coastguard Worker _are_Pax = true;
1114*f6dc9357SAndroid Build Coastguard Worker
1115*f6dc9357SAndroid Build Coastguard Worker if (item.PaxTimes.MTime.IsDefined()) _are_mtime = true;
1116*f6dc9357SAndroid Build Coastguard Worker if (item.PaxTimes.ATime.IsDefined()) _are_atime = true;
1117*f6dc9357SAndroid Build Coastguard Worker if (item.PaxTimes.CTime.IsDefined()) _are_ctime = true;
1118*f6dc9357SAndroid Build Coastguard Worker if (!item.SCHILY_fflags.IsEmpty()) _are_SCHILY_fflags = true;
1119*f6dc9357SAndroid Build Coastguard Worker
1120*f6dc9357SAndroid Build Coastguard Worker if (item.pax_path_WasUsed)
1121*f6dc9357SAndroid Build Coastguard Worker _are_pax_path = true;
1122*f6dc9357SAndroid Build Coastguard Worker if (item.pax_link_WasUsed)
1123*f6dc9357SAndroid Build Coastguard Worker _are_pax_link = true;
1124*f6dc9357SAndroid Build Coastguard Worker if (item.LongName_WasUsed)
1125*f6dc9357SAndroid Build Coastguard Worker _are_LongName = true;
1126*f6dc9357SAndroid Build Coastguard Worker if (item.LongLink_WasUsed)
1127*f6dc9357SAndroid Build Coastguard Worker _are_LongLink = true;
1128*f6dc9357SAndroid Build Coastguard Worker if (item.Prefix_WasUsed)
1129*f6dc9357SAndroid Build Coastguard Worker _pathPrefix_WasUsed = true;
1130*f6dc9357SAndroid Build Coastguard Worker /*
1131*f6dc9357SAndroid Build Coastguard Worker if (item.IsSparse())
1132*f6dc9357SAndroid Build Coastguard Worker _isSparse = true;
1133*f6dc9357SAndroid Build Coastguard Worker */
1134*f6dc9357SAndroid Build Coastguard Worker if (item.Is_PaxExtendedHeader())
1135*f6dc9357SAndroid Build Coastguard Worker _are_Pax_Items = true;
1136*f6dc9357SAndroid Build Coastguard Worker if (item.IsThereWarning()
1137*f6dc9357SAndroid Build Coastguard Worker || item.HeaderError
1138*f6dc9357SAndroid Build Coastguard Worker || item.Pax_Error)
1139*f6dc9357SAndroid Build Coastguard Worker _is_Warning = true;
1140*f6dc9357SAndroid Build Coastguard Worker }
1141*f6dc9357SAndroid Build Coastguard Worker
1142*f6dc9357SAndroid Build Coastguard Worker const UInt64 headerEnd = item.HeaderPos + item.HeaderSize;
1143*f6dc9357SAndroid Build Coastguard Worker // _headersSize += headerEnd - _phySize;
1144*f6dc9357SAndroid Build Coastguard Worker // we don't count skipped records
1145*f6dc9357SAndroid Build Coastguard Worker _headersSize += item.HeaderSize;
1146*f6dc9357SAndroid Build Coastguard Worker _phySize = headerEnd;
1147*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1148*f6dc9357SAndroid Build Coastguard Worker }
1149*f6dc9357SAndroid Build Coastguard Worker
1150*f6dc9357SAndroid Build Coastguard Worker }}
1151