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 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
@@ -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;
}
@@ -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;
};
@@ -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;
@@ -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;
};