xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/Iso/IsoItem.h (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // Archive/IsoItem.h
2 
3 #ifndef ZIP7_INC_ARCHIVE_ISO_ITEM_H
4 #define ZIP7_INC_ARCHIVE_ISO_ITEM_H
5 
6 #include "../../../../C/CpuArch.h"
7 
8 #include "../../../Common/MyString.h"
9 #include "../../../Common/MyBuffer.h"
10 
11 #include "../../../Windows/TimeUtils.h"
12 
13 #include "IsoHeader.h"
14 
15 namespace NArchive {
16 namespace NIso {
17 
18 struct CRecordingDateTime
19 {
20   Byte Year;
21   Byte Month;
22   Byte Day;
23   Byte Hour;
24   Byte Minute;
25   Byte Second;
26   signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded.
27 
GetFileTimeCRecordingDateTime28   bool GetFileTime(NWindows::NCOM::CPropVariant &prop) const
29   {
30     UInt64 v;
31     const bool res = NWindows::NTime::GetSecondsSince1601(Year + 1900, Month, Day, Hour, Minute, Second, v);
32     if (res)
33     {
34       v = (UInt64)((Int64)v - (Int64)((Int32)GmtOffset * 15 * 60));
35       v *= 10000000;
36       prop.SetAsTimeFrom_Ft64_Prec(v, k_PropVar_TimePrec_Base);
37     }
38     return res;
39   }
40 };
41 
42 enum EPx
43 {
44   k_Px_Mode,
45   k_Px_Links,
46   k_Px_User,
47   k_Px_Group,
48   k_Px_SerialNumber
49 
50   // k_Px_Num
51 };
52 
53 /*
54 enum ETf
55 {
56   k_Tf_CTime,
57   k_Tf_MTime,
58   k_Tf_ATime,
59   k_Tf_Attrib,
60   k_Tf_Backup,
61   k_Tf_Expiration,
62   k_Tf_Effective
63 
64   // k_Tf_Num
65 };
66 */
67 
68 struct CDirRecord
69 {
70   UInt32 ExtentLocation;
71   UInt32 Size;
72   CRecordingDateTime DateTime;
73   Byte FileFlags;
74   Byte FileUnitSize;
75   Byte InterleaveGapSize;
76   Byte ExtendedAttributeRecordLen;
77   UInt16 VolSequenceNumber;
78   CByteBuffer FileId;
79   CByteBuffer SystemUse;
80 
AreMultiPartEqualWithCDirRecord81   bool AreMultiPartEqualWith(const CDirRecord &a) const
82   {
83     return FileId == a.FileId
84         && (FileFlags & (~NFileFlags::kNonFinalExtent)) ==
85         (a.FileFlags & (~NFileFlags::kNonFinalExtent));
86   }
87 
IsDirCDirRecord88   bool IsDir() const { return (FileFlags & NFileFlags::kDirectory) != 0; }
IsNonFinalExtentCDirRecord89   bool IsNonFinalExtent() const { return (FileFlags & NFileFlags::kNonFinalExtent) != 0; }
90 
IsSystemItemCDirRecord91   bool IsSystemItem() const
92   {
93     if (FileId.Size() != 1)
94       return false;
95     Byte b = *(const Byte *)FileId;
96     return (b == 0 || b == 1);
97   }
98 
99 
FindSuspRecordCDirRecord100   const Byte* FindSuspRecord(unsigned skipSize, Byte id0, Byte id1, unsigned &lenRes) const
101   {
102     lenRes = 0;
103     if (SystemUse.Size() < skipSize)
104       return NULL;
105     const Byte *p = (const Byte *)SystemUse + skipSize;
106     unsigned rem = (unsigned)(SystemUse.Size() - skipSize);
107     while (rem >= 5)
108     {
109       unsigned len = p[2];
110       if (len < 3 || len > rem)
111         return NULL;
112       if (p[0] == id0 && p[1] == id1 && p[3] == 1)
113       {
114         if (len < 4)
115           return NULL; // Check it
116         lenRes = len - 4;
117         return p + 4;
118       }
119       p += len;
120       rem -= len;
121     }
122     return NULL;
123   }
124 
125 
GetNameCurCDirRecord126   const Byte* GetNameCur(bool checkSusp, unsigned skipSize, unsigned &nameLenRes) const
127   {
128     const Byte *res = NULL;
129     unsigned len = 0;
130     if (checkSusp)
131       res = FindSuspRecord(skipSize, 'N', 'M', len);
132     if (!res || len < 1)
133     {
134       res = (const Byte *)FileId;
135       len = (unsigned)FileId.Size();
136     }
137     else
138     {
139       res++;
140       len--;
141     }
142     unsigned i;
143     for (i = 0; i < len; i++)
144       if (res[i] == 0)
145         break;
146     nameLenRes = i;
147     return res;
148   }
149 
150 
GetSymLinkCDirRecord151   bool GetSymLink(unsigned skipSize, AString &link) const
152   {
153     link.Empty();
154     const Byte *p = NULL;
155     unsigned len = 0;
156     p = FindSuspRecord(skipSize, 'S', 'L', len);
157     if (!p || len < 1)
158       return false;
159 
160     if (*p != 0)
161       return false;
162 
163     p++;
164     len--;
165 
166     while (len != 0)
167     {
168       if (len < 2)
169         return false;
170       unsigned flags = p[0];
171       unsigned cl = p[1];
172       p += 2;
173       len -= 2;
174 
175       if (cl > len)
176         return false;
177 
178       bool needSlash = false;
179 
180            if (flags & (1 << 1)) link += "./";
181       else if (flags & (1 << 2)) link += "../";
182       else if (flags & (1 << 3)) link.Add_Slash();
183       else
184         needSlash = true;
185 
186       for (unsigned i = 0; i < cl; i++)
187       {
188         const Byte c = p[i];
189         if (c == 0)
190         {
191           break;
192           // return false;
193         }
194         link += (char)c;
195       }
196 
197       p += cl;
198       len -= cl;
199 
200       if (len == 0)
201         break;
202 
203       if (needSlash)
204         link.Add_Slash();
205     }
206 
207     return true;
208   }
209 
GetLe32Be32CDirRecord210   static bool GetLe32Be32(const Byte *p, UInt32 &dest)
211   {
212     UInt32 v1 = GetUi32(p);
213     UInt32 v2 = GetBe32(p + 4);
214     if (v1 == v2)
215     {
216       dest = v1;
217       return true;
218     }
219     return false;
220   }
221 
222 
GetPxCDirRecord223   bool GetPx(unsigned skipSize, unsigned pxType, UInt32 &val) const
224   {
225     val = 0;
226     const Byte *p = NULL;
227     unsigned len = 0;
228     p = FindSuspRecord(skipSize, 'P', 'X', len);
229     if (!p)
230       return false;
231     // px.Clear();
232     if (len < (pxType + 1) * 8)
233       return false;
234 
235     return GetLe32Be32(p + pxType * 8, val);
236   }
237 
238   /*
239   bool GetTf(int skipSize, unsigned pxType, CRecordingDateTime &t) const
240   {
241     const Byte *p = NULL;
242     unsigned len = 0;
243     p = FindSuspRecord(skipSize, 'T', 'F', len);
244     if (!p)
245       return false;
246     if (len < 1)
247       return false;
248     Byte flags = *p++;
249     len--;
250 
251     unsigned step = 7;
252     if (flags & 0x80)
253     {
254       step = 17;
255       return false;
256     }
257 
258     if ((flags & (1 << pxType)) == 0)
259       return false;
260 
261     for (unsigned i = 0; i < pxType; i++)
262     {
263       if (len < step)
264         return false;
265       if (flags & (1 << i))
266       {
267         p += step;
268         len -= step;
269       }
270     }
271 
272     if (len < step)
273       return false;
274 
275     t.Year = p[0];
276     t.Month = p[1];
277     t.Day = p[2];
278     t.Hour = p[3];
279     t.Minute = p[4];
280     t.Second = p[5];
281     t.GmtOffset = (signed char)p[6];
282 
283     return true;
284   }
285   */
286 
CheckSuspCDirRecord287   bool CheckSusp(const Byte *p, unsigned &startPos) const
288   {
289     if (p[0] == 'S' &&
290         p[1] == 'P' &&
291         p[2] == 0x7 &&
292         p[3] == 0x1 &&
293         p[4] == 0xBE &&
294         p[5] == 0xEF)
295     {
296       startPos = p[6];
297       return true;
298     }
299     return false;
300   }
301 
CheckSuspCDirRecord302   bool CheckSusp(unsigned &startPos) const
303   {
304     const Byte *p = (const Byte *)SystemUse;
305     const size_t len = SystemUse.Size();
306     const unsigned kMinLen = 7;
307     if (len < kMinLen)
308       return false;
309     if (CheckSusp(p, startPos))
310       return true;
311     const unsigned kOffset2 = 14;
312     if (len < kOffset2 + kMinLen)
313       return false;
314     return CheckSusp(p + kOffset2, startPos);
315   }
316 };
317 
318 }}
319 
320 #endif
321