xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/Tar/TarIn.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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