btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / system / kernel / debug / safemode_settings.cpp
blobc0a6ca6ebd2998301cb8b44f3716a65e01f9e18f
1 /*
2 * Copyright 2004-2009, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include <safemode.h>
9 #include <ctype.h>
10 #include <string.h>
11 #include <strings.h>
13 #include <algorithm>
15 #include <KernelExport.h>
17 #include <boot/kernel_args.h>
18 #include <kernel.h>
19 #include <syscalls.h>
22 #ifndef _BOOT_MODE
25 static status_t
26 get_option_from_kernel_args(kernel_args* args, const char* settingsName,
27 const char* parameter, size_t parameterLength, char* buffer,
28 size_t* _bufferSize)
30 // find the settings in the kernel args
31 const char* settings = NULL;
32 for (driver_settings_file* file = args->driver_settings;
33 file != NULL; file = file->next) {
34 if (strcmp(settingsName, file->name) == 0) {
35 settings = file->buffer;
36 break;
40 if (settings == NULL)
41 return B_ENTRY_NOT_FOUND;
43 // Unfortunately we can't just use parse_driver_settings_string(), since
44 // we might not have a working heap yet. So we do very limited parsing
45 // ourselves.
46 const char* settingsEnd = settings + strlen(settings);
47 int32 parameterLevel = 0;
49 while (*settings != '\0') {
50 // find end of line
51 const char* lineEnd = strchr(settings, '\n');
52 const char* nextLine;
53 if (lineEnd != NULL)
54 nextLine = lineEnd + 1;
55 else
56 nextLine = lineEnd = settingsEnd;
58 // ignore any trailing comments
59 lineEnd = std::find(settings, lineEnd, '#');
61 const char* nameStart = NULL;
62 const char* nameEnd = NULL;
63 const char* valueStart = NULL;
64 const char* valueEnd = NULL;
65 const char** elementEnd = NULL;
66 bool sawSeparator = true;
68 for (; settings < lineEnd; settings++) {
69 switch (*settings) {
70 case '{':
71 parameterLevel++;
72 sawSeparator = true;
73 break;
75 case '}':
76 parameterLevel--;
77 sawSeparator = true;
78 break;
80 case ';':
81 // TODO: That's not correct. There should be another loop.
82 sawSeparator = true;
83 break;
85 default:
86 if (parameterLevel != 0)
87 break;
89 if (isspace(*settings)) {
90 sawSeparator = true;
91 break;
94 if (!sawSeparator)
95 break;
97 sawSeparator = false;
99 if (nameStart == NULL) {
100 nameStart = settings;
101 elementEnd = &nameEnd;
102 } else if (valueStart == NULL) {
103 valueStart = settings;
104 elementEnd = &valueEnd;
106 break;
109 if (sawSeparator && elementEnd != NULL) {
110 *elementEnd = settings;
111 elementEnd = NULL;
115 if (elementEnd != NULL)
116 *elementEnd = settings;
118 if (nameStart != NULL && size_t(nameEnd - nameStart) == parameterLength
119 && strncmp(parameter, nameStart, parameterLength) == 0) {
120 if (valueStart == NULL)
121 return B_NAME_NOT_FOUND;
123 size_t length = valueEnd - valueStart;
124 if (*_bufferSize > 0) {
125 size_t toCopy = std::min(length, *_bufferSize - 1);
126 memcpy(buffer, valueStart, toCopy);
127 buffer[toCopy] = '\0';
130 *_bufferSize = length;
131 return B_OK;
134 settings = nextLine;
137 return B_NAME_NOT_FOUND;
141 #endif // !_BOOT_MODE
144 static status_t
145 get_option(kernel_args* args, const char* settingsName, const char* parameter,
146 size_t parameterLength, char* buffer, size_t* _bufferSize)
148 #ifndef _BOOT_MODE
149 if (args != NULL) {
150 return get_option_from_kernel_args(args, settingsName, parameter,
151 parameterLength, buffer, _bufferSize);
153 #endif
155 void* handle = load_driver_settings(settingsName);
156 if (handle == NULL)
157 return B_ENTRY_NOT_FOUND;
159 status_t status = B_NAME_NOT_FOUND;
161 const char* value = get_driver_parameter(handle, parameter, NULL, NULL);
162 if (value != NULL) {
163 *_bufferSize = strlcpy(buffer, value, *_bufferSize);
164 status = B_OK;
167 unload_driver_settings(handle);
168 return status;
172 static status_t
173 get_option(kernel_args* args, const char* parameter, char* buffer,
174 size_t* _bufferSize)
176 size_t parameterLength = strlen(parameter);
177 status_t status = get_option(args, B_SAFEMODE_DRIVER_SETTINGS, parameter,
178 parameterLength, buffer, _bufferSize);
179 if (status != B_OK) {
180 // Try kernel settings file as a fall back
181 status = get_option(args, "kernel", parameter, parameterLength, buffer,
182 _bufferSize);
185 return status;
189 static bool
190 get_boolean(kernel_args* args, const char* parameter, bool defaultValue)
192 char value[16];
193 size_t length = sizeof(value);
195 if (get_option(args, parameter, value, &length) != B_OK)
196 return defaultValue;
198 return !strcasecmp(value, "on") || !strcasecmp(value, "true")
199 || !strcmp(value, "1") || !strcasecmp(value, "yes")
200 || !strcasecmp(value, "enabled");
204 // #pragma mark -
207 status_t
208 get_safemode_option(const char* parameter, char* buffer, size_t* _bufferSize)
210 return get_option(NULL, parameter, buffer, _bufferSize);
214 bool
215 get_safemode_boolean(const char* parameter, bool defaultValue)
217 return get_boolean(NULL, parameter, defaultValue);
221 #ifndef _BOOT_MODE
224 status_t
225 get_safemode_option_early(kernel_args* args, const char* parameter,
226 char* buffer, size_t* _bufferSize)
228 return get_option(args, parameter, buffer, _bufferSize);
232 bool
233 get_safemode_boolean_early(kernel_args* args, const char* parameter,
234 bool defaultValue)
236 return get_boolean(args, parameter, defaultValue);
240 #endif // _BOOT_MODE
243 // #pragma mark - syscalls
246 #ifndef _BOOT_MODE
249 extern "C" status_t
250 _user_get_safemode_option(const char* userParameter, char* userBuffer,
251 size_t* _userBufferSize)
253 char parameter[B_FILE_NAME_LENGTH];
254 char buffer[B_PATH_NAME_LENGTH];
255 size_t bufferSize, originalBufferSize;
257 if (!IS_USER_ADDRESS(userParameter) || !IS_USER_ADDRESS(userBuffer)
258 || !IS_USER_ADDRESS(_userBufferSize)
259 || user_memcpy(&bufferSize, _userBufferSize, sizeof(size_t)) != B_OK
260 || user_strlcpy(parameter, userParameter, B_FILE_NAME_LENGTH) < B_OK)
261 return B_BAD_ADDRESS;
263 if (bufferSize > B_PATH_NAME_LENGTH)
264 bufferSize = B_PATH_NAME_LENGTH;
266 originalBufferSize = bufferSize;
267 status_t status = get_safemode_option(parameter, buffer, &bufferSize);
269 if (status == B_OK
270 && (user_strlcpy(userBuffer, buffer, originalBufferSize) < B_OK
271 || user_memcpy(_userBufferSize, &bufferSize, sizeof(size_t))
272 != B_OK))
273 return B_BAD_ADDRESS;
275 return status;
279 #endif // !_BOOT_MODE