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