aboutsummaryrefslogtreecommitdiff
path: root/src/pack.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pack.c')
-rw-r--r--src/pack.c430
1 files changed, 254 insertions, 176 deletions
diff --git a/src/pack.c b/src/pack.c
index 59816eb..96ca4d8 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -5,224 +5,302 @@
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
#include <errno.h>
#include <zlib.h>
-#include <mbedtls/base64.h>
+#include <mbedtls/error.h>
+
+
+struct prne_unpack_ctx {
+ size_t end;
+ z_stream zs;
+};
+
+static int bin_tpl_comp_func (const void *a, const void *b) {
+ return ((const prne_bin_tuple_t*)a)->arch < ((const prne_bin_tuple_t*)b)->arch ? -1 : ((const prne_bin_tuple_t*)a)->arch > ((const prne_bin_tuple_t*)b)->arch ? 1 : 0;
+}
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;
+ a->nb_bin = 0;
+ a->bin = 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;
+void prne_free_bin_archive (prne_bin_archive_t *a) {
+ prne_free(a->data);
+ prne_free(a->bin);
+ a->data_size = 0;
+ a->data = NULL;
+ a->nb_bin = 0;
+ a->bin = NULL;
}
-prne_unpack_bin_archive_result_t prne_unpack_bin_archive (const int fd) {
- static const size_t fd_buf_size = 77, b64_buf_size = 58, z_buf_size = 1024;
-
- prne_unpack_bin_archive_result_t ret;
- uint8_t *mem = NULL, *fd_buf = NULL, *b64_buf = NULL, *z_buf = NULL;
- int fd_read_size, fd_data_size, rem_size = 0;
- int z_func_ret;
- z_stream stream;
- size_t dec_b64_size, z_out_size;
- void *ny_buf;
- bool stream_end;
-
- prne_init_unpack_bin_archive_result(&ret);
- memzero(&stream, sizeof(z_stream));
-
- mem = (uint8_t*)prne_malloc(1, fd_buf_size + b64_buf_size + z_buf_size);
- if (mem == NULL) {
- ret.result = PRNE_UNPACK_BIN_ARCHIVE_MEM_ERR;
+prne_pack_ret_t prne_index_bin_archive (void *rf_ctx, prne_bin_archive_read_ft rf, prne_bin_archive_t *out) {
+ prne_pack_ret_t ret;
+ uint8_t *data = NULL;
+ prne_bin_tuple_t *bin = NULL;
+ size_t i, r_len, pos = 0, data_size = 0, nb_bin = 0;
+ uint8_t head[4];
+ void *ny_mem;
+ const size_t pagesize = prne_getpagesize();
+
+ r_len = 0;
+ ret = rf(rf_ctx, 1, head, &r_len);
+ if (ret.rc != PRNE_PACK_RC_OK) {
+ goto ERR;
+ }
+ if (r_len != 1) {
+ ret.rc = PRNE_PACK_RC_FMT_ERR;
+ goto ERR;
+ }
+
+ nb_bin = head[0];
+ bin = (prne_bin_tuple_t*)prne_malloc(sizeof(prne_bin_tuple_t), nb_bin);
+ if (bin == NULL) {
+ ret.rc = PRNE_PACK_RC_ERRNO;
ret.err = errno;
- goto END;
+ goto ERR;
}
- fd_buf = mem;
- b64_buf = mem + fd_buf_size;
- z_buf = mem + fd_buf_size + b64_buf_size;
+ for (i = 0; i < nb_bin; i += 1) {
+ r_len = 0;
+ ret = rf(rf_ctx, 4, head, &r_len);
+ if (ret.rc != PRNE_PACK_RC_OK) {
+ goto ERR;
+ }
+ if (r_len != 4) {
+ ret.rc = PRNE_PACK_RC_FMT_ERR;
+ goto ERR;
+ }
- 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;
+ bin[i].arch = (prne_arch_t)head[0];
+ bin[i].offset = pos;
+ pos += bin[i].size = ((size_t)head[1] << 16) | ((size_t)head[2] << 8) | ((size_t)head[3]);
}
- stream_end = false;
+ pos = 0;
do {
- fd_read_size = read(fd, fd_buf + rem_size, fd_buf_size - rem_size);
- if (fd_read_size < 0) {
- ret.result = PRNE_UNPACK_BIN_ARCHIVE_ERRNO;
+ ny_mem = prne_realloc(data, 1, pos + pagesize);
+ if (ny_mem == NULL) {
+ ret.rc = PRNE_PACK_RC_ERRNO;
ret.err = errno;
- goto END;
- }
- if (fd_read_size == 0) {
- break;
+ goto ERR;
}
- fd_read_size += rem_size;
-
- fd_read_size = fd_data_size = prne_str_shift_spaces((char*)fd_buf, (size_t)fd_read_size);
- fd_data_size = fd_data_size / 4 * 4;
- rem_size = fd_read_size - fd_data_size;
-
- if (fd_data_size > 0) {
- ret.err = mbedtls_base64_decode(b64_buf, b64_buf_size, &dec_b64_size, fd_buf, fd_data_size);
- if (ret.err != 0) {
- ret.result = PRNE_UNPACK_BIN_ARCHIVE_CRYPTO_ERR;
- }
-
- if (dec_b64_size > 0) {
- stream.avail_in = dec_b64_size;
- stream.next_in = b64_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 = prne_realloc(ret.data, 1, 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);
- }
+ data = (uint8_t*)ny_mem;
+
+ ret = rf(rf_ctx, pagesize, data + pos, &r_len);
+ if (ret.rc != PRNE_PACK_RC_OK) {
+ goto ERR;
}
+ data_size += r_len;
+ pos += pagesize;
+ } while (r_len == pagesize);
+ ny_mem = prne_realloc(data, 1, data_size);
+ if (ny_mem == NULL) {
+ ret.rc = PRNE_PACK_RC_ERRNO;
+ ret.err = errno;
+ goto ERR;
+ }
+ data = (uint8_t*)ny_mem;
+
+ qsort(bin, nb_bin, sizeof(prne_bin_tuple_t), bin_tpl_comp_func);
+ out->data = data;
+ out->data_size = data_size;
+ out->nb_bin = nb_bin;
+ out->bin = bin;
+
+ return ret;
+ERR:
+ prne_free(bin);
+ prne_free(data);
+
+ return ret;
+}
- memmove(fd_buf, fd_buf + fd_data_size, rem_size);
- } while (!stream_end);
+prne_unpack_ctx_pt prne_alloc_unpack_ctx (const prne_bin_archive_t *archive, const prne_arch_t arch, prne_pack_ret_t *pr_out) {
+ prne_bin_tuple_t main_tpl;
+ prne_bin_tuple_t *tpl;
+ prne_unpack_ctx_pt ret = NULL;
+ uint8_t buf[4096];
+ size_t i, cnt;
+ prne_pack_ret_t pr;
- if (ret.data_size == 0) {
- ret.result = PRNE_UNPACK_BIN_ARCHIVE_FMT_ERR;
+ pr.rc = PRNE_PACK_RC_OK;
+ pr.err = 0;
+
+ main_tpl.arch = arch;
+ tpl = (prne_bin_tuple_t*)bsearch(&main_tpl, archive->bin, archive->nb_bin, sizeof(prne_bin_tuple_t), bin_tpl_comp_func);
+ if (tpl == NULL) {
+ pr.rc = PRNE_PACK_RC_NO_BIN;
+ goto ERR;
}
+ main_tpl = *tpl;
-END:
- prne_free(mem);
- if (ret.result != PRNE_UNPACK_BIN_ARCHIVE_OK) {
- prne_free(ret.data);
- ret.data = NULL;
- ret.data_size = 0;
+ ret = (prne_unpack_ctx_pt)prne_malloc(sizeof(struct prne_unpack_ctx), 1);
+ if (ret == NULL) {
+ pr.rc = PRNE_PACK_RC_ERRNO;
+ pr.err = errno;
+ goto ERR;
+ }
+ memzero(&ret->zs, sizeof(ret->zs));
+ if (Z_OK != (pr.err = inflateInit(&ret->zs))) {
+ prne_free(ret);
+ ret = NULL;
+
+ pr.rc = PRNE_PACK_RC_Z_ERR;
+ goto ERR;
}
- inflateEnd(&stream);
+ ret->zs.avail_in = archive->data_size;
+ ret->zs.next_in = archive->data;
+ cnt = main_tpl.offset / sizeof(buf);
+ for (i = 0; i < cnt; i += 1) {
+ ret->zs.avail_out = sizeof(buf);
+ ret->zs.next_out = buf;
+ switch (inflate(&ret->zs, Z_SYNC_FLUSH)) {
+ case Z_OK:
+ case Z_BUF_ERROR:
+ break;
+ default:
+ pr.rc = PRNE_PACK_RC_FMT_ERR;
+ goto ERR;
+ }
+ if (ret->zs.avail_out != 0) {
+ pr.rc = PRNE_PACK_RC_FMT_ERR;
+ goto ERR;
+ }
+ }
+
+ ret->zs.avail_out = main_tpl.offset - cnt * sizeof(buf);
+ ret->zs.next_out = buf;
+ switch (inflate(&ret->zs, Z_SYNC_FLUSH)) {
+ case Z_OK:
+ case Z_BUF_ERROR:
+ break;
+ default:
+ pr.rc = PRNE_PACK_RC_FMT_ERR;
+ goto ERR;
+ }
+ if (ret->zs.total_out != main_tpl.offset) {
+ pr.rc = PRNE_PACK_RC_FMT_ERR;
+ goto ERR;
+ }
+
+ ret->end = main_tpl.offset + main_tpl.size;
+ if (pr_out != NULL) {
+ *pr_out = pr;
+ }
return ret;
+ERR:
+ if (ret != NULL) {
+ inflateEnd(&ret->zs);
+ prne_free(ret);
+ }
+ if (pr_out != NULL) {
+ *pr_out = pr;
+ }
+
+ return NULL;
}
-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;
- uint_fast32_t bin_size;
- prne_arch_t arch_arr[NB_PRNE_ARCH];
- prne_bin_archive_t archive;
-
- memzero(arch_arr, sizeof(prne_arch_t) * NB_PRNE_ARCH);
- memzero(offset_arr, sizeof(size_t) * NB_PRNE_ARCH);
- memzero(size_arr, sizeof(size_t) * NB_PRNE_ARCH);
- prne_init_bin_archive(&archive);
+void prne_free_unpack_ctx (prne_unpack_ctx_pt ctx) {
+ if (ctx != NULL) {
+ inflateEnd(&ctx->zs);
+ prne_free(ctx);
+ }
+}
- do {
- if (buf_pos + 4 >= in->data_size || arr_cnt >= NB_PRNE_ARCH) {
- ret = PRNE_INDEX_BIN_ARCHIVE_FMT_ERR;
- goto END;
- }
+ssize_t prne_do_unpack (prne_unpack_ctx_pt ctx, uint8_t *out, const size_t out_len, prne_pack_ret_t *pr_out) {
+ const size_t rem = ctx->end - ctx->zs.total_out;
+ const size_t req = prne_op_min(rem, out_len);
+ prne_pack_ret_t pr;
- arch = (prne_arch_t)in->data[buf_pos];
- bin_size =
- ((uint_fast32_t)in->data[buf_pos + 1] << 16) |
- ((uint_fast32_t)in->data[buf_pos + 2] << 8) |
- (uint_fast32_t)in->data[buf_pos + 3];
- if (prne_arch_tostr(arch) == NULL || bin_size == 0 || buf_pos + 4 + bin_size > in->data_size) {
- ret = PRNE_INDEX_BIN_ARCHIVE_FMT_ERR;
- goto END;
- }
+ pr.rc = PRNE_PACK_RC_OK;
+ pr.err = 0;
- 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);
-
- archive.arch_arr = (prne_arch_t*)prne_malloc(sizeof(prne_arch_t), arr_cnt);
- archive.offset_arr = (size_t*)prne_malloc(sizeof(size_t), arr_cnt);
- archive.size_arr = (size_t*)prne_malloc(sizeof(size_t), arr_cnt);
- if (archive.arch_arr == NULL || archive.offset_arr == NULL || archive.size_arr == NULL) {
- ret = PRNE_INDEX_BIN_ARCHIVE_MEM_ERR;
- goto END;
+ if (req == 0) {
+ return 0;
}
- 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;
+ ctx->zs.next_out = out;
+ ctx->zs.avail_out = req;
+ switch ((pr.err = inflate(&ctx->zs, Z_SYNC_FLUSH))) {
+ case Z_OK:
+ case Z_STREAM_END:
+ case Z_BUF_ERROR:
+ pr.err = 0;
+ break;
+ default:
+ pr.rc = PRNE_PACK_RC_Z_ERR;
+ goto END;
+ }
+ if (ctx->zs.avail_out != 0) {
+ pr.rc = PRNE_PACK_RC_FMT_ERR;
+ goto END;
+ }
END:
- if (ret != PRNE_INDEX_BIN_ARCHIVE_OK) {
- prne_free_bin_archive(&archive);
+ if (pr_out != NULL) {
+ *pr_out = pr;
+ }
+ if (pr.rc != PRNE_PACK_RC_OK) {
+ return -1;
}
- return ret;
+ return req;
}
-void prne_free_unpack_bin_archive_result (prne_unpack_bin_archive_result_t *r) {
- prne_free(r->data);
- r->data = NULL;
- r->data_size = 0;
- r->result = PRNE_INDEX_BIN_ARCHIVE_OK;
- r->err = 0;
-}
+char *prne_pack_ret_tostr (const prne_pack_ret_t pr) {
+ const char *rc_str;
+ const char *err_str;
+ char *buf = NULL, err_buf[31];
+ size_t buf_size;
-void prne_free_bin_archive (prne_bin_archive_t *a) {
- prne_free(a->data);
- prne_free(a->arch_arr);
- prne_free(a->offset_arr);
- prne_free(a->size_arr);
- a->nb_binaries = 0;
- a->data = NULL;
- a->data_size = 0;
- a->arch_arr = NULL;
- a->offset_arr = NULL;
- a->size_arr = NULL;
+ switch (pr.rc) {
+ case PRNE_PACK_RC_OK: rc_str = "ok"; break;
+ case PRNE_PACK_RC_FMT_ERR: rc_str = "fmt err"; break;
+ case PRNE_PACK_RC_NO_BIN: rc_str = "no bin"; break;
+ default: rc_str = NULL;
+ }
+ if (rc_str != NULL) {
+ buf_size = strlen(rc_str) + 1;
+ buf = (char*)prne_malloc(1, buf_size);
+ if (buf != NULL) {
+ memcpy(buf, rc_str, buf_size);
+ }
+ return buf;
+ }
+
+ switch (pr.rc) {
+ case PRNE_PACK_RC_ERRNO:
+ rc_str = "errno";
+ err_str = strerror(pr.err);
+ break;
+ case PRNE_PACK_RC_Z_ERR:
+ rc_str = "zlib err";
+ err_str = zError(pr.err);
+ break;
+ case PRNE_PACK_RC_MBEDTLS_ERR:
+ rc_str = "mbedtls err";
+ mbedtls_strerror(pr.err, err_buf, sizeof(err_buf));
+ err_str = err_buf;
+ break;
+ default:
+ errno = EINVAL;
+ return NULL;
+ }
+
+ buf_size = strlen(rc_str) + 4 + 11 + 1 + strlen(err_str) + 1;
+ buf = (char*)prne_malloc(1, buf_size);
+ if (buf != NULL) {
+ if (sprintf(buf, "%s - (%d)%s", rc_str, pr.err, err_str) < 0) {
+ prne_free(buf);
+ return NULL;
+ }
+ }
+ return buf;
}