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 7 8 #include <package/hpkg/v1/ReaderImplBase.h> 9 10 #include <errno.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <unistd.h> 15 16 #include <algorithm> 17 #include <new> 18 19 #include <ByteOrder.h> 20 #include <DataIO.h> 21 22 #include <package/hpkg/ErrorOutput.h> 23 24 #include <AutoDeleter.h> 25 #include <package/hpkg/v1/HPKGDefsPrivate.h> 26 #include <ZlibCompressionAlgorithm.h> 27 28 29 namespace BPackageKit { 30 31 namespace BHPKG { 32 33 namespace V1 { 34 35 namespace BPrivate { 36 37 38 static const size_t kScratchBufferSize = 64 * 1024; 39 40 41 // #pragma mark - AttributeHandlerContext 42 43 44 ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext( 45 BErrorOutput* errorOutput, BPackageContentHandler* packageContentHandler, 46 BHPKGPackageSectionID section) 47 : 48 errorOutput(errorOutput), 49 packageContentHandler(packageContentHandler), 50 hasLowLevelHandler(false), 51 section(section) 52 { 53 } 54 55 56 ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext( 57 BErrorOutput* errorOutput, BLowLevelPackageContentHandler* lowLevelHandler, 58 BHPKGPackageSectionID section) 59 : 60 errorOutput(errorOutput), 61 lowLevelHandler(lowLevelHandler), 62 hasLowLevelHandler(true), 63 section(section) 64 { 65 } 66 67 68 void 69 ReaderImplBase::AttributeHandlerContext::ErrorOccurred() 70 { 71 if (hasLowLevelHandler) 72 lowLevelHandler->HandleErrorOccurred(); 73 else 74 packageContentHandler->HandleErrorOccurred(); 75 } 76 77 78 // #pragma mark - AttributeHandler 79 80 81 ReaderImplBase::AttributeHandler::~AttributeHandler() 82 { 83 } 84 85 86 void 87 ReaderImplBase::AttributeHandler::SetLevel(int level) 88 { 89 fLevel = level; 90 } 91 92 93 status_t 94 ReaderImplBase::AttributeHandler::HandleAttribute( 95 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 96 AttributeHandler** _handler) 97 { 98 return B_OK; 99 } 100 101 102 status_t 103 ReaderImplBase::AttributeHandler::Delete(AttributeHandlerContext* context) 104 { 105 delete this; 106 return B_OK; 107 } 108 109 110 // #pragma mark - PackageVersionAttributeHandler 111 112 113 ReaderImplBase::PackageVersionAttributeHandler::PackageVersionAttributeHandler( 114 BPackageInfoAttributeValue& packageInfoValue, 115 BPackageVersionData& versionData, bool notify) 116 : 117 fPackageInfoValue(packageInfoValue), 118 fPackageVersionData(versionData), 119 fNotify(notify) 120 { 121 } 122 123 124 status_t 125 ReaderImplBase::PackageVersionAttributeHandler::HandleAttribute( 126 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 127 AttributeHandler** _handler) 128 { 129 switch (id) { 130 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MINOR: 131 fPackageVersionData.minor = value.string; 132 break; 133 134 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MICRO: 135 fPackageVersionData.micro = value.string; 136 break; 137 138 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_PRE_RELEASE: 139 fPackageVersionData.preRelease = value.string; 140 break; 141 142 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_REVISION: 143 fPackageVersionData.revision = value.unsignedInt; 144 break; 145 146 default: 147 context->errorOutput->PrintError("Error: Invalid package " 148 "attribute section: unexpected package attribute id %d " 149 "encountered when parsing package version\n", id); 150 return B_BAD_DATA; 151 } 152 153 return B_OK; 154 } 155 156 157 status_t 158 ReaderImplBase::PackageVersionAttributeHandler::Delete( 159 AttributeHandlerContext* context) 160 { 161 status_t error = B_OK; 162 if (fNotify) { 163 fPackageInfoValue.attributeID = B_PACKAGE_INFO_VERSION; 164 error = context->packageContentHandler->HandlePackageAttribute( 165 fPackageInfoValue); 166 fPackageInfoValue.Clear(); 167 } 168 169 delete this; 170 return error; 171 } 172 173 174 // #pragma mark - PackageResolvableAttributeHandler 175 176 177 ReaderImplBase::PackageResolvableAttributeHandler 178 ::PackageResolvableAttributeHandler( 179 BPackageInfoAttributeValue& packageInfoValue) 180 : 181 fPackageInfoValue(packageInfoValue) 182 { 183 } 184 185 186 status_t 187 ReaderImplBase::PackageResolvableAttributeHandler::HandleAttribute( 188 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 189 AttributeHandler** _handler) 190 { 191 switch (id) { 192 case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_TYPE: 193 // obsolete 194 break; 195 196 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR: 197 fPackageInfoValue.resolvable.haveVersion = true; 198 fPackageInfoValue.resolvable.version.major = value.string; 199 if (_handler != NULL) { 200 *_handler 201 = new(std::nothrow) PackageVersionAttributeHandler( 202 fPackageInfoValue, 203 fPackageInfoValue.resolvable.version, false); 204 if (*_handler == NULL) 205 return B_NO_MEMORY; 206 } 207 break; 208 209 case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_COMPATIBLE: 210 fPackageInfoValue.resolvable.haveCompatibleVersion = true; 211 fPackageInfoValue.resolvable.compatibleVersion.major = value.string; 212 if (_handler != NULL) { 213 *_handler 214 = new(std::nothrow) PackageVersionAttributeHandler( 215 fPackageInfoValue, 216 fPackageInfoValue.resolvable.compatibleVersion, false); 217 if (*_handler == NULL) 218 return B_NO_MEMORY; 219 } 220 break; 221 222 default: 223 context->errorOutput->PrintError("Error: Invalid package " 224 "attribute section: unexpected package attribute id %d " 225 "encountered when parsing package resolvable\n", id); 226 return B_BAD_DATA; 227 } 228 229 return B_OK; 230 } 231 232 233 status_t 234 ReaderImplBase::PackageResolvableAttributeHandler::Delete( 235 AttributeHandlerContext* context) 236 { 237 status_t error = context->packageContentHandler->HandlePackageAttribute( 238 fPackageInfoValue); 239 fPackageInfoValue.Clear(); 240 241 delete this; 242 return error; 243 } 244 245 246 // #pragma mark - PackageResolvableExpressionAttributeHandler 247 248 249 ReaderImplBase::PackageResolvableExpressionAttributeHandler 250 ::PackageResolvableExpressionAttributeHandler( 251 BPackageInfoAttributeValue& packageInfoValue) 252 : 253 fPackageInfoValue(packageInfoValue) 254 { 255 } 256 257 258 status_t 259 ReaderImplBase::PackageResolvableExpressionAttributeHandler::HandleAttribute( 260 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 261 AttributeHandler** _handler) 262 { 263 switch (id) { 264 case B_HPKG_ATTRIBUTE_ID_PACKAGE_RESOLVABLE_OPERATOR: 265 if (value.unsignedInt >= B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT) { 266 context->errorOutput->PrintError( 267 "Error: Invalid package attribute section: invalid " 268 "package resolvable operator %lld encountered\n", 269 value.unsignedInt); 270 return B_BAD_DATA; 271 } 272 fPackageInfoValue.resolvableExpression.op 273 = (BPackageResolvableOperator)value.unsignedInt; 274 break; 275 276 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR: 277 fPackageInfoValue.resolvableExpression.haveOpAndVersion = true; 278 fPackageInfoValue.resolvableExpression.version.major 279 = value.string; 280 if (_handler != NULL) { 281 *_handler 282 = new(std::nothrow) PackageVersionAttributeHandler( 283 fPackageInfoValue, 284 fPackageInfoValue.resolvableExpression.version, 285 false); 286 if (*_handler == NULL) 287 return B_NO_MEMORY; 288 } 289 return B_OK; 290 291 default: 292 context->errorOutput->PrintError("Error: Invalid package " 293 "attribute section: unexpected package attribute id %d " 294 "encountered when parsing package resolvable-expression\n", 295 id); 296 return B_BAD_DATA; 297 } 298 299 return B_OK; 300 } 301 302 303 status_t 304 ReaderImplBase::PackageResolvableExpressionAttributeHandler::Delete( 305 AttributeHandlerContext* context) 306 { 307 status_t error = context->packageContentHandler->HandlePackageAttribute( 308 fPackageInfoValue); 309 fPackageInfoValue.Clear(); 310 311 delete this; 312 return error; 313 } 314 315 316 // #pragma mark - PackageAttributeHandler 317 318 319 status_t 320 ReaderImplBase::PackageAttributeHandler::HandleAttribute( 321 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 322 AttributeHandler** _handler) 323 { 324 switch (id) { 325 case B_HPKG_ATTRIBUTE_ID_PACKAGE_NAME: 326 fPackageInfoValue.SetTo(B_PACKAGE_INFO_NAME, value.string); 327 break; 328 329 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUMMARY: 330 fPackageInfoValue.SetTo(B_PACKAGE_INFO_SUMMARY, value.string); 331 break; 332 333 case B_HPKG_ATTRIBUTE_ID_PACKAGE_DESCRIPTION: 334 fPackageInfoValue.SetTo(B_PACKAGE_INFO_DESCRIPTION, 335 value.string); 336 break; 337 338 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VENDOR: 339 fPackageInfoValue.SetTo(B_PACKAGE_INFO_VENDOR, value.string); 340 break; 341 342 case B_HPKG_ATTRIBUTE_ID_PACKAGE_PACKAGER: 343 fPackageInfoValue.SetTo(B_PACKAGE_INFO_PACKAGER, value.string); 344 break; 345 346 case B_HPKG_ATTRIBUTE_ID_PACKAGE_FLAGS: 347 fPackageInfoValue.SetTo(B_PACKAGE_INFO_FLAGS, 348 (uint32)value.unsignedInt); 349 break; 350 351 case B_HPKG_ATTRIBUTE_ID_PACKAGE_ARCHITECTURE: 352 if (value.unsignedInt 353 >= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) { 354 context->errorOutput->PrintError( 355 "Error: Invalid package attribute section: " 356 "Invalid package architecture %lld encountered\n", 357 value.unsignedInt); 358 return B_BAD_DATA; 359 } 360 fPackageInfoValue.SetTo(B_PACKAGE_INFO_ARCHITECTURE, 361 (uint8)value.unsignedInt); 362 break; 363 364 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR: 365 fPackageInfoValue.attributeID = B_PACKAGE_INFO_VERSION; 366 fPackageInfoValue.version.major = value.string; 367 if (_handler != NULL) { 368 *_handler 369 = new(std::nothrow) PackageVersionAttributeHandler( 370 fPackageInfoValue, fPackageInfoValue.version, true); 371 if (*_handler == NULL) 372 return B_NO_MEMORY; 373 } 374 break; 375 376 case B_HPKG_ATTRIBUTE_ID_PACKAGE_COPYRIGHT: 377 fPackageInfoValue.SetTo(B_PACKAGE_INFO_COPYRIGHTS, 378 value.string); 379 break; 380 381 case B_HPKG_ATTRIBUTE_ID_PACKAGE_LICENSE: 382 fPackageInfoValue.SetTo(B_PACKAGE_INFO_LICENSES, 383 value.string); 384 break; 385 386 case B_HPKG_ATTRIBUTE_ID_PACKAGE_URL: 387 fPackageInfoValue.SetTo(B_PACKAGE_INFO_URLS, value.string); 388 break; 389 390 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SOURCE_URL: 391 fPackageInfoValue.SetTo(B_PACKAGE_INFO_SOURCE_URLS, value.string); 392 break; 393 394 case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES: 395 fPackageInfoValue.resolvable.name = value.string; 396 fPackageInfoValue.attributeID = B_PACKAGE_INFO_PROVIDES; 397 if (_handler != NULL) { 398 *_handler 399 = new(std::nothrow) PackageResolvableAttributeHandler( 400 fPackageInfoValue); 401 if (*_handler == NULL) 402 return B_NO_MEMORY; 403 } 404 break; 405 406 case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES: 407 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS: 408 case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS: 409 case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS: 410 fPackageInfoValue.resolvableExpression.name = value.string; 411 switch (id) { 412 case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES: 413 fPackageInfoValue.attributeID = B_PACKAGE_INFO_REQUIRES; 414 break; 415 416 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS: 417 fPackageInfoValue.attributeID 418 = B_PACKAGE_INFO_SUPPLEMENTS; 419 break; 420 421 case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS: 422 fPackageInfoValue.attributeID 423 = B_PACKAGE_INFO_CONFLICTS; 424 break; 425 426 case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS: 427 fPackageInfoValue.attributeID = B_PACKAGE_INFO_FRESHENS; 428 break; 429 } 430 if (_handler != NULL) { 431 *_handler = new(std::nothrow) 432 PackageResolvableExpressionAttributeHandler( 433 fPackageInfoValue); 434 if (*_handler == NULL) 435 return B_NO_MEMORY; 436 } 437 break; 438 439 case B_HPKG_ATTRIBUTE_ID_PACKAGE_REPLACES: 440 fPackageInfoValue.SetTo(B_PACKAGE_INFO_REPLACES, value.string); 441 break; 442 443 case B_HPKG_ATTRIBUTE_ID_PACKAGE_CHECKSUM: 444 fPackageInfoValue.SetTo(B_PACKAGE_INFO_CHECKSUM, value.string); 445 break; 446 447 case B_HPKG_ATTRIBUTE_ID_PACKAGE_INSTALL_PATH: 448 fPackageInfoValue.SetTo(B_PACKAGE_INFO_INSTALL_PATH, value.string); 449 break; 450 451 default: 452 context->errorOutput->PrintError( 453 "Error: Invalid package attribute section: unexpected " 454 "package attribute id %d encountered\n", id); 455 return B_BAD_DATA; 456 } 457 458 // notify unless the current attribute has children, in which case 459 // the child-handler will notify when it's done 460 if (_handler == NULL) { 461 status_t error = context->packageContentHandler 462 ->HandlePackageAttribute(fPackageInfoValue); 463 fPackageInfoValue.Clear(); 464 if (error != B_OK) 465 return error; 466 } 467 468 return B_OK; 469 } 470 471 472 // #pragma mark - LowLevelAttributeHandler 473 474 475 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler() 476 : 477 fParentToken(NULL), 478 fToken(NULL), 479 fID(B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) 480 { 481 } 482 483 484 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler(uint8 id, 485 const BPackageAttributeValue& value, void* parentToken, void* token) 486 : 487 fParentToken(NULL), 488 fToken(token), 489 fID(id), 490 fValue(value) 491 { 492 } 493 494 495 status_t 496 ReaderImplBase::LowLevelAttributeHandler::HandleAttribute( 497 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 498 AttributeHandler** _handler) 499 { 500 // notify the content handler 501 void* token; 502 status_t error = context->lowLevelHandler->HandleAttribute( 503 (BHPKGAttributeID)id, value, fToken, token); 504 if (error != B_OK) 505 return error; 506 507 // create a subhandler for the attribute, if it has children 508 if (_handler != NULL) { 509 *_handler = new(std::nothrow) LowLevelAttributeHandler(id, value, 510 fToken, token); 511 if (*_handler == NULL) { 512 context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id, 513 value, fToken, token); 514 return B_NO_MEMORY; 515 } 516 return B_OK; 517 } 518 519 // no children -- just call the done hook 520 return context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id, 521 value, fToken, token); 522 } 523 524 525 status_t 526 ReaderImplBase::LowLevelAttributeHandler::Delete( 527 AttributeHandlerContext* context) 528 { 529 status_t error = B_OK; 530 if (fID != B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) { 531 error = context->lowLevelHandler->HandleAttributeDone( 532 (BHPKGAttributeID)fID, fValue, fParentToken, fToken); 533 } 534 535 delete this; 536 return error; 537 } 538 539 540 // #pragma mark - ReaderImplBase 541 542 543 ReaderImplBase::ReaderImplBase(BErrorOutput* errorOutput) 544 : 545 fPackageAttributesSection("package attributes"), 546 fErrorOutput(errorOutput), 547 fFD(-1), 548 fOwnsFD(false), 549 fCurrentSection(NULL), 550 fScratchBuffer(NULL), 551 fScratchBufferSize(0) 552 { 553 } 554 555 556 ReaderImplBase::~ReaderImplBase() 557 { 558 if (fOwnsFD && fFD >= 0) 559 close(fFD); 560 561 delete[] fScratchBuffer; 562 } 563 564 565 status_t 566 ReaderImplBase::Init(int fd, bool keepFD) 567 { 568 fFD = fd; 569 fOwnsFD = keepFD; 570 571 // allocate a scratch buffer 572 fScratchBuffer = new(std::nothrow) uint8[kScratchBufferSize]; 573 if (fScratchBuffer == NULL) { 574 fErrorOutput->PrintError("Error: Out of memory!\n"); 575 return B_NO_MEMORY; 576 } 577 fScratchBufferSize = kScratchBufferSize; 578 579 return B_OK; 580 } 581 582 583 const char* 584 ReaderImplBase::CheckCompression(const SectionInfo& section) const 585 { 586 switch (section.compression) { 587 case B_HPKG_COMPRESSION_NONE: 588 if (section.compressedLength != section.uncompressedLength) { 589 return "Uncompressed, but compressed and uncompressed length " 590 "don't match"; 591 } 592 return NULL; 593 594 case B_HPKG_COMPRESSION_ZLIB: 595 if (section.compressedLength >= section.uncompressedLength) { 596 return "Compressed, but compressed length is not less than " 597 "uncompressed length"; 598 } 599 return NULL; 600 601 default: 602 return "Invalid compression algorithm ID"; 603 } 604 } 605 606 607 status_t 608 ReaderImplBase::ParseStrings() 609 { 610 // allocate table, if there are any strings 611 if (fCurrentSection->stringsCount == 0) { 612 fCurrentSection->currentOffset += fCurrentSection->stringsLength; 613 return B_OK; 614 } 615 616 fCurrentSection->strings 617 = new(std::nothrow) char*[fCurrentSection->stringsCount]; 618 if (fCurrentSection->strings == NULL) { 619 fErrorOutput->PrintError("Error: Out of memory!\n"); 620 return B_NO_MEMORY; 621 } 622 623 // parse the section and fill the table 624 char* position 625 = (char*)fCurrentSection->data + fCurrentSection->currentOffset; 626 char* sectionEnd = position + fCurrentSection->stringsLength; 627 uint32 index = 0; 628 while (true) { 629 if (position >= sectionEnd) { 630 fErrorOutput->PrintError("Error: Malformed %s strings section\n", 631 fCurrentSection->name); 632 return B_BAD_DATA; 633 } 634 635 size_t stringLength = strnlen(position, (char*)sectionEnd - position); 636 637 if (stringLength == 0) { 638 if (position + 1 != sectionEnd) { 639 fErrorOutput->PrintError( 640 "Error: %ld excess bytes in %s strings section\n", 641 sectionEnd - (position + 1), fCurrentSection->name); 642 return B_BAD_DATA; 643 } 644 645 if (index != fCurrentSection->stringsCount) { 646 fErrorOutput->PrintError("Error: Invalid %s strings section: " 647 "Less strings (%lld) than specified in the header (%lld)\n", 648 fCurrentSection->name, index, 649 fCurrentSection->stringsCount); 650 return B_BAD_DATA; 651 } 652 653 fCurrentSection->currentOffset += fCurrentSection->stringsLength; 654 655 return B_OK; 656 } 657 658 if (index >= fCurrentSection->stringsCount) { 659 fErrorOutput->PrintError("Error: Invalid %s strings section: " 660 "More strings (%lld) than specified in the header (%lld)\n", 661 fCurrentSection->name, index, fCurrentSection->stringsCount); 662 return B_BAD_DATA; 663 } 664 665 fCurrentSection->strings[index++] = position; 666 position += stringLength + 1; 667 } 668 } 669 670 671 status_t 672 ReaderImplBase::ParsePackageAttributesSection( 673 AttributeHandlerContext* context, AttributeHandler* rootAttributeHandler) 674 { 675 // parse package attributes 676 SetCurrentSection(&fPackageAttributesSection); 677 678 // init the attribute handler stack 679 rootAttributeHandler->SetLevel(0); 680 ClearAttributeHandlerStack(); 681 PushAttributeHandler(rootAttributeHandler); 682 683 bool sectionHandled; 684 status_t error = ParseAttributeTree(context, sectionHandled); 685 if (error == B_OK && sectionHandled) { 686 if (fPackageAttributesSection.currentOffset 687 < fPackageAttributesSection.uncompressedLength) { 688 fErrorOutput->PrintError("Error: %llu excess byte(s) in package " 689 "attributes section\n", 690 fPackageAttributesSection.uncompressedLength 691 - fPackageAttributesSection.currentOffset); 692 error = B_BAD_DATA; 693 } 694 } 695 696 SetCurrentSection(NULL); 697 698 // clean up on error 699 if (error != B_OK) { 700 context->ErrorOccurred(); 701 while (AttributeHandler* handler = PopAttributeHandler()) { 702 if (handler != rootAttributeHandler) 703 handler->Delete(context); 704 } 705 return error; 706 } 707 708 return B_OK; 709 } 710 711 712 status_t 713 ReaderImplBase::ParseAttributeTree(AttributeHandlerContext* context, 714 bool& _sectionHandled) 715 { 716 if (context->hasLowLevelHandler) { 717 bool handleSection = false; 718 status_t error = context->lowLevelHandler->HandleSectionStart( 719 context->section, handleSection); 720 if (error != B_OK) 721 return error; 722 723 if (!handleSection) { 724 _sectionHandled = false; 725 return B_OK; 726 } 727 } 728 729 status_t error = _ParseAttributeTree(context); 730 731 if (context->hasLowLevelHandler) { 732 status_t endError = context->lowLevelHandler->HandleSectionEnd( 733 context->section); 734 if (error == B_OK) 735 error = endError; 736 } 737 738 _sectionHandled = true; 739 return error; 740 } 741 742 743 status_t 744 ReaderImplBase::_ParseAttributeTree(AttributeHandlerContext* context) 745 { 746 int level = 0; 747 748 while (true) { 749 uint8 id; 750 AttributeValue value; 751 bool hasChildren; 752 uint64 tag; 753 754 status_t error = _ReadAttribute(id, value, &hasChildren, &tag); 755 if (error != B_OK) 756 return error; 757 758 if (tag == 0) { 759 AttributeHandler* handler = PopAttributeHandler(); 760 if (level-- == 0) 761 return B_OK; 762 763 error = handler->Delete(context); 764 if (error != B_OK) 765 return error; 766 767 continue; 768 } 769 770 AttributeHandler* childHandler = NULL; 771 error = CurrentAttributeHandler()->HandleAttribute(context, id, value, 772 hasChildren ? &childHandler : NULL); 773 if (error != B_OK) 774 return error; 775 776 // parse children 777 if (hasChildren) { 778 // create an ignore handler, if necessary 779 if (childHandler == NULL) { 780 childHandler = new(std::nothrow) IgnoreAttributeHandler; 781 if (childHandler == NULL) { 782 fErrorOutput->PrintError("Error: Out of memory!\n"); 783 return B_NO_MEMORY; 784 } 785 } 786 787 childHandler->SetLevel(++level); 788 PushAttributeHandler(childHandler); 789 } 790 } 791 } 792 793 794 status_t 795 ReaderImplBase::_ReadAttribute(uint8& _id, AttributeValue& _value, 796 bool* _hasChildren, uint64* _tag) 797 { 798 uint64 tag; 799 status_t error = ReadUnsignedLEB128(tag); 800 if (error != B_OK) 801 return error; 802 803 if (tag != 0) { 804 // get the type 805 uint16 type = attribute_tag_type(tag); 806 if (type >= B_HPKG_ATTRIBUTE_TYPE_ENUM_COUNT) { 807 fErrorOutput->PrintError("Error: Invalid %s section: attribute " 808 "type %d not supported!\n", fCurrentSection->name, type); 809 return B_BAD_DATA; 810 } 811 812 // get the value 813 error = ReadAttributeValue(type, attribute_tag_encoding(tag), 814 _value); 815 if (error != B_OK) 816 return error; 817 818 _id = attribute_tag_id(tag); 819 if (_id >= B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) { 820 fErrorOutput->PrintError("Error: Invalid %s section: " 821 "attribute id %d not supported!\n", fCurrentSection->name, _id); 822 return B_BAD_DATA; 823 } 824 } 825 826 if (_hasChildren != NULL) 827 *_hasChildren = attribute_tag_has_children(tag); 828 if (_tag != NULL) 829 *_tag = tag; 830 831 return B_OK; 832 } 833 834 835 status_t 836 ReaderImplBase::ReadAttributeValue(uint8 type, uint8 encoding, 837 AttributeValue& _value) 838 { 839 switch (type) { 840 case B_HPKG_ATTRIBUTE_TYPE_INT: 841 case B_HPKG_ATTRIBUTE_TYPE_UINT: 842 { 843 uint64 intValue; 844 status_t error; 845 846 switch (encoding) { 847 case B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT: 848 { 849 uint8 value; 850 error = _Read(value); 851 intValue = value; 852 break; 853 } 854 case B_HPKG_ATTRIBUTE_ENCODING_INT_16_BIT: 855 { 856 uint16 value; 857 error = _Read(value); 858 intValue = B_BENDIAN_TO_HOST_INT16(value); 859 break; 860 } 861 case B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT: 862 { 863 uint32 value; 864 error = _Read(value); 865 intValue = B_BENDIAN_TO_HOST_INT32(value); 866 break; 867 } 868 case B_HPKG_ATTRIBUTE_ENCODING_INT_64_BIT: 869 { 870 uint64 value; 871 error = _Read(value); 872 intValue = B_BENDIAN_TO_HOST_INT64(value); 873 break; 874 } 875 default: 876 { 877 fErrorOutput->PrintError("Error: Invalid %s section: " 878 "invalid encoding %d for int value type %d\n", 879 fCurrentSection->name, encoding, type); 880 return B_BAD_VALUE; 881 } 882 } 883 884 if (error != B_OK) 885 return error; 886 887 if (type == B_HPKG_ATTRIBUTE_TYPE_INT) 888 _value.SetTo((int64)intValue); 889 else 890 _value.SetTo(intValue); 891 892 return B_OK; 893 } 894 895 case B_HPKG_ATTRIBUTE_TYPE_STRING: 896 { 897 if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE) { 898 uint64 index; 899 status_t error = ReadUnsignedLEB128(index); 900 if (error != B_OK) 901 return error; 902 903 if (index > fCurrentSection->stringsCount) { 904 fErrorOutput->PrintError("Error: Invalid %s section: " 905 "string reference (%lld) out of bounds (%lld)\n", 906 fCurrentSection->name, index, 907 fCurrentSection->stringsCount); 908 return B_BAD_DATA; 909 } 910 911 _value.SetTo(fCurrentSection->strings[index]); 912 } else if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE) { 913 const char* string; 914 status_t error = _ReadString(string); 915 if (error != B_OK) 916 return error; 917 918 _value.SetTo(string); 919 } else { 920 fErrorOutput->PrintError("Error: Invalid %s section: invalid " 921 "string encoding (%u)\n", fCurrentSection->name, encoding); 922 return B_BAD_DATA; 923 } 924 925 return B_OK; 926 } 927 928 default: 929 fErrorOutput->PrintError("Error: Invalid %s section: invalid " 930 "value type: %d\n", fCurrentSection->name, type); 931 return B_BAD_DATA; 932 } 933 } 934 935 936 status_t 937 ReaderImplBase::ReadUnsignedLEB128(uint64& _value) 938 { 939 uint64 result = 0; 940 int shift = 0; 941 while (true) { 942 uint8 byte; 943 status_t error = _Read(byte); 944 if (error != B_OK) 945 return error; 946 947 result |= uint64(byte & 0x7f) << shift; 948 if ((byte & 0x80) == 0) 949 break; 950 shift += 7; 951 } 952 953 _value = result; 954 return B_OK; 955 } 956 957 958 status_t 959 ReaderImplBase::_ReadString(const char*& _string, size_t* _stringLength) 960 { 961 const char* string 962 = (const char*)fCurrentSection->data + fCurrentSection->currentOffset; 963 size_t stringLength = strnlen(string, 964 fCurrentSection->uncompressedLength - fCurrentSection->currentOffset); 965 966 if (stringLength 967 == fCurrentSection->uncompressedLength 968 - fCurrentSection->currentOffset) { 969 fErrorOutput->PrintError( 970 "_ReadString(): string extends beyond %s end\n", 971 fCurrentSection->name); 972 return B_BAD_DATA; 973 } 974 975 _string = string; 976 if (_stringLength != NULL) 977 *_stringLength = stringLength; 978 979 fCurrentSection->currentOffset += stringLength + 1; 980 return B_OK; 981 } 982 983 984 status_t 985 ReaderImplBase::_ReadSectionBuffer(void* buffer, size_t size) 986 { 987 if (size > fCurrentSection->uncompressedLength 988 - fCurrentSection->currentOffset) { 989 fErrorOutput->PrintError("_ReadBuffer(%lu): read beyond %s end\n", 990 size, fCurrentSection->name); 991 return B_BAD_DATA; 992 } 993 994 memcpy(buffer, fCurrentSection->data + fCurrentSection->currentOffset, 995 size); 996 fCurrentSection->currentOffset += size; 997 return B_OK; 998 } 999 1000 1001 status_t 1002 ReaderImplBase::ReadBuffer(off_t offset, void* buffer, size_t size) 1003 { 1004 ssize_t bytesRead = pread(fFD, buffer, size, offset); 1005 if (bytesRead < 0) { 1006 fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read data: " 1007 "%s\n", buffer, size, strerror(errno)); 1008 return errno; 1009 } 1010 if ((size_t)bytesRead != size) { 1011 fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read all " 1012 "data\n", buffer, size); 1013 return B_ERROR; 1014 } 1015 1016 return B_OK; 1017 } 1018 1019 1020 status_t 1021 ReaderImplBase::ReadCompressedBuffer(const SectionInfo& section) 1022 { 1023 uint32 compressedSize = section.compressedLength; 1024 uint64 offset = section.offset; 1025 1026 switch (section.compression) { 1027 case B_HPKG_COMPRESSION_NONE: 1028 return ReadBuffer(offset, section.data, compressedSize); 1029 1030 case B_HPKG_COMPRESSION_ZLIB: 1031 { 1032 // create the decompression stream 1033 BMemoryIO bufferOutput(section.data, section.uncompressedLength); 1034 BZlibCompressionAlgorithm algorithm; 1035 BDataIO* zlibOutput; 1036 status_t error = algorithm.CreateDecompressingOutputStream( 1037 &bufferOutput, NULL, zlibOutput); 1038 if (error != B_OK) 1039 return error; 1040 1041 ObjectDeleter<BDataIO> zlibOutputDeleter(zlibOutput); 1042 1043 while (compressedSize > 0) { 1044 // read compressed buffer 1045 size_t toRead = std::min((size_t)compressedSize, 1046 fScratchBufferSize); 1047 error = ReadBuffer(offset, fScratchBuffer, toRead); 1048 if (error != B_OK) 1049 return error; 1050 1051 // uncompress 1052 error = zlibOutput->WriteExactly(fScratchBuffer, toRead); 1053 if (error != B_OK) 1054 return error; 1055 1056 compressedSize -= toRead; 1057 offset += toRead; 1058 } 1059 1060 error = zlibOutput->Flush(); 1061 if (error != B_OK) 1062 return error; 1063 1064 // verify that all data have been read 1065 if ((uint64)bufferOutput.Position() != section.uncompressedLength) { 1066 fErrorOutput->PrintError("Error: Missing bytes in uncompressed " 1067 "buffer!\n"); 1068 return B_BAD_DATA; 1069 } 1070 1071 return B_OK; 1072 } 1073 1074 default: 1075 { 1076 fErrorOutput->PrintError("Error: Invalid compression type: %u\n", 1077 section.compression); 1078 return B_BAD_DATA; 1079 } 1080 } 1081 } 1082 1083 1084 } // namespace BPrivate 1085 1086 } // namespace V1 1087 1088 } // namespace BHPKG 1089 1090 } // namespace BPackageKit 1091