xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/Udf/UdfIn.h (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // Archive/UdfIn.h -- UDF / ECMA-167
2 
3 #ifndef ZIP7_INC_ARCHIVE_UDF_IN_H
4 #define ZIP7_INC_ARCHIVE_UDF_IN_H
5 
6 #include "../../../Common/IntToString.h"
7 #include "../../../Common/MyBuffer.h"
8 #include "../../../Common/MyCom.h"
9 #include "../../../Common/MyMap.h"
10 #include "../../../Common/MyString.h"
11 
12 #include "../../IStream.h"
13 
14 namespace NArchive {
15 namespace NUdf {
16 
17 // ---------- ECMA Part 1 ----------
18 
19 // ECMA 1/7.2.12
20 // UDF 2.1.3
21 
22 struct CDString32
23 {
24   Byte Data[32];
25 
ParseCDString3226   void Parse(const Byte *buf) { memcpy(Data, buf, sizeof(Data)); }
27   UString GetString() const;
28 };
29 
30 struct CDString128
31 {
32   Byte Data[128];
33 
ParseCDString12834   void Parse(const Byte *buf) { memcpy(Data, buf, sizeof(Data)); }
35   UString GetString() const;
36 };
37 
38 struct CDString
39 {
40   CByteBuffer Data;
41 
42   void Parse(const Byte *p, unsigned size);
43   UString GetString() const;
44 };
45 
46 
47 // ECMA 1/7.3
48 // UDF 2.1.4 timestamp
49 
50 struct CTime
51 {
52   Byte Data[12];
53 
GetTypeCTime54   unsigned GetType() const { return Data[1] >> 4; }
IsLocalCTime55   bool IsLocal() const { return GetType() == 1; }
GetMinutesOffsetCTime56   int GetMinutesOffset() const
57   {
58     int t = (Data[0] | ((unsigned)Data[1] << 8)) & 0xFFF;
59     if ((t >> 11) != 0)
60       t -= (1 << 12);
61     return (t > (60 * 24) || t < -(60 * 24)) ? 0 : t;
62   }
GetYearCTime63   unsigned GetYear() const { return (Data[2] | ((unsigned)Data[3] << 8)); }
64   void Parse(const Byte *buf);
65 };
66 
67 
68 // ECMA 1/7.4 regid
69 // UDF 2.1.5 EntityID
70 
71 struct CRegId
72 {
73   Byte Flags;
74   char Id[23];
75   Byte Suffix[8];
76 
77   void Parse(const Byte *buf);
78   void AddCommentTo(UString &s) const;
79   void AddUdfVersionTo(UString &s) const;
80 };
81 
82 
83 
84 // ---------- ECMA Part 3: Volume Structure ----------
85 
86 // ECMA 3/7.1
87 
88 struct CExtent
89 {
90   UInt32 Len;
91   UInt32 Pos; // logical sector number
92 
93   void Parse(const Byte *p);
94 };
95 
96 
97 // ECMA 3/10.1
98 // UDF 2.2.2 PrimaryVolumeDescriptor
99 
100 struct CPrimeVol
101 {
102   // UInt32 VolumeDescriptorSequenceNumber;
103   UInt32 PrimaryVolumeDescriptorNumber;
104   CDString32 VolumeId;
105   UInt16 VolumeSequenceNumber;
106   UInt16 MaximumVolumeSequenceNumber;
107   // UInt16 InterchangeLevel;
108   // UInt16 MaximumInterchangeLevel;
109   // UInt32 CharacterSetList;
110   // UInt32 MaximumCharacterSetList;
111   CDString128 VolumeSetId;
112   // charspec DescriptorCharacterSet; // (1/7.2.1)
113   // charspec ExplanatoryCharacterSet; // (1/7.2.1)
114   // CExtent VolumeAbstract;
115   // CExtent VolumeCopyrightNotice;
116   CRegId ApplicationId;
117   CTime RecordingTime;
118   CRegId ImplId;
119   // bytes ImplementationUse
120   // UInt32 PredecessorVolumeDescriptorSequenceLocation;
121   // UInt16 Flags;
122 
123   void Parse(const Byte *p);
124 };
125 
126 
127 // ECMA 3/10.5
128 // UDF 2.2.14 PartitionDescriptor
129 
130 struct CPartition
131 {
132   UInt32 Pos;
133   UInt32 Len;
134 
135   UInt16 Flags;
136   UInt16 Number;
137   CRegId ContentsId;
138   // Byte ContentsUse[128];
139   UInt32 AccessType;
140 
141   CRegId ImplId;
142   // Byte ImplUse[128];
143 
144   // int VolIndex;
145   CMap32 Map;
146 
147   bool IsMetadata;
148 
CPartitionCPartition149   CPartition():
150     //  VolIndex(-1),
151     IsMetadata(false) {}
152 
153   // bool IsNsr() const { return (strncmp(ContentsId.Id, "+NSR0", 5) == 0); }
154   // bool IsAllocated() const { return ((Flags & 1) != 0); }
155 };
156 
157 
158 // ECMA 4/7.1 lb_addr
159 
160 struct CLogBlockAddr
161 {
162   UInt32 Pos;
163   UInt16 PartitionRef;
164 
165   void Parse(const Byte *p);
166 };
167 
168 
169 enum EShortAllocDescType
170 {
171   SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated = 0,
172   SHORT_ALLOC_DESC_TYPE_NotRecordedButAllocated = 1,
173   SHORT_ALLOC_DESC_TYPE_NotRecordedAndNotAllocated = 2,
174   SHORT_ALLOC_DESC_TYPE_NextExtent = 3
175 };
176 
177 
178 // ECMA 4/14.14.1 short_ad
179 
180 struct CShortAllocDesc
181 {
182   UInt32 Len;
183   UInt32 Pos;
184 
185   // UInt32 GetLen() const { return Len & 0x3FFFFFFF; }
186   // UInt32 GetType() const { return Len >> 30; }
187   // bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; }
188   void Parse(const Byte *p);
189 };
190 
191 /*
192 struct CADImpUse
193 {
194   UInt16 Flags;
195   UInt32 UdfUniqueId;
196   void Parse(const Byte *p);
197 };
198 */
199 
200 // ECMA 4/14.14.2 long_ad
201 // UDF 2.3.10.1
202 
203 struct CLongAllocDesc
204 {
205   UInt32 Len;
206   CLogBlockAddr Location;
207 
208   // Byte ImplUse[6];
209   // CADImpUse adImpUse; // UDF
210 
GetLenCLongAllocDesc211   UInt32 GetLen() const { return Len & 0x3FFFFFFF; }
GetTypeCLongAllocDesc212   UInt32 GetType() const { return Len >> 30; }
IsRecAndAllocCLongAllocDesc213   bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; }
214   void Parse(const Byte *p);
215 };
216 
217 
218 // ECMA 3/10.7 Partition maps
219 // UDF 2.2.8-2.2.10 Partition Maps
220 
221 struct CPartitionMap
222 {
223   unsigned PartitionIndex;
224 
225   Byte Type;
226   // Byte Len;
227 
228   // ECMA 10.7.2
229   UInt16 VolumeSequenceNumber;
230   UInt16 PartitionNumber;
231 
232   CRegId PartitionTypeId;
233 
234   // UDF 2.2.10 Metadata Partition Map
235   UInt32 MetadataFileLocation;
236   // UInt32 MetadataMirrorFileLocation;
237   // UInt32 MetadataBitmapFileLocation;
238   // UInt32 AllocationUnitSize; // (Blocks)
239   // UInt16 AlignmentUnitSize; // (Blocks)
240   // Byte Flags;
241 
242   // Byte Data[256];
243   // CPartitionMap(): PartitionIndex(-1) {}
244 };
245 
246 
247 // ECMA 4/14.6.6
248 
249 enum EIcbFileType
250 {
251   ICB_FILE_TYPE_DIR = 4,
252   ICB_FILE_TYPE_FILE = 5,
253 
254   ICB_FILE_TYPE_METADATA = 250,        // 2.2.13.1 Metadata File
255   ICB_FILE_TYPE_METADATA_MIRROR = 251
256 };
257 
258 enum EIcbDescriptorType
259 {
260   ICB_DESC_TYPE_SHORT = 0,
261   ICB_DESC_TYPE_LONG = 1,
262   ICB_DESC_TYPE_EXTENDED = 2,
263   ICB_DESC_TYPE_INLINE = 3
264 };
265 
266 // ECMA 4/14.6
267 // UDF 3.3.2
268 
269 struct CIcbTag
270 {
271   // UInt32 PriorDirectNum;
272   // UInt16 StrategyType;
273   // UInt16 StrategyParam;
274   // UInt16 MaxNumOfEntries;
275   Byte FileType;
276   // CLogBlockAddr ParentIcb;
277   UInt16 Flags;
278 
IsDirCIcbTag279   bool IsDir() const { return FileType == ICB_FILE_TYPE_DIR; }
GetDescriptorTypeCIcbTag280   int GetDescriptorType() const { return Flags & 3; }
281   void Parse(const Byte *p);
282 };
283 
284 
285 // ECMA 4/14.4.3
286 // UDF 2.3.4.2 FileCharacteristics
287 
288 // const Byte FILEID_CHARACS_Existance = (1 << 0);
289 const Byte FILEID_CHARACS_Dir     = (1 << 1);
290 const Byte FILEID_CHARACS_Deleted = (1 << 2);
291 const Byte FILEID_CHARACS_Parent  = (1 << 3);
292 // const Byte FILEID_CHARACS_Metadata = (1 << 4);
293 
294 struct CFile
295 {
296   int ItemIndex;
297   // UInt16 FileVersion;
298   // Byte FileCharacteristics;
299   // CByteBuffer ImplUse;
300   CDString Id;
301 
CFileCFile302   CFile(): /* FileVersion(0), FileCharacteristics(0), */ ItemIndex(-1) {}
GetNameCFile303   UString GetName() const { return Id.GetString(); }
304 };
305 
306 
307 struct CMyExtent
308 {
309   UInt32 Pos;
310   UInt32 Len;
311   unsigned PartitionRef; // index in CLogVol::PartitionMaps
312 
GetLenCMyExtent313   UInt32 GetLen() const { return Len & 0x3FFFFFFF; }
GetTypeCMyExtent314   UInt32 GetType() const { return Len >> 30; }
IsRecAndAllocCMyExtent315   bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; }
316 };
317 
318 
319 struct CItem
320 {
321   CIcbTag IcbTag;
322 
323   // UInt32 Uid;
324   // UInt32 Gid;
325   // UInt32 Permissions;
326   UInt16 FileLinkCount;
327   // Byte RecordFormat;
328   // Byte RecordDisplayAttr;
329   // UInt32 RecordLen;
330   UInt64 Size;
331   UInt64 NumLogBlockRecorded;
332   // UInt64 ObjectSize;
333 
334   CTime ATime;
335   CTime MTime;
336   CTime AttribTime; // Attribute time : most recent date and time of the day of file creation or modification of the attributes of.
337   CTime CreateTime;
338   // UInt32 CheckPoint;
339   // CLongAllocDesc ExtendedAttrIcb;
340   // CRegId ImplId;
341   // UInt64 UniqueId;
342 
343   bool IsExtended;
344   bool IsInline;
345   CByteBuffer InlineData;
346   CRecordVector<CMyExtent> Extents;
347   CUIntVector SubFiles;
348 
349   void Parse(const Byte *p);
350 
IsRecAndAllocCItem351   bool IsRecAndAlloc() const
352   {
353     FOR_VECTOR (i, Extents)
354       if (!Extents[i].IsRecAndAlloc())
355         return false;
356     return true;
357   }
358 
GetChunksSumSizeCItem359   UInt64 GetChunksSumSize() const
360   {
361     if (IsInline)
362       return InlineData.Size();
363     UInt64 size = 0;
364     FOR_VECTOR (i, Extents)
365       size += Extents[i].GetLen();
366     return size;
367   }
368 
CheckChunkSizesCItem369   bool CheckChunkSizes() const  {  return GetChunksSumSize() == Size; }
370 
IsDirCItem371   bool IsDir() const { return IcbTag.IsDir(); }
372 };
373 
374 
375 struct CRef
376 {
377   unsigned FileIndex;
378   int Parent;
379 };
380 
381 
382 // ECMA 4 / 14.1
383 struct CFileSet
384 {
385   CRecordVector<CRef> Refs;
386 
387   CTime RecordingTime;
388   // UInt16 InterchangeLevel;
389   // UInt16 MaxInterchangeLevel;
390   UInt32 FileSetNumber;
391   UInt32 FileSetDescNumber;
392   CDString128 LogicalVolumeId;
393   CDString32 Id;
394   CDString32 CopyrightId;
395   CDString32 AbstractId;
396 
397   CLongAllocDesc RootDirICB;
398   CRegId DomainId;
399   // CLongAllocDesc SystemStreamDirICB;
400 };
401 
402 
403 /* 8.3 Volume descriptors
404 8.4
405 A Volume Descriptor Sequence:
406  shall contain one or more Primary Volume Descriptors.
407 */
408 
409 // ECMA 3/10.6
410 // UDF 2.2.4  LogicalVolumeDescriptor
411 
412 struct CLogVol
413 {
414   CObjectVector<CPartitionMap> PartitionMaps;
415   CObjectVector<CFileSet> FileSets;
416 
417   UInt32 BlockSize;
418   CDString128 Id;
419   CRegId DomainId;
420 
421   // Byte ContentsUse[16];
422   CLongAllocDesc FileSetLocation; // UDF
423 
424   CRegId ImplId;
425   // Byte ImplUse[128];
426   // CExtent IntegritySequenceExtent;
427 
GetNameCLogVol428   UString GetName() const { return Id.GetString(); }
429 };
430 
431 
432 Z7_PURE_INTERFACES_BEGIN
433 struct Z7_DECLSPEC_NOVTABLE CProgressVirt
434 {
435   virtual HRESULT SetTotal(UInt64 numBytes) =0; \
436   virtual HRESULT SetCompleted(UInt64 numFiles, UInt64 numBytes) =0; \
437   virtual HRESULT SetCompleted() =0; \
438 };
439 Z7_PURE_INTERFACES_END
440 
441 class CInArchive
442 {
443 public:
444   CObjectVector<CLogVol> LogVols;
445   CObjectVector<CItem> Items;
446   CObjectVector<CFile> Files;
447   CObjectVector<CPartition> Partitions;
448 
449   unsigned SecLogSize;
450   UInt64 PhySize;
451   UInt64 FileSize;
452 
453   bool IsArc;
454   bool Unsupported;
455   bool UnexpectedEnd;
456   bool NoEndAnchor;
457 
458   CObjectVector<CPrimeVol> PrimeVols;
459 
460   HRESULT Open(IInStream *inStream, CProgressVirt *progress);
461   void Clear();
462 
463   UString GetComment() const;
464   UString GetItemPath(unsigned volIndex, unsigned fsIndex, unsigned refIndex,
465       bool showVolName, bool showFsName) const;
466 
467   bool CheckItemExtents(unsigned volIndex, const CItem &item) const;
468 
469 private:
470   IInStream *_stream;
471   CProgressVirt *_progress;
472 
473   HRESULT Read(unsigned volIndex, unsigned partitionRef, UInt32 blockPos, UInt32 len, Byte *buf);
474   HRESULT ReadLad(unsigned volIndex, const CLongAllocDesc &lad, Byte *buf);
475   HRESULT ReadFromFile(unsigned volIndex, const CItem &item, CByteBuffer &buf);
476 
477   HRESULT ReadFileItem(unsigned volIndex, unsigned fsIndex, const CLongAllocDesc &lad, bool isDir, int numRecurseAllowed);
478   HRESULT ReadItem(unsigned volIndex, int fsIndex, const CLongAllocDesc &lad, bool isDir, int numRecurseAllowed);
479 
480   HRESULT Open2();
481   HRESULT FillRefs(CFileSet &fs, unsigned fileIndex, int parent, int numRecurseAllowed);
482 
483   UInt64 _processedProgressBytes;
484 
485   UInt64 _fileNameLengthTotal;
486   unsigned _numRefs;
487   UInt32 _numExtents;
488   UInt64 _inlineExtentsSize;
489   bool CheckExtent(unsigned volIndex, unsigned partitionRef, UInt32 blockPos, UInt32 len) const;
490 
UpdatePhySize(UInt64 val)491   void UpdatePhySize(UInt64 val)
492   {
493     if (PhySize < val)
494       PhySize = val;
495   }
496 
UpdatePhySize(const CExtent & e)497   void UpdatePhySize(const CExtent &e)
498   {
499     UpdatePhySize(((UInt64)e.Pos << SecLogSize) + e.Len);
500   }
501 };
502 
503 API_FUNC_IsArc IsArc_Udf(const Byte *p, size_t size);
504 
505 }}
506 
507 #endif
508