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