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