xref: /haiku/src/system/boot/loader/file_systems/packagefs/PackageSettingsItem.cpp (revision 3b07762c548ec4016dea480d1061577cd15ec614)
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 <AutoDeleter.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 	int fd = open_from(systemDirectory, settingsFilePath, B_READ_ONLY, 0);
49 	if (fd < 0)
50 		return NULL;
51 	FileDescriptorCloser fdCloser(fd);
52 
53 	// load the driver settings
54 	void* settingsHandle = load_driver_settings_file(fd);
55 	if (settingsHandle == NULL)
56 		return NULL;
57 	CObjectDeleter<void, status_t> settingsDeleter(settingsHandle,
58 		&unload_driver_settings);
59 
60 	const driver_settings* settings = get_driver_settings(settingsHandle);
61 	for (int i = 0; i < settings->parameter_count; i++) {
62 		const driver_parameter& parameter = settings->parameters[i];
63 		if (strcmp(parameter.name, "Package") != 0
64 			|| parameter.value_count < 1
65 			|| strcmp(parameter.values[0], name) != 0) {
66 			continue;
67 		}
68 
69 		PackageSettingsItem* settingsItem
70 			= new(std::nothrow) PackageSettingsItem;
71 		if (settingsItem == NULL || settingsItem->Init(parameter) != B_OK) {
72 			delete settingsItem;
73 			return NULL;
74 		}
75 
76 		return settingsItem;
77 	}
78 
79 	return NULL;
80 }
81 
82 
83 status_t
84 PackageSettingsItem::Init(const driver_parameter& parameter)
85 {
86 	if (fEntries.Init() != B_OK)
87 		return B_NO_MEMORY;
88 
89 	for (int i = 0; i < parameter.parameter_count; i++) {
90 		const driver_parameter& subParameter = parameter.parameters[i];
91 		if (strcmp(subParameter.name, "EntryBlacklist") != 0)
92 			continue;
93 
94 		status_t error = _AddBlackListedEntries(subParameter);
95 		// abort only in case of serious issues (memory shortage)
96 		if (error == B_NO_MEMORY)
97 			return error;
98 	}
99 
100 	return B_OK;
101 }
102 
103 
104 void
105 PackageSettingsItem::AddEntry(Entry* entry)
106 {
107 	fEntries.Insert(entry);
108 }
109 
110 
111 status_t
112 PackageSettingsItem::AddEntry(const char* path, Entry*& _entry)
113 {
114 	Entry* parent = NULL;
115 
116 	while (*path != '\0') {
117 		while (*path == '/') {
118 			path++;
119 			continue;
120 		}
121 
122 		const char* componentEnd = strchr(path, '/');
123 		if (componentEnd == NULL)
124 			componentEnd = path + strlen(path);
125 
126 		const char* name = path;
127 		size_t nameLength = componentEnd - path;
128 
129 		Entry* entry = FindEntry(parent, name, nameLength);
130 		if (entry == NULL) {
131 			entry = new(std::nothrow) Entry(parent);
132 			if (entry == NULL || !entry->SetName(name, nameLength)) {
133 				delete entry;
134 				return B_NO_MEMORY;
135 			}
136 			AddEntry(entry);
137 		}
138 
139 		path = componentEnd;
140 		parent = entry;
141 	}
142 
143 	if (parent == NULL)
144 		return B_BAD_VALUE;
145 
146 	_entry = parent;
147 	return B_OK;
148 }
149 
150 
151 PackageSettingsItem::Entry*
152 PackageSettingsItem::FindEntry(Entry* parent, const char* name) const
153 {
154 	return fEntries.Lookup(EntryKey(parent, name));
155 }
156 
157 
158 PackageSettingsItem::Entry*
159 PackageSettingsItem::FindEntry(Entry* parent, const char* name,
160 	size_t nameLength) const
161 {
162 	return fEntries.Lookup(EntryKey(parent, name, nameLength));
163 }
164 
165 
166 status_t
167 PackageSettingsItem::_AddBlackListedEntries(const driver_parameter& parameter)
168 {
169 	for (int i = 0; i < parameter.parameter_count; i++) {
170 		Entry* entry;
171 		status_t error = AddEntry(parameter.parameters[i].name, entry);
172 		// abort only in case of serious issues (memory shortage)
173 		if (error == B_NO_MEMORY)
174 			return error;
175 
176 		entry->SetBlackListed(true);
177 	}
178 
179 	return B_OK;
180 }
181 
182 
183 }	// namespace PackageFS
184