packagefs: Support blacklisting entries in packages

In each installation location, it is now possible to create a settings
file "packages" that allows to blacklist entries contained in packages.
The format is:

Package <package name> {
	EntryBlacklist {
		<entry path>
		...
	}
}
...

<package name> is the base name (no version) of the respective package
(e.g. "haiku"), <entry path> is an installation location relative path
(e.g. "add-ons/Translators/FooTranslator").

Blacklisted entries will be ignored by packagefs, i.e. they won't appear
in the file system. This addresses the issue that it may be necessary to
remove a problematic file (e.g. driver, add-on, or library), which would
otherwise require editing the containing package file.

The settings file is not not "live". Changes take effect only after
reboot (respectively when remounting the concerned packagefs volume).
This commit is contained in:
Ingo Weinhold 2013-11-19 15:30:34 +01:00
parent 2fdd1d9ef1
commit 3a7e0b0014
16 changed files with 929 additions and 29 deletions

View File

@ -38,6 +38,7 @@
#define kSystemPackageLinksDirectory "/boot/system/package-links"
#define kSystemPreferencesDirectory "/boot/system/preferences"
#define kSystemServersDirectory "/boot/system/servers"
#define kSystemSettingsDirectory "/boot/system/settings"
#define kSystemEtcDirectory "/boot/system/settings/etc"
#define kSystemTempDirectory "/boot/system/cache/tmp"
@ -55,6 +56,7 @@
#define kUserLibDirectory "/boot/home/config/lib"
#define kUserPackagesDirectory "/boot/home/config/packages"
#define kUserSettingsDirectory "/boot/home/config/settings"
#define kUserSettingsGlobalDirectory "/boot/home/config/settings/global"
#define kUserNonpackagedDirectory "/boot/home/config/non-packaged"
#define kUserNonpackagedAddonsDirectory "/boot/home/config/non-packaged/add-ons"
#define kUserNonpackagedBinDirectory "/boot/home/config/non-packaged/bin"

View File

@ -50,6 +50,7 @@ HAIKU_PACKAGE_FS_SOURCES =
PackageLinkSymlink.cpp
PackageNode.cpp
PackageNodeAttribute.cpp
PackageSettings.cpp
PackageSymlink.cpp
Resolvable.cpp
ResolvableFamily.cpp

View File

