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