xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/MubHandler.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // MubHandler.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "../../../C/CpuArch.h"
6 #include "../../../C/SwapBytes.h"
7 
8 #include "../../Common/ComTry.h"
9 #include "../../Common/IntToString.h"
10 #include "../../Common/MyString.h"
11 
12 #include "../../Windows/PropVariant.h"
13 
14 #include "../Common/RegisterArc.h"
15 #include "../Common/StreamUtils.h"
16 
17 #include "HandlerCont.h"
18 
19 using namespace NWindows;
20 using namespace NCOM;
21 
22 namespace NArchive {
23 namespace NMub {
24 
25 #define MACH_CPU_ARCH_ABI64 ((UInt32)1 << 24)
26 #define MACH_CPU_TYPE_386    7
27 #define MACH_CPU_TYPE_ARM   12
28 #define MACH_CPU_TYPE_SPARC 14
29 #define MACH_CPU_TYPE_PPC   18
30 
31 #define MACH_CPU_TYPE_PPC64 (MACH_CPU_ARCH_ABI64 | MACH_CPU_TYPE_PPC)
32 #define MACH_CPU_TYPE_AMD64 (MACH_CPU_ARCH_ABI64 | MACH_CPU_TYPE_386)
33 #define MACH_CPU_TYPE_ARM64 (MACH_CPU_ARCH_ABI64 | MACH_CPU_TYPE_ARM)
34 
35 #define MACH_CPU_SUBTYPE_LIB64 ((UInt32)1 << 31)
36 
37 #define MACH_CPU_SUBTYPE_I386_ALL 3
38 
39 struct CItem
40 {
41   UInt32 Type;
42   UInt32 SubType;
43   UInt32 Offset;
44   UInt32 Size;
45   UInt32 Align;
46 };
47 
48 static const UInt32 kNumFilesMax = 6;
49 
50 Z7_class_CHandler_final: public CHandlerCont
51 {
52   Z7_IFACE_COM7_IMP(IInArchive_Cont)
53 
54   // UInt64 _startPos;
55   UInt64 _phySize;
56   UInt32 _numItems;
57   bool _bigEndian;
58   CItem _items[kNumFilesMax];
59 
60   HRESULT Open2(IInStream *stream);
61 
62   virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override
63   {
64     const CItem &item = _items[index];
65     pos = item.Offset;
66     size = item.Size;
67     return NExtract::NOperationResult::kOK;
68   }
69 };
70 
71 static const Byte kArcProps[] =
72 {
73   kpidBigEndian
74 };
75 
76 static const Byte kProps[] =
77 {
78   kpidPath,
79   kpidSize,
80   kpidOffset,
81   kpidClusterSize // Align
82 };
83 
84 IMP_IInArchive_Props
85 IMP_IInArchive_ArcProps
86 
87 Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
88 {
89   PropVariant_Clear(value);
90   switch (propID)
91   {
92     case kpidBigEndian: PropVarEm_Set_Bool(value, _bigEndian); break;
93     case kpidPhySize: PropVarEm_Set_UInt64(value, _phySize); break;
94   }
95   return S_OK;
96 }
97 
98 Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
99 {
100   PropVariant_Clear(value);
101   const CItem &item = _items[index];
102   switch (propID)
103   {
104     case kpidExtension:
105     {
106       char temp[32];
107       const char *ext = NULL;
108       switch (item.Type)
109       {
110         case MACH_CPU_TYPE_386:   ext = "x86";   break;
111         case MACH_CPU_TYPE_ARM:   ext = "arm";   break;
112         case MACH_CPU_TYPE_SPARC: ext = "sparc"; break;
113         case MACH_CPU_TYPE_PPC:   ext = "ppc";   break;
114         case MACH_CPU_TYPE_AMD64: ext = "x64";   break;
115         case MACH_CPU_TYPE_ARM64: ext = "arm64"; break;
116         case MACH_CPU_TYPE_PPC64: ext = "ppc64"; break;
117         default:
118           temp[0] = 'c';
119           temp[1] = 'p';
120           temp[2] = 'u';
121           char *p = ConvertUInt32ToString(item.Type & ~MACH_CPU_ARCH_ABI64, temp + 3);
122           if (item.Type & MACH_CPU_ARCH_ABI64)
123             MyStringCopy(p, "_64");
124           break;
125       }
126       if (ext)
127         MyStringCopy(temp, ext);
128       if (item.SubType != 0)
129       if ((item.Type != MACH_CPU_TYPE_386 &&
130            item.Type != MACH_CPU_TYPE_AMD64)
131            || (item.SubType & ~(UInt32)MACH_CPU_SUBTYPE_LIB64) != MACH_CPU_SUBTYPE_I386_ALL
132          )
133       {
134         unsigned pos = MyStringLen(temp);
135         temp[pos++] = '-';
136         ConvertUInt32ToString(item.SubType, temp + pos);
137       }
138       return PropVarEm_Set_Str(value, temp);
139     }
140     case kpidSize:
141     case kpidPackSize:
142       PropVarEm_Set_UInt64(value, item.Size);
143       break;
144     case kpidOffset:
145       PropVarEm_Set_UInt64(value, item.Offset);
146       break;
147     case kpidClusterSize:
148       PropVarEm_Set_UInt32(value, (UInt32)1 << item.Align);
149       break;
150   }
151   return S_OK;
152 }
153 
154 HRESULT CHandler::Open2(IInStream *stream)
155 {
156   // RINOK(InStream_GetPos(stream, _startPos));
157 
158   const UInt32 kHeaderSize = 2;
159   const UInt32 kRecordSize = 5;
160   const UInt32 kBufSize = kHeaderSize + kNumFilesMax * kRecordSize;
161   UInt32 buf[kBufSize];
162   size_t processed = kBufSize * 4;
163   RINOK(ReadStream(stream, buf, &processed))
164   processed >>= 2;
165   if (processed < kHeaderSize)
166     return S_FALSE;
167 
168   bool be;
169   switch (buf[0])
170   {
171     case Z7_CONV_BE_TO_NATIVE_CONST32(0xCAFEBABE): be = true; break;
172     case Z7_CONV_BE_TO_NATIVE_CONST32(0xB9FAF10E): be = false; break;
173     default: return S_FALSE;
174   }
175   _bigEndian = be;
176   if (
177       #if defined(MY_CPU_BE)
178         !
179       #endif
180         be)
181     z7_SwapBytes4(&buf[1], processed - 1);
182   const UInt32 num = buf[1];
183   if (num > kNumFilesMax || processed < kHeaderSize + num * kRecordSize)
184     return S_FALSE;
185   if (num == 0)
186     return S_FALSE;
187   UInt64 endPosMax = kHeaderSize;
188 
189   for (UInt32 i = 0; i < num; i++)
190   {
191     const UInt32 *p = buf + kHeaderSize + i * kRecordSize;
192     CItem &sb = _items[i];
193     sb.Type = p[0];
194     sb.SubType = p[1];
195     sb.Offset = p[2];
196     sb.Size = p[3];
197     const UInt32 align = p[4];
198     sb.Align = align;
199     if (align > 31)
200       return S_FALSE;
201     if (sb.Offset < kHeaderSize + num * kRecordSize)
202       return S_FALSE;
203     if ((sb.Type & ~MACH_CPU_ARCH_ABI64) >= 0x100 ||
204         (sb.SubType & ~MACH_CPU_SUBTYPE_LIB64) >= 0x100)
205       return S_FALSE;
206 
207     const UInt64 endPos = (UInt64)sb.Offset + sb.Size;
208     if (endPosMax < endPos)
209       endPosMax = endPos;
210   }
211   _numItems = num;
212   _phySize = endPosMax;
213   return S_OK;
214 }
215 
216 Z7_COM7F_IMF(CHandler::Open(IInStream *inStream,
217     const UInt64 * /* maxCheckStartPosition */,
218     IArchiveOpenCallback * /* openArchiveCallback */))
219 {
220   COM_TRY_BEGIN
221   Close();
222   try
223   {
224     if (Open2(inStream) != S_OK)
225       return S_FALSE;
226     _stream = inStream;
227   }
228   catch(...) { return S_FALSE; }
229   return S_OK;
230   COM_TRY_END
231 }
232 
233 Z7_COM7F_IMF(CHandler::Close())
234 {
235   _stream.Release();
236   _numItems = 0;
237   _phySize = 0;
238   return S_OK;
239 }
240 
241 Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
242 {
243   *numItems = _numItems;
244   return S_OK;
245 }
246 
247 namespace NBe {
248 
249 static const Byte k_Signature[] = {
250     7, 0xCA, 0xFE, 0xBA, 0xBE, 0, 0, 0,
251     4, 0xB9, 0xFA, 0xF1, 0x0E };
252 
253 REGISTER_ARC_I(
254   "Mub", "mub", NULL, 0xE2,
255   k_Signature,
256   0,
257   NArcInfoFlags::kMultiSignature,
258   NULL)
259 
260 }
261 
262 }}
263