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 // validate file is longer than header (when not a stream) 455 if (fileSize >= 0 && fileSize < (off_t)sizeof(header)) { 456 ErrorOutput()->PrintError("Error: Invalid %s file: Length shorter than " 457 "header!\n", fFileType); 458 return B_BAD_DATA; 459 } 460 461 // read the header 462 if ((error = ReadBuffer(0, &header, sizeof(header))) != B_OK) 463 return error; 464 465 // check the header 466 467 // magic 468 if (B_BENDIAN_TO_HOST_INT32(header.magic) != kMagic) { 469 ErrorOutput()->PrintError("Error: Invalid %s file: Invalid " 470 "magic\n", fFileType); 471 return B_BAD_DATA; 472 } 473 474 // version 475 if (B_BENDIAN_TO_HOST_INT16(header.version) != kVersion) { 476 if ((flags & B_HPKG_READER_DONT_PRINT_VERSION_MISMATCH_MESSAGE) == 0) { 477 ErrorOutput()->PrintError("Error: Invalid/unsupported %s file " 478 "version (%d)\n", fFileType, 479 B_BENDIAN_TO_HOST_INT16(header.version)); 480 } 481 return B_MISMATCHED_VALUES; 482 } 483 484 fMinorFormatVersion = B_BENDIAN_TO_HOST_INT16(header.minor_version); 485 fCurrentMinorFormatVersion = kMinorVersion; 486 487 // header size 488 uint64 heapOffset = B_BENDIAN_TO_HOST_INT16(header.header_size); 489 if (heapOffset < (off_t)sizeof(header)) { 490 ErrorOutput()->PrintError("Error: Invalid %s file: Invalid header " 491 "size (%" B_PRIu64 ")\n", fFileType, heapOffset); 492 return B_BAD_DATA; 493 } 494 495 // total size 496 uint64 totalSize = B_BENDIAN_TO_HOST_INT64(header.total_size); 497 if (fileSize >= 0 && totalSize != (uint64)fileSize) { 498 ErrorOutput()->PrintError("Error: Invalid %s file: Total size in " 499 "header (%" B_PRIu64 ") doesn't agree with total file size (%" 500 B_PRIdOFF ")\n", fFileType, totalSize, fileSize); 501 return B_BAD_DATA; 502 } 503 504 // heap size 505 uint64 compressedHeapSize 506 = B_BENDIAN_TO_HOST_INT64(header.heap_size_compressed); 507 if (compressedHeapSize > totalSize 508 || heapOffset > totalSize - compressedHeapSize) { 509 ErrorOutput()->PrintError("Error: Invalid %s file: Heap size in " 510 "header (%" B_PRIu64 ") doesn't agree with total file size (%" 511 B_PRIu64 ") and heap offset (%" B_PRIu64 ")\n", fFileType, 512 compressedHeapSize, totalSize, heapOffset); 513 return B_BAD_DATA; 514 } 515 516 error = InitHeapReader( 517 B_BENDIAN_TO_HOST_INT16(header.heap_compression), 518 B_BENDIAN_TO_HOST_INT32(header.heap_chunk_size), heapOffset, 519 compressedHeapSize, 520 B_BENDIAN_TO_HOST_INT64(header.heap_size_uncompressed)); 521 if (error != B_OK) 522 return error; 523 524 return B_OK; 525 } 526 527 528 inline BPositionIO* 529 ReaderImplBase::File() const 530 { 531 return fFile; 532 } 533 534 535 inline BErrorOutput* 536 ReaderImplBase::ErrorOutput() const 537 { 538 return fErrorOutput; 539 } 540 541 542 PackageFileSection* 543 ReaderImplBase::CurrentSection() 544 { 545 return fCurrentSection; 546 } 547 548 549 void 550 ReaderImplBase::SetCurrentSection(PackageFileSection* section) 551 { 552 fCurrentSection = section; 553 } 554 555 556 template<typename Type> 557 status_t 558 ReaderImplBase::_Read(Type& _value) 559 { 560 return _ReadSectionBuffer(&_value, sizeof(Type)); 561 } 562 563 564 inline ReaderImplBase::AttributeHandler* 565 ReaderImplBase::CurrentAttributeHandler() const 566 { 567 return fAttributeHandlerStack.Head(); 568 } 569 570 571 inline void 572 ReaderImplBase::PushAttributeHandler(AttributeHandler* handler) 573 { 574 fAttributeHandlerStack.Add(handler); 575 } 576 577 578 inline ReaderImplBase::AttributeHandler* 579 ReaderImplBase::PopAttributeHandler() 580 { 581 return fAttributeHandlerStack.RemoveHead(); 582 } 583 584 585 inline void 586 ReaderImplBase::ClearAttributeHandlerStack() 587 { 588 fAttributeHandlerStack.MakeEmpty(); 589 } 590 591 592 } // namespace BPrivate 593 594 } // namespace BHPKG 595 596 } // namespace BPackageKit 597 598 599 #endif // _PACKAGE__HPKG__PRIVATE__READER_IMPL_BASE_H_ 600