diff --git a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp index 31412bd0cc..934f7f766e 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp @@ -161,14 +161,15 @@ struct Volume::DomainDirectoryListener : NotificationListener { virtual void EventOccurred(NotificationService& service, const KMessage* event) { - DomainDirectoryEventJob* job = new(std::nothrow) - DomainDirectoryEventJob(fVolume, fDomain); - if (job == NULL || job->Init(event)) { - delete job; - return; - } - - fVolume->_PushJob(job); +// TODO: Remove! +// DomainDirectoryEventJob* job = new(std::nothrow) +// DomainDirectoryEventJob(fVolume, fDomain); +// if (job == NULL || job->Init(event)) { +// delete job; +// return; +// } +// +// fVolume->_PushJob(job); } private: diff --git a/src/servers/package/Jamfile b/src/servers/package/Jamfile index 099f966092..bc6bc7d7d1 100644 --- a/src/servers/package/Jamfile +++ b/src/servers/package/Jamfile @@ -1,11 +1,12 @@ SubDir HAIKU_TOP src servers package ; UsePrivateSystemHeaders ; -UsePrivateHeaders app package shared ; +UsePrivateHeaders app kernel package shared ; Server package_daemon : DebugSupport.cpp + Package.cpp PackageDaemon.cpp Root.cpp Volume.cpp diff --git a/src/servers/package/Package.cpp b/src/servers/package/Package.cpp new file mode 100644 index 0000000000..c88767ee0d --- /dev/null +++ b/src/servers/package/Package.cpp @@ -0,0 +1,67 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold + */ + + +#include "Package.h" + +#include + +#include + +#include + +#include "DebugSupport.h" + + +Package::Package() + : + fNodeRef(), + fFileName(), + fInfo(), + fActive(false), + fFileNameHashTableNext(NULL), + fNodeRefHashTableNext(NULL) +{ +} + + +Package::~Package() +{ +} + + +status_t +Package::Init(const entry_ref& entryRef) +{ + // init the file name + fFileName = entryRef.name; + if (fFileName.IsEmpty()) + RETURN_ERROR(B_NO_MEMORY); + + // open the file and get the node_ref + BFile file; + status_t error = file.SetTo(&entryRef, B_READ_ONLY); + if (error != B_OK) + RETURN_ERROR(error); + + error = file.GetNodeRef(&fNodeRef); + if (error != B_OK) + RETURN_ERROR(error); + + // get the package info + int fd = file.Dup(); + if (fd < 0) + RETURN_ERROR(error); + FileDescriptorCloser fdCloser(fd); + + error = fInfo.ReadFromPackageFile(fd); + if (error != B_OK) + RETURN_ERROR(error); + + return B_OK; +} diff --git a/src/servers/package/Package.h b/src/servers/package/Package.h new file mode 100644 index 0000000000..b93fed8a2f --- /dev/null +++ b/src/servers/package/Package.h @@ -0,0 +1,113 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold + */ +#ifndef PACKAGE_H +#define PACKAGE_H + + +#include +#include +#include + +#include + + +using namespace BPackageKit; + + +class Package { +public: + Package(); + ~Package(); + + status_t Init(const entry_ref& entryRef); + + const node_ref& NodeRef() const + { return fNodeRef; } + const BString& FileName() const + { return fFileName; } + + const BPackageInfo & Info() const + { return fInfo; } + + bool IsActive() const + { return fActive; } + void SetActive(bool active) + { fActive = active; } + + Package*& FileNameHashTableNext() + { return fFileNameHashTableNext; } + Package*& NodeRefHashTableNext() + { return fNodeRefHashTableNext; } + +private: + node_ref fNodeRef; + BString fFileName; + BPackageInfo fInfo; + bool fActive; + Package* fFileNameHashTableNext; + Package* fNodeRefHashTableNext; +}; + + +struct PackageFileNameHashDefinition { + typedef const char* KeyType; + typedef Package ValueType; + + size_t HashKey(const char* key) const + { + return BString::HashValue(key); + } + + size_t Hash(const Package* value) const + { + return HashKey(value->FileName()); + } + + bool Compare(const char* key, const Package* value) const + { + return value->FileName() == key; + } + + Package*& GetLink(Package* value) const + { + return value->FileNameHashTableNext(); + } +}; + + +struct PackageNodeRefHashDefinition { + typedef node_ref KeyType; + typedef Package ValueType; + + size_t HashKey(const node_ref& key) const + { + return (size_t)key.device + 17 * (size_t)key.node; + } + + size_t Hash(const Package* value) const + { + return HashKey(value->NodeRef()); + } + + bool Compare(const node_ref& key, const Package* value) const + { + return key == value->NodeRef(); + } + + Package*& GetLink(Package* value) const + { + return value->NodeRefHashTableNext(); + } +}; + + +typedef BOpenHashTable PackageFileNameHashTable; +typedef BOpenHashTable PackageNodeRefHashTable; + + +#endif // PACKAGE_H diff --git a/src/servers/package/PackageDaemon.cpp b/src/servers/package/PackageDaemon.cpp index 0942049d0f..8229e4877c 100644 --- a/src/servers/package/PackageDaemon.cpp +++ b/src/servers/package/PackageDaemon.cpp @@ -69,6 +69,7 @@ PackageDaemon::MessageReceived(BMessage* message) int32 opcode; if (message->FindInt32("opcode", &opcode) != B_OK) break; + if (opcode == B_DEVICE_MOUNTED) _HandleVolumeMounted(message); else if (opcode == B_DEVICE_UNMOUNTED) @@ -94,27 +95,14 @@ PackageDaemon::_RegisterVolume(dev_t deviceID) if (strcmp(info.fsh_name, "packagefs") != 0) RETURN_ERROR(B_BAD_VALUE); - // open the root directory of the volume - node_ref nodeRef; - nodeRef.device = info.dev; - nodeRef.node = info.root; - BDirectory directory; - error = directory.SetTo(&nodeRef); - if (error != B_OK) { - ERROR("PackageDaemon::_RegisterVolume(): failed to open root: %s\n", - strerror(error)); - return error; - } - // create a volume Volume* volume = new(std::nothrow) Volume; if (volume == NULL) RETURN_ERROR(B_NO_MEMORY); ObjectDeleter volumeDeleter(volume); - dev_t rootDeviceID; - ino_t rootNodeID; - error = volume->Init(directory, rootDeviceID, rootNodeID); + node_ref rootRef; + error = volume->Init(node_ref(info.dev, info.root), rootRef); if (error != B_OK) RETURN_ERROR(error); @@ -127,7 +115,7 @@ PackageDaemon::_RegisterVolume(dev_t deviceID) // get the root for the volume and register it Root* root; - error = _GetOrCreateRoot(rootDeviceID, rootNodeID, root); + error = _GetOrCreateRoot(rootRef, root); if (error != B_OK) RETURN_ERROR(error); @@ -138,6 +126,19 @@ PackageDaemon::_RegisterVolume(dev_t deviceID) } volumeDeleter.Detach(); + AddHandler(volume); + + // node-monitor the volume's packages directory + error = watch_node(&volume->PackagesDirectoryRef(), B_WATCH_DIRECTORY, + BMessenger(volume, this)); + if (error != B_OK) { + ERROR("PackageDaemon::_RegisterVolume(): failed to start watching the " + "packages directory of the volume at \"%s\": %s\n", + volume->Path().String(), strerror(error)); + // Not good, but not fatal. Only the manual package operations in the + // packages directory won't work correctly. + } + INFORM("volume at \"%s\" registered\n", volume->Path().String()); return B_OK; @@ -147,6 +148,10 @@ PackageDaemon::_RegisterVolume(dev_t deviceID) void PackageDaemon::_UnregisterVolume(Volume* volume) { + stop_watching(BMessenger(volume, this)); + + RemoveHandler(volume); + Root* root = volume->GetRoot(); root->UnregisterVolume(volume); @@ -158,9 +163,9 @@ PackageDaemon::_UnregisterVolume(Volume* volume) status_t -PackageDaemon::_GetOrCreateRoot(dev_t deviceID, ino_t nodeID, Root*& _root) +PackageDaemon::_GetOrCreateRoot(const node_ref& nodeRef, Root*& _root) { - Root* root = _FindRoot(deviceID, nodeID); + Root* root = _FindRoot(nodeRef); if (root != NULL) { root->AcquireReference(); } else { @@ -169,7 +174,7 @@ PackageDaemon::_GetOrCreateRoot(dev_t deviceID, ino_t nodeID, Root*& _root) RETURN_ERROR(B_NO_MEMORY); ObjectDeleter rootDeleter(root); - status_t error = root->Init(deviceID, nodeID); + status_t error = root->Init(nodeRef); if (error != B_OK) RETURN_ERROR(error); @@ -179,7 +184,8 @@ PackageDaemon::_GetOrCreateRoot(dev_t deviceID, ino_t nodeID, Root*& _root) rootDeleter.Detach(); INFORM("root at \"%s\" (device: %" B_PRIdDEV ", node: %" B_PRIdINO ") " - "registered\n", root->Path().String(), deviceID, nodeID); + "registered\n", root->Path().String(), nodeRef.device, + nodeRef.node); } _root = root; @@ -188,10 +194,10 @@ PackageDaemon::_GetOrCreateRoot(dev_t deviceID, ino_t nodeID, Root*& _root) Root* -PackageDaemon::_FindRoot(dev_t deviceID, ino_t nodeID) const +PackageDaemon::_FindRoot(const node_ref& nodeRef) const { for (int32 i = 0; Root* root = fRoots.ItemAt(i); i++) { - if (root->DeviceID() == deviceID && root->NodeID() == nodeID) + if (root->NodeRef() == nodeRef) return root; } diff --git a/src/servers/package/PackageDaemon.h b/src/servers/package/PackageDaemon.h index 86c6f4c2c0..c2ef13ff2a 100644 --- a/src/servers/package/PackageDaemon.h +++ b/src/servers/package/PackageDaemon.h @@ -10,6 +10,7 @@ #include +#include #include #include @@ -36,9 +37,9 @@ private: status_t _RegisterVolume(dev_t device); void _UnregisterVolume(Volume* volume); - status_t _GetOrCreateRoot(dev_t deviceID, ino_t nodeID, + status_t _GetOrCreateRoot(const node_ref& nodeRef, Root*& _root); - Root* _FindRoot(dev_t deviceID, ino_t nodeID) const; + Root* _FindRoot(const node_ref& nodeRef) const; void _PutRoot(Root* root); Volume* _FindVolume(dev_t deviceID) const; diff --git a/src/servers/package/Root.cpp b/src/servers/package/Root.cpp index bf7fec9939..d72a5041ef 100644 --- a/src/servers/package/Root.cpp +++ b/src/servers/package/Root.cpp @@ -19,8 +19,7 @@ Root::Root() : - fDeviceID(-1), - fNodeID(-1), + fNodeRef(), fPath(), fSystemVolume(NULL), fCommonVolume(NULL), @@ -35,17 +34,13 @@ Root::~Root() status_t -Root::Init(dev_t deviceID, ino_t nodeID) +Root::Init(const node_ref& nodeRef) { - fDeviceID = deviceID; - fNodeID = nodeID; + fNodeRef = nodeRef; // get the path - node_ref nodeRef; - nodeRef.device = fDeviceID; - nodeRef.node = fNodeID; BDirectory directory; - status_t error = directory.SetTo(&nodeRef); + status_t error = directory.SetTo(&fNodeRef); if (error != B_OK) { ERROR("Root::Init(): failed to open directory: %s\n", strerror(error)); return error; diff --git a/src/servers/package/Root.h b/src/servers/package/Root.h index 940f99c27f..8afa89cf14 100644 --- a/src/servers/package/Root.h +++ b/src/servers/package/Root.h @@ -9,7 +9,7 @@ #define ROOT_H -#include +#include #include #include @@ -25,12 +25,12 @@ public: Root(); virtual ~Root(); - status_t Init(dev_t deviceID, ino_t nodeID); + status_t Init(const node_ref& nodeRef); - dev_t DeviceID() const { return fDeviceID; } - ino_t NodeID() const { return fNodeID; } - const BString& Path() const - { return fPath; } + const node_ref& NodeRef() const { return fNodeRef; } + dev_t DeviceID() const { return fNodeRef.device; } + ino_t NodeID() const { return fNodeRef.node; } + const BString& Path() const { return fPath; } status_t RegisterVolume(Volume* volume); void UnregisterVolume(Volume* volume); @@ -44,8 +44,7 @@ private: Volume** _GetVolume(PackageFSMountType mountType); private: - dev_t fDeviceID; - ino_t fNodeID; + node_ref fNodeRef; BString fPath; Volume* fSystemVolume; Volume* fCommonVolume; diff --git a/src/servers/package/Volume.cpp b/src/servers/package/Volume.cpp index 4d17279fc0..526a7ed2bf 100644 --- a/src/servers/package/Volume.cpp +++ b/src/servers/package/Volume.cpp @@ -10,38 +10,67 @@ #include "Volume.h" #include +#include #include #include #include #include +#include #include +#include + #include "DebugSupport.h" Volume::Volume() : + BHandler(), fPath(), fMountType(PACKAGE_FS_MOUNT_TYPE_CUSTOM), - fDeviceID(-1), - fRootDirectoryID(1), - fRoot(NULL) + fRootDirectoryRef(), + fPackagesDirectoryRef(), + fRoot(NULL), + fPackagesByFileName(), + fPackagesByNodeRef() { } Volume::~Volume() { + fPackagesByFileName.Clear(); + + Package* package = fPackagesByNodeRef.Clear(true); + while (package != NULL) { + Package* next = package->NodeRefHashTableNext(); + delete package; + package = next; + } } status_t -Volume::Init(BDirectory& directory, dev_t& _rootDeviceID, ino_t& _rootNodeID) +Volume::Init(const node_ref& rootDirectoryRef, node_ref& _packageRootRef) { + if (fPackagesByFileName.Init() != B_OK || fPackagesByNodeRef.Init() != B_OK) + RETURN_ERROR(B_NO_MEMORY); + + fRootDirectoryRef = rootDirectoryRef; + + // open the root directory + BDirectory directory; + status_t error = directory.SetTo(&fRootDirectoryRef); + if (error != B_OK) { + ERROR("Volume::Init(): failed to open root directory: %s\n", + strerror(error)); + RETURN_ERROR(error); + } + // get the directory path BEntry entry; - status_t error = directory.GetEntry(&entry); + error = directory.GetEntry(&entry); BPath path; if (error == B_OK) @@ -57,18 +86,6 @@ Volume::Init(BDirectory& directory, dev_t& _rootDeviceID, ino_t& _rootNodeID) if (fPath.IsEmpty()) RETURN_ERROR(B_NO_MEMORY); - // stat() the directory - struct stat st; - error = directory.GetStat(&st); - if (error != B_OK) { - ERROR("Volume::Init(): failed to stat root directory: %s\n", - strerror(error)); - RETURN_ERROR(error); - } - - fDeviceID = st.st_dev; - fRootDirectoryID = st.st_ino; - // get a volume info from the FS int fd = directory.Dup(); if (fd < 0) { @@ -76,24 +93,347 @@ Volume::Init(BDirectory& directory, dev_t& _rootDeviceID, ino_t& _rootNodeID) strerror(fd)); RETURN_ERROR(fd); } + FileDescriptorCloser fdCloser(fd); PackageFSVolumeInfo info; if (ioctl(fd, PACKAGE_FS_OPERATION_GET_VOLUME_INFO, &info, sizeof(info)) != 0) { - error = errno; - close(fd); - if (error != B_OK) { - ERROR("Volume::Init(): failed to get volume info: %s\n", - strerror(error)); - RETURN_ERROR(error); - } + ERROR("Volume::Init(): failed to get volume info: %s\n", + strerror(errno)); + RETURN_ERROR(errno); } - close(fd); - fMountType = info.mountType; - _rootDeviceID = info.rootDeviceID; - _rootNodeID = info.rootDirectoryID; + fPackagesDirectoryRef.device = info.packagesDeviceID; + fPackagesDirectoryRef.node = info.packagesDirectoryID; + + // read in all packages in the directory + error = _ReadPackagesDirectory(); + if (error != B_OK) + RETURN_ERROR(error); + + _GetActivePackages(fd); + + _packageRootRef.device = info.rootDeviceID; + _packageRootRef.node = info.rootDirectoryID; + + return B_OK; +} + +void +Volume::MessageReceived(BMessage* message) +{ + switch (message->what) { + case B_NODE_MONITOR: + { + int32 opcode; + if (message->FindInt32("opcode", &opcode) != B_OK) + break; + + switch (opcode) { + case B_ENTRY_CREATED: + _HandleEntryCreatedOrRemoved(message, true); + break; + case B_ENTRY_REMOVED: + _HandleEntryCreatedOrRemoved(message, false); + break; + case B_ENTRY_MOVED: + _HandleEntryMoved(message); + break; + default: + break; + } + break; + } + + default: + BHandler::MessageReceived(message); + break; + } +} + + +int +Volume::OpenRootDirectory() const +{ + BDirectory directory; + status_t error = directory.SetTo(&fRootDirectoryRef); + if (error != B_OK) { + ERROR("Volume::OpenRootDirectory(): failed to open root directory: " + "%s\n", strerror(error)); + RETURN_ERROR(error); + } + + return directory.Dup(); +} + + +void +Volume::_HandleEntryCreatedOrRemoved(const BMessage* message, bool created) +{ + // only moves to or from our packages directory are interesting + int32 deviceID; + int64 directoryID; + const char* name; + if (message->FindInt32("device", &deviceID) != B_OK + || message->FindInt64("directory", &directoryID) != B_OK + || message->FindString("name", &name) != B_OK + || node_ref(deviceID, directoryID) != fPackagesDirectoryRef) { + return; + } + + if (created) + _PackagesEntryCreated(name); + else + _PackagesEntryRemoved(name); +} + + +void +Volume::_HandleEntryMoved(const BMessage* message) +{ + int32 deviceID; + int64 fromDirectoryID; + int64 toDirectoryID; + const char* fromName; + const char* toName; + if (message->FindInt32("device", &deviceID) != B_OK + || message->FindInt64("from directory", &fromDirectoryID) != B_OK + || message->FindInt64("to directory", &toDirectoryID) != B_OK + || message->FindString("from name", &fromName) != B_OK + || message->FindString("name", &toName) != B_OK + || deviceID != fPackagesDirectoryRef.device + || (fromDirectoryID != fPackagesDirectoryRef.node + && toDirectoryID != fPackagesDirectoryRef.node)) { + return; + } + + if (fromDirectoryID == fPackagesDirectoryRef.node) + _PackagesEntryRemoved(fromName); + if (toDirectoryID == fPackagesDirectoryRef.node) + _PackagesEntryCreated(toName); +} + + +void +Volume::_PackagesEntryCreated(const char* name) +{ +INFORM("Volume::_PackagesEntryCreated(\"%s\")\n", name); + entry_ref entry; + entry.device = fPackagesDirectoryRef.device; + entry.directory = fPackagesDirectoryRef.node; + status_t error = entry.set_name(name); + if (error != B_OK) { + ERROR("out of memory"); + return; + } + + Package* package = new(std::nothrow) Package; + if (package == NULL) { + ERROR("out of memory"); + return; + } + ObjectDeleter packageDeleter(package); + + error = package->Init(entry); + if (error != B_OK) { + ERROR("failed to init package for file \"%s\"\n", name); + return; + } + + fPackagesByFileName.Insert(package); + fPackagesByNodeRef.Insert(package); + packageDeleter.Detach(); + + // activate package +// TODO: Don't do that here! + size_t nameLength = strlen(package->FileName()); + size_t requestSize = sizeof(PackageFSActivationChangeRequest) + nameLength; + PackageFSActivationChangeRequest* request + = (PackageFSActivationChangeRequest*)malloc(requestSize); + if (request == NULL) { + ERROR("out of memory"); + return; + } + MemoryDeleter requestDeleter(request); + + request->itemCount = 1; + PackageFSActivationChangeItem& item = request->items[0]; + item.type = PACKAGE_FS_ACTIVATE_PACKAGE; + + item.packageDeviceID = package->NodeRef().device; + item.packageNodeID = package->NodeRef().node; + + item.nameLength = nameLength; + item.parentDeviceID = fPackagesDirectoryRef.device; + item.parentDirectoryID = fPackagesDirectoryRef.node; + strcpy(item.name, package->FileName()); + + int fd = OpenRootDirectory(); + if (fd < 0) { + ERROR("Volume::_PackagesEntryCreated(): failed to open root directory: " + "%s", strerror(fd)); + return; + } + FileDescriptorCloser fdCloser(fd); + + if (ioctl(fd, PACKAGE_FS_OPERATION_CHANGE_ACTIVATION, request, requestSize) + != 0) { + ERROR("Volume::_PackagesEntryCreated(): activate packages: %s\n", + strerror(errno)); + return; + } + + package->SetActive(true); +} + + +void +Volume::_PackagesEntryRemoved(const char* name) +{ +INFORM("Volume::_PackagesEntryRemoved(\"%s\")\n", name); + Package* package = fPackagesByFileName.Lookup(name); + if (package == NULL) + return; + + if (package->IsActive()) { + // deactivate the package +// TODO: Don't do that here! + size_t nameLength = strlen(package->FileName()); + size_t requestSize = sizeof(PackageFSActivationChangeRequest) + + nameLength; + PackageFSActivationChangeRequest* request + = (PackageFSActivationChangeRequest*)malloc(requestSize); + if (request == NULL) { + ERROR("out of memory"); + return; + } + MemoryDeleter requestDeleter(request); + + request->itemCount = 1; + PackageFSActivationChangeItem& item = request->items[0]; + item.type = PACKAGE_FS_DEACTIVATE_PACKAGE; + + item.packageDeviceID = package->NodeRef().device; + item.packageNodeID = package->NodeRef().node; + + item.nameLength = nameLength; + item.parentDeviceID = fPackagesDirectoryRef.device; + item.parentDirectoryID = fPackagesDirectoryRef.node; + strcpy(item.name, package->FileName()); + + int fd = OpenRootDirectory(); + if (fd < 0) { + ERROR("Volume::_PackagesEntryRemoved(): failed to open root " + "directory: %s", strerror(fd)); + return; + } + FileDescriptorCloser fdCloser(fd); + + if (ioctl(fd, PACKAGE_FS_OPERATION_CHANGE_ACTIVATION, request, + requestSize) != 0) { + ERROR("Volume::_PackagesEntryRemoved(): activate packages: %s\n", + strerror(errno)); + return; + } + } + + fPackagesByFileName.Remove(package); + fPackagesByNodeRef.Remove(package); + delete package; +} + + +status_t +Volume::_ReadPackagesDirectory() +{ + BDirectory directory; + status_t error = directory.SetTo(&fPackagesDirectoryRef); + if (error != B_OK) { + ERROR("Volume::_ReadPackagesDirectory(): open packages directory: %s\n", + strerror(error)); + RETURN_ERROR(error); + } + + entry_ref entry; + while (directory.GetNextRef(&entry) == B_OK) { + Package* package = new(std::nothrow) Package; + if (package == NULL) + RETURN_ERROR(B_NO_MEMORY); + ObjectDeleter packageDeleter(package); + + status_t error = package->Init(entry); + if (error == B_OK) { + fPackagesByFileName.Insert(package); + fPackagesByNodeRef.Insert(package); + packageDeleter.Detach(); + } + } + + return B_OK; +} + + +status_t +Volume::_GetActivePackages(int fd) +{ + uint32 maxPackageCount = 16 * 1024; + PackageFSGetPackageInfosRequest* request = NULL; + MemoryDeleter requestDeleter; + size_t bufferSize; + for (;;) { + bufferSize = sizeof(PackageFSGetPackageInfosRequest) + + (maxPackageCount - 1) * sizeof(PackageFSPackageInfo); + request = (PackageFSGetPackageInfosRequest*)malloc(bufferSize); + if (request == NULL) + RETURN_ERROR(B_NO_MEMORY); + requestDeleter.SetTo(request); + + if (ioctl(fd, PACKAGE_FS_OPERATION_GET_PACKAGE_INFOS, request, + bufferSize) != 0) { + ERROR("Volume::_GetActivePackages(): failed to get active package " + "info from package FS: %s\n", strerror(errno)); + RETURN_ERROR(errno); + } + + if (request->packageCount <= maxPackageCount) + break; + + maxPackageCount = request->packageCount; + requestDeleter.Unset(); + } + + // mark the returned packages active + for (uint32 i = 0; i < request->packageCount; i++) { + Package* package = fPackagesByNodeRef.Lookup( + node_ref(request->infos[i].packageDeviceID, + request->infos[i].packageNodeID)); + if (package == NULL) { + WARN("active package (dev: %" B_PRIdDEV ", node: %" B_PRIdINO ") " + "not found in package directory\n", + request->infos[i].packageDeviceID, + request->infos[i].packageNodeID); +// TODO: Deactivate the package right away? + continue; + } + + package->SetActive(true); +INFORM("active package: \"%s\"\n", package->FileName().String()); + } + +for (PackageNodeRefHashTable::Iterator it = fPackagesByNodeRef.GetIterator(); + it.HasNext();) { + Package* package = it.Next(); + if (!package->IsActive()) + INFORM("inactive package: \"%s\"\n", package->FileName().String()); +} + + PackageNodeRefHashTable fPackagesByNodeRef; +// INFORM("%" B_PRIu32 " active packages:\n", request->packageCount); +// for (uint32 i = 0; i < request->packageCount; i++) { +// INFORM(" dev: %" B_PRIdDEV ", node: %" B_PRIdINO "\n", +// request->infos[i].packageDeviceID, request->infos[i].packageNodeID); +// } return B_OK; } diff --git a/src/servers/package/Volume.h b/src/servers/package/Volume.h index aa90a29716..4dc5450d2f 100644 --- a/src/servers/package/Volume.h +++ b/src/servers/package/Volume.h @@ -9,47 +9,75 @@ #define VOLUME_H -#include +#include #include #include +#include "Package.h" + class BDirectory; class Root; -class Volume { +class Volume : public BHandler { public: Volume(); - ~Volume(); + virtual ~Volume(); - status_t Init(BDirectory& directory, - dev_t& _rootDeviceID, ino_t& _rootNodeID); + status_t Init(const node_ref& rootDirectoryRef, + node_ref& _packageRootRef); + + virtual void MessageReceived(BMessage* message); const BString& Path() const { return fPath; } PackageFSMountType MountType() const { return fMountType; } + + const node_ref& RootDirectoryRef() const + { return fRootDirectoryRef; } dev_t DeviceID() const - { return fDeviceID; } + { return fRootDirectoryRef.device; } ino_t RootDirectoryID() const - { return fRootDirectoryID; } + { return fRootDirectoryRef.node; } + + const node_ref& PackagesDirectoryRef() const + { return fPackagesDirectoryRef; } + dev_t PackagesDeviceID() const + { return fPackagesDirectoryRef.device; } + ino_t PackagesDirectoryID() const + { return fPackagesDirectoryRef.node; } Root* GetRoot() const { return fRoot; } void SetRoot(Root* root) { fRoot = root; } + int OpenRootDirectory() const; + +private: + void _HandleEntryCreatedOrRemoved( + const BMessage* message, bool created); + void _HandleEntryMoved(const BMessage* message); + + void _PackagesEntryCreated(const char* name); + void _PackagesEntryRemoved(const char* name); + + status_t _ReadPackagesDirectory(); + status_t _GetActivePackages(int fd); + private: BString fPath; PackageFSMountType fMountType; - dev_t fDeviceID; - ino_t fRootDirectoryID; + node_ref fRootDirectoryRef; + node_ref fPackagesDirectoryRef; Root* fRoot; + PackageFileNameHashTable fPackagesByFileName; + PackageNodeRefHashTable fPackagesByNodeRef; }; - #endif // VOLUME_H