Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for LZMA legacy images #37

Merged
merged 2 commits into from
Jun 28, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 72 additions & 5 deletions decompress.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "decompress.h"

#include "squashfs_fs.h"
#include "swap.h"

#include <string.h>

Expand Down Expand Up @@ -65,6 +66,66 @@ static sqfs_err sqfs_decompressor_xz(void *in, size_t insz,
return SQFS_OK;
}
#define CAN_DECOMPRESS_XZ 1

// The following implementation was adapted from squashfs-tools
// https://github.com/plougher/squashfs-tools.git

#define LZMA_PROPS_SIZE 5
#define LZMA_UNCOMP_SIZE 8
#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + LZMA_UNCOMP_SIZE)
#define MEMLIMIT (32 * 1024 * 1024)

static sqfs_err sqfs_decompressor_lzma(void *in, size_t insz,
void *out, size_t *outsz) {

lzma_stream strm = LZMA_STREAM_INIT;
uint32_t uncompressed_size = 0, res;
unsigned char lzma_header[LZMA_HEADER_SIZE];

res = lzma_alone_decoder(&strm, MEMLIMIT);
if (res != LZMA_OK) {
lzma_end(&strm);
return SQFS_ERR;
}

memcpy(lzma_header, in, LZMA_HEADER_SIZE);
uncompressed_size = *((uint32_t*)(lzma_header + LZMA_PROPS_SIZE));
sqfs_swapin32(&uncompressed_size);

if (uncompressed_size > *outsz) {
lzma_end(&strm);
return SQFS_ERR;
}

memset(lzma_header + LZMA_PROPS_SIZE, 255, LZMA_UNCOMP_SIZE);

strm.next_out = out;
strm.avail_out = *outsz;
strm.next_in = lzma_header;
strm.avail_in = LZMA_HEADER_SIZE;

res = lzma_code(&strm, LZMA_RUN);

if (res != LZMA_OK || strm.avail_in != 0) {
lzma_end(&strm);
return SQFS_ERR;
}

strm.next_in = (uint8_t *)in + LZMA_HEADER_SIZE;
strm.avail_in = insz - LZMA_HEADER_SIZE;

res = lzma_code(&strm, LZMA_FINISH);
lzma_end(&strm);

if (res == LZMA_STREAM_END || (res == LZMA_OK &&
strm.total_out >= uncompressed_size && strm.avail_in == 0)) {
*outsz = uncompressed_size;
return SQFS_OK;
}

return SQFS_ERR;
}
#define CAN_DECOMPRESS_LZMA 1
#endif


Expand Down Expand Up @@ -116,12 +177,15 @@ sqfs_decompressor sqfs_decompressor_get(sqfs_compression_type type) {
#ifdef CAN_DECOMPRESS_ZLIB
case ZLIB_COMPRESSION: return &sqfs_decompressor_zlib;
#endif
#ifdef CAN_DECOMPRESS_XZ
case XZ_COMPRESSION: return &sqfs_decompressor_xz;
#ifdef CAN_DECOMPRESS_LZMA
case LZMA_COMPRESSION: return &sqfs_decompressor_lzma;
#endif
#ifdef CAN_DECOMPRESS_LZO
case LZO_COMPRESSION: return &sqfs_decompressor_lzo;
#endif
#ifdef CAN_DECOMPRESS_XZ
case XZ_COMPRESSION: return &sqfs_decompressor_xz;
#endif
#ifdef CAN_DECOMPRESS_LZ4
case LZ4_COMPRESSION: return &sqfs_decompressor_lz4;
#endif
Expand All @@ -145,15 +209,18 @@ char *sqfs_compression_name(sqfs_compression_type type) {
void sqfs_compression_supported(sqfs_compression_type *types) {
size_t i = 0;
memset(types, SQFS_COMP_UNKNOWN, SQFS_COMP_MAX * sizeof(*types));
#ifdef CAN_DECOMPRESS_ZLIB
types[i++] = ZLIB_COMPRESSION;
#endif
#ifdef CAN_DECOMPRESS_LZMA
types[i++] = LZMA_COMPRESSION;
#endif
#ifdef CAN_DECOMPRESS_LZO
types[i++] = LZO_COMPRESSION;
#endif
#ifdef CAN_DECOMPRESS_XZ
types[i++] = XZ_COMPRESSION;
#endif
#ifdef CAN_DECOMPRESS_ZLIB
types[i++] = ZLIB_COMPRESSION;
#endif
#ifdef CAN_DECOMPRESS_LZ4
types[i++] = LZ4_COMPRESSION;
#endif
Expand Down