1 /* 2 * Copyright 2009-2014, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de> 4 * Distributed under the terms of the MIT License. 5 */ 6 #ifndef _PACKAGE__HPKG__PRIVATE__READER_IMPL_BASE_H_ 7 #define _PACKAGE__HPKG__PRIVATE__READER_IMPL_BASE_H_ 8 9 10 #include <errno.h> 11 #include <sys/stat.h> 12 13 #include <ByteOrder.h> 14 #include <DataIO.h> 15 16 #include <Array.h> 17 #include <util/SinglyLinkedList.h> 18 19 #include <package/hpkg/ErrorOutput.h> 20 #include <package/hpkg/PackageAttributeValue.h> 21 #include <package/hpkg/PackageContentHandler.h> 22 #include <package/hpkg/PackageInfoAttributeValue.h> 23 24 25 class BCompressionAlgorithm; 26 class BDecompressionParameters; 27 28 29 namespace BPackageKit { 30 31 namespace BHPKG { 32 33 34 class BAbstractBufferedDataReader; 35 class BErrorOutput; 36 37 38 namespace BPrivate { 39 40 41 class PackageFileHeapReader; 42 43 44 struct PackageFileSection { 45 uint32 uncompressedLength; 46 uint8* data; 47 uint64 offset; 48 uint64 currentOffset; 49 uint64 stringsLength; 50 uint64 stringsCount; 51 char** strings; 52 const char* name; 53 54 PackageFileSection(const char* _name) 55 : 56 data(NULL), 57 strings(NULL), 58 name(_name) 59 { 60 } 61 62 ~PackageFileSection() 63 { 64 delete[] strings; 65 delete[] data; 66 } 67 }; 68 69 70 class ReaderImplBase { 71 public: 72 inline const PackageFileSection& PackageAttributesSection() const 73 { return fPackageAttributesSection; } 74 75 protected: 76 ReaderImplBase(const char* fileType, 77 BErrorOutput* errorOutput); 78 virtual ~ReaderImplBase(); 79 80 BPositionIO* File() const; 81 82 BErrorOutput* ErrorOutput() const; 83 84 uint16 MinorFormatVersion() const 85 { return fMinorFormatVersion; } 86 87 uint64 UncompressedHeapSize() const; 88 89 PackageFileHeapReader* RawHeapReader() const 90 { return fRawHeapReader; } 91 BAbstractBufferedDataReader* HeapReader() const 92 { return fHeapReader; } 93 // equals RawHeapReader(), if uncached 94 95 BAbstractBufferedDataReader* DetachHeapReader( 96 PackageFileHeapReader*& _rawHeapReader); 97 // Detaches both raw and (if applicable) 98 // cached heap reader. The called gains 99 // ownership of both. The file may need to 100 // be set on the raw heap reader, if it 101 // shall be used after destroying this 102 // object and Init() has been called with 103 // keepFile == true. 104 105 protected: 106 class AttributeHandlerContext; 107 class AttributeHandler; 108 class IgnoreAttributeHandler; 109 class PackageInfoAttributeHandlerBase; 110 class PackageVersionAttributeHandler; 111 class PackageResolvableAttributeHandler; 112 class PackageResolvableExpressionAttributeHandler; 113 class GlobalWritableFileInfoAttributeHandler; 114 class UserSettingsFileInfoAttributeHandler; 115 class UserAttributeHandler; 116 class PackageAttributeHandler; 117 class LowLevelAttributeHandler; 118 119 typedef BPackageAttributeValue AttributeValue; 120 typedef SinglyLinkedList<AttributeHandler> AttributeHandlerList; 121 122 protected: 123 template<typename Header, uint32 kMagic, uint16 kVersion, 124 uint16 kMinorVersion> 125 status_t Init(BPositionIO* file, bool keepFile, 126 Header& header, uint32 flags); 127 status_t InitHeapReader(uint32 compression, 128 uint32 chunkSize, off_t offset, 129 uint64 compressedSize, 130 uint64 uncompressedSize); 131 virtual status_t CreateCachedHeapReader( 132 PackageFileHeapReader* heapReader, 133 BAbstractBufferedDataReader*& 134 _cachedReader); 135 status_t InitSection(PackageFileSection& section, 136 uint64 endOffset, uint64 length, 137 uint64 maxSaneLength, uint64 stringsLength, 138 uint64 stringsCount); 139 status_t PrepareSection(PackageFileSection& section); 140 141 status_t ParseStrings(); 142 143 status_t ParsePackageAttributesSection( 144 AttributeHandlerContext* context, 145 AttributeHandler* rootAttributeHandler); 146 status_t ParseAttributeTree( 147 AttributeHandlerContext* context, 148 bool& _sectionHandled); 149 150 virtual status_t ReadAttributeValue(uint8 type, uint8 encoding, 151 AttributeValue& _value); 152 153 status_t ReadUnsignedLEB128(uint64& _value); 154 155 status_t ReadBuffer(off_t offset, void* buffer, 156 size_t size); 157 status_t ReadSection(const PackageFileSection& section); 158 159 inline AttributeHandler* CurrentAttributeHandler() const; 160 inline void PushAttributeHandler( 161 AttributeHandler* handler); 162 inline AttributeHandler* PopAttributeHandler(); 163 inline void ClearAttributeHandlerStack(); 164 165 inline PackageFileSection* CurrentSection(); 166 inline void SetCurrentSection(PackageFileSection* section); 167 168 protected: 169 PackageFileSection fPackageAttributesSection; 170 171 private: 172 status_t _Init(BPositionIO* file, bool keepFile); 173 174 status_t _ParseAttributeTree( 175 AttributeHandlerContext* context); 176 177 template<typename Type> 178 inline status_t _Read(Type& _value); 179 180 status_t _ReadSectionBuffer(void* buffer, size_t size); 181 182 status_t _ReadAttribute(uint8& _id, 183 AttributeValue& _value, 184 bool* _hasChildren = NULL, 185 uint64* _tag = NULL); 186 187 status_t _ReadString(const char*& _string, 188 size_t* _stringLength = NULL); 189 190 private: 191 const char* fFileType; 192 BErrorOutput* fErrorOutput; 193 BPositionIO* fFile; 194 bool fOwnsFile; 195 uint16 fMinorFormatVersion; 196 uint16 fCurrentMinorFormatVersion; 197 198 PackageFileHeapReader* fRawHeapReader; 199 BAbstractBufferedDataReader* fHeapReader; 200 201 PackageFileSection* fCurrentSection; 202 203 AttributeHandlerList fAttributeHandlerStack; 204 }; 205 206 207 // #pragma mark - attribute handlers 208 209 210 class ReaderImplBase::AttributeHandlerContext { 211 public: 212 BErrorOutput* errorOutput; 213 union { 214 BPackageContentHandler* packageContentHandler; 215 BLowLevelPackageContentHandler* lowLevelHandler; 216 }; 217 bool hasLowLevelHandler; 218 bool ignoreUnknownAttributes; 219 220 BHPKGPackageSectionID section; 221 222 public: 223 AttributeHandlerContext( 224 BErrorOutput* errorOutput, 225 BPackageContentHandler* 226 packageContentHandler, 227 BHPKGPackageSectionID section, 228 bool ignoreUnknownAttributes); 229 AttributeHandlerContext( 230 BErrorOutput* errorOutput, 231 BLowLevelPackageContentHandler* 232 lowLevelHandler, 233 BHPKGPackageSectionID section, 234 bool ignoreUnknownAttributes); 235 236 void ErrorOccurred(); 237 }; 238 239 240 class ReaderImplBase::AttributeHandler 241 : public SinglyLinkedListLinkImpl<AttributeHandler> { 242 public: 243 virtual ~AttributeHandler(); 244 245 void SetLevel(int level); 246 virtual status_t HandleAttribute( 247 AttributeHandlerContext* context, uint8 id, 248 const AttributeValue& value, 249 AttributeHandler** _handler); 250 251 virtual status_t NotifyDone(AttributeHandlerContext* context); 252 253 virtual status_t Delete(AttributeHandlerContext* context); 254 255 protected: 256 int fLevel; 257 }; 258 259 260 class ReaderImplBase::IgnoreAttributeHandler : public AttributeHandler { 261 }; 262 263 264 class ReaderImplBase::PackageInfoAttributeHandlerBase 265 : public AttributeHandler { 266 private: 267 typedef AttributeHandler super; 268 public: 269 PackageInfoAttributeHandlerBase( 270 BPackageInfoAttributeValue& 271 packageInfoValue); 272 273 virtual status_t NotifyDone(AttributeHandlerContext* context); 274 275 protected: 276 BPackageInfoAttributeValue& fPackageInfoValue; 277 }; 278 279 280 class ReaderImplBase::PackageVersionAttributeHandler 281 : public PackageInfoAttributeHandlerBase { 282 private: 283 typedef PackageInfoAttributeHandlerBase super; 284 public: 285 PackageVersionAttributeHandler( 286 BPackageInfoAttributeValue& 287 packageInfoValue, 288 BPackageVersionData& versionData, 289 bool notify); 290 291 virtual status_t HandleAttribute( 292 AttributeHandlerContext* context, uint8 id, 293 const AttributeValue& value, 294 AttributeHandler** _handler); 295 296 virtual status_t NotifyDone(AttributeHandlerContext* context); 297 298 private: 299 BPackageVersionData& fPackageVersionData; 300 bool fNotify; 301 }; 302 303 304 class ReaderImplBase::PackageResolvableAttributeHandler 305 : public PackageInfoAttributeHandlerBase { 306 private: 307 typedef PackageInfoAttributeHandlerBase super; 308 public: 309 PackageResolvableAttributeHandler( 310 BPackageInfoAttributeValue& 311 packageInfoValue); 312 313 virtual status_t HandleAttribute( 314 AttributeHandlerContext* context, uint8 id, 315 const AttributeValue& value, 316 AttributeHandler** _handler); 317 }; 318 319 320 class ReaderImplBase::PackageResolvableExpressionAttributeHandler 321 : public PackageInfoAttributeHandlerBase { 322 private: 323 typedef PackageInfoAttributeHandlerBase super; 324 public: 325 PackageResolvableExpressionAttributeHandler( 326 BPackageInfoAttributeValue& 327 packageInfoValue); 328 329 virtual status_t HandleAttribute( 330 AttributeHandlerContext* context, uint8 id, 331 const AttributeValue& value, 332 AttributeHandler** _handler); 333 }; 334 335 336 class ReaderImplBase::GlobalWritableFileInfoAttributeHandler 337 : public PackageInfoAttributeHandlerBase { 338 private: 339 typedef PackageInfoAttributeHandlerBase super; 340 public: 341 GlobalWritableFileInfoAttributeHandler( 342 BPackageInfoAttributeValue& 343 packageInfoValue); 344 345 virtual status_t HandleAttribute( 346 AttributeHandlerContext* context, uint8 id, 347 const AttributeValue& value, 348 AttributeHandler** _handler); 349 }; 350 351 352 class ReaderImplBase::UserSettingsFileInfoAttributeHandler 353 : public PackageInfoAttributeHandlerBase { 354 private: 355 typedef PackageInfoAttributeHandlerBase super; 356 public: 357 UserSettingsFileInfoAttributeHandler( 358 BPackageInfoAttributeValue& 359 packageInfoValue); 360 361 virtual status_t HandleAttribute( 362 AttributeHandlerContext* context, uint8 id, 363 const AttributeValue& value, 364 AttributeHandler** _handler); 365 }; 366 367 368 class ReaderImplBase::UserAttributeHandler 369 : public PackageInfoAttributeHandlerBase { 370 private: 371 typedef PackageInfoAttributeHandlerBase super; 372 public: 373 UserAttributeHandler( 374 BPackageInfoAttributeValue& 375 packageInfoValue); 376 377 virtual status_t HandleAttribute( 378 AttributeHandlerContext* context, uint8 id, 379 const AttributeValue& value, 380 AttributeHandler** _handler); 381 382 virtual status_t NotifyDone(AttributeHandlerContext* context); 383 384 private: 385 Array<const char*> fGroups; 386 }; 387 388 389 class ReaderImplBase::PackageAttributeHandler : public AttributeHandler { 390 private: 391 typedef AttributeHandler super; 392 public: 393 virtual status_t HandleAttribute( 394 AttributeHandlerContext* context, uint8 id, 395 const AttributeValue& value, 396 AttributeHandler** _handler); 397 398 private: 399 BPackageInfoAttributeValue fPackageInfoValue; 400 }; 401 402 403 class ReaderImplBase::LowLevelAttributeHandler : public AttributeHandler { 404 private: 405 typedef AttributeHandler super; 406 public: 407 LowLevelAttributeHandler(); 408 LowLevelAttributeHandler(uint8 id, 409 const BPackageAttributeValue& value, 410 void* parentToken, void* token); 411 412 virtual status_t HandleAttribute( 413 AttributeHandlerContext* context, uint8 id, 414 const AttributeValue& value, 415 AttributeHandler** _handler); 416 417 virtual status_t NotifyDone(AttributeHandlerContext* context); 418 419 private: 420 void* fParentToken; 421 void* fToken; 422 uint8 fID; 423 AttributeValue fValue; 424 }; 425 426 427 // #pragma mark - template and inline methods 428 429 430 template<typename Header, uint32 kMagic, uint16 kVersion, uint16 kMinorVersion> 431 status_t 432 ReaderImplBase::Init(BPositionIO* file, bool keepFile, Header& header, uint32 flags) 433 { 434 status_t error = _Init(file, keepFile); 435 if (error != B_OK) 436 return error; 437 438 // get the file size 439 off_t fileSize; 440 error = fFile->GetSize(&fileSize); 441 if (error != B_OK) { 442 if (error != B_NOT_SUPPORTED) { 443 ErrorOutput()->PrintError( 444 "Error: Failed to get size of %s file: %s\n", 445 fFileType, strerror(error)); 446 return error; 447 } 448 449 // Might be a stream. We only use the file size for checking the total 450 // heap size, which we don't have to do. 451 fileSize = -1; 452 } 453 454 // read the header 455 if ((error = ReadBuffer(0, &header, sizeof(header))) != B_OK) 456 return error; 457 458 // check the header 459 460 // magic 461 if (B_BENDIAN_TO_HOST_INT32(header.magic) != kMagic) { 462 ErrorOutput()->PrintError("Error: Invalid %s file: Invalid " 463 "magic\n", fFileType); 464 return B_BAD_DATA; 465 } 466 467 // version 468 if (B_BENDIAN_TO_HOST_INT16(header.version) != kVersion) { 469 if ((flags & B_HPKG_READER_DONT_PRINT_VERSION_MISMATCH_MESSAGE) == 0) { 470 ErrorOutput()->PrintError("Error: Invalid/unsupported %s file " 471 "version (%d)\n", fFileType, 472 B_BENDIAN_TO_HOST_INT16(header.version)); 473 } 474 return B_MISMATCHED_VALUES; 475 } 476 477 fMinorFormatVersion = B_BENDIAN_TO_HOST_INT16(header.minor_version); 478 fCurrentMinorFormatVersion = kMinorVersion; 479 480 // header size 481 uint64 heapOffset = B_BENDIAN_TO_HOST_INT16(header.header_size); 482 if (heapOffset < (off_t)sizeof(header)) { 483 ErrorOutput()->PrintError("Error: Invalid %s file: Invalid header " 484 "size (%" B_PRIu64 ")\n", fFileType, heapOffset); 485 return B_BAD_DATA; 486 } 487 488 // total size 489 uint64 totalSize = B_BENDIAN_TO_HOST_INT64(header.total_size); 490 if (fileSize >= 0 && totalSize != (uint64)fileSize) { 491 ErrorOutput()->PrintError("Error: Invalid %s file: Total size in " 492 "header (%" B_PRIu64 ") doesn't agree with total file size (%" 493 B_PRIdOFF ")\n", fFileType, totalSize, fileSize); 494 return B_BAD_DATA; 495 } 496 497 // heap size 498 uint64 compressedHeapSize 499 = B_BENDIAN_TO_HOST_INT64(header.heap_size_compressed); 500 if (compressedHeapSize > totalSize 501 || heapOffset > totalSize - compressedHeapSize) { 502 ErrorOutput()->PrintError("Error: Invalid %s file: Heap size in " 503 "header (%" B_PRIu64 ") doesn't agree with total file size (%" 504 B_PRIu64 ") and heap offset (%" B_PRIu64 ")\n", fFileType, 505 compressedHeapSize, totalSize, heapOffset); 506 return B_BAD_DATA; 507 } 508 509 error = InitHeapReader( 510 B_BENDIAN_TO_HOST_INT16(header.heap_compression), 511 B_BENDIAN_TO_HOST_INT32(header.heap_chunk_size), heapOffset, 512 compressedHeapSize, 513 B_BENDIAN_TO_HOST_INT64(header.heap_size_uncompressed)); 514 if (error != B_OK) 515 return error; 516 517 return B_OK; 518 } 519 520 521 inline BPositionIO* 522 ReaderImplBase::File() const 523 { 524 return fFile; 525 } 526 527 528 inline BErrorOutput* 529 ReaderImplBase::ErrorOutput() const 530 { 531 return fErrorOutput; 532 } 533 534 535 PackageFileSection* 536 ReaderImplBase::CurrentSection() 537 { 538 return fCurrentSection; 539 } 540 541 542 void 543 ReaderImplBase::SetCurrentSection(PackageFileSection* section) 544 { 545 fCurrentSection = section; 546 } 547 548 549 template<typename Type> 550 status_t 551 ReaderImplBase::_Read(Type& _value) 552 { 553 return _ReadSectionBuffer(&_value, sizeof(Type)); 554 } 555 556 557 inline ReaderImplBase::AttributeHandler* 558 ReaderImplBase::CurrentAttributeHandler() const 559 { 560 return fAttributeHandlerStack.Head(); 561 } 562 563 564 inline void 565 ReaderImplBase::PushAttributeHandler(AttributeHandler* handler) 566 { 567 fAttributeHandlerStack.Add(handler); 568 } 569 570 571 inline ReaderImplBase::AttributeHandler* 572 ReaderImplBase::PopAttributeHandler() 573 { 574 return fAttributeHandlerStack.RemoveHead(); 575 } 576 577 578 inline void 579 ReaderImplBase::ClearAttributeHandlerStack() 580 { 581 fAttributeHandlerStack.MakeEmpty(); 582 } 583 584 585 } // namespace BPrivate 586 587 } // namespace BHPKG 588 589 } // namespace BPackageKit 590 591 592 #endif // _PACKAGE__HPKG__PRIVATE__READER_IMPL_BASE_H_ 593