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.
This commit is contained in:
Ingo Weinhold
2013-04-29 15:38:34 +02:00
parent 87a36d2227
commit 58081381ea
5 changed files with 112 additions and 60 deletions
+4 -1
View File
@@ -212,8 +212,11 @@ AddDirectoryToHaikuImage home mail draft ;
AddDirectoryToHaikuImage home mail in ; AddDirectoryToHaikuImage home mail in ;
AddDirectoryToHaikuImage home mail out ; 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 # Deskbar Application links
AddSymlinkToHaikuImage home config settings : deskbar : be ;
AddDirectoryToHaikuImage home config settings deskbar Applications ; AddDirectoryToHaikuImage home config settings deskbar Applications ;
DESKBAR_APPLICATIONS = ActivityMonitor CharacterMap CodyCam CDPlayer DeskCalc DESKBAR_APPLICATIONS = ActivityMonitor CharacterMap CodyCam CDPlayer DeskCalc
Devices DiskProbe DriveSetup DiskUsage Expander Icon-O-Matic Installer Devices DiskProbe DriveSetup DiskUsage Expander Icon-O-Matic Installer
@@ -20,13 +20,15 @@
static const char* const kSelfLinkName = ".self"; static const char* const kSelfLinkName = ".self";
static const char* const kSettingsLinkName = ".settings";
PackageLinkDirectory::PackageLinkDirectory() PackageLinkDirectory::PackageLinkDirectory()
: :
Directory(0), Directory(0),
// the ID needs to be assigned later, when added to a volume // the ID needs to be assigned later, when added to a volume
fSelfLink(NULL) fSelfLink(NULL),
fSettingsLink(NULL)
{ {
get_real_time(fModifiedTime); get_real_time(fModifiedTime);
} }
@@ -36,6 +38,8 @@ PackageLinkDirectory::~PackageLinkDirectory()
{ {
if (fSelfLink != NULL) if (fSelfLink != NULL)
fSelfLink->ReleaseReference(); fSelfLink->ReleaseReference();
if (fSettingsLink != NULL)
fSettingsLink->ReleaseReference();
while (DependencyLink* link = fDependencyLinks.RemoveHead()) while (DependencyLink* link = fDependencyLinks.RemoveHead())
link->ReleaseReference(); link->ReleaseReference();
@@ -154,55 +158,32 @@ PackageLinkDirectory::_Update(PackageLinksListener* listener)
{ {
// Always remove all dependency links -- if there's still a package, they // Always remove all dependency links -- if there's still a package, they
// will be re-created below. // will be re-created below.
while (DependencyLink* link = fDependencyLinks.RemoveHead()) { while (DependencyLink* link = fDependencyLinks.RemoveHead())
NodeWriteLocker linkLocker(link); _RemoveLink(link, listener);
if (listener != NULL)
listener->PackageLinkNodeRemoved(link);
RemoveChild(link);
linkLocker.Unlock();
link->ReleaseReference();
}
// check, if empty // check, if empty
Package* package = fPackages.Head(); Package* package = fPackages.Head();
if (package == NULL) { if (package == NULL) {
// remove self link, if any // remove self and settings link
if (fSelfLink != NULL) { _RemoveLink(fSelfLink, listener);
NodeWriteLocker selfLinkLocker(fSelfLink); fSelfLink = NULL;
if (listener != NULL)
listener->PackageLinkNodeRemoved(fSelfLink);
RemoveChild(fSelfLink); _RemoveLink(fSettingsLink, listener);
selfLinkLocker.Unlock(); fSettingsLink = NULL;
fSelfLink->ReleaseReference();
fSelfLink = NULL;
}
return B_OK; return B_OK;
} }
// create/update self link // create/update self and settings link
if (fSelfLink == NULL) { status_t error = _CreateOrUpdateLink(fSelfLink, package,
fSelfLink = new(std::nothrow) Link(package); Link::TYPE_INSTALLATION_LOCATION, kSelfLinkName, listener);
if (fSelfLink == NULL) if (error != B_OK)
return B_NO_MEMORY; RETURN_ERROR(error);
status_t error = fSelfLink->Init(this, kSelfLinkName, error = _CreateOrUpdateLink(fSettingsLink, package, Link::TYPE_SETTINGS,
NODE_FLAG_CONST_NAME); kSettingsLinkName, listener);
if (error != B_OK) if (error != B_OK)
RETURN_ERROR(error); RETURN_ERROR(error);
AddChild(fSelfLink);
if (listener != NULL) {
NodeWriteLocker selfLinkLocker(fSelfLink);
listener->PackageLinkNodeAdded(fSelfLink);
}
} else {
NodeWriteLocker selfLinkLocker(fSelfLink);
fSelfLink->Update(package, listener);
}
// update the dependency links // update the dependency links
return _UpdateDependencies(listener); return _UpdateDependencies(listener);
@@ -256,3 +237,47 @@ PackageLinkDirectory::_UpdateDependencies(PackageLinksListener* listener)
return B_OK; 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;
}
@@ -41,7 +41,7 @@ private:
struct DependencyLink : public PackageLinkSymlink { struct DependencyLink : public PackageLinkSymlink {
DependencyLink(Package* package) DependencyLink(Package* package)
: :
PackageLinkSymlink(package) PackageLinkSymlink(package, TYPE_INSTALLATION_LOCATION)
{ {
} }
@@ -58,10 +58,18 @@ private:
status_t _UpdateDependencies( status_t _UpdateDependencies(
PackageLinksListener* listener); PackageLinksListener* listener);
status_t _CreateOrUpdateLink(Link*& link,
Package* package, Link::Type type,
const char* name,
PackageLinksListener* listener);
void _RemoveLink(Link* link,
PackageLinksListener* listener);
private: private:
timespec fModifiedTime; timespec fModifiedTime;
PackageList fPackages; PackageList fPackages;
Link* fSelfLink; Link* fSelfLink;
Link* fSettingsLink;
FamilyDependencyList fDependencyLinks; FamilyDependencyList fDependencyLinks;
}; };
@@ -17,27 +17,32 @@
#include "Volume.h" #include "Volume.h"
static const char* const kSystemLinkPath = "../.."; static const char* const kLinkPaths[PackageLinkSymlink::TYPE_ENUM_COUNT]
static const char* const kCommonLinkPath = "../../../common"; [PACKAGE_FS_MOUNT_TYPE_ENUM_COUNT] = {
static const char* const kHomeLinkPath = "../../../home/config"; {
"../..",
"../../../common",
"../../../home/config"
},
{
"../../../common/settings",
"../../../common/settings",
"../../../home/config/settings/global"
}
};
static const char* const kUnknownLinkTarget = "?"; static const char* const kUnknownLinkTarget = "?";
static const char* static const char*
link_path_for_mount_type(MountType type) link_path_for_mount_type(MountType mountType, PackageLinkSymlink::Type linkType)
{ {
switch (type) { if (mountType < 0 || mountType >= PACKAGE_FS_MOUNT_TYPE_ENUM_COUNT
case PACKAGE_FS_MOUNT_TYPE_SYSTEM: || linkType < 0 || linkType >= PackageLinkSymlink::TYPE_ENUM_COUNT) {
return kSystemLinkPath; return kUnknownLinkTarget;
case PACKAGE_FS_MOUNT_TYPE_COMMON:
return kCommonLinkPath;
case PACKAGE_FS_MOUNT_TYPE_HOME:
return kHomeLinkPath;
case PACKAGE_FS_MOUNT_TYPE_CUSTOM:
default:
return "?";
} }
return kLinkPaths[linkType][mountType];
} }
@@ -71,10 +76,11 @@ private:
// #pragma mark - PackageLinkSymlink // #pragma mark - PackageLinkSymlink
PackageLinkSymlink::PackageLinkSymlink(Package* package) PackageLinkSymlink::PackageLinkSymlink(Package* package, Type type)
: :
Node(0), Node(0),
fLinkPath(kUnknownLinkTarget) fLinkPath(kUnknownLinkTarget),
fType(type)
{ {
Update(package, NULL); Update(package, NULL);
} }
@@ -94,7 +100,7 @@ PackageLinkSymlink::Update(Package* package, PackageLinksListener* listener)
fLinkPath = package->InstallPath(); fLinkPath = package->InstallPath();
if (fLinkPath == NULL) { if (fLinkPath == NULL) {
fLinkPath = link_path_for_mount_type( fLinkPath = link_path_for_mount_type(
package->Volume()->MountType()); package->Volume()->MountType(), fType);
} }
} else } else
fLinkPath = kUnknownLinkTarget; fLinkPath = kUnknownLinkTarget;
@@ -15,7 +15,16 @@ class PackageLinksListener;
class PackageLinkSymlink : public Node { class PackageLinkSymlink : public Node {
public: public:
PackageLinkSymlink(Package* package); enum Type {
TYPE_INSTALLATION_LOCATION,
TYPE_SETTINGS,
TYPE_ENUM_COUNT
};
public:
PackageLinkSymlink(Package* package,
Type type);
virtual ~PackageLinkSymlink(); virtual ~PackageLinkSymlink();
void Update(Package* package, void Update(Package* package,
@@ -37,6 +46,7 @@ private:
private: private:
timespec fModifiedTime; timespec fModifiedTime;
const char* fLinkPath; const char* fLinkPath;
Type fType;
}; };