From 62f7022a8294bbd5407826c0bb8b071975ed90d5 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Thu, 11 Apr 2013 02:03:25 +0200 Subject: [PATCH] package kit: get active packages list from daemon * daemon: Implement private message protocol to retrieve the active packages. * BPackageRoster::GetActivePackages(): Get the active packages list from the daemon. --- headers/private/package/PackageDaemonDefs.h | 37 +++++++++ src/kits/package/PackageRoster.cpp | 61 ++++++-------- src/servers/package/PackageDaemon.cpp | 22 +++++- src/servers/package/Root.cpp | 88 ++++++++++++++++++++- src/servers/package/Root.h | 8 ++ src/servers/package/Volume.cpp | 24 ++++++ src/servers/package/Volume.h | 1 + 7 files changed, 201 insertions(+), 40 deletions(-) create mode 100644 headers/private/package/PackageDaemonDefs.h diff --git a/headers/private/package/PackageDaemonDefs.h b/headers/private/package/PackageDaemonDefs.h new file mode 100644 index 0000000000..ccb74b7df6 --- /dev/null +++ b/headers/private/package/PackageDaemonDefs.h @@ -0,0 +1,37 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold + */ +#ifndef _PACKAGE__PRIVATE__PACKAGE_DAEMON_DEFS_H_ +#define _PACKAGE__PRIVATE__PACKAGE_DAEMON_DEFS_H_ + + +namespace BPackageKit { +namespace BPrivate { + + +#define PACKAGE_DAEMON_APP_SIGNATURE "application/x-vnd.haiku-package_daemon" + + +// message codes for requests to and replies from the daemon +enum { + MESSAGE_GET_PACKAGES = 'PKGG', + // "location": int32 + // the respective installation location constant + MESSAGE_GET_PACKAGES_REPLY = 'PKGR' + // "active packages": string[] + // file names of the active packages (no path) + // "inactive packages": string[] + // file names of the inactive packages (no path) + +}; + + +#endif // _PACKAGE__PRIVATE__PACKAGE_DAEMON_DEFS_H_ + + +} // namespace BPrivate +} // namespace BPackageKit diff --git a/src/kits/package/PackageRoster.cpp b/src/kits/package/PackageRoster.cpp index 5ee0451718..62b4bb90ad 100644 --- a/src/kits/package/PackageRoster.cpp +++ b/src/kits/package/PackageRoster.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -26,6 +27,10 @@ #include +#if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU) +# include +#endif + namespace BPackageKit { @@ -206,63 +211,45 @@ BPackageRoster::GetActivePackages(BPackageInstallationLocation location, return B_BAD_VALUE; } - // find the package links directory - BPath packageLinksPath; - status_t error = find_directory(B_PACKAGE_LINKS_DIRECTORY, - &packageLinksPath); + // get the package daemon's address + status_t error; + BMessenger messenger(PACKAGE_DAEMON_APP_SIGNATURE, -1, &error); if (error != B_OK) return error; + // request a list of packages + BMessage request(BPackageKit::BPrivate::MESSAGE_GET_PACKAGES); + error = request.AddInt32("location", location); + if (error != B_OK) + return error; + + BMessage reply; + messenger.SendMessage(&request, &reply); + if (reply.what != BPackageKit::BPrivate::MESSAGE_GET_PACKAGES_REPLY) + return B_ERROR; + // find and open the packages directory BPath packagesDirPath; error = find_directory(packagesDirectory, &packagesDirPath); if (error != B_OK) return error; - BDirectory directory; - error = directory.SetTo(packagesDirPath.Path()); - if (error != B_OK) - return error; - - // TODO: Implement that correctly be reading the activation files/directory! - // iterate through the packages - char buffer[sizeof(dirent) + B_FILE_NAME_LENGTH]; - dirent* entry = (dirent*)&buffer; - while (directory.GetNextDirents(entry, sizeof(buffer), 1) == 1) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - + const char* packageFileName; + for (int32 i = 0; + reply.FindString("active packages", i, &packageFileName) == B_OK; i++) { // get the full package file path BPath packagePath; - error = packagePath.SetTo(packagesDirPath.Path(), entry->d_name); + error = packagePath.SetTo(packagesDirPath.Path(), packageFileName); if (error != B_OK) continue; // read the package info from the file - BPackageReader packageReader(NULL); - error = packageReader.Init(packagePath.Path()); - if (error != B_OK) - continue; - BPackageInfo info; - BPackageInfoContentHandler handler(info); - error = packageReader.ParseContent(&handler); + error = info.ReadFromPackageFile(packagePath.Path()); if (error != B_OK || info.InitCheck() != B_OK) continue; - // check whether the package is really active by verifying that a - // package link exists for it - BString packageLinkName(info.Name()); - packageLinkName << '-' << info.Version().ToString(); - BPath packageLinkPath; - struct stat st; - if (packageLinkPath.SetTo(packageLinksPath.Path(), packageLinkName) - != B_OK - || lstat(packageLinkPath.Path(), &st) != 0) { - continue; - } - // add the info error = packageInfos.AddInfo(info); if (error != B_OK) diff --git a/src/servers/package/PackageDaemon.cpp b/src/servers/package/PackageDaemon.cpp index 4380102f5c..e5ebee0515 100644 --- a/src/servers/package/PackageDaemon.cpp +++ b/src/servers/package/PackageDaemon.cpp @@ -16,15 +16,19 @@ #include #include +#include #include "DebugSupport.h" #include "Root.h" #include "Volume.h" +using namespace BPackageKit::BPrivate; + + PackageDaemon::PackageDaemon(status_t* _error) : - BServer("application/x-vnd.haiku-package_daemon", false, _error), + BServer(PACKAGE_DAEMON_APP_SIGNATURE, false, _error), fSystemRoot(NULL), fRoots(10, true), fVolumeWatcher() @@ -34,7 +38,6 @@ PackageDaemon::PackageDaemon(status_t* _error) PackageDaemon::~PackageDaemon() { -// delete fSystemRoot; } @@ -56,6 +59,11 @@ PackageDaemon::Init() _RegisterVolume(device); } + // find the system root + struct stat st; + if (stat("/boot", &st) == 0) + fSystemRoot = _FindRoot(node_ref(st.st_dev, st.st_ino)); + return B_OK; } @@ -76,6 +84,16 @@ PackageDaemon::MessageReceived(BMessage* message) _HandleVolumeUnmounted(message); break; } + + case MESSAGE_GET_PACKAGES: + { + if (fSystemRoot == NULL) + break; + + fSystemRoot->HandleGetPackagesRequest(DetachCurrentMessage()); + break; + } + default: BServer::MessageReceived(message); break; diff --git a/src/servers/package/Root.cpp b/src/servers/package/Root.cpp index 012f5d0276..b2d63b4bf5 100644 --- a/src/servers/package/Root.cpp +++ b/src/servers/package/Root.cpp @@ -11,8 +11,12 @@ #include #include +#include #include +#include +#include + #include "DebugSupport.h" @@ -38,11 +42,34 @@ private: }; +// #pragma mark - VolumeJob + + +struct Root::HandleGetPackagesJob : public Job { + HandleGetPackagesJob(Root* root, BMessage* message) + : + fRoot(root), + fMessage(message) + { + } + + virtual void Do() + { + fRoot->_HandleGetPackagesRequest(fMessage.Get()); + } + +private: + Root* fRoot; + ObjectDeleter fMessage; +}; + + // #pragma mark - Root Root::Root() : + fLock("packagefs root"), fNodeRef(), fPath(), fSystemVolume(NULL), @@ -68,11 +95,15 @@ Root::Init(const node_ref& nodeRef) { fNodeRef = nodeRef; - // init job queue and spawn job runner thread + // init members and spawn job runner thread status_t error = fJobQueue.Init(); if (error != B_OK) RETURN_ERROR(error); + error = fLock.InitCheck(); + if (error != B_OK) + RETURN_ERROR(error); + fJobRunner = spawn_thread(&_JobRunnerEntry, "job runner", B_NORMAL_PRIORITY, this); if (fJobRunner < 0) @@ -112,6 +143,8 @@ Root::Init(const node_ref& nodeRef) status_t Root::RegisterVolume(Volume* volume) { + AutoLocker locker(fLock); + Volume** volumeToSet = _GetVolume(volume->MountType()); if (volumeToSet == NULL) return B_BAD_VALUE; @@ -142,6 +175,8 @@ Root::RegisterVolume(Volume* volume) void Root::UnregisterVolume(Volume* volume) { + AutoLocker locker(fLock); + Volume** volumeToSet = _GetVolume(volume->MountType()); if (volumeToSet == NULL || *volumeToSet != volume) { ERROR("Root::UnregisterVolume(): can't unregister unknown volume at " @@ -160,6 +195,8 @@ Root::UnregisterVolume(Volume* volume) Volume* Root::FindVolume(dev_t deviceID) const { + AutoLocker locker(fLock); + Volume* volumes[] = { fSystemVolume, fCommonVolume, fHomeVolume }; for (size_t i = 0; i < sizeof(volumes) / sizeof(volumes[0]); i++) { Volume* volume = volumes[i]; @@ -171,6 +208,20 @@ Root::FindVolume(dev_t deviceID) const } +void +Root::HandleGetPackagesRequest(BMessage* message) +{ + HandleGetPackagesJob* job + = new(std::nothrow) HandleGetPackagesJob(this, message); + if (job == NULL) { + delete message; + return; + } + + _QueueJob(job); +} + + void Root::VolumeNodeMonitorEventOccurred(Volume* volume) { @@ -235,8 +286,11 @@ void Root::_InitPackages(Volume* volume) { if (volume->InitPackages(this) == B_OK) { + AutoLocker locker(fLock); Volume* nextVolume = _NextVolumeFor(volume); Volume* nextNextVolume = _NextVolumeFor(nextVolume); + locker.Unlock(); + volume->InitialVerify(nextVolume, nextNextVolume); } } @@ -259,6 +313,38 @@ Root::_ProcessNodeMonitorEvents(Volume* volume) } +void +Root::_HandleGetPackagesRequest(BMessage* message) +{ + int32 location; + if (message->FindInt32("location", &location) != B_OK + || location < 0 + || location >= B_PACKAGE_INSTALLATION_LOCATION_ENUM_COUNT) { + return; + } + + // get the volume and let it handle the message + AutoLocker locker(fLock); + Volume* volume; + switch ((BPackageInstallationLocation)location) { + case B_PACKAGE_INSTALLATION_LOCATION_SYSTEM: + volume = fSystemVolume; + break; + case B_PACKAGE_INSTALLATION_LOCATION_COMMON: + volume = fCommonVolume; + break; + case B_PACKAGE_INSTALLATION_LOCATION_HOME: + volume = fHomeVolume; + break; + default: + return; + } + + if (volume != NULL) + volume->HandleGetPackagesRequest(message); +} + + status_t Root::_QueueJob(Job* job) { diff --git a/src/servers/package/Root.h b/src/servers/package/Root.h index d4fb807ddd..ad84421aa9 100644 --- a/src/servers/package/Root.h +++ b/src/servers/package/Root.h @@ -9,6 +9,7 @@ #define ROOT_H +#include #include #include #include @@ -40,6 +41,8 @@ public: Volume* FindVolume(dev_t deviceID) const; + void HandleGetPackagesRequest(BMessage* message); + private: // Volume::Listener virtual void VolumeNodeMonitorEventOccurred(Volume* volume); @@ -49,6 +52,9 @@ protected: private: struct VolumeJob; + struct HandleGetPackagesJob; + + friend struct HandleGetPackagesJob; private: Volume** _GetVolume(PackageFSMountType mountType); @@ -57,6 +63,7 @@ private: void _InitPackages(Volume* volume); void _DeleteVolume(Volume* volume); void _ProcessNodeMonitorEvents(Volume* volume); + void _HandleGetPackagesRequest(BMessage* message); status_t _QueueJob(Job* job); @@ -64,6 +71,7 @@ private: status_t _JobRunner(); private: + mutable BLocker fLock; node_ref fNodeRef; BString fPath; Volume* fSystemVolume; diff --git a/src/servers/package/Volume.cpp b/src/servers/package/Volume.cpp index 697b122411..e4f75d15dc 100644 --- a/src/servers/package/Volume.cpp +++ b/src/servers/package/Volume.cpp @@ -30,11 +30,15 @@ #include #include +#include #include #include "DebugSupport.h" +using namespace BPackageKit::BPrivate; + + static const char* const kPackageFileNameExtension = ".hpkg"; static const char* const kConfigDirectoryName = PACKAGES_DIRECTORY_CONFIG_DIRECTORY; @@ -43,6 +47,8 @@ static const char* const kActivationFileName static const char* const kTemporaryActivationFileName = PACKAGES_DIRECTORY_ACTIVATION_FILE ".tmp"; +static bigtime_t kCommunicationTimeout = 1000000; + // #pragma mark - Listener @@ -328,6 +334,24 @@ INFORM("Volume::InitialVerify(%p, %p)\n", nextVolume, nextNextVolume); } +void +Volume::HandleGetPackagesRequest(BMessage* message) +{ + BMessage reply(MESSAGE_GET_PACKAGES_REPLY); + + for (PackageFileNameHashTable::Iterator it + = fPackagesByFileName.GetIterator(); it.HasNext();) { + Package* package = it.Next(); + const char* fieldName = package->IsActive() + ? "active packages" : "inactive packages"; + if (reply.AddString(fieldName, package->FileName()) != B_OK) + return; + } + + message->SendReply(&reply, (BHandler*)NULL, kCommunicationTimeout); +} + + void Volume::Unmounted() { diff --git a/src/servers/package/Volume.h b/src/servers/package/Volume.h index 2b5f2ce281..404f6c4a57 100644 --- a/src/servers/package/Volume.h +++ b/src/servers/package/Volume.h @@ -48,6 +48,7 @@ public: bool activeOnly); void InitialVerify(Volume* nextVolume, Volume* nextNextVolume); + void HandleGetPackagesRequest(BMessage* message); void Unmounted();