summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compress.c30
-rw-r--r--src/compress.h3
-rw-r--r--src/io.c8
-rw-r--r--src/io.h3
-rw-r--r--src/main.c20
-rw-r--r--src/table.c176
-rw-r--r--src/table.h28
7 files changed, 160 insertions, 108 deletions
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 <http://www.gnu.org/licenses/>. */
+#include <stdlib.h>
+
#include <zlib.h>
#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, &timestamp, 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, &timestamp, 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);