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