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