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.
This commit is contained in:
Ingo Weinhold
2013-04-11 02:03:25 +02:00
parent b254217a09
commit 62f7022a82
7 changed files with 201 additions and 40 deletions
@@ -0,0 +1,37 @@
/*
* Copyright 2013, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
*/
#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
+24 -37
View File
@@ -14,6 +14,7 @@
#include <Directory.h>
#include <Entry.h>
#include <Messenger.h>
#include <Path.h>
#include <String.h>
#include <StringList.h>
@@ -26,6 +27,10 @@
#include <package/hpkg/PackageReader.h>
#if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU)
# include <package/PackageDaemonDefs.h>
#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)
+20 -2
View File
@@ -16,15 +16,19 @@
#include <NodeMonitor.h>
#include <AutoDeleter.h>
#include <package/PackageDaemonDefs.h>
#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;
+87 -1
View File
@@ -11,8 +11,12 @@
#include <Directory.h>
#include <Entry.h>
#include <package/PackageDefs.h>
#include <Path.h>
#include <AutoDeleter.h>
#include <AutoLocker.h>
#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<BMessage> 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<BLocker> 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<BLocker> 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<BLocker> 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<BLocker> 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<BLocker> 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)
{
+8
View File
@@ -9,6 +9,7 @@
#define ROOT_H
#include <Locker.h>
#include <Node.h>
#include <ObjectList.h>
#include <OS.h>
@@ -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;
+24
View File
@@ -30,11 +30,15 @@
#include <AutoDeleter.h>
#include <AutoLocker.h>
#include <package/PackageDaemonDefs.h>
#include <package/PackagesDirectoryDefs.h>
#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()
{
+1
View File
@@ -48,6 +48,7 @@ public:
bool activeOnly);
void InitialVerify(Volume* nextVolume,
Volume* nextNextVolume);
void HandleGetPackagesRequest(BMessage* message);
void Unmounted();