1 /* 2 * Copyright 2009-2014, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "Package.h" 8 9 #include <errno.h> 10 #include <fcntl.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <unistd.h> 14 15 #include <package/hpkg/ErrorOutput.h> 16 #include <package/hpkg/PackageDataReader.h> 17 #include <package/hpkg/PackageEntry.h> 18 #include <package/hpkg/PackageEntryAttribute.h> 19 #include <package/hpkg/v1/PackageEntry.h> 20 #include <package/hpkg/v1/PackageEntryAttribute.h> 21 22 #include <AutoDeleter.h> 23 #include <package/hpkg/PackageFileHeapReader.h> 24 #include <package/hpkg/PackageReaderImpl.h> 25 #include <package/hpkg/v1/PackageReaderImpl.h> 26 #include <util/AutoLock.h> 27 28 #include "CachedDataReader.h" 29 #include "DebugSupport.h" 30 #include "GlobalFactory.h" 31 #include "PackageDirectory.h" 32 #include "PackageFile.h" 33 #include "PackagesDirectory.h" 34 #include "PackageSettings.h" 35 #include "PackageSymlink.h" 36 #include "Version.h" 37 #include "Volume.h" 38 39 40 using namespace BPackageKit; 41 42 using BPackageKit::BHPKG::BErrorOutput; 43 using BPackageKit::BHPKG::BFDDataReader; 44 using BPackageKit::BHPKG::BPackageInfoAttributeValue; 45 using BPackageKit::BHPKG::BPackageVersionData; 46 using BPackageKit::BHPKG::BPrivate::PackageFileHeapReader; 47 48 // current format version types 49 typedef BPackageKit::BHPKG::BPackageContentHandler BPackageContentHandler; 50 typedef BPackageKit::BHPKG::BPackageEntry BPackageEntry; 51 typedef BPackageKit::BHPKG::BPackageEntryAttribute BPackageEntryAttribute; 52 typedef BPackageKit::BHPKG::BPrivate::PackageReaderImpl PackageReaderImpl; 53 54 // format version V1 types 55 typedef BPackageKit::BHPKG::V1::BPackageContentHandler BPackageContentHandlerV1; 56 typedef BPackageKit::BHPKG::V1::BPackageEntry BPackageEntryV1; 57 typedef BPackageKit::BHPKG::V1::BPackageEntryAttribute BPackageEntryAttributeV1; 58 typedef BPackageKit::BHPKG::V1::BPrivate::PackageReaderImpl PackageReaderImplV1; 59 60 61 const char* const kArchitectureNames[B_PACKAGE_ARCHITECTURE_ENUM_COUNT] = { 62 "any", 63 "x86", 64 "x86_gcc2", 65 "source", 66 "x86_64", 67 "ppc", 68 "arm", 69 "m68k" 70 }; 71 72 73 // #pragma mark - LoaderErrorOutput 74 75 76 struct Package::LoaderErrorOutput : BErrorOutput { 77 LoaderErrorOutput(Package* package) 78 : 79 fPackage(package) 80 { 81 } 82 83 virtual void PrintErrorVarArgs(const char* format, va_list args) 84 { 85 ERRORV(format, args); 86 } 87 88 private: 89 Package* fPackage; 90 }; 91 92 93 // #pragma mark - LoaderContentHandler 94 95 96 struct Package::LoaderContentHandler : BPackageContentHandler { 97 LoaderContentHandler(Package* package, const PackageSettings& settings) 98 : 99 fPackage(package), 100 fSettings(settings), 101 fSettingsItem(NULL), 102 fLastSettingsEntry(NULL), 103 fLastSettingsEntryEntry(NULL), 104 fErrorOccurred(false) 105 { 106 } 107 108 status_t Init() 109 { 110 return B_OK; 111 } 112 113 virtual status_t HandleEntry(BPackageEntry* entry) 114 { 115 if (fErrorOccurred 116 || (fLastSettingsEntry != NULL 117 && fLastSettingsEntry->IsBlackListed())) { 118 return B_OK; 119 } 120 121 PackageDirectory* parentDir = NULL; 122 if (entry->Parent() != NULL) { 123 parentDir = dynamic_cast<PackageDirectory*>( 124 (PackageNode*)entry->Parent()->UserToken()); 125 if (parentDir == NULL) 126 RETURN_ERROR(B_BAD_DATA); 127 } 128 129 if (fSettingsItem != NULL 130 && (parentDir == NULL 131 || entry->Parent() == fLastSettingsEntryEntry)) { 132 PackageSettingsItem::Entry* settingsEntry 133 = fSettingsItem->FindEntry(fLastSettingsEntry, entry->Name()); 134 if (settingsEntry != NULL) { 135 fLastSettingsEntry = settingsEntry; 136 fLastSettingsEntryEntry = entry; 137 if (fLastSettingsEntry->IsBlackListed()) 138 return B_OK; 139 } 140 } 141 142 // get the file mode -- filter out write permissions 143 mode_t mode = entry->Mode() & ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH); 144 145 // create the package node 146 PackageNode* node; 147 if (S_ISREG(mode)) { 148 // file 149 node = new(std::nothrow) PackageFile(fPackage, mode, 150 PackageData(entry->Data())); 151 } else if (S_ISLNK(mode)) { 152 // symlink 153 String path; 154 if (!path.SetTo(entry->SymlinkPath())) 155 RETURN_ERROR(B_NO_MEMORY); 156 157 PackageSymlink* symlink = new(std::nothrow) PackageSymlink( 158 fPackage, mode); 159 if (symlink == NULL) 160 RETURN_ERROR(B_NO_MEMORY); 161 162 symlink->SetSymlinkPath(path); 163 node = symlink; 164 } else if (S_ISDIR(mode)) { 165 // directory 166 node = new(std::nothrow) PackageDirectory(fPackage, mode); 167 } else 168 RETURN_ERROR(B_BAD_DATA); 169 170 if (node == NULL) 171 RETURN_ERROR(B_NO_MEMORY); 172 BReference<PackageNode> nodeReference(node, true); 173 174 String entryName; 175 if (!entryName.SetTo(entry->Name())) 176 RETURN_ERROR(B_NO_MEMORY); 177 178 status_t error = node->Init(parentDir, entryName); 179 if (error != B_OK) 180 RETURN_ERROR(error); 181 182 node->SetModifiedTime(entry->ModifiedTime()); 183 184 // add it to the parent directory 185 if (parentDir != NULL) 186 parentDir->AddChild(node); 187 else 188 fPackage->AddNode(node); 189 190 entry->SetUserToken(node); 191 192 return B_OK; 193 } 194 195 virtual status_t HandleEntryAttribute(BPackageEntry* entry, 196 BPackageEntryAttribute* attribute) 197 { 198 if (fErrorOccurred 199 || (fLastSettingsEntry != NULL 200 && fLastSettingsEntry->IsBlackListed())) { 201 return B_OK; 202 } 203 204 PackageNode* node = (PackageNode*)entry->UserToken(); 205 206 String name; 207 if (!name.SetTo(attribute->Name())) 208 RETURN_ERROR(B_NO_MEMORY); 209 210 PackageNodeAttribute* nodeAttribute = new(std::nothrow) 211 PackageNodeAttribute(attribute->Type(), 212 PackageData(attribute->Data())); 213 if (nodeAttribute == NULL) 214 RETURN_ERROR(B_NO_MEMORY) 215 216 nodeAttribute->Init(name); 217 node->AddAttribute(nodeAttribute); 218 219 return B_OK; 220 } 221 222 virtual status_t HandleEntryDone(BPackageEntry* entry) 223 { 224 if (entry == fLastSettingsEntryEntry) { 225 fLastSettingsEntryEntry = entry->Parent(); 226 fLastSettingsEntry = fLastSettingsEntry->Parent(); 227 } 228 229 return B_OK; 230 } 231 232 virtual status_t HandlePackageAttribute( 233 const BPackageInfoAttributeValue& value) 234 { 235 switch (value.attributeID) { 236 case B_PACKAGE_INFO_NAME: 237 { 238 String name; 239 if (!name.SetTo(value.string)) 240 return B_NO_MEMORY; 241 fPackage->SetName(name); 242 243 fSettingsItem = fSettings.PackageItemFor(fPackage->Name()); 244 245 return B_OK; 246 } 247 248 case B_PACKAGE_INFO_INSTALL_PATH: 249 { 250 String path; 251 if (!path.SetTo(value.string)) 252 return B_NO_MEMORY; 253 fPackage->SetInstallPath(path); 254 return B_OK; 255 } 256 257 case B_PACKAGE_INFO_VERSION: 258 { 259 ::Version* version; 260 status_t error = Version::Create(value.version.major, 261 value.version.minor, value.version.micro, 262 value.version.preRelease, value.version.revision, version); 263 if (error != B_OK) 264 RETURN_ERROR(error); 265 266 fPackage->SetVersion(version); 267 break; 268 } 269 270 case B_PACKAGE_INFO_ARCHITECTURE: 271 if (value.unsignedInt >= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) 272 RETURN_ERROR(B_BAD_VALUE); 273 274 fPackage->SetArchitecture( 275 (BPackageArchitecture)value.unsignedInt); 276 break; 277 278 case B_PACKAGE_INFO_PROVIDES: 279 { 280 // create a version object, if a version is specified 281 ::Version* version = NULL; 282 if (value.resolvable.haveVersion) { 283 const BPackageVersionData& versionInfo 284 = value.resolvable.version; 285 status_t error = Version::Create(versionInfo.major, 286 versionInfo.minor, versionInfo.micro, 287 versionInfo.preRelease, versionInfo.revision, version); 288 if (error != B_OK) 289 RETURN_ERROR(error); 290 } 291 ObjectDeleter< ::Version> versionDeleter(version); 292 293 // create a version object, if a compatible version is specified 294 ::Version* compatibleVersion = NULL; 295 if (value.resolvable.haveCompatibleVersion) { 296 const BPackageVersionData& versionInfo 297 = value.resolvable.compatibleVersion; 298 status_t error = Version::Create(versionInfo.major, 299 versionInfo.minor, versionInfo.micro, 300 versionInfo.preRelease, versionInfo.revision, 301 compatibleVersion); 302 if (error != B_OK) 303 RETURN_ERROR(error); 304 } 305 ObjectDeleter< ::Version> compatibleVersionDeleter( 306 compatibleVersion); 307 308 // create the resolvable 309 Resolvable* resolvable = new(std::nothrow) Resolvable(fPackage); 310 if (resolvable == NULL) 311 RETURN_ERROR(B_NO_MEMORY); 312 ObjectDeleter<Resolvable> resolvableDeleter(resolvable); 313 314 status_t error = resolvable->Init(value.resolvable.name, 315 versionDeleter.Detach(), compatibleVersionDeleter.Detach()); 316 if (error != B_OK) 317 RETURN_ERROR(error); 318 319 fPackage->AddResolvable(resolvableDeleter.Detach()); 320 321 break; 322 } 323 324 case B_PACKAGE_INFO_REQUIRES: 325 { 326 // create the dependency 327 Dependency* dependency = new(std::nothrow) Dependency(fPackage); 328 if (dependency == NULL) 329 RETURN_ERROR(B_NO_MEMORY); 330 ObjectDeleter<Dependency> dependencyDeleter(dependency); 331 332 status_t error = dependency->Init( 333 value.resolvableExpression.name); 334 if (error != B_OK) 335 RETURN_ERROR(error); 336 337 // create a version object, if a version is specified 338 ::Version* version = NULL; 339 if (value.resolvableExpression.haveOpAndVersion) { 340 const BPackageVersionData& versionInfo 341 = value.resolvableExpression.version; 342 status_t error = Version::Create(versionInfo.major, 343 versionInfo.minor, versionInfo.micro, 344 versionInfo.preRelease, versionInfo.revision, version); 345 if (error != B_OK) 346 RETURN_ERROR(error); 347 348 dependency->SetVersionRequirement( 349 value.resolvableExpression.op, version); 350 } 351 352 fPackage->AddDependency(dependencyDeleter.Detach()); 353 354 break; 355 } 356 357 default: 358 break; 359 } 360 361 return B_OK; 362 } 363 364 virtual void HandleErrorOccurred() 365 { 366 fErrorOccurred = true; 367 } 368 369 private: 370 Package* fPackage; 371 const PackageSettings& fSettings; 372 const PackageSettingsItem* fSettingsItem; 373 PackageSettingsItem::Entry* fLastSettingsEntry; 374 const BPackageEntry* fLastSettingsEntryEntry; 375 bool fErrorOccurred; 376 }; 377 378 379 // #pragma mark - LoaderContentHandlerV1 380 381 382 struct Package::LoaderContentHandlerV1 : BPackageContentHandlerV1 { 383 LoaderContentHandlerV1(Package* package) 384 : 385 fPackage(package), 386 fErrorOccurred(false) 387 { 388 } 389 390 status_t Init() 391 { 392 return B_OK; 393 } 394 395 virtual status_t HandleEntry(BPackageEntryV1* entry) 396 { 397 if (fErrorOccurred) 398 return B_OK; 399 400 PackageDirectory* parentDir = NULL; 401 if (entry->Parent() != NULL) { 402 parentDir = dynamic_cast<PackageDirectory*>( 403 (PackageNode*)entry->Parent()->UserToken()); 404 if (parentDir == NULL) 405 RETURN_ERROR(B_BAD_DATA); 406 } 407 408 // get the file mode -- filter out write permissions 409 mode_t mode = entry->Mode() & ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH); 410 411 // create the package node 412 PackageNode* node; 413 if (S_ISREG(mode)) { 414 // file 415 node = new(std::nothrow) PackageFile(fPackage, mode, 416 PackageData(entry->Data())); 417 } else if (S_ISLNK(mode)) { 418 // symlink 419 String path; 420 if (!path.SetTo(entry->SymlinkPath())) 421 RETURN_ERROR(B_NO_MEMORY); 422 423 PackageSymlink* symlink = new(std::nothrow) PackageSymlink( 424 fPackage, mode); 425 if (symlink == NULL) 426 RETURN_ERROR(B_NO_MEMORY); 427 428 symlink->SetSymlinkPath(path); 429 node = symlink; 430 } else if (S_ISDIR(mode)) { 431 // directory 432 node = new(std::nothrow) PackageDirectory(fPackage, mode); 433 } else 434 RETURN_ERROR(B_BAD_DATA); 435 436 if (node == NULL) 437 RETURN_ERROR(B_NO_MEMORY); 438 BReference<PackageNode> nodeReference(node, true); 439 440 String entryName; 441 if (!entryName.SetTo(entry->Name())) 442 RETURN_ERROR(B_NO_MEMORY); 443 444 status_t error = node->Init(parentDir, entryName); 445 if (error != B_OK) 446 RETURN_ERROR(error); 447 448 node->SetModifiedTime(entry->ModifiedTime()); 449 450 // add it to the parent directory 451 if (parentDir != NULL) 452 parentDir->AddChild(node); 453 else 454 fPackage->AddNode(node); 455 456 entry->SetUserToken(node); 457 458 return B_OK; 459 } 460 461 virtual status_t HandleEntryAttribute(BPackageEntryV1* entry, 462 BPackageEntryAttributeV1* attribute) 463 { 464 if (fErrorOccurred) 465 return B_OK; 466 467 PackageNode* node = (PackageNode*)entry->UserToken(); 468 469 String name; 470 if (!name.SetTo(attribute->Name())) 471 RETURN_ERROR(B_NO_MEMORY); 472 473 PackageNodeAttribute* nodeAttribute = new(std::nothrow) 474 PackageNodeAttribute(attribute->Type(), 475 PackageData(attribute->Data())); 476 if (nodeAttribute == NULL) 477 RETURN_ERROR(B_NO_MEMORY) 478 479 nodeAttribute->Init(name); 480 node->AddAttribute(nodeAttribute); 481 482 return B_OK; 483 } 484 485 virtual status_t HandleEntryDone(BPackageEntryV1* entry) 486 { 487 return B_OK; 488 } 489 490 virtual status_t HandlePackageAttribute( 491 const BPackageInfoAttributeValue& value) 492 { 493 switch (value.attributeID) { 494 case B_PACKAGE_INFO_NAME: 495 { 496 String name; 497 if (!name.SetTo(value.string)) 498 return B_NO_MEMORY; 499 fPackage->SetName(name); 500 return B_OK; 501 } 502 503 case B_PACKAGE_INFO_INSTALL_PATH: 504 { 505 String path; 506 if (!path.SetTo(value.string)) 507 return B_NO_MEMORY; 508 fPackage->SetInstallPath(path); 509 return B_OK; 510 } 511 512 case B_PACKAGE_INFO_VERSION: 513 { 514 ::Version* version; 515 status_t error = Version::Create(value.version.major, 516 value.version.minor, value.version.micro, 517 value.version.preRelease, value.version.revision, version); 518 if (error != B_OK) 519 RETURN_ERROR(error); 520 521 fPackage->SetVersion(version); 522 523 break; 524 } 525 526 case B_PACKAGE_INFO_ARCHITECTURE: 527 if (value.unsignedInt >= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) 528 RETURN_ERROR(B_BAD_VALUE); 529 530 fPackage->SetArchitecture( 531 (BPackageArchitecture)value.unsignedInt); 532 break; 533 534 case B_PACKAGE_INFO_PROVIDES: 535 { 536 // create a version object, if a version is specified 537 ::Version* version = NULL; 538 if (value.resolvable.haveVersion) { 539 const BPackageVersionData& versionInfo 540 = value.resolvable.version; 541 status_t error = Version::Create(versionInfo.major, 542 versionInfo.minor, versionInfo.micro, 543 versionInfo.preRelease, versionInfo.revision, version); 544 if (error != B_OK) 545 RETURN_ERROR(error); 546 } 547 ObjectDeleter< ::Version> versionDeleter(version); 548 549 // create a version object, if a compatible version is specified 550 ::Version* compatibleVersion = NULL; 551 if (value.resolvable.haveCompatibleVersion) { 552 const BPackageVersionData& versionInfo 553 = value.resolvable.compatibleVersion; 554 status_t error = Version::Create(versionInfo.major, 555 versionInfo.minor, versionInfo.micro, 556 versionInfo.preRelease, versionInfo.revision, 557 compatibleVersion); 558 if (error != B_OK) 559 RETURN_ERROR(error); 560 } 561 ObjectDeleter< ::Version> compatibleVersionDeleter( 562 compatibleVersion); 563 564 // create the resolvable 565 Resolvable* resolvable = new(std::nothrow) Resolvable(fPackage); 566 if (resolvable == NULL) 567 RETURN_ERROR(B_NO_MEMORY); 568 ObjectDeleter<Resolvable> resolvableDeleter(resolvable); 569 570 status_t error = resolvable->Init(value.resolvable.name, 571 versionDeleter.Detach(), compatibleVersionDeleter.Detach()); 572 if (error != B_OK) 573 RETURN_ERROR(error); 574 575 fPackage->AddResolvable(resolvableDeleter.Detach()); 576 577 break; 578 } 579 580 case B_PACKAGE_INFO_REQUIRES: 581 { 582 // create the dependency 583 Dependency* dependency = new(std::nothrow) Dependency(fPackage); 584 if (dependency == NULL) 585 RETURN_ERROR(B_NO_MEMORY); 586 ObjectDeleter<Dependency> dependencyDeleter(dependency); 587 588 status_t error = dependency->Init( 589 value.resolvableExpression.name); 590 if (error != B_OK) 591 RETURN_ERROR(error); 592 593 // create a version object, if a version is specified 594 ::Version* version = NULL; 595 if (value.resolvableExpression.haveOpAndVersion) { 596 const BPackageVersionData& versionInfo 597 = value.resolvableExpression.version; 598 status_t error = Version::Create(versionInfo.major, 599 versionInfo.minor, versionInfo.micro, 600 versionInfo.preRelease, versionInfo.revision, version); 601 if (error != B_OK) 602 RETURN_ERROR(error); 603 604 dependency->SetVersionRequirement( 605 value.resolvableExpression.op, version); 606 } 607 608 fPackage->AddDependency(dependencyDeleter.Detach()); 609 610 break; 611 } 612 613 default: 614 break; 615 } 616 617 return B_OK; 618 } 619 620 virtual void HandleErrorOccurred() 621 { 622 fErrorOccurred = true; 623 } 624 625 private: 626 Package* fPackage; 627 bool fErrorOccurred; 628 }; 629 630 631 // #pragma mark - HeapReader 632 633 634 struct Package::HeapReader { 635 virtual ~HeapReader() 636 { 637 } 638 639 virtual void UpdateFD(int fd) = 0; 640 641 virtual status_t CreateDataReader(const PackageData& data, 642 BAbstractBufferedDataReader*& _reader) = 0; 643 }; 644 645 646 // #pragma mark - HeapReaderV1 647 648 649 struct Package::HeapReaderV1 : public HeapReader, private BDataReader { 650 public: 651 HeapReaderV1(int fd) 652 : 653 fFileReader(fd) 654 { 655 } 656 657 ~HeapReaderV1() 658 { 659 } 660 661 virtual void UpdateFD(int fd) 662 { 663 fFileReader.SetFD(fd); 664 } 665 666 virtual status_t CreateDataReader(const PackageData& data, 667 BAbstractBufferedDataReader*& _reader) 668 { 669 return GlobalFactory::Default()->CreatePackageDataReader(this, 670 data.DataV1(), _reader); 671 } 672 673 private: 674 // BDataReader 675 676 virtual status_t ReadData(off_t offset, void* buffer, size_t size) 677 { 678 return fFileReader.ReadData(offset, buffer, size); 679 } 680 681 private: 682 BFDDataReader fFileReader; 683 }; 684 685 686 // #pragma mark - HeapReaderV2 687 688 689 struct Package::HeapReaderV2 : public HeapReader, public CachedDataReader, 690 private BErrorOutput { 691 public: 692 HeapReaderV2() 693 : 694 fHeapReader(NULL) 695 { 696 } 697 698 ~HeapReaderV2() 699 { 700 delete fHeapReader; 701 } 702 703 status_t Init(const PackageFileHeapReader* heapReader, int fd) 704 { 705 fHeapReader = heapReader->Clone(); 706 if (fHeapReader == NULL) 707 return B_NO_MEMORY; 708 709 fHeapReader->SetErrorOutput(this); 710 fHeapReader->SetFD(fd); 711 712 status_t error = CachedDataReader::Init(fHeapReader, 713 fHeapReader->UncompressedHeapSize()); 714 if (error != B_OK) 715 return error; 716 717 return B_OK; 718 } 719 720 virtual void UpdateFD(int fd) 721 { 722 fHeapReader->SetFD(fd); 723 } 724 725 virtual status_t CreateDataReader(const PackageData& data, 726 BAbstractBufferedDataReader*& _reader) 727 { 728 return BPackageKit::BHPKG::BPackageDataReaderFactory() 729 .CreatePackageDataReader(this, data.DataV2(), _reader); 730 } 731 732 private: 733 // BErrorOutput 734 735 virtual void PrintErrorVarArgs(const char* format, va_list args) 736 { 737 ERRORV(format, args); 738 } 739 740 private: 741 PackageFileHeapReader* fHeapReader; 742 }; 743 744 745 // #pragma mark - Package 746 747 748 struct Package::CachingPackageReader : public PackageReaderImpl { 749 CachingPackageReader(BErrorOutput* errorOutput) 750 : 751 PackageReaderImpl(errorOutput), 752 fCachedHeapReader(NULL) 753 { 754 } 755 756 ~CachingPackageReader() 757 { 758 } 759 760 virtual status_t CreateCachedHeapReader( 761 PackageFileHeapReader* rawHeapReader, 762 BAbstractBufferedDataReader*& _cachedReader) 763 { 764 fCachedHeapReader = new(std::nothrow) HeapReaderV2; 765 if (fCachedHeapReader == NULL) 766 RETURN_ERROR(B_NO_MEMORY); 767 768 status_t error = fCachedHeapReader->Init(rawHeapReader, FD()); 769 if (error != B_OK) 770 RETURN_ERROR(error); 771 772 _cachedReader = fCachedHeapReader; 773 return B_OK; 774 } 775 776 HeapReaderV2* DetachCachedHeapReader() 777 { 778 DetachHeapReader(); 779 780 HeapReaderV2* cachedHeapReader = fCachedHeapReader; 781 fCachedHeapReader = NULL; 782 return cachedHeapReader; 783 } 784 785 private: 786 HeapReaderV2* fCachedHeapReader; 787 }; 788 789 790 // #pragma mark - Package 791 792 793 Package::Package(::Volume* volume, PackagesDirectory* directory, dev_t deviceID, 794 ino_t nodeID) 795 : 796 fVolume(volume), 797 fPackagesDirectory(directory), 798 fFileName(), 799 fName(), 800 fInstallPath(), 801 fVersionedName(), 802 fVersion(NULL), 803 fArchitecture(B_PACKAGE_ARCHITECTURE_ENUM_COUNT), 804 fLinkDirectory(NULL), 805 fFD(-1), 806 fOpenCount(0), 807 fHeapReader(NULL), 808 fNodeID(nodeID), 809 fDeviceID(deviceID) 810 { 811 mutex_init(&fLock, "packagefs package"); 812 813 fPackagesDirectory->AcquireReference(); 814 } 815 816 817 Package::~Package() 818 { 819 delete fHeapReader; 820 821 while (PackageNode* node = fNodes.RemoveHead()) 822 node->ReleaseReference(); 823 824 while (Resolvable* resolvable = fResolvables.RemoveHead()) 825 delete resolvable; 826 827 while (Dependency* dependency = fDependencies.RemoveHead()) 828 delete dependency; 829 830 delete fVersion; 831 832 fPackagesDirectory->ReleaseReference(); 833 834 mutex_destroy(&fLock); 835 } 836 837 838 status_t 839 Package::Init(const char* fileName) 840 { 841 if (!fFileName.SetTo(fileName)) 842 RETURN_ERROR(B_NO_MEMORY); 843 844 return B_OK; 845 } 846 847 848 status_t 849 Package::Load(const PackageSettings& settings) 850 { 851 status_t error = _Load(settings); 852 if (error != B_OK) 853 return error; 854 855 if (!_InitVersionedName()) 856 RETURN_ERROR(B_NO_MEMORY); 857 858 return B_OK; 859 } 860 861 862 void 863 Package::SetName(const String& name) 864 { 865 fName = name; 866 } 867 868 869 void 870 Package::SetInstallPath(const String& installPath) 871 { 872 fInstallPath = installPath; 873 } 874 875 876 void 877 Package::SetVersion(::Version* version) 878 { 879 if (fVersion != NULL) 880 delete fVersion; 881 882 fVersion = version; 883 } 884 885 886 const char* 887 Package::ArchitectureName() const 888 { 889 if (fArchitecture < 0 890 || fArchitecture >= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) { 891 return NULL; 892 } 893 894 return kArchitectureNames[fArchitecture]; 895 } 896 897 898 void 899 Package::AddNode(PackageNode* node) 900 { 901 fNodes.Add(node); 902 node->AcquireReference(); 903 } 904 905 906 void 907 Package::AddResolvable(Resolvable* resolvable) 908 { 909 fResolvables.Add(resolvable); 910 } 911 912 913 void 914 Package::AddDependency(Dependency* dependency) 915 { 916 fDependencies.Add(dependency); 917 } 918 919 920 int 921 Package::Open() 922 { 923 MutexLocker locker(fLock); 924 if (fOpenCount > 0) { 925 fOpenCount++; 926 return fFD; 927 } 928 929 // open the file 930 fFD = openat(fPackagesDirectory->DirectoryFD(), fFileName, O_RDONLY); 931 if (fFD < 0) { 932 ERROR("Failed to open package file \"%s\"\n", fFileName.Data()); 933 return errno; 934 } 935 936 // stat it to verify that it's still the same file 937 struct stat st; 938 if (fstat(fFD, &st) < 0) { 939 ERROR("Failed to stat package file \"%s\"\n", fFileName.Data()); 940 close(fFD); 941 fFD = -1; 942 return errno; 943 } 944 945 if (st.st_dev != fDeviceID || st.st_ino != fNodeID) { 946 close(fFD); 947 fFD = -1; 948 RETURN_ERROR(B_ENTRY_NOT_FOUND); 949 } 950 951 fOpenCount = 1; 952 953 if (fHeapReader != NULL) 954 fHeapReader->UpdateFD(fFD); 955 956 return fFD; 957 } 958 959 960 void 961 Package::Close() 962 { 963 MutexLocker locker(fLock); 964 if (fOpenCount == 0) { 965 ERROR("Package open count already 0!\n"); 966 return; 967 } 968 969 if (--fOpenCount == 0) { 970 close(fFD); 971 fFD = -1; 972 973 if (fHeapReader != NULL) 974 fHeapReader->UpdateFD(fFD); 975 } 976 } 977 978 979 status_t 980 Package::CreateDataReader(const PackageData& data, 981 BAbstractBufferedDataReader*& _reader) 982 { 983 if (fHeapReader == NULL) 984 return B_BAD_VALUE; 985 986 return fHeapReader->CreateDataReader(data, _reader); 987 } 988 989 990 status_t 991 Package::_Load(const PackageSettings& settings) 992 { 993 // open package file 994 int fd = Open(); 995 if (fd < 0) 996 RETURN_ERROR(fd); 997 PackageCloser packageCloser(this); 998 999 // initialize package reader 1000 LoaderErrorOutput errorOutput(this); 1001 1002 // try current package file format version 1003 { 1004 CachingPackageReader packageReader(&errorOutput); 1005 status_t error = packageReader.Init(fd, false, 1006 BHPKG::B_HPKG_READER_DONT_PRINT_VERSION_MISMATCH_MESSAGE); 1007 if (error == B_OK) { 1008 // parse content 1009 LoaderContentHandler handler(this, settings); 1010 error = handler.Init(); 1011 if (error != B_OK) 1012 RETURN_ERROR(error); 1013 1014 error = packageReader.ParseContent(&handler); 1015 if (error != B_OK) 1016 RETURN_ERROR(error); 1017 1018 // get the heap reader 1019 fHeapReader = packageReader.DetachCachedHeapReader(); 1020 return B_OK; 1021 } 1022 1023 if (error != B_MISMATCHED_VALUES) 1024 RETURN_ERROR(error); 1025 } 1026 1027 // try package file format version 1 1028 PackageReaderImplV1 packageReader(&errorOutput); 1029 status_t error = packageReader.Init(fd, false); 1030 if (error != B_OK) 1031 RETURN_ERROR(error); 1032 1033 // parse content 1034 LoaderContentHandlerV1 handler(this); 1035 error = handler.Init(); 1036 if (error != B_OK) 1037 RETURN_ERROR(error); 1038 1039 error = packageReader.ParseContent(&handler); 1040 if (error != B_OK) 1041 RETURN_ERROR(error); 1042 1043 // create a heap reader 1044 fHeapReader = new(std::nothrow) HeapReaderV1(fd); 1045 if (fHeapReader == NULL) 1046 RETURN_ERROR(B_NO_MEMORY); 1047 1048 return B_OK; 1049 } 1050 1051 1052 bool 1053 Package::_InitVersionedName() 1054 { 1055 // compute the allocation size needed for the versioned name 1056 size_t nameLength = strlen(fName); 1057 size_t size = nameLength + 1; 1058 1059 if (fVersion != NULL) { 1060 size += 1 + fVersion->ToString(NULL, 0); 1061 // + 1 for the '-' 1062 } 1063 1064 // allocate the name and compose it 1065 char* name = (char*)malloc(size); 1066 if (name == NULL) 1067 return false; 1068 MemoryDeleter nameDeleter(name); 1069 1070 memcpy(name, fName, nameLength + 1); 1071 if (fVersion != NULL) { 1072 name[nameLength] = '-'; 1073 fVersion->ToString(name + nameLength + 1, size - nameLength - 1); 1074 } 1075 1076 return fVersionedName.SetTo(name); 1077 } 1078