From 58081381ea065528589e828d290d8643526cd64e Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Mon, 29 Apr 2013 15:38:34 +0200 Subject: [PATCH] packagefs: Add a .settings package symlink It points to the settings directory appropriate for global settings. When a package is installed in ~/config, we cannot use the settings/ subdirectory for global settings, since then the files could clash with equally named user specific settings files (e.g. in case of ssh/known_hosts). So we use ~/config/settings/global for global settings instead. --- build/jam/HaikuImage | 5 +- .../packagefs/PackageLinkDirectory.cpp | 105 +++++++++++------- .../packagefs/PackageLinkDirectory.h | 10 +- .../packagefs/PackageLinkSymlink.cpp | 40 ++++--- .../packagefs/PackageLinkSymlink.h | 12 +- 5 files changed, 112 insertions(+), 60 deletions(-) diff --git a/build/jam/HaikuImage b/build/jam/HaikuImage index 580bdb670b..0fd497d1cd 100644 --- a/build/jam/HaikuImage +++ b/build/jam/HaikuImage @@ -212,8 +212,11 @@ AddDirectoryToHaikuImage home mail draft ; AddDirectoryToHaikuImage home mail in ; AddDirectoryToHaikuImage home mail out ; -AddSymlinkToHaikuImage home config settings : deskbar : be ; +# global settings when a package is installed in ~/config +AddDirectoryToHaikuImage home config settings global ; + # Deskbar Application links +AddSymlinkToHaikuImage home config settings : deskbar : be ; AddDirectoryToHaikuImage home config settings deskbar Applications ; DESKBAR_APPLICATIONS = ActivityMonitor CharacterMap CodyCam CDPlayer DeskCalc Devices DiskProbe DriveSetup DiskUsage Expander Icon-O-Matic Installer diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.cpp b/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.cpp index b0dc5a45a6..24e505bbf7 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.cpp @@ -20,13 +20,15 @@ static const char* const kSelfLinkName = ".self"; +static const char* const kSettingsLinkName = ".settings"; PackageLinkDirectory::PackageLinkDirectory() : Directory(0), // the ID needs to be assigned later, when added to a volume - fSelfLink(NULL) + fSelfLink(NULL), + fSettingsLink(NULL) { get_real_time(fModifiedTime); } @@ -36,6 +38,8 @@ PackageLinkDirectory::~PackageLinkDirectory() { if (fSelfLink != NULL) fSelfLink->ReleaseReference(); + if (fSettingsLink != NULL) + fSettingsLink->ReleaseReference(); while (DependencyLink* link = fDependencyLinks.RemoveHead()) link->ReleaseReference(); @@ -154,55 +158,32 @@ PackageLinkDirectory::_Update(PackageLinksListener* listener) { // Always remove all dependency links -- if there's still a package, they // will be re-created below. - while (DependencyLink* link = fDependencyLinks.RemoveHead()) { - NodeWriteLocker linkLocker(link); - if (listener != NULL) - listener->PackageLinkNodeRemoved(link); - - RemoveChild(link); - linkLocker.Unlock(); - link->ReleaseReference(); - } + while (DependencyLink* link = fDependencyLinks.RemoveHead()) + _RemoveLink(link, listener); // check, if empty Package* package = fPackages.Head(); if (package == NULL) { - // remove self link, if any - if (fSelfLink != NULL) { - NodeWriteLocker selfLinkLocker(fSelfLink); - if (listener != NULL) - listener->PackageLinkNodeRemoved(fSelfLink); + // remove self and settings link + _RemoveLink(fSelfLink, listener); + fSelfLink = NULL; - RemoveChild(fSelfLink); - selfLinkLocker.Unlock(); - fSelfLink->ReleaseReference(); - fSelfLink = NULL; - } + _RemoveLink(fSettingsLink, listener); + fSettingsLink = NULL; return B_OK; } - // create/update self link - if (fSelfLink == NULL) { - fSelfLink = new(std::nothrow) Link(package); - if (fSelfLink == NULL) - return B_NO_MEMORY; + // create/update self and settings link + status_t error = _CreateOrUpdateLink(fSelfLink, package, + Link::TYPE_INSTALLATION_LOCATION, kSelfLinkName, listener); + if (error != B_OK) + RETURN_ERROR(error); - status_t error = fSelfLink->Init(this, kSelfLinkName, - NODE_FLAG_CONST_NAME); - if (error != B_OK) - RETURN_ERROR(error); - - AddChild(fSelfLink); - - if (listener != NULL) { - NodeWriteLocker selfLinkLocker(fSelfLink); - listener->PackageLinkNodeAdded(fSelfLink); - } - } else { - NodeWriteLocker selfLinkLocker(fSelfLink); - fSelfLink->Update(package, listener); - } + error = _CreateOrUpdateLink(fSettingsLink, package, Link::TYPE_SETTINGS, + kSettingsLinkName, listener); + if (error != B_OK) + RETURN_ERROR(error); // update the dependency links return _UpdateDependencies(listener); @@ -256,3 +237,47 @@ PackageLinkDirectory::_UpdateDependencies(PackageLinksListener* listener) return B_OK; } + + +void +PackageLinkDirectory::_RemoveLink(Link* link, PackageLinksListener* listener) +{ + if (link != NULL) { + NodeWriteLocker linkLocker(link); + if (listener != NULL) + listener->PackageLinkNodeRemoved(link); + + RemoveChild(link); + linkLocker.Unlock(); + link->ReleaseReference(); + } +} + + +status_t +PackageLinkDirectory::_CreateOrUpdateLink(Link*& link, Package* package, + Link::Type type, const char* name, PackageLinksListener* listener) +{ + if (link == NULL) { + link = new(std::nothrow) Link(package, type); + if (link == NULL) + return B_NO_MEMORY; + + status_t error = link->Init(this, name, NODE_FLAG_CONST_NAME); + if (error != B_OK) + RETURN_ERROR(error); + + AddChild(link); + + if (listener != NULL) { + NodeWriteLocker lLinkLocker(link); + listener->PackageLinkNodeAdded(link); + } + } else { + NodeWriteLocker lLinkLocker(link); + link->Update(package, listener); + } + + + return B_OK; +} diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.h b/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.h index 798592c243..c0af9ab3ef 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.h +++ b/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.h @@ -41,7 +41,7 @@ private: struct DependencyLink : public PackageLinkSymlink { DependencyLink(Package* package) : - PackageLinkSymlink(package) + PackageLinkSymlink(package, TYPE_INSTALLATION_LOCATION) { } @@ -58,10 +58,18 @@ private: status_t _UpdateDependencies( PackageLinksListener* listener); + status_t _CreateOrUpdateLink(Link*& link, + Package* package, Link::Type type, + const char* name, + PackageLinksListener* listener); + void _RemoveLink(Link* link, + PackageLinksListener* listener); + private: timespec fModifiedTime; PackageList fPackages; Link* fSelfLink; + Link* fSettingsLink; FamilyDependencyList fDependencyLinks; }; diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageLinkSymlink.cpp b/src/add-ons/kernel/file_systems/packagefs/PackageLinkSymlink.cpp index 4fbf81f7f2..23098716ab 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageLinkSymlink.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/PackageLinkSymlink.cpp @@ -17,27 +17,32 @@ #include "Volume.h" -static const char* const kSystemLinkPath = "../.."; -static const char* const kCommonLinkPath = "../../../common"; -static const char* const kHomeLinkPath = "../../../home/config"; +static const char* const kLinkPaths[PackageLinkSymlink::TYPE_ENUM_COUNT] + [PACKAGE_FS_MOUNT_TYPE_ENUM_COUNT] = { + { + "../..", + "../../../common", + "../../../home/config" + }, + { + "../../../common/settings", + "../../../common/settings", + "../../../home/config/settings/global" + } +}; static const char* const kUnknownLinkTarget = "?"; static const char* -link_path_for_mount_type(MountType type) +link_path_for_mount_type(MountType mountType, PackageLinkSymlink::Type linkType) { - switch (type) { - case PACKAGE_FS_MOUNT_TYPE_SYSTEM: - return kSystemLinkPath; - case PACKAGE_FS_MOUNT_TYPE_COMMON: - return kCommonLinkPath; - case PACKAGE_FS_MOUNT_TYPE_HOME: - return kHomeLinkPath; - case PACKAGE_FS_MOUNT_TYPE_CUSTOM: - default: - return "?"; + if (mountType < 0 || mountType >= PACKAGE_FS_MOUNT_TYPE_ENUM_COUNT + || linkType < 0 || linkType >= PackageLinkSymlink::TYPE_ENUM_COUNT) { + return kUnknownLinkTarget; } + + return kLinkPaths[linkType][mountType]; } @@ -71,10 +76,11 @@ private: // #pragma mark - PackageLinkSymlink -PackageLinkSymlink::PackageLinkSymlink(Package* package) +PackageLinkSymlink::PackageLinkSymlink(Package* package, Type type) : Node(0), - fLinkPath(kUnknownLinkTarget) + fLinkPath(kUnknownLinkTarget), + fType(type) { Update(package, NULL); } @@ -94,7 +100,7 @@ PackageLinkSymlink::Update(Package* package, PackageLinksListener* listener) fLinkPath = package->InstallPath(); if (fLinkPath == NULL) { fLinkPath = link_path_for_mount_type( - package->Volume()->MountType()); + package->Volume()->MountType(), fType); } } else fLinkPath = kUnknownLinkTarget; diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageLinkSymlink.h b/src/add-ons/kernel/file_systems/packagefs/PackageLinkSymlink.h index cbf66fcec3..37e3c42a53 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageLinkSymlink.h +++ b/src/add-ons/kernel/file_systems/packagefs/PackageLinkSymlink.h @@ -15,7 +15,16 @@ class PackageLinksListener; class PackageLinkSymlink : public Node { public: - PackageLinkSymlink(Package* package); + enum Type { + TYPE_INSTALLATION_LOCATION, + TYPE_SETTINGS, + + TYPE_ENUM_COUNT + }; + +public: + PackageLinkSymlink(Package* package, + Type type); virtual ~PackageLinkSymlink(); void Update(Package* package, @@ -37,6 +46,7 @@ private: private: timespec fModifiedTime; const char* fLinkPath; + Type fType; };