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