From c8dd5bbd9427cd219a880b00c6f077888a3df6ce Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Tue, 22 Apr 2014 20:54:00 +0200 Subject: [PATCH] package daemon: Retrieve all package directories from packagefs --- src/servers/package/Volume.cpp | 153 +++++++++++++++++++++++++-------- src/servers/package/Volume.h | 11 +-- 2 files changed, 124 insertions(+), 40 deletions(-) diff --git a/src/servers/package/Volume.cpp b/src/servers/package/Volume.cpp index 248d458fa9..1ebffe6919 100644 --- a/src/servers/package/Volume.cpp +++ b/src/servers/package/Volume.cpp @@ -32,6 +32,7 @@ #include #include +#include #include #include "CommitTransactionHandler.h" @@ -81,6 +82,52 @@ private: }; +// #pragma mark - PackagesDirectory + + +struct Volume::PackagesDirectory { +public: + PackagesDirectory() + : + fNodeRef(), + fName() + { + } + + void Init(const node_ref& nodeRef, bool isPackagesDir) + { + fNodeRef = nodeRef; + + if (isPackagesDir) + return; + + BDirectory directory; + BEntry entry; + if (directory.SetTo(&fNodeRef) == B_OK + && directory.GetEntry(&entry) == B_OK) { + fName = entry.Name(); + } + + if (fName.IsEmpty()) + fName = "unknown state"; + } + + const node_ref& NodeRef() const + { + return fNodeRef; + } + + const BString& Name() const + { + return fName; + } + +private: + node_ref fNodeRef; + BString fName; +}; + + // #pragma mark - Volume @@ -90,7 +137,8 @@ Volume::Volume(BLooper* looper) fPath(), fMountType(PACKAGE_FS_MOUNT_TYPE_CUSTOM), fRootDirectoryRef(), - fPackagesDirectoryRef(), + fPackagesDirectories(NULL), + fPackagesDirectoryCount(0), fRoot(NULL), fListener(NULL), fState(NULL), @@ -111,6 +159,7 @@ Volume::~Volume() Unmounted(); // need for error case in InitPackages() + delete fPackagesDirectories; delete fState; } @@ -160,21 +209,56 @@ Volume::Init(const node_ref& rootDirectoryRef, node_ref& _packageRootRef) } FileDescriptorCloser fdCloser(fd); - PackageFSVolumeInfo info; - if (ioctl(fd, PACKAGE_FS_OPERATION_GET_VOLUME_INFO, &info, sizeof(info)) - != 0) { - ERROR("Volume::Init(): failed to get volume info: %s\n", - strerror(errno)); - RETURN_ERROR(errno); + // get the volume info from packagefs + uint32 maxPackagesDirCount = 16; + PackageFSVolumeInfo* info = NULL; + MemoryDeleter infoDeleter; + size_t bufferSize; + for (;;) { + bufferSize = sizeof(PackageFSVolumeInfo) + + (maxPackagesDirCount - 1) * sizeof(PackageFSDirectoryInfo); + info = (PackageFSVolumeInfo*)malloc(bufferSize); + if (info == NULL) + RETURN_ERROR(B_NO_MEMORY); + infoDeleter.SetTo(info); + + if (ioctl(fd, PACKAGE_FS_OPERATION_GET_VOLUME_INFO, info, + bufferSize) != 0) { + ERROR("Volume::Init(): failed to get volume info: %s\n", + strerror(errno)); + RETURN_ERROR(errno); + } + + if (info->packagesDirectoryCount <= maxPackagesDirCount) + break; + + maxPackagesDirCount = info->packagesDirectoryCount; + infoDeleter.Unset(); } - fMountType = info.mountType; - fPackagesDirectoryRef.device = info.packagesDirectoryInfos[0].deviceID; - fPackagesDirectoryRef.node = info.packagesDirectoryInfos[0].nodeID; -// TODO: Adjust for old state support! + if (info->packagesDirectoryCount < 1) { + ERROR("Volume::Init(): got invalid volume info from packagefs\n"); + RETURN_ERROR(B_BAD_VALUE); + } - _packageRootRef.device = info.rootDeviceID; - _packageRootRef.node = info.rootDirectoryID; + fMountType = info->mountType; + + fPackagesDirectories = new(std::nothrow) PackagesDirectory[ + info->packagesDirectoryCount]; + if (fPackagesDirectories == NULL) + RETURN_ERROR(B_NO_MEMORY); + + fPackagesDirectoryCount = info->packagesDirectoryCount; + + for (uint32 i = 0; i < info->packagesDirectoryCount; i++) { + fPackagesDirectories[i].Init( + node_ref(info->packagesDirectoryInfos[i].deviceID, + info->packagesDirectoryInfos[i].nodeID), + i == 0); + } + + _packageRootRef.device = info->rootDeviceID; + _packageRootRef.node = info->rootDirectoryID; return B_OK; } @@ -184,7 +268,7 @@ status_t Volume::InitPackages(Listener* listener) { // node-monitor the volume's packages directory - status_t error = watch_node(&fPackagesDirectoryRef, B_WATCH_DIRECTORY, + status_t error = watch_node(&PackagesDirectoryRef(), B_WATCH_DIRECTORY, BMessenger(this)); if (error == B_OK) { fListener = listener; @@ -215,7 +299,7 @@ Volume::InitPackages(Listener* listener) // create the admin directory, if it doesn't exist yet BDirectory packagesDirectory; - if (packagesDirectory.SetTo(&fPackagesDirectoryRef) == B_OK) { + if (packagesDirectory.SetTo(&PackagesDirectoryRef()) == B_OK) { if (!BEntry(&packagesDirectory, kAdminDirectoryName).Exists()) packagesDirectory.CreateDirectory(kAdminDirectoryName, NULL); } @@ -355,9 +439,9 @@ Volume::HandleGetLocationInfoRequest(BMessage* message) || fLocationInfoReply.AddInt64("base directory node", fRootDirectoryRef.node) != B_OK || fLocationInfoReply.AddInt32("packages directory device", - fPackagesDirectoryRef.device) != B_OK + PackagesDeviceID()) != B_OK || fLocationInfoReply.AddInt64("packages directory node", - fPackagesDirectoryRef.node) != B_OK) { + PackagesDirectoryID()) != B_OK) { return; } @@ -512,6 +596,13 @@ Volume::Location() const } +const node_ref& +Volume::PackagesDirectoryRef() const +{ + return fPackagesDirectories[0].NodeRef(); +} + + PackageFileNameHashTable::Iterator Volume::PackagesByFileNameIterator() const { @@ -687,7 +778,7 @@ Volume::_HandleEntryCreatedOrRemoved(const BMessage* message, bool created) if (message->FindInt32("device", &deviceID) != B_OK || message->FindInt64("directory", &directoryID) != B_OK || message->FindString("name", &name) != B_OK - || node_ref(deviceID, directoryID) != fPackagesDirectoryRef) { + || node_ref(deviceID, directoryID) != PackagesDirectoryRef()) { return; } @@ -708,18 +799,18 @@ Volume::_HandleEntryMoved(const BMessage* message) || 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)) { + || deviceID != PackagesDeviceID() + || (fromDirectoryID != PackagesDirectoryID() + && toDirectoryID != PackagesDirectoryID())) { return; } AutoLocker eventsLock(fPendingNodeMonitorEventsLock); // make sure for a move the two events cannot get split - if (fromDirectoryID == fPackagesDirectoryRef.node) + if (fromDirectoryID == PackagesDirectoryID()) _QueueNodeMonitorEvent(fromName, false); - if (toDirectoryID == fPackagesDirectoryRef.node) + if (toDirectoryID == PackagesDirectoryID()) _QueueNodeMonitorEvent(toName, true); } @@ -772,15 +863,6 @@ INFORM("Volume::_PackagesEntryCreated(\"%s\")\n", name); return; } - 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\n"); - return; - } - package = new(std::nothrow) Package; if (package == NULL) { ERROR("out of memory\n"); @@ -788,7 +870,8 @@ INFORM("Volume::_PackagesEntryCreated(\"%s\")\n", name); } ObjectDeleter packageDeleter(package); - error = package->Init(entry); + NotOwningEntryRef entry(PackagesDirectoryRef(), name); + status_t error = package->Init(entry); if (error != B_OK) { ERROR("failed to init package for file \"%s\"\n", name); return; @@ -847,7 +930,7 @@ status_t Volume::_ReadPackagesDirectory() { BDirectory directory; - status_t error = directory.SetTo(&fPackagesDirectoryRef); + status_t error = directory.SetTo(&PackagesDirectoryRef()); if (error != B_OK) { ERROR("Volume::_ReadPackagesDirectory(): failed to open packages " "directory: %s\n", strerror(error)); @@ -977,7 +1060,7 @@ Volume::_OpenPackagesSubDirectory(const RelativePath& path, bool create, { // open the packages directory BDirectory directory; - status_t error = directory.SetTo(&fPackagesDirectoryRef); + status_t error = directory.SetTo(&PackagesDirectoryRef()); if (error != B_OK) { ERROR("Volume::_OpenPackagesSubDirectory(): failed to open packages " "directory: %s\n", strerror(error)); diff --git a/src/servers/package/Volume.h b/src/servers/package/Volume.h index 0afbcf7cb7..f364a3f15a 100644 --- a/src/servers/package/Volume.h +++ b/src/servers/package/Volume.h @@ -99,12 +99,11 @@ public: ino_t RootDirectoryID() const { return fRootDirectoryRef.node; } - const node_ref& PackagesDirectoryRef() const - { return fPackagesDirectoryRef; } + const node_ref& PackagesDirectoryRef() const; dev_t PackagesDeviceID() const - { return fPackagesDirectoryRef.device; } + { return PackagesDirectoryRef().device; } ino_t PackagesDirectoryID() const - { return fPackagesDirectoryRef.node; } + { return PackagesDirectoryRef().node; } Root* GetRoot() const { return fRoot; } @@ -139,6 +138,7 @@ public: private: struct NodeMonitorEvent; + struct PackagesDirectory; typedef FSUtils::RelativePath RelativePath; typedef DoublyLinkedList NodeMonitorEventList; @@ -171,7 +171,8 @@ private: BString fPath; PackageFSMountType fMountType; node_ref fRootDirectoryRef; - node_ref fPackagesDirectoryRef; + PackagesDirectory* fPackagesDirectories; + uint32 fPackagesDirectoryCount; Root* fRoot; Listener* fListener; VolumeState* fState;