clarify the gui
[open-ps2-loader.git] / src / config.c
bloba0a4503a8a1bb848325710aed466e6a230c2daf7
1 /*
2 Copyright 2009, Ifcaro & volca
3 Licenced under Academic Free License version 3.0
4 Review OpenUsbLd README & LICENSE files for further details.
5 */
7 #include "include/usbld.h"
8 #include "include/util.h"
9 #include "include/ioman.h"
10 #include <string.h>
12 #define CONFIG_INDEX_OPL 0
13 #define CONFIG_INDEX_LAST 1
14 #define CONFIG_INDEX_APPS 2
15 #define CONFIG_INDEX_VMODE 3
17 static config_set_t configFiles[CONFIG_FILE_NUM];
18 static char configPath[255] = "mc?:SYS-CONF/IPCONFIG.DAT";
20 static int strToColor(const char *string, unsigned char *color) {
21 int cnt=0, n=0;
22 color[0]=0;
23 color[1]=0;
24 color[2]=0;
26 if (!string || !*string) return 0;
27 if (string[0]!='#') return 0;
29 string++;
31 while (*string) {
32 int fh = fromHex(*string);
33 if (fh >= 0) {
34 color[n] = color[n] * 16 + fh;
35 } else {
36 break;
39 // Two characters per color
40 if(cnt==1) {
41 cnt=0;
42 n++;
43 }else{
44 cnt++;
47 string++;
50 return 1;
53 /// true if given a whitespace character
54 int isWS(char c) {
55 return c == ' ' || c == '\t';
58 static int splitAssignment(char* line, char* key, size_t keymax, char* val, size_t valmax) {
59 // skip whitespace
60 for (;isWS(*line); ++line);
62 // find "=".
63 // If found, the text before is key, after is val.
64 // Otherwise malformed string is encountered
66 char* eqpos = strchr(line, '=');
68 if (eqpos) {
69 // copy the name and the value
70 size_t keylen = min(keymax, eqpos - line);
72 strncpy(key, line, keylen);
74 eqpos++;
76 size_t vallen = min(valmax, strlen(line) - (eqpos - line));
77 strncpy(val, eqpos, vallen);
80 return (int) eqpos;
83 static int parsePrefix(char* line, char* prefix) {
84 // find "=".
85 // If found, the text before is key, after is val.
86 // Otherwise malformed string is encountered
87 char* colpos = strchr(line, ':');
89 if (colpos && colpos != line) {
90 // copy the name and the value
91 strncpy(prefix, line, colpos - line);
93 return 1;
94 } else {
95 return 0;
99 static int configKeyValidate(const char* key) {
100 if (strlen(key) == 0)
101 return 0;
103 return !strchr(key, '=');
106 static struct config_value_t* allocConfigItem(const char* key, const char* val) {
107 struct config_value_t* it = (struct config_value_t*) malloc(sizeof(struct config_value_t));
108 strncpy(it->key, key, 32);
109 it->key[min(strlen(key), 31)] = '\0';
110 strncpy(it->val, val, 255);
111 it->val[min(strlen(val), 254)] = '\0';
112 it->next = NULL;
114 return it;
117 /// Low level key addition. Does not check for uniqueness.
118 static void addConfigValue(config_set_t* configSet, const char* key, const char* val) {
119 if (!configSet->tail) {
120 configSet->head = allocConfigItem(key, val);
121 configSet->tail = configSet->head;
122 } else {
123 configSet->tail->next = allocConfigItem(key, val);
124 configSet->tail = configSet->tail->next;
128 static struct config_value_t* getConfigItemForName(config_set_t* configSet, const char* name) {
129 struct config_value_t* val = configSet->head;
131 while (val) {
132 if (strncmp(val->key, name, 32) == 0)
133 break;
135 val = val->next;
138 return val;
141 void configInit(char *prefix) {
142 char path[255];
144 if (prefix)
145 snprintf(configPath, 255, "%s/IPCONFIG.DAT", prefix);
146 else
147 prefix = gBaseMCDir;
149 snprintf(path, 255, "%s/conf_opl.cfg", prefix);
150 configAlloc(CONFIG_OPL, &configFiles[CONFIG_INDEX_OPL], path);
151 snprintf(path, 255, "%s/conf_last.cfg", prefix);
152 configAlloc(CONFIG_LAST, &configFiles[CONFIG_INDEX_LAST], path);
153 snprintf(path, 255, "%s/conf_apps.cfg", prefix);
154 configAlloc(CONFIG_APPS, &configFiles[CONFIG_INDEX_APPS], path);
155 snprintf(path, 255, "%s/conf_vmode.cfg", prefix);
156 configAlloc(CONFIG_VMODE, &configFiles[CONFIG_INDEX_VMODE], path);
159 void configEnd() {
160 int index = 0;
161 while(index < CONFIG_FILE_NUM) {
162 config_set_t *configSet = &configFiles[index];
164 configClear(configSet);
165 free(configSet->filename);
166 configSet->filename = NULL;
167 index++;
171 config_set_t *configAlloc(int type, config_set_t *configSet, char *fileName) {
172 if (!configSet)
173 configSet = (config_set_t*) malloc(sizeof(config_set_t));
175 configSet->type = type;
176 configSet->head = NULL;
177 configSet->tail = NULL;
178 if (fileName) {
179 int length = strlen(fileName) + 1;
180 configSet->filename = (char*) malloc(length * sizeof(char));
181 memcpy(configSet->filename, fileName, length);
182 } else
183 configSet->filename = NULL;
184 configSet->modified = 0;
185 return configSet;
188 void configFree(config_set_t *configSet) {
189 configClear(configSet);
190 free(configSet->filename);
191 free(configSet);
192 configSet = NULL;
195 config_set_t *configGetByType(int type) {
196 int index = 0;
197 while(index < CONFIG_FILE_NUM) {
198 config_set_t *configSet = &configFiles[index];
200 if (configSet->type == type)
201 return configSet;
202 index++;
204 return NULL;
207 int configSetStr(config_set_t* configSet, const char* key, const char* value) {
208 if (!configKeyValidate(key))
209 return 0;
211 struct config_value_t *it = getConfigItemForName(configSet, key);
213 if (it) {
214 if (strncmp(it->val, value, 255) != 0) {
215 strncpy(it->val, value, 255);
216 it->val[min(strlen(value), 254)] = '\0';
217 if (it->key[0] != '#')
218 configSet->modified = 1;
220 } else {
221 addConfigValue(configSet, key, value);
222 if (key[0] != '#')
223 configSet->modified = 1;
226 return 1;
229 // sets the value to point to the value str in the config. Do not overwrite - it will overwrite the string in config
230 int configGetStr(config_set_t* configSet, const char* key, char** value) {
231 if (!configKeyValidate(key))
232 return 0;
234 struct config_value_t *it = getConfigItemForName(configSet, key);
236 if (it) {
237 *value = it->val;
238 return 1;
239 } else
240 return 0;
243 void configGetStrCopy(config_set_t* configSet, const char* key, char* value) {
244 char *valref = NULL;
245 if (configGetStr(configSet, key, &valref))
246 strncpy(value, valref, 32);
247 else
248 value[0] = '\0';
251 int configSetInt(config_set_t* configSet, const char* key, const int value) {
252 char tmp[12];
253 snprintf(tmp, 12, "%d", value);
254 return configSetStr(configSet, key, tmp);
257 int configGetInt(config_set_t* configSet, const char* key, int* value) {
258 char *valref = NULL;
259 if (configGetStr(configSet, key, &valref)) {
260 *value = atoi(valref);
261 return 1;
262 } else {
263 return 0;
267 int configSetColor(config_set_t* configSet, const char* key, unsigned char* color) {
268 char tmp[8];
269 snprintf(tmp, 8, "#%02X%02X%02X", color[0], color[1], color[2]);
270 return configSetStr(configSet, key, tmp);
273 int configGetColor(config_set_t* configSet, const char* key, unsigned char* color) {
274 char *valref = NULL;
275 if (configGetStr(configSet, key, &valref)) {
276 strToColor(valref, color);
277 return 1;
278 } else {
279 return 0;
283 int configRemoveKey(config_set_t* configSet, const char* key) {
284 if (!configKeyValidate(key))
285 return 0;
287 struct config_value_t* val = configSet->head;
288 struct config_value_t* prev = NULL;
290 while (val) {
291 if (strncmp(val->key, key, 32) == 0) {
292 if (key[0] != '#')
293 configSet->modified = 1;
295 if (val == configSet->tail)
296 configSet->tail = prev;
298 val = val->next;
299 if (prev) {
300 free(prev->next);
301 prev->next = val;
303 else {
304 free(configSet->head);
305 configSet->head = val;
307 } else {
308 prev = val;
309 val = val->next;
313 return 1;
316 void configReadIP() {
317 int fd = openFile(configPath, O_RDONLY);
318 if (fd >= 0) {
319 char ipconfig[255];
320 int size = getFileSize(fd);
321 fioRead(fd, &ipconfig, size);
322 fioClose(fd);
324 sscanf(ipconfig, "%d.%d.%d.%d %d.%d.%d.%d %d.%d.%d.%d", &ps2_ip[0], &ps2_ip[1], &ps2_ip[2], &ps2_ip[3],
325 &ps2_netmask[0], &ps2_netmask[1], &ps2_netmask[2], &ps2_netmask[3],
326 &ps2_gateway[0], &ps2_gateway[1], &ps2_gateway[2], &ps2_gateway[3]);
329 return;
332 void configWriteIP() {
333 int fd = openFile(configPath, O_WRONLY | O_CREAT);
334 if (fd >= 0) {
335 char ipconfig[255];
336 sprintf(ipconfig, "%d.%d.%d.%d %d.%d.%d.%d %d.%d.%d.%d\r\n", ps2_ip[0], ps2_ip[1], ps2_ip[2], ps2_ip[3],
337 ps2_netmask[0], ps2_netmask[1], ps2_netmask[2], ps2_netmask[3],
338 ps2_gateway[0], ps2_gateway[1], ps2_gateway[2], ps2_gateway[3]);
340 fioWrite(fd, ipconfig, strlen(ipconfig));
341 fioClose(fd);
342 gIPConfigChanged = 0;
346 // dst has to have 5 bytes space
347 void configGetDiscIDBinary(config_set_t* configSet, void* dst) {
348 memset(dst, 0, 5);
350 char *gid = NULL;
351 if (configGetStr(configSet, CONFIG_ITEM_DNAS, &gid)) {
352 // convert from hex to binary
353 char* cdst = dst;
354 int p = 0;
355 while (*gid && p < 10) {
356 int dv = -1;
358 while (dv < 0 && *gid) // skip spaces, etc
359 dv = fromHex(*(gid++));
361 if (dv < 0)
362 break;
364 *cdst = *cdst * 16 + dv;
365 if ((++p & 1) == 0)
366 cdst++;
371 int configRead(config_set_t* configSet) {
372 file_buffer_t* fileBuffer = openFileBuffer(configSet->filename, O_RDONLY, 0, 4096);
373 if (!fileBuffer) {
374 LOG("No config %s.\n", configSet->filename);
375 configSet->modified = 0;
376 return 0;
379 char* line;
380 unsigned int lineno = 0;
382 char prefix[32];
383 memset(prefix, 0, sizeof(prefix));
385 while (readFileBuffer(fileBuffer, &line)) {
386 lineno++;
388 char key[32], val[255];
389 memset(key, 0, sizeof(key));
390 memset(val, 0, sizeof(val));
392 if (splitAssignment(line, key, sizeof(key), val, sizeof(val))) {
393 /* if the line does not start with whitespace,
394 * the prefix ends and we have to reset it
396 if (!isWS(line[0]))
397 memset(prefix, 0, sizeof(prefix));
399 // insert config value
400 if (prefix[0]) {
401 // we have a prefix
402 char composedKey[66];
404 snprintf(composedKey, 65, "%s_%s", prefix, key);
405 composedKey[65] = '\0';
407 configSetStr(configSet, composedKey, val);
408 } else {
409 configSetStr(configSet, key, val);
411 } else if (parsePrefix(line, prefix)) {
412 // prefix is set, that's about it
413 } else {
414 LOG("Malformed config file '%s' line %d: '%s'\n", configSet->filename, lineno, line);
417 closeFileBuffer(fileBuffer);
418 configSet->modified = 0;
419 return configSet->type;
422 int configWrite(config_set_t* configSet) {
423 if (configSet->modified) {
424 // BUG in PFS: O_TRUNC doesn't work, so we remove the file and re-create it
425 if (strncmp(configSet->filename, "pfs0:", 5) == 0)
426 fioRemove(configSet->filename);
428 file_buffer_t* fileBuffer = openFileBuffer(configSet->filename, O_WRONLY | O_CREAT | O_TRUNC, 0, 4096);
429 if (fileBuffer) {
430 char line[512];
432 struct config_value_t* cur = configSet->head;
433 while (cur) {
434 if ((cur->key[0] != '\0') && (cur->key[0] != '#')) {
435 snprintf(line, 512, "%s=%s\r\n", cur->key, cur->val); // add windows CR+LF (0x0D 0x0A)
436 writeFileBuffer(fileBuffer, line, strlen(line));
439 // and advance
440 cur = cur->next;
443 closeFileBuffer(fileBuffer);
444 configSet->modified = 0;
445 return 1;
447 return 0;
449 return 1;
452 void configClear(config_set_t* configSet) {
453 while (configSet->head) {
454 struct config_value_t* cur = configSet->head;
455 configSet->head = cur->next;
457 free(cur);
460 configSet->head = NULL;
461 configSet->tail = NULL;
462 configSet->modified = 1;
465 int configReadMulti(int types) {
466 int result = 0;
468 if (CONFIG_OPL & types)
469 configReadIP();
471 int index = 0;
472 while(index < CONFIG_FILE_NUM) {
473 config_set_t *configSet = &configFiles[index];
475 if (configSet->type & types) {
476 configClear(configSet);
477 result |= configRead(configSet);
479 index++;
482 return result;
485 int configWriteMulti(int types) {
486 int result = 0;
488 if ((CONFIG_OPL & types) && gIPConfigChanged)
489 configWriteIP();
491 int index = 0;
492 while(index < CONFIG_FILE_NUM) {
493 config_set_t *configSet = &configFiles[index];
495 if (configSet->type & types)
496 result += configWrite(configSet);
497 index++;
500 return result;
503 #ifdef VMC
504 void configGetVMC(config_set_t* configSet, char* vmc, int slot) {
505 char *valref = NULL;
506 char gkey[255];
507 snprintf(gkey, 255, "%s_%d", CONFIG_ITEM_VMC, slot);
508 if (configGetStr(configSet, gkey, &valref))
509 strncpy(vmc, valref, 32);
510 else
511 vmc[0] = '\0';
514 void configSetVMC(config_set_t* configSet, const char* vmc, int slot) {
515 char gkey[255];
516 if(vmc[0] == '\0') {
517 configRemoveVMC(configSet, slot);
518 return;
520 snprintf(gkey, 255, "%s_%d", CONFIG_ITEM_VMC, slot);
521 configSetStr(configSet, gkey, vmc);
524 void configRemoveVMC(config_set_t* configSet, int slot) {
525 char gkey[255];
526 snprintf(gkey, 255, "%s_%d", CONFIG_ITEM_VMC, slot);
527 configRemoveKey(configSet, gkey);
529 #endif