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
16 static config_set_t configFiles
[CONFIG_FILE_NUM
];
17 static char configPath
[255] = "mc?:SYS-CONF/IPCONFIG.DAT";
19 static int strToColor(const char *string
, unsigned char *color
) {
25 if (!string
|| !*string
) return 0;
26 if (string
[0]!='#') return 0;
31 int fh
= fromHex(*string
);
33 color
[n
] = color
[n
] * 16 + fh
;
38 // Two characters per color
52 /// true if given a whitespace character
54 return c
== ' ' || c
== '\t';
57 static int splitAssignment(char* line
, char* key
, size_t keymax
, char* val
, size_t valmax
) {
59 for (;isWS(*line
); ++line
);
62 // If found, the text before is key, after is val.
63 // Otherwise malformed string is encountered
65 char* eqpos
= strchr(line
, '=');
68 // copy the name and the value
69 size_t keylen
= min(keymax
, eqpos
- line
);
71 strncpy(key
, line
, keylen
);
75 size_t vallen
= min(valmax
, strlen(line
) - (eqpos
- line
));
76 strncpy(val
, eqpos
, vallen
);
82 static int parsePrefix(char* line
, char* prefix
) {
84 // If found, the text before is key, after is val.
85 // Otherwise malformed string is encountered
86 char* colpos
= strchr(line
, ':');
88 if (colpos
&& colpos
!= line
) {
89 // copy the name and the value
90 strncpy(prefix
, line
, colpos
- line
);
98 static int configKeyValidate(const char* key
) {
102 return !strchr(key
, '=');
105 static struct config_value_t
* allocConfigItem(const char* key
, const char* val
) {
106 struct config_value_t
* it
= (struct config_value_t
*) malloc(sizeof(struct config_value_t
));
107 strncpy(it
->key
, key
, 32);
108 it
->key
[min(strlen(key
), 31)] = '\0';
109 strncpy(it
->val
, val
, 255);
110 it
->val
[min(strlen(val
), 254)] = '\0';
116 /// Low level key addition. Does not check for uniqueness.
117 static void addConfigValue(config_set_t
* configSet
, const char* key
, const char* val
) {
118 if (!configSet
->tail
) {
119 configSet
->head
= allocConfigItem(key
, val
);
120 configSet
->tail
= configSet
->head
;
122 configSet
->tail
->next
= allocConfigItem(key
, val
);
123 configSet
->tail
= configSet
->tail
->next
;
127 static struct config_value_t
* getConfigItemForName(config_set_t
* configSet
, const char* name
) {
128 struct config_value_t
* val
= configSet
->head
;
131 if (strncmp(val
->key
, name
, 32) == 0)
140 void configInit(char *prefix
) {
144 snprintf(configPath
, 255, "%s/IPCONFIG.DAT", prefix
);
148 snprintf(path
, 255, "%s/conf_opl.cfg", prefix
);
149 configAlloc(CONFIG_OPL
, &configFiles
[CONFIG_INDEX_OPL
], path
);
150 snprintf(path
, 255, "%s/conf_last.cfg", prefix
);
151 configAlloc(CONFIG_LAST
, &configFiles
[CONFIG_INDEX_LAST
], path
);
152 snprintf(path
, 255, "%s/conf_apps.cfg", prefix
);
153 configAlloc(CONFIG_APPS
, &configFiles
[CONFIG_INDEX_APPS
], path
);
158 while(index
< CONFIG_FILE_NUM
) {
159 config_set_t
*configSet
= &configFiles
[index
];
161 configClear(configSet
);
162 free(configSet
->filename
);
163 configSet
->filename
= NULL
;
168 config_set_t
*configAlloc(int type
, config_set_t
*configSet
, char *fileName
) {
170 configSet
= (config_set_t
*) malloc(sizeof(config_set_t
));
172 configSet
->type
= type
;
173 configSet
->head
= NULL
;
174 configSet
->tail
= NULL
;
176 int length
= strlen(fileName
) + 1;
177 configSet
->filename
= (char*) malloc(length
* sizeof(char));
178 memcpy(configSet
->filename
, fileName
, length
);
180 configSet
->filename
= NULL
;
181 configSet
->modified
= 0;
185 void configFree(config_set_t
*configSet
) {
186 configClear(configSet
);
187 free(configSet
->filename
);
192 config_set_t
*configGetByType(int type
) {
194 while(index
< CONFIG_FILE_NUM
) {
195 config_set_t
*configSet
= &configFiles
[index
];
197 if (configSet
->type
== type
)
204 int configSetStr(config_set_t
* configSet
, const char* key
, const char* value
) {
205 if (!configKeyValidate(key
))
208 struct config_value_t
*it
= getConfigItemForName(configSet
, key
);
211 if (strncmp(it
->val
, value
, 255) != 0) {
212 strncpy(it
->val
, value
, 255);
213 it
->val
[min(strlen(value
), 254)] = '\0';
214 if (it
->key
[0] != '#')
215 configSet
->modified
= 1;
218 addConfigValue(configSet
, key
, value
);
220 configSet
->modified
= 1;
226 // sets the value to point to the value str in the config. Do not overwrite - it will overwrite the string in config
227 int configGetStr(config_set_t
* configSet
, const char* key
, char** value
) {
228 if (!configKeyValidate(key
))
231 struct config_value_t
*it
= getConfigItemForName(configSet
, key
);
240 void configGetStrCopy(config_set_t
* configSet
, const char* key
, char* value
) {
242 if (configGetStr(configSet
, key
, &valref
))
243 strncpy(value
, valref
, 32);
248 int configSetInt(config_set_t
* configSet
, const char* key
, const int value
) {
250 snprintf(tmp
, 12, "%d", value
);
251 return configSetStr(configSet
, key
, tmp
);
254 int configGetInt(config_set_t
* configSet
, const char* key
, int* value
) {
256 if (configGetStr(configSet
, key
, &valref
)) {
257 *value
= atoi(valref
);
264 int configSetColor(config_set_t
* configSet
, const char* key
, unsigned char* color
) {
266 snprintf(tmp
, 8, "#%02X%02X%02X", color
[0], color
[1], color
[2]);
267 return configSetStr(configSet
, key
, tmp
);
270 int configGetColor(config_set_t
* configSet
, const char* key
, unsigned char* color
) {
272 if (configGetStr(configSet
, key
, &valref
)) {
273 strToColor(valref
, color
);
280 int configRemoveKey(config_set_t
* configSet
, const char* key
) {
281 if (!configKeyValidate(key
))
284 struct config_value_t
* val
= configSet
->head
;
285 struct config_value_t
* prev
= NULL
;
288 if (strncmp(val
->key
, key
, 32) == 0) {
290 configSet
->modified
= 1;
292 if (val
== configSet
->tail
)
293 configSet
->tail
= prev
;
301 free(configSet
->head
);
302 configSet
->head
= val
;
313 void configReadIP() {
314 int fd
= openFile(configPath
, O_RDONLY
);
317 int size
= getFileSize(fd
);
318 fioRead(fd
, &ipconfig
, size
);
321 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],
322 &ps2_netmask
[0], &ps2_netmask
[1], &ps2_netmask
[2], &ps2_netmask
[3],
323 &ps2_gateway
[0], &ps2_gateway
[1], &ps2_gateway
[2], &ps2_gateway
[3]);
329 void configWriteIP() {
330 int fd
= openFile(configPath
, O_WRONLY
| O_CREAT
);
333 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],
334 ps2_netmask
[0], ps2_netmask
[1], ps2_netmask
[2], ps2_netmask
[3],
335 ps2_gateway
[0], ps2_gateway
[1], ps2_gateway
[2], ps2_gateway
[3]);
337 fioWrite(fd
, ipconfig
, strlen(ipconfig
));
339 gIPConfigChanged
= 0;
343 // dst has to have 5 bytes space
344 void configGetDiscIDBinary(config_set_t
* configSet
, void* dst
) {
348 if (configGetStr(configSet
, CONFIG_ITEM_DNAS
, &gid
)) {
349 // convert from hex to binary
352 while (*gid
&& p
< 10) {
355 while (dv
< 0 && *gid
) // skip spaces, etc
356 dv
= fromHex(*(gid
++));
361 *cdst
= *cdst
* 16 + dv
;
368 int configRead(config_set_t
* configSet
) {
369 file_buffer_t
* fileBuffer
= openFileBuffer(configSet
->filename
, O_RDONLY
, 0, 4096);
371 LOG("CONFIG No file %s.\n", configSet
->filename
);
372 configSet
->modified
= 0;
377 unsigned int lineno
= 0;
380 memset(prefix
, 0, sizeof(prefix
));
382 while (readFileBuffer(fileBuffer
, &line
)) {
385 char key
[32], val
[255];
386 memset(key
, 0, sizeof(key
));
387 memset(val
, 0, sizeof(val
));
389 if (splitAssignment(line
, key
, sizeof(key
), val
, sizeof(val
))) {
390 /* if the line does not start with whitespace,
391 * the prefix ends and we have to reset it
394 memset(prefix
, 0, sizeof(prefix
));
396 // insert config value
399 char composedKey
[66];
401 snprintf(composedKey
, 65, "%s_%s", prefix
, key
);
402 composedKey
[65] = '\0';
404 configSetStr(configSet
, composedKey
, val
);
406 configSetStr(configSet
, key
, val
);
408 } else if (parsePrefix(line
, prefix
)) {
409 // prefix is set, that's about it
411 LOG("CONFIG Malformed file '%s' line %d: '%s'\n", configSet
->filename
, lineno
, line
);
414 closeFileBuffer(fileBuffer
);
415 configSet
->modified
= 0;
416 return configSet
->type
;
419 int configWrite(config_set_t
* configSet
) {
420 if (configSet
->modified
) {
421 // BUG in PFS: O_TRUNC doesn't work, so we remove the file and re-create it
422 if (strncmp(configSet
->filename
, "pfs0:", 5) == 0)
423 fioRemove(configSet
->filename
);
425 file_buffer_t
* fileBuffer
= openFileBuffer(configSet
->filename
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0, 4096);
429 struct config_value_t
* cur
= configSet
->head
;
431 if ((cur
->key
[0] != '\0') && (cur
->key
[0] != '#')) {
432 snprintf(line
, 512, "%s=%s\r\n", cur
->key
, cur
->val
); // add windows CR+LF (0x0D 0x0A)
433 writeFileBuffer(fileBuffer
, line
, strlen(line
));
440 closeFileBuffer(fileBuffer
);
441 configSet
->modified
= 0;
449 void configClear(config_set_t
* configSet
) {
450 while (configSet
->head
) {
451 struct config_value_t
* cur
= configSet
->head
;
452 configSet
->head
= cur
->next
;
457 configSet
->head
= NULL
;
458 configSet
->tail
= NULL
;
459 configSet
->modified
= 1;
462 int configReadMulti(int types
) {
465 if (CONFIG_OPL
& types
)
469 while(index
< CONFIG_FILE_NUM
) {
470 config_set_t
*configSet
= &configFiles
[index
];
472 if (configSet
->type
& types
) {
473 configClear(configSet
);
474 result
|= configRead(configSet
);
482 int configWriteMulti(int types
) {
485 if ((CONFIG_OPL
& types
) && gIPConfigChanged
)
489 while(index
< CONFIG_FILE_NUM
) {
490 config_set_t
*configSet
= &configFiles
[index
];
492 if (configSet
->type
& types
)
493 result
+= configWrite(configSet
);
501 void configGetVMC(config_set_t
* configSet
, char* vmc
, int slot
) {
504 snprintf(gkey
, 255, "%s_%d", CONFIG_ITEM_VMC
, slot
);
505 if (configGetStr(configSet
, gkey
, &valref
))
506 strncpy(vmc
, valref
, 32);
511 void configSetVMC(config_set_t
* configSet
, const char* vmc
, int slot
) {
514 configRemoveVMC(configSet
, slot
);
517 snprintf(gkey
, 255, "%s_%d", CONFIG_ITEM_VMC
, slot
);
518 configSetStr(configSet
, gkey
, vmc
);
521 void configRemoveVMC(config_set_t
* configSet
, int slot
) {
523 snprintf(gkey
, 255, "%s_%d", CONFIG_ITEM_VMC
, slot
);
524 configRemoveKey(configSet
, gkey
);