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