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 202 203 // #pragma mark - attribute handlers 204 205 206 class ReaderImplBase::AttributeHandlerContext { 207 public: 208 BErrorOutput* errorOutput; 209 union { 210 BPackageContentHandler* packageContentHandler; 211 BLowLevelPackageContentHandler* lowLevelHandler; 212 }; 213 bool hasLowLevelHandler; 214 bool ignoreUnknownAttributes; 215 216 BHPKGPackageSectionID section; 217 218 public: 219 AttributeHandlerContext( 220 BErrorOutput* errorOutput, 221 BPackageContentHandler* 222 packageContentHandler, 223 BHPKGPackageSectionID section, 224 bool ignoreUnknownAttributes); 225 AttributeHandlerContext( 226 BErrorOutput* errorOutput, 227 BLowLevelPackageContentHandler* 228 lowLevelHandler, 229 BHPKGPackageSectionID section, 230 bool ignoreUnknownAttributes); 231 232 void ErrorOccurred(); 233 }; 234 235 236 class ReaderImplBase::AttributeHandler 237 : public SinglyLinkedListLinkImpl<AttributeHandler> { 238 public: 239 virtual ~AttributeHandler(); 240 241 void SetLevel(int level); 242 virtual status_t HandleAttribute( 243 AttributeHandlerContext* context, uint8 id, 244 const AttributeValue& value, 245 AttributeHandler** _handler); 246 247 virtual status_t NotifyDone(AttributeHandlerContext* context); 248 249 virtual status_t Delete(AttributeHandlerContext* context); 250 251 protected: 252 int fLevel; 253 }; 254 255 256 class ReaderImplBase::IgnoreAttributeHandler : public AttributeHandler { 257 }; 258 259 260 class ReaderImplBase::PackageInfoAttributeHandlerBase 261 : public AttributeHandler { 262 private: 263 typedef AttributeHandler super; 264 public: 265 PackageInfoAttributeHandlerBase( 266 BPackageInfoAttributeValue& 267 packageInfoValue); 268 269 virtual status_t NotifyDone(AttributeHandlerContext* context); 270 271 protected: 272 BPackageInfoAttributeValue& fPackageInfoValue; 273 }; 274 275 276 class ReaderImplBase::PackageVersionAttributeHandler 277 : public PackageInfoAttributeHandlerBase { 278 private: 279 typedef PackageInfoAttributeHandlerBase super; 280 public: 281 PackageVersionAttributeHandler( 282 BPackageInfoAttributeValue& 283 packageInfoValue, 284 BPackageVersionData& versionData, 285 bool notify); 286 287 virtual status_t HandleAttribute( 288 AttributeHandlerContext* context, uint8 id, 289 const AttributeValue& value, 290 AttributeHandler** _handler); 291 292 virtual status_t NotifyDone(AttributeHandlerContext* context); 293 294 private: 295 BPackageVersionData& fPackageVersionData; 296 bool fNotify; 297 }; 298 299 300 class ReaderImplBase::PackageResolvableAttributeHandler 301 : public PackageInfoAttributeHandlerBase { 302 private: 303 typedef PackageInfoAttributeHandlerBase super; 304 public: 305 PackageResolvableAttributeHandler( 306 BPackageInfoAttributeValue& 307 packageInfoValue); 308 309 virtual status_t HandleAttribute( 310 AttributeHandlerContext* context, uint8 id, 311 const AttributeValue& value, 312 AttributeHandler** _handler); 313 }; 314 315 316 class ReaderImplBase::PackageResolvableExpressionAttributeHandler 317 : public PackageInfoAttributeHandlerBase { 318 private: 319 typedef PackageInfoAttributeHandlerBase super; 320 public: 321 PackageResolvableExpressionAttributeHandler( 322 BPackageInfoAttributeValue& 323 packageInfoValue); 324 325 virtual status_t HandleAttribute( 326 AttributeHandlerContext* context, uint8 id, 327 const AttributeValue& value, 328 AttributeHandler** _handler); 329 }; 330 331 332 class ReaderImplBase::GlobalWritableFileInfoAttributeHandler 333 : public PackageInfoAttributeHandlerBase { 334 private: 335 typedef PackageInfoAttributeHandlerBase super; 336 public: 337 GlobalWritableFileInfoAttributeHandler( 338 BPackageInfoAttributeValue& 339 packageInfoValue); 340 341 virtual status_t HandleAttribute( 342 AttributeHandlerContext* context, uint8 id, 343 const AttributeValue& value, 344 AttributeHandler** _handler); 345 }; 346 347 348 class ReaderImplBase::UserSettingsFileInfoAttributeHandler 349 : public PackageInfoAttributeHandlerBase { 350 private: 351 typedef PackageInfoAttributeHandlerBase super; 352 public: 353 UserSettingsFileInfoAttributeHandler( 354 BPackageInfoAttributeValue& 355 packageInfoValue); 356 357 virtual status_t HandleAttribute( 358 AttributeHandlerContext* context, uint8 id, 359 const AttributeValue& value, 360 AttributeHandler** _handler); 361 }; 362 363 364 class ReaderImplBase::UserAttributeHandler 365 : public PackageInfoAttributeHandlerBase { 366 private: 367 typedef PackageInfoAttributeHandlerBase super; 368 public: 369 UserAttributeHandler( 370 BPackageInfoAttributeValue& 371 packageInfoValue); 372 373 virtual status_t HandleAttribute( 374 AttributeHandlerContext* context, uint8 id, 375 const AttributeValue& value, 376 AttributeHandler** _handler); 377 378 virtual status_t NotifyDone(AttributeHandlerContext* context); 379 380 private: 381 Array<const char*> fGroups; 382 }; 383 384 385 class ReaderImplBase::PackageAttributeHandler : public AttributeHandler { 386 private: 387 typedef AttributeHandler super; 388 public: 389 virtual status_t HandleAttribute( 390 AttributeHandlerContext* context, uint8 id, 391 const AttributeValue& value, 392 AttributeHandler** _handler); 393 394 private: 395 BPackageInfoAttributeValue fPackageInfoValue; 396 }; 397 398 399 class ReaderImplBase::LowLevelAttributeHandler : public AttributeHandler { 400 private: 401 typedef AttributeHandler super; 402 public: 403 LowLevelAttributeHandler(); 404 LowLevelAttributeHandler(uint8 id, 405 const BPackageAttributeValue& value, 406 void* parentToken, void* token); 407 408 virtual status_t HandleAttribute( 409 AttributeHandlerContext* context, uint8 id, 410 const AttributeValue& value, 411 AttributeHandler** _handler); 412 413 virtual status_t NotifyDone(AttributeHandlerContext* context); 414 415 private: 416 void* fParentToken; 417 void* fToken; 418 uint8 fID; 419 AttributeValue fValue; 420 }; 421 422 423 // #pragma mark - template and inline methods 424 425 426 template<typename Header, uint32 kMagic, uint16 kVersion, uint16 kMinorVersion> 427 status_t 428 ReaderImplBase::Init(int fd, bool keepFD, Header& header, uint32 flags) 429 { 430 status_t error = _Init(fd, keepFD); 431 if (error != B_OK) 432 return error; 433 434 // stat the file 435 struct stat st; 436 if (fstat(FD(), &st) < 0) { 437 ErrorOutput()->PrintError("Error: Failed to access %s file: %s\n", 438 fFileType, strerror(errno)); 439 return errno; 440 } 441 442 // read the header 443 if ((error = ReadBuffer(0, &header, sizeof(header))) != B_OK) 444 return error; 445 446 // check the header 447 448 // magic 449 if (B_BENDIAN_TO_HOST_INT32(header.magic) != kMagic) { 450 ErrorOutput()->PrintError("Error: Invalid %s file: Invalid " 451 "magic\n", fFileType); 452 return B_BAD_DATA; 453 } 454 455 // version 456 if (B_BENDIAN_TO_HOST_INT16(header.version) != kVersion) { 457 if ((flags & B_HPKG_READER_DONT_PRINT_VERSION_MISMATCH_MESSAGE) == 0) { 458 ErrorOutput()->PrintError("Error: Invalid/unsupported %s file " 459 "version (%d)\n", fFileType, 460 B_BENDIAN_TO_HOST_INT16(header.version)); 461 } 462 return B_MISMATCHED_VALUES; 463 } 464 465 fMinorFormatVersion = B_BENDIAN_TO_HOST_INT16(header.minor_version); 466 fCurrentMinorFormatVersion = kMinorVersion; 467 468 // header size 469 uint64 heapOffset = B_BENDIAN_TO_HOST_INT16(header.header_size); 470 if (heapOffset < (off_t)sizeof(header)) { 471 ErrorOutput()->PrintError("Error: Invalid %s file: Invalid header " 472 "size (%" B_PRIu64 ")\n", fFileType, heapOffset); 473 return B_BAD_DATA; 474 } 475 476 // total size 477 uint64 totalSize = B_BENDIAN_TO_HOST_INT64(header.total_size); 478 if (totalSize != (uint64)st.st_size) { 479 ErrorOutput()->PrintError("Error: Invalid %s file: Total size in " 480 "header (%" B_PRIu64 ") doesn't agree with total file size (%" 481 B_PRIdOFF ")\n", fFileType, totalSize, st.st_size); 482 return B_BAD_DATA; 483 } 484 485 // heap size 486 uint64 compressedHeapSize 487 = B_BENDIAN_TO_HOST_INT64(header.heap_size_compressed); 488 if (compressedHeapSize > totalSize 489 || heapOffset > totalSize - compressedHeapSize) { 490 ErrorOutput()->PrintError("Error: Invalid %s file: Heap size in " 491 "header (%" B_PRIu64 ") doesn't agree with total file size (%" 492 B_PRIu64 ") and heap offset (%" B_PRIu64 ")\n", fFileType, 493 compressedHeapSize, totalSize, heapOffset); 494 return B_BAD_DATA; 495 } 496 497 error = InitHeapReader( 498 B_BENDIAN_TO_HOST_INT16(header.heap_compression), 499 B_BENDIAN_TO_HOST_INT32(header.heap_chunk_size), heapOffset, 500 compressedHeapSize, 501 B_BENDIAN_TO_HOST_INT64(header.heap_size_uncompressed)); 502 if (error != B_OK) 503 return error; 504 505 return B_OK; 506 } 507 508 509 inline int 510 ReaderImplBase::FD() const 511 { 512 return fFD; 513 } 514 515 516 inline BErrorOutput* 517 ReaderImplBase::ErrorOutput() const 518 { 519 return fErrorOutput; 520 } 521 522 523 PackageFileSection* 524 ReaderImplBase::CurrentSection() 525 { 526 return fCurrentSection; 527 } 528 529 530 void 531 ReaderImplBase::SetCurrentSection(PackageFileSection* section) 532 { 533 fCurrentSection = section; 534 } 535 536 537 template<typename Type> 538 status_t 539 ReaderImplBase::_Read(Type& _value) 540 { 541 return _ReadSectionBuffer(&_value, sizeof(Type)); 542 } 543 544 545 inline ReaderImplBase::AttributeHandler* 546 ReaderImplBase::CurrentAttributeHandler() const 547 { 548 return fAttributeHandlerStack.Head(); 549 } 550 551 552 inline void 553 ReaderImplBase::PushAttributeHandler(AttributeHandler* handler) 554 { 555 fAttributeHandlerStack.Add(handler); 556 } 557 558 559 inline ReaderImplBase::AttributeHandler* 560 ReaderImplBase::PopAttributeHandler() 561 { 562 return fAttributeHandlerStack.RemoveHead(); 563 } 564 565 566 inline void 567 ReaderImplBase::ClearAttributeHandlerStack() 568 { 569 fAttributeHandlerStack.MakeEmpty(); 570 } 571 572 573 } // namespace BPrivate 574 575 } // namespace BHPKG 576 577 } // namespace BPackageKit 578 579 580 #endif // _PACKAGE__HPKG__PRIVATE__READER_IMPL_BASE_H_ 581