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