1 // TarItem.h 2 3 #ifndef ZIP7_INC_ARCHIVE_TAR_ITEM_H 4 #define ZIP7_INC_ARCHIVE_TAR_ITEM_H 5 6 #include "../../../Common/MyLinux.h" 7 #include "../../../Common/UTFConvert.h" 8 9 #include "TarHeader.h" 10 11 namespace NArchive { 12 namespace NTar { 13 14 struct CSparseBlock 15 { 16 UInt64 Offset; 17 UInt64 Size; 18 }; 19 20 21 enum EPaxTimeRemoveZeroMode 22 { 23 k_PaxTimeMode_DontRemoveZero, 24 k_PaxTimeMode_RemoveZero_if_PureSecondOnly, 25 k_PaxTimeMode_RemoveZero_Always 26 }; 27 28 struct CTimeOptions 29 { 30 EPaxTimeRemoveZeroMode RemoveZeroMode; 31 unsigned NumDigitsMax; 32 InitCTimeOptions33 void Init() 34 { 35 RemoveZeroMode = k_PaxTimeMode_RemoveZero_if_PureSecondOnly; 36 NumDigitsMax = 0; 37 } CTimeOptionsCTimeOptions38 CTimeOptions() { Init(); } 39 }; 40 41 42 struct CPaxTime 43 { 44 Int32 NumDigits; // -1 means undefined 45 UInt32 Ns; // it's smaller than 1G. Even if (Sec < 0), larger (Ns) value means newer files. 46 Int64 Sec; // can be negative 47 GetSecCPaxTime48 Int64 GetSec() const { return NumDigits != -1 ? Sec : 0; } 49 IsDefinedCPaxTime50 bool IsDefined() const { return NumDigits != -1; } 51 // bool IsDefined_And_nonZero() const { return NumDigits != -1 && (Sec != 0 || Ns != 0); } 52 ClearCPaxTime53 void Clear() 54 { 55 NumDigits = -1; 56 Ns = 0; 57 Sec = 0; 58 } CPaxTimeCPaxTime59 CPaxTime() { Clear(); } 60 61 /* 62 void ReducePrecison(int numDigits) 63 { 64 // we don't use this->NumDigits here 65 if (numDigits > 0) 66 { 67 if (numDigits >= 9) 68 return; 69 UInt32 r = 1; 70 for (unsigned i = numDigits; i < 9; i++) 71 r *= 10; 72 Ns /= r; 73 Ns *= r; 74 return; 75 } 76 Ns = 0; 77 if (numDigits == 0) 78 return; 79 UInt32 r; 80 if (numDigits == -1) r = 60; 81 else if (numDigits == -2) r = 60 * 60; 82 else if (numDigits == -3) r = 60 * 60 * 24; 83 else return; 84 Sec /= r; 85 Sec *= r; 86 } 87 */ 88 }; 89 90 91 struct CPaxTimes 92 { 93 CPaxTime MTime; 94 CPaxTime ATime; 95 CPaxTime CTime; 96 ClearCPaxTimes97 void Clear() 98 { 99 MTime.Clear(); 100 ATime.Clear(); 101 CTime.Clear(); 102 } 103 104 /* 105 void ReducePrecison(int numDigits) 106 { 107 MTime.ReducePrecison(numDigits); 108 CTime.ReducePrecison(numDigits); 109 ATime.ReducePrecison(numDigits); 110 } 111 */ 112 }; 113 114 115 struct CItem 116 { 117 UInt64 PackSize; 118 UInt64 Size; 119 Int64 MTime; 120 121 char LinkFlag; 122 bool DeviceMajor_Defined; 123 bool DeviceMinor_Defined; 124 125 UInt32 Mode; 126 UInt32 UID; 127 UInt32 GID; 128 UInt32 DeviceMajor; 129 UInt32 DeviceMinor; 130 131 AString Name; 132 AString LinkName; 133 AString User; 134 AString Group; 135 136 char Magic[8]; 137 138 CPaxTimes PaxTimes; 139 140 CRecordVector<CSparseBlock> SparseBlocks; 141 SetMagic_PosixCItem142 void SetMagic_Posix(bool posixMode) 143 { 144 memcpy(Magic, posixMode ? 145 NFileHeader::NMagic::k_Posix_ustar_00 : 146 NFileHeader::NMagic::k_GNU_ustar, 147 8); 148 } 149 Is_SymLinkCItem150 bool Is_SymLink() const { return LinkFlag == NFileHeader::NLinkFlag::kSymLink && (Size == 0); } Is_HardLinkCItem151 bool Is_HardLink() const { return LinkFlag == NFileHeader::NLinkFlag::kHardLink; } Is_SparseCItem152 bool Is_Sparse() const { return LinkFlag == NFileHeader::NLinkFlag::kSparse; } 153 Get_UnpackSizeCItem154 UInt64 Get_UnpackSize() const { return Is_SymLink() ? LinkName.Len() : Size; } 155 Is_PaxExtendedHeaderCItem156 bool Is_PaxExtendedHeader() const 157 { 158 switch (LinkFlag) 159 { 160 case NFileHeader::NLinkFlag::kPax: 161 case NFileHeader::NLinkFlag::kPax_2: 162 case NFileHeader::NLinkFlag::kGlobal: 163 return true; 164 default: break; 165 } 166 return false; 167 } 168 Get_Combined_ModeCItem169 UInt32 Get_Combined_Mode() const 170 { 171 return (Mode & ~(UInt32)MY_LIN_S_IFMT) | Get_FileTypeMode_from_LinkFlag(); 172 } 173 Set_LinkFlag_for_FileCItem174 void Set_LinkFlag_for_File(UInt32 mode) 175 { 176 char lf = NFileHeader::NLinkFlag::kNormal; 177 if (MY_LIN_S_ISCHR(mode)) lf = NFileHeader::NLinkFlag::kCharacter; 178 else if (MY_LIN_S_ISBLK(mode)) lf = NFileHeader::NLinkFlag::kBlock; 179 else if (MY_LIN_S_ISFIFO(mode)) lf = NFileHeader::NLinkFlag::kFIFO; 180 // else if (MY_LIN_S_ISDIR(mode)) lf = NFileHeader::NLinkFlag::kDirectory; 181 // else if (MY_LIN_S_ISLNK(mode)) lf = NFileHeader::NLinkFlag::kSymLink; 182 LinkFlag = lf; 183 } 184 Get_FileTypeMode_from_LinkFlagCItem185 UInt32 Get_FileTypeMode_from_LinkFlag() const 186 { 187 switch (LinkFlag) 188 { 189 /* 190 case NFileHeader::NLinkFlag::kDirectory: 191 case NFileHeader::NLinkFlag::kDumpDir: 192 return MY_LIN_S_IFDIR; 193 */ 194 case NFileHeader::NLinkFlag::kSymLink: return MY_LIN_S_IFLNK; 195 case NFileHeader::NLinkFlag::kBlock: return MY_LIN_S_IFBLK; 196 case NFileHeader::NLinkFlag::kCharacter: return MY_LIN_S_IFCHR; 197 case NFileHeader::NLinkFlag::kFIFO: return MY_LIN_S_IFIFO; 198 // case return MY_LIN_S_IFSOCK; 199 default: break; 200 } 201 202 if (IsDir()) 203 return MY_LIN_S_IFDIR; 204 return MY_LIN_S_IFREG; 205 } 206 IsDirCItem207 bool IsDir() const 208 { 209 switch (LinkFlag) 210 { 211 case NFileHeader::NLinkFlag::kDirectory: 212 case NFileHeader::NLinkFlag::kDumpDir: 213 return true; 214 case NFileHeader::NLinkFlag::kOldNormal: 215 case NFileHeader::NLinkFlag::kNormal: 216 case NFileHeader::NLinkFlag::kSymLink: 217 if (Name.IsEmpty()) 218 return false; 219 // GNU TAR uses last character as directory marker 220 // we also do it 221 return Name.Back() == '/'; 222 // return NItemName::HasTailSlash(Name, CP_OEMCP); 223 default: break; 224 } 225 return false; 226 } 227 IsMagic_ustar_5charsCItem228 bool IsMagic_ustar_5chars() const 229 { 230 for (unsigned i = 0; i < 5; i++) 231 if (Magic[i] != NFileHeader::NMagic::k_GNU_ustar[i]) 232 return false; 233 return true; 234 } 235 IsMagic_Posix_ustar_00CItem236 bool IsMagic_Posix_ustar_00() const 237 { 238 for (unsigned i = 0; i < 8; i++) 239 if (Magic[i] != NFileHeader::NMagic::k_Posix_ustar_00[i]) 240 return false; 241 return true; 242 } 243 IsMagic_GNUCItem244 bool IsMagic_GNU() const 245 { 246 for (unsigned i = 0; i < 8; i++) 247 if (Magic[i] != NFileHeader::NMagic::k_GNU_ustar[i]) 248 return false; 249 return true; 250 } 251 Get_PackSize_AlignedCItem252 UInt64 Get_PackSize_Aligned() const { return (PackSize + 0x1FF) & (~((UInt64)0x1FF)); } 253 IsThereWarningCItem254 bool IsThereWarning() const 255 { 256 // that Header Warning is possible if (Size != 0) for dir item 257 return (PackSize < Size) && (LinkFlag == NFileHeader::NLinkFlag::kDirectory); 258 } 259 }; 260 261 262 263 struct CEncodingCharacts 264 { 265 bool IsAscii; 266 // bool Oem_Checked; 267 // bool Oem_Ok; 268 // bool Utf_Checked; 269 CUtf8Check UtfCheck; 270 ClearCEncodingCharacts271 void Clear() 272 { 273 IsAscii = true; 274 // Oem_Checked = false; 275 // Oem_Ok = false; 276 // Utf_Checked = false; 277 UtfCheck.Clear(); 278 } 279 UpdateCEncodingCharacts280 void Update(const CEncodingCharacts &ec) 281 { 282 if (!ec.IsAscii) 283 IsAscii = false; 284 285 // if (ec.Utf_Checked) 286 { 287 UtfCheck.Update(ec.UtfCheck); 288 // Utf_Checked = true; 289 } 290 } 291 CEncodingCharactsCEncodingCharacts292 CEncodingCharacts() { Clear(); } 293 void Check(const AString &s); 294 AString GetCharactsString() const; 295 }; 296 297 298 struct CPaxExtra 299 { 300 AString RecordPath; 301 AString RawLines; 302 ClearCPaxExtra303 void Clear() 304 { 305 RecordPath.Empty(); 306 RawLines.Empty(); 307 } 308 Print_To_StringCPaxExtra309 void Print_To_String(AString &s) const 310 { 311 if (!RecordPath.IsEmpty()) 312 { 313 s += RecordPath; 314 s.Add_LF(); 315 } 316 if (!RawLines.IsEmpty()) 317 s += RawLines; 318 } 319 }; 320 321 322 struct CItemEx: public CItem 323 { 324 bool HeaderError; 325 326 bool IsSignedChecksum; 327 bool Prefix_WasUsed; 328 329 bool Pax_Error; 330 bool Pax_Overflow; 331 bool pax_path_WasUsed; 332 bool pax_link_WasUsed; 333 bool pax_size_WasUsed; 334 335 bool MTime_IsBin; 336 bool PackSize_IsBin; 337 bool Size_IsBin; 338 339 bool LongName_WasUsed; 340 bool LongName_WasUsed_2; 341 342 bool LongLink_WasUsed; 343 bool LongLink_WasUsed_2; 344 345 // bool Name_CouldBeReduced; 346 // bool LinkName_CouldBeReduced; 347 348 UInt64 HeaderPos; 349 UInt64 HeaderSize; 350 351 UInt64 Num_Pax_Records; 352 CPaxExtra PaxExtra; 353 AString SCHILY_fflags; 354 355 CEncodingCharacts EncodingCharacts; 356 Get_DataPosCItemEx357 UInt64 Get_DataPos() const { return HeaderPos + HeaderSize; } 358 // UInt64 GetFullSize() const { return HeaderSize + PackSize; } Get_FullSize_AlignedCItemEx359 UInt64 Get_FullSize_Aligned() const { return HeaderSize + Get_PackSize_Aligned(); } 360 }; 361 362 }} 363 364 #endif 365