From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
To: barebox@lists.infradead.org
Subject: [PATCH] lib/decompress_unlzo: use fill and full to read and write data
Date: Fri, 28 Jan 2011 11:13:24 +0100 [thread overview]
Message-ID: <1296209604-29790-1-git-send-email-plagnioj@jcrosoft.com> (raw)
this will all to simplify the sync with the kernel and later easly add the
self decompression support to barebox
as example with a lzo compression will reduce barebox from 180224 to 99863
bytes so 55.41%
-rwxr-xr-x 1 root root 99863 Jan 28 02:17 build/versatilepb/barebox.bin.lzo
we also reduce the binary size by 224 bytes
Old version
# ls -al build/versatilepb/barebox.bin
-rwxr-xr-x 1 root root 180468 Jan 28 02:14 build/versatilepb/barebox.bin
New version
# ls -al build/versatilepb/barebox*
-rwxr-xr-x 1 root root 180244 Jan 28 02:13 build/versatilepb/barebox.bin
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
lib/decompress_unlzo.c | 180 ++++++++++++++++++++++++-----------------------
1 files changed, 92 insertions(+), 88 deletions(-)
diff --git a/lib/decompress_unlzo.c b/lib/decompress_unlzo.c
index 8f9cdcf..fc5c49f 100644
--- a/lib/decompress_unlzo.c
+++ b/lib/decompress_unlzo.c
@@ -47,98 +47,73 @@ static const unsigned char lzop_magic[] = {
#define LZO_BLOCK_SIZE (256*1024l)
#define HEADER_HAS_FILTER 0x00000800L
-static inline int parse_header(int in_fd)
+static inline int parse_header(u8 *input, u8 *skip)
{
- u8 l;
+ int l;
+ u8 *parse = input;
+ u8 level = 0;
u16 version;
- int ret;
- unsigned char buf[256]; /* maximum filename length + 1 */
- /* read magic (9), library version (2), 'need to be extracted'
- * version (2) and method (1)
- */
- ret = read(in_fd, buf, 9);
- if (ret < 0)
- return ret;
-
- /* check magic */
+ /* read magic: 9 first bits */
for (l = 0; l < 9; l++) {
- if (buf[l] != lzop_magic[l])
- return -EINVAL;
+ if (*parse++ != lzop_magic[l])
+ return 0;
}
-
- ret = read(in_fd, buf, 4); /* version, lib_version */
- if (ret < 0)
- return ret;
- version = get_unaligned_be16(buf);
-
- if (version >= 0x0940) {
- ret = read(in_fd, buf, 2); /* version to extract */
- if (ret < 0)
- return ret;
- }
-
- ret = read(in_fd, buf, 1); /* method */
- if (ret < 0)
- return ret;
-
+ /* get version (2bytes), skip library version (2),
+ * 'need to be extracted' version (2) and
+ * method (1) */
+ version = get_unaligned_be16(parse);
+ parse += 7;
if (version >= 0x0940)
- read(in_fd, buf, 1); /* level */
-
- ret = read(in_fd, buf, 4); /* flags */
- if (ret < 0)
- return ret;
-
- if (get_unaligned_be32(buf) & HEADER_HAS_FILTER) {
- ret = read(in_fd, buf, 4); /* skip filter info */
- if (ret < 0)
- return ret;
- }
+ level = *parse++;
+ if (get_unaligned_be32(parse) & HEADER_HAS_FILTER)
+ parse += 8; /* flags + filter info */
+ else
+ parse += 4; /* flags */
/* skip mode and mtime_low */
- ret = read(in_fd, buf, 8);
- if (ret < 0)
- return ret;
-
- if (version >= 0x0940) {
- ret = read(in_fd, buf, 4); /* skip mtime_high */
- if (ret < 0)
- return ret;
- }
+ parse += 8;
+ if (version >= 0x0940)
+ parse += 4; /* skip mtime_high */
- ret = read(in_fd, &l, 1);
- if (ret < 0)
- return ret;
+ l = *parse++;
/* don't care about the file name, and skip checksum */
- ret = read(in_fd, buf, l + 4);
- if (ret < 0)
- return ret;
+ parse += l + 4;
- return 0;
+ *skip = parse - input;
+ return 1;
}
-int unlzo(int in_fd, int out_fd, int *dest_len)
+static int __unlzo(int *dest_len,
+ int (*fill) (void *, unsigned int),
+ int (*flush) (void *, unsigned int))
{
- u8 r = 0;
+ u8 skip = 0, r = 0;
u32 src_len, dst_len;
size_t tmp;
- u8 *in_buf, *out_buf;
+ u8 *in_buf, *in_buf_save, *out_buf, *out_buf_save;
int obytes_processed = 0;
- unsigned char buf[8];
- int ret;
-
- if (parse_header(in_fd))
- return -EINVAL;
+ int ret = -1;
out_buf = xmalloc(LZO_BLOCK_SIZE);
in_buf = xmalloc(lzo1x_worst_compress(LZO_BLOCK_SIZE));
+ in_buf_save = in_buf;
+ out_buf_save = out_buf;
+
+ ret = fill(in_buf, lzo1x_worst_compress(LZO_BLOCK_SIZE));
+ if (ret < 0)
+ goto exit_free;
+
+ if (!parse_header(in_buf, &skip))
+ return -EINVAL;
+
+ in_buf += skip;
+
for (;;) {
/* read uncompressed block size */
- ret = read(in_fd, buf, 4);
- if (ret < 0)
- goto exit_free;
- dst_len = get_unaligned_be32(buf);
+ dst_len = get_unaligned_be32(in_buf);
+ in_buf += 4;
/* exit if last block */
if (dst_len == 0)
@@ -150,43 +125,53 @@ int unlzo(int in_fd, int out_fd, int *dest_len)
}
/* read compressed block size, and skip block checksum info */
- ret = read(in_fd, buf, 8);
- if (ret < 0)
- goto exit_free;
-
- src_len = get_unaligned_be32(buf);
+ src_len = get_unaligned_be32(in_buf);
+ in_buf += 8;
if (src_len <= 0 || src_len > dst_len) {
printf("file corrupted");
goto exit_free;
}
- ret = read(in_fd, in_buf, src_len);
- if (ret < 0)
- goto exit_free;
/* decompress */
tmp = dst_len;
- if (src_len < dst_len) {
- r = lzo1x_decompress_safe((u8 *) in_buf, src_len,
- out_buf, &tmp);
- if (r != LZO_E_OK || dst_len != tmp) {
+
+ /* When the input data is not compressed at all,
+ * lzo1x_decompress_safe will fail, so call memcpy()
+ * instead */
+ if (unlikely(dst_len == src_len)) {
+ if (src_len != dst_len) {
printf("Compressed data violation");
goto exit_free;
}
- ret = write(out_fd, out_buf, dst_len);
- if (ret < 0)
- goto exit_free;
+ out_buf = in_buf;
} else {
- if (src_len != dst_len) {
+ r = lzo1x_decompress_safe((u8 *) in_buf, src_len,
+ out_buf, &tmp);
+
+ if (r != LZO_E_OK || dst_len != tmp) {
printf("Compressed data violation");
goto exit_free;
}
- ret = write(out_fd, in_buf, dst_len);
- if (ret < 0)
- goto exit_free;
}
+ ret = flush(out_buf, dst_len);
+ if (ret < 0)
+ goto exit_free;
+
+ out_buf = in_buf + src_len;
+ in_buf = in_buf_save;
+ ret = fill(in_buf, lzo1x_worst_compress(LZO_BLOCK_SIZE));
+ if (ret < 0)
+ goto exit_free;
+
+ if (ret == 0)
+ in_buf = out_buf;
+
+ out_buf = out_buf_save;
+
obytes_processed += dst_len;
+
}
exit_free:
@@ -197,3 +182,22 @@ exit_free:
return 0;
}
+static int in_fd;
+static int out_fd;
+
+static int unlzo_fill(void *buf, unsigned int len)
+{
+ return read(in_fd, buf, len);
+}
+
+static int unlzo_flush(void *buf, unsigned int len)
+{
+ return write(out_fd, buf, len);
+}
+
+int unlzo(int _in_fd, int _out_fd, int *dest_len)
+{
+ in_fd = _in_fd;
+ out_fd = _out_fd;
+ return __unlzo(dest_len, unlzo_fill, unlzo_flush);
+}
--
1.7.2.3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
next reply other threads:[~2011-01-28 10:15 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-01-28 10:13 Jean-Christophe PLAGNIOL-VILLARD [this message]
2011-02-22 23:59 ` Eric Benard
2011-02-23 17:05 ` Jean-Christophe PLAGNIOL-VILLARD
2011-02-23 17:21 ` Eric Benard
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1296209604-29790-1-git-send-email-plagnioj@jcrosoft.com \
--to=plagnioj@jcrosoft.com \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox