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_PROVIDES: 380 fPackageInfoValue.resolvable.name = value.string; 381 fPackageInfoValue.attributeID = B_PACKAGE_INFO_PROVIDES; 382 if (_handler != NULL) { 383 *_handler 384 = new(std::nothrow) PackageResolvableAttributeHandler( 385 fPackageInfoValue); 386 if (*_handler == NULL) 387 return B_NO_MEMORY; 388 } 389 break; 390 391 case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES: 392 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS: 393 case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS: 394 case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS: 395 fPackageInfoValue.resolvableExpression.name = value.string; 396 switch (id) { 397 case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES: 398 fPackageInfoValue.attributeID = B_PACKAGE_INFO_REQUIRES; 399 break; 400 401 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS: 402 fPackageInfoValue.attributeID 403 = B_PACKAGE_INFO_SUPPLEMENTS; 404 break; 405 406 case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS: 407 fPackageInfoValue.attributeID 408 = B_PACKAGE_INFO_CONFLICTS; 409 break; 410 411 case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS: 412 fPackageInfoValue.attributeID = B_PACKAGE_INFO_FRESHENS; 413 break; 414 } 415 if (_handler != NULL) { 416 *_handler = new(std::nothrow) 417 PackageResolvableExpressionAttributeHandler( 418 fPackageInfoValue); 419 if (*_handler == NULL) 420 return B_NO_MEMORY; 421 } 422 break; 423 424 case B_HPKG_ATTRIBUTE_ID_PACKAGE_REPLACES: 425 fPackageInfoValue.SetTo(B_PACKAGE_INFO_REPLACES, value.string); 426 break; 427 428 case B_HPKG_ATTRIBUTE_ID_PACKAGE_CHECKSUM: 429 fPackageInfoValue.SetTo(B_PACKAGE_INFO_CHECKSUM, value.string); 430 break; 431 432 default: 433 context->errorOutput->PrintError( 434 "Error: Invalid package attribute section: unexpected " 435 "package attribute id %d encountered\n", id); 436 return B_BAD_DATA; 437 } 438 439 // notify unless the current attribute has children, in which case 440 // the child-handler will notify when it's done 441 if (_handler == NULL) { 442 status_t error = context->packageContentHandler 443 ->HandlePackageAttribute(fPackageInfoValue); 444 fPackageInfoValue.Clear(); 445 if (error != B_OK) 446 return error; 447 } 448 449 return B_OK; 450 } 451 452 453 // #pragma mark - LowLevelAttributeHandler 454 455 456 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler() 457 : 458 fToken(NULL), 459 fID(B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) 460 { 461 } 462 463 464 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler(uint8 id, 465 const BPackageAttributeValue& value, void* token) 466 : 467 fToken(token), 468 fID(id), 469 fValue(value) 470 { 471 } 472 473 474 status_t 475 ReaderImplBase::LowLevelAttributeHandler::HandleAttribute( 476 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 477 AttributeHandler** _handler) 478 { 479 // notify the content handler 480 void* token; 481 status_t error = context->lowLevelHandler->HandleAttribute( 482 (BHPKGAttributeID)id, value, fToken, token); 483 if (error != B_OK) 484 return error; 485 486 // create a subhandler for the attribute, if it has children 487 if (_handler != NULL) { 488 *_handler = new(std::nothrow) LowLevelAttributeHandler(id, value, 489 token); 490 if (*_handler == NULL) { 491 context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id, 492 value, token); 493 return B_NO_MEMORY; 494 } 495 return B_OK; 496 } 497 498 // no children -- just call the done hook 499 return context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id, 500 value, token); 501 } 502 503 504 status_t 505 ReaderImplBase::LowLevelAttributeHandler::Delete( 506 AttributeHandlerContext* context) 507 { 508 status_t error = B_OK; 509 if (fID != B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) { 510 error = context->lowLevelHandler->HandleAttributeDone( 511 (BHPKGAttributeID)fID, fValue, fToken); 512 } 513 514 delete this; 515 return error; 516 } 517 518 519 // #pragma mark - ReaderImplBase 520 521 522 ReaderImplBase::ReaderImplBase(BErrorOutput* errorOutput) 523 : 524 fPackageAttributesSection("package attributes"), 525 fErrorOutput(errorOutput), 526 fFD(-1), 527 fOwnsFD(false), 528 fCurrentSection(NULL), 529 fScratchBuffer(NULL), 530 fScratchBufferSize(0) 531 { 532 } 533 534 535 ReaderImplBase::~ReaderImplBase() 536 { 537 if (fOwnsFD && fFD >= 0) 538 close(fFD); 539 540 delete[] fScratchBuffer; 541 } 542 543 544 status_t 545 ReaderImplBase::Init(int fd, bool keepFD) 546 { 547 fFD = fd; 548 fOwnsFD = keepFD; 549 550 // allocate a scratch buffer 551 fScratchBuffer = new(std::nothrow) uint8[kScratchBufferSize]; 552 if (fScratchBuffer == NULL) { 553 fErrorOutput->PrintError("Error: Out of memory!\n"); 554 return B_NO_MEMORY; 555 } 556 fScratchBufferSize = kScratchBufferSize; 557 558 return B_OK; 559 } 560 561 562 const char* 563 ReaderImplBase::CheckCompression(const SectionInfo& section) const 564 { 565 switch (section.compression) { 566 case B_HPKG_COMPRESSION_NONE: 567 if (section.compressedLength != section.uncompressedLength) { 568 return "Uncompressed, but compressed and uncompressed length " 569 "don't match"; 570 } 571 return NULL; 572 573 case B_HPKG_COMPRESSION_ZLIB: 574 if (section.compressedLength >= section.uncompressedLength) { 575 return "Compressed, but compressed length is not less than " 576 "uncompressed length"; 577 } 578 return NULL; 579 580 default: 581 return "Invalid compression algorithm ID"; 582 } 583 } 584 585 586 status_t 587 ReaderImplBase::ParseStrings() 588 { 589 // allocate table, if there are any strings 590 if (fCurrentSection->stringsCount == 0) { 591 fCurrentSection->currentOffset += fCurrentSection->stringsLength; 592 return B_OK; 593 } 594 595 fCurrentSection->strings 596 = new(std::nothrow) char*[fCurrentSection->stringsCount]; 597 if (fCurrentSection->strings == NULL) { 598 fErrorOutput->PrintError("Error: Out of memory!\n"); 599 return B_NO_MEMORY; 600 } 601 602 // parse the section and fill the table 603 char* position 604 = (char*)fCurrentSection->data + fCurrentSection->currentOffset; 605 char* sectionEnd = position + fCurrentSection->stringsLength; 606 uint32 index = 0; 607 while (true) { 608 if (position >= sectionEnd) { 609 fErrorOutput->PrintError("Error: Malformed %s strings section\n", 610 fCurrentSection->name); 611 return B_BAD_DATA; 612 } 613 614 size_t stringLength = strnlen(position, (char*)sectionEnd - position); 615 616 if (stringLength == 0) { 617 if (position + 1 != sectionEnd) { 618 fErrorOutput->PrintError( 619 "Error: %ld excess bytes in %s strings section\n", 620 sectionEnd - (position + 1), fCurrentSection->name); 621 return B_BAD_DATA; 622 } 623 624 if (index != fCurrentSection->stringsCount) { 625 fErrorOutput->PrintError("Error: Invalid %s strings section: " 626 "Less strings (%lld) than specified in the header (%lld)\n", 627 fCurrentSection->name, index, 628 fCurrentSection->stringsCount); 629 return B_BAD_DATA; 630 } 631 632 fCurrentSection->currentOffset += fCurrentSection->stringsLength; 633 634 return B_OK; 635 } 636 637 if (index >= fCurrentSection->stringsCount) { 638 fErrorOutput->PrintError("Error: Invalid %s strings section: " 639 "More strings (%lld) than specified in the header (%lld)\n", 640 fCurrentSection->name, index, fCurrentSection->stringsCount); 641 return B_BAD_DATA; 642 } 643 644 fCurrentSection->strings[index++] = position; 645 position += stringLength + 1; 646 } 647 } 648 649 650 status_t 651 ReaderImplBase::ParsePackageAttributesSection( 652 AttributeHandlerContext* context, AttributeHandler* rootAttributeHandler) 653 { 654 // parse package attributes 655 SetCurrentSection(&fPackageAttributesSection); 656 657 // init the attribute handler stack 658 rootAttributeHandler->SetLevel(0); 659 ClearAttributeHandlerStack(); 660 PushAttributeHandler(rootAttributeHandler); 661 662 status_t error = ParseAttributeTree(context); 663 if (error == B_OK) { 664 if (fPackageAttributesSection.currentOffset 665 < fPackageAttributesSection.uncompressedLength) { 666 fErrorOutput->PrintError("Error: %llu excess byte(s) in package " 667 "attributes section\n", 668 fPackageAttributesSection.uncompressedLength 669 - fPackageAttributesSection.currentOffset); 670 error = B_BAD_DATA; 671 } 672 } 673 674 SetCurrentSection(NULL); 675 676 // clean up on error 677 if (error != B_OK) { 678 context->ErrorOccurred(); 679 while (AttributeHandler* handler = PopAttributeHandler()) { 680 if (handler != rootAttributeHandler) 681 handler->Delete(context); 682 } 683 return error; 684 } 685 686 return B_OK; 687 } 688 689 690 status_t 691 ReaderImplBase::ParseAttributeTree(AttributeHandlerContext* context) 692 { 693 int level = 0; 694 695 while (true) { 696 uint8 id; 697 AttributeValue value; 698 bool hasChildren; 699 uint64 tag; 700 701 status_t error = _ReadAttribute(id, value, &hasChildren, &tag); 702 if (error != B_OK) 703 return error; 704 705 if (tag == 0) { 706 AttributeHandler* handler = PopAttributeHandler(); 707 if (level-- == 0) 708 return B_OK; 709 710 error = handler->Delete(context); 711 if (error != B_OK) 712 return error; 713 714 continue; 715 } 716 717 AttributeHandler* childHandler = NULL; 718 error = CurrentAttributeHandler()->HandleAttribute(context, id, value, 719 hasChildren ? &childHandler : NULL); 720 if (error != B_OK) 721 return error; 722 723 // parse children 724 if (hasChildren) { 725 // create an ignore handler, if necessary 726 if (childHandler == NULL) { 727 childHandler = new(std::nothrow) IgnoreAttributeHandler; 728 if (childHandler == NULL) { 729 fErrorOutput->PrintError("Error: Out of memory!\n"); 730 return B_NO_MEMORY; 731 } 732 } 733 734 childHandler->SetLevel(++level); 735 PushAttributeHandler(childHandler); 736 } 737 } 738 } 739 740 741 status_t 742 ReaderImplBase::_ReadAttribute(uint8& _id, AttributeValue& _value, 743 bool* _hasChildren, uint64* _tag) 744 { 745 uint64 tag; 746 status_t error = ReadUnsignedLEB128(tag); 747 if (error != B_OK) 748 return error; 749 750 if (tag != 0) { 751 // get the type 752 uint16 type = HPKG_ATTRIBUTE_TAG_TYPE(tag); 753 if (type >= B_HPKG_ATTRIBUTE_TYPE_ENUM_COUNT) { 754 fErrorOutput->PrintError("Error: Invalid %s section: attribute " 755 "type %d not supported!\n", fCurrentSection->name, type); 756 return B_BAD_DATA; 757 } 758 759 // get the value 760 error = ReadAttributeValue(type, HPKG_ATTRIBUTE_TAG_ENCODING(tag), 761 _value); 762 if (error != B_OK) 763 return error; 764 765 _id = HPKG_ATTRIBUTE_TAG_ID(tag); 766 if (_id >= B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) { 767 fErrorOutput->PrintError("Error: Invalid %s section: " 768 "attribute id %d not supported!\n", fCurrentSection->name, _id); 769 return B_BAD_DATA; 770 } 771 } 772 773 if (_hasChildren != NULL) 774 *_hasChildren = HPKG_ATTRIBUTE_TAG_HAS_CHILDREN(tag); 775 if (_tag != NULL) 776 *_tag = tag; 777 778 return B_OK; 779 } 780 781 782 status_t 783 ReaderImplBase::ReadAttributeValue(uint8 type, uint8 encoding, 784 AttributeValue& _value) 785 { 786 switch (type) { 787 case B_HPKG_ATTRIBUTE_TYPE_INT: 788 case B_HPKG_ATTRIBUTE_TYPE_UINT: 789 { 790 uint64 intValue; 791 status_t error; 792 793 switch (encoding) { 794 case B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT: 795 { 796 uint8 value; 797 error = _Read(value); 798 intValue = value; 799 break; 800 } 801 case B_HPKG_ATTRIBUTE_ENCODING_INT_16_BIT: 802 { 803 uint16 value; 804 error = _Read(value); 805 intValue = B_BENDIAN_TO_HOST_INT16(value); 806 break; 807 } 808 case B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT: 809 { 810 uint32 value; 811 error = _Read(value); 812 intValue = B_BENDIAN_TO_HOST_INT32(value); 813 break; 814 } 815 case B_HPKG_ATTRIBUTE_ENCODING_INT_64_BIT: 816 { 817 uint64 value; 818 error = _Read(value); 819 intValue = B_BENDIAN_TO_HOST_INT64(value); 820 break; 821 } 822 default: 823 { 824 fErrorOutput->PrintError("Error: Invalid %s section: " 825 "invalid encoding %d for int value type %d\n", 826 fCurrentSection->name, encoding, type); 827 return B_BAD_VALUE; 828 } 829 } 830 831 if (error != B_OK) 832 return error; 833 834 if (type == B_HPKG_ATTRIBUTE_TYPE_INT) 835 _value.SetTo((int64)intValue); 836 else 837 _value.SetTo(intValue); 838 839 return B_OK; 840 } 841 842 case B_HPKG_ATTRIBUTE_TYPE_STRING: 843 { 844 if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE) { 845 uint64 index; 846 status_t error = ReadUnsignedLEB128(index); 847 if (error != B_OK) 848 return error; 849 850 if (index > fCurrentSection->stringsCount) { 851 fErrorOutput->PrintError("Error: Invalid %s section: " 852 "string reference (%lld) out of bounds (%lld)\n", 853 fCurrentSection->name, index, 854 fCurrentSection->stringsCount); 855 return B_BAD_DATA; 856 } 857 858 _value.SetTo(fCurrentSection->strings[index]); 859 } else if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE) { 860 const char* string; 861 status_t error = _ReadString(string); 862 if (error != B_OK) 863 return error; 864 865 _value.SetTo(string); 866 } else { 867 fErrorOutput->PrintError("Error: Invalid %s section: invalid " 868 "string encoding (%u)\n", fCurrentSection->name, encoding); 869 return B_BAD_DATA; 870 } 871 872 return B_OK; 873 } 874 875 default: 876 fErrorOutput->PrintError("Error: Invalid %s section: invalid " 877 "value type: %d\n", fCurrentSection->name, type); 878 return B_BAD_DATA; 879 } 880 } 881 882 883 status_t 884 ReaderImplBase::ReadUnsignedLEB128(uint64& _value) 885 { 886 uint64 result = 0; 887 int shift = 0; 888 while (true) { 889 uint8 byte; 890 status_t error = _Read(byte); 891 if (error != B_OK) 892 return error; 893 894 result |= uint64(byte & 0x7f) << shift; 895 if ((byte & 0x80) == 0) 896 break; 897 shift += 7; 898 } 899 900 _value = result; 901 return B_OK; 902 } 903 904 905 status_t 906 ReaderImplBase::_ReadString(const char*& _string, size_t* _stringLength) 907 { 908 const char* string 909 = (const char*)fCurrentSection->data + fCurrentSection->currentOffset; 910 size_t stringLength = strnlen(string, 911 fCurrentSection->uncompressedLength - fCurrentSection->currentOffset); 912 913 if (stringLength 914 == fCurrentSection->uncompressedLength 915 - fCurrentSection->currentOffset) { 916 fErrorOutput->PrintError( 917 "_ReadString(): string extends beyond %s end\n", 918 fCurrentSection->name); 919 return B_BAD_DATA; 920 } 921 922 _string = string; 923 if (_stringLength != NULL) 924 *_stringLength = stringLength; 925 926 fCurrentSection->currentOffset += stringLength + 1; 927 return B_OK; 928 } 929 930 931 status_t 932 ReaderImplBase::_ReadSectionBuffer(void* buffer, size_t size) 933 { 934 if (size > fCurrentSection->uncompressedLength 935 - fCurrentSection->currentOffset) { 936 fErrorOutput->PrintError("_ReadBuffer(%lu): read beyond %s end\n", 937 size, fCurrentSection->name); 938 return B_BAD_DATA; 939 } 940 941 memcpy(buffer, fCurrentSection->data + fCurrentSection->currentOffset, 942 size); 943 fCurrentSection->currentOffset += size; 944 return B_OK; 945 } 946 947 948 status_t 949 ReaderImplBase::ReadBuffer(off_t offset, void* buffer, size_t size) 950 { 951 ssize_t bytesRead = pread(fFD, buffer, size, offset); 952 if (bytesRead < 0) { 953 fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read data: " 954 "%s\n", buffer, size, strerror(errno)); 955 return errno; 956 } 957 if ((size_t)bytesRead != size) { 958 fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read all " 959 "data\n", buffer, size); 960 return B_ERROR; 961 } 962 963 return B_OK; 964 } 965 966 967 status_t 968 ReaderImplBase::ReadCompressedBuffer(const SectionInfo& section) 969 { 970 uint32 compressedSize = section.compressedLength; 971 uint64 offset = section.offset; 972 973 switch (section.compression) { 974 case B_HPKG_COMPRESSION_NONE: 975 return ReadBuffer(offset, section.data, compressedSize); 976 977 case B_HPKG_COMPRESSION_ZLIB: 978 { 979 // init the decompressor 980 BBufferDataOutput bufferOutput(section.data, 981 section.uncompressedLength); 982 ZlibDecompressor decompressor(&bufferOutput); 983 status_t error = decompressor.Init(); 984 if (error != B_OK) 985 return error; 986 987 while (compressedSize > 0) { 988 // read compressed buffer 989 size_t toRead = std::min((size_t)compressedSize, 990 fScratchBufferSize); 991 error = ReadBuffer(offset, fScratchBuffer, toRead); 992 if (error != B_OK) 993 return error; 994 995 // uncompress 996 error = decompressor.DecompressNext(fScratchBuffer, toRead); 997 if (error != B_OK) 998 return error; 999 1000 compressedSize -= toRead; 1001 offset += toRead; 1002 } 1003 1004 error = decompressor.Finish(); 1005 if (error != B_OK) 1006 return error; 1007 1008 // verify that all data have been read 1009 if (bufferOutput.BytesWritten() != section.uncompressedLength) { 1010 fErrorOutput->PrintError("Error: Missing bytes in uncompressed " 1011 "buffer!\n"); 1012 return B_BAD_DATA; 1013 } 1014 1015 return B_OK; 1016 } 1017 1018 default: 1019 return B_BAD_DATA; 1020 } 1021 } 1022 1023 1024 } // namespace BPrivate 1025 1026 } // namespace BHPKG 1027 1028 } // namespace BPackageKit 1029