From 2ba0b505ce1ee748f42a85f7e27906737fa47fc8 Mon Sep 17 00:00:00 2001 From: jakob Date: Sun, 14 May 2017 19:07:06 -0400 Subject: Initial data dumping functionality. --- .astylerc | 4 -- Makefile | 5 +- src/compress.c | 30 ++++++++++ src/compress.h | 3 + src/io.c | 8 ++- src/io.h | 3 + src/main.c | 20 ++++++- src/table.c | 176 ++++++++++++++++++++++++++++----------------------------- src/table.h | 28 ++++----- 9 files changed, 161 insertions(+), 116 deletions(-) delete mode 100644 .astylerc diff --git a/.astylerc b/.astylerc deleted file mode 100644 index 319a751..0000000 --- a/.astylerc +++ /dev/null @@ -1,4 +0,0 @@ ---style=java \ - --indent-preproc-block \ - --pad-oper --pad-comma --pad-header --unpad-paren \ - --align-pointer=name diff --git a/Makefile b/Makefile index 0daf03f..fe662af 100644 --- a/Makefile +++ b/Makefile @@ -50,7 +50,4 @@ test: bin/test clean: rm -f bin/* obj/* -style: - astyle -n --recursive "src/*.c" "src/*.h" "test/*.c" "test/*.h" - -.PHONY: clean test style +.PHONY: clean test diff --git a/src/compress.c b/src/compress.c index 578441b..47acb74 100644 --- a/src/compress.c +++ b/src/compress.c @@ -17,10 +17,14 @@ You should have received a copy of the GNU General Public License along with Nekopack. If not, see . */ +#include + #include #include "io.h" +#define LEVEL -1 + /* Inflates `s` into a newly allocated stream structure. */ struct stream *stream_inflate(struct stream *s, size_t len, @@ -56,3 +60,29 @@ struct stream *stream_inflate(struct stream *s, size_t len, inflateEnd(&strm); return n; } + + +/* Deflates `s` into a newly allocated stream structure. */ +struct stream *stream_deflate(struct stream *s, size_t len) { + struct stream *new = stream_new(len); + z_stream strm; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + + if (deflateInit(&strm, LEVEL) != Z_OK) + return NULL; + + do { + strm.avail_in = len; + strm.next_in = (unsigned char *) s->_cur; + do { + strm.avail_out = len; + strm.next_out = (unsigned char *) new->_cur; + deflate(&strm, Z_NO_FLUSH); // Flush param may cause issues. + } while (strm.avail_out == 0); + } while (0); + + deflateEnd(&strm); + return new; +} diff --git a/src/compress.h b/src/compress.h index 070151f..cfb2487 100644 --- a/src/compress.h +++ b/src/compress.h @@ -24,3 +24,6 @@ /* Inflates `s` into a newly allocated stream structure. */ struct stream *stream_inflate(struct stream *s, size_t len, size_t decompressed_len); + +/* Deflates `s` into a newly allocated stream structure. */ +struct stream *stream_deflate(struct stream *s, size_t len); diff --git a/src/io.c b/src/io.c index d282edc..cd6e8a3 100644 --- a/src/io.c +++ b/src/io.c @@ -91,7 +91,7 @@ void stream_dump(FILE *fp, struct stream *s, size_t n) { /* Copies `n` bytes into the given stream from the memory area specified by `src`. The stream's cursor is advanced appropriately. */ void stream_write(struct stream *s, void *src, size_t n) { - if (s->_cur + n > s->_start + s->len) { + while (s->_cur + n > s->_start + s->len) { ptrdiff_t dist = (uintptr_t) s->_cur - (uintptr_t) s->_start; switch(s->_loc) { case HEAP: @@ -105,6 +105,12 @@ void stream_write(struct stream *s, void *src, size_t n) { } +/* Concatenats the contents of `src` onto `dst`. */ +void stream_concat(struct stream *dst, struct stream *src, size_t n) { + stream_write(dst, src->_cur, n); +} + + /* Applies an initial and primary key to the given stream, effectively encrypting or decrypting it. */ void stream_xor(struct stream *s, uint8_t initial, uint8_t primary) { diff --git a/src/io.h b/src/io.h index b37ec51..ae80149 100644 --- a/src/io.h +++ b/src/io.h @@ -61,6 +61,9 @@ void stream_read(void *dest, struct stream *s, size_t n); by `src`. The stream's cursor is advanced appropriately. */ void stream_write(struct stream *s, void *src, size_t n); +/* Concatenats the contents of `src` onto `dst`. */ +void stream_concat(struct stream *dst, struct stream *src, size_t n); + /* Dumps the contents of `s` into the file specified by `fp`. */ void stream_dump(FILE *fp, struct stream *s, size_t n); diff --git a/src/main.c b/src/main.c index db7c21c..8949272 100644 --- a/src/main.c +++ b/src/main.c @@ -208,15 +208,29 @@ static void create_archive(char **paths, int argc, struct params p) { return; } - struct table_entry *cur, *root = calloc(sizeof(struct table_entry), 1); - struct header *h = create_header(); - struct stream *table = stream_new(1); + struct table_entry *root = calloc(sizeof(struct table_entry), 1); + struct table_entry *cur; + struct header *h = create_header(); + struct stream *data = stream_new(1); + struct stream *table = stream_new(1); + struct stream *file; + uint64_t data_size = 0; uint64_t table_size; dump_header(fp, h); for (int i = 1; i < argc - p.vararg_index; i++) { + file = stream_from_file(paths[i]); + if (file == NULL) { + perror(paths[i]); + continue; + } + + data_size += file->len; + stream_concat(data, file, file->len); cur = add_file(root, paths[i]); } + stream_seek(data, 0, SEEK_SET); + stream_dump(fp, data, data_size); table_size = dump_table(table, root); stream_dump(fp, table, table_size); } diff --git a/src/table.c b/src/table.c index 849780d..6a88d56 100644 --- a/src/table.c +++ b/src/table.c @@ -54,18 +54,55 @@ static void read_segm(struct stream *s, struct table_entry *tmp, uint64_t count) } +/* Dumps the segm segment for `cur` into the table at `s`. */ +static void dump_segm(struct stream *s, struct table_entry *cur) { + struct segment *segm; + uint32_t magic = SEGM_MAGIC; + uint64_t entry_size = cur->segment_count * 28; + stream_write(s, &magic, sizeof(uint32_t)); + stream_write(s, &entry_size, sizeof(uint64_t)); + for (uint64_t i = 0; i < cur->segment_count; i++) { + segm = cur->segments[i]; + stream_write(s, &segm->compressed, sizeof(uint32_t)); + stream_write(s, &segm->offset, sizeof(uint64_t)); + stream_write(s, &segm->decompressed_size, sizeof(uint64_t)); + stream_write(s, &segm->compressed_size, sizeof(uint64_t)); + } +} + + /* Reads an adlr chunk into the table_entry specified by `tmp`. */ static void read_adlr(struct stream *s, struct table_entry *tmp) { stream_read(&tmp->key, s, sizeof(uint32_t)); } +/* Dumps the adlr segment for `key` into the table at `s`. */ +static void dump_adlr(struct stream *s, uint32_t key) { + uint32_t magic = ADLR_MAGIC; + uint64_t entry_size = sizeof(uint32_t); + stream_write(s, &magic, sizeof(uint32_t)); + stream_write(s, &entry_size, sizeof(uint64_t)); + stream_write(s, &key, sizeof(uint32_t)); +} + + /* Reads a time chunk into the table_entry specified by `tmp`. */ static void read_time(struct stream *s, struct table_entry *tmp) { stream_read(&tmp->ctime, s, sizeof(uint64_t)); } +/* Dumps the time segment for `timestamp` into the table at `s`. */ +static void dump_time(struct stream *s, uint64_t timestamp) { + uint32_t magic = TIME_MAGIC; + uint64_t entry_size = sizeof(uint64_t); + stream_write(s, &magic, sizeof(uint32_t)); + stream_write(s, &entry_size, sizeof(uint64_t)); + stream_write(s, ×tamp, sizeof(uint64_t)); +} + + /* Reads the contents of a File chunk. If there is an entry with a matching key in the linked list specified by `root`, that structure will be modified. Otherwise, a new entry will be created and appended @@ -107,6 +144,25 @@ void read_file(struct stream *s, struct table_entry *root) { } +/* Dumps the File entry for `cur` into the table at `s` and returns the + number of bytes written. */ +static uint64_t dump_file(struct stream *s, struct table_entry *cur) { + uint32_t magic = FILE_MAGIC; + uint64_t bytes_written = 28 * cur->segment_count + 48; + stream_write(s, &magic, sizeof(uint32_t)); + stream_write(s, &bytes_written, sizeof(uint64_t)); + + dump_adlr(s, cur->key); + dump_time(s, cur->ctime); + dump_segm(s, cur); + + stream_seek(s, -bytes_written, SEEK_CUR); + stream_write(s, &bytes_written, sizeof(uint64_t)); + stream_seek(s, bytes_written, SEEK_CUR); + return bytes_written; +} + + /* Reads the contents of an eliF chunk. If there is an entry with a matching key in the linked list specified by `root`, that structure will be modified. Otherwise, a new entry will be created and appended @@ -155,6 +211,24 @@ void read_elif(struct stream *s, struct table_entry *root) { } +/* Dumps the eliF entry for `cur` into the table at `s` and returns the + number of bytes written. */ +static uint64_t dump_elif(struct stream *s, struct table_entry *cur) { + uint32_t magic = ELIF_MAGIC; + uint16_t name_len = strlen(cur->filename); + uint64_t entry_size = name_len * 2 + 8; + char *encoded = malloc(name_len * 2 + 2); + utf16le_encode(cur->filename, encoded, name_len); + + stream_write(s, &magic, sizeof(uint32_t)); + stream_write(s, &entry_size, sizeof(uint64_t)); + stream_write(s, &cur->key, sizeof(uint32_t)); + stream_write(s, &name_len, sizeof(uint16_t)); + stream_write(s, encoded, name_len * 2 + 2); + return 18 + name_len * 2 + 2; +} + + /* Returns the root of a linked list containing all of the files listed in the archive's table section. */ struct table_entry *read_table(struct stream *s) { @@ -186,6 +260,20 @@ struct table_entry *read_table(struct stream *s) { } +/* Dumps the XP3 table specified by `root` into `s` and returns the + number of bytes written. */ +uint64_t dump_table(struct stream *s, struct table_entry *root) { + uint64_t bytes_written = 0; + struct table_entry *cur; + for (cur = root->next; cur != NULL; cur = cur->next) { + bytes_written += dump_elif(s, cur); + bytes_written += dump_file(s, cur); + } + stream_seek(s, 0, SEEK_SET); + return bytes_written; +} + + /* Inserts the file specified by `path` into the table linked list specified by `root`. */ struct table_entry *add_file(struct table_entry *root, char *path) { @@ -203,94 +291,6 @@ struct table_entry *add_file(struct table_entry *root, char *path) { } -/* Dumps the adlr segment for `key` into the table at `s`. */ -static void dump_adlr(struct stream *s, uint32_t key) { - uint32_t magic = ADLR_MAGIC; - uint64_t entry_size = sizeof(uint32_t); - stream_write(s, &magic, sizeof(uint32_t)); - stream_write(s, &entry_size, sizeof(uint64_t)); - stream_write(s, &key, sizeof(uint32_t)); -} - - -/* Dumps the time segment for `timestamp` into the table at `s`. */ -static void dump_time(struct stream *s, uint64_t timestamp) { - uint32_t magic = TIME_MAGIC; - uint64_t entry_size = sizeof(uint64_t); - stream_write(s, &magic, sizeof(uint32_t)); - stream_write(s, &entry_size, sizeof(uint64_t)); - stream_write(s, ×tamp, sizeof(uint64_t)); -} - - -/* Dumps the segm segment for `cur` into the table at `s`. */ -static void dump_segm(struct stream *s, struct table_entry *cur) { - struct segment *segm; - uint32_t magic = SEGM_MAGIC; - uint64_t entry_size = cur->segment_count * 28; - stream_write(s, &magic, sizeof(uint32_t)); - stream_write(s, &entry_size, sizeof(uint64_t)); - for (uint64_t i = 0; i < cur->segment_count; i++) { - segm = cur->segments[i]; - stream_write(s, &segm->compressed, sizeof(uint32_t)); - stream_write(s, &segm->offset, sizeof(uint64_t)); - stream_write(s, &segm->decompressed_size, sizeof(uint64_t)); - stream_write(s, &segm->compressed_size, sizeof(uint64_t)); - } -} - - -/* Dumps the File entry for `cur` into the table at `s` and returns the - number of bytes written. */ -static uint64_t dump_file(struct stream *s, struct table_entry *cur) { - uint32_t magic = FILE_MAGIC; - uint64_t bytes_written = 28 * cur->segment_count + 48; - stream_write(s, &magic, sizeof(uint32_t)); - stream_write(s, &bytes_written, sizeof(uint64_t)); - - dump_adlr(s, cur->key); - dump_time(s, cur->ctime); - dump_segm(s, cur); - - stream_seek(s, -bytes_written, SEEK_CUR); - stream_write(s, &bytes_written, sizeof(uint64_t)); - stream_seek(s, bytes_written, SEEK_CUR); - return bytes_written; -} - - -/* Dumps the eliF entry for `cur` into the table at `s` and returns the - number of bytes written. */ -static uint64_t dump_elif(struct stream *s, struct table_entry *cur) { - uint32_t magic = ELIF_MAGIC; - uint16_t name_len = strlen(cur->filename); - uint64_t entry_size = name_len * 2 + 8; - char *encoded = malloc(name_len * 2 + 2); - utf16le_encode(cur->filename, encoded, name_len); - - stream_write(s, &magic, sizeof(uint32_t)); - stream_write(s, &entry_size, sizeof(uint64_t)); - stream_write(s, &cur->key, sizeof(uint32_t)); - stream_write(s, &name_len, sizeof(uint16_t)); - stream_write(s, encoded, name_len * 2 + 2); - return 18 + name_len * 2 + 2; -} - - -/* Dumps the XP3 table specified by `root` into `s` and returns the - number of bytes written. */ -uint64_t dump_table(struct stream *s, struct table_entry *root) { - uint64_t bytes_written = 0; - struct table_entry *cur; - for (cur = root->next; cur != NULL; cur = cur->next) { - bytes_written += dump_elif(s, cur); - bytes_written += dump_file(s, cur); - } - stream_seek(s, 0, SEEK_SET); - return bytes_written; -} - - /* Traverses `root` for a node with the given key. If the linked list lacks a node with the key, a new node is created and appended. */ struct table_entry *get_node(struct table_entry *root, uint32_t key) { diff --git a/src/table.h b/src/table.h index e36759c..74de5b0 100644 --- a/src/table.h +++ b/src/table.h @@ -44,21 +44,25 @@ struct table_entry { }; -/* Returns the root of a linked list containing all of the files listed - in the archive's table section. */ -struct table_entry *read_table(struct stream *s); - -/* Reads the contents of an eliF chunk. If there is an entry with a +/* Reads the contents of a File chunk. If there is an entry with a matching key in the linked list specified by `root`, that structure will be modified. Otherwise, a new entry will be created and appended to the linked list. */ -void read_elif(struct stream *s, struct table_entry *root); +void read_file(struct stream *s, struct table_entry *root); -/* Reads the contents of a File chunk. If there is an entry with a +/* Reads the contents of an eliF chunk. If there is an entry with a matching key in the linked list specified by `root`, that structure will be modified. Otherwise, a new entry will be created and appended to the linked list. */ -void read_file(struct stream *s, struct table_entry *root); +void read_elif(struct stream *s, struct table_entry *root); + +/* Returns the root of a linked list containing all of the files listed + in the archive's table section. */ +struct table_entry *read_table(struct stream *s); + +/* Dumps the XP3 table specified by `root` into `s` and returns the + number of bytes written. */ +uint64_t dump_table(struct stream *s, struct table_entry *root); /* Inserts the file specified by `path` into the table linked list specified by `root`. */ @@ -73,11 +77,3 @@ void entry_append(struct table_entry *root, struct table_entry *e); /* Frees every entry in the linked list specified by `cur`. */ void entry_free(struct table_entry *cur); - -/* Dumps the XP3 table specified by `root` into `s` and returns the - number of bytes written. */ -uint64_t dump_table(struct stream *s, struct table_entry *root); - -/* Inserts the file specified by `path` into the table linked list - specified by `root`. */ -struct table_entry *add_file(struct table_entry *root, char *path); -- cgit v1.3