1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73#include "libbb.h"
74#include "common_bufsiz.h"
75#include "bb_archive.h"
76#include "liblzo_interface.h"
77
78
79#define pd(a,b) ((unsigned)((a)-(b)))
80
81#define lzo_version() LZO_VERSION
82#define lzo_sizeof_dict_t (sizeof(uint8_t*))
83
84
85#define LZO1X_1_MEM_COMPRESS (16384 * lzo_sizeof_dict_t)
86#define LZO1X_1_15_MEM_COMPRESS (32768 * lzo_sizeof_dict_t)
87#define LZO1X_999_MEM_COMPRESS (14 * 16384 * sizeof(short))
88
89
90#define NO_LIT UINT_MAX
91
92
93static void copy2(uint8_t* ip, const uint8_t* m_pos, unsigned off)
94{
95 ip[0] = m_pos[0];
96 if (off == 1)
97 ip[1] = m_pos[0];
98 else
99 ip[1] = m_pos[1];
100}
101
102static void copy3(uint8_t* ip, const uint8_t* m_pos, unsigned off)
103{
104 ip[0] = m_pos[0];
105 if (off == 1) {
106 ip[2] = ip[1] = m_pos[0];
107 }
108 else if (off == 2) {
109 ip[1] = m_pos[1];
110 ip[2] = m_pos[0];
111 }
112 else {
113 ip[1] = m_pos[1];
114 ip[2] = m_pos[2];
115 }
116}
117
118
119
120
121#define TEST_IP (ip < ip_end)
122#define TEST_OP (op <= op_end)
123
124static NOINLINE int lzo1x_optimize(uint8_t *in, unsigned in_len,
125 uint8_t *out, unsigned *out_len,
126 void* wrkmem UNUSED_PARAM)
127{
128 uint8_t* op;
129 uint8_t* ip;
130 unsigned t;
131 uint8_t* m_pos;
132 uint8_t* const ip_end = in + in_len;
133 uint8_t* const op_end = out + *out_len;
134 uint8_t* litp = NULL;
135 unsigned lit = 0;
136 unsigned next_lit = NO_LIT;
137 unsigned nl;
138 unsigned long o_m1_a = 0, o_m1_b = 0, o_m2 = 0, o_m3_a = 0, o_m3_b = 0;
139
140
141
142 *out_len = 0;
143
144 op = out;
145 ip = in;
146
147 if (*ip > 17) {
148 t = *ip++ - 17;
149 if (t < 4)
150 goto match_next;
151 goto first_literal_run;
152 }
153
154 while (TEST_IP && TEST_OP) {
155 t = *ip++;
156 if (t >= 16)
157 goto match;
158
159 litp = ip - 1;
160 if (t == 0) {
161 t = 15;
162 while (*ip == 0)
163 t += 255, ip++;
164 t += *ip++;
165 }
166 lit = t + 3;
167
168 copy_literal_run:
169 *op++ = *ip++;
170 *op++ = *ip++;
171 *op++ = *ip++;
172 first_literal_run:
173 do *op++ = *ip++; while (--t > 0);
174
175 t = *ip++;
176
177 if (t >= 16)
178 goto match;
179#if defined(LZO1X)
180 m_pos = op - 1 - 0x800;
181#elif defined(LZO1Y)
182 m_pos = op - 1 - 0x400;
183#endif
184 m_pos -= t >> 2;
185 m_pos -= *ip++ << 2;
186 *op++ = *m_pos++;
187 *op++ = *m_pos++;
188 *op++ = *m_pos++;
189 lit = 0;
190 goto match_done;
191
192
193
194 do {
195 if (t < 16) {
196 m_pos = op - 1;
197 m_pos -= t >> 2;
198 m_pos -= *ip++ << 2;
199
200 if (litp == NULL)
201 goto copy_m1;
202
203 nl = ip[-2] & 3;
204
205 if (nl == 0 && lit == 1 && ip[0] >= 16) {
206 next_lit = nl;
207
208 lit += 2;
209 *litp = (unsigned char)((*litp & ~3) | lit);
210
211 copy2(ip-2, m_pos, pd(op, m_pos));
212 o_m1_a++;
213 }
214
215 else
216 if (nl == 0
217 && ip[0] < 16
218 && ip[0] != 0
219 && (lit + 2 + ip[0] < 16)
220 ) {
221 t = *ip++;
222
223 *litp &= ~3;
224
225 copy2(ip-3+1, m_pos, pd(op, m_pos));
226
227 litp += 2;
228 if (lit > 0)
229 memmove(litp+1, litp, lit);
230
231 lit += 2 + t + 3;
232 *litp = (unsigned char)(lit - 3);
233
234 o_m1_b++;
235 *op++ = *m_pos++;
236 *op++ = *m_pos++;
237 goto copy_literal_run;
238 }
239 copy_m1:
240 *op++ = *m_pos++;
241 *op++ = *m_pos++;
242 } else {
243 match:
244 if (t >= 64) {
245 m_pos = op - 1;
246#if defined(LZO1X)
247 m_pos -= (t >> 2) & 7;
248 m_pos -= *ip++ << 3;
249 t = (t >> 5) - 1;
250#elif defined(LZO1Y)
251 m_pos -= (t >> 2) & 3;
252 m_pos -= *ip++ << 2;
253 t = (t >> 4) - 3;
254#endif
255 if (litp == NULL)
256 goto copy_m;
257
258 nl = ip[-2] & 3;
259
260 if (t == 1 && lit > 3 && nl == 0
261 && ip[0] < 16 && ip[0] != 0 && (lit + 3 + ip[0] < 16)
262 ) {
263 t = *ip++;
264
265 copy3(ip-1-2, m_pos, pd(op, m_pos));
266
267 lit += 3 + t + 3;
268 *litp = (unsigned char)(lit - 3);
269 o_m2++;
270 *op++ = *m_pos++;
271 *op++ = *m_pos++;
272 *op++ = *m_pos++;
273 goto copy_literal_run;
274 }
275 } else {
276 if (t >= 32) {
277 t &= 31;
278 if (t == 0) {
279 t = 31;
280 while (*ip == 0)
281 t += 255, ip++;
282 t += *ip++;
283 }
284 m_pos = op - 1;
285 m_pos -= *ip++ >> 2;
286 m_pos -= *ip++ << 6;
287 } else {
288 m_pos = op;
289 m_pos -= (t & 8) << 11;
290 t &= 7;
291 if (t == 0) {
292 t = 7;
293 while (*ip == 0)
294 t += 255, ip++;
295 t += *ip++;
296 }
297 m_pos -= *ip++ >> 2;
298 m_pos -= *ip++ << 6;
299 if (m_pos == op)
300 goto eof_found;
301 m_pos -= 0x4000;
302 }
303 if (litp == NULL)
304 goto copy_m;
305
306 nl = ip[-2] & 3;
307
308 if (t == 1 && lit == 0 && nl == 0 && ip[0] >= 16) {
309 next_lit = nl;
310
311 lit += 3;
312 *litp = (unsigned char)((*litp & ~3) | lit);
313
314 copy3(ip-3, m_pos, pd(op, m_pos));
315 o_m3_a++;
316 }
317
318 else if (t == 1 && lit <= 3 && nl == 0
319 && ip[0] < 16 && ip[0] != 0 && (lit + 3 + ip[0] < 16)
320 ) {
321 t = *ip++;
322
323 *litp &= ~3;
324
325 copy3(ip-4+1, m_pos, pd(op, m_pos));
326
327 litp += 2;
328 if (lit > 0)
329 memmove(litp+1,litp,lit);
330
331 lit += 3 + t + 3;
332 *litp = (unsigned char)(lit - 3);
333
334 o_m3_b++;
335 *op++ = *m_pos++;
336 *op++ = *m_pos++;
337 *op++ = *m_pos++;
338 goto copy_literal_run;
339 }
340 }
341 copy_m:
342 *op++ = *m_pos++;
343 *op++ = *m_pos++;
344 do *op++ = *m_pos++; while (--t > 0);
345 }
346
347 match_done:
348 if (next_lit == NO_LIT) {
349 t = ip[-2] & 3;
350 lit = t;
351 litp = ip - 2;
352 }
353 else
354 t = next_lit;
355 next_lit = NO_LIT;
356 if (t == 0)
357 break;
358
359 match_next:
360 do *op++ = *ip++; while (--t > 0);
361 t = *ip++;
362 } while (TEST_IP && TEST_OP);
363 }
364
365
366 *out_len = pd(op, out);
367 return LZO_E_EOF_NOT_FOUND;
368
369 eof_found:
370
371
372 *out_len = pd(op, out);
373 return (ip == ip_end ? LZO_E_OK :
374 (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
375}
376
377
378#define F_OS F_OS_UNIX
379#define F_CS F_CS_NATIVE
380
381
382#define ADLER32_INIT_VALUE 1
383#define CRC32_INIT_VALUE 0
384
385
386enum {
387 M_LZO1X_1 = 1,
388 M_LZO1X_1_15 = 2,
389 M_LZO1X_999 = 3,
390};
391
392
393
394#define F_ADLER32_D 0x00000001L
395#define F_ADLER32_C 0x00000002L
396#define F_H_EXTRA_FIELD 0x00000040L
397#define F_H_GMTDIFF 0x00000080L
398#define F_CRC32_D 0x00000100L
399#define F_CRC32_C 0x00000200L
400#define F_H_FILTER 0x00000800L
401#define F_H_CRC32 0x00001000L
402#define F_MASK 0x00003FFFL
403
404
405#define F_OS_UNIX 0x03000000L
406#define F_OS_SHIFT 24
407#define F_OS_MASK 0xff000000L
408
409
410#define F_CS_NATIVE 0x00000000L
411#define F_CS_SHIFT 20
412#define F_CS_MASK 0x00f00000L
413
414
415#define F_RESERVED ((F_MASK | F_OS_MASK | F_CS_MASK) ^ 0xffffffffL)
416
417typedef struct chksum_t {
418 uint32_t f_adler32;
419 uint32_t f_crc32;
420} chksum_t;
421
422typedef struct header_t {
423 unsigned version;
424 unsigned lib_version;
425 unsigned version_needed_to_extract;
426 uint32_t flags;
427 uint32_t mode;
428 uint32_t mtime;
429 uint32_t gmtdiff;
430 uint32_t header_checksum;
431
432 uint32_t extra_field_len;
433 uint32_t extra_field_checksum;
434
435 unsigned char method;
436 unsigned char level;
437
438
439 char name[255+1];
440} header_t;
441
442struct globals {
443
444 chksum_t chksum_in;
445 chksum_t chksum_out;
446} FIX_ALIASING;
447#define G (*(struct globals*)bb_common_bufsiz1)
448#define INIT_G() do { setup_common_bufsiz(); } while (0)
449
450
451
452
453
454
455
456#define LZOP_VERSION 0x1010
457
458
459
460#define OPTION_STRING "cfvqdt123456789CF"
461
462
463enum {
464 OPT_STDOUT = (1 << 0),
465 OPT_FORCE = (1 << 1),
466 OPT_VERBOSE = (1 << 2),
467 OPT_QUIET = (1 << 3),
468 OPT_DECOMPRESS = (1 << 4),
469 OPT_TEST = (1 << 5),
470 OPT_1 = (1 << 6),
471 OPT_2 = (1 << 7),
472 OPT_3 = (1 << 8),
473 OPT_4 = (1 << 9),
474 OPT_5 = (1 << 10),
475 OPT_6 = (1 << 11),
476 OPT_789 = (7 << 12),
477 OPT_7 = (1 << 13),
478 OPT_8 = (1 << 14),
479 OPT_C = (1 << 15),
480 OPT_F = (1 << 16),
481};
482
483
484
485
486
487
488static FAST_FUNC uint32_t
489lzo_adler32(uint32_t adler, const uint8_t* buf, unsigned len)
490{
491 enum {
492 LZO_BASE = 65521,
493
494
495 LZO_NMAX = 5552,
496 };
497 uint32_t s1 = adler & 0xffff;
498 uint32_t s2 = (adler >> 16) & 0xffff;
499 unsigned k;
500
501 if (buf == NULL)
502 return 1;
503
504 while (len > 0) {
505 k = len < LZO_NMAX ? (unsigned) len : LZO_NMAX;
506 len -= k;
507 if (k != 0) do {
508 s1 += *buf++;
509 s2 += s1;
510 } while (--k > 0);
511 s1 %= LZO_BASE;
512 s2 %= LZO_BASE;
513 }
514 return (s2 << 16) | s1;
515}
516
517static FAST_FUNC uint32_t
518lzo_crc32(uint32_t c, const uint8_t* buf, unsigned len)
519{
520
521
522
523 return ~crc32_block_endian0(~c, buf, len, global_crc32_table);
524}
525
526
527static void init_chksum(chksum_t *ct)
528{
529 ct->f_adler32 = ADLER32_INIT_VALUE;
530 ct->f_crc32 = CRC32_INIT_VALUE;
531}
532
533static void add_bytes_to_chksum(chksum_t *ct, const void* buf, int cnt)
534{
535
536
537
538 ct->f_adler32 = lzo_adler32(ct->f_adler32, (const uint8_t*)buf, cnt);
539 ct->f_crc32 = lzo_crc32(ct->f_crc32, (const uint8_t*)buf, cnt);
540}
541
542static uint32_t chksum_getresult(chksum_t *ct, const header_t *h)
543{
544 return (h->flags & F_H_CRC32) ? ct->f_crc32 : ct->f_adler32;
545}
546
547
548static uint32_t read32(void)
549{
550 uint32_t v;
551 xread(0, &v, 4);
552 return ntohl(v);
553}
554
555static void write32(uint32_t v)
556{
557 v = htonl(v);
558 xwrite(1, &v, 4);
559}
560
561static void f_write(const void* buf, int cnt)
562{
563 xwrite(1, buf, cnt);
564 add_bytes_to_chksum(&G.chksum_out, buf, cnt);
565}
566
567static void f_read(void* buf, int cnt)
568{
569 xread(0, buf, cnt);
570 add_bytes_to_chksum(&G.chksum_in, buf, cnt);
571}
572
573static int f_read8(void)
574{
575 uint8_t v;
576 f_read(&v, 1);
577 return v;
578}
579
580static void f_write8(uint8_t v)
581{
582 f_write(&v, 1);
583}
584
585static unsigned f_read16(void)
586{
587 uint16_t v;
588 f_read(&v, 2);
589 return ntohs(v);
590}
591
592static void f_write16(uint16_t v)
593{
594 v = htons(v);
595 f_write(&v, 2);
596}
597
598static uint32_t f_read32(void)
599{
600 uint32_t v;
601 f_read(&v, 4);
602 return ntohl(v);
603}
604
605static void f_write32(uint32_t v)
606{
607 v = htonl(v);
608 f_write(&v, 4);
609}
610
611
612static int lzo_get_method(header_t *h)
613{
614
615 if (h->method == M_LZO1X_1) {
616 if (h->level == 0)
617 h->level = 3;
618 } else if (h->method == M_LZO1X_1_15) {
619 if (h->level == 0)
620 h->level = 1;
621 } else if (h->method == M_LZO1X_999) {
622 if (h->level == 0)
623 h->level = 9;
624 } else
625 return -1;
626
627
628 if (h->level < 1 || h->level > 9)
629 return 15;
630
631 return 0;
632}
633
634
635#define LZO_BLOCK_SIZE (256 * 1024l)
636#define MAX_BLOCK_SIZE (64 * 1024l * 1024l)
637
638
639#define MAX_COMPRESSED_SIZE(x) ((x) + (x) / 16 + 64 + 3)
640
641
642
643
644static NOINLINE int lzo_compress(const header_t *h)
645{
646 unsigned block_size = LZO_BLOCK_SIZE;
647 int r = 0;
648 uint8_t *const b1 = xzalloc(block_size);
649 uint8_t *const b2 = xzalloc(MAX_COMPRESSED_SIZE(block_size));
650 unsigned src_len = 0, dst_len = 0;
651 uint32_t d_adler32 = ADLER32_INIT_VALUE;
652 uint32_t d_crc32 = CRC32_INIT_VALUE;
653 int l;
654 uint8_t *wrk_mem = NULL;
655
656 if (h->method == M_LZO1X_1)
657 wrk_mem = xzalloc(LZO1X_1_MEM_COMPRESS);
658 else if (h->method == M_LZO1X_1_15)
659 wrk_mem = xzalloc(LZO1X_1_15_MEM_COMPRESS);
660 else if (h->method == M_LZO1X_999)
661 wrk_mem = xzalloc(LZO1X_999_MEM_COMPRESS);
662
663 for (;;) {
664
665 l = full_read(0, b1, block_size);
666 src_len = (l > 0 ? l : 0);
667
668
669 write32(src_len);
670
671
672 if (src_len == 0)
673 break;
674
675
676 if (h->flags & F_ADLER32_D)
677 d_adler32 = lzo_adler32(ADLER32_INIT_VALUE, b1, src_len);
678 if (h->flags & F_CRC32_D)
679 d_crc32 = lzo_crc32(CRC32_INIT_VALUE, b1, src_len);
680
681
682 if (h->method == M_LZO1X_1)
683 r = lzo1x_1_compress(b1, src_len, b2, &dst_len, wrk_mem);
684 else if (h->method == M_LZO1X_1_15)
685 r = lzo1x_1_15_compress(b1, src_len, b2, &dst_len, wrk_mem);
686#if ENABLE_LZOP_COMPR_HIGH
687 else if (h->method == M_LZO1X_999)
688 r = lzo1x_999_compress_level(b1, src_len, b2, &dst_len,
689 wrk_mem, h->level);
690#endif
691 else
692 bb_error_msg_and_die("internal error");
693
694 if (r != 0)
695 bb_error_msg_and_die("internal error - compression failed");
696
697
698 if (dst_len < src_len) {
699
700 if (h->method == M_LZO1X_999) {
701 unsigned new_len = src_len;
702 r = lzo1x_optimize(b2, dst_len, b1, &new_len, NULL);
703 if (r != 0 || new_len != src_len)
704 bb_error_msg_and_die("internal error - optimization failed");
705 }
706 write32(dst_len);
707 } else {
708
709 write32(src_len);
710 }
711
712
713 if (h->flags & F_ADLER32_D)
714 write32(d_adler32);
715 if (h->flags & F_CRC32_D)
716 write32(d_crc32);
717
718 if (dst_len < src_len) {
719
720 if (h->flags & F_ADLER32_C)
721 write32(lzo_adler32(ADLER32_INIT_VALUE, b2, dst_len));
722 if (h->flags & F_CRC32_C)
723 write32(lzo_crc32(CRC32_INIT_VALUE, b2, dst_len));
724
725 xwrite(1, b2, dst_len);
726 } else {
727
728 xwrite(1, b1, src_len);
729 }
730 }
731
732 free(wrk_mem);
733 free(b1);
734 free(b2);
735 return 1;
736}
737
738static FAST_FUNC void lzo_check(
739 uint32_t init,
740 uint8_t* buf, unsigned len,
741 uint32_t FAST_FUNC (*fn)(uint32_t, const uint8_t*, unsigned),
742 uint32_t ref)
743{
744
745
746
747
748 uint32_t c = fn(init, buf, len);
749 if (c != ref)
750 bb_error_msg_and_die("checksum error");
751}
752
753
754
755
756static NOINLINE int lzo_decompress(const header_t *h)
757{
758 unsigned block_size = LZO_BLOCK_SIZE;
759 int r;
760 uint32_t src_len, dst_len;
761 uint32_t c_adler32 = ADLER32_INIT_VALUE;
762 uint32_t d_adler32 = ADLER32_INIT_VALUE;
763 uint32_t c_crc32 = CRC32_INIT_VALUE, d_crc32 = CRC32_INIT_VALUE;
764 uint8_t *b1;
765 uint32_t mcs_block_size = MAX_COMPRESSED_SIZE(block_size);
766 uint8_t *b2 = NULL;
767
768 for (;;) {
769 uint8_t *dst;
770
771
772 dst_len = read32();
773
774
775 if (dst_len == 0)
776 break;
777
778
779 if (dst_len == 0xffffffffL)
780
781 bb_error_msg_and_die("this file is a split lzop file");
782
783 if (dst_len > MAX_BLOCK_SIZE)
784 bb_error_msg_and_die("corrupted data");
785
786
787 src_len = read32();
788 if (src_len <= 0 || src_len > dst_len)
789 bb_error_msg_and_die("corrupted data");
790
791 if (dst_len > block_size) {
792 if (b2) {
793 free(b2);
794 b2 = NULL;
795 }
796 block_size = dst_len;
797 mcs_block_size = MAX_COMPRESSED_SIZE(block_size);
798 }
799
800
801 if (h->flags & F_ADLER32_D)
802 d_adler32 = read32();
803 if (h->flags & F_CRC32_D)
804 d_crc32 = read32();
805
806
807 if (src_len < dst_len) {
808 if (h->flags & F_ADLER32_C)
809 c_adler32 = read32();
810 if (h->flags & F_CRC32_C)
811 c_crc32 = read32();
812 }
813
814 if (b2 == NULL)
815 b2 = xzalloc(mcs_block_size);
816
817 b1 = b2 + mcs_block_size - src_len;
818 xread(0, b1, src_len);
819
820 if (src_len < dst_len) {
821 unsigned d = dst_len;
822
823 if (!(option_mask32 & OPT_F)) {
824
825 if (h->flags & F_ADLER32_C)
826 lzo_check(ADLER32_INIT_VALUE,
827 b1, src_len,
828 lzo_adler32, c_adler32);
829 if (h->flags & F_CRC32_C)
830 lzo_check(CRC32_INIT_VALUE,
831 b1, src_len,
832 lzo_crc32, c_crc32);
833 }
834
835
836
837
838
839 r = lzo1x_decompress_safe(b1, src_len, b2, &d, NULL);
840
841 if (r != 0 || dst_len != d) {
842 bb_error_msg_and_die("corrupted data");
843 }
844 dst = b2;
845 } else {
846
847 dst = b1;
848 }
849
850 if (!(option_mask32 & OPT_F)) {
851
852 if (h->flags & F_ADLER32_D)
853 lzo_check(ADLER32_INIT_VALUE,
854 dst, dst_len,
855 lzo_adler32, d_adler32);
856 if (h->flags & F_CRC32_D)
857 lzo_check(CRC32_INIT_VALUE,
858 dst, dst_len,
859 lzo_crc32, d_crc32);
860 }
861
862
863 xwrite(1, dst, dst_len);
864 }
865
866 free(b2);
867 return 1;
868}
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899static const unsigned char lzop_magic[9] ALIGN1 = {
900 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a
901};
902
903
904static void check_magic(void)
905{
906 unsigned char magic[sizeof(lzop_magic)];
907 xread(0, magic, sizeof(magic));
908 if (memcmp(magic, lzop_magic, sizeof(lzop_magic)) != 0)
909 bb_error_msg_and_die("bad magic number");
910}
911
912
913
914
915static void write_header(const header_t *h)
916{
917 int l;
918
919 xwrite(1, lzop_magic, sizeof(lzop_magic));
920
921 init_chksum(&G.chksum_out);
922
923 f_write16(h->version);
924 f_write16(h->lib_version);
925 f_write16(h->version_needed_to_extract);
926 f_write8(h->method);
927 f_write8(h->level);
928 f_write32(h->flags);
929 f_write32(h->mode);
930 f_write32(h->mtime);
931 f_write32(h->gmtdiff);
932
933 l = (int) strlen(h->name);
934 f_write8(l);
935 if (l)
936 f_write(h->name, l);
937
938 f_write32(chksum_getresult(&G.chksum_out, h));
939}
940
941static int read_header(header_t *h)
942{
943 int r;
944 int l;
945 uint32_t checksum;
946
947 memset(h, 0, sizeof(*h));
948 h->version_needed_to_extract = 0x0900;
949 h->level = 0;
950
951 init_chksum(&G.chksum_in);
952
953 h->version = f_read16();
954 if (h->version < 0x0900)
955 return 3;
956 h->lib_version = f_read16();
957 if (h->version >= 0x0940) {
958 h->version_needed_to_extract = f_read16();
959 if (h->version_needed_to_extract > LZOP_VERSION)
960 return 16;
961 if (h->version_needed_to_extract < 0x0900)
962 return 3;
963 }
964 h->method = f_read8();
965 if (h->version >= 0x0940)
966 h->level = f_read8();
967 h->flags = f_read32();
968 if (h->flags & F_H_FILTER)
969 return 16;
970 h->mode = f_read32();
971 h->mtime = f_read32();
972 if (h->version >= 0x0940)
973 h->gmtdiff = f_read32();
974
975 l = f_read8();
976 if (l > 0)
977 f_read(h->name, l);
978 h->name[l] = 0;
979
980 checksum = chksum_getresult(&G.chksum_in, h);
981 h->header_checksum = f_read32();
982 if (h->header_checksum != checksum)
983 return 2;
984
985 if (h->method <= 0)
986 return 14;
987 r = lzo_get_method(h);
988 if (r != 0)
989 return r;
990
991
992 if (h->flags & F_RESERVED)
993 return -13;
994
995
996 if (h->flags & F_H_EXTRA_FIELD) {
997 uint32_t k;
998
999
1000 init_chksum(&G.chksum_in);
1001 h->extra_field_len = f_read32();
1002 for (k = 0; k < h->extra_field_len; k++)
1003 f_read8();
1004 checksum = chksum_getresult(&G.chksum_in, h);
1005 h->extra_field_checksum = f_read32();
1006 if (h->extra_field_checksum != checksum)
1007 return 3;
1008 }
1009
1010 return 0;
1011}
1012
1013static void p_header(header_t *h)
1014{
1015 int r;
1016
1017 r = read_header(h);
1018 if (r == 0)
1019 return;
1020 bb_error_msg_and_die("header_error %d", r);
1021}
1022
1023
1024
1025
1026static void lzo_set_method(header_t *h)
1027{
1028 int level = 1;
1029
1030 if (option_mask32 & OPT_1) {
1031 h->method = M_LZO1X_1_15;
1032 } else if (option_mask32 & OPT_789) {
1033#if ENABLE_LZOP_COMPR_HIGH
1034 h->method = M_LZO1X_999;
1035 if (option_mask32 & OPT_7)
1036 level = 7;
1037 else if (option_mask32 & OPT_8)
1038 level = 8;
1039 else
1040 level = 9;
1041#else
1042 bb_error_msg_and_die("high compression not compiled in");
1043#endif
1044 } else {
1045 h->method = M_LZO1X_1;
1046 level = 5;
1047 }
1048
1049 h->level = level;
1050}
1051
1052static int do_lzo_compress(void)
1053{
1054 header_t header;
1055
1056#define h (&header)
1057 memset(h, 0, sizeof(*h));
1058
1059 lzo_set_method(h);
1060
1061 h->version = (LZOP_VERSION & 0xffff);
1062 h->version_needed_to_extract = 0x0940;
1063 h->lib_version = lzo_version() & 0xffff;
1064
1065 h->flags = (F_OS & F_OS_MASK) | (F_CS & F_CS_MASK);
1066
1067 if (!(option_mask32 & OPT_F) || h->method == M_LZO1X_999) {
1068 h->flags |= F_ADLER32_D;
1069 if (option_mask32 & OPT_C)
1070 h->flags |= F_ADLER32_C;
1071 }
1072 write_header(h);
1073 return lzo_compress(h);
1074#undef h
1075}
1076
1077
1078
1079
1080static int do_lzo_decompress(void)
1081{
1082 header_t header;
1083
1084 check_magic();
1085 p_header(&header);
1086 return lzo_decompress(&header);
1087}
1088
1089static char* FAST_FUNC make_new_name_lzop(char *filename, const char *expected_ext UNUSED_PARAM)
1090{
1091 if (option_mask32 & OPT_DECOMPRESS) {
1092 char *extension = strrchr(filename, '.');
1093 if (!extension || strcmp(extension + 1, "lzo") != 0)
1094 return xasprintf("%s.out", filename);
1095 *extension = '\0';
1096 return filename;
1097 }
1098 return xasprintf("%s.lzo", filename);
1099}
1100
1101static IF_DESKTOP(long long) int FAST_FUNC pack_lzop(transformer_state_t *xstate UNUSED_PARAM)
1102{
1103 if (option_mask32 & OPT_DECOMPRESS)
1104 return do_lzo_decompress();
1105 return do_lzo_compress();
1106}
1107
1108int lzop_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1109int lzop_main(int argc UNUSED_PARAM, char **argv)
1110{
1111 getopt32(argv, OPTION_STRING);
1112 argv += optind;
1113
1114 if (applet_name[4] == 'c')
1115 option_mask32 |= (OPT_STDOUT | OPT_DECOMPRESS);
1116
1117 if (applet_name[4] == 'o')
1118 option_mask32 |= OPT_DECOMPRESS;
1119
1120 global_crc32_table = crc32_filltable(NULL, 0);
1121 return bbunpack(argv, pack_lzop, make_new_name_lzop, NULL);
1122}
1123