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 fRawHeapReader(NULL), 547 fHeapReader(NULL), 548 fCurrentSection(NULL), 549 fScratchBuffer(NULL), 550 fScratchBufferSize(0) 551 { 552 } 553 554 555 ReaderImplBase::~ReaderImplBase() 556 { 557 delete fHeapReader; 558 if (fRawHeapReader != fHeapReader) 559 delete fRawHeapReader; 560 561 if (fOwnsFD && fFD >= 0) 562 close(fFD); 563 564 delete[] fScratchBuffer; 565 } 566 567 568 uint64 569 ReaderImplBase::UncompressedHeapSize() const 570 { 571 return fRawHeapReader->UncompressedHeapSize(); 572 } 573 574 575 BAbstractBufferedDataReader* 576 ReaderImplBase::DetachHeapReader(PackageFileHeapReader** _rawHeapReader) 577 { 578 BAbstractBufferedDataReader* heapReader = fHeapReader; 579 fHeapReader = NULL; 580 581 if (_rawHeapReader != NULL) 582 *_rawHeapReader = fRawHeapReader; 583 fRawHeapReader = NULL; 584 585 return heapReader; 586 } 587 588 589 status_t 590 ReaderImplBase::InitHeapReader(uint32 compression, uint32 chunkSize, 591 off_t offset, uint64 compressedSize, uint64 uncompressedSize) 592 { 593 if (compression != B_HPKG_COMPRESSION_ZLIB) { 594 fErrorOutput->PrintError("Error: Invalid heap compression\n"); 595 return B_BAD_DATA; 596 } 597 598 fRawHeapReader = new(std::nothrow) PackageFileHeapReader(fErrorOutput, fFD, 599 offset, compressedSize, uncompressedSize); 600 if (fRawHeapReader == NULL) 601 return B_NO_MEMORY; 602 603 status_t error = fRawHeapReader->Init(); 604 if (error != B_OK) 605 return error; 606 607 error = CreateCachedHeapReader(fRawHeapReader, fHeapReader); 608 if (error != B_OK) { 609 if (error != B_NOT_SUPPORTED) 610 return error; 611 612 fHeapReader = fRawHeapReader; 613 } 614 615 return B_OK; 616 } 617 618 619 status_t 620 ReaderImplBase::CreateCachedHeapReader(PackageFileHeapReader* heapReader, 621 BAbstractBufferedDataReader*& _cachedReader) 622 { 623 return B_NOT_SUPPORTED; 624 } 625 626 627 status_t 628 ReaderImplBase::InitSection(PackageFileSection& section, uint64 endOffset, 629 uint64 length, uint64 maxSaneLength, uint64 stringsLength, 630 uint64 stringsCount) 631 { 632 // check length vs. endOffset 633 if (length > endOffset) { 634 ErrorOutput()->PrintError("Error: %s file %s section size is %" 635 B_PRIu64 " bytes. This is greater than the available space\n", 636 fFileType, section.name, length); 637 return B_BAD_DATA; 638 } 639 640 // check sanity length 641 if (maxSaneLength > 0 && length > maxSaneLength) { 642 ErrorOutput()->PrintError("Error: %s file %s section size is %" 643 B_PRIu64 " bytes. This is beyond the reader's sanity limit\n", 644 fFileType, section.name, length); 645 return B_NOT_SUPPORTED; 646 } 647 648 // check strings subsection size/count 649 if ((stringsLength <= 1) != (stringsCount == 0) || stringsLength > length) { 650 ErrorOutput()->PrintError("Error: strings subsection description of %s " 651 "file %s section is invalid (%" B_PRIu64 " strings, length: %" 652 B_PRIu64 ", section length: %" B_PRIu64 ")\n", 653 fFileType, section.name, stringsCount, stringsLength, length); 654 return B_BAD_DATA; 655 } 656 657 section.uncompressedLength = length; 658 section.offset = endOffset - length; 659 section.currentOffset = 0; 660 section.stringsLength = stringsLength; 661 section.stringsCount = stringsCount; 662 663 return B_OK; 664 } 665 666 667 status_t 668 ReaderImplBase::PrepareSection(PackageFileSection& section) 669 { 670 // allocate memory for the section data and read it in 671 section.data = new(std::nothrow) uint8[section.uncompressedLength]; 672 if (section.data == NULL) { 673 ErrorOutput()->PrintError("Error: Out of memory!\n"); 674 return B_NO_MEMORY; 675 } 676 677 status_t error = ReadSection(section); 678 if (error != B_OK) 679 return error; 680 681 // parse the section strings 682 section.currentOffset = 0; 683 SetCurrentSection(§ion); 684 685 error = ParseStrings(); 686 if (error != B_OK) 687 return error; 688 689 return B_OK; 690 } 691 692 693 status_t 694 ReaderImplBase::ParseStrings() 695 { 696 // allocate table, if there are any strings 697 if (fCurrentSection->stringsCount == 0) { 698 fCurrentSection->currentOffset += fCurrentSection->stringsLength; 699 return B_OK; 700 } 701 702 fCurrentSection->strings 703 = new(std::nothrow) char*[fCurrentSection->stringsCount]; 704 if (fCurrentSection->strings == NULL) { 705 fErrorOutput->PrintError("Error: Out of memory!\n"); 706 return B_NO_MEMORY; 707 } 708 709 // parse the section and fill the table 710 char* position 711 = (char*)fCurrentSection->data + fCurrentSection->currentOffset; 712 char* sectionEnd = position + fCurrentSection->stringsLength; 713 uint32 index = 0; 714 while (true) { 715 if (position >= sectionEnd) { 716 fErrorOutput->PrintError("Error: Malformed %s strings section\n", 717 fCurrentSection->name); 718 return B_BAD_DATA; 719 } 720 721 size_t stringLength = strnlen(position, (char*)sectionEnd - position); 722 723 if (stringLength == 0) { 724 if (position + 1 != sectionEnd) { 725 fErrorOutput->PrintError( 726 "Error: %ld excess bytes in %s strings section\n", 727 sectionEnd - (position + 1), fCurrentSection->name); 728 return B_BAD_DATA; 729 } 730 731 if (index != fCurrentSection->stringsCount) { 732 fErrorOutput->PrintError("Error: Invalid %s strings section: " 733 "Less strings (%lld) than specified in the header (%lld)\n", 734 fCurrentSection->name, index, 735 fCurrentSection->stringsCount); 736 return B_BAD_DATA; 737 } 738 739 fCurrentSection->currentOffset += fCurrentSection->stringsLength; 740 741 return B_OK; 742 } 743 744 if (index >= fCurrentSection->stringsCount) { 745 fErrorOutput->PrintError("Error: Invalid %s strings section: " 746 "More strings (%lld) than specified in the header (%lld)\n", 747 fCurrentSection->name, index, fCurrentSection->stringsCount); 748 return B_BAD_DATA; 749 } 750 751 fCurrentSection->strings[index++] = position; 752 position += stringLength + 1; 753 } 754 } 755 756 757 status_t 758 ReaderImplBase::ParsePackageAttributesSection( 759 AttributeHandlerContext* context, AttributeHandler* rootAttributeHandler) 760 { 761 // parse package attributes 762 SetCurrentSection(&fPackageAttributesSection); 763 764 // init the attribute handler stack 765 rootAttributeHandler->SetLevel(0); 766 ClearAttributeHandlerStack(); 767 PushAttributeHandler(rootAttributeHandler); 768 769 bool sectionHandled; 770 status_t error = ParseAttributeTree(context, sectionHandled); 771 if (error == B_OK && sectionHandled) { 772 if (fPackageAttributesSection.currentOffset 773 < fPackageAttributesSection.uncompressedLength) { 774 fErrorOutput->PrintError("Error: %llu excess byte(s) in package " 775 "attributes section\n", 776 fPackageAttributesSection.uncompressedLength 777 - fPackageAttributesSection.currentOffset); 778 error = B_BAD_DATA; 779 } 780 } 781 782 SetCurrentSection(NULL); 783 784 // clean up on error 785 if (error != B_OK) { 786 context->ErrorOccurred(); 787 while (AttributeHandler* handler = PopAttributeHandler()) { 788 if (handler != rootAttributeHandler) 789 handler->Delete(context); 790 } 791 return error; 792 } 793 794 return B_OK; 795 } 796 797 798 status_t 799 ReaderImplBase::ParseAttributeTree(AttributeHandlerContext* context, 800 bool& _sectionHandled) 801 { 802 if (context->hasLowLevelHandler) { 803 bool handleSection = false; 804 status_t error = context->lowLevelHandler->HandleSectionStart( 805 context->section, handleSection); 806 if (error != B_OK) 807 return error; 808 809 if (!handleSection) { 810 _sectionHandled = false; 811 return B_OK; 812 } 813 } 814 815 status_t error = _ParseAttributeTree(context); 816 817 if (context->hasLowLevelHandler) { 818 status_t endError = context->lowLevelHandler->HandleSectionEnd( 819 context->section); 820 if (error == B_OK) 821 error = endError; 822 } 823 824 _sectionHandled = true; 825 return error; 826 } 827 828 829 status_t 830 ReaderImplBase::_Init(int fd, bool keepFD) 831 { 832 fFD = fd; 833 fOwnsFD = keepFD; 834 835 // allocate a scratch buffer 836 fScratchBuffer = new(std::nothrow) uint8[kScratchBufferSize]; 837 if (fScratchBuffer == NULL) { 838 fErrorOutput->PrintError("Error: Out of memory!\n"); 839 return B_NO_MEMORY; 840 } 841 fScratchBufferSize = kScratchBufferSize; 842 843 return B_OK; 844 } 845 846 847 status_t 848 ReaderImplBase::_ParseAttributeTree(AttributeHandlerContext* context) 849 { 850 int level = 0; 851 852 while (true) { 853 uint8 id; 854 AttributeValue value; 855 bool hasChildren; 856 uint64 tag; 857 858 status_t error = _ReadAttribute(id, value, &hasChildren, &tag); 859 if (error != B_OK) 860 return error; 861 862 if (tag == 0) { 863 AttributeHandler* handler = PopAttributeHandler(); 864 if (level-- == 0) 865 return B_OK; 866 867 error = handler->Delete(context); 868 if (error != B_OK) 869 return error; 870 871 continue; 872 } 873 874 AttributeHandler* childHandler = NULL; 875 error = CurrentAttributeHandler()->HandleAttribute(context, id, value, 876 hasChildren ? &childHandler : NULL); 877 if (error != B_OK) 878 return error; 879 880 // parse children 881 if (hasChildren) { 882 // create an ignore handler, if necessary 883 if (childHandler == NULL) { 884 childHandler = new(std::nothrow) IgnoreAttributeHandler; 885 if (childHandler == NULL) { 886 fErrorOutput->PrintError("Error: Out of memory!\n"); 887 return B_NO_MEMORY; 888 } 889 } 890 891 childHandler->SetLevel(++level); 892 PushAttributeHandler(childHandler); 893 } 894 } 895 } 896 897 898 status_t 899 ReaderImplBase::_ReadAttribute(uint8& _id, AttributeValue& _value, 900 bool* _hasChildren, uint64* _tag) 901 { 902 uint64 tag; 903 status_t error = ReadUnsignedLEB128(tag); 904 if (error != B_OK) 905 return error; 906 907 if (tag != 0) { 908 // get the type 909 uint16 type = attribute_tag_type(tag); 910 if (type >= B_HPKG_ATTRIBUTE_TYPE_ENUM_COUNT) { 911 fErrorOutput->PrintError("Error: Invalid %s section: attribute " 912 "type %d not supported!\n", fCurrentSection->name, type); 913 return B_BAD_DATA; 914 } 915 916 // get the value 917 error = ReadAttributeValue(type, attribute_tag_encoding(tag), 918 _value); 919 if (error != B_OK) 920 return error; 921 922 _id = attribute_tag_id(tag); 923 if (_id >= B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) { 924 fErrorOutput->PrintError("Error: Invalid %s section: " 925 "attribute id %d not supported!\n", fCurrentSection->name, _id); 926 return B_BAD_DATA; 927 } 928 } 929 930 if (_hasChildren != NULL) 931 *_hasChildren = attribute_tag_has_children(tag); 932 if (_tag != NULL) 933 *_tag = tag; 934 935 return B_OK; 936 } 937 938 939 status_t 940 ReaderImplBase::ReadAttributeValue(uint8 type, uint8 encoding, 941 AttributeValue& _value) 942 { 943 switch (type) { 944 case B_HPKG_ATTRIBUTE_TYPE_INT: 945 case B_HPKG_ATTRIBUTE_TYPE_UINT: 946 { 947 uint64 intValue; 948 status_t error; 949 950 switch (encoding) { 951 case B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT: 952 { 953 uint8 value; 954 error = _Read(value); 955 intValue = value; 956 break; 957 } 958 case B_HPKG_ATTRIBUTE_ENCODING_INT_16_BIT: 959 { 960 uint16 value; 961 error = _Read(value); 962 intValue = B_BENDIAN_TO_HOST_INT16(value); 963 break; 964 } 965 case B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT: 966 { 967 uint32 value; 968 error = _Read(value); 969 intValue = B_BENDIAN_TO_HOST_INT32(value); 970 break; 971 } 972 case B_HPKG_ATTRIBUTE_ENCODING_INT_64_BIT: 973 { 974 uint64 value; 975 error = _Read(value); 976 intValue = B_BENDIAN_TO_HOST_INT64(value); 977 break; 978 } 979 default: 980 { 981 fErrorOutput->PrintError("Error: Invalid %s section: " 982 "invalid encoding %d for int value type %d\n", 983 fCurrentSection->name, encoding, type); 984 return B_BAD_VALUE; 985 } 986 } 987 988 if (error != B_OK) 989 return error; 990 991 if (type == B_HPKG_ATTRIBUTE_TYPE_INT) 992 _value.SetTo((int64)intValue); 993 else 994 _value.SetTo(intValue); 995 996 return B_OK; 997 } 998 999 case B_HPKG_ATTRIBUTE_TYPE_STRING: 1000 { 1001 if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE) { 1002 uint64 index; 1003 status_t error = ReadUnsignedLEB128(index); 1004 if (error != B_OK) 1005 return error; 1006 1007 if (index > fCurrentSection->stringsCount) { 1008 fErrorOutput->PrintError("Error: Invalid %s section: " 1009 "string reference (%lld) out of bounds (%lld)\n", 1010 fCurrentSection->name, index, 1011 fCurrentSection->stringsCount); 1012 return B_BAD_DATA; 1013 } 1014 1015 _value.SetTo(fCurrentSection->strings[index]); 1016 } else if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE) { 1017 const char* string; 1018 status_t error = _ReadString(string); 1019 if (error != B_OK) 1020 return error; 1021 1022 _value.SetTo(string); 1023 } else { 1024 fErrorOutput->PrintError("Error: Invalid %s section: invalid " 1025 "string encoding (%u)\n", fCurrentSection->name, encoding); 1026 return B_BAD_DATA; 1027 } 1028 1029 return B_OK; 1030 } 1031 1032 default: 1033 fErrorOutput->PrintError("Error: Invalid %s section: invalid " 1034 "value type: %d\n", fCurrentSection->name, type); 1035 return B_BAD_DATA; 1036 } 1037 } 1038 1039 1040 status_t 1041 ReaderImplBase::ReadUnsignedLEB128(uint64& _value) 1042 { 1043 uint64 result = 0; 1044 int shift = 0; 1045 while (true) { 1046 uint8 byte; 1047 status_t error = _Read(byte); 1048 if (error != B_OK) 1049 return error; 1050 1051 result |= uint64(byte & 0x7f) << shift; 1052 if ((byte & 0x80) == 0) 1053 break; 1054 shift += 7; 1055 } 1056 1057 _value = result; 1058 return B_OK; 1059 } 1060 1061 1062 status_t 1063 ReaderImplBase::_ReadString(const char*& _string, size_t* _stringLength) 1064 { 1065 const char* string 1066 = (const char*)fCurrentSection->data + fCurrentSection->currentOffset; 1067 size_t stringLength = strnlen(string, 1068 fCurrentSection->uncompressedLength - fCurrentSection->currentOffset); 1069 1070 if (stringLength 1071 == fCurrentSection->uncompressedLength 1072 - fCurrentSection->currentOffset) { 1073 fErrorOutput->PrintError( 1074 "_ReadString(): string extends beyond %s end\n", 1075 fCurrentSection->name); 1076 return B_BAD_DATA; 1077 } 1078 1079 _string = string; 1080 if (_stringLength != NULL) 1081 *_stringLength = stringLength; 1082 1083 fCurrentSection->currentOffset += stringLength + 1; 1084 return B_OK; 1085 } 1086 1087 1088 status_t 1089 ReaderImplBase::_ReadSectionBuffer(void* buffer, size_t size) 1090 { 1091 if (size > fCurrentSection->uncompressedLength 1092 - fCurrentSection->currentOffset) { 1093 fErrorOutput->PrintError( 1094 "_ReadSectionBuffer(%lu): read beyond %s end\n", size, 1095 fCurrentSection->name); 1096 return B_BAD_DATA; 1097 } 1098 1099 memcpy(buffer, fCurrentSection->data + fCurrentSection->currentOffset, 1100 size); 1101 fCurrentSection->currentOffset += size; 1102 return B_OK; 1103 } 1104 1105 1106 status_t 1107 ReaderImplBase::ReadBuffer(off_t offset, void* buffer, size_t size) 1108 { 1109 ssize_t bytesRead = pread(fFD, buffer, size, offset); 1110 if (bytesRead < 0) { 1111 fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read data: " 1112 "%s\n", buffer, size, strerror(errno)); 1113 return errno; 1114 } 1115 if ((size_t)bytesRead != size) { 1116 fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read all " 1117 "data\n", buffer, size); 1118 return B_ERROR; 1119 } 1120 1121 return B_OK; 1122 } 1123 1124 1125 status_t 1126 ReaderImplBase::ReadSection(const PackageFileSection& section) 1127 { 1128 BBufferDataOutput output(section.data, section.uncompressedLength); 1129 return fHeapReader->ReadDataToOutput(section.offset, 1130 section.uncompressedLength, &output); 1131 } 1132 1133 1134 } // namespace BPrivate 1135 1136 } // namespace BHPKG 1137 1138 } // namespace BPackageKit 1139