ssn-installer/src/inflate.c

110 lines
3.4 KiB
C
Raw Normal View History

2018-07-31 13:18:18 +02:00
//Based on https://github.com/richgel999/miniz/blob/master/examples/example5.c (Public domain, April 11 2012, Rich Geldreich, richgel99@gmail.com)
#include <stdbool.h>
#include <stdio.h>
//Include miniz, disabling what we don't need
#define MINIZ_NO_STDIO
#define MINIZ_NO_ARCHIVE_APIS
#define MINIZ_NO_TIME
#define MINIZ_NO_ZLIB_APIS
#define MINIZ_NO_MALLOC
#include "../lib/miniz/miniz.h"
2018-09-14 01:41:35 +02:00
#include "errorAndExit.h"
2018-07-31 13:18:18 +02:00
#include "inflate.h"
//The compressed and uncompressed buffer arrays
static const uint8_t* comprBuffer;
static uint8_t* uncomprBuffer;
2018-07-31 13:18:18 +02:00
//Position of the inflater in the buffer arrays
static const uint8_t* comprBufferNext;
static uint8_t* uncomprBufferNext;
2018-07-31 13:18:18 +02:00
//Buffer lengths
static unsigned long uncomprBufferSize;
static size_t remainingInput;
static size_t spaceInOutput;
2018-07-31 13:18:18 +02:00
//Internal variables used by miniz
static tinfl_decompressor decompressor;
2018-09-14 02:34:32 +02:00
static tinfl_status status;
static size_t in_bytes, out_bytes;
2018-07-31 13:18:18 +02:00
void inflateInit(uint8_t* comprBufferIn, uint8_t* uncomprBufferIn, unsigned long uncomprBufferSizeIn) {
2018-07-31 13:18:18 +02:00
comprBuffer = comprBufferIn;
uncomprBuffer = uncomprBufferIn;
uncomprBufferSize = uncomprBufferSizeIn;
tinfl_init(&decompressor);
2018-07-31 13:18:18 +02:00
}
struct InflateOutput inflateInflate(unsigned long numInputBytes, bool hasMoreBytes) {
if (numInputBytes == 0) {
//continue in input buffer where we were before
} else {
//go back to beginning of input buffer
comprBufferNext = comprBuffer;
2018-07-31 13:18:18 +02:00
remainingInput = numInputBytes;
}
//output buffer was previously fully filled and all output was processed. New uncompressed data can be written starting at offset 0
2018-08-09 16:20:21 +02:00
if (spaceInOutput == 0) {
uncomprBufferNext = (mz_uint8 *)uncomprBuffer;
spaceInOutput = uncomprBufferSize;
}
2018-07-31 13:18:18 +02:00
struct InflateOutput out;
out.hasReachedEnd = false;
2018-08-09 16:20:21 +02:00
out.numBytesWrittenToOutput = 0UL;
2018-07-31 13:18:18 +02:00
while (remainingInput > 0 && spaceInOutput > 0) {
in_bytes = remainingInput;
out_bytes = spaceInOutput;
//Call decompression
status = tinfl_decompress(
&decompressor,
2018-07-31 13:18:18 +02:00
(const mz_uint8 *)comprBufferNext,
&in_bytes,
(mz_uint8 *)uncomprBuffer,
2018-07-31 13:18:18 +02:00
(mz_uint8 *)uncomprBufferNext,
&out_bytes,
(hasMoreBytes ? TINFL_FLAG_HAS_MORE_INPUT : 0)
);
//Adjust buffer positions by the amount of bytes processed
comprBufferNext = (const uint8_t *)(comprBufferNext + in_bytes);
2018-07-31 13:18:18 +02:00
remainingInput -= in_bytes;
uncomprBufferNext = (uint8_t *)(uncomprBufferNext + out_bytes);
2018-07-31 13:18:18 +02:00
spaceInOutput -= out_bytes;
2018-08-09 16:20:21 +02:00
out.numBytesWrittenToOutput += out_bytes;
2018-07-31 13:18:18 +02:00
//Check for errors
if (status <= TINFL_STATUS_DONE) {
if (status == TINFL_STATUS_DONE) {
// Decompression completed successfully.
out.hasReachedEnd = true;
2018-07-31 13:18:18 +02:00
break;
} else {
// Decompression failed.
fprintf(stderr, "tinfl_decompress() failed with status %i!\n", status);
2018-09-14 01:41:35 +02:00
errorAndExit();
2018-07-31 13:18:18 +02:00
}
}
if (status == TINFL_STATUS_NEEDS_MORE_INPUT && remainingInput != 0) {
fprintf(stderr, "Received status NEEDS_MORE_INPUT, with remaining input %lu and space in output %lu.\n", remainingInput, spaceInOutput);
}
if (status == TINFL_STATUS_HAS_MORE_OUTPUT && spaceInOutput != 0) {
fprintf(stderr, "Received status HAS_MORE_OUTPUT, with remaining input %lu and space in output %lu.\n", remainingInput, spaceInOutput);
}
2018-07-31 13:18:18 +02:00
}
//Return output
if (remainingInput == 0) {
out.needMoreInput = hasMoreBytes;
} else {
out.needMoreInput = false;
2018-07-31 13:18:18 +02:00
}
return out;
}