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