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