cog/Frameworks/vgmstream/vgmstream/src/util/companion_files.c

150 lines
4.0 KiB
C

#include "companion_files.h"
#include "paths.h"
#include "../vgmstream.h"
#include "../util/reader_text.h"
size_t read_key_file(uint8_t* buf, size_t buf_size, STREAMFILE* sf) {
char keyname[PATH_LIMIT];
char filename[PATH_LIMIT];
const char *path, *ext;
STREAMFILE* sf_key = NULL;
size_t keysize;
get_streamfile_name(sf, filename, sizeof(filename));
if (strlen(filename)+4 > sizeof(keyname)) goto fail;
/* try to open a keyfile using variations */
{
ext = strrchr(filename,'.');
if (ext!=NULL) ext = ext+1;
path = strrchr(filename, DIR_SEPARATOR);
if (path!=NULL) path = path+1;
/* "(name.ext)key" */
strcpy(keyname, filename);
strcat(keyname, "key");
sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE);
if (sf_key) goto found;
/* "(name.ext)KEY" */
/*
strcpy(keyname+strlen(keyname)-3,"KEY");
sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE);
if (sf_key) goto found;
*/
/* "(.ext)key" */
if (path) {
strcpy(keyname, filename);
keyname[path-filename] = '\0';
strcat(keyname, ".");
} else {
strcpy(keyname, ".");
}
if (ext) strcat(keyname, ext);
strcat(keyname, "key");
sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE);
if (sf_key) goto found;
/* "(.ext)KEY" */
/*
strcpy(keyname+strlen(keyname)-3,"KEY");
sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE);
if (sf_key) goto found;
*/
goto fail;
}
found:
keysize = get_streamfile_size(sf_key);
if (keysize > buf_size) goto fail;
if (read_streamfile(buf, 0, keysize, sf_key) != keysize)
goto fail;
close_streamfile(sf_key);
return keysize;
fail:
close_streamfile(sf_key);
return 0;
}
STREAMFILE* read_filemap_file(STREAMFILE* sf, int file_num) {
return read_filemap_file_pos(sf, file_num, NULL);
}
STREAMFILE* read_filemap_file_pos(STREAMFILE* sf, int file_num, int* p_pos) {
char filename[PATH_LIMIT];
off_t txt_offset, file_size;
STREAMFILE* sf_map = NULL;
int file_pos = 0;
sf_map = open_streamfile_by_filename(sf, ".txtm");
if (!sf_map) goto fail;
get_streamfile_filename(sf, filename, sizeof(filename));
txt_offset = read_bom(sf_map);
file_size = get_streamfile_size(sf_map);
/* read lines and find target filename, format is (filename): value1, ... valueN */
while (txt_offset < file_size) {
char line[0x2000];
char key[PATH_LIMIT] = { 0 }, val[0x2000] = { 0 };
int ok, bytes_read, line_ok;
bytes_read = read_line(line, sizeof(line), txt_offset, sf_map, &line_ok);
if (!line_ok) goto fail;
txt_offset += bytes_read;
/* get key/val (ignores lead/trailing spaces, stops at comment/separator) */
ok = sscanf(line, " %[^\t#:] : %[^\t#\r\n] ", key, val);
if (ok != 2) { /* ignore line if no key=val (comment or garbage) */
/* better way? */
if (strcmp(line, "#@reset-pos") == 0) {
file_pos = 0;
}
continue;
}
if (strcmp(key, filename) == 0) {
int n;
char subval[PATH_LIMIT];
const char* current = val;
int i;
for (i = 0; i <= file_num; i++) {
if (current[0] == '\0')
goto fail;
ok = sscanf(current, " %[^\t#\r\n,]%n ", subval, &n);
if (ok != 1)
goto fail;
if (i == file_num) {
if (p_pos) *p_pos = file_pos;
close_streamfile(sf_map);
return open_streamfile_by_filename(sf, subval);
}
current += n;
if (current[0] == ',')
current++;
}
}
file_pos++;
}
fail:
close_streamfile(sf_map);
return NULL;
}