xref: /haiku/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Settings.cpp (revision 1acbe440b8dd798953bec31d18ee589aa3f71b73)
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 &param = container->parameters[cookie];
34 			if (!strcmp(param.name, name))
35 				parameter = &param;
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 &param = 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