From: Gao Xiang <[email protected]>

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

Cc: Lasse Collin <[email protected]>
Signed-off-by: Gao Xiang <[email protected]>
---
 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

Reply via email to