summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.c10
-rw-r--r--src/table.c81
-rw-r--r--src/table.h7
3 files changed, 84 insertions, 14 deletions
diff --git a/src/main.c b/src/main.c
index cd0d0f5..d68961c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -200,7 +200,7 @@ static void map_entries(char *path, struct params p) {
/* Creates a new XP3 archive at the first path specified by `paths`, and
flattens files specified by any following paths into the archive. */
-static void create_archive(char **paths, struct params p) {
+static void create_archive(char **paths, int argc, struct params p) {
FILE *fp = fopen(paths[0], "wb+");
if (fp == NULL) {
perror(paths[0]);
@@ -208,8 +208,12 @@ static void create_archive(char **paths, struct params p) {
}
struct header *h = create_header();
- struct table_entry *root = calloc(sizeof(struct table_entry), 1);
+ struct table_entry *root = calloc(sizeof(struct table_entry), 1), *cur;
dump_header(fp, h);
+ for (int i = 1; i < argc - p.vararg_index; i++) {
+ cur = add_file(root, paths[i]);
+ }
+ dump_table(fp, root);
}
@@ -232,7 +236,7 @@ int main(int argc, char **argv) {
map_entries(argv[i], p);
break;
case CREATE:
- create_archive(argv + p.vararg_index, p);
+ create_archive(argv + p.vararg_index, argc, p);
}
params_free(p);
return EXIT_SUCCESS;
diff --git a/src/table.c b/src/table.c
index a67c735..afd2e0f 100644
--- a/src/table.c
+++ b/src/table.c
@@ -203,17 +203,75 @@ struct table_entry *add_file(struct table_entry *root, char *path) {
}
-/* Dumps an eliF entry into the table at `fp`. */
-static void dump_elif(FILE *fp, char *path, uint32_t key) {
- /* FIXME: Entry size is likely incorrect. Go back and inspect the
- table output. */
- uint16_t name_len = strlen(path);
+/* Dumps the adlr segment for `key` into the table at `fp` and returns
+ the number of bytes written. */
+static uint64_t dump_adlr(FILE *fp, uint32_t key) {
+ uint32_t magic = ADLR_MAGIC;
+ uint64_t written, entry_size = sizeof(uint32_t);
+ written = fwrite(&magic, sizeof(uint32_t), 1, fp);
+ written += fwrite(&entry_size, sizeof(uint64_t), 1, fp);
+ written += fwrite(&key, sizeof(uint32_t), 1, fp);
+ return written;
+}
+
+
+/* Dumps the time segment for `timestamp` into the table at `fp` and
+ returns the number of bytes written. */
+static uint64_t dump_time(FILE *fp, uint64_t timestamp) {
+ uint32_t magic = TIME_MAGIC;
+ uint64_t written, entry_size = sizeof(uint64_t);
+ written = fwrite(&magic, sizeof(uint32_t), 1, fp);
+ written += fwrite(&entry_size, sizeof(uint32_t), 1, fp);
+ written += fwrite(&timestamp, sizeof(uint32_t), 1, fp);
+ return written;
+}
+
+
+/* Dumps the segm segment for `cur` into the table at `fp` and returns
+ the number of bytes written. */
+static uint64_t dump_segm(FILE *fp, struct table_entry *cur) {
+ struct segment *s;
+ uint32_t magic = SEGM_MAGIC;
+ uint64_t written, entry_size = cur->segment_count * 28;
+ written = fwrite(&magic, sizeof(uint32_t), 1, fp);
+ written += fwrite(&entry_size, sizeof(uint32_t), 1, fp);
+ for (uint64_t i = 0; i < cur->segment_count; i++) {
+ s = cur->segments[i];
+ written += fwrite(&s->compressed, sizeof(uint32_t), 1, fp);
+ written += fwrite(&s->offset, sizeof(uint64_t), 1, fp);
+ written += fwrite(&s->decompressed_size, sizeof(uint64_t), 1, fp);
+ written += fwrite(&s->compressed_size, sizeof(uint64_t), 1, fp);
+ }
+ return written;
+}
+
+
+/* Dumps the File entry for `cur` into the table at `fp`. */
+static void dump_file(FILE *fp, struct table_entry *cur) {
+ uint32_t magic = FILE_MAGIC;
+ uint64_t bytes_written;
+ fwrite(&magic, sizeof(uint32_t), 1, fp);
+ fwrite(&bytes_written, sizeof(uint64_t), 1, fp);
+ bytes_written = dump_adlr(fp, cur->key);
+ bytes_written += dump_time(fp, cur->ctime);
+ bytes_written += dump_segm(fp, cur);
+
+ fseek(fp, -bytes_written, SEEK_CUR);
+ fwrite(&bytes_written, sizeof(uint64_t), 1, fp);
+ fseek(fp, bytes_written, SEEK_CUR);
+}
+
+
+/* Dumps the eliF entry for `cur` into the table at `fp`. */
+static void dump_elif(FILE *fp, 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(path, encoded, name_len);
- fwrite(&ELIF_MAGIC, sizeof(uint32_t), 1, fp);
+ utf16le_encode(cur->filename, encoded, name_len);
+ fwrite(&magic, sizeof(uint32_t), 1, fp);
fwrite(&entry_size, sizeof(uint64_t), 1, fp);
- fwrite(&key, sizeof(uint32_t), 1, fp);
+ fwrite(&cur->key, sizeof(uint32_t), 1, fp);
fwrite(&name_len, sizeof(uint16_t), 1, fp);
fwrite(encoded, name_len * 2 + 2, 1, fp);
}
@@ -222,8 +280,9 @@ static void dump_elif(FILE *fp, char *path, uint32_t key) {
/* Dumps the XP3 table specified by `root` into `fp`. */
void dump_table(FILE *fp, struct table_entry *root) {
struct table_entry *cur;
- for (cur = root; cur != NULL; cur = cur->next) {
- dump_elif(fp, cur->filename, cur->key);
+ for (cur = root->next; cur != NULL; cur = cur->next) {
+ dump_elif(fp, cur);
+ dump_file(fp, cur);
}
}
@@ -238,7 +297,7 @@ struct table_entry *get_node(struct table_entry *root, uint32_t key) {
if (cur == NULL) return NULL;
entry_append(root, cur);
cur->key = key;
-p }
+ }
return cur;
}
diff --git a/src/table.h b/src/table.h
index 89189c6..d9e9f53 100644
--- a/src/table.h
+++ b/src/table.h
@@ -73,3 +73,10 @@ 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 `fp`. */
+void dump_table(FILE *fp, 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);