xref: /haiku/src/system/boot/loader/file_systems/packagefs/PackageSettingsItem.cpp (revision 9a6a20d4689307142a7ed26a1437ba47e244e73f)
1 /*
2  * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "PackageSettingsItem.h"
8 
9 #include <driver_settings.h>
10 
11 #include <AutoDeleterDrivers.h>
12 #include <boot/vfs.h>
13 #include <system/directories.h>
14 
15 
16 namespace PackageFS {
17 
18 
19 static const char* const kBlockedEntriesParameterName = "BlockedEntries";
20 static const char* const kLegacyBlockedEntriesParameterName = "EntryBlacklist";
21 
22 
23 // #pragma mark - PackageSettingsItem
24 
25 
26 PackageSettingsItem::PackageSettingsItem()
27 	:
28 	fEntries(),
29 	fHashNext(NULL)
30 {
31 }
32 
33 
34 PackageSettingsItem::~PackageSettingsItem()
35 {
36 	Entry* entry = fEntries.Clear(true);
37 	while (entry != NULL) {
38 		Entry* next = entry->HashNext();
39 		delete entry;
40 		entry = next;
41 	}
42 }
43 
44 
45 /*static*/ PackageSettingsItem*
46 PackageSettingsItem::Load(::Directory* systemDirectory, const char* name)
47 {
48 	// open the driver settings file
49 	const char* settingsFilePath
50 		= &(kSystemSettingsDirectory "/packages")[strlen(kSystemDirectory) + 1];
51 
52 	FileDescriptorCloser fd(open_from(systemDirectory, settingsFilePath,
53 		B_READ_ONLY, 0));
54 	if (!fd.IsSet())
55 		return NULL;
56 
57 	// load the driver settings
58 	DriverSettingsUnloader settingsHandle(load_driver_settings_file(fd.Get()));
59 	if (!settingsHandle.IsSet())
60 		return NULL;
61 
62 	const driver_settings* settings = get_driver_settings(settingsHandle.Get());
63 	for (int i = 0; i < settings->parameter_count; i++) {
64 		const driver_parameter& parameter = settings->parameters[i];
65 		if (strcmp(parameter.name, "Package") != 0
66 			|| parameter.value_count < 1
67 			|| strcmp(parameter.values[0], name) != 0) {
68 			continue;
69 		}
70 
71 		PackageSettingsItem* settingsItem
72 			= new(std::nothrow) PackageSettingsItem;
73 		if (settingsItem == NULL || settingsItem->Init(parameter) != B_OK) {
74 			delete settingsItem;
75 			return NULL;
76 		}
77 
78 		return settingsItem;
79 	}
80 
81 	return NULL;
82 }
83 
84 
85 status_t
86 PackageSettingsItem::Init(const driver_parameter& parameter)
87 {
88 	if (fEntries.Init() != B_OK)
89 		return B_NO_MEMORY;
90 
91 	for (int i = 0; i < parameter.parameter_count; i++) {
92 		const driver_parameter& subParameter = parameter.parameters[i];
93 		if (strcmp(subParameter.name, kBlockedEntriesParameterName) != 0
94 			&& strcmp(subParameter.name, kLegacyBlockedEntriesParameterName)
95 				!= 0)
96 			continue;
97 
98 		status_t error = _AddBlockedEntries(subParameter);
99 		// abort only in case of serious issues (memory shortage)
100 		if (error == B_NO_MEMORY)
101 			return error;
102 	}
103 
104 	return B_OK;
105 }
106 
107 
108 void
109 PackageSettingsItem::AddEntry(Entry* entry)
110 {
111 	fEntries.Insert(entry);
112 }
113 
114 
115 status_t
116 PackageSettingsItem::AddEntry(const char* path, Entry*& _entry)
117 {
118 	Entry* parent = NULL;
119 
120 	while (*path != '\0') {
121 		while (*path == '/') {
122 			path++;
123 			continue;
124 		}
125 
126 		const char* componentEnd = strchr(path, '/');
127 		if (componentEnd == NULL)
128 			componentEnd = path + strlen(path);
129 
130 		const char* name = path;
131 		size_t nameLength = componentEnd - path;
132 
133 		Entry* entry = FindEntry(parent, name, nameLength);
134 		if (entry == NULL) {
135 			entry = new(std::nothrow) Entry(parent);
136 			if (entry == NULL || !entry->SetName(name, nameLength)) {
137 				delete entry;
138 				return B_NO_MEMORY;
139 			}
140 			AddEntry(entry);
141 		}
142 
143 		path = componentEnd;
144 		parent = entry;
145 	}
146 
147 	if (parent == NULL)
148 		return B_BAD_VALUE;
149 
150 	_entry = parent;
151 	return B_OK;
152 }
153 
154 
155 PackageSettingsItem::Entry*
156 PackageSettingsItem::FindEntry(Entry* parent, const char* name) const
157 {
158 	return fEntries.Lookup(EntryKey(parent, name));
159 }
160 
161 
162 PackageSettingsItem::Entry*
163 PackageSettingsItem::FindEntry(Entry* parent, const char* name,
164 	size_t nameLength) const
165 {
166 	return fEntries.Lookup(EntryKey(parent, name, nameLength));
167 }
168 
169 
170 status_t
171 PackageSettingsItem::_AddBlockedEntries(const driver_parameter& parameter)
172 {
173 	for (int i = 0; i < parameter.parameter_count; i++) {
174 		Entry* entry;
175 		status_t error = AddEntry(parameter.parameters[i].name, entry);
176 		// abort only in case of serious issues (memory shortage)
177 		if (error == B_NO_MEMORY)
178 			return error;
179 
180 		entry->SetBlocked(true);
181 	}
182 
183 	return B_OK;
184 }
185 
186 
187 }	// namespace PackageFS
188