xref: /haiku/src/add-ons/kernel/file_systems/packagefs/volume/PackageSettings.cpp (revision 46b7da1f4f40f7157d74fc7fb26ff9ec7f2416f2)
13a7e0b00SIngo Weinhold /*
23a7e0b00SIngo Weinhold  * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
33a7e0b00SIngo Weinhold  * Distributed under the terms of the MIT License.
43a7e0b00SIngo Weinhold  */
53a7e0b00SIngo Weinhold 
63a7e0b00SIngo Weinhold 
73a7e0b00SIngo Weinhold #include "PackageSettings.h"
83a7e0b00SIngo Weinhold 
93a7e0b00SIngo Weinhold #include <driver_settings.h>
103a7e0b00SIngo Weinhold 
11cdccd323SX512 #include <AutoDeleterDrivers.h>
123a7e0b00SIngo Weinhold #include <directories.h>
133a7e0b00SIngo Weinhold #include <fs/KPath.h>
143a7e0b00SIngo Weinhold #include <vfs.h>
153a7e0b00SIngo Weinhold 
163a7e0b00SIngo Weinhold #include "DebugSupport.h"
173a7e0b00SIngo Weinhold 
183a7e0b00SIngo Weinhold 
19560961eeSMurai Takashi static const char* const kBlockedEntriesParameterName = "BlockedEntries";
20560961eeSMurai Takashi static const char* const kLegacyBlockedEntriesParameterName = "EntryBlacklist";
21c04f3a62SIngo Weinhold 
22c04f3a62SIngo Weinhold 
233a7e0b00SIngo Weinhold // #pragma mark - PackageSettingsItem
243a7e0b00SIngo Weinhold 
253a7e0b00SIngo Weinhold 
PackageSettingsItem()263a7e0b00SIngo Weinhold PackageSettingsItem::PackageSettingsItem()
273a7e0b00SIngo Weinhold 	:
283a7e0b00SIngo Weinhold 	fName(),
293a7e0b00SIngo Weinhold 	fEntries()
303a7e0b00SIngo Weinhold {
313a7e0b00SIngo Weinhold }
323a7e0b00SIngo Weinhold 
333a7e0b00SIngo Weinhold 
~PackageSettingsItem()343a7e0b00SIngo Weinhold PackageSettingsItem::~PackageSettingsItem()
353a7e0b00SIngo Weinhold {
363a7e0b00SIngo Weinhold 	Entry* entry = fEntries.Clear(true);
373a7e0b00SIngo Weinhold 	while (entry != NULL) {
383a7e0b00SIngo Weinhold 		Entry* next = entry->HashNext();
393a7e0b00SIngo Weinhold 		delete entry;
403a7e0b00SIngo Weinhold 		entry = next;
413a7e0b00SIngo Weinhold 	}
423a7e0b00SIngo Weinhold }
433a7e0b00SIngo Weinhold 
443a7e0b00SIngo Weinhold 
453a7e0b00SIngo Weinhold status_t
Init(const char * name)46c04f3a62SIngo Weinhold PackageSettingsItem::Init(const char* name)
473a7e0b00SIngo Weinhold {
48c04f3a62SIngo Weinhold 	if (!fName.SetTo(name) || fEntries.Init() != B_OK)
493a7e0b00SIngo Weinhold 		RETURN_ERROR(B_NO_MEMORY);
50c04f3a62SIngo Weinhold 	return B_OK;
51c04f3a62SIngo Weinhold }
523a7e0b00SIngo Weinhold 
53c04f3a62SIngo Weinhold 
54c04f3a62SIngo Weinhold status_t
ApplySettings(const driver_parameter * parameters,int parameterCount)55c04f3a62SIngo Weinhold PackageSettingsItem::ApplySettings(const driver_parameter* parameters,
56c04f3a62SIngo Weinhold 	int parameterCount)
57c04f3a62SIngo Weinhold {
58c04f3a62SIngo Weinhold 	for (int i = 0; i < parameterCount; i++) {
59c04f3a62SIngo Weinhold 		const driver_parameter& subParameter = parameters[i];
60560961eeSMurai Takashi 		if (strcmp(subParameter.name, kBlockedEntriesParameterName) != 0
61560961eeSMurai Takashi 			&& strcmp(subParameter.name, kLegacyBlockedEntriesParameterName)
62560961eeSMurai Takashi 				!= 0)
633a7e0b00SIngo Weinhold 			continue;
643a7e0b00SIngo Weinhold 
65560961eeSMurai Takashi 		status_t error = _AddBlockedEntries(subParameter);
663a7e0b00SIngo Weinhold 		// abort only in case of serious issues (memory shortage)
673a7e0b00SIngo Weinhold 		if (error == B_NO_MEMORY)
683a7e0b00SIngo Weinhold 			return error;
693a7e0b00SIngo Weinhold 	}
703a7e0b00SIngo Weinhold 
713a7e0b00SIngo Weinhold 	return B_OK;
723a7e0b00SIngo Weinhold }
733a7e0b00SIngo Weinhold 
743a7e0b00SIngo Weinhold 
753a7e0b00SIngo Weinhold void
AddEntry(Entry * entry)763a7e0b00SIngo Weinhold PackageSettingsItem::AddEntry(Entry* entry)
773a7e0b00SIngo Weinhold {
783a7e0b00SIngo Weinhold 	fEntries.Insert(entry);
793a7e0b00SIngo Weinhold }
803a7e0b00SIngo Weinhold 
813a7e0b00SIngo Weinhold 
823a7e0b00SIngo Weinhold status_t
AddEntry(const char * path,Entry * & _entry)833a7e0b00SIngo Weinhold PackageSettingsItem::AddEntry(const char* path, Entry*& _entry)
843a7e0b00SIngo Weinhold {
853a7e0b00SIngo Weinhold 	Entry* parent = NULL;
863a7e0b00SIngo Weinhold 
873a7e0b00SIngo Weinhold 	while (*path != '\0') {
883a7e0b00SIngo Weinhold 		while (*path == '/') {
893a7e0b00SIngo Weinhold 			path++;
903a7e0b00SIngo Weinhold 			continue;
913a7e0b00SIngo Weinhold 		}
923a7e0b00SIngo Weinhold 
933a7e0b00SIngo Weinhold 		const char* componentEnd = strchr(path, '/');
943a7e0b00SIngo Weinhold 		if (componentEnd == NULL)
953a7e0b00SIngo Weinhold 			componentEnd = path + strlen(path);
963a7e0b00SIngo Weinhold 
973a7e0b00SIngo Weinhold 		String name;
983a7e0b00SIngo Weinhold 		if (!name.SetTo(path, componentEnd - path))
993a7e0b00SIngo Weinhold 			RETURN_ERROR(B_NO_MEMORY);
1003a7e0b00SIngo Weinhold 
1013a7e0b00SIngo Weinhold 		Entry* entry = FindEntry(parent, name);
1023a7e0b00SIngo Weinhold 		if (entry == NULL) {
1033a7e0b00SIngo Weinhold 			entry = new(std::nothrow) Entry(parent, name);
1043a7e0b00SIngo Weinhold 			if (entry == NULL)
1053a7e0b00SIngo Weinhold 				RETURN_ERROR(B_NO_MEMORY);
1063a7e0b00SIngo Weinhold 			AddEntry(entry);
1073a7e0b00SIngo Weinhold 		}
1083a7e0b00SIngo Weinhold 
1093a7e0b00SIngo Weinhold 		path = componentEnd;
1103a7e0b00SIngo Weinhold 		parent = entry;
1113a7e0b00SIngo Weinhold 	}
1123a7e0b00SIngo Weinhold 
1133a7e0b00SIngo Weinhold 	if (parent == NULL)
1143a7e0b00SIngo Weinhold 		return B_BAD_VALUE;
1153a7e0b00SIngo Weinhold 
1163a7e0b00SIngo Weinhold 	_entry = parent;
1173a7e0b00SIngo Weinhold 	return B_OK;
1183a7e0b00SIngo Weinhold }
1193a7e0b00SIngo Weinhold 
1203a7e0b00SIngo Weinhold 
1213a7e0b00SIngo Weinhold PackageSettingsItem::Entry*
FindEntry(Entry * parent,const String & name) const1223a7e0b00SIngo Weinhold PackageSettingsItem::FindEntry(Entry* parent, const String& name) const
1233a7e0b00SIngo Weinhold {
1243a7e0b00SIngo Weinhold 	return fEntries.Lookup(EntryKey(parent, name));
1253a7e0b00SIngo Weinhold }
1263a7e0b00SIngo Weinhold 
1273a7e0b00SIngo Weinhold 
1283a7e0b00SIngo Weinhold PackageSettingsItem::Entry*
FindEntry(Entry * parent,const char * name) const1293a7e0b00SIngo Weinhold PackageSettingsItem::FindEntry(Entry* parent, const char* name) const
1303a7e0b00SIngo Weinhold {
1313a7e0b00SIngo Weinhold 	return fEntries.Lookup(EntryKey(parent, name));
1323a7e0b00SIngo Weinhold }
1333a7e0b00SIngo Weinhold 
1343a7e0b00SIngo Weinhold 
1353a7e0b00SIngo Weinhold status_t
_AddBlockedEntries(const driver_parameter & parameter)136560961eeSMurai Takashi PackageSettingsItem::_AddBlockedEntries(const driver_parameter& parameter)
1373a7e0b00SIngo Weinhold {
1383a7e0b00SIngo Weinhold 	for (int i = 0; i < parameter.parameter_count; i++) {
1393a7e0b00SIngo Weinhold 		Entry* entry;
1403a7e0b00SIngo Weinhold 		status_t error = AddEntry(parameter.parameters[i].name, entry);
1413a7e0b00SIngo Weinhold 		// abort only in case of serious issues (memory shortage)
1423a7e0b00SIngo Weinhold 		if (error == B_NO_MEMORY)
1433a7e0b00SIngo Weinhold 			return error;
1443a7e0b00SIngo Weinhold 
145560961eeSMurai Takashi 		entry->SetBlocked(true);
1463a7e0b00SIngo Weinhold 	}
1473a7e0b00SIngo Weinhold 
1483a7e0b00SIngo Weinhold 	return B_OK;
1493a7e0b00SIngo Weinhold }
1503a7e0b00SIngo Weinhold 
1513a7e0b00SIngo Weinhold 
1523a7e0b00SIngo Weinhold // #pragma mark - PackageSettings
1533a7e0b00SIngo Weinhold 
1543a7e0b00SIngo Weinhold 
PackageSettings()1553a7e0b00SIngo Weinhold PackageSettings::PackageSettings()
1563a7e0b00SIngo Weinhold 	:
1573a7e0b00SIngo Weinhold 	fPackageItems()
1583a7e0b00SIngo Weinhold {
1593a7e0b00SIngo Weinhold }
1603a7e0b00SIngo Weinhold 
1613a7e0b00SIngo Weinhold 
~PackageSettings()1623a7e0b00SIngo Weinhold PackageSettings::~PackageSettings()
1633a7e0b00SIngo Weinhold {
1643a7e0b00SIngo Weinhold 	PackageSettingsItem* item = fPackageItems.Clear(true);
1653a7e0b00SIngo Weinhold 	while (item != NULL) {
1663a7e0b00SIngo Weinhold 		PackageSettingsItem* next = item->HashNext();
1673a7e0b00SIngo Weinhold 		delete item;
1683a7e0b00SIngo Weinhold 		item = next;
1693a7e0b00SIngo Weinhold 	}
1703a7e0b00SIngo Weinhold }
1713a7e0b00SIngo Weinhold 
1723a7e0b00SIngo Weinhold 
1733a7e0b00SIngo Weinhold status_t
Load(dev_t mountPointDeviceID,ino_t mountPointNodeID,PackageFSMountType mountType)1743a7e0b00SIngo Weinhold PackageSettings::Load(dev_t mountPointDeviceID, ino_t mountPointNodeID,
1753a7e0b00SIngo Weinhold 	PackageFSMountType mountType)
1763a7e0b00SIngo Weinhold {
1773a7e0b00SIngo Weinhold 	status_t error = fPackageItems.Init();
1783a7e0b00SIngo Weinhold 	if (error != B_OK)
1793a7e0b00SIngo Weinhold 		RETURN_ERROR(error);
1803a7e0b00SIngo Weinhold 
181c04f3a62SIngo Weinhold 	// First get the safe mode options. Those apply to the system package.
182c04f3a62SIngo Weinhold 	if (mountType == PACKAGE_FS_MOUNT_TYPE_SYSTEM) {
183c04f3a62SIngo Weinhold 		void* settingsHandle = load_driver_settings(B_SAFEMODE_DRIVER_SETTINGS);
184c04f3a62SIngo Weinhold 		if (settingsHandle != NULL) {
185c04f3a62SIngo Weinhold 			if (const driver_settings* settings
186c04f3a62SIngo Weinhold 					= get_driver_settings(settingsHandle)) {
187c04f3a62SIngo Weinhold 				error = _AddPackageSettingsItem("haiku", settings->parameters,
188c04f3a62SIngo Weinhold 					settings->parameter_count);
189c04f3a62SIngo Weinhold 				// abort only in case of serious issues (memory shortage)
190c04f3a62SIngo Weinhold 				if (error == B_NO_MEMORY)
191c04f3a62SIngo Weinhold 					return error;
192c04f3a62SIngo Weinhold 			}
193c04f3a62SIngo Weinhold 			unload_driver_settings(settingsHandle);
194c04f3a62SIngo Weinhold 		}
195c04f3a62SIngo Weinhold 	}
196c04f3a62SIngo Weinhold 
1973a7e0b00SIngo Weinhold 	// get the mount point relative settings file path
1983a7e0b00SIngo Weinhold 	const char* settingsFilePath = mountType == PACKAGE_FS_MOUNT_TYPE_HOME
19939be4f89SX512 		? &(kUserSettingsGlobalDirectory "/packages")
20039be4f89SX512 			[strlen(kUserConfigDirectory) + 1]
20139be4f89SX512 		: &(kSystemSettingsDirectory "/packages")[strlen(kSystemDirectory) + 1];
2023a7e0b00SIngo Weinhold 
2033a7e0b00SIngo Weinhold 	// get an absolute path
2043a7e0b00SIngo Weinhold 	KPath path;
2053a7e0b00SIngo Weinhold 	if (path.InitCheck() != B_OK)
2063a7e0b00SIngo Weinhold 		RETURN_ERROR(path.InitCheck());
2073a7e0b00SIngo Weinhold 
2083a7e0b00SIngo Weinhold 	error = vfs_entry_ref_to_path(mountPointDeviceID, mountPointNodeID,
2093a7e0b00SIngo Weinhold 		NULL, true, path.LockBuffer(), path.BufferSize());
2103a7e0b00SIngo Weinhold 	if (error != B_OK)
2113a7e0b00SIngo Weinhold 		return error;
2123a7e0b00SIngo Weinhold 	path.UnlockBuffer();
2133a7e0b00SIngo Weinhold 
2143a7e0b00SIngo Weinhold 	error = path.Append(settingsFilePath);
2153a7e0b00SIngo Weinhold 	if (error != B_OK)
2163a7e0b00SIngo Weinhold 		return error;
2173a7e0b00SIngo Weinhold 
2183a7e0b00SIngo Weinhold 	// load the driver settings
219*fce7f3a7SX512 	DriverSettingsUnloader settingsHandle(load_driver_settings(path.Path()));
220*fce7f3a7SX512 	if (!settingsHandle.IsSet())
2213a7e0b00SIngo Weinhold 		return B_ENTRY_NOT_FOUND;
2223a7e0b00SIngo Weinhold 
223*fce7f3a7SX512 	const driver_settings* settings
224*fce7f3a7SX512 		= get_driver_settings(settingsHandle.Get());
2253a7e0b00SIngo Weinhold 	for (int i = 0; i < settings->parameter_count; i++) {
2263a7e0b00SIngo Weinhold 		const driver_parameter& parameter = settings->parameters[i];
2273a7e0b00SIngo Weinhold 		if (strcmp(parameter.name, "Package") != 0
2283a7e0b00SIngo Weinhold 			|| parameter.value_count < 1) {
2293a7e0b00SIngo Weinhold 			continue;
2303a7e0b00SIngo Weinhold 		}
2313a7e0b00SIngo Weinhold 
232c04f3a62SIngo Weinhold 		error = _AddPackageSettingsItem(parameter.values[0],
233c04f3a62SIngo Weinhold 			parameter.parameters, parameter.parameter_count);
2343a7e0b00SIngo Weinhold 		// abort only in case of serious issues (memory shortage)
2353a7e0b00SIngo Weinhold 		if (error == B_NO_MEMORY)
2363a7e0b00SIngo Weinhold 			return error;
2373a7e0b00SIngo Weinhold 	}
2383a7e0b00SIngo Weinhold 
2393a7e0b00SIngo Weinhold 	return B_OK;
2403a7e0b00SIngo Weinhold }
2413a7e0b00SIngo Weinhold 
2423a7e0b00SIngo Weinhold 
2433a7e0b00SIngo Weinhold const PackageSettingsItem*
PackageItemFor(const String & name) const2443a7e0b00SIngo Weinhold PackageSettings::PackageItemFor(const String& name) const
2453a7e0b00SIngo Weinhold {
2463a7e0b00SIngo Weinhold 	return fPackageItems.Lookup(name);
2473a7e0b00SIngo Weinhold }
2483a7e0b00SIngo Weinhold 
2493a7e0b00SIngo Weinhold 
2503a7e0b00SIngo Weinhold status_t
_AddPackageSettingsItem(const char * name,const driver_parameter * parameters,int parameterCount)251c04f3a62SIngo Weinhold PackageSettings::_AddPackageSettingsItem(const char* name,
252c04f3a62SIngo Weinhold 	const driver_parameter* parameters, int parameterCount)
2533a7e0b00SIngo Weinhold {
254c04f3a62SIngo Weinhold 	// get/create the package item
255c04f3a62SIngo Weinhold 	PackageSettingsItem* packageItem = fPackageItems.Lookup(StringKey(name));
256c04f3a62SIngo Weinhold 	if (packageItem == NULL) {
257c04f3a62SIngo Weinhold 		packageItem = new(std::nothrow) PackageSettingsItem;
258c04f3a62SIngo Weinhold 		if (packageItem == NULL || packageItem->Init(name) != B_OK) {
2593a7e0b00SIngo Weinhold 			delete packageItem;
2603a7e0b00SIngo Weinhold 			RETURN_ERROR(B_NO_MEMORY);
2613a7e0b00SIngo Weinhold 		}
2623a7e0b00SIngo Weinhold 
2633a7e0b00SIngo Weinhold 		fPackageItems.Insert(packageItem);
264c04f3a62SIngo Weinhold 	}
265c04f3a62SIngo Weinhold 
266c04f3a62SIngo Weinhold 	// apply the settings
267c04f3a62SIngo Weinhold 	return packageItem->ApplySettings(parameters, parameterCount);
2683a7e0b00SIngo Weinhold }
269