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