@ -30,6 +30,7 @@
#include "GlobalFactory.h"
#include "PackageDirectory.h"
#include "PackageFile.h"
#include "PackageSettings.h"
#include "PackageSymlink.h"
#include "Version.h"
#include "Volume.h"
@ -93,9 +94,13 @@ private:
struct Package::LoaderContentHandler : BPackageContentHandler {
LoaderContentHandler(Package* package)
LoaderContentHandler(Package* package, const PackageSettings& settings)
:
fPackage(package),
fSettings(settings),
fSettingsItem(NULL),
fLastSettingsEntry(NULL),
fLastSettingsEntryEntry(NULL),
fErrorOccurred(false)
{
}
@ -107,8 +112,11 @@ struct Package::LoaderContentHandler : BPackageContentHandler {
virtual status_t HandleEntry(BPackageEntry* entry)
{
if (fErrorOccurred)
if (fErrorOccurred
|| (fLastSettingsEntry != NULL
&& fLastSettingsEntry->IsBlackListed())) {
return B_OK;
}
PackageDirectory* parentDir = NULL;
if (entry->Parent() != NULL) {
@ -118,6 +126,19 @@ struct Package::LoaderContentHandler : BPackageContentHandler {
RETURN_ERROR(B_BAD_DATA);
}
if (fSettingsItem != NULL
&& (parentDir == NULL
|| entry->Parent() == fLastSettingsEntryEntry)) {
PackageSettingsItem::Entry* settingsEntry
= fSettingsItem->FindEntry(fLastSettingsEntry, entry->Name());
if (settingsEntry != NULL) {
fLastSettingsEntry = settingsEntry;
fLastSettingsEntryEntry = entry;
if (fLastSettingsEntry->IsBlackListed())
return B_OK;
}
}
// get the file mode -- filter out write permissions
mode_t mode = entry->Mode() & ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH);
@ -174,8 +195,11 @@ struct Package::LoaderContentHandler : BPackageContentHandler {
virtual status_t HandleEntryAttribute(BPackageEntry* entry,
BPackageEntryAttribute* attribute)
{
if (fErrorOccurred)
if (fErrorOccurred
|| (fLastSettingsEntry != NULL
&& fLastSettingsEntry->IsBlackListed())) {
return B_OK;
}
PackageNode* node = (PackageNode*)entry->UserToken();
@ -197,6 +221,11 @@ struct Package::LoaderContentHandler : BPackageContentHandler {
virtual status_t HandleEntryDone(BPackageEntry* entry)
{
if (entry == fLastSettingsEntryEntry) {
fLastSettingsEntryEntry = entry->Parent();
fLastSettingsEntry = fLastSettingsEntry->Parent();
}
return B_OK;
}
@ -210,6 +239,9 @@ struct Package::LoaderContentHandler : BPackageContentHandler {
if (!name.SetTo(value.string))
return B_NO_MEMORY;
fPackage->SetName(name);
fSettingsItem = fSettings.PackageItemFor(fPackage->Name());
return B_OK;
}
@ -232,7 +264,6 @@ struct Package::LoaderContentHandler : BPackageContentHandler {
RETURN_ERROR(error);
fPackage->SetVersion(version);
break;
}
@ -336,8 +367,12 @@ struct Package::LoaderContentHandler : BPackageContentHandler {
}
private:
Package* fPackage;
bool fErrorOccurred;
Package* fPackage;
const PackageSettings& fSettings;
const PackageSettingsItem* fSettingsItem;
PackageSettingsItem::Entry* fLastSettingsEntry;
const BPackageEntry* fLastSettingsEntryEntry;
bool fErrorOccurred;
};
@ -805,9 +840,9 @@ Package::Init(const char* fileName)
status_t
Package::Load()
Package::Load(const PackageSettings& settings)
{
status_t error = _Load();
status_t error = _Load(settings);
if (error != B_OK)
return error;
@ -947,7 +982,7 @@ Package::CreateDataReader(const PackageData& data,
status_t
Package::_Load()
Package::_Load(const PackageSettings& settings)
{
// open package file
int fd = Open();
@ -965,7 +1000,7 @@ Package::_Load()
BHPKG::B_HPKG_READER_DONT_PRINT_VERSION_MISMATCH_MESSAGE);
if (error == B_OK) {
// parse content
LoaderContentHandler handler(this);
LoaderContentHandler handler(this, settings);
error = handler.Init();
if (error != B_OK)
RETURN_ERROR(error);

View File

@ -28,6 +28,7 @@ using BPackageKit::BHPKG::BAbstractBufferedDataReader;
class PackageLinkDirectory;
class PackageSettings;
class Volume;
class Version;
@ -40,7 +41,7 @@ public:
~Package();
status_t Init(const char* fileName);
status_t Load();
status_t Load(const PackageSettings& settings);
::Volume* Volume() const { return fVolume; }
const String& FileName() const { return fFileName; }
@ -106,7 +107,7 @@ private:
struct CachingPackageReader;
private:
status_t _Load();
status_t _Load(const PackageSettings& settings);
bool _InitVersionedName();
private:

View File

@ -0,0 +1,232 @@
/*
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "PackageSettings.h"
#include <driver_settings.h>
#include <AutoDeleter.h>
#include <directories.h>
#include <fs/KPath.h>
#include <vfs.h>
#include "DebugSupport.h"
// #pragma mark - PackageSettingsItem
PackageSettingsItem::PackageSettingsItem()
:
fName(),
fEntries()
{
}
PackageSettingsItem::~PackageSettingsItem()
{
Entry* entry = fEntries.Clear(true);
while (entry != NULL) {
Entry* next = entry->HashNext();
delete entry;
entry = next;
}
}
status_t
PackageSettingsItem::Init(const driver_parameter& parameter)
{
if (!fName.SetTo(parameter.values[0]) || fEntries.Init() != B_OK)
RETURN_ERROR(B_NO_MEMORY);
for (int i = 0; i < parameter.parameter_count; i++) {
const driver_parameter& subParameter = parameter.parameters[i];
if (strcmp(subParameter.name, "EntryBlacklist") != 0)
continue;
status_t error = _AddBlackListedEntries(subParameter);
// abort only in case of serious issues (memory shortage)
if (error == B_NO_MEMORY)
return error;
}
return B_OK;
}
void
PackageSettingsItem::AddEntry(Entry* entry)
{
fEntries.Insert(entry);
}
status_t
PackageSettingsItem::AddEntry(const char* path, Entry*& _entry)
{
Entry* parent = NULL;
while (*path != '\0') {
while (*path == '/') {
path++;
continue;
}
const char* componentEnd = strchr(path, '/');
if (componentEnd == NULL)
componentEnd = path + strlen(path);
String name;
if (!name.SetTo(path, componentEnd - path))
RETURN_ERROR(B_NO_MEMORY);
Entry* entry = FindEntry(parent, name);
if (entry == NULL) {
entry = new(std::nothrow) Entry(parent, name);
if (entry == NULL)
RETURN_ERROR(B_NO_MEMORY);
AddEntry(entry);
}
path = componentEnd;
parent = entry;
}
if (parent == NULL)
return B_BAD_VALUE;
_entry = parent;
return B_OK;
}
PackageSettingsItem::Entry*
PackageSettingsItem::FindEntry(Entry* parent, const String& name) const
{
return fEntries.Lookup(EntryKey(parent, name));
}
PackageSettingsItem::Entry*
PackageSettingsItem::FindEntry(Entry* parent, const char* name) const
{
return fEntries.Lookup(EntryKey(parent, name));
}
status_t
PackageSettingsItem::_AddBlackListedEntries(const driver_parameter& parameter)
{
for (int i = 0; i < parameter.parameter_count; i++) {
Entry* entry;
status_t error = AddEntry(parameter.parameters[i].name, entry);
// abort only in case of serious issues (memory shortage)
if (error == B_NO_MEMORY)
return error;
entry->SetBlackListed(true);
}
return B_OK;
}
// #pragma mark - PackageSettings
PackageSettings::PackageSettings()
:
fPackageItems()
{
}
PackageSettings::~PackageSettings()
{
PackageSettingsItem* item = fPackageItems.Clear(true);
while (item != NULL) {
PackageSettingsItem* next = item->HashNext();
delete item;
item = next;
}
}
status_t
PackageSettings::Load(dev_t mountPointDeviceID, ino_t mountPointNodeID,
PackageFSMountType mountType)
{
status_t error = fPackageItems.Init();
if (error != B_OK)
RETURN_ERROR(error);
// get the mount point relative settings file path
const char* settingsFilePath = mountType == PACKAGE_FS_MOUNT_TYPE_HOME
? kUserSettingsGlobalDirectory "/packages"
+ strlen(kUserConfigDirectory) + 1
: kSystemSettingsDirectory "/packages" + strlen(kSystemDirectory) + 1;
// get an absolute path
KPath path;
if (path.InitCheck() != B_OK)
RETURN_ERROR(path.InitCheck());
error = vfs_entry_ref_to_path(mountPointDeviceID, mountPointNodeID,
NULL, true, path.LockBuffer(), path.BufferSize());
if (error != B_OK)
return error;
path.UnlockBuffer();
error = path.Append(settingsFilePath);
if (error != B_OK)
return error;
// load the driver settings
void* settingsHandle = load_driver_settings(path.Path());
if (settingsHandle == NULL)
return B_ENTRY_NOT_FOUND;
CObjectDeleter<void, status_t> settingsDeleter(settingsHandle,
&unload_driver_settings);
const driver_settings* settings = get_driver_settings(settingsHandle);
for (int i = 0; i < settings->parameter_count; i++) {
const driver_parameter& parameter = settings->parameters[i];
if (strcmp(parameter.name, "Package") != 0
|| parameter.value_count < 1) {
continue;
}
error = _AddPackageSettingsItem(parameter);
// abort only in case of serious issues (memory shortage)
if (error == B_NO_MEMORY)
return error;
}
return B_OK;
}
const PackageSettingsItem*
PackageSettings::PackageItemFor(const String& name) const
{
return fPackageItems.Lookup(name);
}
status_t
PackageSettings::_AddPackageSettingsItem(const driver_parameter& parameter)
{
PackageSettingsItem* packageItem = new(std::nothrow) PackageSettingsItem;
if (packageItem == NULL || packageItem->Init(parameter) != B_OK) {
delete packageItem;
RETURN_ERROR(B_NO_MEMORY);
}
fPackageItems.Insert(packageItem);
return B_OK;
}

View File

@ -0,0 +1,210 @@
/*
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef PACKAGE_SETTINGS_H
#define PACKAGE_SETTINGS_H
#include <packagefs.h>
#include <util/OpenHashTable.h>
#include "String.h"
struct driver_parameter;
class PackageSettingsItem {
public:
class Entry {
public:
Entry(Entry* parent, const String& name)
:
fParent(parent),
fName(name),
fIsBlackListed(false)
{
}
Entry* Parent() const
{
return fParent;
}
const String& Name() const
{
return fName;
}
bool IsBlackListed() const
{
return fIsBlackListed;
}
void SetBlackListed(bool blackListed)
{
fIsBlackListed = blackListed;
}
Entry*& HashNext()
{
return fHashNext;
}
private:
Entry* fParent;
String fName;
bool fIsBlackListed;
Entry* fHashNext;
};
class EntryKey {
public:
EntryKey(Entry* parent, const char* name)
:
fParent(parent),
fName(name),
fHash((addr_t)parent / 8 ^ hash_hash_string(name))
{
}
EntryKey(Entry* parent, const String& name)
:
fParent(parent),
fName(name),
fHash((addr_t)parent / 8 ^ name.Hash())
{
}
Entry* Parent() const
{
return fParent;
}
const char* Name() const
{
return fName;
}
size_t Hash() const
{
return fHash;
}
private:
Entry* fParent;
const char* fName;
size_t fHash;
};
public:
PackageSettingsItem();
~PackageSettingsItem();
status_t Init(const driver_parameter& parameter);
const String& Name() const
{ return fName; }
void AddEntry(Entry* entry);
status_t AddEntry(const char* path, Entry*& _entry);
Entry* FindEntry(Entry* parent, const String& name)
const;
Entry* FindEntry(Entry* parent, const char* name)
const;
PackageSettingsItem*& HashNext()
{ return fHashNext; }
private:
struct EntryHashDefinition {
typedef EntryKey KeyType;
typedef Entry ValueType;
size_t HashKey(const EntryKey& key) const
{
return key.Hash();
}
size_t Hash(const Entry* value) const
{
return HashKey(EntryKey(value->Parent(), value->Name()));
}
bool Compare(const EntryKey& key, const Entry* value) const
{
return key.Parent() == value->Parent()
&& strcmp(key.Name(), value->Name()) == 0;
}
Entry*& GetLink(Entry* value) const
{
return value->HashNext();
}
};
typedef BOpenHashTable<EntryHashDefinition> EntryTable;
private:
status_t _AddBlackListedEntries(
const driver_parameter& parameter);
private:
String fName;
EntryTable fEntries;
PackageSettingsItem* fHashNext;
};
struct PackageSettingsItemHashDefinition {
typedef String KeyType;
typedef PackageSettingsItem ValueType;
size_t HashKey(const String& key) const
{
return key.Hash();
}
size_t Hash(const PackageSettingsItem* value) const
{
return HashKey(value->Name());
}
bool Compare(const String& key, const PackageSettingsItem* value) const
{
return key == value->Name();
}
PackageSettingsItem*& GetLink(PackageSettingsItem* value) const
{
return value->HashNext();
}
};
class PackageSettings {
public:
PackageSettings();
~PackageSettings();
status_t Load(dev_t mountPointDeviceID,
ino_t mountPointNodeID,
PackageFSMountType mountType);
const PackageSettingsItem* PackageItemFor(const String& name) const;
private:
typedef BOpenHashTable<PackageSettingsItemHashDefinition>
PackageItemTable;
private:
status_t _AddPackageSettingsItem(
const driver_parameter& parameter);
private:
PackageItemTable fPackageItems;
};
#endif // PACKAGE_SETTINGS_H

View File

@ -275,6 +275,7 @@ Volume::Volume(fs_volume* fsVolume)
fRootDirectory(NULL),
fPackageFSRoot(NULL),
fPackagesDirectory(NULL),
fPackageSettings(),
fNextNodeID(kRootDirectoryID + 1)
{
rw_lock_init(&fLock, "packagefs volume");
@ -450,6 +451,13 @@ Volume::Mount(const char* parameterString)
if (error != B_OK)
RETURN_ERROR(error);
// load package settings
error = fPackageSettings.Load(fMountPoint.deviceID, fMountPoint.nodeID,
fMountType);
// abort only in case of serious issues (memory shortage)
if (error == B_NO_MEMORY)
RETURN_ERROR(error);
// create package domain
fPackagesDirectory = new(std::nothrow) PackagesDirectory;
if (fPackagesDirectory == NULL)
@ -1434,7 +1442,7 @@ Volume::_LoadPackage(const char* name, Package*& _package)
if (error != B_OK)
return error;
error = package->Load();
error = package->Load(fPackageSettings);
if (error != B_OK)
return error;

View File

@ -21,6 +21,7 @@
#include "NodeListener.h"
#include "Package.h"
#include "PackageLinksListener.h"
#include "PackageSettings.h"
#include "Query.h"
@ -179,6 +180,7 @@ private:
::PackageFSRoot* fPackageFSRoot;
::MountType fMountType;
PackagesDirectory* fPackagesDirectory;
PackageSettings fPackageSettings;
struct {
dev_t deviceID;

View File

@ -79,6 +79,7 @@ BootStaticLibrary boot_loader :
list.cpp
ring_buffer.cpp
safemode_settings.cpp
StringHash.cpp
Referenceable.cpp
@ -105,7 +106,7 @@ BootStaticLibrary boot_partitions :
;
# Tell Jam where to find the utility sources
SEARCH on [ FGristFiles kernel_cpp.cpp list.cpp ring_buffer.cpp ]
SEARCH on [ FGristFiles kernel_cpp.cpp list.cpp ring_buffer.cpp StringHash.cpp ]
= [ FDirName $(HAIKU_TOP) src system kernel util ] ;
SEARCH on [ FGristFiles KMessage.cpp ]

View File

@ -17,6 +17,7 @@ SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src kits package hpkg ] ;
BootStaticLibrary boot_packagefs :
packagefs.cpp
PackageSettingsItem.cpp
# package kit

View File

@ -0,0 +1,182 @@
/*
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "PackageSettingsItem.h"
#include <driver_settings.h>
#include <AutoDeleter.h>
#include <boot/vfs.h>
#include <system/directories.h>
namespace PackageFS {
// #pragma mark - PackageSettingsItem
PackageSettingsItem::PackageSettingsItem()
:
fEntries()
{
}
PackageSettingsItem::~PackageSettingsItem()
{
Entry* entry = fEntries.Clear(true);
while (entry != NULL) {
Entry* next = entry->HashNext();
delete entry;
entry = next;
}
}
/*static*/ PackageSettingsItem*
PackageSettingsItem::Load(::Directory* systemDirectory, const char* name)
{
// open the driver settings file
const char* settingsFilePath
= kSystemSettingsDirectory "/packages" + strlen(kSystemDirectory) + 1;
int fd = open_from(systemDirectory, settingsFilePath, B_READ_ONLY, 0);
if (fd < 0)
return NULL;
FileDescriptorCloser fdCloser(fd);
// load the driver settings
void* settingsHandle = load_driver_settings_file(fd);
if (settingsHandle == NULL)
return NULL;
CObjectDeleter<void, status_t> settingsDeleter(settingsHandle,
&unload_driver_settings);
const driver_settings* settings = get_driver_settings(settingsHandle);
for (int i = 0; i < settings->parameter_count; i++) {
const driver_parameter& parameter = settings->parameters[i];
if (strcmp(parameter.name, "Package") != 0
|| parameter.value_count < 1
|| strcmp(parameter.values[0], name) != 0) {
continue;
}
PackageSettingsItem* settingsItem
= new(std::nothrow) PackageSettingsItem;
if (settingsItem == NULL || settingsItem->Init(parameter) != B_OK) {
delete settingsItem;
return NULL;
}
return settingsItem;
}
return NULL;
}
status_t
PackageSettingsItem::Init(const driver_parameter& parameter)
{
if (fEntries.Init() != B_OK)
return B_NO_MEMORY;
for (int i = 0; i < parameter.parameter_count; i++) {
const driver_parameter& subParameter = parameter.parameters[i];
if (strcmp(subParameter.name, "EntryBlacklist") != 0)
continue;
status_t error = _AddBlackListedEntries(subParameter);
// abort only in case of serious issues (memory shortage)
if (error == B_NO_MEMORY)
return error;
}
return B_OK;
}
void
PackageSettingsItem::AddEntry(Entry* entry)
{
fEntries.Insert(entry);
}
status_t
PackageSettingsItem::AddEntry(const char* path, Entry*& _entry)
{
Entry* parent = NULL;
while (*path != '\0') {
while (*path == '/') {
path++;
continue;
}
const char* componentEnd = strchr(path, '/');
if (componentEnd == NULL)
componentEnd = path + strlen(path);
const char* name = path;
size_t nameLength = componentEnd - path;
Entry* entry = FindEntry(parent, name, nameLength);
if (entry == NULL) {
entry = new(std::nothrow) Entry(parent);
if (entry == NULL || !entry->SetName(name, nameLength)) {
delete entry;
return B_NO_MEMORY;
}
AddEntry(entry);
}
path = componentEnd;
parent = entry;
}
if (parent == NULL)
return B_BAD_VALUE;
_entry = parent;
return B_OK;
}
PackageSettingsItem::Entry*
PackageSettingsItem::FindEntry(Entry* parent, const char* name) const
{
return fEntries.Lookup(EntryKey(parent, name));
}
PackageSettingsItem::Entry*
PackageSettingsItem::FindEntry(Entry* parent, const char* name,
size_t nameLength) const
{
return fEntries.Lookup(EntryKey(parent, name, nameLength));
}
status_t
PackageSettingsItem::_AddBlackListedEntries(const driver_parameter& parameter)
{
for (int i = 0; i < parameter.parameter_count; i++) {
Entry* entry;
status_t error = AddEntry(parameter.parameters[i].name, entry);
// abort only in case of serious issues (memory shortage)
if (error == B_NO_MEMORY)
return error;
entry->SetBlackListed(true);
}
return B_OK;
}
} // namespace PackageFS

View File

@ -0,0 +1,190 @@
/*
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef BOOT_LOADER_FILE_SYSTEMS_PACKAGEFS_PACKAGE_SETTINGS_ITEM_H
#define BOOT_LOADER_FILE_SYSTEMS_PACKAGEFS_PACKAGE_SETTINGS_ITEM_H
#include <string.h>
#include <util/OpenHashTable.h>
#include <util/StringHash.h>
struct driver_parameter;
class Directory;
namespace PackageFS {
class PackageSettingsItem {
public:
class Entry {
public:
Entry(Entry* parent)
:
fParent(parent),
fName(NULL),
fIsBlackListed(false)
{
}
~Entry()
{
free(fName);
}
bool SetName(const char* name, size_t nameLength)
{
fName = (char*)malloc(nameLength + 1);
if (fName == NULL)
return false;
memcpy(fName, name, nameLength);
fName[nameLength] = '\0';
return true;
}
Entry* Parent() const
{
return fParent;
}
const char* Name() const
{
return fName;
}
bool IsBlackListed() const
{
return fIsBlackListed;
}
void SetBlackListed(bool blackListed)
{
fIsBlackListed = blackListed;
}
Entry*& HashNext()
{
return fHashNext;
}
private:
Entry* fParent;
char* fName;
bool fIsBlackListed;
Entry* fHashNext;
};
class EntryKey {
public:
EntryKey(Entry* parent, const char* name, size_t nameLength)
:
fParent(parent),
fName(name),
fNameLength(nameLength)
{
}
EntryKey(Entry* parent, const char* name)
:
fParent(parent),
fName(name),
fNameLength(strlen(name))
{
}
Entry* Parent() const
{
return fParent;
}
const char* Name() const
{
return fName;
}
size_t NameLength() const
{
return fNameLength;
}
size_t Hash() const
{
return (addr_t)fParent / 8
^ hash_hash_string_part(fName, fNameLength);
}
private:
Entry* fParent;
const char* fName;
size_t fNameLength;
};
public:
PackageSettingsItem();
~PackageSettingsItem();
static PackageSettingsItem* Load(::Directory* systemDirectory,
const char* name);
status_t Init(const driver_parameter& parameter);
void AddEntry(Entry* entry);
status_t AddEntry(const char* path, Entry*& _entry);
Entry* FindEntry(Entry* parent, const char* name)
const;
Entry* FindEntry(Entry* parent, const char* name,
size_t nameLength) const;
PackageSettingsItem*& HashNext()
{ return fHashNext; }
private:
struct EntryHashDefinition {
typedef EntryKey KeyType;
typedef Entry ValueType;
size_t HashKey(const EntryKey& key) const
{
return key.Hash();
}
size_t Hash(const Entry* value) const
{
return HashKey(EntryKey(value->Parent(), value->Name()));
}
bool Compare(const EntryKey& key, const Entry* value) const
{
const char* name = value->Name();
return key.Parent() == value->Parent()
&& strncmp(key.Name(), name, key.NameLength()) == 0
&& name[key.NameLength()] == '\0';
}
Entry*& GetLink(Entry* value) const
{
return value->HashNext();
}
};
typedef BOpenHashTable<EntryHashDefinition> EntryTable;
private:
status_t _AddBlackListedEntries(
const driver_parameter& parameter);
private:
EntryTable fEntries;
PackageSettingsItem* fHashNext;
};
} // namespace PackageFS
#endif // BOOT_LOADER_FILE_SYSTEMS_PACKAGEFS_PACKAGE_SETTINGS_ITEM_H

View File

@ -25,6 +25,8 @@
#include <boot/platform.h>
#include "PackageSettingsItem.h"
#if 0
# define RETURN_ERROR(error) return (error);
@ -44,6 +46,8 @@ using namespace BPackageKit::BHPKG;
using BPackageKit::BHPKG::BPrivate::PackageFileHeapReader;
using BPackageKit::BHPKG::BPrivate::PackageReaderImpl;
using PackageFS::PackageSettingsItem;
namespace {
@ -325,9 +329,13 @@ private:
struct PackageLoaderContentHandler : BPackageContentHandler {
PackageLoaderContentHandler(PackageVolume* volume)
PackageLoaderContentHandler(PackageVolume* volume,
PackageSettingsItem* settingsItem)
:
fVolume(volume),
fSettingsItem(settingsItem),
fLastSettingsEntry(NULL),
fLastSettingsEntryEntry(NULL),
fErrorOccurred(false)
{
}
@ -339,8 +347,11 @@ struct PackageLoaderContentHandler : BPackageContentHandler {
virtual status_t HandleEntry(BPackageEntry* entry)
{
if (fErrorOccurred)
if (fErrorOccurred
|| (fLastSettingsEntry != NULL
&& fLastSettingsEntry->IsBlackListed())) {
return B_OK;
}
PackageDirectory* parentDir = NULL;
if (const BPackageEntry* parentEntry = entry->Parent()) {
@ -351,6 +362,19 @@ struct PackageLoaderContentHandler : BPackageContentHandler {
(PackageNode*)parentEntry->UserToken());
}
if (fSettingsItem != NULL
&& (parentDir == NULL
|| entry->Parent() == fLastSettingsEntryEntry)) {
PackageSettingsItem::Entry* settingsEntry
= fSettingsItem->FindEntry(fLastSettingsEntry, entry->Name());
if (settingsEntry != NULL) {
fLastSettingsEntry = settingsEntry;
fLastSettingsEntryEntry = entry;
if (fLastSettingsEntry->IsBlackListed())
return B_OK;
}
}
if (parentDir == NULL)
parentDir = fVolume->RootDirectory();
@ -412,6 +436,11 @@ struct PackageLoaderContentHandler : BPackageContentHandler {
virtual status_t HandleEntryDone(BPackageEntry* entry)
{
if (entry == fLastSettingsEntryEntry) {
fLastSettingsEntryEntry = entry->Parent();
fLastSettingsEntry = fLastSettingsEntry->Parent();
}
return B_OK;
}
@ -428,8 +457,11 @@ struct PackageLoaderContentHandler : BPackageContentHandler {
}
private:
PackageVolume* fVolume;
bool fErrorOccurred;
PackageVolume* fVolume;
const PackageSettingsItem* fSettingsItem;
PackageSettingsItem::Entry* fLastSettingsEntry;
const BPackageEntry* fLastSettingsEntryEntry;
bool fErrorOccurred;
};
@ -761,7 +793,8 @@ create_node(PackageNode* packageNode, ::Node*& _node)
status_t
packagefs_mount_file(int fd, ::Directory*& _mountedDirectory)
packagefs_mount_file(int fd, ::Directory* systemDirectory,
::Directory*& _mountedDirectory)
{
PackageLoaderErrorOutput errorOutput;
PackageReaderImpl packageReader(&errorOutput);
@ -779,8 +812,13 @@ packagefs_mount_file(int fd, ::Directory*& _mountedDirectory)
if (error != B_OK)
RETURN_ERROR(error);
// load settings for the package
PackageSettingsItem* settings = PackageSettingsItem::Load(systemDirectory,
"haiku");
ObjectDeleter<PackageSettingsItem> settingsDeleter(settings);
// parse content -- this constructs the entry/node tree
PackageLoaderContentHandler handler(volume);
PackageLoaderContentHandler handler(volume, settings);
error = handler.Init();
if (error != B_OK)
RETURN_ERROR(error);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2011-2013, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef BOOT_LOADER_FILE_SYSTEMS_PACKAGEFS_H
@ -15,13 +15,8 @@ class Directory;
class Node;
__BEGIN_DECLS
status_t packagefs_mount_file(int fd, Directory*& _mountedDirectory);
__END_DECLS
status_t packagefs_mount_file(int fd, Directory* systemDirectory,
Directory*& _mountedDirectory);
#endif // BOOT_LOADER_FILE_SYSTEMS_PACKAGEFS_H

View File

@ -445,7 +445,8 @@ BootVolume::SetTo(Directory* rootDirectory)
// the system is packaged -- mount the packagefs
Directory* packageRootDirectory;
status_t error = packagefs_mount_file(packageFD, packageRootDirectory);
status_t error = packagefs_mount_file(packageFD, fSystemDirectory,
packageRootDirectory);
close(packageFD);
if (error != B_OK) {
Unset();

View File

@ -15,6 +15,7 @@ KernelMergeObject kernel_util.o :
ring_buffer.cpp
RadixBitmap.cpp
Random.cpp
StringHash.cpp
: $(TARGET_KERNEL_PIC_CCFLAGS) -DUSING_LIBGCC
;