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
PackageSettingsItem()26 PackageSettingsItem::PackageSettingsItem()
27 :
28 fEntries(),
29 fHashNext(NULL)
30 {
31 }
32
33
~PackageSettingsItem()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*
Load(::Directory * systemDirectory,const char * name)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
Init(const driver_parameter & parameter)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
AddEntry(Entry * entry)109 PackageSettingsItem::AddEntry(Entry* entry)
110 {
111 fEntries.Insert(entry);
112 }
113
114
115 status_t
AddEntry(const char * path,Entry * & _entry)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*
FindEntry(Entry * parent,const char * name) const156 PackageSettingsItem::FindEntry(Entry* parent, const char* name) const
157 {
158 return fEntries.Lookup(EntryKey(parent, name));
159 }
160
161
162 PackageSettingsItem::Entry*
FindEntry(Entry * parent,const char * name,size_t nameLength) const163 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
_AddBlockedEntries(const driver_parameter & parameter)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