summaryrefslogtreecommitdiff
path: root/src/extract.c
diff options
context:
space:
mode:
authorjakob <jakob@memeware.net>2017-01-12 17:09:17 -0500
committerjakob <jakob@memeware.net>2017-01-12 17:09:17 -0500
commit43e539561a4ea95274468b78735555d6e89fdfd9 (patch)
tree4a005aed01dc34c40b4fe5657d2b155ea4231e85 /src/extract.c
parent350b126eef468c7c8d66c72100d8a3c76e9afec1 (diff)
Finished implementation of file decryption. There are still many memory corruption bugs and a segfault is not uncommon.
Diffstat (limited to 'src/extract.c')
-rw-r--r--src/extract.c38
1 files changed, 15 insertions, 23 deletions
diff --git a/src/extract.c b/src/extract.c
index f452eaf..1dad149 100644
--- a/src/extract.c
+++ b/src/extract.c
@@ -44,33 +44,28 @@ void read_stream(void *destination, Bytef **source, size_t size);
parsing, decrypting and writing the table entries. */
void extract(FILE *archive, uint64_t table_offset) {
/* eliF and File entries are stored in a linked list as they're
- seen, because the order of entries in XP3 archives is not
+ seen because the order of entries in XP3 archives is not
guaranteed to be chronological. calloc is used to prevent the
"next" pointer from being garbage and causing a segfault. */
- elif_node *elif_root = calloc(sizeof(elif_node), 1);
- elif_node *elif_new;
- file_node *file_root = calloc(sizeof(file_node), 1);
- file_node *file_new;
+ elif_node *elif_new, *elif_root = calloc(sizeof(elif_node), 1);
+ file_node *file_new, *file_root = calloc(sizeof(file_node), 1);
uint8_t compressed;
+ uint64_t compressed_size, decompressed_size;
fseek(archive, table_offset, SEEK_SET);
fread(&compressed, sizeof(uint8_t), 1, archive);
+ fread(&compressed_size, sizeof(uint64_t), 1, archive);
+ fread(&decompressed_size, sizeof(uint64_t), 1, archive);
int stream_ended = 0;
memory_stream data_stream;
+ memory_stream compressed_data = read_to_stream(archive, compressed_size);
if (compressed) {
- data_stream = decompress_file(archive, ftell(archive));
+ data_stream = decompress_stream(compressed_data, decompressed_size);
+ free(compressed_data.start);
} else {
- uint64_t decompressed_size;
- fread(&decompressed_size, sizeof(uint64_t), 1, archive);
- /* The second size is irrelevant and therefore ignored. */
- fseek(archive, sizeof(uint64_t), SEEK_CUR);
- data_stream.stream_length = decompressed_size;
- data_stream.data = malloc(decompressed_size);
- data_stream.start = data_stream.data;
- fread(data_stream.data, decompressed_size, 1, archive);
- fclose(archive);
- }
+ data_stream = compressed_data;
+ }
uint32_t entry_magic;
uint64_t entry_size;
@@ -102,9 +97,7 @@ void extract(FILE *archive, uint64_t table_offset) {
}
} while (!stream_ended);
- write_files(file_root, elif_root, data_stream.start);
- test_elif_linked_list(elif_root);
- test_file_linked_list(file_root);
+ write_files(file_root, elif_root, archive);
free_elif_nodes(elif_root);
free_file_nodes(file_root);
free(data_stream.start);
@@ -129,8 +122,8 @@ elif_node *read_elif_entry(memory_stream *data_stream) {
char *file_name;
if (name_size < 0x100) {
- /* Strings are terminated by null bytes, but
- they aren't counted in the name size. */
+ /* Strings are terminated by null bytes,
+ which aren't counted in the name size. */
char *input_buffer = malloc(name_size * 2 + 2);
file_name = malloc(name_size + 1);
read_stream(input_buffer, &data_stream->data, name_size * 2 + 2);
@@ -145,8 +138,7 @@ elif_node *read_elif_entry(memory_stream *data_stream) {
free(input_buffer);
} else {
- /* It's pretty safe to assume anything
- larger is the copyright notice. */
+ /* It's safe to assume too large is the copyright notice. */
data_stream->data += name_size * 2 + 2;
file_name = strdup("COPYING.txt");
}