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