// TarItem.h #ifndef ZIP7_INC_ARCHIVE_TAR_ITEM_H #define ZIP7_INC_ARCHIVE_TAR_ITEM_H #include "../../../Common/MyLinux.h" #include "../../../Common/UTFConvert.h" #include "TarHeader.h" namespace NArchive { namespace NTar { struct CSparseBlock { UInt64 Offset; UInt64 Size; }; enum EPaxTimeRemoveZeroMode { k_PaxTimeMode_DontRemoveZero, k_PaxTimeMode_RemoveZero_if_PureSecondOnly, k_PaxTimeMode_RemoveZero_Always }; struct CTimeOptions { EPaxTimeRemoveZeroMode RemoveZeroMode; unsigned NumDigitsMax; void Init() { RemoveZeroMode = k_PaxTimeMode_RemoveZero_if_PureSecondOnly; NumDigitsMax = 0; } CTimeOptions() { Init(); } }; struct CPaxTime { Int32 NumDigits; // -1 means undefined UInt32 Ns; // it's smaller than 1G. Even if (Sec < 0), larger (Ns) value means newer files. Int64 Sec; // can be negative Int64 GetSec() const { return NumDigits != -1 ? Sec : 0; } bool IsDefined() const { return NumDigits != -1; } // bool IsDefined_And_nonZero() const { return NumDigits != -1 && (Sec != 0 || Ns != 0); } void Clear() { NumDigits = -1; Ns = 0; Sec = 0; } CPaxTime() { Clear(); } /* void ReducePrecison(int numDigits) { // we don't use this->NumDigits here if (numDigits > 0) { if (numDigits >= 9) return; UInt32 r = 1; for (unsigned i = numDigits; i < 9; i++) r *= 10; Ns /= r; Ns *= r; return; } Ns = 0; if (numDigits == 0) return; UInt32 r; if (numDigits == -1) r = 60; else if (numDigits == -2) r = 60 * 60; else if (numDigits == -3) r = 60 * 60 * 24; else return; Sec /= r; Sec *= r; } */ }; struct CPaxTimes { CPaxTime MTime; CPaxTime ATime; CPaxTime CTime; void Clear() { MTime.Clear(); ATime.Clear(); CTime.Clear(); } /* void ReducePrecison(int numDigits) { MTime.ReducePrecison(numDigits); CTime.ReducePrecison(numDigits); ATime.ReducePrecison(numDigits); } */ }; struct CItem { UInt64 PackSize; UInt64 Size; Int64 MTime; char LinkFlag; bool DeviceMajor_Defined; bool DeviceMinor_Defined; UInt32 Mode; UInt32 UID; UInt32 GID; UInt32 DeviceMajor; UInt32 DeviceMinor; AString Name; AString LinkName; AString User; AString Group; char Magic[8]; CPaxTimes PaxTimes; CRecordVector SparseBlocks; void SetMagic_Posix(bool posixMode) { memcpy(Magic, posixMode ? NFileHeader::NMagic::k_Posix_ustar_00 : NFileHeader::NMagic::k_GNU_ustar, 8); } bool Is_SymLink() const { return LinkFlag == NFileHeader::NLinkFlag::kSymLink && (Size == 0); } bool Is_HardLink() const { return LinkFlag == NFileHeader::NLinkFlag::kHardLink; } bool Is_Sparse() const { return LinkFlag == NFileHeader::NLinkFlag::kSparse; } UInt64 Get_UnpackSize() const { return Is_SymLink() ? LinkName.Len() : Size; } bool Is_PaxExtendedHeader() const { switch (LinkFlag) { case NFileHeader::NLinkFlag::kPax: case NFileHeader::NLinkFlag::kPax_2: case NFileHeader::NLinkFlag::kGlobal: return true; default: break; } return false; } UInt32 Get_Combined_Mode() const { return (Mode & ~(UInt32)MY_LIN_S_IFMT) | Get_FileTypeMode_from_LinkFlag(); } void Set_LinkFlag_for_File(UInt32 mode) { char lf = NFileHeader::NLinkFlag::kNormal; if (MY_LIN_S_ISCHR(mode)) lf = NFileHeader::NLinkFlag::kCharacter; else if (MY_LIN_S_ISBLK(mode)) lf = NFileHeader::NLinkFlag::kBlock; else if (MY_LIN_S_ISFIFO(mode)) lf = NFileHeader::NLinkFlag::kFIFO; // else if (MY_LIN_S_ISDIR(mode)) lf = NFileHeader::NLinkFlag::kDirectory; // else if (MY_LIN_S_ISLNK(mode)) lf = NFileHeader::NLinkFlag::kSymLink; LinkFlag = lf; } UInt32 Get_FileTypeMode_from_LinkFlag() const { switch (LinkFlag) { /* case NFileHeader::NLinkFlag::kDirectory: case NFileHeader::NLinkFlag::kDumpDir: return MY_LIN_S_IFDIR; */ case NFileHeader::NLinkFlag::kSymLink: return MY_LIN_S_IFLNK; case NFileHeader::NLinkFlag::kBlock: return MY_LIN_S_IFBLK; case NFileHeader::NLinkFlag::kCharacter: return MY_LIN_S_IFCHR; case NFileHeader::NLinkFlag::kFIFO: return MY_LIN_S_IFIFO; // case return MY_LIN_S_IFSOCK; default: break; } if (IsDir()) return MY_LIN_S_IFDIR; return MY_LIN_S_IFREG; } bool IsDir() const { switch (LinkFlag) { case NFileHeader::NLinkFlag::kDirectory: case NFileHeader::NLinkFlag::kDumpDir: return true; case NFileHeader::NLinkFlag::kOldNormal: case NFileHeader::NLinkFlag::kNormal: case NFileHeader::NLinkFlag::kSymLink: if (Name.IsEmpty()) return false; // GNU TAR uses last character as directory marker // we also do it return Name.Back() == '/'; // return NItemName::HasTailSlash(Name, CP_OEMCP); default: break; } return false; } bool IsMagic_ustar_5chars() const { for (unsigned i = 0; i < 5; i++) if (Magic[i] != NFileHeader::NMagic::k_GNU_ustar[i]) return false; return true; } bool IsMagic_Posix_ustar_00() const { for (unsigned i = 0; i < 8; i++) if (Magic[i] != NFileHeader::NMagic::k_Posix_ustar_00[i]) return false; return true; } bool IsMagic_GNU() const { for (unsigned i = 0; i < 8; i++) if (Magic[i] != NFileHeader::NMagic::k_GNU_ustar[i]) return false; return true; } UInt64 Get_PackSize_Aligned() const { return (PackSize + 0x1FF) & (~((UInt64)0x1FF)); } bool IsThereWarning() const { // that Header Warning is possible if (Size != 0) for dir item return (PackSize < Size) && (LinkFlag == NFileHeader::NLinkFlag::kDirectory); } }; struct CEncodingCharacts { bool IsAscii; // bool Oem_Checked; // bool Oem_Ok; // bool Utf_Checked; CUtf8Check UtfCheck; void Clear() { IsAscii = true; // Oem_Checked = false; // Oem_Ok = false; // Utf_Checked = false; UtfCheck.Clear(); } void Update(const CEncodingCharacts &ec) { if (!ec.IsAscii) IsAscii = false; // if (ec.Utf_Checked) { UtfCheck.Update(ec.UtfCheck); // Utf_Checked = true; } } CEncodingCharacts() { Clear(); } void Check(const AString &s); AString GetCharactsString() const; }; struct CPaxExtra { AString RecordPath; AString RawLines; void Clear() { RecordPath.Empty(); RawLines.Empty(); } void Print_To_String(AString &s) const { if (!RecordPath.IsEmpty()) { s += RecordPath; s.Add_LF(); } if (!RawLines.IsEmpty()) s += RawLines; } }; struct CItemEx: public CItem { bool HeaderError; bool IsSignedChecksum; bool Prefix_WasUsed; bool Pax_Error; bool Pax_Overflow; bool pax_path_WasUsed; bool pax_link_WasUsed; bool pax_size_WasUsed; bool MTime_IsBin; bool PackSize_IsBin; bool Size_IsBin; bool LongName_WasUsed; bool LongName_WasUsed_2; bool LongLink_WasUsed; bool LongLink_WasUsed_2; // bool Name_CouldBeReduced; // bool LinkName_CouldBeReduced; UInt64 HeaderPos; UInt64 HeaderSize; UInt64 Num_Pax_Records; CPaxExtra PaxExtra; AString SCHILY_fflags; CEncodingCharacts EncodingCharacts; UInt64 Get_DataPos() const { return HeaderPos + HeaderSize; } // UInt64 GetFullSize() const { return HeaderSize + PackSize; } UInt64 Get_FullSize_Aligned() const { return HeaderSize + Get_PackSize_Aligned(); } }; }} #endif