summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/encoding.c21
-rw-r--r--src/encoding.h4
-rw-r--r--src/main.c3
-rw-r--r--src/table.c106
-rw-r--r--src/table.h4
5 files changed, 102 insertions, 36 deletions
diff --git a/src/encoding.c b/src/encoding.c
index e7af310..8b1b7dc 100644
--- a/src/encoding.c
+++ b/src/encoding.c
@@ -18,11 +18,13 @@
along with Nekopack. If not, see <http://www.gnu.org/licenses/>. */
#include <iconv.h>
+#include <string.h>
/* Wrapper for iconv, using the conversion specified by `conv`. */
-static void convert(char *in_buf, char *out_buf, size_t len, iconv_t conv) {
- size_t in_size = len, out_size = len;
+static void convert(char *in_buf, char *out_buf, size_t in_len,
+ size_t out_len, iconv_t conv) {
+ size_t in_size = in_len, out_size = out_len;
char *in_start = in_buf, *out_start = out_buf;
iconv(conv, &in_start, &in_size, &out_start, &out_size);
}
@@ -31,6 +33,19 @@ static void convert(char *in_buf, char *out_buf, size_t len, iconv_t conv) {
/* Decodes the UTF-16LE string specified by `in_buf` into `out_buf`. */
void utf16le_decode(char *in_buf, char *out_buf, size_t len) {
iconv_t conv = iconv_open("UTF-8", "UTF-16LE");
- convert(in_buf, out_buf, len, conv);
+ convert(in_buf, out_buf, len, len, conv);
+ iconv_close(conv);
+}
+
+
+/* Encodes the UTF-8 string specified by `in_buf` into a UTF-16LE string
+ stored in `out_buf`. */
+void utf16le_encode(char *in_buf, char *out_buf, size_t len) {
+ iconv_t conv = iconv_open("UTF-16LE", "UTF-8");
+ /* This is to ensure that the null-terminator is included in the
+ encoded string. */
+ if (strlen(in_buf) == len)
+ len++;
+ convert(in_buf, out_buf, len, len * 2 + 2, conv);
iconv_close(conv);
}
diff --git a/src/encoding.h b/src/encoding.h
index d47f78e..b8f211f 100644
--- a/src/encoding.h
+++ b/src/encoding.h
@@ -21,3 +21,7 @@
/* Decodes the UTF-16LE string specified by `in_buf` into `out_buf`. */
void utf16le_decode(char *in_buf, char *out_buf, size_t len);
+
+/* Encodes the UTF-8 string specified by `in_buf` into a UTF-16LE string
+ stored in `out_buf`. */
+void utf16le_encode(char *in_buf, char *out_buf, size_t len);
diff --git a/src/main.c b/src/main.c
index 566ea55..cd0d0f5 100644
--- a/src/main.c
+++ b/src/main.c
@@ -207,7 +207,8 @@ static void create_archive(char **paths, struct params p) {
return;
}
- struct header *h = create_header();
+ struct header *h = create_header();
+ struct table_entry *root = calloc(sizeof(struct table_entry), 1);
dump_header(fp, h);
}
diff --git a/src/table.c b/src/table.c
index 7998295..a67c735 100644
--- a/src/table.c
+++ b/src/table.c
@@ -66,37 +66,6 @@ static void read_time(struct stream *s, struct table_entry *tmp) {
}
-/* 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) {
- struct table_entry *root = calloc(sizeof(struct table_entry), 1);
-
- bool ended = false;
- uint32_t magic;
- uint64_t size;
-
- do {
- stream_read(&magic, s, sizeof(uint32_t));
- stream_read(&size, s, sizeof(uint64_t));
-
- switch (magic) {
- case ELIF_MAGIC:
- case HNFN_MAGIC:
- case NEKO_MAGIC:
- read_elif(s, root);
- break;
- case FILE_MAGIC:
- read_file(s, root);
- break;
- default:
- ended = 1;
- }
- } while (!ended);
-
- return root;
-}
-
-
/* 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
@@ -186,6 +155,79 @@ 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) {
+ struct table_entry *root = calloc(sizeof(struct table_entry), 1);
+
+ bool ended = false;
+ uint32_t magic;
+ uint64_t size;
+
+ do {
+ stream_read(&magic, s, sizeof(uint32_t));
+ stream_read(&size, s, sizeof(uint64_t));
+
+ switch (magic) {
+ case ELIF_MAGIC:
+ case HNFN_MAGIC:
+ case NEKO_MAGIC:
+ read_elif(s, root);
+ break;
+ case FILE_MAGIC:
+ read_file(s, root);
+ break;
+ default:
+ ended = 1;
+ }
+ } while (!ended);
+
+ return 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) {
+ struct table_entry *new = calloc(sizeof(struct table_entry), 1);
+ size_t name_len = strlen(path);
+ new->filename = malloc(name_len);
+ strncpy(new->filename, path, name_len);
+
+ new->key = 0xffffffff;
+ new->ctime = 0;
+ new->segment_count = 0;
+ entry_append(root, new);
+
+ return new;
+}
+
+
+/* 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);
+ 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);
+ fwrite(&entry_size, sizeof(uint64_t), 1, fp);
+ fwrite(&key, sizeof(uint32_t), 1, fp);
+ fwrite(&name_len, sizeof(uint16_t), 1, fp);
+ fwrite(encoded, name_len * 2 + 2, 1, fp);
+}
+
+
+/* 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);
+ }
+}
+
+
/* 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) {
@@ -196,7 +238,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 80ad099..89189c6 100644
--- a/src/table.h
+++ b/src/table.h
@@ -60,6 +60,10 @@ void read_elif(struct stream *s, struct table_entry *root);
to the linked list. */
void read_file(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);
+
/* 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);