[RFC PATCH v0 4/4] erofs-utils: fuse: add LZMA algorithm support

Gao Xiang hsiangkao at aol.com
Mon Jan 18 04:46:03 AEDT 2021


From: Gao Xiang <hsiangkao at aol.com>

This patch adds LZMA compression algorithms to erofsfuse to test
if LZMA fixed-sized output algorithm works as expected.

Cc: Lasse Collin <lasse.collin at tukaani.org>
Signed-off-by: Gao Xiang <hsiangkao at aol.com>
---
 lib/data.c       |  7 +++---
 lib/decompress.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 66 insertions(+), 3 deletions(-)

diff --git a/lib/data.c b/lib/data.c
index 3781846743aa..4247dd3a33aa 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -146,9 +146,10 @@ static int z_erofs_read_data(struct erofs_inode *inode, char *buffer,
 		if (ret < 0)
 			return -EIO;
 
-		algorithmformat = map.m_flags & EROFS_MAP_ZIPPED ?
-						Z_EROFS_COMPRESSION_LZ4 :
-						Z_EROFS_COMPRESSION_SHIFTED;
+		if (map.m_flags & EROFS_MAP_ZIPPED)
+			algorithmformat = inode->z_algorithmtype[0];
+		else
+			algorithmformat = Z_EROFS_COMPRESSION_SHIFTED;
 
 		/*
 		 * trim to the needed size if the returned extent is quite
diff --git a/lib/decompress.c b/lib/decompress.c
index 490c4bc771da..fd9f24bcbeb6 100644
--- a/lib/decompress.c
+++ b/lib/decompress.c
@@ -10,6 +10,66 @@
 #include "erofs/decompress.h"
 #include "erofs/err.h"
 
+#include <lzma.h>
+
+/* FIXME! need to record it into superblock */
+#define DICT_SIZE	(64U << 10)
+
+static int z_erofs_decompress_lzma(struct z_erofs_decompress_req *rq)
+{
+	int ret = 0;
+	u8 *dest = (u8 *)rq->out;
+	u8 *src = (u8 *)rq->in;
+	u8 *buff = NULL;
+	unsigned int inputmargin = 0;
+	lzma_stream strm;
+	lzma_ret ret2;
+
+	if (!erofs_sb_has_lz4_0padding())
+		return -EFSCORRUPTED;
+
+	while (!src[inputmargin & ~PAGE_MASK])
+		if (!(++inputmargin & ~PAGE_MASK))
+			break;
+
+	if (inputmargin >= rq->inputsize)
+		return -EFSCORRUPTED;
+
+	if (rq->decodedskip) {
+		buff = malloc(rq->decodedlength);
+		if (!buff)
+			return -ENOMEM;
+		dest = buff;
+	}
+
+	strm = (lzma_stream)LZMA_STREAM_INIT;
+	strm.next_in = src + inputmargin;
+	strm.avail_in = rq->inputsize - inputmargin;
+	strm.next_out = dest;
+	strm.avail_out = rq->decodedlength;
+
+	ret2 = lzma_erofs_decoder(&strm, strm.avail_in, rq->decodedlength,
+				  !rq->partial_decoding, DICT_SIZE);
+	if (ret2 != LZMA_OK) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	ret2 = lzma_code(&strm, LZMA_FINISH);
+	if (ret2 != LZMA_STREAM_END) {
+		ret = -EFSCORRUPTED;
+		goto out;
+	}
+
+	if (rq->decodedskip)
+		memcpy(rq->out, dest + rq->decodedskip,
+		       rq->decodedlength - rq->decodedskip);
+out:
+	if (buff)
+		free(buff);
+	return ret;
+}
+
 #ifdef LZ4_ENABLED
 #include <lz4.h>
 
@@ -84,5 +144,7 @@ int z_erofs_decompress(struct z_erofs_decompress_req *rq)
 	if (rq->alg == Z_EROFS_COMPRESSION_LZ4)
 		return z_erofs_decompress_lz4(rq);
 #endif
+	if (rq->alg == Z_EROFS_COMPRESSION_LZMA)
+		return z_erofs_decompress_lzma(rq);
 	return -EOPNOTSUPP;
 }
-- 
2.24.0



More information about the Linux-erofs mailing list