2016-08-26 21:57:51 +00:00
|
|
|
/*
|
2017-10-13 10:42:36 +00:00
|
|
|
VitaShell
|
|
|
|
Copyright (C) 2015-2017, TheFloW
|
2016-08-26 21:57:51 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
2016-08-26 21:57:51 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
2016-08-26 21:57:51 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2016-08-26 21:57:51 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "main.h"
|
2016-09-14 09:33:52 +00:00
|
|
|
#include "file.h"
|
2016-08-26 21:57:51 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
2017-02-12 15:27:43 +00:00
|
|
|
static void trim(char *str) {
|
2017-10-13 10:42:36 +00:00
|
|
|
int len = strlen(str);
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = len - 1; i >= 0; i--) {
|
|
|
|
if (str[i] == 0x20 || str[i] == '\t') {
|
|
|
|
str[i] = 0;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-08-26 21:57:51 +00:00
|
|
|
}
|
|
|
|
|
2017-02-12 15:27:43 +00:00
|
|
|
static int GetLine(char *buf, int size, char *str) {
|
2017-10-13 10:42:36 +00:00
|
|
|
uint8_t ch = 0;
|
|
|
|
int n = 0;
|
|
|
|
int i = 0;
|
|
|
|
uint8_t *s = (uint8_t *)str;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
if (i >= size)
|
|
|
|
break;
|
|
|
|
|
|
|
|
ch = ((uint8_t *)buf)[i];
|
|
|
|
|
|
|
|
if (ch < 0x20 && ch != '\t') {
|
|
|
|
if (n != 0) {
|
|
|
|
i++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*str++ = ch;
|
|
|
|
n++;
|
|
|
|
}
|
2016-08-26 21:57:51 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
i++;
|
|
|
|
}
|
2016-08-26 21:57:51 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
trim((char *)s);
|
2016-08-26 21:57:51 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
return i;
|
2016-08-26 21:57:51 +00:00
|
|
|
}
|
|
|
|
|
2017-02-12 15:27:43 +00:00
|
|
|
static int getDecimal(const char *str) {
|
2017-10-13 10:42:36 +00:00
|
|
|
return strtol(str, NULL, 0);
|
2016-08-26 21:57:51 +00:00
|
|
|
}
|
|
|
|
|
2017-02-12 15:27:43 +00:00
|
|
|
static int getHexdecimal(const char *str) {
|
2017-10-13 10:42:36 +00:00
|
|
|
return strtoul(str, NULL, 16);
|
2016-08-26 21:57:51 +00:00
|
|
|
}
|
|
|
|
|
2017-02-12 15:27:43 +00:00
|
|
|
static int getBoolean(const char *str) {
|
2017-10-13 10:42:36 +00:00
|
|
|
if (strcasecmp(str, "false") == 0 || strcasecmp(str, "off") == 0 || strcasecmp(str, "no") == 0)
|
|
|
|
return 0;
|
2016-08-26 21:57:51 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
if (strcasecmp(str, "true") == 0 || strcasecmp(str, "on") == 0 || strcasecmp(str, "yes") == 0)
|
|
|
|
return 1;
|
2016-08-26 21:57:51 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
return -1;
|
2016-08-26 21:57:51 +00:00
|
|
|
}
|
|
|
|
|
2017-02-12 15:27:43 +00:00
|
|
|
static char *getString(const char *str) {
|
2017-10-13 10:42:36 +00:00
|
|
|
if (str[0] != '"')
|
|
|
|
return NULL;
|
2016-08-26 21:57:51 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
char *p = strchr(str + 1, '"');
|
|
|
|
if (!p)
|
|
|
|
return NULL;
|
2016-08-26 21:57:51 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
int len = p - (str + 1);
|
2016-08-26 21:57:51 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
char *out = malloc(len + 1);
|
|
|
|
strncpy(out, str + 1, len);
|
|
|
|
out[len] = '\0';
|
2016-08-26 21:57:51 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
int i;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
if (out[i] == '\\')
|
|
|
|
out[i] = '\n';
|
|
|
|
}
|
2016-08-26 21:57:51 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
return out;
|
2016-08-26 21:57:51 +00:00
|
|
|
}
|
|
|
|
|
2017-02-12 15:27:43 +00:00
|
|
|
static int readEntry(const char *line, ConfigEntry *entries, int n_entries) {
|
2017-10-13 10:42:36 +00:00
|
|
|
// Trim at beginning
|
|
|
|
while (*line == ' ' || *line == '\t')
|
|
|
|
line++;
|
2016-08-26 21:57:51 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
// Ignore comments #1
|
|
|
|
if (line[0] == '#') {
|
|
|
|
// debugPrintf("IGNORE %s\n", line);
|
|
|
|
return 0;
|
|
|
|
}
|
2016-08-26 21:57:51 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
// Ignore comments #2
|
|
|
|
char *p = strchr(line, '#');
|
|
|
|
if (p) {
|
|
|
|
// debugPrintf("IGNORE %s\n", p);
|
|
|
|
*p = '\0';
|
|
|
|
}
|
2016-08-26 21:57:51 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
// Get token
|
|
|
|
p = strchr(line, '=');
|
|
|
|
if (!p)
|
|
|
|
return -1;
|
2016-08-26 21:57:51 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
// Name of entry
|
|
|
|
char name[MAX_CONFIG_NAME_LENGTH];
|
|
|
|
int len = p - line;
|
|
|
|
if (len > MAX_CONFIG_NAME_LENGTH - 1)
|
|
|
|
len = MAX_CONFIG_NAME_LENGTH-1;
|
|
|
|
strncpy(name, line, len);
|
|
|
|
name[len] = '\0';
|
2016-08-26 21:57:51 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
trim(name);
|
2016-10-31 19:31:44 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
// debugPrintf("NAME: %s\n", name);
|
2017-03-13 20:45:04 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
// String of entry
|
|
|
|
char *string = p + 1;
|
2016-10-31 19:31:44 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
// Trim at beginning
|
|
|
|
while (*string == ' ' || *string == '\t')
|
|
|
|
string++;
|
2016-10-31 19:31:44 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
// Trim at end
|
|
|
|
trim(string);
|
2016-10-31 19:31:44 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
// debugPrintf("STRING: %s\n", string);
|
|
|
|
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < n_entries; i++) {
|
|
|
|
if (strcasecmp(name, entries[i].name) == 0) {
|
|
|
|
switch (entries[i].type) {
|
2016-10-31 19:31:44 +00:00
|
|
|
case CONFIG_TYPE_DECIMAL:
|
2017-10-13 10:42:36 +00:00
|
|
|
*(uint32_t *)entries[i].value = getDecimal(string);
|
|
|
|
// debugPrintf("VALUE DECIMAL: %d\n", *(uint32_t *)entries[i].value);
|
|
|
|
break;
|
|
|
|
|
2016-10-31 19:31:44 +00:00
|
|
|
case CONFIG_TYPE_HEXDECIMAL:
|
2017-10-13 10:42:36 +00:00
|
|
|
*(uint32_t *)entries[i].value = getHexdecimal(string);
|
|
|
|
// debugPrintf("VALUE HEXDECIMAL: 0x%X\n", *(uint32_t *)entries[i].value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CONFIG_TYPE_BOOLEAN:
|
|
|
|
*(uint32_t *)entries[i].value = getBoolean(string);
|
|
|
|
// debugPrintf("VALUE BOOLEAN: %d\n", *(uint32_t *)entries[i].value);
|
|
|
|
break;
|
|
|
|
|
2016-10-31 19:31:44 +00:00
|
|
|
case CONFIG_TYPE_STRING:
|
2017-10-13 10:42:36 +00:00
|
|
|
{
|
|
|
|
char *value = getString(string);
|
|
|
|
if (value) {
|
|
|
|
*(uint32_t *)entries[i].value = (uint32_t)value;
|
|
|
|
// debugPrintf("VALUE STRING: %s\n", *(uint32_t *)entries[i].value);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2016-10-31 19:31:44 +00:00
|
|
|
}
|
2017-10-13 10:42:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
2016-10-31 19:31:44 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
int readConfigBuffer(void *buffer, int size, ConfigEntry *entries, int n_entries) {
|
|
|
|
int res = 0;
|
|
|
|
char line[MAX_CONFIG_LINE_LENGTH];
|
|
|
|
char *p = buffer;
|
|
|
|
|
|
|
|
// Skip UTF-8 bom
|
|
|
|
uint32_t bom = 0xBFBBEF;
|
|
|
|
if (memcmp(p, &bom, 3) == 0) {
|
|
|
|
p += 3;
|
|
|
|
size -= 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
memset(line, 0, sizeof(line));
|
|
|
|
res = GetLine(p, size, line);
|
|
|
|
|
|
|
|
if (res > 0) {
|
|
|
|
readEntry(line, entries, n_entries);
|
|
|
|
size -= res;
|
|
|
|
p += res;
|
|
|
|
}
|
|
|
|
} while (res > 0);
|
2016-10-31 19:31:44 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2016-10-31 19:31:44 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
int readConfig(const char *path, ConfigEntry *entries, int n_entries) {
|
|
|
|
void *buffer = NULL;
|
|
|
|
int size = allocateReadFile(path, &buffer);
|
|
|
|
if (size < 0) {
|
|
|
|
if (buffer)
|
|
|
|
free(buffer);
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
readConfigBuffer(buffer, size, entries, n_entries);
|
|
|
|
|
|
|
|
free(buffer);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int writeEntry(SceUID fd, ConfigEntry *entry) {
|
|
|
|
if (!entry->value)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
int result;
|
|
|
|
if ((result = sceIoWrite(fd, entry->name, strlen(entry->name))) < 0)
|
|
|
|
return result;
|
|
|
|
|
|
|
|
if ((result = sceIoWrite(fd, " = ", 3)) < 0)
|
|
|
|
return result;
|
|
|
|
|
|
|
|
char *val;
|
|
|
|
char buffer[33];
|
|
|
|
|
|
|
|
switch (entry->type) {
|
|
|
|
case CONFIG_TYPE_BOOLEAN:
|
|
|
|
val = *(uint32_t *)entry->value != 0 ? "true" : "false";
|
|
|
|
result = sceIoWrite(fd, val, strlen(val));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CONFIG_TYPE_DECIMAL:
|
|
|
|
itoa(*(int *)entry->value, buffer, 10);
|
|
|
|
result = sceIoWrite(fd, buffer, strlen(buffer));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CONFIG_TYPE_HEXDECIMAL:
|
|
|
|
itoa(*(int *)entry->value, buffer, 16);
|
|
|
|
result = sceIoWrite(fd, buffer, strlen(buffer));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CONFIG_TYPE_STRING:
|
|
|
|
val = *(char **)entry->value;
|
|
|
|
sceIoWrite(fd, "\"", 1);
|
|
|
|
result = sceIoWrite(fd, val, strlen(val));
|
|
|
|
sceIoWrite(fd, "\"", 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result < 0)
|
|
|
|
return result;
|
|
|
|
|
|
|
|
if ((sceIoWrite(fd, "\n", 1)) < 0)
|
|
|
|
return result;
|
|
|
|
|
|
|
|
return 0;
|
2016-10-31 19:31:44 +00:00
|
|
|
}
|
|
|
|
|
2017-02-12 15:27:43 +00:00
|
|
|
int writeConfig(const char *path, ConfigEntry *entries, int n_entries) {
|
2017-10-13 10:42:36 +00:00
|
|
|
SceUID fd = sceIoOpen(path, SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0777);
|
|
|
|
if (fd < 0)
|
|
|
|
return fd;
|
|
|
|
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < n_entries; i++) {
|
|
|
|
int result = writeEntry(fd, entries+i);
|
|
|
|
if (result != 0) {
|
|
|
|
return result;
|
2016-10-31 19:31:44 +00:00
|
|
|
}
|
2017-10-13 10:42:36 +00:00
|
|
|
}
|
2016-10-31 19:31:44 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
sceIoClose(fd);
|
2016-10-31 19:31:44 +00:00
|
|
|
|
2017-10-13 10:42:36 +00:00
|
|
|
return 0;
|
2016-09-14 09:33:52 +00:00
|
|
|
}
|