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