From e85e9dadda48ba707367595e2aa93dc8f9f78054 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sun, 7 Apr 2013 11:45:47 +0200 Subject: [PATCH] packagefs: Move the package loading code to Package * Volume::_LoadPackage() -> Package::Load() * Volume::_DomainEntryCreated(): Pull a bit of code into a new _LoadPackage() method for reuse. --- .../kernel/file_systems/packagefs/Package.cpp | 304 +++++++++++++++ .../kernel/file_systems/packagefs/Package.h | 5 + .../kernel/file_systems/packagefs/Volume.cpp | 353 ++---------------- .../kernel/file_systems/packagefs/Volume.h | 4 +- 4 files changed, 345 insertions(+), 321 deletions(-) diff --git a/src/add-ons/kernel/file_systems/packagefs/Package.cpp b/src/add-ons/kernel/file_systems/packagefs/Package.cpp index c5a21e8c96..28fc000b80 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Package.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/Package.cpp @@ -12,13 +12,26 @@ #include #include +#include +#include +#include +#include +#include #include #include "DebugSupport.h" +#include "PackageDirectory.h" #include "PackageDomain.h" +#include "PackageFile.h" +#include "PackageSymlink.h" #include "Version.h" +using namespace BPackageKit; +using namespace BPackageKit::BHPKG; +using BPackageKit::BHPKG::BPrivate::PackageReaderImpl; + + const char* const kArchitectureNames[B_PACKAGE_ARCHITECTURE_ENUM_COUNT] = { "any", "x86", @@ -26,6 +39,267 @@ const char* const kArchitectureNames[B_PACKAGE_ARCHITECTURE_ENUM_COUNT] = { }; +// #pragma mark - LoaderErrorOutput + + +struct Package::LoaderErrorOutput : BErrorOutput { + LoaderErrorOutput(Package* package) + : + fPackage(package) + { + } + + virtual void PrintErrorVarArgs(const char* format, va_list args) + { +// TODO:... + } + +private: + Package* fPackage; +}; + + +// #pragma mark - LoaderContentHandler + + +struct Package::LoaderContentHandler : BPackageContentHandler { + LoaderContentHandler(Package* package) + : + fPackage(package), + fErrorOccurred(false) + { + } + + status_t Init() + { + return B_OK; + } + + virtual status_t HandleEntry(BPackageEntry* entry) + { + if (fErrorOccurred) + return B_OK; + + PackageDirectory* parentDir = NULL; + if (entry->Parent() != NULL) { + parentDir = dynamic_cast( + (PackageNode*)entry->Parent()->UserToken()); + if (parentDir == NULL) + RETURN_ERROR(B_BAD_DATA); + } + + status_t error; + + // get the file mode -- filter out write permissions + mode_t mode = entry->Mode() & ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH); + + // create the package node + PackageNode* node; + if (S_ISREG(mode)) { + // file + node = new(std::nothrow) PackageFile(fPackage, mode, entry->Data()); + } else if (S_ISLNK(mode)) { + // symlink + PackageSymlink* symlink = new(std::nothrow) PackageSymlink( + fPackage, mode); + if (symlink == NULL) + RETURN_ERROR(B_NO_MEMORY); + + error = symlink->SetSymlinkPath(entry->SymlinkPath()); + if (error != B_OK) { + delete symlink; + return error; + } + + node = symlink; + } else if (S_ISDIR(mode)) { + // directory + node = new(std::nothrow) PackageDirectory(fPackage, mode); + } else + RETURN_ERROR(B_BAD_DATA); + + if (node == NULL) + RETURN_ERROR(B_NO_MEMORY); + BReference nodeReference(node, true); + + error = node->Init(parentDir, entry->Name()); + if (error != B_OK) + RETURN_ERROR(error); + + node->SetModifiedTime(entry->ModifiedTime()); + + // add it to the parent directory + if (parentDir != NULL) + parentDir->AddChild(node); + else + fPackage->AddNode(node); + + entry->SetUserToken(node); + + return B_OK; + } + + virtual status_t HandleEntryAttribute(BPackageEntry* entry, + BPackageEntryAttribute* attribute) + { + if (fErrorOccurred) + return B_OK; + + PackageNode* node = (PackageNode*)entry->UserToken(); + + PackageNodeAttribute* nodeAttribute = new(std::nothrow) + PackageNodeAttribute(attribute->Type(), attribute->Data()); + if (nodeAttribute == NULL) + RETURN_ERROR(B_NO_MEMORY) + + status_t error = nodeAttribute->Init(attribute->Name()); + if (error != B_OK) { + delete nodeAttribute; + RETURN_ERROR(error); + } + + node->AddAttribute(nodeAttribute); + + return B_OK; + } + + virtual status_t HandleEntryDone(BPackageEntry* entry) + { + return B_OK; + } + + virtual status_t HandlePackageAttribute( + const BPackageInfoAttributeValue& value) + { + switch (value.attributeID) { + case B_PACKAGE_INFO_NAME: + return fPackage->SetName(value.string); + + case B_PACKAGE_INFO_INSTALL_PATH: + return fPackage->SetInstallPath(value.string); + + case B_PACKAGE_INFO_VERSION: + { + ::Version* version; + status_t error = Version::Create(value.version.major, + value.version.minor, value.version.micro, + value.version.preRelease, value.version.release, version); + if (error != B_OK) + RETURN_ERROR(error); + + fPackage->SetVersion(version); + + break; + } + + case B_PACKAGE_INFO_ARCHITECTURE: + if (value.unsignedInt >= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) + RETURN_ERROR(B_BAD_VALUE); + + fPackage->SetArchitecture( + (BPackageArchitecture)value.unsignedInt); + break; + + case B_PACKAGE_INFO_PROVIDES: + { + // create a version object, if a version is specified + ::Version* version = NULL; + if (value.resolvable.haveVersion) { + const BPackageVersionData& versionInfo + = value.resolvable.version; + status_t error = Version::Create(versionInfo.major, + versionInfo.minor, versionInfo.micro, + versionInfo.preRelease, versionInfo.release, version); + if (error != B_OK) + RETURN_ERROR(error); + } + ObjectDeleter< ::Version> versionDeleter(version); + + // create a version object, if a compatible version is specified + ::Version* compatibleVersion = NULL; + if (value.resolvable.haveCompatibleVersion) { + const BPackageVersionData& versionInfo + = value.resolvable.compatibleVersion; + status_t error = Version::Create(versionInfo.major, + versionInfo.minor, versionInfo.micro, + versionInfo.preRelease, versionInfo.release, + compatibleVersion); + if (error != B_OK) + RETURN_ERROR(error); + } + ObjectDeleter< ::Version> compatibleVersionDeleter( + compatibleVersion); + + // create the resolvable + Resolvable* resolvable = new(std::nothrow) Resolvable(fPackage); + if (resolvable == NULL) + RETURN_ERROR(B_NO_MEMORY); + ObjectDeleter resolvableDeleter(resolvable); + + status_t error = resolvable->Init(value.resolvable.name, + versionDeleter.Detach(), compatibleVersionDeleter.Detach()); + if (error != B_OK) + RETURN_ERROR(error); + + fPackage->AddResolvable(resolvableDeleter.Detach()); + + break; + } + + case B_PACKAGE_INFO_REQUIRES: + { + // create the dependency + Dependency* dependency = new(std::nothrow) Dependency(fPackage); + if (dependency == NULL) + RETURN_ERROR(B_NO_MEMORY); + ObjectDeleter dependencyDeleter(dependency); + + status_t error = dependency->Init( + value.resolvableExpression.name); + if (error != B_OK) + RETURN_ERROR(error); + + // create a version object, if a version is specified + ::Version* version = NULL; + if (value.resolvableExpression.haveOpAndVersion) { + const BPackageVersionData& versionInfo + = value.resolvableExpression.version; + status_t error = Version::Create(versionInfo.major, + versionInfo.minor, versionInfo.micro, + versionInfo.preRelease, versionInfo.release, version); + if (error != B_OK) + RETURN_ERROR(error); + + dependency->SetVersionRequirement( + value.resolvableExpression.op, version); + } + + fPackage->AddDependency(dependencyDeleter.Detach()); + + break; + } + + default: + break; + } + + return B_OK; + } + + virtual void HandleErrorOccurred() + { + fErrorOccurred = true; + } + +private: + Package* fPackage; + bool fErrorOccurred; +}; + + +// #pragma mark - Package + + Package::Package(PackageDomain* domain, dev_t deviceID, ino_t nodeID) : fDomain(domain), @@ -75,6 +349,36 @@ Package::Init(const char* fileName) } +status_t +Package::Load() +{ + // open package file + int fd = Open(); + if (fd < 0) + RETURN_ERROR(fd); + PackageCloser packageCloser(this); + + // initialize package reader + LoaderErrorOutput errorOutput(this); + PackageReaderImpl packageReader(&errorOutput); + status_t error = packageReader.Init(fd, false); + if (error != B_OK) + RETURN_ERROR(error); + + // parse content + LoaderContentHandler handler(this); + error = handler.Init(); + if (error != B_OK) + RETURN_ERROR(error); + + error = packageReader.ParseContent(&handler); + if (error != B_OK) + RETURN_ERROR(error); + + return B_OK; +} + + status_t Package::SetName(const char* name) { diff --git a/src/add-ons/kernel/file_systems/packagefs/Package.h b/src/add-ons/kernel/file_systems/packagefs/Package.h index 6b69fd01ef..d9b0b56a6a 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Package.h +++ b/src/add-ons/kernel/file_systems/packagefs/Package.h @@ -37,6 +37,7 @@ public: ~Package(); status_t Init(const char* fileName); + status_t Load(); PackageDomain* Domain() const { return fDomain; } const char* FileName() const { return fFileName; } @@ -86,6 +87,10 @@ public: const DependencyList& Dependencies() const { return fDependencies; } +private: + struct LoaderErrorOutput; + struct LoaderContentHandler; + private: mutex fLock; PackageDomain* fDomain; diff --git a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp index 6d89b4e04d..d0ed67e3d5 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp @@ -25,23 +25,15 @@ #include #include -#include -#include -#include -#include - #include "AttributeIndex.h" #include "DebugSupport.h" #include "kernel_interface.h" #include "LastModifiedIndex.h" #include "NameIndex.h" #include "OldUnpackingNodeAttributes.h" -#include "PackageDirectory.h" -#include "PackageFile.h" #include "PackageFSRoot.h" #include "PackageLinkDirectory.h" #include "PackageLinksDirectory.h" -#include "PackageSymlink.h" #include "Resolvable.h" #include "SizeIndex.h" #include "UnpackingLeafNode.h" @@ -50,11 +42,6 @@ #include "Version.h" -using namespace BPackageKit; -using namespace BPackageKit::BHPKG; -using BPackageKit::BHPKG::BPrivate::PackageReaderImpl; - - // node ID of the root directory static const ino_t kRootDirectoryID = 1; @@ -156,264 +143,6 @@ private: }; -// #pragma mark - PackageLoaderErrorOutput - - -struct Volume::PackageLoaderErrorOutput : BErrorOutput { - PackageLoaderErrorOutput(Package* package) - : - fPackage(package) - { - } - - virtual void PrintErrorVarArgs(const char* format, va_list args) - { -// TODO:... - } - -private: - Package* fPackage; -}; - - -// #pragma mark - PackageLoaderContentHandler - - -struct Volume::PackageLoaderContentHandler : BPackageContentHandler { - PackageLoaderContentHandler(Package* package) - : - fPackage(package), - fErrorOccurred(false) - { - } - - status_t Init() - { - return B_OK; - } - - virtual status_t HandleEntry(BPackageEntry* entry) - { - if (fErrorOccurred) - return B_OK; - - PackageDirectory* parentDir = NULL; - if (entry->Parent() != NULL) { - parentDir = dynamic_cast( - (PackageNode*)entry->Parent()->UserToken()); - if (parentDir == NULL) - RETURN_ERROR(B_BAD_DATA); - } - - status_t error; - - // get the file mode -- filter out write permissions - mode_t mode = entry->Mode() & ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH); - - // create the package node - PackageNode* node; - if (S_ISREG(mode)) { - // file - node = new(std::nothrow) PackageFile(fPackage, mode, entry->Data()); - } else if (S_ISLNK(mode)) { - // symlink - PackageSymlink* symlink = new(std::nothrow) PackageSymlink( - fPackage, mode); - if (symlink == NULL) - RETURN_ERROR(B_NO_MEMORY); - - error = symlink->SetSymlinkPath(entry->SymlinkPath()); - if (error != B_OK) { - delete symlink; - return error; - } - - node = symlink; - } else if (S_ISDIR(mode)) { - // directory - node = new(std::nothrow) PackageDirectory(fPackage, mode); - } else - RETURN_ERROR(B_BAD_DATA); - - if (node == NULL) - RETURN_ERROR(B_NO_MEMORY); - BReference nodeReference(node, true); - - error = node->Init(parentDir, entry->Name()); - if (error != B_OK) - RETURN_ERROR(error); - - node->SetModifiedTime(entry->ModifiedTime()); - - // add it to the parent directory - if (parentDir != NULL) - parentDir->AddChild(node); - else - fPackage->AddNode(node); - - entry->SetUserToken(node); - - return B_OK; - } - - virtual status_t HandleEntryAttribute(BPackageEntry* entry, - BPackageEntryAttribute* attribute) - { - if (fErrorOccurred) - return B_OK; - - PackageNode* node = (PackageNode*)entry->UserToken(); - - PackageNodeAttribute* nodeAttribute = new(std::nothrow) - PackageNodeAttribute(attribute->Type(), attribute->Data()); - if (nodeAttribute == NULL) - RETURN_ERROR(B_NO_MEMORY) - - status_t error = nodeAttribute->Init(attribute->Name()); - if (error != B_OK) { - delete nodeAttribute; - RETURN_ERROR(error); - } - - node->AddAttribute(nodeAttribute); - - return B_OK; - } - - virtual status_t HandleEntryDone(BPackageEntry* entry) - { - return B_OK; - } - - virtual status_t HandlePackageAttribute( - const BPackageInfoAttributeValue& value) - { - switch (value.attributeID) { - case B_PACKAGE_INFO_NAME: - return fPackage->SetName(value.string); - - case B_PACKAGE_INFO_INSTALL_PATH: - return fPackage->SetInstallPath(value.string); - - case B_PACKAGE_INFO_VERSION: - { - Version* version; - status_t error = Version::Create(value.version.major, - value.version.minor, value.version.micro, - value.version.preRelease, value.version.release, version); - if (error != B_OK) - RETURN_ERROR(error); - - fPackage->SetVersion(version); - - break; - } - - case B_PACKAGE_INFO_ARCHITECTURE: - if (value.unsignedInt >= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) - RETURN_ERROR(B_BAD_VALUE); - - fPackage->SetArchitecture( - (BPackageArchitecture)value.unsignedInt); - break; - - case B_PACKAGE_INFO_PROVIDES: - { - // create a version object, if a version is specified - Version* version = NULL; - if (value.resolvable.haveVersion) { - const BPackageVersionData& versionInfo - = value.resolvable.version; - status_t error = Version::Create(versionInfo.major, - versionInfo.minor, versionInfo.micro, - versionInfo.preRelease, versionInfo.release, version); - if (error != B_OK) - RETURN_ERROR(error); - } - ObjectDeleter versionDeleter(version); - - // create a version object, if a compatible version is specified - Version* compatibleVersion = NULL; - if (value.resolvable.haveCompatibleVersion) { - const BPackageVersionData& versionInfo - = value.resolvable.compatibleVersion; - status_t error = Version::Create(versionInfo.major, - versionInfo.minor, versionInfo.micro, - versionInfo.preRelease, versionInfo.release, - compatibleVersion); - if (error != B_OK) - RETURN_ERROR(error); - } - ObjectDeleter compatibleVersionDeleter( - compatibleVersion); - - // create the resolvable - Resolvable* resolvable = new(std::nothrow) Resolvable(fPackage); - if (resolvable == NULL) - RETURN_ERROR(B_NO_MEMORY); - ObjectDeleter resolvableDeleter(resolvable); - - status_t error = resolvable->Init(value.resolvable.name, - versionDeleter.Detach(), compatibleVersionDeleter.Detach()); - if (error != B_OK) - RETURN_ERROR(error); - - fPackage->AddResolvable(resolvableDeleter.Detach()); - - break; - } - - case B_PACKAGE_INFO_REQUIRES: - { - // create the dependency - Dependency* dependency = new(std::nothrow) Dependency(fPackage); - if (dependency == NULL) - RETURN_ERROR(B_NO_MEMORY); - ObjectDeleter dependencyDeleter(dependency); - - status_t error = dependency->Init( - value.resolvableExpression.name); - if (error != B_OK) - RETURN_ERROR(error); - - // create a version object, if a version is specified - Version* version = NULL; - if (value.resolvableExpression.haveOpAndVersion) { - const BPackageVersionData& versionInfo - = value.resolvableExpression.version; - status_t error = Version::Create(versionInfo.major, - versionInfo.minor, versionInfo.micro, - versionInfo.preRelease, versionInfo.release, version); - if (error != B_OK) - RETURN_ERROR(error); - - dependency->SetVersionRequirement( - value.resolvableExpression.op, version); - } - - fPackage->AddDependency(dependencyDeleter.Detach()); - - break; - } - - default: - break; - } - - return B_OK; - } - - virtual void HandleErrorOccurred() - { - fErrorOccurred = true; - } - -private: - Package* fPackage; - bool fErrorOccurred; -}; - - // #pragma mark - DomainDirectoryListener @@ -1039,36 +768,6 @@ Volume::_RemovePackageDomain(PackageDomain* domain) } -status_t -Volume::_LoadPackage(Package* package) -{ - // open package file - int fd = package->Open(); - if (fd < 0) - RETURN_ERROR(fd); - PackageCloser packageCloser(package); - - // initialize package reader - PackageLoaderErrorOutput errorOutput(package); - PackageReaderImpl packageReader(&errorOutput); - status_t error = packageReader.Init(fd, false); - if (error != B_OK) - RETURN_ERROR(error); - - // parse content - PackageLoaderContentHandler handler(package); - error = handler.Init(); - if (error != B_OK) - RETURN_ERROR(error); - - error = packageReader.ParseContent(&handler); - if (error != B_OK) - RETURN_ERROR(error); - - return B_OK; -} - - status_t Volume::_AddPackageContent(Package* package, bool notify) { @@ -1613,34 +1312,18 @@ Volume::_DomainEntryCreated(PackageDomain* domain, dev_t deviceID, return; } - // check whether the entry is a file - struct stat st; - if (fstatat(domain->DirectoryFD(), name, &st, 0) < 0 - || !S_ISREG(st.st_mode)) { - return; - } - - // create a package - Package* package = new(std::nothrow) Package(domain, st.st_dev, st.st_ino); - if (package == NULL) + Package* package; + if (_LoadPackage(domain, name, package) != B_OK) return; BReference packageReference(package, true); - status_t error = package->Init(name); - if (error != B_OK) - return; - - error = _LoadPackage(package); - if (error != B_OK) - return; - VolumeWriteLocker systemVolumeLocker(_SystemVolumeIfNotSelf()); VolumeWriteLocker volumeLocker(this); domain->AddPackage(package); // add the package to the node tree if (addContent) { - error = _AddPackageContent(package, notify); + status_t error = _AddPackageContent(package, notify); if (error != B_OK) { domain->RemovePackage(package); return; @@ -1682,6 +1365,36 @@ Volume::_DomainEntryMoved(PackageDomain* domain, dev_t deviceID, } +/*static*/ status_t +Volume::_LoadPackage(PackageDomain* domain, const char* name, + Package*& _package) +{ + // check whether the entry is a file + struct stat st; + if (fstatat(domain->DirectoryFD(), name, &st, 0) < 0 + || !S_ISREG(st.st_mode)) { + return B_BAD_VALUE; + } + + // create a package + Package* package = new(std::nothrow) Package(domain, st.st_dev, st.st_ino); + if (package == NULL) + RETURN_ERROR(B_NO_MEMORY); + BReference packageReference(package, true); + + status_t error = package->Init(name); + if (error != B_OK) + return error; + + error = package->Load(); + if (error != B_OK) + return error; + + _package = packageReference.Detach(); + return B_OK; +} + + status_t Volume::_InitMountType(const char* mountType) { diff --git a/src/add-ons/kernel/file_systems/packagefs/Volume.h b/src/add-ons/kernel/file_systems/packagefs/Volume.h index 38a6097978..b32736a8e9 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Volume.h +++ b/src/add-ons/kernel/file_systems/packagefs/Volume.h @@ -132,7 +132,6 @@ private: status_t _AddPackageDomain(PackageDomain* domain, bool notify); void _RemovePackageDomain(PackageDomain* domain); - status_t _LoadPackage(Package* package); status_t _AddPackageContent(Package* package, bool notify); @@ -177,6 +176,9 @@ private: ino_t nodeID, const char* fromName, const char* name, bool notify); + static status_t _LoadPackage(PackageDomain* domain, + const char* name, Package*& _package); + status_t _InitMountType(const char* mountType); status_t _CreateShineThroughDirectory(Directory* parent, const char* name, Directory*& _directory);