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 u32 currentUID
= 0;
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
);
159 while(index
< CONFIG_FILE_NUM
) {
160 config_set_t
*configSet
= &configFiles
[index
];
162 configClear(configSet
);
163 free(configSet
->filename
);
164 configSet
->filename
= NULL
;
169 config_set_t
*configAlloc(int type
, config_set_t
*configSet
, char *fileName
) {
171 configSet
= (config_set_t
*) malloc(sizeof(config_set_t
));
173 configSet
->uid
= ++currentUID
;
174 configSet
->type
= type
;
175 configSet
->head
= NULL
;
176 configSet
->tail
= NULL
;
178 int length
= strlen(fileName
) + 1;
179 configSet
->filename
= (char*) malloc(length
* sizeof(char));
180 memcpy(configSet
->filename
, fileName
, length
);
182 configSet
->filename
= NULL
;
183 configSet
->modified
= 0;
187 void configFree(config_set_t
*configSet
) {
188 configClear(configSet
);
189 free(configSet
->filename
);
194 config_set_t
*configGetByType(int type
) {
196 while(index
< CONFIG_FILE_NUM
) {
197 config_set_t
*configSet
= &configFiles
[index
];
199 if (configSet
->type
== type
)
206 int configSetStr(config_set_t
* configSet
, const char* key
, const char* value
) {
207 if (!configKeyValidate(key
))
210 struct config_value_t
*it
= getConfigItemForName(configSet
, key
);
213 if (strncmp(it
->val
, value
, 255) != 0) {
214 strncpy(it
->val
, value
, 255);
215 it
->val
[min(strlen(value
), 254)] = '\0';
216 if (it
->key
[0] != '#')
217 configSet
->modified
= 1;
220 addConfigValue(configSet
, key
, value
);
222 configSet
->modified
= 1;
228 // sets the value to point to the value str in the config. Do not overwrite - it will overwrite the string in config
229 int configGetStr(config_set_t
* configSet
, const char* key
, char** value
) {
230 if (!configKeyValidate(key
))
233 struct config_value_t
*it
= getConfigItemForName(configSet
, key
);
242 void configGetStrCopy(config_set_t
* configSet
, const char* key
, char* value
) {
244 if (configGetStr(configSet
, key
, &valref
))
245 strncpy(value
, valref
, 32);
250 int configSetInt(config_set_t
* configSet
, const char* key
, const int value
) {
252 snprintf(tmp
, 12, "%d", value
);
253 return configSetStr(configSet
, key
, tmp
);
256 int configGetInt(config_set_t
* configSet
, const char* key
, int* value
) {
258 if (configGetStr(configSet
, key
, &valref
)) {
259 *value
= atoi(valref
);
266 int configSetColor(config_set_t
* configSet
, const char* key
, unsigned char* color
) {
268 snprintf(tmp
, 8, "#%02X%02X%02X", color
[0], color
[1], color
[2]);
269 return configSetStr(configSet
, key
, tmp
);
272 int configGetColor(config_set_t
* configSet
, const char* key
, unsigned char* color
) {
274 if (configGetStr(configSet
, key
, &valref
)) {
275 strToColor(valref
, color
);
282 int configRemoveKey(config_set_t
* configSet
, const char* key
) {
283 if (!configKeyValidate(key
))
286 struct config_value_t
* val
= configSet
->head
;
287 struct config_value_t
* prev
= NULL
;
290 if (strncmp(val
->key
, key
, 32) == 0) {
292 configSet
->modified
= 1;
294 if (val
== configSet
->tail
)
295 configSet
->tail
= prev
;
303 free(configSet
->head
);
304 configSet
->head
= val
;
315 void configReadIP() {
316 int fd
= openFile(configPath
, O_RDONLY
);
319 int size
= getFileSize(fd
);
320 fioRead(fd
, &ipconfig
, size
);
323 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],
324 &ps2_netmask
[0], &ps2_netmask
[1], &ps2_netmask
[2], &ps2_netmask
[3],
325 &ps2_gateway
[0], &ps2_gateway
[1], &ps2_gateway
[2], &ps2_gateway
[3]);
331 void configWriteIP() {
332 int fd
= openFile(configPath
, O_WRONLY
| O_CREAT
);
335 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],
336 ps2_netmask
[0], ps2_netmask
[1], ps2_netmask
[2], ps2_netmask
[3],
337 ps2_gateway
[0], ps2_gateway
[1], ps2_gateway
[2], ps2_gateway
[3]);
339 fioWrite(fd
, ipconfig
, strlen(ipconfig
));
341 gIPConfigChanged
= 0;
345 // dst has to have 5 bytes space
346 void configGetDiscIDBinary(config_set_t
* configSet
, void* dst
) {
350 if (configGetStr(configSet
, CONFIG_ITEM_DNAS
, &gid
)) {
351 // convert from hex to binary
354 while (*gid
&& p
< 10) {
357 while (dv
< 0 && *gid
) // skip spaces, etc
358 dv
= fromHex(*(gid
++));
363 *cdst
= *cdst
* 16 + dv
;
370 int configRead(config_set_t
* configSet
) {
371 file_buffer_t
* fileBuffer
= openFileBuffer(configSet
->filename
, O_RDONLY
, 0, 4096);
373 LOG("CONFIG No file %s.\n", configSet
->filename
);
374 configSet
->modified
= 0;
379 unsigned int lineno
= 0;
382 memset(prefix
, 0, sizeof(prefix
));
384 while (readFileBuffer(fileBuffer
, &line
)) {
387 char key
[32], val
[255];
388 memset(key
, 0, sizeof(key
));
389 memset(val
, 0, sizeof(val
));
391 if (splitAssignment(line
, key
, sizeof(key
), val
, sizeof(val
))) {
392 /* if the line does not start with whitespace,
393 * the prefix ends and we have to reset it
396 memset(prefix
, 0, sizeof(prefix
));
398 // insert config value
401 char composedKey
[66];
403 snprintf(composedKey
, 65, "%s_%s", prefix
, key
);
404 composedKey
[65] = '\0';
406 configSetStr(configSet
, composedKey
, val
);
408 configSetStr(configSet
, key
, val
);
410 } else if (parsePrefix(line
, prefix
)) {
411 // prefix is set, that's about it
413 LOG("CONFIG Malformed file '%s' line %d: '%s'\n", configSet
->filename
, lineno
, line
);
416 closeFileBuffer(fileBuffer
);
417 configSet
->modified
= 0;
418 return configSet
->type
;
421 int configWrite(config_set_t
* configSet
) {
422 if (configSet
->modified
) {
423 // BUG in PFS: O_TRUNC doesn't work, so we remove the file and re-create it
424 if (strncmp(configSet
->filename
, "pfs0:", 5) == 0)
425 fioRemove(configSet
->filename
);
427 file_buffer_t
* fileBuffer
= openFileBuffer(configSet
->filename
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0, 4096);
431 struct config_value_t
* cur
= configSet
->head
;
433 if ((cur
->key
[0] != '\0') && (cur
->key
[0] != '#')) {
434 snprintf(line
, 512, "%s=%s\r\n", cur
->key
, cur
->val
); // add windows CR+LF (0x0D 0x0A)
435 writeFileBuffer(fileBuffer
, line
, strlen(line
));
442 closeFileBuffer(fileBuffer
);
443 configSet
->modified
= 0;
451 void configClear(config_set_t
* configSet
) {
452 while (configSet
->head
) {
453 struct config_value_t
* cur
= configSet
->head
;
454 configSet
->head
= cur
->next
;
459 configSet
->head
= NULL
;
460 configSet
->tail
= NULL
;
461 configSet
->modified
= 1;
464 int configReadMulti(int types
) {
467 if (CONFIG_OPL
& types
)
471 while(index
< CONFIG_FILE_NUM
) {
472 config_set_t
*configSet
= &configFiles
[index
];
474 if (configSet
->type
& types
) {
475 configClear(configSet
);
476 result
|= configRead(configSet
);
484 int configWriteMulti(int types
) {
487 if ((CONFIG_OPL
& types
) && gIPConfigChanged
)
491 while(index
< CONFIG_FILE_NUM
) {
492 config_set_t
*configSet
= &configFiles
[index
];
494 if (configSet
->type
& types
)
495 result
+= configWrite(configSet
);
503 void configGetVMC(config_set_t
* configSet
, char* vmc
, int slot
) {
506 snprintf(gkey
, 255, "%s_%d", CONFIG_ITEM_VMC
, slot
);
507 if (configGetStr(configSet
, gkey
, &valref
))
508 strncpy(vmc
, valref
, 32);
513 void configSetVMC(config_set_t
* configSet
, const char* vmc
, int slot
) {
516 configRemoveVMC(configSet
, slot
);
519 snprintf(gkey
, 255, "%s_%d", CONFIG_ITEM_VMC
, slot
);
520 configSetStr(configSet
, gkey
, vmc
);
523 void configRemoveVMC(config_set_t
* configSet
, int slot
) {
525 snprintf(gkey
, 255, "%s_%d", CONFIG_ITEM_VMC
, slot
);
526 configRemoveKey(configSet
, gkey
);