xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/Tar/TarItem.h (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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