1 // TarItem.h
2 
3 #ifndef __ARCHIVE_TAR_ITEM_H
4 #define __ARCHIVE_TAR_ITEM_H
5 
6 #include "../../../Common/MyLinux.h"
7 #include "../../../Common/UTFConvert.h"
8 
9 #include "../Common/ItemNameUtils.h"
10 
11 #include "TarHeader.h"
12 
13 namespace NArchive {
14 namespace NTar {
15 
16 struct CSparseBlock
17 {
18   UInt64 Offset;
19   UInt64 Size;
20 };
21 
22 struct CItem
23 {
24   AString Name;
25   UInt64 PackSize;
26   UInt64 Size;
27   Int64 MTime;
28 
29   UInt32 Mode;
30   UInt32 UID;
31   UInt32 GID;
32   UInt32 DeviceMajor;
33   UInt32 DeviceMinor;
34 
35   AString LinkName;
36   AString User;
37   AString Group;
38 
39   char Magic[8];
40   char LinkFlag;
41   bool DeviceMajorDefined;
42   bool DeviceMinorDefined;
43 
44   CRecordVector<CSparseBlock> SparseBlocks;
45 
SetDefaultWriteFieldsCItem46   void SetDefaultWriteFields()
47   {
48     DeviceMajorDefined = false;
49     DeviceMinorDefined = false;
50     UID = 0;
51     GID = 0;
52     memcpy(Magic, NFileHeader::NMagic::kUsTar_GNU, 8);
53   }
54 
IsSymLinkCItem55   bool IsSymLink() const { return LinkFlag == NFileHeader::NLinkFlag::kSymLink && (Size == 0); }
IsHardLinkCItem56   bool IsHardLink() const { return LinkFlag == NFileHeader::NLinkFlag::kHardLink; }
IsSparseCItem57   bool IsSparse() const { return LinkFlag == NFileHeader::NLinkFlag::kSparse; }
GetUnpackSizeCItem58   UInt64 GetUnpackSize() const { return IsSymLink() ? LinkName.Len() : Size; }
IsPaxExtendedHeaderCItem59   bool IsPaxExtendedHeader() const
60   {
61     switch (LinkFlag)
62     {
63       case 'g':
64       case 'x':
65       case 'X':  // Check it
66         return true;
67     }
68     return false;
69   }
70 
Get_Combined_ModeCItem71   UInt32 Get_Combined_Mode() const
72   {
73     return (Mode & ~(UInt32)MY_LIN_S_IFMT) | Get_FileTypeMode_from_LinkFlag();
74   }
75 
Get_FileTypeMode_from_LinkFlagCItem76   UInt32 Get_FileTypeMode_from_LinkFlag() const
77   {
78     switch (LinkFlag)
79     {
80       /*
81       case NFileHeader::NLinkFlag::kDirectory:
82       case NFileHeader::NLinkFlag::kDumpDir:
83         return MY_LIN_S_IFDIR;
84       */
85       case NFileHeader::NLinkFlag::kSymLink: return MY_LIN_S_IFLNK;
86       case NFileHeader::NLinkFlag::kBlock: return MY_LIN_S_IFBLK;
87       case NFileHeader::NLinkFlag::kCharacter: return MY_LIN_S_IFCHR;
88       case NFileHeader::NLinkFlag::kFIFO: return MY_LIN_S_IFIFO;
89       // case return MY_LIN_S_IFSOCK;
90     }
91 
92     if (IsDir())
93       return MY_LIN_S_IFDIR;
94     return MY_LIN_S_IFREG;
95   }
96 
IsDirCItem97   bool IsDir() const
98   {
99     switch (LinkFlag)
100     {
101       case NFileHeader::NLinkFlag::kDirectory:
102       case NFileHeader::NLinkFlag::kDumpDir:
103         return true;
104       case NFileHeader::NLinkFlag::kOldNormal:
105       case NFileHeader::NLinkFlag::kNormal:
106       case NFileHeader::NLinkFlag::kSymLink:
107         return NItemName::HasTailSlash(Name, CP_OEMCP);
108     }
109     return false;
110   }
111 
IsUstarMagicCItem112   bool IsUstarMagic() const
113   {
114     for (int i = 0; i < 5; i++)
115       if (Magic[i] != NFileHeader::NMagic::kUsTar_GNU[i])
116         return false;
117     return true;
118   }
119 
GetPackSizeAlignedCItem120   UInt64 GetPackSizeAligned() const { return (PackSize + 0x1FF) & (~((UInt64)0x1FF)); }
121 
IsThereWarningCItem122   bool IsThereWarning() const
123   {
124     // that Header Warning is possible if (Size != 0) for dir item
125     return (PackSize < Size) && (LinkFlag == NFileHeader::NLinkFlag::kDirectory);
126   }
127 };
128 
129 
130 
131 struct CEncodingCharacts
132 {
133   bool IsAscii;
134   // bool Oem_Checked;
135   // bool Oem_Ok;
136   // bool Utf_Checked;
137   CUtf8Check UtfCheck;
138 
ClearCEncodingCharacts139   void Clear()
140   {
141     IsAscii = true;
142     // Oem_Checked = false;
143     // Oem_Ok = false;
144     // Utf_Checked = false;
145     UtfCheck.Clear();
146   }
147 
UpdateCEncodingCharacts148   void Update(const CEncodingCharacts &ec)
149   {
150     if (!ec.IsAscii)
151       IsAscii = false;
152 
153     // if (ec.Utf_Checked)
154     {
155       UtfCheck.Update(ec.UtfCheck);
156       // Utf_Checked = true;
157     }
158   }
159 
CEncodingCharactsCEncodingCharacts160   CEncodingCharacts() { Clear(); }
161   void Check(const AString &s);
162   AString GetCharactsString() const;
163 };
164 
165 
166 
167 struct CItemEx: public CItem
168 {
169   UInt64 HeaderPos;
170   unsigned HeaderSize;
171   bool NameCouldBeReduced;
172   bool LinkNameCouldBeReduced;
173 
174   CEncodingCharacts EncodingCharacts;
175 
GetDataPositionCItemEx176   UInt64 GetDataPosition() const { return HeaderPos + HeaderSize; }
GetFullSizeCItemEx177   UInt64 GetFullSize() const { return HeaderSize + PackSize; }
178 };
179 
180 }}
181 
182 #endif
183