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