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