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