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
16 using std::nothrow;
17
18 static 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 };
24 static const char *kFSSubpath = "/userlandfs/file_systems/";
25
26 // IOCtlInfoMap
27 struct Settings::IOCtlInfoMap : public HashMap<HashKey32<int>, IOCtlInfo*> {
28 };
29
30
31 // _FindNextParameter
32 template<typename container_t>
33 static
34 const driver_parameter *
_FindNextParameter(const container_t * container,const char * name,int32 & cookie)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
50 template<typename container_t>
51 static
52 const char *
_GetParameterValue(const container_t * container,const char * name,const char * unknownValue,const char * noArgValue)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
70 static inline
71 bool
contains(const char ** array,size_t size,const char * value)72 contains(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
82 template<typename container_t>
83 static
84 bool
_GetParameterValue(const container_t * container,const char * name,bool unknownValue,bool noArgValue)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
112 template<typename container_t>
113 static
114 int
_GetParameterValue(const container_t * container,const char * name,int unknownValue,int noArgValue)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
130 static
131 const driver_parameter *
_FindFSParameter(const driver_settings * settings,const char * name)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)) {
138 PRINT((" found file_system parameter\n"));
139 if (parameter->value_count > 0)
140 PRINT((" 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
Settings()151 Settings::Settings()
152 : fIOCtlInfos(NULL)
153 {
154 }
155
156 // destructor
~Settings()157 Settings::~Settings()
158 {
159 Unset();
160 }
161
162 // SetTo
163 status_t
SetTo(const char * fsName)164 Settings::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
219 void
Unset()220 Settings::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
234 const IOCtlInfo*
GetIOCtlInfo(int command) const235 Settings::GetIOCtlInfo(int command) const
236 {
237 return (fIOCtlInfos ? fIOCtlInfos->Get(command) : NULL);
238 }
239
240 // Dump
241 void
Dump() const242 Settings::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
260 status_t
_Init(const driver_settings * settings,const driver_parameter * fsParams)261 Settings::_Init(const driver_settings *settings,
262 const driver_parameter *fsParams)
263 {
264 PRINT(("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 }
293 PRINT(("Settings::_Init() done: %s\n", strerror(error)));
294 return error;
295 }
296
297