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