Skip to content

Commit

Permalink
Support multiple gzips in one gzip file.
Browse files Browse the repository at this point in the history
BeebEm seems to emit UEF files that are multiple concatenated
gzip files.
  • Loading branch information
scarybeasts committed Jun 20, 2022
1 parent ac0ac27 commit 458d5f5
Showing 1 changed file with 53 additions and 9 deletions.
62 changes: 53 additions & 9 deletions util_compress.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,19 @@

#include <string.h>

int
util_gunzip(size_t* p_dst_len, uint8_t* p_src, size_t src_len, uint8_t* p_dst) {
static int
util_gunzip_chunk(size_t* p_dst_len,
size_t* p_src_consumed,
uint8_t* p_src,
size_t src_len,
uint8_t* p_dst) {
z_stream stream;
int status;
uint8_t flags;
size_t dst_len = *p_dst_len;
size_t src_left = src_len;

if (src_len < 10) {
if (src_left < 10) {
return -100;
}
if ((p_src[0] != 0x1F) || (p_src[1] != 0x8B)) {
Expand All @@ -32,23 +37,23 @@ util_gunzip(size_t* p_dst_len, uint8_t* p_src, size_t src_len, uint8_t* p_dst) {

/* Skip header. */
p_src += 10;
src_len -= 10;
src_left -= 10;

/* Skip filename if any. */
if (flags & 0x08) {
while ((src_len > 0) && (*p_src != '\0')) {
while ((src_left > 0) && (*p_src != '\0')) {
p_src++;
src_len--;
src_left--;
}
if (src_len > 0) {
if (src_left > 0) {
p_src++;
src_len--;
src_left--;
}
}

(void) memset(&stream, '\0', sizeof(stream));
stream.next_in = p_src;
stream.avail_in = src_len;
stream.avail_in = src_left;
stream.next_out = p_dst;
stream.avail_out = dst_len;

Expand All @@ -63,6 +68,8 @@ util_gunzip(size_t* p_dst_len, uint8_t* p_src, size_t src_len, uint8_t* p_dst) {
}

*p_dst_len = (dst_len - stream.avail_out);
src_left -= stream.total_in;
*p_src_consumed = (src_len - src_left);

if (inflateEnd(&stream) != Z_OK) {
return -3;
Expand All @@ -71,6 +78,43 @@ util_gunzip(size_t* p_dst_len, uint8_t* p_src, size_t src_len, uint8_t* p_dst) {
return 0;
}

int
util_gunzip(size_t* p_dst_len, uint8_t* p_src, size_t src_len, uint8_t* p_dst) {
size_t src_left = src_len;
size_t dst_left = *p_dst_len;
size_t dst_written = 0;
int ret;

while (1) {
size_t src_consumed = 0;
size_t dst_len = dst_left;
ret = util_gunzip_chunk(&dst_len, &src_consumed, p_src, src_left, p_dst);
if (ret != 0) {
break;
}

dst_written += dst_len;
dst_left -= dst_len;
p_dst += dst_len;
src_left -= src_consumed;
p_src += src_consumed;

/* Go again if there are more gzip headers in the expected place. BeebEm
* seems to emit UEF files that are multiple concatenated gzip files.
*/
if ((src_left > 10) && (p_src[8] == 0x1f) && (p_src[9] == 0x8b)) {
src_left -= 8;
p_src += 8;
/* Go again. */
} else {
break;
}
}

*p_dst_len = dst_written;
return ret;
}

int
util_uncompress(size_t* p_dst_len,
uint8_t* p_src,
Expand Down

0 comments on commit 458d5f5

Please sign in to comment.