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