Skip to content
This repository has been archived by the owner on Jan 21, 2019. It is now read-only.

Commit

Permalink
Cleaned up
Browse files Browse the repository at this point in the history
  • Loading branch information
TsarFox committed Jun 6, 2017
1 parent 17b658c commit cfd5fb6
Show file tree
Hide file tree
Showing 13 changed files with 150 additions and 88 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ You can add specific flags to the Makefile with `USER_CFLAGS` and/or `USER_LDFLA


## TODO
* Full unit testing.
* Full unit testing, test static functions.
* Clean up `main.c`, move functions like `load_table` and `make_dirs` into more appropriate files.
* Clean up `create_archive`.
* Strict warnings.

* Game-compatible file encryption on created archives.
18 changes: 9 additions & 9 deletions src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,20 @@
#include "cli.h"
#include "crypto.h"

#define NEKOPACK_VERSION "2.1.0b1"
#define NEKOPACK_VERSION "2.1.0"


/* Copies `optarg` into the out field of `p` and ensures that it ends in
a trailing path delimiter. */
/* Copies `optarg` into the out member of `p` and ensures that it has a
trailing path delimiter. */
static void parse_output_path(const char *optarg, struct params *p) {
p->out_len = strlen(optarg);
p->out = malloc(p->out_len + 2);

if (p->out == NULL)
return;

strcpy(p->out, optarg);

if (p->out[p->out_len - 1] != '/') {
p->out[p->out_len] = '/';
p->out_len += 1;
Expand Down Expand Up @@ -78,15 +83,14 @@ struct params parse_args(int argc, char **argv) {
{"extract", no_argument, NULL, 'e'},
{"list", no_argument, NULL, 'l'},
{"create", no_argument, NULL, 'c'},
{"debug", no_argument, NULL, 'd'},
{"output", no_argument, NULL, 'o'},
{"game", no_argument, NULL, 'g'},
{NULL, 0, NULL, 0}
};

do {
count++;
cur = getopt_long(argc, argv, "hVvelcdqo:g:", long_opts, &opt_index);
cur = getopt_long(argc, argv, "hVvelcqo:g:", long_opts, &opt_index);
switch (cur) {
case 'h':
p.mode = HELP;
Expand Down Expand Up @@ -120,10 +124,6 @@ struct params parse_args(int argc, char **argv) {

case 'c':
p.mode = CREATE;
break;

case 'd':
p.mode = DEBUG;
}
} while (cur >= 0);

Expand Down
1 change: 0 additions & 1 deletion src/cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ enum {
LIST,
EXTRACT,
CREATE,
DEBUG,
};

/* Structure for storing options set from the command-line. */
Expand Down
16 changes: 10 additions & 6 deletions src/compress.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@
#define LEVEL -1


/* Inflates `s` into a newly allocated stream structure. */
/* Inflates `len` bytes from the current position of `s` to a new stream
structure of size `decompressed_len` bytes. Stream inflation will not
work if `decompressed_len` does not represent the actual size of the
original data. */
struct stream *stream_inflate(struct stream *s, size_t len,
size_t decompressed_len) {
z_stream strm;
Expand All @@ -40,29 +43,30 @@ struct stream *stream_inflate(struct stream *s, size_t len,
return NULL;

int ret;
struct stream *n = stream_new(decompressed_len);
struct stream *new = stream_new(decompressed_len);

do {
strm.avail_in = len;
strm.next_in = (Bytef *) s->_cur;
do {
strm.avail_out = decompressed_len;
strm.next_out = (Bytef *) n->_cur;
strm.next_out = (Bytef *) new->_cur;
ret = inflate(&strm, Z_NO_FLUSH);
if (ret == Z_STREAM_ERROR) {
stream_free(n);
stream_free(new);
inflateEnd(&strm);
return NULL;
}
} while (strm.avail_out == 0);
} while (ret != Z_STREAM_END);

inflateEnd(&strm);
return n;
return new;
}


/* Deflates `s` into a newly allocated stream structure. */
/* Deflates `len` bytes from the current position of `s` to a new stream
structure, where the `len` member represents the decompressed size. */
struct stream *stream_deflate(struct stream *s, size_t len) {
struct stream *new = stream_new(len);
if (new == NULL)
Expand Down
8 changes: 6 additions & 2 deletions src/compress.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,13 @@

#include "io.h"

/* Inflates `s` into a newly allocated stream structure. */
/* Inflates `len` bytes from the current position of `s` to a new stream
structure of size `decompressed_len` bytes. Stream inflation will not
work if `decompressed_len` does not represent the actual size of the
original data. */
struct stream *stream_inflate(struct stream *s, size_t len,
size_t decompressed_len);

/* Deflates `s` into a newly allocated stream structure. */
/* Deflates `len` bytes from the current position of `s` to a new stream
structure, where the `len` member represents the decompressed size. */
struct stream *stream_deflate(struct stream *s, size_t len);
32 changes: 16 additions & 16 deletions src/header.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,22 @@ static bool is_supported(struct header *h) {
}


/* Generates an XP3 header structure readable by Nekopara. */
struct header *create_header(void) {
struct header *h = malloc(sizeof(struct header));
if (h == NULL)
return NULL;

memcpy(h->magic, XP3_MAGIC, 11);
h->info_offset = 0x17;
h->version = 1;
h->flags = 0x80;
h->table_size = 0;
h->table_offset = 0;
return h;
}


/* Reads from the given stream into a newly allocated header structure.
NULL is returned if the header contains an invalid magic number, or
if the archive's version is not supported. */
Expand All @@ -63,22 +79,6 @@ struct header *read_header(struct stream *s) {
}


/* Generates an XP3 header structure readable by Nekopara. */
struct header *create_header(void) {
struct header *h = malloc(sizeof(struct header));
if (h == NULL)
return NULL;

memcpy(h->magic, XP3_MAGIC, 11);
h->info_offset = 0x17;
h->version = 1;
h->flags = 0x80;
h->table_size = 0;
h->table_offset = 0;
return h;
}


/* Dumps the XP3 header specified by `h` into `fp`. */
void dump_header(FILE *fp, struct header *h) {
fwrite(h->magic, 11, 1, fp);
Expand Down
44 changes: 0 additions & 44 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
You should have received a copy of the GNU General Public License
along with Nekopack. If not, see <http://www.gnu.org/licenses/>. */

#include <inttypes.h> /* Only used for debug mode. */
#include <errno.h>
#include <sys/stat.h>
#include <stdint.h>
Expand All @@ -35,9 +34,6 @@
#define EXIT_FAILURE 1
#define EXIT_SUCCESS 0

#define ANSI_TITLE "\x1b[36m\x1b[4m"
#define ANSI_END "\x1b[0m"


static struct stream *load_table(struct stream *s) {
uint8_t compressed;
Expand Down Expand Up @@ -245,7 +241,6 @@ static void create_archive(char **paths, int argc, struct params p) {
return;
}

/* TODO: Separate into own function. */
table_size += 20 + strlen(cur->filename) * 2;
table_size += 28 * cur->segment_count + 60;

Expand Down Expand Up @@ -286,11 +281,9 @@ static void create_archive(char **paths, int argc, struct params p) {
h->table_offset = 40 + data->len;
dump_header(fp, h);

/* FIXME: Formatting and this initial seek might not be necessary. */
stream_seek(data, 0, SEEK_SET);
stream_dump(fp, data, data->len);

/* FIXME: May be an incompatible value. Also, move this shitty hack. */
uint8_t compressed = 1;
fwrite(&compressed, sizeof(uint8_t), 1, fp);
fwrite(&table_compressed->len, sizeof(uint64_t), 1, fp);
Expand All @@ -300,38 +293,6 @@ static void create_archive(char **paths, int argc, struct params p) {
}


/* The name is not particularly fitting to its function. */
static void display_table(char *path, struct params p) {
/* Replicated code. Could this be in map_entries? */
struct stream *archive = stream_from_file(path);
if (archive == NULL) {
if (errno == ENOENT) {
perror(path);
} else {
fprintf(stderr, "Error allocating memory.\n");
}
return;
}

struct header *h = read_header(archive);
if (h == NULL) {
fprintf(stderr, "File is not an XP3 archive.\n");
return;
}

printf(ANSI_TITLE "Archive Header\n" ANSI_END);
printf("Magic: ");
for (int i = 0; i < 11; i++)
printf("%x", h->magic[i]);
printf("\n");
printf("Info Offset: 0x%"PRIx64"\n", h->info_offset);
printf("Version: 0x%"PRIx32"\n", h->version);
printf("Flags: 0x%"PRIx8"\n", h->flags);
printf("Table Size: 0x%"PRIx64"\n", h->table_size);
printf("Table Offset: 0x%"PRIx64"\n", h->table_offset);
}


int main(int argc, char **argv) {
struct params p = parse_args(argc, argv);
switch (p.mode) {
Expand All @@ -354,11 +315,6 @@ int main(int argc, char **argv) {
map_entries(argv[i], p);
break;

case DEBUG:
for (int i = p.vararg_index; i < argc; i++)
display_table(argv[i], p);
break;

case CREATE:
create_archive(argv + p.vararg_index, argc, p);
}
Expand Down
16 changes: 8 additions & 8 deletions test/test_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,19 @@ char *test_out_path(void) {
}


char *test_vararg_index(void) {
char *argv[] = {"nekopack", "-l", "a.xp3"};
struct params p = parse_args(3, argv);
mu_assert("Invalid vararg index", !strcmp("a.xp3", argv[p.vararg_index]));
char *test_game_id(void) {
char *argv[] = {"nekopack", "-g", "nekopara_volume_1", "a.xp3"};
struct params p = parse_args(4, argv);
mu_assert("Incorrect game ID", p.game == NEKOPARA_VOLUME_1);
free(p.out);
return NULL;
}


char *test_game_id(void) {
char *argv[] = {"nekopack", "-g", "nekopara_volume_1", "a.xp3"};
struct params p = parse_args(4, argv);
mu_assert("Incorrect game ID", p.game == NEKOPARA_VOLUME_1);
char *test_vararg_index(void) {
char *argv[] = {"nekopack", "-l", "a.xp3"};
struct params p = parse_args(3, argv);
mu_assert("Invalid vararg index", !strcmp("a.xp3", argv[p.vararg_index]));
free(p.out);
return NULL;
}
72 changes: 72 additions & 0 deletions test/test_compress.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/* test_compress.c -- MinUnit test cases for compress.c
Copyright (C) 2017 Jakob Kreuze, All Rights Reserved.
This file is part of Nekopack.
Nekopack is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
Nekopack is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with Nekopack. If not, see <http://www.gnu.org/licenses/>. */

#include <stdbool.h>

#include "minunit.h"

#include "compress.h"
#include "io.h"

extern int tests_run;

/* FIXME: This won't hold up for the future. Even if it works across
different versions of zlib, if the compression rate is ever changed
this test will fail. */

/* TODO: Replace with a proper stream comparison and put it in io.c? */
static bool streams_eq(struct stream *a, struct stream *b) {
if (a->len != b->len)
return false;
for (unsigned long i = 0; i < a->len; i++) {
if (a->_start[i] != b->_start[i])
return false;
}
return true;
}


char *test_compress(void) {
struct stream *s = stream_from_file("test/vectors/test.png");
struct stream *expected = stream_from_file("test/vectors/test.bin");
mu_assert("Could not open test vectors", s != NULL && expected != NULL);

struct stream *res = stream_deflate(s, s->len);
mu_assert("Expected compression not met", streams_eq(res, expected));

stream_free(s);
stream_free(expected);
stream_free(res);
return NULL;
}


char *test_decompress(void) {
struct stream *s = stream_from_file("test/vectors/test.bin");
struct stream *expected = stream_from_file("test/vectors/test.png");
mu_assert("Could not open test vectors", s != NULL && expected != NULL);

struct stream *res = stream_inflate(s, s->len, 176608);
mu_assert("Expected compression not met", streams_eq(res, expected));

stream_free(s);
stream_free(expected);
stream_free(res);
return NULL;
}
23 changes: 23 additions & 0 deletions test/test_compress.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* test_compress.h -- MinUnit test cases for compress.c
Copyright (C) 2017 Jakob Kreuze, All Rights Reserved.
This file is part of Nekopack.
Nekopack is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
Nekopack is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with Nekopack. If not, see <http://www.gnu.org/licenses/>. */

#pragma once

char *test_compress(void);
char *test_decompress(void);
Loading

0 comments on commit cfd5fb6

Please sign in to comment.