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/PackageFileHeapReader.h> 25 #include <package/hpkg/ZlibDecompressor.h> 26 27 28 namespace BPackageKit { 29 30 namespace BHPKG { 31 32 namespace BPrivate { 33 34 35 static const size_t kScratchBufferSize = 64 * 1024; 36 37 38 // #pragma mark - AttributeHandlerContext 39 40 41 ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext( 42 BErrorOutput* errorOutput, BPackageContentHandler* packageContentHandler, 43 BHPKGPackageSectionID section) 44 : 45 errorOutput(errorOutput), 46 packageContentHandler(packageContentHandler), 47 hasLowLevelHandler(false), 48 section(section) 49 { 50 } 51 52 53 ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext( 54 BErrorOutput* errorOutput, BLowLevelPackageContentHandler* lowLevelHandler, 55 BHPKGPackageSectionID section) 56 : 57 errorOutput(errorOutput), 58 lowLevelHandler(lowLevelHandler), 59 hasLowLevelHandler(true), 60 section(section) 61 { 62 } 63 64 65 void 66 ReaderImplBase::AttributeHandlerContext::ErrorOccurred() 67 { 68 if (hasLowLevelHandler) 69 lowLevelHandler->HandleErrorOccurred(); 70 else 71 packageContentHandler->HandleErrorOccurred(); 72 } 73 74 75 // #pragma mark - AttributeHandler 76 77 78 ReaderImplBase::AttributeHandler::~AttributeHandler() 79 { 80 } 81 82 83 void 84 ReaderImplBase::AttributeHandler::SetLevel(int level) 85 { 86 fLevel = level; 87 } 88 89 90 status_t 91 ReaderImplBase::AttributeHandler::HandleAttribute( 92 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 93 AttributeHandler** _handler) 94 { 95 return B_OK; 96 } 97 98 99 status_t 100 ReaderImplBase::AttributeHandler::Delete(AttributeHandlerContext* context) 101 { 102 delete this; 103 return B_OK; 104 } 105 106 107 // #pragma mark - PackageVersionAttributeHandler 108 109 110 ReaderImplBase::PackageVersionAttributeHandler::PackageVersionAttributeHandler( 111 BPackageInfoAttributeValue& packageInfoValue, 112 BPackageVersionData& versionData, bool notify) 113 : 114 fPackageInfoValue(packageInfoValue), 115 fPackageVersionData(versionData), 116 fNotify(notify) 117 { 118 } 119 120 121 status_t 122 ReaderImplBase::PackageVersionAttributeHandler::HandleAttribute( 123 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 124 AttributeHandler** _handler) 125 { 126 switch (id) { 127 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MINOR: 128 fPackageVersionData.minor = value.string; 129 break; 130 131 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MICRO: 132 fPackageVersionData.micro = value.string; 133 break; 134 135 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_PRE_RELEASE: 136 fPackageVersionData.preRelease = value.string; 137 break; 138 139 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_REVISION: 140 fPackageVersionData.revision = value.unsignedInt; 141 break; 142 143 default: 144 context->errorOutput->PrintError("Error: Invalid package " 145 "attribute section: unexpected package attribute id %d " 146 "encountered when parsing package version\n", id); 147 return B_BAD_DATA; 148 } 149 150 return B_OK; 151 } 152 153 154 status_t 155 ReaderImplBase::PackageVersionAttributeHandler::Delete( 156 AttributeHandlerContext* context) 157 { 158 status_t error = B_OK; 159 if (fNotify) { 160 fPackageInfoValue.attributeID = B_PACKAGE_INFO_VERSION; 161 error = context->packageContentHandler->HandlePackageAttribute( 162 fPackageInfoValue); 163 fPackageInfoValue.Clear(); 164 } 165 166 delete this; 167 return error; 168 } 169 170 171 // #pragma mark - PackageResolvableAttributeHandler 172 173 174 ReaderImplBase::PackageResolvableAttributeHandler 175 ::PackageResolvableAttributeHandler( 176 BPackageInfoAttributeValue& packageInfoValue) 177 : 178 fPackageInfoValue(packageInfoValue) 179 { 180 } 181 182 183 status_t 184 ReaderImplBase::PackageResolvableAttributeHandler::HandleAttribute( 185 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 186 AttributeHandler** _handler) 187 { 188 switch (id) { 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_BASE_PACKAGE: 340 fPackageInfoValue.SetTo(B_PACKAGE_INFO_BASE_PACKAGE, value.string); 341 break; 342 343 case B_HPKG_ATTRIBUTE_ID_PACKAGE_FLAGS: 344 fPackageInfoValue.SetTo(B_PACKAGE_INFO_FLAGS, 345 (uint32)value.unsignedInt); 346 break; 347 348 case B_HPKG_ATTRIBUTE_ID_PACKAGE_ARCHITECTURE: 349 if (value.unsignedInt 350 >= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) { 351 context->errorOutput->PrintError( 352 "Error: Invalid package attribute section: " 353 "Invalid package architecture %lld encountered\n", 354 value.unsignedInt); 355 return B_BAD_DATA; 356 } 357 fPackageInfoValue.SetTo(B_PACKAGE_INFO_ARCHITECTURE, 358 (uint8)value.unsignedInt); 359 break; 360 361 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR: 362 fPackageInfoValue.attributeID = B_PACKAGE_INFO_VERSION; 363 fPackageInfoValue.version.major = value.string; 364 if (_handler != NULL) { 365 *_handler 366 = new(std::nothrow) PackageVersionAttributeHandler( 367 fPackageInfoValue, fPackageInfoValue.version, true); 368 if (*_handler == NULL) 369 return B_NO_MEMORY; 370 } 371 break; 372 373 case B_HPKG_ATTRIBUTE_ID_PACKAGE_COPYRIGHT: 374 fPackageInfoValue.SetTo(B_PACKAGE_INFO_COPYRIGHTS, 375 value.string); 376 break; 377 378 case B_HPKG_ATTRIBUTE_ID_PACKAGE_LICENSE: 379 fPackageInfoValue.SetTo(B_PACKAGE_INFO_LICENSES, 380 value.string); 381 break; 382 383 case B_HPKG_ATTRIBUTE_ID_PACKAGE_URL: 384 fPackageInfoValue.SetTo(B_PACKAGE_INFO_URLS, value.string); 385 break; 386 387 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SOURCE_URL: 388 fPackageInfoValue.SetTo(B_PACKAGE_INFO_SOURCE_URLS, value.string); 389 break; 390 391 case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES: 392 fPackageInfoValue.resolvable.name = value.string; 393 fPackageInfoValue.attributeID = B_PACKAGE_INFO_PROVIDES; 394 if (_handler != NULL) { 395 *_handler 396 = new(std::nothrow) PackageResolvableAttributeHandler( 397 fPackageInfoValue); 398 if (*_handler == NULL) 399 return B_NO_MEMORY; 400 } 401 break; 402 403 case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES: 404 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS: 405 case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS: 406 case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS: 407 fPackageInfoValue.resolvableExpression.name = value.string; 408 switch (id) { 409 case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES: 410 fPackageInfoValue.attributeID = B_PACKAGE_INFO_REQUIRES; 411 break; 412 413 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS: 414 fPackageInfoValue.attributeID 415 = B_PACKAGE_INFO_SUPPLEMENTS; 416 break; 417 418 case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS: 419 fPackageInfoValue.attributeID 420 = B_PACKAGE_INFO_CONFLICTS; 421 break; 422 423 case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS: 424 fPackageInfoValue.attributeID = B_PACKAGE_INFO_FRESHENS; 425 break; 426 } 427 if (_handler != NULL) { 428 *_handler = new(std::nothrow) 429 PackageResolvableExpressionAttributeHandler( 430 fPackageInfoValue); 431 if (*_handler == NULL) 432 return B_NO_MEMORY; 433 } 434 break; 435 436 case B_HPKG_ATTRIBUTE_ID_PACKAGE_REPLACES: 437 fPackageInfoValue.SetTo(B_PACKAGE_INFO_REPLACES, value.string); 438 break; 439 440 case B_HPKG_ATTRIBUTE_ID_PACKAGE_CHECKSUM: 441 fPackageInfoValue.SetTo(B_PACKAGE_INFO_CHECKSUM, value.string); 442 break; 443 444 case B_HPKG_ATTRIBUTE_ID_PACKAGE_INSTALL_PATH: 445 fPackageInfoValue.SetTo(B_PACKAGE_INFO_INSTALL_PATH, value.string); 446 break; 447 448 default: 449 context->errorOutput->PrintError( 450 "Error: Invalid package attribute section: unexpected " 451 "package attribute id %d encountered\n", id); 452 return B_BAD_DATA; 453 } 454 455 // notify unless the current attribute has children, in which case 456 // the child-handler will notify when it's done 457 if (_handler == NULL) { 458 status_t error = context->packageContentHandler 459 ->HandlePackageAttribute(fPackageInfoValue); 460 fPackageInfoValue.Clear(); 461 if (error != B_OK) 462 return error; 463 } 464 465 return B_OK; 466 } 467 468 469 // #pragma mark - LowLevelAttributeHandler 470 471 472 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler() 473 : 474 fParentToken(NULL), 475 fToken(NULL), 476 fID(B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) 477 { 478 } 479 480 481 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler(uint8 id, 482 const BPackageAttributeValue& value, void* parentToken, void* token) 483 : 484 fParentToken(NULL), 485 fToken(token), 486 fID(id), 487 fValue(value) 488 { 489 } 490 491 492 status_t 493 ReaderImplBase::LowLevelAttributeHandler::HandleAttribute( 494 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 495 AttributeHandler** _handler) 496 { 497 // notify the content handler 498 void* token; 499 status_t error = context->lowLevelHandler->HandleAttribute( 500 (BHPKGAttributeID)id, value, fToken, token); 501 if (error != B_OK) 502 return error; 503 504 // create a subhandler for the attribute, if it has children 505 if (_handler != NULL) { 506 *_handler = new(std::nothrow) LowLevelAttributeHandler(id, value, 507 fToken, token); 508 if (*_handler == NULL) { 509 context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id, 510 value, fToken, token); 511 return B_NO_MEMORY; 512 } 513 return B_OK; 514 } 515 516 // no children -- just call the done hook 517 return context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id, 518 value, fToken, token); 519 } 520 521 522 status_t 523 ReaderImplBase::LowLevelAttributeHandler::Delete( 524 AttributeHandlerContext* context) 525 { 526 status_t error = B_OK; 527 if (fID != B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) { 528 error = context->lowLevelHandler->HandleAttributeDone( 529 (BHPKGAttributeID)fID, fValue, fParentToken, fToken); 530 } 531 532 delete this; 533 return error; 534 } 535 536 537 // #pragma mark - ReaderImplBase 538 539 540 ReaderImplBase::ReaderImplBase(const char* fileType, BErrorOutput* errorOutput) 541 : 542 fPackageAttributesSection("package attributes"), 543 fFileType(fileType), 544 fErrorOutput(errorOutput), 545 fFD(-1), 546 fOwnsFD(false), 547 fHeapReader(NULL), 548 fCurrentSection(NULL), 549 fScratchBuffer(NULL), 550 fScratchBufferSize(0) 551 { 552 } 553 554 555 ReaderImplBase::~ReaderImplBase() 556 { 557 delete fHeapReader; 558 559 if (fOwnsFD && fFD >= 0) 560 close(fFD); 561 562 delete[] fScratchBuffer; 563 } 564 565 566 status_t 567 ReaderImplBase::_Init(int fd, bool keepFD) 568 { 569 fFD = fd; 570 fOwnsFD = keepFD; 571 572 // allocate a scratch buffer 573 fScratchBuffer = new(std::nothrow) uint8[kScratchBufferSize]; 574 if (fScratchBuffer == NULL) { 575 fErrorOutput->PrintError("Error: Out of memory!\n"); 576 return B_NO_MEMORY; 577 } 578 fScratchBufferSize = kScratchBufferSize; 579 580 return B_OK; 581 } 582 583 584 status_t 585 ReaderImplBase::InitHeapReader(uint32 compression, uint32 chunkSize, 586 off_t offset, uint64 compressedSize, uint64 uncompressedSize) 587 { 588 if (compression != B_HPKG_COMPRESSION_ZLIB) { 589 fErrorOutput->PrintError("Error: Invalid heap compression\n"); 590 return B_BAD_DATA; 591 } 592 593 fHeapReader = new(std::nothrow) PackageFileHeapReader(fErrorOutput, fFD, 594 offset, compressedSize, uncompressedSize); 595 return fHeapReader->Init(); 596 } 597 598 599 status_t 600 ReaderImplBase::InitSection(PackageFileSection& section, uint64 endOffset, 601 uint64 length, uint64 maxSaneLength, uint64 stringsLength, 602 uint64 stringsCount) 603 { 604 // check length vs. endOffset 605 if (length > endOffset) { 606 ErrorOutput()->PrintError("Error: %s file %s section size is %" 607 B_PRIu64 " bytes. This is greater than the available space\n", 608 fFileType, section.name, length); 609 return B_BAD_DATA; 610 } 611 612 // check sanity length 613 if (maxSaneLength > 0 && length > maxSaneLength) { 614 ErrorOutput()->PrintError("Error: %s file %s section size is %" 615 B_PRIu64 " bytes. This is beyond the reader's sanity limit\n", 616 fFileType, section.name, length); 617 return B_NOT_SUPPORTED; 618 } 619 620 // check strings subsection size/count 621 if ((stringsLength == 0) != (stringsCount == 0) || stringsLength > length) { 622 ErrorOutput()->PrintError("Error: strings subsection description of %s " 623 "file %s section is invalid (%" B_PRIu64 " strings, length: %" 624 B_PRIu64 ")\n", 625 fFileType, section.name, length, stringsCount, stringsLength); 626 return B_BAD_DATA; 627 } 628 629 section.uncompressedLength = length; 630 section.offset = endOffset - length; 631 section.currentOffset = 0; 632 section.stringsLength = stringsLength; 633 section.stringsCount = stringsCount; 634 635 return B_OK; 636 } 637 638 639 status_t 640 ReaderImplBase::PrepareSection(PackageFileSection& section) 641 { 642 // allocate memory for the section data and read it in 643 section.data = new(std::nothrow) uint8[section.uncompressedLength]; 644 if (section.data == NULL) { 645 ErrorOutput()->PrintError("Error: Out of memory!\n"); 646 return B_NO_MEMORY; 647 } 648 649 status_t error = ReadSection(section); 650 if (error != B_OK) 651 return error; 652 653 // parse the section strings 654 section.currentOffset = 0; 655 SetCurrentSection(§ion); 656 657 error = ParseStrings(); 658 if (error != B_OK) 659 return error; 660 661 return B_OK; 662 } 663 664 665 status_t 666 ReaderImplBase::ParseStrings() 667 { 668 // allocate table, if there are any strings 669 if (fCurrentSection->stringsCount == 0) { 670 fCurrentSection->currentOffset += fCurrentSection->stringsLength; 671 return B_OK; 672 } 673 674 fCurrentSection->strings 675 = new(std::nothrow) char*[fCurrentSection->stringsCount]; 676 if (fCurrentSection->strings == NULL) { 677 fErrorOutput->PrintError("Error: Out of memory!\n"); 678 return B_NO_MEMORY; 679 } 680 681 // parse the section and fill the table 682 char* position 683 = (char*)fCurrentSection->data + fCurrentSection->currentOffset; 684 char* sectionEnd = position + fCurrentSection->stringsLength; 685 uint32 index = 0; 686 while (true) { 687 if (position >= sectionEnd) { 688 fErrorOutput->PrintError("Error: Malformed %s strings section\n", 689 fCurrentSection->name); 690 return B_BAD_DATA; 691 } 692 693 size_t stringLength = strnlen(position, (char*)sectionEnd - position); 694 695 if (stringLength == 0) { 696 if (position + 1 != sectionEnd) { 697 fErrorOutput->PrintError( 698 "Error: %ld excess bytes in %s strings section\n", 699 sectionEnd - (position + 1), fCurrentSection->name); 700 return B_BAD_DATA; 701 } 702 703 if (index != fCurrentSection->stringsCount) { 704 fErrorOutput->PrintError("Error: Invalid %s strings section: " 705 "Less strings (%lld) than specified in the header (%lld)\n", 706 fCurrentSection->name, index, 707 fCurrentSection->stringsCount); 708 return B_BAD_DATA; 709 } 710 711 fCurrentSection->currentOffset += fCurrentSection->stringsLength; 712 713 return B_OK; 714 } 715 716 if (index >= fCurrentSection->stringsCount) { 717 fErrorOutput->PrintError("Error: Invalid %s strings section: " 718 "More strings (%lld) than specified in the header (%lld)\n", 719 fCurrentSection->name, index, fCurrentSection->stringsCount); 720 return B_BAD_DATA; 721 } 722 723 fCurrentSection->strings[index++] = position; 724 position += stringLength + 1; 725 } 726 } 727 728 729 status_t 730 ReaderImplBase::ParsePackageAttributesSection( 731 AttributeHandlerContext* context, AttributeHandler* rootAttributeHandler) 732 { 733 // parse package attributes 734 SetCurrentSection(&fPackageAttributesSection); 735 736 // init the attribute handler stack 737 rootAttributeHandler->SetLevel(0); 738 ClearAttributeHandlerStack(); 739 PushAttributeHandler(rootAttributeHandler); 740 741 bool sectionHandled; 742 status_t error = ParseAttributeTree(context, sectionHandled); 743 if (error == B_OK && sectionHandled) { 744 if (fPackageAttributesSection.currentOffset 745 < fPackageAttributesSection.uncompressedLength) { 746 fErrorOutput->PrintError("Error: %llu excess byte(s) in package " 747 "attributes section\n", 748 fPackageAttributesSection.uncompressedLength 749 - fPackageAttributesSection.currentOffset); 750 error = B_BAD_DATA; 751 } 752 } 753 754 SetCurrentSection(NULL); 755 756 // clean up on error 757 if (error != B_OK) { 758 context->ErrorOccurred(); 759 while (AttributeHandler* handler = PopAttributeHandler()) { 760 if (handler != rootAttributeHandler) 761 handler->Delete(context); 762 } 763 return error; 764 } 765 766 return B_OK; 767 } 768 769 770 status_t 771 ReaderImplBase::ParseAttributeTree(AttributeHandlerContext* context, 772 bool& _sectionHandled) 773 { 774 if (context->hasLowLevelHandler) { 775 bool handleSection = false; 776 status_t error = context->lowLevelHandler->HandleSectionStart( 777 context->section, handleSection); 778 if (error != B_OK) 779 return error; 780 781 if (!handleSection) { 782 _sectionHandled = false; 783 return B_OK; 784 } 785 } 786 787 status_t error = _ParseAttributeTree(context); 788 789 if (context->hasLowLevelHandler) { 790 status_t endError = context->lowLevelHandler->HandleSectionEnd( 791 context->section); 792 if (error == B_OK) 793 error = endError; 794 } 795 796 _sectionHandled = true; 797 return error; 798 } 799 800 801 status_t 802 ReaderImplBase::_ParseAttributeTree(AttributeHandlerContext* context) 803 { 804 int level = 0; 805 806 while (true) { 807 uint8 id; 808 AttributeValue value; 809 bool hasChildren; 810 uint64 tag; 811 812 status_t error = _ReadAttribute(id, value, &hasChildren, &tag); 813 if (error != B_OK) 814 return error; 815 816 if (tag == 0) { 817 AttributeHandler* handler = PopAttributeHandler(); 818 if (level-- == 0) 819 return B_OK; 820 821 error = handler->Delete(context); 822 if (error != B_OK) 823 return error; 824 825 continue; 826 } 827 828 AttributeHandler* childHandler = NULL; 829 error = CurrentAttributeHandler()->HandleAttribute(context, id, value, 830 hasChildren ? &childHandler : NULL); 831 if (error != B_OK) 832 return error; 833 834 // parse children 835 if (hasChildren) { 836 // create an ignore handler, if necessary 837 if (childHandler == NULL) { 838 childHandler = new(std::nothrow) IgnoreAttributeHandler; 839 if (childHandler == NULL) { 840 fErrorOutput->PrintError("Error: Out of memory!\n"); 841 return B_NO_MEMORY; 842 } 843 } 844 845 childHandler->SetLevel(++level); 846 PushAttributeHandler(childHandler); 847 } 848 } 849 } 850 851 852 status_t 853 ReaderImplBase::_ReadAttribute(uint8& _id, AttributeValue& _value, 854 bool* _hasChildren, uint64* _tag) 855 { 856 uint64 tag; 857 status_t error = ReadUnsignedLEB128(tag); 858 if (error != B_OK) 859 return error; 860 861 if (tag != 0) { 862 // get the type 863 uint16 type = attribute_tag_type(tag); 864 if (type >= B_HPKG_ATTRIBUTE_TYPE_ENUM_COUNT) { 865 fErrorOutput->PrintError("Error: Invalid %s section: attribute " 866 "type %d not supported!\n", fCurrentSection->name, type); 867 return B_BAD_DATA; 868 } 869 870 // get the value 871 error = ReadAttributeValue(type, attribute_tag_encoding(tag), 872 _value); 873 if (error != B_OK) 874 return error; 875 876 _id = attribute_tag_id(tag); 877 if (_id >= B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) { 878 fErrorOutput->PrintError("Error: Invalid %s section: " 879 "attribute id %d not supported!\n", fCurrentSection->name, _id); 880 return B_BAD_DATA; 881 } 882 } 883 884 if (_hasChildren != NULL) 885 *_hasChildren = attribute_tag_has_children(tag); 886 if (_tag != NULL) 887 *_tag = tag; 888 889 return B_OK; 890 } 891 892 893 status_t 894 ReaderImplBase::ReadAttributeValue(uint8 type, uint8 encoding, 895 AttributeValue& _value) 896 { 897 switch (type) { 898 case B_HPKG_ATTRIBUTE_TYPE_INT: 899 case B_HPKG_ATTRIBUTE_TYPE_UINT: 900 { 901 uint64 intValue; 902 status_t error; 903 904 switch (encoding) { 905 case B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT: 906 { 907 uint8 value; 908 error = _Read(value); 909 intValue = value; 910 break; 911 } 912 case B_HPKG_ATTRIBUTE_ENCODING_INT_16_BIT: 913 { 914 uint16 value; 915 error = _Read(value); 916 intValue = B_BENDIAN_TO_HOST_INT16(value); 917 break; 918 } 919 case B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT: 920 { 921 uint32 value; 922 error = _Read(value); 923 intValue = B_BENDIAN_TO_HOST_INT32(value); 924 break; 925 } 926 case B_HPKG_ATTRIBUTE_ENCODING_INT_64_BIT: 927 { 928 uint64 value; 929 error = _Read(value); 930 intValue = B_BENDIAN_TO_HOST_INT64(value); 931 break; 932 } 933 default: 934 { 935 fErrorOutput->PrintError("Error: Invalid %s section: " 936 "invalid encoding %d for int value type %d\n", 937 fCurrentSection->name, encoding, type); 938 return B_BAD_VALUE; 939 } 940 } 941 942 if (error != B_OK) 943 return error; 944 945 if (type == B_HPKG_ATTRIBUTE_TYPE_INT) 946 _value.SetTo((int64)intValue); 947 else 948 _value.SetTo(intValue); 949 950 return B_OK; 951 } 952 953 case B_HPKG_ATTRIBUTE_TYPE_STRING: 954 { 955 if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE) { 956 uint64 index; 957 status_t error = ReadUnsignedLEB128(index); 958 if (error != B_OK) 959 return error; 960 961 if (index > fCurrentSection->stringsCount) { 962 fErrorOutput->PrintError("Error: Invalid %s section: " 963 "string reference (%lld) out of bounds (%lld)\n", 964 fCurrentSection->name, index, 965 fCurrentSection->stringsCount); 966 return B_BAD_DATA; 967 } 968 969 _value.SetTo(fCurrentSection->strings[index]); 970 } else if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE) { 971 const char* string; 972 status_t error = _ReadString(string); 973 if (error != B_OK) 974 return error; 975 976 _value.SetTo(string); 977 } else { 978 fErrorOutput->PrintError("Error: Invalid %s section: invalid " 979 "string encoding (%u)\n", fCurrentSection->name, encoding); 980 return B_BAD_DATA; 981 } 982 983 return B_OK; 984 } 985 986 default: 987 fErrorOutput->PrintError("Error: Invalid %s section: invalid " 988 "value type: %d\n", fCurrentSection->name, type); 989 return B_BAD_DATA; 990 } 991 } 992 993 994 status_t 995 ReaderImplBase::ReadUnsignedLEB128(uint64& _value) 996 { 997 uint64 result = 0; 998 int shift = 0; 999 while (true) { 1000 uint8 byte; 1001 status_t error = _Read(byte); 1002 if (error != B_OK) 1003 return error; 1004 1005 result |= uint64(byte & 0x7f) << shift; 1006 if ((byte & 0x80) == 0) 1007 break; 1008 shift += 7; 1009 } 1010 1011 _value = result; 1012 return B_OK; 1013 } 1014 1015 1016 status_t 1017 ReaderImplBase::_ReadString(const char*& _string, size_t* _stringLength) 1018 { 1019 const char* string 1020 = (const char*)fCurrentSection->data + fCurrentSection->currentOffset; 1021 size_t stringLength = strnlen(string, 1022 fCurrentSection->uncompressedLength - fCurrentSection->currentOffset); 1023 1024 if (stringLength 1025 == fCurrentSection->uncompressedLength 1026 - fCurrentSection->currentOffset) { 1027 fErrorOutput->PrintError( 1028 "_ReadString(): string extends beyond %s end\n", 1029 fCurrentSection->name); 1030 return B_BAD_DATA; 1031 } 1032 1033 _string = string; 1034 if (_stringLength != NULL) 1035 *_stringLength = stringLength; 1036 1037 fCurrentSection->currentOffset += stringLength + 1; 1038 return B_OK; 1039 } 1040 1041 1042 status_t 1043 ReaderImplBase::_ReadSectionBuffer(void* buffer, size_t size) 1044 { 1045 if (size > fCurrentSection->uncompressedLength 1046 - fCurrentSection->currentOffset) { 1047 fErrorOutput->PrintError( 1048 "_ReadSectionBuffer(%lu): read beyond %s end\n", size, 1049 fCurrentSection->name); 1050 return B_BAD_DATA; 1051 } 1052 1053 memcpy(buffer, fCurrentSection->data + fCurrentSection->currentOffset, 1054 size); 1055 fCurrentSection->currentOffset += size; 1056 return B_OK; 1057 } 1058 1059 1060 status_t 1061 ReaderImplBase::ReadBuffer(off_t offset, void* buffer, size_t size) 1062 { 1063 ssize_t bytesRead = pread(fFD, buffer, size, offset); 1064 if (bytesRead < 0) { 1065 fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read data: " 1066 "%s\n", buffer, size, strerror(errno)); 1067 return errno; 1068 } 1069 if ((size_t)bytesRead != size) { 1070 fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read all " 1071 "data\n", buffer, size); 1072 return B_ERROR; 1073 } 1074 1075 return B_OK; 1076 } 1077 1078 1079 status_t 1080 ReaderImplBase::ReadSection(const PackageFileSection& section) 1081 { 1082 BBufferDataOutput output(section.data, section.uncompressedLength); 1083 return fHeapReader->ReadDataToOutput(section.offset, 1084 section.uncompressedLength, &output); 1085 } 1086 1087 1088 } // namespace BPrivate 1089 1090 } // namespace BHPKG 1091 1092 } // namespace BPackageKit 1093