aboutsummaryrefslogtreecommitdiff
path: root/src/pack.c
diff options
context:
space:
mode:
authorDavid Timber <mieabby@gmail.com>2020-01-01 09:50:34 +1100
committerDavid Timber <mieabby@gmail.com>2020-01-01 09:50:34 +1100
commited809a51fdd1c313cd256301ef6f7211e8394cb1 (patch)
tree81a3054ce0d42976f80c973e2b6ebf9c1b8b7476 /src/pack.c
parent6e456edb2757cf9d28d306afb836aa16780fb912 (diff)
checkpoint
Diffstat (limited to 'src/pack.c')
-rw-r--r--src/pack.c240
1 files changed, 240 insertions, 0 deletions
diff --git a/src/pack.c b/src/pack.c
new file mode 100644
index 0000000..e83d433
--- /dev/null
+++ b/src/pack.c
@@ -0,0 +1,240 @@
+#include "pack.h"
+#include "util.h"
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <zlib.h>
+
+
+void prne_init_bin_archive (prne_bin_archive_t *a) {
+ a->data_size = 0;
+ a->data = NULL;
+ a->nb_binaries = 0;
+ a->arch_arr = NULL;
+ a->offset_arr = NULL;
+ a->size_arr = NULL;
+}
+
+void prne_init_unpack_bin_archive_result (prne_unpack_bin_archive_result_t *r) {
+ r->data_size = 0;
+ r->data = NULL;
+ r->result = PRNE_UNPACK_BIN_ARCHIVE_OK;
+ r->err = 0;
+}
+
+prne_unpack_bin_archive_result_t prne_unpack_bin_archive (const int fd) {
+ static const size_t fd_buf_size = 77, bio_buf_size = 58, z_buf_size = 4096;
+
+ prne_unpack_bin_archive_result_t ret;
+ BIO *b64_bio = NULL, *mem_bio = NULL;
+ uint8_t *mem = NULL, *fd_buf = NULL, *bio_buf = NULL, *z_buf = NULL;
+ int fd_read_size, fd_data_size, bio_write_size, bio_read_size;
+ int z_func_ret;
+ z_stream stream;
+ size_t z_out_size;
+ void *ny_buf;
+ bool stream_end;
+
+ prne_init_unpack_bin_archive_result(&ret);
+ memset(&stream, 0, sizeof(z_stream));
+
+ mem = (uint8_t*)malloc(fd_buf_size + bio_buf_size + z_buf_size);
+ if (mem == NULL) {
+ ret.result = PRNE_UNPACK_BIN_ARCHIVE_MEM_ERR;
+ ret.err = errno;
+ goto END;
+ }
+ fd_buf = mem;
+ bio_buf = mem + fd_buf_size;
+ z_buf = mem + fd_buf_size + bio_buf_size;
+
+ z_func_ret = inflateInit(&stream);
+ if (z_func_ret != Z_OK) {
+ ret.result = PRNE_UNPACK_BIN_ARCHIVE_Z_ERR;
+ ret.err = z_func_ret;
+ goto END;
+ }
+
+ if ((mem_bio = BIO_new(BIO_s_mem())) == NULL || (b64_bio = BIO_new(BIO_f_base64())) == NULL) {
+ ret.result = PRNE_UNPACK_BIN_ARCHIVE_OPENSSL_ERR;
+ ret.err = ERR_get_error();
+ goto END;
+ }
+ BIO_set_flags(b64_bio, BIO_FLAGS_BASE64_NO_NL);
+ BIO_push(b64_bio, mem_bio);
+
+ stream_end = false;
+ do {
+ fd_read_size = read(fd, fd_buf, fd_buf_size);
+ if (fd_read_size < 0) {
+ ret.result = PRNE_UNPACK_BIN_ARCHIVE_ERRNO;
+ ret.err = errno;
+ goto END;
+ }
+ if (fd_read_size == 0) {
+ break;
+ }
+
+ // remove white spaces
+ fd_data_size = prne_str_shift_spaces((char*)fd_buf, (size_t)fd_read_size);
+
+ if (fd_data_size > 0) {
+ BIO_reset(mem_bio);
+ bio_write_size = BIO_write(mem_bio, fd_buf, fd_data_size);
+ if (bio_write_size != fd_data_size) {
+ ret.result = PRNE_UNPACK_BIN_ARCHIVE_MEM_ERR;
+ goto END;
+ }
+
+ bio_read_size = BIO_read(b64_bio, bio_buf, (int)bio_buf_size);
+ if (bio_read_size < 0) {
+ ret.result = PRNE_UNPACK_BIN_ARCHIVE_OPENSSL_ERR;
+ ret.err = ERR_get_error();
+ goto END;
+ }
+
+ if (bio_read_size > 0) {
+ stream.avail_in = bio_read_size;
+ stream.next_in = bio_buf;
+ do {
+ stream.avail_out = z_buf_size;
+ stream.next_out = z_buf;
+ z_func_ret = inflate(&stream, Z_NO_FLUSH);
+ switch (z_func_ret) {
+ case Z_STREAM_END:
+ stream_end = true;
+ break;
+ case Z_OK:
+ case Z_BUF_ERROR:
+ break;
+ default:
+ ret.result = PRNE_UNPACK_BIN_ARCHIVE_Z_ERR;
+ ret.err = z_func_ret;
+ goto END;
+ }
+
+ z_out_size = z_buf_size - stream.avail_out;
+ if (z_out_size > 0) {
+ ny_buf = realloc(ret.data, ret.data_size + z_out_size);
+ if (ny_buf == NULL) {
+ ret.result = PRNE_UNPACK_BIN_ARCHIVE_MEM_ERR;
+ ret.err = errno;
+ break;
+ }
+ ret.data = (uint8_t*)ny_buf;
+
+ memcpy(ret.data + ret.data_size, z_buf, z_out_size);
+ ret.data_size += z_out_size;
+ }
+ } while (stream.avail_out == 0);
+ }
+ }
+ } while (!stream_end);
+
+END:
+ free(mem);
+ if (ret.result != PRNE_UNPACK_BIN_ARCHIVE_OK) {
+ free(ret.data);
+ ret.data = NULL;
+ ret.data_size = 0;
+ }
+ inflateEnd(&stream);
+ BIO_free(b64_bio);
+ BIO_free(mem_bio);
+
+ return ret;
+}
+
+prne_index_bin_archive_result_code_t prne_index_bin_archive (prne_unpack_bin_archive_result_t *in, prne_bin_archive_t *out) {
+ prne_index_bin_archive_result_code_t ret = PRNE_INDEX_BIN_ARCHIVE_OK;
+ size_t buf_pos = 0, arr_cnt = 0, offset_arr[NB_PRNE_ARCH], size_arr[NB_PRNE_ARCH];
+ prne_arch_t arch;
+ uint32_t bin_size;
+ prne_arch_t arch_arr[NB_PRNE_ARCH];
+ prne_bin_archive_t archive;
+ uint8_t *out_buf;
+
+ memset(arch_arr, 0, sizeof(prne_arch_t) * NB_PRNE_ARCH);
+ memset(offset_arr, 0, sizeof(size_t) * NB_PRNE_ARCH);
+ memset(size_arr, 0, sizeof(size_t) * NB_PRNE_ARCH);
+ prne_init_bin_archive(&archive);
+
+ do {
+ if (buf_pos + 4 >= in->data_size || arr_cnt >= NB_PRNE_ARCH) {
+ ret = PRNE_INDEX_BIN_ARCHIVE_FMT_ERR;
+ goto END;
+ }
+
+ arch = (prne_arch_t)in->data[buf_pos];
+ bin_size =
+ ((uint32_t)in->data[buf_pos + 1] << 16) |
+ ((uint32_t)in->data[buf_pos + 2] << 8) |
+ (uint32_t)in->data[buf_pos + 3];
+ if (prne_arch2str(arch) == NULL || bin_size == 0 || buf_pos + 4 + bin_size > in->data_size) {
+ ret = PRNE_INDEX_BIN_ARCHIVE_FMT_ERR;
+ goto END;
+ }
+
+ arch_arr[arr_cnt] = arch;
+ offset_arr[arr_cnt] = 4 + buf_pos;
+ size_arr[arr_cnt] = bin_size;
+ arr_cnt += 1;
+
+ buf_pos += 4 + bin_size;
+ } while (buf_pos < in->data_size);
+
+ out_buf = (uint8_t*)malloc(sizeof(prne_arch_t) * arr_cnt + sizeof(size_t*) * arr_cnt + sizeof(size_t*) * arr_cnt);
+ if (out_buf == NULL) {
+ ret = PRNE_INDEX_BIN_ARCHIVE_MEM_ERR;
+ goto END;
+ }
+ archive.arch_arr = (prne_arch_t*)out_buf;
+ archive.offset_arr = (size_t*)(out_buf + sizeof(prne_arch_t) * arr_cnt);
+ archive.size_arr = (size_t*)(out_buf + sizeof(prne_arch_t) * arr_cnt + sizeof(size_t*) * arr_cnt);
+
+ archive.data_size = in->data_size;
+ archive.data = in->data;
+ archive.nb_binaries = arr_cnt;
+ memcpy(archive.arch_arr, arch_arr, arr_cnt * sizeof(prne_arch_t));
+ memcpy(archive.offset_arr, offset_arr, arr_cnt * sizeof(size_t));
+ memcpy(archive.size_arr, size_arr, arr_cnt * sizeof(size_t));
+
+ in->data = NULL;
+ in->data_size = 0;
+ *out = archive;
+
+END:
+ if (ret != PRNE_INDEX_BIN_ARCHIVE_OK) {
+ prne_free_bin_archive(&archive);
+ }
+
+ return ret;
+}
+
+void prne_free_unpack_bin_archive_result (prne_unpack_bin_archive_result_t *r) {
+ free(r->data);
+ r->data = NULL;
+ r->data_size = 0;
+ r->result = PRNE_INDEX_BIN_ARCHIVE_OK;
+ r->err = 0;
+}
+
+void prne_free_bin_archive (prne_bin_archive_t *a) {
+ free(a->data);
+ free(a->arch_arr);
+ a->nb_binaries = 0;
+ a->data_size = 0;
+ a->arch_arr = NULL;
+ a->offset_arr = NULL;
+ a->size_arr = NULL;
+}