1// Settings.cpp 2 3#include <new> 4 5#include <stdio.h> 6#include <stdlib.h> 7 8#include <driver_settings.h> 9#include <FindDirectory.h> 10 11#include "Debug.h" 12#include "HashMap.h" 13#include "IOCtlInfo.h" 14#include "Settings.h" 15 16using std::nothrow; 17 18static const directory_which kDirectories[] = { 19 B_USER_NONPACKAGED_DATA_DIRECTORY, 20 B_USER_DATA_DIRECTORY, 21 B_SYSTEM_NONPACKAGED_DATA_DIRECTORY, 22 B_SYSTEM_DATA_DIRECTORY 23}; 24static const char *kFSSubpath = "/userlandfs/file_systems/"; 25 26// IOCtlInfoMap 27struct Settings::IOCtlInfoMap : public HashMap<HashKey32<int>, IOCtlInfo*> { 28}; 29 30 31// _FindNextParameter 32template<typename container_t> 33static 34const driver_parameter * 35_FindNextParameter(const container_t *container, const char *name, 36 int32 &cookie) 37{ 38 const driver_parameter *parameter = NULL; 39 if (container) { 40 for (; !parameter && cookie < container->parameter_count; cookie++) { 41 const driver_parameter ¶m = container->parameters[cookie]; 42 if (!strcmp(param.name, name)) 43 parameter = ¶m; 44 } 45 } 46 return parameter; 47} 48 49// _GetParameterValue 50template<typename container_t> 51static 52const char * 53_GetParameterValue(const container_t *container, const char *name, 54 const char *unknownValue, const char *noArgValue) 55{ 56 if (container) { 57 for (int32 i = container->parameter_count - 1; i >= 0; i--) { 58 const driver_parameter ¶m = container->parameters[i]; 59 if (!strcmp(param.name, name)) { 60 if (param.value_count > 0) 61 return param.values[0]; 62 return noArgValue; 63 } 64 } 65 } 66 return unknownValue; 67} 68 69// contains 70static inline 71bool 72contains(const char **array, size_t size, const char *value) 73{ 74 for (int32 i = 0; i < (int32)size; i++) { 75 if (!strcmp(array[i], value)) 76 return true; 77 } 78 return false; 79} 80 81// _GetParameterValue 82template<typename container_t> 83static 84bool 85_GetParameterValue(const container_t *container, const char *name, 86 bool unknownValue, bool noArgValue) 87{ 88 // note: container may be NULL 89 const char unknown = 0; 90 const char noArg = 0; 91 const char *value = _GetParameterValue(container, name, &unknown, &noArg); 92 if (value == &unknown) 93 return unknownValue; 94 if (value == &noArg) 95 return noArgValue; 96 const char *trueStrings[] 97 = { "1", "true", "yes", "on", "enable", "enabled" }; 98 const char *falseStrings[] 99 = { "0", "false", "no", "off", "disable", "disabled" }; 100 if (contains(trueStrings, sizeof(trueStrings) / sizeof(const char*), 101 value)) { 102 return true; 103 } 104 if (contains(falseStrings, sizeof(falseStrings) / sizeof(const char*), 105 value)) { 106 return false; 107 } 108 return unknownValue; 109} 110 111// _GetParameterValue 112template<typename container_t> 113static 114int 115_GetParameterValue(const container_t *container, const char *name, 116 int unknownValue, int noArgValue) 117{ 118 // note: container may be NULL 119 const char unknown = 0; 120 const char noArg = 0; 121 const char *value = _GetParameterValue(container, name, &unknown, &noArg); 122 if (value == &unknown) 123 return unknownValue; 124 if (value == &noArg) 125 return noArgValue; 126 return atoi(value); 127} 128 129// _FindFSParameter 130static 131const driver_parameter * 132_FindFSParameter(const driver_settings *settings, const char *name) 133{ 134 if (settings) { 135 int32 cookie = 0; 136 while (const driver_parameter *parameter 137 = _FindNextParameter(settings, "file_system", cookie)) { 138PRINT((" found file_system parameter\n")); 139if (parameter->value_count > 0) 140PRINT((" value: `%s'\n", parameter->values[0])); 141 if (parameter->value_count == 1 142 && !strcmp(parameter->values[0], name)) { 143 return parameter; 144 } 145 } 146 } 147 return NULL; 148} 149 150// constructor 151Settings::Settings() 152 : fIOCtlInfos(NULL) 153{ 154} 155 156// destructor 157Settings::~Settings() 158{ 159 Unset(); 160} 161 162// SetTo 163status_t 164Settings::SetTo(const char* fsName) 165{ 166 if (!fsName) 167 RETURN_ERROR(B_BAD_VALUE); 168 // unset 169 Unset(); 170 // create the ioctl info map 171 fIOCtlInfos = new(nothrow) IOCtlInfoMap; 172 if (!fIOCtlInfos) 173 RETURN_ERROR(B_NO_MEMORY); 174 175 // load the driver settings for the FS 176 char path[B_PATH_NAME_LENGTH]; 177 for (size_t i = 0; i < sizeof(kDirectories) / sizeof(kDirectories[0]); 178 i++) { 179 if (find_directory(kDirectories[i], -1, false, (char*)&path, 180 B_PATH_NAME_LENGTH) != B_OK) { 181 continue; 182 } 183 184 // construct the path within the directory 185 strlcat(path, kFSSubpath, B_PATH_NAME_LENGTH); 186 strlcat(path, fsName, B_PATH_NAME_LENGTH); 187 188 // load the file at the constructed path 189 void *settings = load_driver_settings((char*)&path); 190 if (!settings) 191 continue; 192 193 // get the settings from the loaded file 194 const driver_settings *ds = get_driver_settings(settings); 195 if (!ds) { 196 unload_driver_settings(settings); 197 continue; 198 } 199 200 // get the parameter from the settings 201 const driver_parameter *fsParameter = NULL; 202 fsParameter = _FindFSParameter(ds, fsName); 203 204 // init the object and unload the settings 205 if (fsParameter) 206 _Init(ds, fsParameter); 207 unload_driver_settings(settings); 208 209 // if we found the parameter, we're done 210 if (fsParameter) 211 return B_OK; 212 } 213 214 // if we get here, we did not find the parameter 215 return B_ENTRY_NOT_FOUND; 216} 217 218// Unset 219void 220Settings::Unset() 221{ 222 if (fIOCtlInfos) { 223 for (IOCtlInfoMap::Iterator it = fIOCtlInfos->GetIterator(); 224 it.HasNext();) { 225 IOCtlInfoMap::Entry entry = it.Next(); 226 delete entry.value; 227 } 228 delete fIOCtlInfos; 229 fIOCtlInfos = NULL; 230 } 231} 232 233// GetIOCtlInfo 234const IOCtlInfo* 235Settings::GetIOCtlInfo(int command) const 236{ 237 return (fIOCtlInfos ? fIOCtlInfos->Get(command) : NULL); 238} 239 240// Dump 241void 242Settings::Dump() const 243{ 244 D( 245 PRINT(("Settings:\n")); 246 if (fIOCtlInfos) { 247 for (IOCtlInfoMap::Iterator it = fIOCtlInfos->GetIterator(); 248 it.HasNext();) { 249 IOCtlInfoMap::Entry entry = it.Next(); 250 IOCtlInfo* info = entry.value; 251 PRINT((" ioctl %d: buffer size: %" B_PRId32 252 ", write buffer size: %" B_PRId32 "\n", info->command, 253 info->bufferSize, info->writeBufferSize)); 254 } 255 } 256 ) 257} 258 259// _Init 260status_t 261Settings::_Init(const driver_settings *settings, 262 const driver_parameter *fsParams) 263{ 264PRINT(("Settings::_Init(%p, %p)\n", settings, fsParams)); 265 status_t error = B_OK; 266 int32 cookie = 0; 267 while (const driver_parameter *parameter 268 = _FindNextParameter(fsParams, "ioctl", cookie)) { 269 if (parameter->value_count == 1) { 270 int command = atoi(parameter->values[0]); 271 if (command > 0) { 272 IOCtlInfo* info = fIOCtlInfos->Remove(command); 273 if (!info) { 274 info = new(nothrow) IOCtlInfo; 275 if (!info) 276 RETURN_ERROR(B_NO_MEMORY); 277 } 278 info->command = command; 279 info->bufferSize 280 = _GetParameterValue(parameter, "buffer_size", 0, 0); 281 info->writeBufferSize 282 = _GetParameterValue(parameter, "write_buffer_size", 0, 0); 283 info->isBuffer = _GetParameterValue(parameter, "is_buffer", 284 false, false); 285 error = fIOCtlInfos->Put(command, info); 286 if (error != B_OK) { 287 delete info; 288 return error; 289 } 290 } 291 } 292 } 293PRINT(("Settings::_Init() done: %s\n", strerror(error))); 294 return error; 295} 296 297