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