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