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