2 Copyright 2009, Ifcaro & volca
3 Licenced under Academic Free License version 3.0
4 Review OpenUsbLd README & LICENSE files for further details.
7 #include "include/usbld.h"
8 #include "include/util.h"
9 #include "include/ioman.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
) {
26 if (!string
|| !*string
) return 0;
27 if (string
[0]!='#') return 0;
32 int fh
= fromHex(*string
);
34 color
[n
] = color
[n
] * 16 + fh
;
39 // Two characters per color
53 /// true if given a whitespace character
55 return c
== ' ' || c
== '\t';
58 static int splitAssignment(char* line
, char* key
, size_t keymax
, char* val
, size_t valmax
) {
60 for (;isWS(*line
); ++line
);
63 // If found, the text before is key, after is val.
64 // Otherwise malformed string is encountered
66 char* eqpos
= strchr(line
, '=');
69 // copy the name and the value
70 size_t keylen
= min(keymax
, eqpos
- line
);
72 strncpy(key
, line
, keylen
);
76 size_t vallen
= min(valmax
, strlen(line
) - (eqpos
- line
));
77 strncpy(val
, eqpos
, vallen
);
83 static int parsePrefix(char* line
, char* prefix
) {
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
);
99 static int configKeyValidate(const char* key
) {
100 if (strlen(key
) == 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';
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
;
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
;
132 if (strncmp(val
->key
, name
, 32) == 0)
141 void configInit(char *prefix
) {
145 snprintf(configPath
, 255, "%s/IPCONFIG.DAT", prefix
);
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
);
161 while(index
< CONFIG_FILE_NUM
) {
162 config_set_t
*configSet
= &configFiles
[index
];
164 configClear(configSet
);
165 free(configSet
->filename
);
166 configSet
->filename
= NULL
;
171 config_set_t
*configAlloc(int type
, config_set_t
*configSet
, char *fileName
) {
173 configSet
= (config_set_t
*) malloc(sizeof(config_set_t
));
175 configSet
->type
= type
;
176 configSet
->head
= NULL
;
177 configSet
->tail
= NULL
;
179 int length
= strlen(fileName
) + 1;
180 configSet
->filename
= (char*) malloc(length
* sizeof(char));
181 memcpy(configSet
->filename
, fileName
, length
);
183 configSet
->filename
= NULL
;
184 configSet
->modified
= 0;
188 void configFree(config_set_t
*configSet
) {
189 configClear(configSet
);
190 free(configSet
->filename
);
195 config_set_t
*configGetByType(int type
) {
197 while(index
< CONFIG_FILE_NUM
) {
198 config_set_t
*configSet
= &configFiles
[index
];
200 if (configSet
->type
== type
)
207 int configSetStr(config_set_t
* configSet
, const char* key
, const char* value
) {
208 if (!configKeyValidate(key
))
211 struct config_value_t
*it
= getConfigItemForName(configSet
, key
);
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;
221 addConfigValue(configSet
, key
, value
);
223 configSet
->modified
= 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
))
234 struct config_value_t
*it
= getConfigItemForName(configSet
, key
);
243 void configGetStrCopy(config_set_t
* configSet
, const char* key
, char* value
) {
245 if (configGetStr(configSet
, key
, &valref
))
246 strncpy(value
, valref
, 32);
251 int configSetInt(config_set_t
* configSet
, const char* key
, const int value
) {
253 snprintf(tmp
, 12, "%d", value
);
254 return configSetStr(configSet
, key
, tmp
);
257 int configGetInt(config_set_t
* configSet
, const char* key
, int* value
) {
259 if (configGetStr(configSet
, key
, &valref
)) {
260 *value
= atoi(valref
);
267 int configSetColor(config_set_t
* configSet
, const char* key
, unsigned char* color
) {
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
) {
275 if (configGetStr(configSet
, key
, &valref
)) {
276 strToColor(valref
, color
);
283 int configRemoveKey(config_set_t
* configSet
, const char* key
) {
284 if (!configKeyValidate(key
))
287 struct config_value_t
* val
= configSet
->head
;
288 struct config_value_t
* prev
= NULL
;
291 if (strncmp(val
->key
, key
, 32) == 0) {
293 configSet
->modified
= 1;
295 if (val
== configSet
->tail
)
296 configSet
->tail
= prev
;
304 free(configSet
->head
);
305 configSet
->head
= val
;
316 void configReadIP() {
317 int fd
= openFile(configPath
, O_RDONLY
);
320 int size
= getFileSize(fd
);
321 fioRead(fd
, &ipconfig
, size
);
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]);
332 void configWriteIP() {
333 int fd
= openFile(configPath
, O_WRONLY
| O_CREAT
);
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
));
342 gIPConfigChanged
= 0;
346 // dst has to have 5 bytes space
347 void configGetDiscIDBinary(config_set_t
* configSet
, void* dst
) {
351 if (configGetStr(configSet
, CONFIG_ITEM_DNAS
, &gid
)) {
352 // convert from hex to binary
355 while (*gid
&& p
< 10) {
358 while (dv
< 0 && *gid
) // skip spaces, etc
359 dv
= fromHex(*(gid
++));
364 *cdst
= *cdst
* 16 + dv
;
371 int configRead(config_set_t
* configSet
) {
372 file_buffer_t
* fileBuffer
= openFileBuffer(configSet
->filename
, O_RDONLY
, 0, 4096);
374 LOG("No config %s.\n", configSet
->filename
);
375 configSet
->modified
= 0;
380 unsigned int lineno
= 0;
383 memset(prefix
, 0, sizeof(prefix
));
385 while (readFileBuffer(fileBuffer
, &line
)) {
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
397 memset(prefix
, 0, sizeof(prefix
));
399 // insert config value
402 char composedKey
[66];
404 snprintf(composedKey
, 65, "%s_%s", prefix
, key
);
405 composedKey
[65] = '\0';
407 configSetStr(configSet
, composedKey
, val
);
409 configSetStr(configSet
, key
, val
);
411 } else if (parsePrefix(line
, prefix
)) {
412 // prefix is set, that's about it
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);
432 struct config_value_t
* cur
= configSet
->head
;
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
));
443 closeFileBuffer(fileBuffer
);
444 configSet
->modified
= 0;
452 void configClear(config_set_t
* configSet
) {
453 while (configSet
->head
) {
454 struct config_value_t
* cur
= configSet
->head
;
455 configSet
->head
= cur
->next
;
460 configSet
->head
= NULL
;
461 configSet
->tail
= NULL
;
462 configSet
->modified
= 1;
465 int configReadMulti(int types
) {
468 if (CONFIG_OPL
& types
)
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
);
485 int configWriteMulti(int types
) {
488 if ((CONFIG_OPL
& types
) && gIPConfigChanged
)
492 while(index
< CONFIG_FILE_NUM
) {
493 config_set_t
*configSet
= &configFiles
[index
];
495 if (configSet
->type
& types
)
496 result
+= configWrite(configSet
);
504 void configGetVMC(config_set_t
* configSet
, char* vmc
, int slot
) {
507 snprintf(gkey
, 255, "%s_%d", CONFIG_ITEM_VMC
, slot
);
508 if (configGetStr(configSet
, gkey
, &valref
))
509 strncpy(vmc
, valref
, 32);
514 void configSetVMC(config_set_t
* configSet
, const char* vmc
, int slot
) {
517 configRemoveVMC(configSet
, slot
);
520 snprintf(gkey
, 255, "%s_%d", CONFIG_ITEM_VMC
, slot
);
521 configSetStr(configSet
, gkey
, vmc
);
524 void configRemoveVMC(config_set_t
* configSet
, int slot
) {
526 snprintf(gkey
, 255, "%s_%d", CONFIG_ITEM_VMC
, slot
);
527 configRemoveKey(configSet
, gkey
);