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