xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/Iso/IsoIn.h (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // Archive/IsoIn.h
2 
3 #ifndef ZIP7_INC_ARCHIVE_ISO_IN_H
4 #define ZIP7_INC_ARCHIVE_ISO_IN_H
5 
6 #include "../../../Common/MyCom.h"
7 
8 #include "../../IStream.h"
9 
10 #include "IsoHeader.h"
11 #include "IsoItem.h"
12 
13 namespace NArchive {
14 namespace NIso {
15 
16 struct CDir: public CDirRecord
17 {
18   CDir *Parent;
19   CObjectVector<CDir> _subItems;
20 
ClearCDir21   void Clear()
22   {
23     Parent = NULL;
24     _subItems.Clear();
25   }
26 
GetPathCDir27   AString GetPath(bool checkSusp, unsigned skipSize) const
28   {
29     AString s;
30 
31     unsigned len = 0;
32     const CDir *cur = this;
33 
34     for (;;)
35     {
36       unsigned curLen;
37       cur->GetNameCur(checkSusp, skipSize, curLen);
38       len += curLen;
39       cur = cur->Parent;
40       if (!cur || !cur->Parent)
41         break;
42       len++;
43     }
44 
45     char *p = s.GetBuf_SetEnd(len) + len;
46 
47     cur = this;
48 
49     for (;;)
50     {
51       unsigned curLen;
52       const Byte *name = cur->GetNameCur(checkSusp, skipSize, curLen);
53       p -= curLen;
54       if (curLen != 0)
55         memcpy(p, name, curLen);
56       cur = cur->Parent;
57       if (!cur || !cur->Parent)
58         break;
59       p--;
60       *p = CHAR_PATH_SEPARATOR;
61     }
62 
63     return s;
64   }
65 
GetPathUCDir66   void GetPathU(UString &s) const
67   {
68     s.Empty();
69 
70     unsigned len = 0;
71     const CDir *cur = this;
72 
73     for (;;)
74     {
75       unsigned curLen = (unsigned)(cur->FileId.Size() / 2);
76       const Byte *fid = cur->FileId;
77 
78       unsigned i;
79       for (i = 0; i < curLen; i++)
80         if (fid[i * 2] == 0 && fid[i * 2 + 1] == 0)
81           break;
82       len += i;
83       cur = cur->Parent;
84       if (!cur || !cur->Parent)
85         break;
86       len++;
87     }
88 
89     wchar_t *p = s.GetBuf_SetEnd(len) + len;
90 
91     cur = this;
92 
93     for (;;)
94     {
95       unsigned curLen = (unsigned)(cur->FileId.Size() / 2);
96       const Byte *fid = cur->FileId;
97 
98       unsigned i;
99       for (i = 0; i < curLen; i++)
100         if (fid[i * 2] == 0 && fid[i * 2 + 1] == 0)
101           break;
102       curLen = i;
103 
104       p -= curLen;
105       for (i = 0; i < curLen; i++)
106         p[i] = (wchar_t)(((wchar_t)fid[i * 2] << 8) | fid[i * 2 + 1]);
107       cur = cur->Parent;
108       if (!cur || !cur->Parent)
109         break;
110       p--;
111       *p = WCHAR_PATH_SEPARATOR;
112     }
113   }
114 };
115 
116 struct CDateTime
117 {
118   UInt16 Year;
119   Byte Month;
120   Byte Day;
121   Byte Hour;
122   Byte Minute;
123   Byte Second;
124   Byte Hundredths;
125   signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded.
126 
NotSpecifiedCDateTime127   bool NotSpecified() const { return Year == 0 && Month == 0 && Day == 0 &&
128       Hour == 0 && Minute == 0 && Second == 0 && GmtOffset == 0; }
129 
GetFileTimeCDateTime130   bool GetFileTime(NWindows::NCOM::CPropVariant &prop) const
131   {
132     UInt64 v;
133     const bool res = NWindows::NTime::GetSecondsSince1601(Year, Month, Day, Hour, Minute, Second, v);
134     if (res)
135     {
136       v = (UInt64)((Int64)v - (Int64)((Int32)GmtOffset * 15 * 60));
137       v *= 10000000;
138       if (Hundredths < 100)
139         v += (UInt32)Hundredths * 100000;
140       prop.SetAsTimeFrom_Ft64_Prec(v, k_PropVar_TimePrec_Base + 2);
141     }
142     return res;
143   }
144 };
145 
146 struct CBootRecordDescriptor
147 {
148   Byte BootSystemId[32];  // a-characters
149   Byte BootId[32];        // a-characters
150   Byte BootSystemUse[1977];
151 };
152 
153 struct CBootValidationEntry
154 {
155   Byte PlatformId;
156   Byte Id[24]; // to identify the manufacturer/developer of the CD-ROM.
157 };
158 
159 struct CBootInitialEntry
160 {
161   bool Bootable;
162   Byte BootMediaType;
163   UInt16 LoadSegment;
164   /* This is the load segment for the initial boot image. If this
165      value is 0 the system will use the traditional segment of 7C0. If this value
166      is non-zero the system will use the specified segment. This applies to x86
167      architectures only. For "flat" model architectures (such as Motorola) this
168      is the address divided by 10. */
169   Byte SystemType;    // This must be a copy of byte 5 (System Type) from the
170                       // Partition Table found in the boot image.
171   UInt16 SectorCount; // This is the number of virtual/emulated sectors the system
172                       // will store at Load Segment during the initial boot procedure.
173   UInt32 LoadRBA;     // This is the start address of the virtual disk. CDs use
174                       // Relative/Logical block addressing.
175 
176   Byte VendorSpec[20];
177 
GetSizeCBootInitialEntry178   UInt32 GetSize() const
179   {
180     // if (BootMediaType == NBootMediaType::k1d44Floppy) (1440 << 10);
181     return (UInt32)SectorCount * 512;
182   }
183 
184   bool Parse(const Byte *p);
185   AString GetName() const;
186 };
187 
188 struct CVolumeDescriptor
189 {
190   Byte VolFlags;
191   Byte SystemId[32]; // a-characters. An identification of a system
192                      // which can recognize and act upon the content of the Logical
193                      // Sectors with logical Sector Numbers 0 to 15 of the volume.
194   Byte VolumeId[32]; // d-characters. An identification of the volume.
195   UInt32 VolumeSpaceSize; // the number of Logical Blocks in which the Volume Space of the volume is recorded
196   Byte EscapeSequence[32];
197   UInt16 VolumeSetSize;
198   UInt16 VolumeSequenceNumber; // the ordinal number of the volume in the Volume Set of which the volume is a member.
199   UInt16 LogicalBlockSize;
200   UInt32 PathTableSize;
201   UInt32 LPathTableLocation;
202   UInt32 LOptionalPathTableLocation;
203   UInt32 MPathTableLocation;
204   UInt32 MOptionalPathTableLocation;
205   CDirRecord RootDirRecord;
206   Byte VolumeSetId[128];
207   Byte PublisherId[128];
208   Byte DataPreparerId[128];
209   Byte ApplicationId[128];
210   Byte CopyrightFileId[37];
211   Byte AbstractFileId[37];
212   Byte BibFileId[37];
213   CDateTime CTime;
214   CDateTime MTime;
215   CDateTime ExpirationTime;
216   CDateTime EffectiveTime;
217   // Byte FileStructureVersion; // = 1;
218   Byte ApplicationUse[512];
219 
IsJolietCVolumeDescriptor220   bool IsJoliet() const
221   {
222     if ((VolFlags & 1) != 0)
223       return false;
224     const Byte b = EscapeSequence[2];
225     return (EscapeSequence[0] == 0x25 && EscapeSequence[1] == 0x2F &&
226       (b == 0x40 || b == 0x43 || b == 0x45));
227   }
228 
Get_VolumeSpaceSize_inBytesCVolumeDescriptor229   UInt64 Get_VolumeSpaceSize_inBytes() const { return (UInt64)VolumeSpaceSize * LogicalBlockSize; }
230 };
231 
232 struct CRef
233 {
234   const CDir *Dir;
235   UInt32 Index;
236   UInt32 NumExtents;
237   UInt64 TotalSize;
238 };
239 
240 const UInt32 kBlockSize = 1 << 11;
241 
242 class CInArchive
243 {
244   IInStream *_stream;
245   UInt64 _position;
246 
247   UInt32 m_BufferPos;
248 
249   void Skip(size_t size);
250   void SkipZeros(size_t size);
251   Byte ReadByte();
252   void ReadBytes(Byte *data, UInt32 size);
253   UInt16 ReadUInt16();
254   UInt32 ReadUInt32Le();
255   UInt32 ReadUInt32Be();
256   UInt32 ReadUInt32();
257   UInt64 ReadUInt64();
258   UInt32 ReadDigits(int numDigits);
259   void ReadDateTime(CDateTime &d);
260   void ReadRecordingDateTime(CRecordingDateTime &t);
261   void ReadDirRecord2(CDirRecord &r, Byte len);
262   void ReadDirRecord(CDirRecord &r);
263 
264   void ReadBootRecordDescriptor(CBootRecordDescriptor &d);
265   void ReadVolumeDescriptor(CVolumeDescriptor &d);
266 
267   void SeekToBlock(UInt32 blockIndex);
268   void ReadDir(CDir &d, int level);
269   void CreateRefs(CDir &d);
270 
271   void ReadBootInfo();
272   HRESULT Open2();
273 public:
274   HRESULT Open(IInStream *inStream);
275   void Clear();
276 
277   UInt64 _fileSize;
278   UInt64 PhySize;
279 
280   CRecordVector<CRef> Refs;
281   CObjectVector<CVolumeDescriptor> VolDescs;
282   int MainVolDescIndex;
283   // UInt32 BlockSize;
284   CObjectVector<CBootInitialEntry> BootEntries;
285 
286 private:
287   bool _bootIsDefined;
288 public:
289   bool IsArc;
290   bool UnexpectedEnd;
291   bool HeadersError;
292   bool IncorrectBigEndian;
293   bool TooDeepDirs;
294   bool SelfLinkedDirs;
295   bool IsSusp;
296   unsigned SuspSkipSize;
297 
298   int _expand_BootEntries_index;
299 
300   CRecordVector<UInt32> UniqStartLocations;
301 
UpdatePhySize(const UInt32 blockIndex,const UInt64 size)302   void UpdatePhySize(const UInt32 blockIndex, const UInt64 size)
303   {
304     const UInt64 alignedSize = (size + kBlockSize - 1) & ~((UInt64)kBlockSize - 1);
305     const UInt64 end = (UInt64)blockIndex * kBlockSize + alignedSize;
306     if (PhySize < end)
307       PhySize = end;
308   }
309 
IsJoliet()310   bool IsJoliet() const { return VolDescs[MainVolDescIndex].IsJoliet(); }
311 
312   UInt64 GetBootItemSize(unsigned index) const;
313 
314 private:
315   CDir _rootDir;
316   Byte m_Buffer[kBlockSize];
317   CBootRecordDescriptor _bootDesc;
318 };
319 
320 }}
321 
322 #endif
323