#include #include #include #include #include #include #include #include #include "rarchdb.h" #include "db_parser.h" #define MAX_TOKEN 256 static char *strndup_(const char *s, size_t n) { char* buff = calloc(n, sizeof(char)); if (!buff) return 0; strncpy(buff, s, n); return buff; } static struct rmsgpack_dom_value *get_map_value( const struct rmsgpack_dom_value *m, char* key) { struct rmsgpack_dom_value v; v.type = RDT_STRING; v.string.len = strlen(key); v.string.buff = key; return rmsgpack_dom_value_map_value(m, &v); } static int load_string(int fd, struct rmsgpack_dom_value *out) { char tok[MAX_TOKEN]; ssize_t tok_size; if ((tok_size = get_token(fd, tok, MAX_TOKEN)) < 0) return tok_size; out->type = RDT_STRING; out->string.len = tok_size; out->string.buff = strndup_(tok, tok_size); return 0; } static int load_uint(int fd, struct rmsgpack_dom_value *out) { char tok[MAX_TOKEN], *c; ssize_t tok_size; uint64_t value = 0; if ((tok_size = get_token(fd, tok, MAX_TOKEN)) < 0) return tok_size; for (c = tok; c < tok + tok_size; c++) { value *= 10; value += *c - '0'; } out->type = RDT_UINT; out->uint_ = value; return 0; } static int load_bin(int fd, struct rmsgpack_dom_value *out) { char tok[MAX_TOKEN]; ssize_t tok_size; uint8_t h; uint8_t l; int i; if ((tok_size = get_token(fd, tok, MAX_TOKEN)) < 0) return tok_size; out->type = RDT_BINARY; out->binary.len = tok_size / 2; for (i = 0; i < tok_size; i += 2) { if (tok[i] <= '9') h = tok[i] - '0'; else h = (tok[i] - 'A') + 10; if (tok[i+1] <= '9') l = tok[i+1] - '0'; else l = (tok[i+1] - 'A') + 10; tok[i/2] = h * 16 + l; } out->binary.buff = malloc(out->binary.len); memcpy(out->binary.buff, tok, out->binary.len); return 0; } static int dat_value_provider(void *ctx, struct rmsgpack_dom_value *out) { int rv, i; static const int field_count = 22; int fd = *((int*)ctx); char* key; out->type = RDT_MAP; out->map.len = field_count; out->map.items = calloc(field_count, sizeof(struct rmsgpack_dom_pair)); if (find_token(fd, "game") < 0) return 1; for (i = 0; i < field_count; i++) { if ((rv = load_string(fd, &out->map.items[i].key)) < 0) goto failed; key = out->map.items[i].key.string.buff; if (strncmp(key, "name", sizeof("name")) == 0) { if ((rv = load_string(fd, &out->map.items[i].value)) < 0) goto failed; } else if (strncmp(key, "description", sizeof("description")) == 0) { if ((rv = load_string(fd, &out->map.items[i].value)) < 0) goto failed; } else if (strncmp(key, "users", sizeof("users")) == 0) { if ((rv = load_uint(fd, &out->map.items[i].value)) < 0) goto failed; } else if (strncmp(key, "releasemonth", sizeof("releasemonth")) == 0) { if ((rv = load_uint(fd, &out->map.items[i].value)) < 0) goto failed; } else if (strncmp(key, "releaseyear", sizeof("releaseyear")) == 0) { if ((rv = load_uint(fd, &out->map.items[i].value)) < 0) goto failed; } else if (strncmp(key, "rumble", sizeof("rumble")) == 0) { if ((rv = load_uint(fd, &out->map.items[i].value)) < 0) goto failed; } else if (strncmp(key, "analog", sizeof("analog")) == 0) { if ((rv = load_uint(fd, &out->map.items[i].value)) < 0) goto failed; } else if (strncmp(key, "serial", sizeof("serial")) == 0) { if ((rv = load_string(fd, &out->map.items[i].value)) < 0) goto failed; } else if (strncmp(key, "esrb_rating", sizeof("esrb_rating")) == 0) { if ((rv = load_string(fd, &out->map.items[i].value)) < 0) goto failed; } else if (strncmp(key, "elspa_rating", sizeof("elspa_rating")) == 0) { if ((rv = load_string(fd, &out->map.items[i].value)) < 0) goto failed; } else if (strncmp(key, "pegi_rating", sizeof("pegi_rating")) == 0) { if ((rv = load_string(fd, &out->map.items[i].value)) < 0) goto failed; } else if (strncmp(key, "cero_rating", sizeof("cero_rating")) == 0) { if ((rv = load_string(fd, &out->map.items[i].value)) < 0) goto failed; } else if (strncmp(key, "developer", sizeof("developer")) == 0) { if ((rv = load_string(fd, &out->map.items[i].value)) < 0) goto failed; } else if (strncmp(key, "publisher", sizeof("publisher")) == 0) { if ((rv = load_string(fd, &out->map.items[i].value)) < 0) goto failed; } else if (strncmp(key, "origin", sizeof("origin")) == 0) { if ((rv = load_string(fd, &out->map.items[i].value)) < 0) goto failed; } else if (strncmp(key, "rom", sizeof("rom")) == 0) { if (find_token(fd, "name") < 0) goto failed; if ((rv = load_string(fd, &out->map.items[i].value)) < 0) goto failed; } else if (strncmp(key, "size", sizeof("size")) == 0) { if ((rv = load_uint(fd, &out->map.items[i].value)) < 0) goto failed; } else if (strncmp(key, "sha1", sizeof("sha1")) == 0) { if ((rv = load_bin(fd, &out->map.items[i].value)) < 0) goto failed; } else if (strncmp(key, "crc", sizeof("crc")) == 0) { if ((rv = load_bin(fd, &out->map.items[i].value)) < 0) goto failed; } else if (strncmp(key, "md5", sizeof("md5")) == 0) { if ((rv = load_bin(fd, &out->map.items[i].value)) < 0) goto failed; } else if (strncmp(key, "serial", sizeof("serial")) == 0) { if ((rv = load_string(fd, &out->map.items[i].value)) < 0) goto failed; } else if (strncmp(key, ")", sizeof(")")) == 0) { rmsgpack_dom_value_free(&out->map.items[i].key); out->map.len = i; printf("Couldn't find all fields for item\n"); break; } else { rmsgpack_dom_value_free(&out->map.items[i].key); i--; } } printf("Inserting '%s' (%02X%02X%02X%02X)...\n", get_map_value(out, "name")->string.buff, (unsigned char)get_map_value(out, "crc")->binary.buff[0], (unsigned char)get_map_value(out, "crc")->binary.buff[1], (unsigned char)get_map_value(out, "crc")->binary.buff[2], (unsigned char)get_map_value(out, "crc")->binary.buff[3] ); return 0; failed: rmsgpack_dom_value_free(out); out->type = RDT_NULL; return rv; } int main(int argc, char **argv) { int rv = 0; int src = -1; int dst = -1; if (argc != 3) printf("Usage: %s \n", argv[0]); src = open(argv[1], O_RDONLY); if (src == -1) { printf("Could not open source file '%s': %s\n", argv[1], strerror(errno)); rv = errno; goto clean; } dst = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (dst == -1) { printf("Could not open destination file '%s': %s\n", argv[1], strerror(errno)); rv = errno; goto clean; } rv = rarchdb_create(dst, &dat_value_provider, &src); clean: if (src != -1) close(src); if (dst != -1) close(dst); return rv; }