aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-29 12:01:51 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-29 12:01:51 +0000
commit052ad9a56883a56742cec1afc6c1c8dfff222495 (patch)
treec06321623bd51c725b559f3e91d1a9b736a26646
parentc8653f62f2203d0377933c1b5f0442666e27f91a (diff)
downloadbusybox-w32-052ad9a56883a56742cec1afc6c1c8dfff222495.tar.gz
busybox-w32-052ad9a56883a56742cec1afc6c1c8dfff222495.tar.bz2
busybox-w32-052ad9a56883a56742cec1afc6c1c8dfff222495.zip
lzop: new applet. Busyboxed by Alain Knaff. +7700 bytes.
-rw-r--r--archival/Config.in15
-rw-r--r--archival/Kbuild2
-rw-r--r--archival/liblzo.h93
-rw-r--r--archival/liblzo_interface.h71
-rw-r--r--archival/lzo1x_1.c35
-rw-r--r--archival/lzo1x_1o.c35
-rw-r--r--archival/lzo1x_9x.c920
-rw-r--r--archival/lzo1x_c.c296
-rw-r--r--archival/lzo1x_d.c420
-rw-r--r--archival/lzop.c1075
-rw-r--r--include/applets.h3
-rw-r--r--include/usage.h25
12 files changed, 2990 insertions, 0 deletions
diff --git a/archival/Config.in b/archival/Config.in
index e0d43c0ee..a983e4433 100644
--- a/archival/Config.in
+++ b/archival/Config.in
@@ -165,6 +165,21 @@ config GZIP
165 gzip is used to compress files. 165 gzip is used to compress files.
166 It's probably the most widely used UNIX compression program. 166 It's probably the most widely used UNIX compression program.
167 167
168config LZOP
169 bool "lzop"
170 default n
171 help
172 Lzop compression/decompresion.
173
174config LZOP_COMPR_HIGH
175 bool "lzop complession levels 7,8,9 (not very useful)"
176 default n
177 depends on LZOP
178 help
179 High levels (7,8,9) of lzop compression. These levels
180 are actually slower than gzip at equivalent compression ratios
181 and take up 3.2K of code.
182
168config RPM2CPIO 183config RPM2CPIO
169 bool "rpm2cpio" 184 bool "rpm2cpio"
170 default n 185 default n
diff --git a/archival/Kbuild b/archival/Kbuild
index 72dbdda0e..de0ca4315 100644
--- a/archival/Kbuild
+++ b/archival/Kbuild
@@ -16,6 +16,8 @@ lib-$(CONFIG_DPKG) += dpkg.o
16lib-$(CONFIG_DPKG_DEB) += dpkg_deb.o 16lib-$(CONFIG_DPKG_DEB) += dpkg_deb.o
17lib-$(CONFIG_GUNZIP) += bbunzip.o 17lib-$(CONFIG_GUNZIP) += bbunzip.o
18lib-$(CONFIG_GZIP) += gzip.o bbunzip.o 18lib-$(CONFIG_GZIP) += gzip.o bbunzip.o
19lib-$(CONFIG_LZOP) += lzop.o lzo1x_1.o lzo1x_1o.o lzo1x_d.o
20lib-$(CONFIG_LZOP_COMPR_HIGH) += lzo1x_9x.o
19lib-$(CONFIG_RPM2CPIO) += rpm2cpio.o 21lib-$(CONFIG_RPM2CPIO) += rpm2cpio.o
20lib-$(CONFIG_RPM) += rpm.o 22lib-$(CONFIG_RPM) += rpm.o
21lib-$(CONFIG_TAR) += tar.o 23lib-$(CONFIG_TAR) += tar.o
diff --git a/archival/liblzo.h b/archival/liblzo.h
new file mode 100644
index 000000000..843997cb9
--- /dev/null
+++ b/archival/liblzo.h
@@ -0,0 +1,93 @@
1/*
2 This file is part of the LZO real-time data compression library.
3
4 Copyright (C) 1996..2008 Markus Franz Xaver Johannes Oberhumer
5 All Rights Reserved.
6
7 Markus F.X.J. Oberhumer <markus@oberhumer.com>
8 http://www.oberhumer.com/opensource/lzo/
9
10 The LZO library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2 of
13 the License, or (at your option) any later version.
14
15 The LZO library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with the LZO library; see the file COPYING.
22 If not, write to the Free Software Foundation, Inc.,
23 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 */
25
26#include "liblzo_interface.h"
27
28/* lzo-2.03/src/config1x.h */
29#define M2_MIN_LEN 3
30#define M2_MAX_LEN 8
31#define M3_MAX_LEN 33
32#define M4_MAX_LEN 9
33#define M1_MAX_OFFSET 0x0400
34#define M2_MAX_OFFSET 0x0800
35#define M3_MAX_OFFSET 0x4000
36#define M4_MAX_OFFSET 0xbfff
37#define M1_MARKER 0
38#define M3_MARKER 32
39#define M4_MARKER 16
40
41#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET)
42#define MIN_LOOKAHEAD (M2_MAX_LEN + 1)
43
44#define LZO_EOF_CODE
45
46/* lzo-2.03/src/lzo_dict.h */
47#define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex]
48#define DX2(p,s1,s2) \
49 (((((unsigned)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0])
50//#define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0])
51//#define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0])
52#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0])
53
54#define D_SIZE (1U << D_BITS)
55#define D_MASK ((1U << D_BITS) - 1)
56#define D_HIGH ((D_MASK >> 1) + 1)
57
58#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \
59 ( \
60 m_pos = ip - (unsigned)(ip - m_pos), \
61 ((uintptr_t)m_pos < (uintptr_t)in \
62 || (m_off = (unsigned)(ip - m_pos)) <= 0 \
63 || m_off > max_offset) \
64 )
65
66#define DENTRY(p,in) (p)
67#define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in)
68
69#define DMS(v,s) ((unsigned) (((v) & (D_MASK >> (s))) << (s)))
70#define DM(v) ((unsigned) ((v) & D_MASK))
71#define DMUL(a,b) ((unsigned) ((a) * (b)))
72
73/* lzo-2.03/src/lzo_ptr.h */
74#define pd(a,b) ((unsigned)((a)-(b)))
75
76# define TEST_IP (ip < ip_end)
77# define NEED_IP(x) \
78 if ((unsigned)(ip_end - ip) < (unsigned)(x)) goto input_overrun
79
80# undef TEST_OP /* don't need both of the tests here */
81# define TEST_OP 1
82# define NEED_OP(x) \
83 if ((unsigned)(op_end - op) < (unsigned)(x)) goto output_overrun
84
85#define HAVE_ANY_OP 1
86
87//#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
88# define TEST_LB(m_pos) if (m_pos < out || m_pos >= op) goto lookbehind_overrun
89//# define TEST_LBO(m_pos,o) if (m_pos < out || m_pos >= op - (o)) goto lookbehind_overrun
90//#else
91//# define TEST_LB(m_pos) ((void) 0)
92//# define TEST_LBO(m_pos,o) ((void) 0)
93//#endif
diff --git a/archival/liblzo_interface.h b/archival/liblzo_interface.h
new file mode 100644
index 000000000..9a84c0b6b
--- /dev/null
+++ b/archival/liblzo_interface.h
@@ -0,0 +1,71 @@
1/*
2 This file is part of the LZO real-time data compression library.
3
4 Copyright (C) 1996..2008 Markus Franz Xaver Johannes Oberhumer
5 All Rights Reserved.
6
7 Markus F.X.J. Oberhumer <markus@oberhumer.com>
8 http://www.oberhumer.com/opensource/lzo/
9
10 The LZO library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2 of
13 the License, or (at your option) any later version.
14
15 The LZO library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with the LZO library; see the file COPYING.
22 If not, write to the Free Software Foundation, Inc.,
23 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 */
25
26#define LZO1X
27#undef LZO1Y
28
29#undef assert
30/*
31static void die_at(int line)
32{
33 bb_error_msg_and_die("internal error at %d", line);
34}
35#define assert(v) if (!(v)) die_at(__LINE__)
36*/
37#define assert(v) ((void)0)
38
39int lzo1x_1_compress(const uint8_t* src, unsigned src_len,
40 uint8_t* dst, unsigned* dst_len,
41 void* wrkmem);
42int lzo1x_1_15_compress(const uint8_t* src, unsigned src_len,
43 uint8_t* dst, unsigned* dst_len,
44 void* wrkmem);
45int lzo1x_999_compress_level(const uint8_t* in, unsigned in_len,
46 uint8_t* out, unsigned* out_len,
47 void* wrkmem,
48 int compression_level);
49
50/* decompression */
51//int lzo1x_decompress(const uint8_t* src, unsigned src_len,
52// uint8_t* dst, unsigned* dst_len,
53// void* wrkmem /* NOT USED */);
54/* safe decompression with overrun testing */
55int lzo1x_decompress_safe(const uint8_t* src, unsigned src_len,
56 uint8_t* dst, unsigned* dst_len,
57 void* wrkmem /* NOT USED */);
58
59#define LZO_E_OK 0
60#define LZO_E_ERROR (-1)
61#define LZO_E_OUT_OF_MEMORY (-2) /* [not used right now] */
62#define LZO_E_NOT_COMPRESSIBLE (-3) /* [not used right now] */
63#define LZO_E_INPUT_OVERRUN (-4)
64#define LZO_E_OUTPUT_OVERRUN (-5)
65#define LZO_E_LOOKBEHIND_OVERRUN (-6)
66#define LZO_E_EOF_NOT_FOUND (-7)
67#define LZO_E_INPUT_NOT_CONSUMED (-8)
68#define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */
69
70/* lzo-2.03/include/lzo/lzoconf.h */
71#define LZO_VERSION 0x2030
diff --git a/archival/lzo1x_1.c b/archival/lzo1x_1.c
new file mode 100644
index 000000000..a88839846
--- /dev/null
+++ b/archival/lzo1x_1.c
@@ -0,0 +1,35 @@
1/* LZO1X-1 compression
2
3 This file is part of the LZO real-time data compression library.
4
5 Copyright (C) 1996..2008 Markus Franz Xaver Johannes Oberhumer
6 All Rights Reserved.
7
8 Markus F.X.J. Oberhumer <markus@oberhumer.com>
9 http://www.oberhumer.com/opensource/lzo/
10
11 The LZO library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2 of
14 the License, or (at your option) any later version.
15
16 The LZO library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with the LZO library; see the file COPYING.
23 If not, write to the Free Software Foundation, Inc.,
24 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 */
26#include "libbb.h"
27#include "liblzo.h"
28
29#define D_BITS 14
30#define D_INDEX1(d,p) d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5)
31#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f)
32
33#define DO_COMPRESS lzo1x_1_compress
34
35#include "lzo1x_c.c"
diff --git a/archival/lzo1x_1o.c b/archival/lzo1x_1o.c
new file mode 100644
index 000000000..3c61253e0
--- /dev/null
+++ b/archival/lzo1x_1o.c
@@ -0,0 +1,35 @@
1/* LZO1X-1(15) compression
2
3 This file is part of the LZO real-time data compression library.
4
5 Copyright (C) 1996..2008 Markus Franz Xaver Johannes Oberhumer
6 All Rights Reserved.
7
8 Markus F.X.J. Oberhumer <markus@oberhumer.com>
9 http://www.oberhumer.com/opensource/lzo/
10
11 The LZO library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2 of
14 the License, or (at your option) any later version.
15
16 The LZO library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with the LZO library; see the file COPYING.
23 If not, write to the Free Software Foundation, Inc.,
24 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 */
26#include "libbb.h"
27#include "liblzo.h"
28
29#define D_BITS 15
30#define D_INDEX1(d,p) d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5)
31#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f)
32
33#define DO_COMPRESS lzo1x_1_15_compress
34
35#include "lzo1x_c.c"
diff --git a/archival/lzo1x_9x.c b/archival/lzo1x_9x.c
new file mode 100644
index 000000000..d30e2e7d1
--- /dev/null
+++ b/archival/lzo1x_9x.c
@@ -0,0 +1,920 @@
1/* lzo1x_9x.c -- implementation of the LZO1X-999 compression algorithm
2
3 This file is part of the LZO real-time data compression library.
4
5 Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
6 Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
7 Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
8 Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
9 Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
10 Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
11 Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
12 Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
13 Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
14 Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
15 Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
16 Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
17 Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
18 All Rights Reserved.
19
20 The LZO library is free software; you can redistribute it and/or
21 modify it under the terms of the GNU General Public License as
22 published by the Free Software Foundation; either version 2 of
23 the License, or (at your option) any later version.
24
25 The LZO library is distributed in the hope that it will be useful,
26 but WITHOUT ANY WARRANTY; without even the implied warranty of
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 GNU General Public License for more details.
29
30 You should have received a copy of the GNU General Public License
31 along with the LZO library; see the file COPYING.
32 If not, write to the Free Software Foundation, Inc.,
33 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
34
35 Markus F.X.J. Oberhumer
36 <markus@oberhumer.com>
37 http://www.oberhumer.com/opensource/lzo/
38*/
39#include "libbb.h"
40
41/* The following is probably only safe on Intel-compatible processors ... */
42#define LZO_UNALIGNED_OK_2
43#define LZO_UNALIGNED_OK_4
44
45#include "liblzo.h"
46
47#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b))
48#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b))
49#define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c))
50
51/***********************************************************************
52//
53************************************************************************/
54#define SWD_N M4_MAX_OFFSET /* size of ring buffer */
55#define SWD_F 2048 /* upper limit for match length */
56
57#define SWD_BEST_OFF (LZO_MAX3(M2_MAX_LEN, M3_MAX_LEN, M4_MAX_LEN) + 1)
58
59typedef struct {
60 int init;
61
62 unsigned look; /* bytes in lookahead buffer */
63
64 unsigned m_len;
65 unsigned m_off;
66
67 const uint8_t *bp;
68 const uint8_t *ip;
69 const uint8_t *in;
70 const uint8_t *in_end;
71 uint8_t *out;
72
73 unsigned r1_lit;
74
75} lzo1x_999_t;
76
77#define getbyte(c) ((c).ip < (c).in_end ? *((c).ip)++ : (-1))
78
79/* lzo_swd.c -- sliding window dictionary */
80
81/***********************************************************************
82//
83************************************************************************/
84#define SWD_UINT_MAX USHRT_MAX
85
86#ifndef SWD_HSIZE
87# define SWD_HSIZE 16384
88#endif
89#ifndef SWD_MAX_CHAIN
90# define SWD_MAX_CHAIN 2048
91#endif
92
93#define HEAD3(b, p) \
94 ( ((0x9f5f * ((((b[p]<<5)^b[p+1])<<5) ^ b[p+2])) >> 5) & (SWD_HSIZE-1) )
95
96#if defined(LZO_UNALIGNED_OK_2)
97# define HEAD2(b,p) (* (uint16_t *) &(b[p]))
98#else
99# define HEAD2(b,p) (b[p] ^ ((unsigned)b[p+1]<<8))
100#endif
101#define NIL2 SWD_UINT_MAX
102
103typedef struct lzo_swd {
104 /* public - "built-in" */
105
106 /* public - configuration */
107 unsigned max_chain;
108 int use_best_off;
109
110 /* public - output */
111 unsigned m_len;
112 unsigned m_off;
113 unsigned look;
114 int b_char;
115#if defined(SWD_BEST_OFF)
116 unsigned best_off[SWD_BEST_OFF];
117#endif
118
119 /* semi public */
120 lzo1x_999_t *c;
121 unsigned m_pos;
122#if defined(SWD_BEST_OFF)
123 unsigned best_pos[SWD_BEST_OFF];
124#endif
125
126 /* private */
127 unsigned ip; /* input pointer (lookahead) */
128 unsigned bp; /* buffer pointer */
129 unsigned rp; /* remove pointer */
130
131 unsigned node_count;
132 unsigned first_rp;
133
134 uint8_t b[SWD_N + SWD_F];
135 uint8_t b_wrap[SWD_F]; /* must follow b */
136 uint16_t head3[SWD_HSIZE];
137 uint16_t succ3[SWD_N + SWD_F];
138 uint16_t best3[SWD_N + SWD_F];
139 uint16_t llen3[SWD_HSIZE];
140#ifdef HEAD2
141 uint16_t head2[65536L];
142#endif
143} lzo_swd_t, *lzo_swd_p;
144
145#define SIZEOF_LZO_SWD_T (sizeof(lzo_swd_t))
146
147
148/* Access macro for head3.
149 * head3[key] may be uninitialized, but then its value will never be used.
150 */
151#define s_get_head3(s,key) s->head3[key]
152
153
154/***********************************************************************
155//
156************************************************************************/
157#define B_SIZE (SWD_N + SWD_F)
158
159static int swd_init(lzo_swd_p s)
160{
161 /* defaults */
162 s->node_count = SWD_N;
163
164 memset(s->llen3, 0, sizeof(s->llen3[0]) * (unsigned)SWD_HSIZE);
165#ifdef HEAD2
166 memset(s->head2, 0xff, sizeof(s->head2[0]) * 65536L);
167 assert(s->head2[0] == NIL2);
168#endif
169
170 s->ip = 0;
171 s->bp = s->ip;
172 s->first_rp = s->ip;
173
174 assert(s->ip + SWD_F <= B_SIZE);
175 s->look = (unsigned) (s->c->in_end - s->c->ip);
176 if (s->look > 0) {
177 if (s->look > SWD_F)
178 s->look = SWD_F;
179 memcpy(&s->b[s->ip],s->c->ip,s->look);
180 s->c->ip += s->look;
181 s->ip += s->look;
182 }
183 if (s->ip == B_SIZE)
184 s->ip = 0;
185
186 s->rp = s->first_rp;
187 if (s->rp >= s->node_count)
188 s->rp -= s->node_count;
189 else
190 s->rp += B_SIZE - s->node_count;
191
192 return LZO_E_OK;
193}
194
195#define swd_pos2off(s,pos) \
196 (s->bp > (pos) ? s->bp - (pos) : B_SIZE - ((pos) - s->bp))
197
198
199/***********************************************************************
200//
201************************************************************************/
202static void swd_getbyte(lzo_swd_p s)
203{
204 int c;
205
206 if ((c = getbyte(*(s->c))) < 0) {
207 if (s->look > 0)
208 --s->look;
209 } else {
210 s->b[s->ip] = c;
211 if (s->ip < SWD_F)
212 s->b_wrap[s->ip] = c;
213 }
214 if (++s->ip == B_SIZE)
215 s->ip = 0;
216 if (++s->bp == B_SIZE)
217 s->bp = 0;
218 if (++s->rp == B_SIZE)
219 s->rp = 0;
220}
221
222
223/***********************************************************************
224// remove node from lists
225************************************************************************/
226static void swd_remove_node(lzo_swd_p s, unsigned node)
227{
228 if (s->node_count == 0) {
229 unsigned key;
230
231 key = HEAD3(s->b,node);
232 assert(s->llen3[key] > 0);
233 --s->llen3[key];
234
235#ifdef HEAD2
236 key = HEAD2(s->b,node);
237 assert(s->head2[key] != NIL2);
238 if ((unsigned) s->head2[key] == node)
239 s->head2[key] = NIL2;
240#endif
241 } else
242 --s->node_count;
243}
244
245
246/***********************************************************************
247//
248************************************************************************/
249static void swd_accept(lzo_swd_p s, unsigned n)
250{
251 assert(n <= s->look);
252
253 while (n--) {
254 unsigned key;
255
256 swd_remove_node(s,s->rp);
257
258 /* add bp into HEAD3 */
259 key = HEAD3(s->b,s->bp);
260 s->succ3[s->bp] = s_get_head3(s,key);
261 s->head3[key] = s->bp;
262 s->best3[s->bp] = SWD_F + 1;
263 s->llen3[key]++;
264 assert(s->llen3[key] <= SWD_N);
265
266#ifdef HEAD2
267 /* add bp into HEAD2 */
268 key = HEAD2(s->b,s->bp);
269 s->head2[key] = s->bp;
270#endif
271
272 swd_getbyte(s);
273 }
274}
275
276
277/***********************************************************************
278//
279************************************************************************/
280static void swd_search(lzo_swd_p s, unsigned node, unsigned cnt)
281{
282 const uint8_t *p1;
283 const uint8_t *p2;
284 const uint8_t *px;
285 unsigned m_len = s->m_len;
286 const uint8_t *b = s->b;
287 const uint8_t *bp = s->b + s->bp;
288 const uint8_t *bx = s->b + s->bp + s->look;
289 unsigned char scan_end1;
290
291 assert(s->m_len > 0);
292
293 scan_end1 = bp[m_len - 1];
294 for ( ; cnt-- > 0; node = s->succ3[node]) {
295 p1 = bp;
296 p2 = b + node;
297 px = bx;
298
299 assert(m_len < s->look);
300
301 if (p2[m_len - 1] == scan_end1 &&
302 p2[m_len] == p1[m_len] &&
303 p2[0] == p1[0] &&
304 p2[1] == p1[1]) {
305 unsigned i;
306 assert(lzo_memcmp(bp,&b[node],3) == 0);
307
308 p1 += 2; p2 += 2;
309 do {} while (++p1 < px && *p1 == *++p2);
310 i = p1-bp;
311
312 assert(lzo_memcmp(bp,&b[node],i) == 0);
313
314#if defined(SWD_BEST_OFF)
315 if (i < SWD_BEST_OFF) {
316 if (s->best_pos[i] == 0)
317 s->best_pos[i] = node + 1;
318 }
319#endif
320 if (i > m_len) {
321 s->m_len = m_len = i;
322 s->m_pos = node;
323 if (m_len == s->look)
324 return;
325 if (m_len >= SWD_F)
326 return;
327 if (m_len > (unsigned) s->best3[node])
328 return;
329 scan_end1 = bp[m_len - 1];
330 }
331 }
332 }
333}
334
335
336/***********************************************************************
337//
338************************************************************************/
339#ifdef HEAD2
340
341static int swd_search2(lzo_swd_p s)
342{
343 unsigned key;
344
345 assert(s->look >= 2);
346 assert(s->m_len > 0);
347
348 key = s->head2[ HEAD2(s->b,s->bp) ];
349 if (key == NIL2)
350 return 0;
351 assert(lzo_memcmp(&s->b[s->bp],&s->b[key],2) == 0);
352#if defined(SWD_BEST_OFF)
353 if (s->best_pos[2] == 0)
354 s->best_pos[2] = key + 1;
355#endif
356
357 if (s->m_len < 2) {
358 s->m_len = 2;
359 s->m_pos = key;
360 }
361 return 1;
362}
363
364#endif
365
366
367/***********************************************************************
368//
369************************************************************************/
370static void swd_findbest(lzo_swd_p s)
371{
372 unsigned key;
373 unsigned cnt, node;
374 unsigned len;
375
376 assert(s->m_len > 0);
377
378 /* get current head, add bp into HEAD3 */
379 key = HEAD3(s->b,s->bp);
380 node = s->succ3[s->bp] = s_get_head3(s,key);
381 cnt = s->llen3[key]++;
382 assert(s->llen3[key] <= SWD_N + SWD_F);
383 if (cnt > s->max_chain)
384 cnt = s->max_chain;
385 s->head3[key] = s->bp;
386
387 s->b_char = s->b[s->bp];
388 len = s->m_len;
389 if (s->m_len >= s->look) {
390 if (s->look == 0)
391 s->b_char = -1;
392 s->m_off = 0;
393 s->best3[s->bp] = SWD_F + 1;
394 } else {
395#ifdef HEAD2
396 if (swd_search2(s))
397#endif
398 if (s->look >= 3)
399 swd_search(s,node,cnt);
400 if (s->m_len > len)
401 s->m_off = swd_pos2off(s,s->m_pos);
402 s->best3[s->bp] = s->m_len;
403
404#if defined(SWD_BEST_OFF)
405 if (s->use_best_off) {
406 int i;
407 for (i = 2; i < SWD_BEST_OFF; i++)
408 if (s->best_pos[i] > 0)
409 s->best_off[i] = swd_pos2off(s,s->best_pos[i]-1);
410 else
411 s->best_off[i] = 0;
412 }
413#endif
414 }
415
416 swd_remove_node(s,s->rp);
417
418#ifdef HEAD2
419 /* add bp into HEAD2 */
420 key = HEAD2(s->b,s->bp);
421 s->head2[key] = s->bp;
422#endif
423}
424
425#undef HEAD3
426#undef HEAD2
427#undef s_get_head3
428
429
430/***********************************************************************
431//
432************************************************************************/
433static int init_match(lzo1x_999_t *c, lzo_swd_p s, uint32_t use_best_off)
434{
435 int r;
436
437 assert(!c->init);
438 c->init = 1;
439
440 s->c = c;
441
442 r = swd_init(s);
443 if (r != 0)
444 return r;
445
446 s->use_best_off = use_best_off;
447 return r;
448}
449
450
451/***********************************************************************
452//
453************************************************************************/
454static int find_match(lzo1x_999_t *c, lzo_swd_p s,
455 unsigned this_len, unsigned skip)
456{
457 assert(c->init);
458
459 if (skip > 0) {
460 assert(this_len >= skip);
461 swd_accept(s, this_len - skip);
462 } else {
463 assert(this_len <= 1);
464 }
465
466 s->m_len = 1;
467 s->m_len = 1;
468#ifdef SWD_BEST_OFF
469 if (s->use_best_off)
470 memset(s->best_pos,0,sizeof(s->best_pos));
471#endif
472 swd_findbest(s);
473 c->m_len = s->m_len;
474 c->m_off = s->m_off;
475
476 swd_getbyte(s);
477
478 if (s->b_char < 0) {
479 c->look = 0;
480 c->m_len = 0;
481 } else {
482 c->look = s->look + 1;
483 }
484 c->bp = c->ip - c->look;
485
486 return LZO_E_OK;
487}
488
489/* this is a public functions, but there is no prototype in a header file */
490static int lzo1x_999_compress_internal(const uint8_t *in , unsigned in_len,
491 uint8_t *out, unsigned *out_len,
492 void *wrkmem,
493 unsigned good_length,
494 unsigned max_lazy,
495 unsigned max_chain,
496 uint32_t use_best_off);
497
498
499/***********************************************************************
500//
501************************************************************************/
502static uint8_t *code_match(lzo1x_999_t *c,
503 uint8_t *op, unsigned m_len, unsigned m_off)
504{
505 assert(op > c->out);
506 if (m_len == 2) {
507 assert(m_off <= M1_MAX_OFFSET);
508 assert(c->r1_lit > 0); assert(c->r1_lit < 4);
509 m_off -= 1;
510 *op++ = M1_MARKER | ((m_off & 3) << 2);
511 *op++ = m_off >> 2;
512 } else if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) {
513 assert(m_len >= 3);
514 m_off -= 1;
515 *op++ = ((m_len - 1) << 5) | ((m_off & 7) << 2);
516 *op++ = m_off >> 3;
517 assert(op[-2] >= M2_MARKER);
518 } else if (m_len == M2_MIN_LEN && m_off <= MX_MAX_OFFSET && c->r1_lit >= 4) {
519 assert(m_len == 3);
520 assert(m_off > M2_MAX_OFFSET);
521 m_off -= 1 + M2_MAX_OFFSET;
522 *op++ = M1_MARKER | ((m_off & 3) << 2);
523 *op++ = m_off >> 2;
524 } else if (m_off <= M3_MAX_OFFSET) {
525 assert(m_len >= 3);
526 m_off -= 1;
527 if (m_len <= M3_MAX_LEN)
528 *op++ = M3_MARKER | (m_len - 2);
529 else {
530 m_len -= M3_MAX_LEN;
531 *op++ = M3_MARKER | 0;
532 while (m_len > 255)
533 {
534 m_len -= 255;
535 *op++ = 0;
536 }
537 assert(m_len > 0);
538 *op++ = m_len;
539 }
540 *op++ = m_off << 2;
541 *op++ = m_off >> 6;
542 } else {
543 unsigned k;
544
545 assert(m_len >= 3);
546 assert(m_off > 0x4000); assert(m_off <= 0xbfff);
547 m_off -= 0x4000;
548 k = (m_off & 0x4000) >> 11;
549 if (m_len <= M4_MAX_LEN)
550 *op++ = M4_MARKER | k | (m_len - 2);
551 else {
552 m_len -= M4_MAX_LEN;
553 *op++ = M4_MARKER | k | 0;
554 while (m_len > 255)
555 {
556 m_len -= 255;
557 *op++ = 0;
558 }
559 assert(m_len > 0);
560 *op++ = m_len;
561 }
562 *op++ = m_off << 2;
563 *op++ = m_off >> 6;
564 }
565
566 return op;
567}
568
569
570static uint8_t *STORE_RUN(lzo1x_999_t *c, uint8_t *op,
571 const uint8_t *ii, unsigned t)
572{
573 if (op == c->out && t <= 238) {
574 *op++ = 17 + t;
575 } else if (t <= 3) {
576 op[-2] |= t;
577 } else if (t <= 18) {
578 *op++ = t - 3;
579 } else {
580 unsigned tt = t - 18;
581
582 *op++ = 0;
583 while (tt > 255) {
584 tt -= 255;
585 *op++ = 0;
586 }
587 assert(tt > 0);
588 *op++ = tt;
589 }
590 do *op++ = *ii++; while (--t > 0);
591
592 return op;
593}
594
595
596static uint8_t *code_run(lzo1x_999_t *c, uint8_t *op, const uint8_t *ii,
597 unsigned lit)
598{
599 if (lit > 0) {
600 assert(m_len >= 2);
601 op = STORE_RUN(c,op,ii,lit);
602 } else {
603 assert(m_len >= 3);
604 }
605 c->r1_lit = lit;
606
607 return op;
608}
609
610
611/***********************************************************************
612//
613************************************************************************/
614static int len_of_coded_match(unsigned m_len, unsigned m_off, unsigned lit)
615{
616 int n = 4;
617
618 if (m_len < 2)
619 return -1;
620 if (m_len == 2)
621 return (m_off <= M1_MAX_OFFSET && lit > 0 && lit < 4) ? 2 : -1;
622 if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET)
623 return 2;
624 if (m_len == M2_MIN_LEN && m_off <= MX_MAX_OFFSET && lit >= 4)
625 return 2;
626 if (m_off <= M3_MAX_OFFSET) {
627 if (m_len <= M3_MAX_LEN)
628 return 3;
629 m_len -= M3_MAX_LEN;
630 } else if (m_off <= M4_MAX_OFFSET) {
631 if (m_len <= M4_MAX_LEN)
632 return 3;
633 m_len -= M4_MAX_LEN;
634 } else
635 return -1;
636 while (m_len > 255) {
637 m_len -= 255;
638 n++;
639 }
640 return n;
641}
642
643
644static int min_gain(unsigned ahead, unsigned lit1,
645 unsigned lit2, int l1, int l2, int l3)
646{
647 int lazy_match_min_gain = 0;
648
649 assert (ahead >= 1);
650 lazy_match_min_gain += ahead;
651
652 if (lit1 <= 3)
653 lazy_match_min_gain += (lit2 <= 3) ? 0 : 2;
654 else if (lit1 <= 18)
655 lazy_match_min_gain += (lit2 <= 18) ? 0 : 1;
656
657 lazy_match_min_gain += (l2 - l1) * 2;
658 if (l3 > 0)
659 lazy_match_min_gain -= (ahead - l3) * 2;
660
661 if (lazy_match_min_gain < 0)
662 lazy_match_min_gain = 0;
663
664 return lazy_match_min_gain;
665}
666
667
668/***********************************************************************
669//
670************************************************************************/
671#if defined(SWD_BEST_OFF)
672
673static void better_match(const lzo_swd_p swd,
674 unsigned *m_len, unsigned *m_off)
675{
676
677 if (*m_len <= M2_MIN_LEN)
678 return;
679
680 if (*m_off <= M2_MAX_OFFSET)
681 return;
682
683 /* M3/M4 -> M2 */
684 if (*m_off > M2_MAX_OFFSET &&
685 *m_len >= M2_MIN_LEN + 1 && *m_len <= M2_MAX_LEN + 1 &&
686 swd->best_off[*m_len-1] && swd->best_off[*m_len-1] <= M2_MAX_OFFSET)
687 {
688 *m_len = *m_len - 1;
689 *m_off = swd->best_off[*m_len];
690 return;
691 }
692
693 /* M4 -> M2 */
694 if (*m_off > M3_MAX_OFFSET &&
695 *m_len >= M4_MAX_LEN + 1 && *m_len <= M2_MAX_LEN + 2 &&
696 swd->best_off[*m_len-2] && swd->best_off[*m_len-2] <= M2_MAX_OFFSET)
697 {
698 *m_len = *m_len - 2;
699 *m_off = swd->best_off[*m_len];
700 return;
701 }
702 /* M4 -> M3 */
703 if (*m_off > M3_MAX_OFFSET &&
704 *m_len >= M4_MAX_LEN + 1 && *m_len <= M3_MAX_LEN + 1 &&
705 swd->best_off[*m_len-1] && swd->best_off[*m_len-1] <= M3_MAX_OFFSET)
706 {
707 *m_len = *m_len - 1;
708 *m_off = swd->best_off[*m_len];
709 }
710}
711
712#endif
713
714
715/***********************************************************************
716//
717************************************************************************/
718static int lzo1x_999_compress_internal(const uint8_t *in, unsigned in_len,
719 uint8_t *out, unsigned *out_len,
720 void *wrkmem,
721 unsigned good_length,
722 unsigned max_lazy,
723 unsigned max_chain,
724 uint32_t use_best_off)
725{
726 uint8_t *op;
727 const uint8_t *ii;
728 unsigned lit;
729 unsigned m_len, m_off;
730 lzo1x_999_t cc;
731 lzo1x_999_t * const c = &cc;
732 lzo_swd_p const swd = (lzo_swd_p) wrkmem;
733 int r;
734
735 c->init = 0;
736 c->ip = c->in = in;
737 c->in_end = in + in_len;
738 c->out = out;
739
740 op = out;
741 ii = c->ip; /* point to start of literal run */
742 lit = 0;
743 c->r1_lit = 0;
744
745 r = init_match(c, swd, use_best_off);
746 if (r != 0)
747 return r;
748 swd->max_chain = max_chain;
749
750 r = find_match(c, swd, 0, 0);
751 if (r != 0)
752 return r;
753
754 while (c->look > 0) {
755 unsigned ahead;
756 unsigned max_ahead;
757 int l1, l2, l3;
758
759 m_len = c->m_len;
760 m_off = c->m_off;
761
762 assert(c->bp == c->ip - c->look);
763 assert(c->bp >= in);
764 if (lit == 0)
765 ii = c->bp;
766 assert(ii + lit == c->bp);
767 assert(swd->b_char == *(c->bp));
768
769 if ( m_len < 2 ||
770 (m_len == 2 && (m_off > M1_MAX_OFFSET || lit == 0 || lit >= 4)) ||
771 /* Do not accept this match for compressed-data compatibility
772 * with LZO v1.01 and before
773 * [ might be a problem for decompress() and optimize() ]
774 */
775 (m_len == 2 && op == out) ||
776 (op == out && lit == 0))
777 {
778 /* a literal */
779 m_len = 0;
780 }
781 else if (m_len == M2_MIN_LEN) {
782 /* compression ratio improves if we code a literal in some cases */
783 if (m_off > MX_MAX_OFFSET && lit >= 4)
784 m_len = 0;
785 }
786
787 if (m_len == 0) {
788 /* a literal */
789 lit++;
790 swd->max_chain = max_chain;
791 r = find_match(c,swd,1,0);
792 assert(r == 0);
793 continue;
794 }
795
796 /* a match */
797#if defined(SWD_BEST_OFF)
798 if (swd->use_best_off)
799 better_match(swd,&m_len,&m_off);
800#endif
801
802 /* shall we try a lazy match ? */
803 ahead = 0;
804 if (m_len >= max_lazy) {
805 /* no */
806 l1 = 0;
807 max_ahead = 0;
808 } else {
809 /* yes, try a lazy match */
810 l1 = len_of_coded_match(m_len,m_off,lit);
811 assert(l1 > 0);
812 max_ahead = LZO_MIN(2, (unsigned)l1 - 1);
813 }
814
815
816 while (ahead < max_ahead && c->look > m_len) {
817 int lazy_match_min_gain;
818
819 if (m_len >= good_length)
820 swd->max_chain = max_chain >> 2;
821 else
822 swd->max_chain = max_chain;
823 r = find_match(c,swd,1,0);
824 ahead++;
825
826 assert(r == 0);
827 assert(c->look > 0);
828 assert(ii + lit + ahead == c->bp);
829
830 if (c->m_len < m_len)
831 continue;
832 if (c->m_len == m_len && c->m_off >= m_off)
833 continue;
834#if defined(SWD_BEST_OFF)
835 if (swd->use_best_off)
836 better_match(swd,&c->m_len,&c->m_off);
837#endif
838 l2 = len_of_coded_match(c->m_len,c->m_off,lit+ahead);
839 if (l2 < 0)
840 continue;
841
842 /* compressed-data compatibility [see above] */
843 l3 = (op == out) ? -1 : len_of_coded_match(ahead,m_off,lit);
844
845 lazy_match_min_gain = min_gain(ahead,lit,lit+ahead,l1,l2,l3);
846 if (c->m_len >= m_len + lazy_match_min_gain) {
847 if (l3 > 0) {
848 /* code previous run */
849 op = code_run(c,op,ii,lit);
850 lit = 0;
851 /* code shortened match */
852 op = code_match(c,op,ahead,m_off);
853 } else {
854 lit += ahead;
855 assert(ii + lit == c->bp);
856 }
857 goto lazy_match_done;
858 }
859 }
860
861 assert(ii + lit + ahead == c->bp);
862
863 /* 1 - code run */
864 op = code_run(c,op,ii,lit);
865 lit = 0;
866
867 /* 2 - code match */
868 op = code_match(c,op,m_len,m_off);
869 swd->max_chain = max_chain;
870 r = find_match(c,swd,m_len,1+ahead);
871 assert(r == 0);
872
873 lazy_match_done: ;
874 }
875
876 /* store final run */
877 if (lit > 0)
878 op = STORE_RUN(c,op,ii,lit);
879
880#if defined(LZO_EOF_CODE)
881 *op++ = M4_MARKER | 1;
882 *op++ = 0;
883 *op++ = 0;
884#endif
885
886 *out_len = op - out;
887
888 return LZO_E_OK;
889}
890
891
892/***********************************************************************
893//
894************************************************************************/
895int lzo1x_999_compress_level(const uint8_t *in, unsigned in_len,
896 uint8_t *out, unsigned *out_len,
897 void *wrkmem,
898 int compression_level)
899{
900 static const struct {
901 uint16_t good_length;
902 uint16_t max_lazy;
903 uint16_t max_chain;
904 uint16_t use_best_off;
905 } c[3] = {
906 { 8, 32, 256, 0 },
907 { 32, 128, 2048, 1 },
908 { SWD_F, SWD_F, 4096, 1 } /* max. compression */
909 };
910
911 if (compression_level < 7 || compression_level > 9)
912 return LZO_E_ERROR;
913
914 compression_level -= 7;
915 return lzo1x_999_compress_internal(in, in_len, out, out_len, wrkmem,
916 c[compression_level].good_length,
917 c[compression_level].max_lazy,
918 c[compression_level].max_chain,
919 c[compression_level].use_best_off);
920}
diff --git a/archival/lzo1x_c.c b/archival/lzo1x_c.c
new file mode 100644
index 000000000..cc86f74b1
--- /dev/null
+++ b/archival/lzo1x_c.c
@@ -0,0 +1,296 @@
1/* implementation of the LZO1[XY]-1 compression algorithm
2
3 This file is part of the LZO real-time data compression library.
4
5 Copyright (C) 1996..2008 Markus Franz Xaver Johannes Oberhumer
6 All Rights Reserved.
7
8 Markus F.X.J. Oberhumer <markus@oberhumer.com>
9 http://www.oberhumer.com/opensource/lzo/
10
11 The LZO library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2 of
14 the License, or (at your option) any later version.
15
16 The LZO library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with the LZO library; see the file COPYING.
23 If not, write to the Free Software Foundation, Inc.,
24 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 */
26
27/***********************************************************************
28// compress a block of data.
29************************************************************************/
30static NOINLINE unsigned
31do_compress(const uint8_t* in, unsigned in_len,
32 uint8_t* out, unsigned* out_len,
33 void* wrkmem)
34{
35 register const uint8_t* ip;
36 uint8_t* op;
37 const uint8_t* const in_end = in + in_len;
38 const uint8_t* const ip_end = in + in_len - M2_MAX_LEN - 5;
39 const uint8_t* ii;
40 const void* *const dict = (const void**) wrkmem;
41
42 op = out;
43 ip = in;
44 ii = ip;
45
46 ip += 4;
47 for (;;) {
48 register const uint8_t* m_pos;
49 unsigned m_off;
50 unsigned m_len;
51 unsigned dindex;
52
53 D_INDEX1(dindex,ip);
54 GINDEX(m_pos,m_off,dict,dindex,in);
55 if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET))
56 goto literal;
57#if 1
58 if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
59 goto try_match;
60 D_INDEX2(dindex,ip);
61#endif
62 GINDEX(m_pos,m_off,dict,dindex,in);
63 if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET))
64 goto literal;
65 if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
66 goto try_match;
67 goto literal;
68
69 try_match:
70#if 1 && defined(LZO_UNALIGNED_OK_2)
71 if (* (const lzo_ushortp) m_pos != * (const lzo_ushortp) ip)
72#else
73 if (m_pos[0] != ip[0] || m_pos[1] != ip[1])
74#endif
75 {
76 } else {
77 if (m_pos[2] == ip[2]) {
78#if 0
79 if (m_off <= M2_MAX_OFFSET)
80 goto match;
81 if (lit <= 3)
82 goto match;
83 if (lit == 3) { /* better compression, but slower */
84 assert(op - 2 > out); op[-2] |= (uint8_t)(3);
85 *op++ = *ii++; *op++ = *ii++; *op++ = *ii++;
86 goto code_match;
87 }
88 if (m_pos[3] == ip[3])
89#endif
90 goto match;
91 }
92 else {
93 /* still need a better way for finding M1 matches */
94#if 0
95 /* a M1 match */
96#if 0
97 if (m_off <= M1_MAX_OFFSET && lit > 0 && lit <= 3)
98#else
99 if (m_off <= M1_MAX_OFFSET && lit == 3)
100#endif
101 {
102 register unsigned t;
103
104 t = lit;
105 assert(op - 2 > out); op[-2] |= (uint8_t)(t);
106 do *op++ = *ii++; while (--t > 0);
107 assert(ii == ip);
108 m_off -= 1;
109 *op++ = (uint8_t)(M1_MARKER | ((m_off & 3) << 2));
110 *op++ = (uint8_t)(m_off >> 2);
111 ip += 2;
112 goto match_done;
113 }
114#endif
115 }
116 }
117
118 /* a literal */
119 literal:
120 UPDATE_I(dict, 0, dindex, ip, in);
121 ++ip;
122 if (ip >= ip_end)
123 break;
124 continue;
125
126 /* a match */
127match:
128 UPDATE_I(dict, 0, dindex, ip, in);
129 /* store current literal run */
130 if (pd(ip, ii) > 0) {
131 register unsigned t = pd(ip, ii);
132
133 if (t <= 3) {
134 assert(op - 2 > out);
135 op[-2] |= (uint8_t)(t);
136 }
137 else if (t <= 18)
138 *op++ = (uint8_t)(t - 3);
139 else {
140 register unsigned tt = t - 18;
141
142 *op++ = 0;
143 while (tt > 255) {
144 tt -= 255;
145 *op++ = 0;
146 }
147 assert(tt > 0);
148 *op++ = (uint8_t)(tt);
149 }
150 do *op++ = *ii++; while (--t > 0);
151 }
152
153 /* code the match */
154 assert(ii == ip);
155 ip += 3;
156 if (m_pos[3] != *ip++ || m_pos[4] != *ip++ || m_pos[5] != *ip++
157 || m_pos[6] != *ip++ || m_pos[7] != *ip++ || m_pos[8] != *ip++
158#ifdef LZO1Y
159 || m_pos[ 9] != *ip++ || m_pos[10] != *ip++ || m_pos[11] != *ip++
160 || m_pos[12] != *ip++ || m_pos[13] != *ip++ || m_pos[14] != *ip++
161#endif
162 ) {
163 --ip;
164 m_len = pd(ip, ii);
165 assert(m_len >= 3);
166 assert(m_len <= M2_MAX_LEN);
167
168 if (m_off <= M2_MAX_OFFSET) {
169 m_off -= 1;
170#if defined(LZO1X)
171 *op++ = (uint8_t)(((m_len - 1) << 5) | ((m_off & 7) << 2));
172 *op++ = (uint8_t)(m_off >> 3);
173#elif defined(LZO1Y)
174 *op++ = (uint8_t)(((m_len + 1) << 4) | ((m_off & 3) << 2));
175 *op++ = (uint8_t)(m_off >> 2);
176#endif
177 }
178 else if (m_off <= M3_MAX_OFFSET) {
179 m_off -= 1;
180 *op++ = (uint8_t)(M3_MARKER | (m_len - 2));
181 goto m3_m4_offset;
182 } else {
183#if defined(LZO1X)
184 m_off -= 0x4000;
185 assert(m_off > 0);
186 assert(m_off <= 0x7fff);
187 *op++ = (uint8_t)(M4_MARKER | ((m_off & 0x4000) >> 11) | (m_len - 2));
188 goto m3_m4_offset;
189#elif defined(LZO1Y)
190 goto m4_match;
191#endif
192 }
193 }
194 else {
195 {
196 const uint8_t* end = in_end;
197 const uint8_t* m = m_pos + M2_MAX_LEN + 1;
198 while (ip < end && *m == *ip)
199 m++, ip++;
200 m_len = pd(ip, ii);
201 }
202 assert(m_len > M2_MAX_LEN);
203
204 if (m_off <= M3_MAX_OFFSET) {
205 m_off -= 1;
206 if (m_len <= 33)
207 *op++ = (uint8_t)(M3_MARKER | (m_len - 2));
208 else {
209 m_len -= 33;
210 *op++ = M3_MARKER | 0;
211 goto m3_m4_len;
212 }
213 } else {
214#if defined(LZO1Y)
215 m4_match:
216#endif
217 m_off -= 0x4000;
218 assert(m_off > 0);
219 assert(m_off <= 0x7fff);
220 if (m_len <= M4_MAX_LEN)
221 *op++ = (uint8_t)(M4_MARKER | ((m_off & 0x4000) >> 11) | (m_len - 2));
222 else {
223 m_len -= M4_MAX_LEN;
224 *op++ = (uint8_t)(M4_MARKER | ((m_off & 0x4000) >> 11));
225 m3_m4_len:
226 while (m_len > 255) {
227 m_len -= 255;
228 *op++ = 0;
229 }
230 assert(m_len > 0);
231 *op++ = (uint8_t)(m_len);
232 }
233 }
234 m3_m4_offset:
235 *op++ = (uint8_t)((m_off & 63) << 2);
236 *op++ = (uint8_t)(m_off >> 6);
237 }
238#if 0
239 match_done:
240#endif
241 ii = ip;
242 if (ip >= ip_end)
243 break;
244 }
245
246 *out_len = pd(op, out);
247 return pd(in_end, ii);
248}
249
250/***********************************************************************
251// public entry point
252************************************************************************/
253int DO_COMPRESS(const uint8_t* in, unsigned in_len,
254 uint8_t* out, unsigned* out_len,
255 void* wrkmem)
256{
257 uint8_t* op = out;
258 unsigned t;
259
260 if (in_len <= M2_MAX_LEN + 5)
261 t = in_len;
262 else {
263 t = do_compress(in,in_len,op,out_len,wrkmem);
264 op += *out_len;
265 }
266
267 if (t > 0) {
268 const uint8_t* ii = in + in_len - t;
269
270 if (op == out && t <= 238)
271 *op++ = (uint8_t)(17 + t);
272 else if (t <= 3)
273 op[-2] |= (uint8_t)(t);
274 else if (t <= 18)
275 *op++ = (uint8_t)(t - 3);
276 else {
277 unsigned tt = t - 18;
278
279 *op++ = 0;
280 while (tt > 255) {
281 tt -= 255;
282 *op++ = 0;
283 }
284 assert(tt > 0);
285 *op++ = (uint8_t)(tt);
286 }
287 do *op++ = *ii++; while (--t > 0);
288 }
289
290 *op++ = M4_MARKER | 1;
291 *op++ = 0;
292 *op++ = 0;
293
294 *out_len = pd(op, out);
295 return 0; /*LZO_E_OK*/
296}
diff --git a/archival/lzo1x_d.c b/archival/lzo1x_d.c
new file mode 100644
index 000000000..348a85510
--- /dev/null
+++ b/archival/lzo1x_d.c
@@ -0,0 +1,420 @@
1/* implementation of the LZO1X decompression algorithm
2
3 This file is part of the LZO real-time data compression library.
4
5 Copyright (C) 1996..2008 Markus Franz Xaver Johannes Oberhumer
6 All Rights Reserved.
7
8 Markus F.X.J. Oberhumer <markus@oberhumer.com>
9 http://www.oberhumer.com/opensource/lzo/
10
11 The LZO library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2 of
14 the License, or (at your option) any later version.
15
16 The LZO library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with the LZO library; see the file COPYING.
23 If not, write to the Free Software Foundation, Inc.,
24 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 */
26#include "libbb.h"
27#include "liblzo.h"
28
29/***********************************************************************
30// decompress a block of data.
31************************************************************************/
32/* safe decompression with overrun testing */
33int lzo1x_decompress_safe(const uint8_t* in, unsigned in_len,
34 uint8_t* out, unsigned* out_len,
35 void* wrkmem UNUSED_PARAM)
36{
37 register uint8_t* op;
38 register const uint8_t* ip;
39 register unsigned t;
40#if defined(COPY_DICT)
41 unsigned m_off;
42 const uint8_t* dict_end;
43#else
44 register const uint8_t* m_pos = NULL; /* possibly not needed */
45#endif
46 const uint8_t* const ip_end = in + in_len;
47#if defined(HAVE_ANY_OP)
48 uint8_t* const op_end = out + *out_len;
49#endif
50#if defined(LZO1Z)
51 unsigned last_m_off = 0;
52#endif
53
54// LZO_UNUSED(wrkmem);
55
56#if defined(COPY_DICT)
57 if (dict) {
58 if (dict_len > M4_MAX_OFFSET) {
59 dict += dict_len - M4_MAX_OFFSET;
60 dict_len = M4_MAX_OFFSET;
61 }
62 dict_end = dict + dict_len;
63 } else {
64 dict_len = 0;
65 dict_end = NULL;
66 }
67#endif /* COPY_DICT */
68
69 *out_len = 0;
70
71 op = out;
72 ip = in;
73
74 if (*ip > 17) {
75 t = *ip++ - 17;
76 if (t < 4)
77 goto match_next;
78 assert(t > 0); NEED_OP(t); NEED_IP(t+1);
79 do *op++ = *ip++; while (--t > 0);
80 goto first_literal_run;
81 }
82
83 while (TEST_IP && TEST_OP) {
84 t = *ip++;
85 if (t >= 16)
86 goto match;
87 /* a literal run */
88 if (t == 0) {
89 NEED_IP(1);
90 while (*ip == 0) {
91 t += 255;
92 ip++;
93 NEED_IP(1);
94 }
95 t += 15 + *ip++;
96 }
97 /* copy literals */
98 assert(t > 0);
99 NEED_OP(t+3);
100 NEED_IP(t+4);
101#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
102# if !defined(LZO_UNALIGNED_OK_4)
103 if (PTR_ALIGNED2_4(op, ip))
104# endif
105 {
106 COPY4(op, ip);
107 op += 4;
108 ip += 4;
109 if (--t > 0) {
110 if (t >= 4) {
111 do {
112 COPY4(op, ip);
113 op += 4;
114 ip += 4;
115 t -= 4;
116 } while (t >= 4);
117 if (t > 0)
118 do *op++ = *ip++; while (--t > 0);
119 } else {
120 do *op++ = *ip++; while (--t > 0);
121 }
122 }
123 }
124# if !defined(LZO_UNALIGNED_OK_4)
125 else
126# endif
127#endif
128#if !defined(LZO_UNALIGNED_OK_4)
129 {
130 *op++ = *ip++;
131 *op++ = *ip++;
132 *op++ = *ip++;
133 do *op++ = *ip++; while (--t > 0);
134 }
135#endif
136
137 first_literal_run:
138 t = *ip++;
139 if (t >= 16)
140 goto match;
141#if defined(COPY_DICT)
142#if defined(LZO1Z)
143 m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
144 last_m_off = m_off;
145#else
146 m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2);
147#endif
148 NEED_OP(3);
149 t = 3; COPY_DICT(t,m_off)
150#else /* !COPY_DICT */
151#if defined(LZO1Z)
152 t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
153 m_pos = op - t;
154 last_m_off = t;
155#else
156 m_pos = op - (1 + M2_MAX_OFFSET);
157 m_pos -= t >> 2;
158 m_pos -= *ip++ << 2;
159#endif
160 TEST_LB(m_pos); NEED_OP(3);
161 *op++ = *m_pos++;
162 *op++ = *m_pos++;
163 *op++ = *m_pos;
164#endif /* COPY_DICT */
165 goto match_done;
166
167 /* handle matches */
168 do {
169 match:
170 if (t >= 64) { /* a M2 match */
171#if defined(COPY_DICT)
172#if defined(LZO1X)
173 m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3);
174 t = (t >> 5) - 1;
175#elif defined(LZO1Y)
176 m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2);
177 t = (t >> 4) - 3;
178#elif defined(LZO1Z)
179 m_off = t & 0x1f;
180 if (m_off >= 0x1c)
181 m_off = last_m_off;
182 else {
183 m_off = 1 + (m_off << 6) + (*ip++ >> 2);
184 last_m_off = m_off;
185 }
186 t = (t >> 5) - 1;
187#endif
188#else /* !COPY_DICT */
189#if defined(LZO1X)
190 m_pos = op - 1;
191 m_pos -= (t >> 2) & 7;
192 m_pos -= *ip++ << 3;
193 t = (t >> 5) - 1;
194#elif defined(LZO1Y)
195 m_pos = op - 1;
196 m_pos -= (t >> 2) & 3;
197 m_pos -= *ip++ << 2;
198 t = (t >> 4) - 3;
199#elif defined(LZO1Z)
200 {
201 unsigned off = t & 0x1f;
202 m_pos = op;
203 if (off >= 0x1c) {
204 assert(last_m_off > 0);
205 m_pos -= last_m_off;
206 } else {
207 off = 1 + (off << 6) + (*ip++ >> 2);
208 m_pos -= off;
209 last_m_off = off;
210 }
211 }
212 t = (t >> 5) - 1;
213#endif
214 TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
215 goto copy_match;
216#endif /* COPY_DICT */
217 }
218 else if (t >= 32) { /* a M3 match */
219 t &= 31;
220 if (t == 0) {
221 NEED_IP(1);
222 while (*ip == 0) {
223 t += 255;
224 ip++;
225 NEED_IP(1);
226 }
227 t += 31 + *ip++;
228 }
229#if defined(COPY_DICT)
230#if defined(LZO1Z)
231 m_off = 1 + (ip[0] << 6) + (ip[1] >> 2);
232 last_m_off = m_off;
233#else
234 m_off = 1 + (ip[0] >> 2) + (ip[1] << 6);
235#endif
236#else /* !COPY_DICT */
237#if defined(LZO1Z)
238 {
239 unsigned off = 1 + (ip[0] << 6) + (ip[1] >> 2);
240 m_pos = op - off;
241 last_m_off = off;
242 }
243#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
244 m_pos = op - 1;
245 m_pos -= (* (const lzo_ushortp) ip) >> 2;
246#else
247 m_pos = op - 1;
248 m_pos -= (ip[0] >> 2) + (ip[1] << 6);
249#endif
250#endif /* COPY_DICT */
251 ip += 2;
252 }
253 else if (t >= 16) { /* a M4 match */
254#if defined(COPY_DICT)
255 m_off = (t & 8) << 11;
256#else /* !COPY_DICT */
257 m_pos = op;
258 m_pos -= (t & 8) << 11;
259#endif /* COPY_DICT */
260 t &= 7;
261 if (t == 0) {
262 NEED_IP(1);
263 while (*ip == 0) {
264 t += 255;
265 ip++;
266 NEED_IP(1);
267 }
268 t += 7 + *ip++;
269 }
270#if defined(COPY_DICT)
271#if defined(LZO1Z)
272 m_off += (ip[0] << 6) + (ip[1] >> 2);
273#else
274 m_off += (ip[0] >> 2) + (ip[1] << 6);
275#endif
276 ip += 2;
277 if (m_off == 0)
278 goto eof_found;
279 m_off += 0x4000;
280#if defined(LZO1Z)
281 last_m_off = m_off;
282#endif
283#else /* !COPY_DICT */
284#if defined(LZO1Z)
285 m_pos -= (ip[0] << 6) + (ip[1] >> 2);
286#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
287 m_pos -= (* (const lzo_ushortp) ip) >> 2;
288#else
289 m_pos -= (ip[0] >> 2) + (ip[1] << 6);
290#endif
291 ip += 2;
292 if (m_pos == op)
293 goto eof_found;
294 m_pos -= 0x4000;
295#if defined(LZO1Z)
296 last_m_off = pd((const uint8_t*)op, m_pos);
297#endif
298#endif /* COPY_DICT */
299 }
300 else { /* a M1 match */
301#if defined(COPY_DICT)
302#if defined(LZO1Z)
303 m_off = 1 + (t << 6) + (*ip++ >> 2);
304 last_m_off = m_off;
305#else
306 m_off = 1 + (t >> 2) + (*ip++ << 2);
307#endif
308 NEED_OP(2);
309 t = 2; COPY_DICT(t,m_off)
310#else /* !COPY_DICT */
311#if defined(LZO1Z)
312 t = 1 + (t << 6) + (*ip++ >> 2);
313 m_pos = op - t;
314 last_m_off = t;
315#else
316 m_pos = op - 1;
317 m_pos -= t >> 2;
318 m_pos -= *ip++ << 2;
319#endif
320 TEST_LB(m_pos); NEED_OP(2);
321 *op++ = *m_pos++;
322 *op++ = *m_pos;
323#endif /* COPY_DICT */
324 goto match_done;
325 }
326
327 /* copy match */
328#if defined(COPY_DICT)
329
330 NEED_OP(t+3-1);
331 t += 3-1; COPY_DICT(t,m_off)
332
333#else /* !COPY_DICT */
334
335 TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
336#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
337# if !defined(LZO_UNALIGNED_OK_4)
338 if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) {
339 assert((op - m_pos) >= 4); /* both pointers are aligned */
340# else
341 if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) {
342# endif
343 COPY4(op,m_pos);
344 op += 4; m_pos += 4; t -= 4 - (3 - 1);
345 do {
346 COPY4(op,m_pos);
347 op += 4; m_pos += 4; t -= 4;
348 } while (t >= 4);
349 if (t > 0)
350 do *op++ = *m_pos++; while (--t > 0);
351 }
352 else
353#endif
354 {
355 copy_match:
356 *op++ = *m_pos++; *op++ = *m_pos++;
357 do *op++ = *m_pos++; while (--t > 0);
358 }
359
360#endif /* COPY_DICT */
361
362 match_done:
363#if defined(LZO1Z)
364 t = ip[-1] & 3;
365#else
366 t = ip[-2] & 3;
367#endif
368 if (t == 0)
369 break;
370
371 /* copy literals */
372 match_next:
373 assert(t > 0);
374 assert(t < 4);
375 NEED_OP(t);
376 NEED_IP(t+1);
377#if 0
378 do *op++ = *ip++; while (--t > 0);
379#else
380 *op++ = *ip++;
381 if (t > 1) {
382 *op++ = *ip++;
383 if (t > 2)
384 *op++ = *ip++;
385 }
386#endif
387 t = *ip++;
388 } while (TEST_IP && TEST_OP);
389 }
390
391//#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
392 /* no EOF code was found */
393 *out_len = pd(op, out);
394 return LZO_E_EOF_NOT_FOUND;
395//#endif
396
397 eof_found:
398 assert(t == 1);
399 *out_len = pd(op, out);
400 return (ip == ip_end ? LZO_E_OK :
401 (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
402
403//#if defined(HAVE_NEED_IP)
404 input_overrun:
405 *out_len = pd(op, out);
406 return LZO_E_INPUT_OVERRUN;
407//#endif
408
409//#if defined(HAVE_NEED_OP)
410 output_overrun:
411 *out_len = pd(op, out);
412 return LZO_E_OUTPUT_OVERRUN;
413//#endif
414
415//#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
416 lookbehind_overrun:
417 *out_len = pd(op, out);
418 return LZO_E_LOOKBEHIND_OVERRUN;
419//#endif
420}
diff --git a/archival/lzop.c b/archival/lzop.c
new file mode 100644
index 000000000..a30d5e78b
--- /dev/null
+++ b/archival/lzop.c
@@ -0,0 +1,1075 @@
1/*
2 This file is part of the lzop file compressor.
3
4 Copyright (C) 1996..2003 Markus Franz Xaver Johannes Oberhumer
5 All Rights Reserved.
6
7 Markus F.X.J. Oberhumer <markus@oberhumer.com>
8 http://www.oberhumer.com/opensource/lzop/
9
10 lzop and the LZO library are free software; you can redistribute them
11 and/or modify them under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2 of
13 the License, or (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; see the file COPYING.
22 If not, write to the Free Software Foundation, Inc.,
23 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25 "Minimalized" for busybox by Alain Knaff
26*/
27
28#include "libbb.h"
29#include "unarchive.h"
30#include "liblzo_interface.h"
31
32/* lzo-2.03/src/lzo_ptr.h */
33#define pd(a,b) ((unsigned)((a)-(b)))
34
35#define lzo_version() LZO_VERSION
36#define lzo_sizeof_dict_t (sizeof(uint8_t*))
37
38/* lzo-2.03/include/lzo/lzo1x.h */
39#define LZO1X_1_MEM_COMPRESS (16384 * lzo_sizeof_dict_t)
40#define LZO1X_1_15_MEM_COMPRESS (32768 * lzo_sizeof_dict_t)
41#define LZO1X_999_MEM_COMPRESS (14 * 16384 * sizeof(short))
42
43/* lzo-2.03/src/lzo1x_oo.c */
44#define NO_LIT UINT_MAX
45
46/**********************************************************************/
47static void copy2(uint8_t* ip, const uint8_t* m_pos, unsigned off)
48{
49 ip[0] = m_pos[0];
50 if (off == 1)
51 ip[1] = m_pos[0];
52 else
53 ip[1] = m_pos[1];
54}
55
56static void copy3(uint8_t* ip, const uint8_t* m_pos, unsigned off)
57{
58 ip[0] = m_pos[0];
59 if (off == 1) {
60 ip[2] = ip[1] = m_pos[0];
61 }
62 else if (off == 2) {
63 ip[1] = m_pos[1];
64 ip[2] = m_pos[0];
65 }
66 else {
67 ip[1] = m_pos[1];
68 ip[2] = m_pos[2];
69 }
70}
71
72/**********************************************************************/
73// optimize a block of data.
74/**********************************************************************/
75#define TEST_IP (ip < ip_end)
76#define TEST_OP (op <= op_end)
77
78static int lzo1x_optimize(uint8_t *in, unsigned in_len,
79 uint8_t *out, unsigned *out_len,
80 void* wrkmem UNUSED_PARAM)
81{
82 uint8_t* op;
83 uint8_t* ip;
84 unsigned t;
85 uint8_t* m_pos;
86 uint8_t* const ip_end = in + in_len;
87 uint8_t* const op_end = out + *out_len;
88 uint8_t* litp = NULL;
89 unsigned lit = 0;
90 unsigned next_lit = NO_LIT;
91 unsigned nl;
92 unsigned long o_m1_a = 0, o_m1_b = 0, o_m2 = 0, o_m3_a = 0, o_m3_b = 0;
93
94// LZO_UNUSED(wrkmem);
95
96 *out_len = 0;
97
98 op = out;
99 ip = in;
100
101 if (*ip > 17) {
102 t = *ip++ - 17;
103 if (t < 4)
104 goto match_next;
105 goto first_literal_run;
106 }
107
108 while (TEST_IP && TEST_OP) {
109 t = *ip++;
110 if (t >= 16)
111 goto match;
112 /* a literal run */
113 litp = ip - 1;
114 if (t == 0) {
115 t = 15;
116 while (*ip == 0)
117 t += 255, ip++;
118 t += *ip++;
119 }
120 lit = t + 3;
121 /* copy literals */
122 copy_literal_run:
123 *op++ = *ip++;
124 *op++ = *ip++;
125 *op++ = *ip++;
126 first_literal_run:
127 do *op++ = *ip++; while (--t > 0);
128
129 t = *ip++;
130
131 if (t >= 16)
132 goto match;
133#if defined(LZO1X)
134 m_pos = op - 1 - 0x800;
135#elif defined(LZO1Y)
136 m_pos = op - 1 - 0x400;
137#endif
138 m_pos -= t >> 2;
139 m_pos -= *ip++ << 2;
140 *op++ = *m_pos++;
141 *op++ = *m_pos++;
142 *op++ = *m_pos++;
143 lit = 0;
144 goto match_done;
145
146
147 /* handle matches */
148 do {
149 if (t < 16) { /* a M1 match */
150 m_pos = op - 1;
151 m_pos -= t >> 2;
152 m_pos -= *ip++ << 2;
153
154 if (litp == NULL)
155 goto copy_m1;
156
157 nl = ip[-2] & 3;
158 /* test if a match follows */
159 if (nl == 0 && lit == 1 && ip[0] >= 16) {
160 next_lit = nl;
161 /* adjust length of previous short run */
162 lit += 2;
163 *litp = (unsigned char)((*litp & ~3) | lit);
164 /* copy over the 2 literals that replace the match */
165 copy2(ip-2, m_pos, pd(op, m_pos));
166 o_m1_a++;
167 }
168 /* test if a literal run follows */
169 else if (nl == 0 && ip[0] < 16 && ip[0] != 0 &&
170 (lit + 2 + ip[0] < 16))
171 {
172 t = *ip++;
173 /* remove short run */
174 *litp &= ~3;
175 /* copy over the 2 literals that replace the match */
176 copy2(ip-3+1,m_pos,pd(op,m_pos));
177 /* move literals 1 byte ahead */
178 litp += 2;
179 if (lit > 0)
180 memmove(litp+1, litp, lit);
181 /* insert new length of long literal run */
182 lit += 2 + t + 3;
183 *litp = (unsigned char)(lit - 3);
184
185 o_m1_b++;
186 *op++ = *m_pos++; *op++ = *m_pos++;
187 goto copy_literal_run;
188 }
189 copy_m1:
190 *op++ = *m_pos++;
191 *op++ = *m_pos++;
192 } else {
193 match:
194 if (t >= 64) { /* a M2 match */
195 m_pos = op - 1;
196#if defined(LZO1X)
197 m_pos -= (t >> 2) & 7;
198 m_pos -= *ip++ << 3;
199 t = (t >> 5) - 1;
200#elif defined(LZO1Y)
201 m_pos -= (t >> 2) & 3;
202 m_pos -= *ip++ << 2;
203 t = (t >> 4) - 3;
204#endif
205 if (litp == NULL)
206 goto copy_m;
207
208 nl = ip[-2] & 3;
209 /* test if in beetween two long literal runs */
210 if (t == 1 && lit > 3 && nl == 0
211 && ip[0] < 16 && ip[0] != 0 && (lit + 3 + ip[0] < 16)
212 ) {
213 t = *ip++;
214 /* copy over the 3 literals that replace the match */
215 copy3(ip-1-2,m_pos,pd(op,m_pos));
216 /* set new length of previous literal run */
217 lit += 3 + t + 3;
218 *litp = (unsigned char)(lit - 3);
219 o_m2++;
220 *op++ = *m_pos++;
221 *op++ = *m_pos++;
222 *op++ = *m_pos++;
223 goto copy_literal_run;
224 }
225 } else {
226 if (t >= 32) { /* a M3 match */
227 t &= 31;
228 if (t == 0) {
229 t = 31;
230 while (*ip == 0)
231 t += 255, ip++;
232 t += *ip++;
233 }
234 m_pos = op - 1;
235 m_pos -= *ip++ >> 2;
236 m_pos -= *ip++ << 6;
237 } else { /* a M4 match */
238 m_pos = op;
239 m_pos -= (t & 8) << 11;
240 t &= 7;
241 if (t == 0) {
242 t = 7;
243 while (*ip == 0)
244 t += 255, ip++;
245 t += *ip++;
246 }
247 m_pos -= *ip++ >> 2;
248 m_pos -= *ip++ << 6;
249 if (m_pos == op)
250 goto eof_found;
251 m_pos -= 0x4000;
252 }
253 if (litp == NULL)
254 goto copy_m;
255
256 nl = ip[-2] & 3;
257 /* test if in beetween two matches */
258 if (t == 1 && lit == 0 && nl == 0 && ip[0] >= 16) {
259 next_lit = nl;
260 /* make a previous short run */
261 lit += 3;
262 *litp = (unsigned char)((*litp & ~3) | lit);
263 /* copy over the 3 literals that replace the match */
264 copy3(ip-3,m_pos,pd(op,m_pos));
265 o_m3_a++;
266 }
267 /* test if a literal run follows */
268 else if (t == 1 && lit <= 3 && nl == 0
269 && ip[0] < 16 && ip[0] != 0 && (lit + 3 + ip[0] < 16)
270 ) {
271 t = *ip++;
272 /* remove short run */
273 *litp &= ~3;
274 /* copy over the 3 literals that replace the match */
275 copy3(ip-4+1,m_pos,pd(op,m_pos));
276 /* move literals 1 byte ahead */
277 litp += 2;
278 if (lit > 0)
279 memmove(litp+1,litp,lit);
280 /* insert new length of long literal run */
281 lit += 3 + t + 3;
282 *litp = (unsigned char)(lit - 3);
283
284 o_m3_b++;
285 *op++ = *m_pos++;
286 *op++ = *m_pos++;
287 *op++ = *m_pos++;
288 goto copy_literal_run;
289 }
290 }
291 copy_m:
292 *op++ = *m_pos++;
293 *op++ = *m_pos++;
294 do *op++ = *m_pos++; while (--t > 0);
295 }
296
297 match_done:
298 if (next_lit == NO_LIT) {
299 t = ip[-2] & 3;
300 lit = t;
301 litp = ip - 2;
302 }
303 else
304 t = next_lit;
305 next_lit = NO_LIT;
306 if (t == 0)
307 break;
308 /* copy literals */
309 match_next:
310 do *op++ = *ip++; while (--t > 0);
311 t = *ip++;
312 } while (TEST_IP && TEST_OP);
313 }
314
315 /* no EOF code was found */
316 *out_len = pd(op, out);
317 return LZO_E_EOF_NOT_FOUND;
318
319 eof_found:
320// LZO_UNUSED(o_m1_a); LZO_UNUSED(o_m1_b); LZO_UNUSED(o_m2);
321// LZO_UNUSED(o_m3_a); LZO_UNUSED(o_m3_b);
322 *out_len = pd(op, out);
323 return (ip == ip_end ? LZO_E_OK :
324 (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
325}
326
327/**********************************************************************/
328#define F_OS F_OS_UNIX
329#define F_CS F_CS_NATIVE
330
331/**********************************************************************/
332#define ADLER32_INIT_VALUE 1
333#define CRC32_INIT_VALUE 0
334
335/**********************************************************************/
336enum {
337 M_LZO1X_1 = 1,
338 M_LZO1X_1_15 = 2,
339 M_LZO1X_999 = 3,
340};
341
342/**********************************************************************/
343/* header flags */
344#define F_ADLER32_D 0x00000001L
345#define F_ADLER32_C 0x00000002L
346#define F_H_EXTRA_FIELD 0x00000040L
347#define F_H_GMTDIFF 0x00000080L
348#define F_CRC32_D 0x00000100L
349#define F_CRC32_C 0x00000200L
350#define F_H_FILTER 0x00000800L
351#define F_H_CRC32 0x00001000L
352#define F_MASK 0x00003FFFL
353
354/* operating system & file system that created the file [mostly unused] */
355#define F_OS_UNIX 0x03000000L
356#define F_OS_SHIFT 24
357#define F_OS_MASK 0xff000000L
358
359/* character set for file name encoding [mostly unused] */
360#define F_CS_NATIVE 0x00000000L
361#define F_CS_SHIFT 20
362#define F_CS_MASK 0x00f00000L
363
364/* these bits must be zero */
365#define F_RESERVED ((F_MASK | F_OS_MASK | F_CS_MASK) ^ 0xffffffffL)
366
367typedef struct chksum_t {
368 uint32_t f_adler32;
369 uint32_t f_crc32;
370} chksum_t;
371
372typedef struct header_t {
373 unsigned version;
374 unsigned lib_version;
375 unsigned version_needed_to_extract;
376 uint32_t flags;
377 uint32_t mode;
378 uint32_t mtime;
379 uint32_t gmtdiff;
380 uint32_t header_checksum;
381
382 uint32_t extra_field_len;
383 uint32_t extra_field_checksum;
384
385 unsigned char method;
386 unsigned char level;
387
388 /* info */
389 char name[255+1];
390} header_t;
391
392struct globals {
393 const uint32_t *lzo_crc32_table;
394 chksum_t chksum_in;
395 chksum_t chksum_out;
396};
397#define G (*(struct globals*)&bb_common_bufsiz1)
398#define INIT_G() do { } while (0)
399//#define G (*ptr_to_globals)
400//#define INIT_G() do {
401// SET_PTR_TO_GLOBALS(xzalloc(sizeof(G)));
402//} while (0)
403
404
405/**********************************************************************/
406#define LZOP_VERSION 0x1010
407//#define LZOP_VERSION_STRING "1.01"
408//#define LZOP_VERSION_DATE "Apr 27th 2003"
409
410#define OPTION_STRING "cfvdt123456789CF"
411
412enum {
413 OPT_STDOUT = (1 << 0),
414 OPT_FORCE = (1 << 1),
415 OPT_VERBOSE = (1 << 2),
416 OPT_DECOMPRESS = (1 << 3),
417 OPT_TEST = (1 << 4),
418 OPT_1 = (1 << 5),
419 OPT_2 = (1 << 6),
420 OPT_3 = (1 << 7),
421 OPT_4 = (1 << 8),
422 OPT_5 = (1 << 9),
423 OPT_6 = (1 << 10),
424 OPT_789 = (7 << 11),
425 OPT_7 = (1 << 11),
426 OPT_8 = (1 << 12),
427 OPT_C = (1 << 14),
428 OPT_F = (1 << 15),
429};
430
431/**********************************************************************/
432// adler32 checksum
433// adapted from free code by Mark Adler <madler@alumni.caltech.edu>
434// see http://www.zlib.org/
435/**********************************************************************/
436static FAST_FUNC uint32_t
437lzo_adler32(uint32_t adler, const uint8_t* buf, unsigned len)
438{
439 enum {
440 LZO_BASE = 65521, /* largest prime smaller than 65536 */
441 /* NMAX is the largest n such that
442 * 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
443 LZO_NMAX = 5552,
444 };
445 uint32_t s1 = adler & 0xffff;
446 uint32_t s2 = (adler >> 16) & 0xffff;
447 unsigned k;
448
449 if (buf == NULL)
450 return 1;
451
452 while (len > 0) {
453 k = len < LZO_NMAX ? (unsigned) len : LZO_NMAX;
454 len -= k;
455 if (k != 0) do {
456 s1 += *buf++;
457 s2 += s1;
458 } while (--k > 0);
459 s1 %= LZO_BASE;
460 s2 %= LZO_BASE;
461 }
462 return (s2 << 16) | s1;
463}
464
465static FAST_FUNC uint32_t
466lzo_crc32(uint32_t c, const uint8_t* buf, unsigned len)
467{
468 uint32_t crc;
469
470 if (buf == NULL)
471 return 0;
472
473 crc = ~c;
474 if (len != 0) do {
475 crc = G.lzo_crc32_table[((int)crc ^ *buf) & 0xff] ^ (crc >> 8);
476 buf += 1;
477 len -= 1;
478 } while (len > 0);
479
480 return ~crc;
481}
482
483/**********************************************************************/
484static void init_chksum(chksum_t *ct)
485{
486 ct->f_adler32 = ADLER32_INIT_VALUE;
487 ct->f_crc32 = CRC32_INIT_VALUE;
488}
489
490static void add_bytes_to_chksum(chksum_t *ct, const void* buf, int cnt)
491{
492 /* We need to handle the two checksums at once, because at the
493 * beginning of the header, we don't know yet which one we'll
494 * eventually need */
495 ct->f_adler32 = lzo_adler32(ct->f_adler32, (const uint8_t*)buf, cnt);
496 ct->f_crc32 = lzo_crc32(ct->f_crc32, (const uint8_t*)buf, cnt);
497}
498
499static uint32_t chksum_getresult(chksum_t *ct, const header_t *h)
500{
501 return (h->flags & F_H_CRC32) ? ct->f_crc32 : ct->f_adler32;
502}
503
504/**********************************************************************/
505static uint32_t read32(void)
506{
507 uint32_t v;
508 xread(0, &v, 4);
509 return ntohl(v);
510}
511
512static void write32(uint32_t v)
513{
514 v = htonl(v);
515 xwrite(1, &v, 4);
516}
517
518static void f_write(const void* buf, int cnt)
519{
520 xwrite(1, buf, cnt);
521 add_bytes_to_chksum(&G.chksum_out, buf, cnt);
522}
523
524static void f_read(void* buf, int cnt)
525{
526 xread(0, buf, cnt);
527 add_bytes_to_chksum(&G.chksum_in, buf, cnt);
528}
529
530static int f_read8(void)
531{
532 uint8_t v;
533 f_read(&v, 1);
534 return v;
535}
536
537static void f_write8(uint8_t v)
538{
539 f_write(&v, 1);
540}
541
542static unsigned f_read16(void)
543{
544 uint16_t v;
545 f_read(&v, 2);
546 return ntohs(v);
547}
548
549static void f_write16(uint16_t v)
550{
551 v = htons(v);
552 f_write(&v, 2);
553}
554
555static uint32_t f_read32(void)
556{
557 uint32_t v;
558 f_read(&v, 4);
559 return ntohl(v);
560}
561
562static void f_write32(uint32_t v)
563{
564 v = htonl(v);
565 f_write(&v, 4);
566}
567
568/**********************************************************************/
569static int lzo_get_method(header_t *h)
570{
571 /* check method */
572 if (h->method == M_LZO1X_1) {
573 if (h->level == 0)
574 h->level = 3;
575 } else if (h->method == M_LZO1X_1_15) {
576 if (h->level == 0)
577 h->level = 1;
578 } else if (h->method == M_LZO1X_999) {
579 if (h->level == 0)
580 h->level = 9;
581 } else
582 return -1; /* not a LZO method */
583
584 /* check compression level */
585 if (h->level < 1 || h->level > 9)
586 return 15;
587
588 return 0;
589}
590
591/**********************************************************************/
592#define LZO_BLOCK_SIZE (256 * 1024l)
593#define MAX_BLOCK_SIZE (64 * 1024l * 1024l) /* DO NOT CHANGE */
594
595/* LZO may expand uncompressible data by a small amount */
596#define MAX_COMPRESSED_SIZE(x) ((x) + (x) / 16 + 64 + 3)
597
598/**********************************************************************/
599// compress a file
600/**********************************************************************/
601static smallint lzo_compress(const header_t *h)
602{
603 unsigned block_size = LZO_BLOCK_SIZE;
604 int r = 0; /* LZO_E_OK */
605 uint8_t *const b1 = xzalloc(block_size);
606 uint8_t *const b2 = xzalloc(MAX_COMPRESSED_SIZE(block_size));
607 unsigned src_len = 0, dst_len = 0;
608 uint32_t d_adler32 = ADLER32_INIT_VALUE;
609 uint32_t d_crc32 = CRC32_INIT_VALUE;
610 int l;
611 smallint ok = 1;
612 uint8_t *wrk_mem = NULL;
613
614 if (h->method == M_LZO1X_1)
615 wrk_mem = xzalloc(LZO1X_1_MEM_COMPRESS);
616 else if (h->method == M_LZO1X_1_15)
617 wrk_mem = xzalloc(LZO1X_1_15_MEM_COMPRESS);
618 else if (h->method == M_LZO1X_999)
619 wrk_mem = xzalloc(LZO1X_999_MEM_COMPRESS);
620
621 for (;;) {
622 /* read a block */
623 l = full_read(0, b1, block_size);
624 src_len = (l > 0 ? l : 0);
625
626 /* write uncompressed block size */
627 write32(src_len);
628
629 /* exit if last block */
630 if (src_len == 0)
631 break;
632
633 /* compute checksum of uncompressed block */
634 if (h->flags & F_ADLER32_D)
635 d_adler32 = lzo_adler32(ADLER32_INIT_VALUE, b1, src_len);
636 if (h->flags & F_CRC32_D)
637 d_crc32 = lzo_crc32(CRC32_INIT_VALUE, b1, src_len);
638
639 /* compress */
640 if (h->method == M_LZO1X_1)
641 r = lzo1x_1_compress(b1, src_len, b2, &dst_len, wrk_mem);
642 else if (h->method == M_LZO1X_1_15)
643 r = lzo1x_1_15_compress(b1, src_len, b2, &dst_len, wrk_mem);
644#if ENABLE_LZOP_COMPR_HIGH
645 else if (h->method == M_LZO1X_999)
646 r = lzo1x_999_compress_level(b1, src_len, b2, &dst_len,
647 wrk_mem, h->level);
648#endif
649 else
650 bb_error_msg_and_die("internal error");
651
652 if (r != 0) /* not LZO_E_OK */
653 bb_error_msg_and_die("internal error - compression failed");
654
655 /* write compressed block size */
656 if (dst_len < src_len) {
657 /* optimize */
658 if (h->method == M_LZO1X_999) {
659 unsigned new_len = src_len;
660 r = lzo1x_optimize(b2, dst_len, b1, &new_len, NULL);
661 if (r != 0 /*LZO_E_OK*/ || new_len != src_len)
662 bb_error_msg_and_die("internal error - optimization failed");
663 }
664 write32(dst_len);
665 } else {
666 /* data actually expanded => store data uncompressed */
667 write32(src_len);
668 }
669
670 /* write checksum of uncompressed block */
671 if (h->flags & F_ADLER32_D)
672 write32(d_adler32);
673 if (h->flags & F_CRC32_D)
674 write32(d_crc32);
675
676 if (dst_len < src_len) {
677 /* write checksum of compressed block */
678 if (h->flags & F_ADLER32_C)
679 write32(lzo_adler32(ADLER32_INIT_VALUE, b2,
680 dst_len));
681 if (h->flags & F_CRC32_C)
682 write32(lzo_crc32(CRC32_INIT_VALUE, b2, dst_len));
683 /* write compressed block data */
684 xwrite(1, b2, dst_len);
685 } else {
686 /* write uncompressed block data */
687 xwrite(1, b1, src_len);
688 }
689 }
690
691 free(wrk_mem);
692 free(b1);
693 free(b2);
694 return ok;
695}
696
697static void lzo_check(uint32_t FAST_FUNC (*fn)(uint32_t, const uint8_t*, unsigned),
698 uint32_t ref, uint32_t init,
699 uint8_t* buf, unsigned len)
700{
701 uint32_t c = fn(init, buf, len);
702 if (c != ref)
703 bb_error_msg_and_die("checksum error");
704}
705
706/**********************************************************************/
707// decompress a file
708/**********************************************************************/
709static smallint lzo_decompress(const header_t *h)
710{
711 unsigned block_size = LZO_BLOCK_SIZE;
712 int r;
713 uint32_t src_len, dst_len;
714 uint32_t c_adler32 = ADLER32_INIT_VALUE;
715 uint32_t d_adler32 = ADLER32_INIT_VALUE;
716 uint32_t c_crc32 = CRC32_INIT_VALUE, d_crc32 = CRC32_INIT_VALUE;
717 smallint ok = 1;
718 uint8_t *b1;
719 uint32_t mcs_block_size = MAX_COMPRESSED_SIZE(block_size);
720 uint8_t *b2 = NULL;
721
722 for (;;) {
723 uint8_t *dst;
724
725 /* read uncompressed block size */
726 dst_len = read32();
727
728 /* exit if last block */
729 if (dst_len == 0)
730 break;
731
732 /* error if split file */
733 if (dst_len == 0xffffffffL)
734 /* should not happen - not yet implemented */
735 bb_error_msg_and_die("this file is a split lzop file");
736
737 if (dst_len > MAX_BLOCK_SIZE)
738 bb_error_msg_and_die("lzop file corrupted");
739
740 /* read compressed block size */
741 src_len = read32();
742 if (src_len <= 0 || src_len > dst_len)
743 bb_error_msg_and_die("lzop file corrupted");
744
745 if (dst_len > block_size) {
746 if (b2) {
747//FIXME!
748 b2 = NULL;
749 free(b2);
750 }
751 block_size = dst_len;
752 mcs_block_size = MAX_COMPRESSED_SIZE(block_size);
753 }
754
755 /* read checksum of uncompressed block */
756 if (h->flags & F_ADLER32_D)
757 d_adler32 = read32();
758 if (h->flags & F_CRC32_D)
759 d_crc32 = read32();
760
761 /* read checksum of compressed block */
762 if (src_len < dst_len) {
763 if (h->flags & F_ADLER32_C)
764 c_adler32 = read32();
765 if (h->flags & F_CRC32_C)
766 c_crc32 = read32();
767 }
768
769 if (b2 == NULL)
770 b2 = xzalloc(mcs_block_size);
771 /* read the block into the end of our buffer */
772 b1 = b2 + mcs_block_size - src_len;
773 xread(0, b1, src_len);
774
775 if (src_len < dst_len) {
776 unsigned d = dst_len;
777
778 if (!(option_mask32 & OPT_F)) {
779 /* verify checksum of compressed block */
780 if (h->flags & F_ADLER32_C)
781 lzo_check(lzo_adler32, c_adler32,
782 ADLER32_INIT_VALUE,
783 b1, src_len);
784 if (h->flags & F_CRC32_C)
785 lzo_check(lzo_crc32, c_crc32,
786 CRC32_INIT_VALUE,
787 b1, src_len);
788 }
789
790 /* decompress */
791// if (option_mask32 & OPT_F)
792// r = lzo1x_decompress(b1, src_len, b2, &d, NULL);
793// else
794 r = lzo1x_decompress_safe(b1, src_len, b2, &d, NULL);
795
796 if (r != 0 /*LZO_E_OK*/ || dst_len != d) {
797 bb_error_msg_and_die("corrupted compressed data");
798 }
799 dst = b2;
800 } else {
801 /* "stored" block => no decompression */
802 dst = b1;
803 }
804
805 if (!(option_mask32 & OPT_F)) {
806 /* verify checksum of uncompressed block */
807 if (h->flags & F_ADLER32_D)
808 lzo_check(lzo_adler32, d_adler32, ADLER32_INIT_VALUE,
809 dst, dst_len);
810 if (h->flags & F_CRC32_D)
811 lzo_check(lzo_crc32, d_crc32, CRC32_INIT_VALUE,
812 dst, dst_len);
813 }
814
815 /* write uncompressed block data */
816 xwrite(1, dst, dst_len);
817 }
818
819 free(b2);
820 return ok;
821}
822
823/**********************************************************************/
824// lzop file signature (shamelessly borrowed from PNG)
825/**********************************************************************/
826/*
827 * The first nine bytes of a lzop file always contain the following values:
828 *
829 * 0 1 2 3 4 5 6 7 8
830 * --- --- --- --- --- --- --- --- ---
831 * (hex) 89 4c 5a 4f 00 0d 0a 1a 0a
832 * (decimal) 137 76 90 79 0 13 10 26 10
833 * (C notation - ASCII) \211 L Z O \0 \r \n \032 \n
834 */
835
836/* (vda) comparison with lzop v1.02rc1 ("lzop -1 <FILE" cmd):
837 * Only slight differences in header:
838 * -00000000 89 4c 5a 4f 00 0d 0a 1a 0a 10 20 20 20 09 40 02
839 * +00000000 89 4c 5a 4f 00 0d 0a 1a 0a 10 10 20 30 09 40 02
840 * ^^^^^ ^^^^^
841 * version lib_version
842 * -00000010 01 03 00 00 0d 00 00 81 a4 49 f7 a6 3f 00 00 00
843 * +00000010 01 03 00 00 01 00 00 00 00 00 00 00 00 00 00 00
844 * ^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^
845 * flags mode mtime
846 * -00000020 00 00 2d 67 04 17 00 04 00 00 00 03 ed ec 9d 6d
847 * +00000020 00 00 10 5f 00 c1 00 04 00 00 00 03 ed ec 9d 6d
848 * ^^^^^^^^^^^
849 * chksum_out
850 * The rest is identical.
851*/
852static const unsigned char lzop_magic[9] = {
853 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a
854};
855
856/* This coding is derived from Alexander Lehmann's pngcheck code. */
857static void check_magic(void)
858{
859 unsigned char magic[sizeof(lzop_magic)];
860 xread(0, magic, sizeof(magic));
861 if (memcmp(magic, lzop_magic, sizeof(lzop_magic)) != 0)
862 bb_error_msg_and_die("bad magic number");
863}
864
865/**********************************************************************/
866// lzop file header
867/**********************************************************************/
868static void write_header(const header_t *h)
869{
870 int l;
871
872 xwrite(1, lzop_magic, sizeof(lzop_magic));
873
874 init_chksum(&G.chksum_out);
875
876 f_write16(h->version);
877 f_write16(h->lib_version);
878 f_write16(h->version_needed_to_extract);
879 f_write8(h->method);
880 f_write8(h->level);
881 f_write32(h->flags);
882 f_write32(h->mode);
883 f_write32(h->mtime);
884 f_write32(h->gmtdiff);
885
886 l = (int) strlen(h->name);
887 f_write8(l);
888 if (l)
889 f_write(h->name, l);
890
891 f_write32(chksum_getresult(&G.chksum_out, h));
892}
893
894static int read_header(header_t *h)
895{
896 int r;
897 int l;
898 uint32_t checksum;
899
900 memset(h, 0, sizeof(*h));
901 h->version_needed_to_extract = 0x0900; /* first lzop version */
902 h->level = 0;
903
904 init_chksum(&G.chksum_in);
905
906 h->version = f_read16();
907 if (h->version < 0x0900)
908 return 3;
909 h->lib_version = f_read16();
910 if (h->version >= 0x0940) {
911 h->version_needed_to_extract = f_read16();
912 if (h->version_needed_to_extract > LZOP_VERSION)
913 return 16;
914 if (h->version_needed_to_extract < 0x0900)
915 return 3;
916 }
917 h->method = f_read8();
918 if (h->version >= 0x0940)
919 h->level = f_read8();
920 h->flags = f_read32();
921 if (h->flags & F_H_FILTER)
922 return 16; /* filter not supported */
923 h->mode = f_read32();
924 h->mtime = f_read32();
925 if (h->version >= 0x0940)
926 h->gmtdiff = f_read32();
927
928 l = f_read8();
929 if (l > 0)
930 f_read(h->name, l);
931 h->name[l] = 0;
932
933 checksum = chksum_getresult(&G.chksum_in, h);
934 h->header_checksum = f_read32();
935 if (h->header_checksum != checksum)
936 return 2;
937
938 if (h->method <= 0)
939 return 14;
940 r = lzo_get_method(h);
941 if (r != 0)
942 return r;
943
944 /* check reserved flags */
945 if (h->flags & F_RESERVED)
946 return -13;
947
948 /* skip extra field [not used yet] */
949 if (h->flags & F_H_EXTRA_FIELD) {
950 uint32_t k;
951
952 /* note: the checksum also covers the length */
953 init_chksum(&G.chksum_in);
954 h->extra_field_len = f_read32();
955 for (k = 0; k < h->extra_field_len; k++)
956 f_read8();
957 checksum = chksum_getresult(&G.chksum_in, h);
958 h->extra_field_checksum = f_read32();
959 if (h->extra_field_checksum != checksum)
960 return 3;
961 }
962
963 return 0;
964}
965
966static void p_header(header_t *h)
967{
968 int r;
969
970 r = read_header(h);
971 if (r == 0)
972 return;
973 bb_error_msg_and_die("header_error %d", r);
974}
975
976/**********************************************************************/
977// compress
978/**********************************************************************/
979static void lzo_set_method(header_t *h)
980{
981 int level = 1;
982
983 if (option_mask32 & OPT_1) {
984 h->method = M_LZO1X_1_15;
985 } else if (option_mask32 & OPT_789) {
986#if ENABLE_LZOP_COMPR_HIGH
987 h->method = M_LZO1X_999;
988 if (option_mask32 & OPT_7)
989 level = 7;
990 else if (option_mask32 & OPT_8)
991 level = 8;
992 else
993 level = 9;
994#else
995 bb_error_msg_and_die("high compression not compiled in");
996#endif
997 } else { /* levels 2..6 or none (defaults to level 3) */
998 h->method = M_LZO1X_1;
999 level = 5; /* levels 2-6 are actually the same */
1000 }
1001
1002 h->level = level;
1003}
1004
1005static smallint do_lzo_compress(void)
1006{
1007 header_t header;
1008
1009#define h (&header)
1010 memset(h, 0, sizeof(*h));
1011
1012 lzo_set_method(h);
1013
1014 h->version = (LZOP_VERSION & 0xffff);
1015 h->version_needed_to_extract = 0x0940;
1016 h->lib_version = lzo_version() & 0xffff;
1017
1018 h->flags = (F_OS & F_OS_MASK) | (F_CS & F_CS_MASK);
1019
1020 if (!(option_mask32 & OPT_F) || h->method == M_LZO1X_999) {
1021 h->flags |= F_ADLER32_D;
1022 if (option_mask32 & OPT_C)
1023 h->flags |= F_ADLER32_C;
1024 }
1025 write_header(h);
1026 return lzo_compress(h);
1027#undef h
1028}
1029
1030/**********************************************************************/
1031// decompress
1032/**********************************************************************/
1033static smallint do_lzo_decompress(void)
1034{
1035 header_t header;
1036
1037 check_magic();
1038 p_header(&header);
1039 return lzo_decompress(&header);
1040}
1041
1042static char* make_new_name_lzop(char *filename)
1043{
1044 if (option_mask32 & OPT_DECOMPRESS) {
1045 char *extension = strrchr(filename, '.');
1046 if (!extension || strcmp(extension + 1, "lzo") != 0)
1047 return xasprintf("%s.out", filename);
1048 *extension = '\0';
1049 return filename;
1050 }
1051 return xasprintf("%s.lzo", filename);
1052}
1053
1054static IF_DESKTOP(long long) int pack_lzop(unpack_info_t *info UNUSED_PARAM)
1055{
1056 if (option_mask32 & OPT_DECOMPRESS)
1057 return do_lzo_decompress();
1058 return do_lzo_compress();
1059}
1060
1061int lzop_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1062int lzop_main(int argc UNUSED_PARAM, char **argv)
1063{
1064 getopt32(argv, OPTION_STRING);
1065 argv += optind;
1066 /* lzopcat? */
1067 if (applet_name[4] == 'c')
1068 option_mask32 |= (OPT_STDOUT | OPT_DECOMPRESS);
1069 /* unlzop? */
1070 if (applet_name[0] == 'u')
1071 option_mask32 |= OPT_DECOMPRESS;
1072
1073 G.lzo_crc32_table = crc32_filltable(NULL, 0);
1074 return bbunpack(argv, make_new_name_lzop, pack_lzop);
1075}
diff --git a/include/applets.h b/include/applets.h
index a41f75e31..359440def 100644
--- a/include/applets.h
+++ b/include/applets.h
@@ -242,6 +242,8 @@ IF_LSATTR(APPLET(lsattr, _BB_DIR_BIN, _BB_SUID_NEVER))
242IF_LSMOD(APPLET(lsmod, _BB_DIR_SBIN, _BB_SUID_NEVER)) 242IF_LSMOD(APPLET(lsmod, _BB_DIR_SBIN, _BB_SUID_NEVER))
243IF_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER, modprobe)) 243IF_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER, modprobe))
244IF_UNLZMA(APPLET_ODDNAME(lzmacat, unlzma, _BB_DIR_USR_BIN, _BB_SUID_NEVER, lzmacat)) 244IF_UNLZMA(APPLET_ODDNAME(lzmacat, unlzma, _BB_DIR_USR_BIN, _BB_SUID_NEVER, lzmacat))
245IF_LZOP(APPLET(lzop, _BB_DIR_BIN, _BB_SUID_NEVER))
246IF_LZOP(APPLET_ODDNAME(lzopcat, lzop, _BB_DIR_USR_BIN, _BB_SUID_NEVER, lzopcat))
245IF_MAKEDEVS(APPLET(makedevs, _BB_DIR_SBIN, _BB_SUID_NEVER)) 247IF_MAKEDEVS(APPLET(makedevs, _BB_DIR_SBIN, _BB_SUID_NEVER))
246IF_MAKEMIME(APPLET(makemime, _BB_DIR_BIN, _BB_SUID_NEVER)) 248IF_MAKEMIME(APPLET(makemime, _BB_DIR_BIN, _BB_SUID_NEVER))
247IF_MAN(APPLET(man, _BB_DIR_SBIN, _BB_SUID_NEVER)) 249IF_MAN(APPLET(man, _BB_DIR_SBIN, _BB_SUID_NEVER))
@@ -401,6 +403,7 @@ IF_UNEXPAND(APPLET_ODDNAME(unexpand, expand, _BB_DIR_USR_BIN, _BB_SUID_NEVER, un
401IF_UNIQ(APPLET(uniq, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) 403IF_UNIQ(APPLET(uniq, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
402IF_UNIX2DOS(APPLET_ODDNAME(unix2dos, dos2unix, _BB_DIR_USR_BIN, _BB_SUID_NEVER, unix2dos)) 404IF_UNIX2DOS(APPLET_ODDNAME(unix2dos, dos2unix, _BB_DIR_USR_BIN, _BB_SUID_NEVER, unix2dos))
403IF_UNLZMA(APPLET(unlzma, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) 405IF_UNLZMA(APPLET(unlzma, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
406IF_LZOP(APPLET_ODDNAME(unlzop, lzop, _BB_DIR_USR_BIN, _BB_SUID_NEVER, unlzop))
404IF_UNZIP(APPLET(unzip, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) 407IF_UNZIP(APPLET(unzip, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
405IF_UPTIME(APPLET(uptime, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) 408IF_UPTIME(APPLET(uptime, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
406IF_USLEEP(APPLET_NOFORK(usleep, usleep, _BB_DIR_BIN, _BB_SUID_NEVER, usleep)) 409IF_USLEEP(APPLET_NOFORK(usleep, usleep, _BB_DIR_BIN, _BB_SUID_NEVER, usleep))
diff --git a/include/usage.h b/include/usage.h
index 3fb996126..123462a02 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -202,6 +202,31 @@
202#define busybox_notes_usage \ 202#define busybox_notes_usage \
203 "Hello world!\n" 203 "Hello world!\n"
204 204
205#define lzop_trivial_usage \
206 "[-cfvd123456789CF] [file..]"
207#define lzop_full_usage "\n\n" \
208 " -c Write to standard output" \
209 "\n -f Force" \
210 "\n -v Verbose" \
211 "\n -d Decompress" \
212 "\n -F Don't store or verify checksum" \
213 "\n -C Also write checksum of compressed block" \
214 "\n -1..9 Compression level" \
215
216#define lzopcat_trivial_usage \
217 "[-vCF] [file..]"
218#define lzopcat_full_usage "\n\n" \
219 " -v Verbose" \
220 "\n -F Don't store or verify checksum" \
221
222#define unlzop_trivial_usage \
223 "[-cfvCF] [file..]"
224#define unlzop_full_usage "\n\n" \
225 " -c Write to standard output" \
226 "\n -f Force" \
227 "\n -v Verbose" \
228 "\n -F Don't store or verify checksum" \
229
205#define bzcat_trivial_usage \ 230#define bzcat_trivial_usage \
206 "FILE" 231 "FILE"
207#define bzcat_full_usage "\n\n" \ 232#define bzcat_full_usage "\n\n" \