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