regularize format of source file headers, no code changes
[oweals/busybox.git] / archival / lzop.c
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 //config:config LZOP
28 //config:       bool "lzop (13 kb)"
29 //config:       default y
30 //config:       help
31 //config:       Lzop compression/decompresion.
32 //config:
33 //config:config UNLZOP
34 //config:       bool "unlzop (13 kb)"
35 //config:       default n  # INCOMPAT: upstream lzop does not provide such tool
36 //config:       help
37 //config:       Lzop decompresion.
38 //config:
39 //config:config LZOPCAT
40 //config:       bool "lzopcat (13 kb)"
41 //config:       default n  # INCOMPAT: upstream lzop does not provide such tool
42 //config:       help
43 //config:       Alias to "lzop -dc".
44 //config:
45 //config:config LZOP_COMPR_HIGH
46 //config:       bool "lzop compression levels 7,8,9 (not very useful)"
47 //config:       default n
48 //config:       depends on LZOP || UNLZOP || LZOPCAT
49 //config:       help
50 //config:       High levels (7,8,9) of lzop compression. These levels
51 //config:       are actually slower than gzip at equivalent compression ratios
52 //config:       and take up 3.2K of code.
53
54 //applet:IF_LZOP(APPLET(lzop, BB_DIR_BIN, BB_SUID_DROP))
55 //                  APPLET_ODDNAME:name     main  location        suid_type     help
56 //applet:IF_UNLZOP( APPLET_ODDNAME(unlzop,  lzop, BB_DIR_USR_BIN, BB_SUID_DROP, unlzop))
57 //applet:IF_LZOPCAT(APPLET_ODDNAME(lzopcat, lzop, BB_DIR_USR_BIN, BB_SUID_DROP, lzopcat))
58
59 //kbuild:lib-$(CONFIG_LZOP) += lzop.o
60 //kbuild:lib-$(CONFIG_UNLZOP) += lzop.o
61 //kbuild:lib-$(CONFIG_LZOPCAT) += lzop.o
62
63 //usage:#define lzop_trivial_usage
64 //usage:       "[-cfUvd123456789CF] [FILE]..."
65 //usage:#define lzop_full_usage "\n\n"
66 //usage:       "        -1..9   Compression level"
67 //usage:     "\n        -d      Decompress"
68 //usage:     "\n        -c      Write to stdout"
69 //usage:     "\n        -f      Force"
70 //usage:     "\n        -U      Delete input files"
71 ///////:     "\n        -k      Keep input files" (default, so why bother documenting?)
72 //usage:     "\n        -v      Verbose"
73 //usage:     "\n        -F      Don't store or verify checksum"
74 //usage:     "\n        -C      Also write checksum of compressed block"
75 //usage:
76 //usage:#define lzopcat_trivial_usage
77 //usage:       "[-vF] [FILE]..."
78 //usage:#define lzopcat_full_usage "\n\n"
79 //usage:       "        -v      Verbose"
80 //usage:     "\n        -F      Don't verify checksum"
81 //usage:
82 //usage:#define unlzop_trivial_usage
83 //usage:       "[-cfkvF] [FILE]..."
84 //usage:#define unlzop_full_usage "\n\n"
85 //usage:       "        -c      Write to stdout"
86 //usage:     "\n        -f      Force"
87 //usage:     "\n        -U      Delete input files"
88 ///////:     "\n        -k      Keep input files" (default, so why bother documenting?)
89 //usage:     "\n        -v      Verbose"
90 //usage:     "\n        -F      Don't verify checksum"
91
92 #include "libbb.h"
93 #include "common_bufsiz.h"
94 #include "bb_archive.h"
95 #include "liblzo_interface.h"
96
97 /* lzo-2.03/src/lzo_ptr.h */
98 #define pd(a,b)  ((unsigned)((a)-(b)))
99
100 #define lzo_version()                   LZO_VERSION
101 #define lzo_sizeof_dict_t               (sizeof(uint8_t*))
102
103 /* lzo-2.03/include/lzo/lzo1x.h */
104 #define LZO1X_1_MEM_COMPRESS    (16384 * lzo_sizeof_dict_t)
105 #define LZO1X_1_15_MEM_COMPRESS (32768 * lzo_sizeof_dict_t)
106 #define LZO1X_999_MEM_COMPRESS  (14 * 16384 * sizeof(short))
107
108 /* lzo-2.03/src/lzo1x_oo.c */
109 #define NO_LIT UINT_MAX
110
111 /**********************************************************************/
112 static void copy2(uint8_t* ip, const uint8_t* m_pos, unsigned off)
113 {
114         ip[0] = m_pos[0];
115         if (off == 1)
116                 ip[1] = m_pos[0];
117         else
118                 ip[1] = m_pos[1];
119 }
120
121 static void copy3(uint8_t* ip, const uint8_t* m_pos, unsigned off)
122 {
123         ip[0] = m_pos[0];
124         if (off == 1) {
125                 ip[2] = ip[1] = m_pos[0];
126         }
127         else if (off == 2) {
128                 ip[1] = m_pos[1];
129                 ip[2] = m_pos[0];
130         }
131         else {
132                 ip[1] = m_pos[1];
133                 ip[2] = m_pos[2];
134         }
135 }
136
137 /**********************************************************************/
138 // optimize a block of data.
139 /**********************************************************************/
140 #define TEST_IP         (ip < ip_end)
141 #define TEST_OP         (op <= op_end)
142
143 static NOINLINE int lzo1x_optimize(uint8_t *in, unsigned in_len,
144                 uint8_t *out, unsigned *out_len,
145                 void* wrkmem UNUSED_PARAM)
146 {
147         uint8_t* op;
148         uint8_t* ip;
149         unsigned t;
150         uint8_t* m_pos;
151         uint8_t* const ip_end = in + in_len;
152         uint8_t* const op_end = out + *out_len;
153         uint8_t* litp = NULL;
154         unsigned lit = 0;
155         unsigned next_lit = NO_LIT;
156         unsigned nl;
157         unsigned long o_m1_a = 0, o_m1_b = 0, o_m2 = 0, o_m3_a = 0, o_m3_b = 0;
158
159 //      LZO_UNUSED(wrkmem);
160
161         *out_len = 0;
162
163         op = out;
164         ip = in;
165
166         if (*ip > 17) {
167                 t = *ip++ - 17;
168                 if (t < 4)
169                         goto match_next;
170                 goto first_literal_run;
171         }
172
173         while (TEST_IP && TEST_OP) {
174                 t = *ip++;
175                 if (t >= 16)
176                         goto match;
177                 /* a literal run */
178                 litp = ip - 1;
179                 if (t == 0) {
180                         t = 15;
181                         while (*ip == 0)
182                                 t += 255, ip++;
183                         t += *ip++;
184                 }
185                 lit = t + 3;
186                 /* copy literals */
187  copy_literal_run:
188                 *op++ = *ip++;
189                 *op++ = *ip++;
190                 *op++ = *ip++;
191  first_literal_run:
192                 do *op++ = *ip++; while (--t > 0);
193
194                 t = *ip++;
195
196                 if (t >= 16)
197                         goto match;
198 #if defined(LZO1X)
199                 m_pos = op - 1 - 0x800;
200 #elif defined(LZO1Y)
201                 m_pos = op - 1 - 0x400;
202 #endif
203                 m_pos -= t >> 2;
204                 m_pos -= *ip++ << 2;
205                 *op++ = *m_pos++;
206                 *op++ = *m_pos++;
207                 *op++ = *m_pos++;
208                 lit = 0;
209                 goto match_done;
210
211
212                 /* handle matches */
213                 do {
214                         if (t < 16) { /* a M1 match */
215                                 m_pos = op - 1;
216                                 m_pos -= t >> 2;
217                                 m_pos -= *ip++ << 2;
218
219                                 if (litp == NULL)
220                                         goto copy_m1;
221
222                                 nl = ip[-2] & 3;
223                                 /* test if a match follows */
224                                 if (nl == 0 && lit == 1 && ip[0] >= 16) {
225                                         next_lit = nl;
226                                         /* adjust length of previous short run */
227                                         lit += 2;
228                                         *litp = (unsigned char)((*litp & ~3) | lit);
229                                         /* copy over the 2 literals that replace the match */
230                                         copy2(ip-2, m_pos, pd(op, m_pos));
231                                         o_m1_a++;
232                                 }
233                                 /* test if a literal run follows */
234                                 else
235                                 if (nl == 0
236                                  && ip[0] < 16
237                                  && ip[0] != 0
238                                  && (lit + 2 + ip[0] < 16)
239                                 ) {
240                                         t = *ip++;
241                                         /* remove short run */
242                                         *litp &= ~3;
243                                         /* copy over the 2 literals that replace the match */
244                                         copy2(ip-3+1, m_pos, pd(op, m_pos));
245                                         /* move literals 1 byte ahead */
246                                         litp += 2;
247                                         if (lit > 0)
248                                                 memmove(litp+1, litp, lit);
249                                         /* insert new length of long literal run */
250                                         lit += 2 + t + 3;
251                                         *litp = (unsigned char)(lit - 3);
252
253                                         o_m1_b++;
254                                         *op++ = *m_pos++;
255                                         *op++ = *m_pos++;
256                                         goto copy_literal_run;
257                                 }
258  copy_m1:
259                                 *op++ = *m_pos++;
260                                 *op++ = *m_pos++;
261                         } else {
262  match:
263                                 if (t >= 64) {                          /* a M2 match */
264                                         m_pos = op - 1;
265 #if defined(LZO1X)
266                                         m_pos -= (t >> 2) & 7;
267                                         m_pos -= *ip++ << 3;
268                                         t = (t >> 5) - 1;
269 #elif defined(LZO1Y)
270                                         m_pos -= (t >> 2) & 3;
271                                         m_pos -= *ip++ << 2;
272                                         t = (t >> 4) - 3;
273 #endif
274                                         if (litp == NULL)
275                                                 goto copy_m;
276
277                                         nl = ip[-2] & 3;
278                                         /* test if in beetween two long literal runs */
279                                         if (t == 1 && lit > 3 && nl == 0
280                                          && ip[0] < 16 && ip[0] != 0 && (lit + 3 + ip[0] < 16)
281                                         ) {
282                                                 t = *ip++;
283                                                 /* copy over the 3 literals that replace the match */
284                                                 copy3(ip-1-2, m_pos, pd(op, m_pos));
285                                                 /* set new length of previous literal run */
286                                                 lit += 3 + t + 3;
287                                                 *litp = (unsigned char)(lit - 3);
288                                                 o_m2++;
289                                                 *op++ = *m_pos++;
290                                                 *op++ = *m_pos++;
291                                                 *op++ = *m_pos++;
292                                                 goto copy_literal_run;
293                                         }
294                                 } else {
295                                         if (t >= 32) {                  /* a M3 match */
296                                                 t &= 31;
297                                                 if (t == 0) {
298                                                         t = 31;
299                                                         while (*ip == 0)
300                                                                 t += 255, ip++;
301                                                         t += *ip++;
302                                                 }
303                                                 m_pos = op - 1;
304                                                 m_pos -= *ip++ >> 2;
305                                                 m_pos -= *ip++ << 6;
306                                         } else {                                        /* a M4 match */
307                                                 m_pos = op;
308                                                 m_pos -= (t & 8) << 11;
309                                                 t &= 7;
310                                                 if (t == 0) {
311                                                         t = 7;
312                                                         while (*ip == 0)
313                                                                 t += 255, ip++;
314                                                         t += *ip++;
315                                                 }
316                                                 m_pos -= *ip++ >> 2;
317                                                 m_pos -= *ip++ << 6;
318                                                 if (m_pos == op)
319                                                         goto eof_found;
320                                                 m_pos -= 0x4000;
321                                         }
322                                         if (litp == NULL)
323                                                 goto copy_m;
324
325                                         nl = ip[-2] & 3;
326                                         /* test if in beetween two matches */
327                                         if (t == 1 && lit == 0 && nl == 0 && ip[0] >= 16) {
328                                                 next_lit = nl;
329                                                 /* make a previous short run */
330                                                 lit += 3;
331                                                 *litp = (unsigned char)((*litp & ~3) | lit);
332                                                 /* copy over the 3 literals that replace the match */
333                                                 copy3(ip-3, m_pos, pd(op, m_pos));
334                                                 o_m3_a++;
335                                         }
336                                         /* test if a literal run follows */
337                                         else if (t == 1 && lit <= 3 && nl == 0
338                                          && ip[0] < 16 && ip[0] != 0 && (lit + 3 + ip[0] < 16)
339                                         ) {
340                                                 t = *ip++;
341                                                 /* remove short run */
342                                                 *litp &= ~3;
343                                                 /* copy over the 3 literals that replace the match */
344                                                 copy3(ip-4+1, m_pos, pd(op, m_pos));
345                                                 /* move literals 1 byte ahead */
346                                                 litp += 2;
347                                                 if (lit > 0)
348                                                         memmove(litp+1,litp,lit);
349                                                 /* insert new length of long literal run */
350                                                 lit += 3 + t + 3;
351                                                 *litp = (unsigned char)(lit - 3);
352
353                                                 o_m3_b++;
354                                                 *op++ = *m_pos++;
355                                                 *op++ = *m_pos++;
356                                                 *op++ = *m_pos++;
357                                                 goto copy_literal_run;
358                                         }
359                                 }
360  copy_m:
361                                 *op++ = *m_pos++;
362                                 *op++ = *m_pos++;
363                                 do *op++ = *m_pos++; while (--t > 0);
364                         }
365
366  match_done:
367                         if (next_lit == NO_LIT) {
368                                 t = ip[-2] & 3;
369                                 lit = t;
370                                 litp = ip - 2;
371                         }
372                         else
373                                 t = next_lit;
374                         next_lit = NO_LIT;
375                         if (t == 0)
376                                 break;
377                         /* copy literals */
378  match_next:
379                         do *op++ = *ip++; while (--t > 0);
380                         t = *ip++;
381                 } while (TEST_IP && TEST_OP);
382         }
383
384         /* no EOF code was found */
385         *out_len = pd(op, out);
386         return LZO_E_EOF_NOT_FOUND;
387
388  eof_found:
389 //      LZO_UNUSED(o_m1_a); LZO_UNUSED(o_m1_b); LZO_UNUSED(o_m2);
390 //      LZO_UNUSED(o_m3_a); LZO_UNUSED(o_m3_b);
391         *out_len = pd(op, out);
392         return (ip == ip_end ? LZO_E_OK :
393                 (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
394 }
395
396 /**********************************************************************/
397 #define F_OS F_OS_UNIX
398 #define F_CS F_CS_NATIVE
399
400 /**********************************************************************/
401 #define ADLER32_INIT_VALUE 1
402 #define CRC32_INIT_VALUE   0
403
404 /**********************************************************************/
405 enum {
406         M_LZO1X_1    = 1,
407         M_LZO1X_1_15 = 2,
408         M_LZO1X_999  = 3,
409 };
410
411 /**********************************************************************/
412 /* header flags */
413 #define F_ADLER32_D     0x00000001L
414 #define F_ADLER32_C     0x00000002L
415 #define F_H_EXTRA_FIELD 0x00000040L
416 #define F_H_GMTDIFF     0x00000080L
417 #define F_CRC32_D       0x00000100L
418 #define F_CRC32_C       0x00000200L
419 #define F_H_FILTER      0x00000800L
420 #define F_H_CRC32       0x00001000L
421 #define F_MASK          0x00003FFFL
422
423 /* operating system & file system that created the file [mostly unused] */
424 #define F_OS_UNIX       0x03000000L
425 #define F_OS_SHIFT      24
426 #define F_OS_MASK       0xff000000L
427
428 /* character set for file name encoding [mostly unused] */
429 #define F_CS_NATIVE     0x00000000L
430 #define F_CS_SHIFT      20
431 #define F_CS_MASK       0x00f00000L
432
433 /* these bits must be zero */
434 #define F_RESERVED      ((F_MASK | F_OS_MASK | F_CS_MASK) ^ 0xffffffffL)
435
436 typedef struct chksum_t {
437         uint32_t f_adler32;
438         uint32_t f_crc32;
439 } chksum_t;
440
441 typedef struct header_t {
442         unsigned version;
443         unsigned lib_version;
444         unsigned version_needed_to_extract;
445         uint32_t flags;
446         uint32_t mode;
447         uint32_t mtime;
448         uint32_t gmtdiff;
449         uint32_t header_checksum;
450
451         uint32_t extra_field_len;
452         uint32_t extra_field_checksum;
453
454         unsigned char method;
455         unsigned char level;
456
457         /* info */
458         char name[255+1];
459 } header_t;
460
461 struct globals {
462         /*const uint32_t *lzo_crc32_table;*/
463         chksum_t chksum_in;
464         chksum_t chksum_out;
465 } FIX_ALIASING;
466 #define G (*(struct globals*)bb_common_bufsiz1)
467 #define INIT_G() do { setup_common_bufsiz(); } while (0)
468 //#define G (*ptr_to_globals)
469 //#define INIT_G() do {
470 //      SET_PTR_TO_GLOBALS(xzalloc(sizeof(G)));
471 //} while (0)
472
473
474 /**********************************************************************/
475 #define LZOP_VERSION            0x1010
476 //#define LZOP_VERSION_STRING     "1.01"
477 //#define LZOP_VERSION_DATE       "Apr 27th 2003"
478
479 // lzop wants to be weird:
480 // unlike all other compressosrs, its -k "keep" option is the default,
481 // and -U is used to delete the source. We will invert the bit after getopt().
482 #define OPTION_STRING "cfUvqdt123456789CFk"
483
484 /* Note: must be kept in sync with archival/bbunzip.c */
485 enum {
486         OPT_STDOUT      = (1 << 0),
487         OPT_FORCE       = (1 << 1),
488         OPT_KEEP        = (1 << 2),
489         OPT_VERBOSE     = (1 << 3),
490         OPT_QUIET       = (1 << 4),
491         OPT_DECOMPRESS  = (1 << 5),
492         OPT_TEST        = (1 << 6),
493         OPT_1           = (1 << 7),
494         OPT_2           = (1 << 8),
495         OPT_3           = (1 << 9),
496         OPT_4           = (1 << 10),
497         OPT_5           = (1 << 11),
498         OPT_6           = (1 << 12),
499         OPT_7           = (1 << 13),
500         OPT_8           = (1 << 14),
501         OPT_9           = (1 << 15),
502         OPT_C           = (1 << 16),
503         OPT_F           = (1 << 17),
504         OPT_k           = (1 << 18),
505         OPT_789         = OPT_7 | OPT_8 | OPT_9
506 };
507
508 /**********************************************************************/
509 // adler32 checksum
510 // adapted from free code by Mark Adler <madler@alumni.caltech.edu>
511 // see http://www.zlib.org/
512 /**********************************************************************/
513 static FAST_FUNC uint32_t
514 lzo_adler32(uint32_t adler, const uint8_t* buf, unsigned len)
515 {
516         enum {
517                 LZO_BASE = 65521, /* largest prime smaller than 65536 */
518                 /* NMAX is the largest n such that
519                  * 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
520                 LZO_NMAX = 5552,
521         };
522         uint32_t s1 = adler & 0xffff;
523         uint32_t s2 = (adler >> 16) & 0xffff;
524         unsigned k;
525
526         if (buf == NULL)
527                 return 1;
528
529         while (len > 0) {
530                 k = len < LZO_NMAX ? (unsigned) len : LZO_NMAX;
531                 len -= k;
532                 if (k != 0) do {
533                         s1 += *buf++;
534                         s2 += s1;
535                 } while (--k > 0);
536                 s1 %= LZO_BASE;
537                 s2 %= LZO_BASE;
538         }
539         return (s2 << 16) | s1;
540 }
541
542 static FAST_FUNC uint32_t
543 lzo_crc32(uint32_t c, const uint8_t* buf, unsigned len)
544 {
545         //if (buf == NULL) - impossible
546         //      return 0;
547
548         return ~crc32_block_endian0(~c, buf, len, global_crc32_table);
549 }
550
551 /**********************************************************************/
552 static void init_chksum(chksum_t *ct)
553 {
554         ct->f_adler32 = ADLER32_INIT_VALUE;
555         ct->f_crc32 = CRC32_INIT_VALUE;
556 }
557
558 static void add_bytes_to_chksum(chksum_t *ct, const void* buf, int cnt)
559 {
560         /* We need to handle the two checksums at once, because at the
561          * beginning of the header, we don't know yet which one we'll
562          * eventually need */
563         ct->f_adler32 = lzo_adler32(ct->f_adler32, (const uint8_t*)buf, cnt);
564         ct->f_crc32 = lzo_crc32(ct->f_crc32, (const uint8_t*)buf, cnt);
565 }
566
567 static uint32_t chksum_getresult(chksum_t *ct, const header_t *h)
568 {
569         return (h->flags & F_H_CRC32) ? ct->f_crc32 : ct->f_adler32;
570 }
571
572 /**********************************************************************/
573 static uint32_t read32(void)
574 {
575         uint32_t v;
576         xread(0, &v, 4);
577         return ntohl(v);
578 }
579
580 static void write32(uint32_t v)
581 {
582         v = htonl(v);
583         xwrite(1, &v, 4);
584 }
585
586 static void f_write(const void* buf, int cnt)
587 {
588         xwrite(1, buf, cnt);
589         add_bytes_to_chksum(&G.chksum_out, buf, cnt);
590 }
591
592 static void f_read(void* buf, int cnt)
593 {
594         xread(0, buf, cnt);
595         add_bytes_to_chksum(&G.chksum_in, buf, cnt);
596 }
597
598 static int f_read8(void)
599 {
600         uint8_t v;
601         f_read(&v, 1);
602         return v;
603 }
604
605 static void f_write8(uint8_t v)
606 {
607         f_write(&v, 1);
608 }
609
610 static unsigned f_read16(void)
611 {
612         uint16_t v;
613         f_read(&v, 2);
614         return ntohs(v);
615 }
616
617 static void f_write16(uint16_t v)
618 {
619         v = htons(v);
620         f_write(&v, 2);
621 }
622
623 static uint32_t f_read32(void)
624 {
625         uint32_t v;
626         f_read(&v, 4);
627         return ntohl(v);
628 }
629
630 static void f_write32(uint32_t v)
631 {
632         v = htonl(v);
633         f_write(&v, 4);
634 }
635
636 /**********************************************************************/
637 static int lzo_get_method(header_t *h)
638 {
639         /* check method */
640         if (h->method == M_LZO1X_1) {
641                 if (h->level == 0)
642                         h->level = 3;
643         } else if (h->method == M_LZO1X_1_15) {
644                 if (h->level == 0)
645                         h->level = 1;
646         } else if (h->method == M_LZO1X_999) {
647                 if (h->level == 0)
648                         h->level = 9;
649         } else
650                 return -1;              /* not a LZO method */
651
652         /* check compression level */
653         if (h->level < 1 || h->level > 9)
654                 return 15;
655
656         return 0;
657 }
658
659 /**********************************************************************/
660 #define LZO_BLOCK_SIZE  (256 * 1024l)
661 #define MAX_BLOCK_SIZE  (64 * 1024l * 1024l)    /* DO NOT CHANGE */
662
663 /* LZO may expand uncompressible data by a small amount */
664 #define MAX_COMPRESSED_SIZE(x)  ((x) + (x) / 16 + 64 + 3)
665
666 /**********************************************************************/
667 // compress a file
668 /**********************************************************************/
669 static NOINLINE int lzo_compress(const header_t *h)
670 {
671         unsigned block_size = LZO_BLOCK_SIZE;
672         int r = 0; /* LZO_E_OK */
673         uint8_t *const b1 = xzalloc(block_size);
674         uint8_t *const b2 = xzalloc(MAX_COMPRESSED_SIZE(block_size));
675         unsigned src_len = 0, dst_len = 0;
676         uint32_t d_adler32 = ADLER32_INIT_VALUE;
677         uint32_t d_crc32 = CRC32_INIT_VALUE;
678         int l;
679         uint8_t *wrk_mem = NULL;
680
681         if (h->method == M_LZO1X_1)
682                 wrk_mem = xzalloc(LZO1X_1_MEM_COMPRESS);
683         else if (h->method == M_LZO1X_1_15)
684                 wrk_mem = xzalloc(LZO1X_1_15_MEM_COMPRESS);
685         else if (h->method == M_LZO1X_999)
686                 wrk_mem = xzalloc(LZO1X_999_MEM_COMPRESS);
687
688         for (;;) {
689                 /* read a block */
690                 l = full_read(0, b1, block_size);
691                 src_len = (l > 0 ? l : 0);
692
693                 /* write uncompressed block size */
694                 write32(src_len);
695
696                 /* exit if last block */
697                 if (src_len == 0)
698                         break;
699
700                 /* compute checksum of uncompressed block */
701                 if (h->flags & F_ADLER32_D)
702                         d_adler32 = lzo_adler32(ADLER32_INIT_VALUE, b1, src_len);
703                 if (h->flags & F_CRC32_D)
704                         d_crc32 = lzo_crc32(CRC32_INIT_VALUE, b1, src_len);
705
706                 /* compress */
707                 if (h->method == M_LZO1X_1)
708                         r = lzo1x_1_compress(b1, src_len, b2, &dst_len, wrk_mem);
709                 else if (h->method == M_LZO1X_1_15)
710                         r = lzo1x_1_15_compress(b1, src_len, b2, &dst_len, wrk_mem);
711 #if ENABLE_LZOP_COMPR_HIGH
712                 else if (h->method == M_LZO1X_999)
713                         r = lzo1x_999_compress_level(b1, src_len, b2, &dst_len,
714                                                 wrk_mem, h->level);
715 #endif
716                 else
717                         bb_error_msg_and_die("internal error");
718
719                 if (r != 0) /* not LZO_E_OK */
720                         bb_error_msg_and_die("internal error - compression failed");
721
722                 /* write compressed block size */
723                 if (dst_len < src_len) {
724                         /* optimize */
725                         if (h->method == M_LZO1X_999) {
726                                 unsigned new_len = src_len;
727                                 r = lzo1x_optimize(b2, dst_len, b1, &new_len, NULL);
728                                 if (r != 0 /*LZO_E_OK*/ || new_len != src_len)
729                                         bb_error_msg_and_die("internal error - optimization failed");
730                         }
731                         write32(dst_len);
732                 } else {
733                         /* data actually expanded => store data uncompressed */
734                         write32(src_len);
735                 }
736
737                 /* write checksum of uncompressed block */
738                 if (h->flags & F_ADLER32_D)
739                         write32(d_adler32);
740                 if (h->flags & F_CRC32_D)
741                         write32(d_crc32);
742
743                 if (dst_len < src_len) {
744                         /* write checksum of compressed block */
745                         if (h->flags & F_ADLER32_C)
746                                 write32(lzo_adler32(ADLER32_INIT_VALUE, b2, dst_len));
747                         if (h->flags & F_CRC32_C)
748                                 write32(lzo_crc32(CRC32_INIT_VALUE, b2, dst_len));
749                         /* write compressed block data */
750                         xwrite(1, b2, dst_len);
751                 } else {
752                         /* write uncompressed block data */
753                         xwrite(1, b1, src_len);
754                 }
755         }
756
757         free(wrk_mem);
758         free(b1);
759         free(b2);
760         return 1;
761 }
762
763 static FAST_FUNC void lzo_check(
764                 uint32_t init,
765                 uint8_t* buf, unsigned len,
766                 uint32_t FAST_FUNC (*fn)(uint32_t, const uint8_t*, unsigned),
767                 uint32_t ref)
768 {
769         /* This function, by having the same order of parameters
770          * as fn, and by being marked FAST_FUNC (same as fn),
771          * saves a dozen bytes of code.
772          */
773         uint32_t c = fn(init, buf, len);
774         if (c != ref)
775                 bb_error_msg_and_die("checksum error");
776 }
777
778 /**********************************************************************/
779 // decompress a file
780 /**********************************************************************/
781 static NOINLINE int lzo_decompress(const header_t *h)
782 {
783         unsigned block_size = LZO_BLOCK_SIZE;
784         int r;
785         uint32_t src_len, dst_len;
786         uint32_t c_adler32 = ADLER32_INIT_VALUE;
787         uint32_t d_adler32 = ADLER32_INIT_VALUE;
788         uint32_t c_crc32 = CRC32_INIT_VALUE, d_crc32 = CRC32_INIT_VALUE;
789         uint8_t *b1;
790         uint32_t mcs_block_size = MAX_COMPRESSED_SIZE(block_size);
791         uint8_t *b2 = NULL;
792
793         for (;;) {
794                 uint8_t *dst;
795
796                 /* read uncompressed block size */
797                 dst_len = read32();
798
799                 /* exit if last block */
800                 if (dst_len == 0)
801                         break;
802
803                 /* error if split file */
804                 if (dst_len == 0xffffffffL)
805                         /* should not happen - not yet implemented */
806                         bb_error_msg_and_die("this file is a split lzop file");
807
808                 if (dst_len > MAX_BLOCK_SIZE)
809                         bb_error_msg_and_die("corrupted data");
810
811                 /* read compressed block size */
812                 src_len = read32();
813                 if (src_len <= 0 || src_len > dst_len)
814                         bb_error_msg_and_die("corrupted data");
815
816                 if (dst_len > block_size) {
817                         if (b2) {
818                                 free(b2);
819                                 b2 = NULL;
820                         }
821                         block_size = dst_len;
822                         mcs_block_size = MAX_COMPRESSED_SIZE(block_size);
823                 }
824
825                 /* read checksum of uncompressed block */
826                 if (h->flags & F_ADLER32_D)
827                         d_adler32 = read32();
828                 if (h->flags & F_CRC32_D)
829                         d_crc32 = read32();
830
831                 /* read checksum of compressed block */
832                 if (src_len < dst_len) {
833                         if (h->flags & F_ADLER32_C)
834                                 c_adler32 = read32();
835                         if (h->flags & F_CRC32_C)
836                                 c_crc32 = read32();
837                 }
838
839                 if (b2 == NULL)
840                         b2 = xzalloc(mcs_block_size);
841                 /* read the block into the end of our buffer */
842                 b1 = b2 + mcs_block_size - src_len;
843                 xread(0, b1, src_len);
844
845                 if (src_len < dst_len) {
846                         unsigned d = dst_len;
847
848                         if (!(option_mask32 & OPT_F)) {
849                                 /* verify checksum of compressed block */
850                                 if (h->flags & F_ADLER32_C)
851                                         lzo_check(ADLER32_INIT_VALUE,
852                                                         b1, src_len,
853                                                         lzo_adler32, c_adler32);
854                                 if (h->flags & F_CRC32_C)
855                                         lzo_check(CRC32_INIT_VALUE,
856                                                         b1, src_len,
857                                                         lzo_crc32, c_crc32);
858                         }
859
860                         /* decompress */
861 //                      if (option_mask32 & OPT_F)
862 //                              r = lzo1x_decompress(b1, src_len, b2, &d, NULL);
863 //                      else
864                                 r = lzo1x_decompress_safe(b1, src_len, b2, &d, NULL);
865
866                         if (r != 0 /*LZO_E_OK*/ || dst_len != d) {
867                                 bb_error_msg_and_die("corrupted data");
868                         }
869                         dst = b2;
870                 } else {
871                         /* "stored" block => no decompression */
872                         dst = b1;
873                 }
874
875                 if (!(option_mask32 & OPT_F)) {
876                         /* verify checksum of uncompressed block */
877                         if (h->flags & F_ADLER32_D)
878                                 lzo_check(ADLER32_INIT_VALUE,
879                                         dst, dst_len,
880                                         lzo_adler32, d_adler32);
881                         if (h->flags & F_CRC32_D)
882                                 lzo_check(CRC32_INIT_VALUE,
883                                         dst, dst_len,
884                                         lzo_crc32, d_crc32);
885                 }
886
887                 /* write uncompressed block data */
888                 xwrite(1, dst, dst_len);
889         }
890
891         free(b2);
892         return 1;
893 }
894
895 /**********************************************************************/
896 // lzop file signature (shamelessly borrowed from PNG)
897 /**********************************************************************/
898 /*
899  * The first nine bytes of a lzop file always contain the following values:
900  *
901  *                                 0   1   2   3   4   5   6   7   8
902  *                               --- --- --- --- --- --- --- --- ---
903  * (hex)                          89  4c  5a  4f  00  0d  0a  1a  0a
904  * (decimal)                     137  76  90  79   0  13  10  26  10
905  * (C notation - ASCII)         \211   L   Z   O  \0  \r  \n \032 \n
906  */
907
908 /* (vda) comparison with lzop v1.02rc1 ("lzop -1 <FILE" cmd):
909  * Only slight differences in header:
910  * -00000000  89 4c 5a 4f 00 0d 0a 1a 0a 10 20 20 20 09 40 02
911  * +00000000  89 4c 5a 4f 00 0d 0a 1a 0a 10 10 20 30 09 40 02
912  *                                       ^^^^^ ^^^^^
913  *                                     version lib_version
914  * -00000010  01 03 00 00 0d 00 00 81 a4 49 f7 a6 3f 00 00 00
915  * +00000010  01 03 00 00 01 00 00 00 00 00 00 00 00 00 00 00
916  *               ^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^
917  *               flags       mode        mtime
918  * -00000020  00 00 2d 67 04 17 00 04 00 00 00 03 ed ec 9d 6d
919  * +00000020  00 00 10 5f 00 c1 00 04 00 00 00 03 ed ec 9d 6d
920  *                  ^^^^^^^^^^^
921  *                  chksum_out
922  * The rest is identical.
923 */
924 static const unsigned char lzop_magic[9] ALIGN1 = {
925         0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a
926 };
927
928 /* This coding is derived from Alexander Lehmann's pngcheck code. */
929 static void check_magic(void)
930 {
931         unsigned char magic[sizeof(lzop_magic)];
932         xread(0, magic, sizeof(magic));
933         if (memcmp(magic, lzop_magic, sizeof(lzop_magic)) != 0)
934                 bb_error_msg_and_die("bad magic number");
935 }
936
937 /**********************************************************************/
938 // lzop file header
939 /**********************************************************************/
940 static void write_header(const header_t *h)
941 {
942         int l;
943
944         xwrite(1, lzop_magic, sizeof(lzop_magic));
945
946         init_chksum(&G.chksum_out);
947
948         f_write16(h->version);
949         f_write16(h->lib_version);
950         f_write16(h->version_needed_to_extract);
951         f_write8(h->method);
952         f_write8(h->level);
953         f_write32(h->flags);
954         f_write32(h->mode);
955         f_write32(h->mtime);
956         f_write32(h->gmtdiff);
957
958         l = (int) strlen(h->name);
959         f_write8(l);
960         if (l)
961                 f_write(h->name, l);
962
963         f_write32(chksum_getresult(&G.chksum_out, h));
964 }
965
966 static int read_header(header_t *h)
967 {
968         int r;
969         int l;
970         uint32_t checksum;
971
972         memset(h, 0, sizeof(*h));
973         h->version_needed_to_extract = 0x0900;  /* first lzop version */
974         h->level = 0;
975
976         init_chksum(&G.chksum_in);
977
978         h->version = f_read16();
979         if (h->version < 0x0900)
980                 return 3;
981         h->lib_version = f_read16();
982         if (h->version >= 0x0940) {
983                 h->version_needed_to_extract = f_read16();
984                 if (h->version_needed_to_extract > LZOP_VERSION)
985                         return 16;
986                 if (h->version_needed_to_extract < 0x0900)
987                         return 3;
988         }
989         h->method = f_read8();
990         if (h->version >= 0x0940)
991                 h->level = f_read8();
992         h->flags = f_read32();
993         if (h->flags & F_H_FILTER)
994                 return 16; /* filter not supported */
995         h->mode = f_read32();
996         h->mtime = f_read32();
997         if (h->version >= 0x0940)
998                 h->gmtdiff = f_read32();
999
1000         l = f_read8();
1001         if (l > 0)
1002                 f_read(h->name, l);
1003         h->name[l] = 0;
1004
1005         checksum = chksum_getresult(&G.chksum_in, h);
1006         h->header_checksum = f_read32();
1007         if (h->header_checksum != checksum)
1008                 return 2;
1009
1010         if (h->method <= 0)
1011                 return 14;
1012         r = lzo_get_method(h);
1013         if (r != 0)
1014                 return r;
1015
1016         /* check reserved flags */
1017         if (h->flags & F_RESERVED)
1018                 return -13;
1019
1020         /* skip extra field [not used yet] */
1021         if (h->flags & F_H_EXTRA_FIELD) {
1022                 uint32_t k;
1023
1024                 /* note: the checksum also covers the length */
1025                 init_chksum(&G.chksum_in);
1026                 h->extra_field_len = f_read32();
1027                 for (k = 0; k < h->extra_field_len; k++)
1028                         f_read8();
1029                 checksum = chksum_getresult(&G.chksum_in, h);
1030                 h->extra_field_checksum = f_read32();
1031                 if (h->extra_field_checksum != checksum)
1032                         return 3;
1033         }
1034
1035         return 0;
1036 }
1037
1038 static void p_header(header_t *h)
1039 {
1040         int r;
1041
1042         r = read_header(h);
1043         if (r == 0)
1044                 return;
1045         bb_error_msg_and_die("header_error %d", r);
1046 }
1047
1048 /**********************************************************************/
1049 // compress
1050 /**********************************************************************/
1051 static void lzo_set_method(header_t *h)
1052 {
1053         int level = 1;
1054
1055         if (option_mask32 & OPT_1) {
1056                 h->method = M_LZO1X_1_15;
1057         } else if (option_mask32 & OPT_789) {
1058 #if ENABLE_LZOP_COMPR_HIGH
1059                 h->method = M_LZO1X_999;
1060                 if (option_mask32 & OPT_7)
1061                         level = 7;
1062                 else if (option_mask32 & OPT_8)
1063                         level = 8;
1064                 else
1065                         level = 9;
1066 #else
1067                 bb_error_msg_and_die("high compression not compiled in");
1068 #endif
1069         } else { /* levels 2..6 or none (defaults to level 3) */
1070                 h->method = M_LZO1X_1;
1071                 level = 5; /* levels 2-6 are actually the same */
1072         }
1073
1074         h->level = level;
1075 }
1076
1077 static int do_lzo_compress(void)
1078 {
1079         header_t header;
1080
1081 #define h (&header)
1082         memset(h, 0, sizeof(*h));
1083
1084         lzo_set_method(h);
1085
1086         h->version = (LZOP_VERSION & 0xffff);
1087         h->version_needed_to_extract = 0x0940;
1088         h->lib_version = lzo_version() & 0xffff;
1089
1090         h->flags = (F_OS & F_OS_MASK) | (F_CS & F_CS_MASK);
1091
1092         if (!(option_mask32 & OPT_F) || h->method == M_LZO1X_999) {
1093                 h->flags |= F_ADLER32_D;
1094                 if (option_mask32 & OPT_C)
1095                         h->flags |= F_ADLER32_C;
1096         }
1097         write_header(h);
1098         return lzo_compress(h);
1099 #undef h
1100 }
1101
1102 /**********************************************************************/
1103 // decompress
1104 /**********************************************************************/
1105 static int do_lzo_decompress(void)
1106 {
1107         header_t header;
1108
1109         check_magic();
1110         p_header(&header);
1111         return lzo_decompress(&header);
1112 }
1113
1114 static char* FAST_FUNC make_new_name_lzop(char *filename, const char *expected_ext UNUSED_PARAM)
1115 {
1116         if (option_mask32 & OPT_DECOMPRESS) {
1117                 char *extension = strrchr(filename, '.');
1118                 if (!extension || strcmp(extension + 1, "lzo") != 0)
1119                         return xasprintf("%s.out", filename);
1120                 *extension = '\0';
1121                 return filename;
1122         }
1123         return xasprintf("%s.lzo", filename);
1124 }
1125
1126 static IF_DESKTOP(long long) int FAST_FUNC pack_lzop(transformer_state_t *xstate UNUSED_PARAM)
1127 {
1128         if (option_mask32 & OPT_DECOMPRESS)
1129                 return do_lzo_decompress();
1130         return do_lzo_compress();
1131 }
1132
1133 int lzop_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1134 int lzop_main(int argc UNUSED_PARAM, char **argv)
1135 {
1136         getopt32(argv, OPTION_STRING);
1137         argv += optind;
1138         /* -U is "anti -k", invert bit for bbunpack(): */
1139         option_mask32 ^= OPT_KEEP;
1140         /* -k disables -U (if any): */
1141         /* opt_complementary "k-U"? - nope, only handles -Uk, not -kU */
1142         if (option_mask32 & OPT_k)
1143                 option_mask32 |= OPT_KEEP;
1144
1145         /* lzopcat? */
1146         if (ENABLE_LZOPCAT && applet_name[4] == 'c')
1147                 option_mask32 |= (OPT_STDOUT | OPT_DECOMPRESS);
1148         /* unlzop? */
1149         if (ENABLE_UNLZOP && applet_name[4] == 'o')
1150                 option_mask32 |= OPT_DECOMPRESS;
1151
1152         global_crc32_table = crc32_filltable(NULL, 0);
1153         return bbunpack(argv, pack_lzop, make_new_name_lzop, /*unused:*/ NULL);
1154 }