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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93#include "libbb.h"
94#include "common_bufsiz.h"
95#include "bb_archive.h"
96#include "liblzo_interface.h"
97
98
99#define pd(a,b) ((unsigned)((a)-(b)))
100
101#define lzo_version() LZO_VERSION
102#define lzo_sizeof_dict_t (sizeof(uint8_t*))
103
104
105#define LZO1X_1_MEM_COMPRESS (16384 * lzo_sizeof_dict_t)
106#define LZO1X_1_15_MEM_COMPRESS (32768 * lzo_sizeof_dict_t)
107#define LZO1X_999_MEM_COMPRESS (14 * 16384 * sizeof(short))
108
109
110#define NO_LIT UINT_MAX
111
112
113static void copy2(uint8_t* ip, const uint8_t* m_pos, unsigned off)
114{
115 ip[0] = m_pos[0];
116 if (off == 1)
117 ip[1] = m_pos[0];
118 else
119 ip[1] = m_pos[1];
120}
121
122static void copy3(uint8_t* ip, const uint8_t* m_pos, unsigned off)
123{
124 ip[0] = m_pos[0];
125 if (off == 1) {
126 ip[2] = ip[1] = m_pos[0];
127 }
128 else if (off == 2) {
129 ip[1] = m_pos[1];
130 ip[2] = m_pos[0];
131 }
132 else {
133 ip[1] = m_pos[1];
134 ip[2] = m_pos[2];
135 }
136}
137
138
139
140
141#define TEST_IP (ip < ip_end)
142#define TEST_OP (op <= op_end)
143
144static NOINLINE int lzo1x_optimize(uint8_t *in, unsigned in_len,
145 uint8_t *out, unsigned *out_len )
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
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
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
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
213 do {
214 if (t < 16) {
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
224 if (nl == 0 && lit == 1 && ip[0] >= 16) {
225 next_lit = nl;
226
227 lit += 2;
228 *litp = (unsigned char)((*litp & ~3) | lit);
229
230 copy2(ip-2, m_pos, pd(op, m_pos));
231 o_m1_a++;
232 }
233
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
242 *litp &= ~3;
243
244 copy2(ip-3+1, m_pos, pd(op, m_pos));
245
246 litp += 2;
247 if (lit > 0)
248 memmove(litp+1, litp, lit);
249
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) {
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
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
284 copy3(ip-1-2, m_pos, pd(op, m_pos));
285
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) {
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 {
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
327 if (t == 1 && lit == 0 && nl == 0 && ip[0] >= 16) {
328 next_lit = nl;
329
330 lit += 3;
331 *litp = (unsigned char)((*litp & ~3) | lit);
332
333 copy3(ip-3, m_pos, pd(op, m_pos));
334 o_m3_a++;
335 }
336
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
342 *litp &= ~3;
343
344 copy3(ip-4+1, m_pos, pd(op, m_pos));
345
346 litp += 2;
347 if (lit > 0)
348 memmove(litp+1,litp,lit);
349
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
378 match_next:
379 do *op++ = *ip++; while (--t > 0);
380 t = *ip++;
381 } while (TEST_IP && TEST_OP);
382 }
383
384
385 *out_len = pd(op, out);
386 return LZO_E_EOF_NOT_FOUND;
387
388 eof_found:
389
390
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
405enum {
406 M_LZO1X_1 = 1,
407 M_LZO1X_1_15 = 2,
408 M_LZO1X_999 = 3,
409};
410
411
412
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
424#define F_OS_UNIX 0x03000000L
425#define F_OS_SHIFT 24
426#define F_OS_MASK 0xff000000L
427
428
429#define F_CS_NATIVE 0x00000000L
430#define F_CS_SHIFT 20
431#define F_CS_MASK 0x00f00000L
432
433
434#define F_RESERVED ((F_MASK | F_OS_MASK | F_CS_MASK) ^ 0xffffffffL)
435
436typedef struct chksum_t {
437 uint32_t f_adler32;
438 uint32_t f_crc32;
439} chksum_t;
440
441typedef struct header_t {
442
443
444
445
446
447 uint16_t version_be16;
448 uint16_t lib_version_be16;
449 uint16_t version_needed_to_extract_be16;
450 uint8_t method;
451 uint8_t level;
452 uint32_t flags32;
453 uint32_t mode_be32;
454 uint32_t mtime_be32;
455 uint32_t gmtdiff_be32;
456 char len_and_name[1+255+1];
457} header_t;
458
459struct globals {
460
461 chksum_t chksum;
462} FIX_ALIASING;
463#define G (*(struct globals*)bb_common_bufsiz1)
464
465#define INIT_G() do { \
466 setup_common_bufsiz(); \
467 \
468} while (0)
469
470
471
472#define LZOP_VERSION 0x1010
473
474
475
476
477
478
479#define OPTION_STRING "cfUvqdt123456789CFk"
480
481
482enum {
483 OPT_STDOUT = (1 << 0),
484 OPT_FORCE = (1 << 1),
485 OPT_KEEP = (1 << 2),
486 OPT_VERBOSE = (1 << 3),
487 OPT_QUIET = (1 << 4),
488 OPT_DECOMPRESS = (1 << 5),
489 OPT_TEST = (1 << 6),
490 OPT_1 = (1 << 7),
491 OPT_2 = (1 << 8),
492 OPT_3 = (1 << 9),
493 OPT_4 = (1 << 10),
494 OPT_5 = (1 << 11),
495 OPT_6 = (1 << 12),
496 OPT_7 = (1 << 13),
497 OPT_8 = (1 << 14),
498 OPT_9 = (1 << 15),
499 OPT_C = (1 << 16),
500 OPT_F = (1 << 17),
501 OPT_k = (1 << 18),
502 OPT_789 = OPT_7 | OPT_8 | OPT_9
503};
504
505
506
507
508
509
510static FAST_FUNC uint32_t
511lzo_adler32(uint32_t adler, const uint8_t* buf, unsigned len)
512{
513 enum {
514 LZO_BASE = 65521,
515
516
517 LZO_NMAX = 5552,
518 };
519 uint32_t s1 = adler & 0xffff;
520 uint32_t s2 = (adler >> 16) & 0xffff;
521 unsigned k;
522
523 if (buf == NULL)
524 return 1;
525
526 while (len > 0) {
527 k = len < LZO_NMAX ? (unsigned) len : LZO_NMAX;
528 len -= k;
529 if (k != 0) do {
530 s1 += *buf++;
531 s2 += s1;
532 } while (--k > 0);
533 s1 %= LZO_BASE;
534 s2 %= LZO_BASE;
535 }
536 return (s2 << 16) | s1;
537}
538
539static FAST_FUNC uint32_t
540lzo_crc32(uint32_t c, const uint8_t* buf, unsigned len)
541{
542
543
544
545 return ~crc32_block_endian0(~c, buf, len, global_crc32_table);
546}
547
548
549static void init_chksum(void)
550{
551 G.chksum.f_adler32 = ADLER32_INIT_VALUE;
552 G.chksum.f_crc32 = CRC32_INIT_VALUE;
553}
554
555static void add_bytes_to_chksum(const void* buf, int cnt)
556{
557
558
559
560 G.chksum.f_adler32 = lzo_adler32(G.chksum.f_adler32, (const uint8_t*)buf, cnt);
561 G.chksum.f_crc32 = lzo_crc32(G.chksum.f_crc32, (const uint8_t*)buf, cnt);
562}
563
564static uint32_t chksum_getresult(uint32_t h_flags32)
565{
566 return (h_flags32 & F_H_CRC32) ? G.chksum.f_crc32 : G.chksum.f_adler32;
567}
568
569
570static uint32_t read32(void)
571{
572 uint32_t v;
573 xread(0, &v, 4);
574 return ntohl(v);
575}
576static void f_read(void* buf, int cnt)
577{
578 xread(0, buf, cnt);
579 add_bytes_to_chksum(buf, cnt);
580}
581
582
583
584
585
586
587
588
589
590
591
592
593static uint32_t f_read32(void)
594{
595 uint32_t v;
596 f_read(&v, 4);
597 return ntohl(v);
598}
599
600static void write32(uint32_t v)
601{
602 v = htonl(v);
603 xwrite(1, &v, 4);
604}
605static void f_write(const void* buf, int cnt)
606{
607 xwrite(1, buf, cnt);
608 add_bytes_to_chksum(buf, cnt);
609}
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626#define LZO_BLOCK_SIZE (256 * 1024l)
627#define MAX_BLOCK_SIZE (64 * 1024l * 1024l)
628
629
630#define MAX_COMPRESSED_SIZE(x) ((x) + (x) / 16 + 64 + 3)
631
632
633
634
635static NOINLINE int lzo_compress(const header_t *h)
636{
637 unsigned block_size = LZO_BLOCK_SIZE;
638 int r = 0;
639 uint8_t *const b1 = xzalloc(block_size);
640 uint8_t *const b2 = xzalloc(MAX_COMPRESSED_SIZE(block_size));
641 uint32_t d_adler32 = ADLER32_INIT_VALUE;
642 uint32_t d_crc32 = CRC32_INIT_VALUE;
643 uint8_t *wrk_mem = NULL;
644
645
646
647
648
649
650 if (h->method == M_LZO1X_1)
651 wrk_mem = xzalloc(LZO1X_1_MEM_COMPRESS);
652 else
653 IF_LZOP_COMPR_HIGH(if (h->method == M_LZO1X_1_15))
654 wrk_mem = xzalloc(LZO1X_1_15_MEM_COMPRESS);
655#if ENABLE_LZOP_COMPR_HIGH
656 else
657 wrk_mem = xzalloc(LZO1X_999_MEM_COMPRESS);
658#endif
659
660 for (;;) {
661 unsigned src_len, dst_len;
662 int l;
663 uint32_t wordbuf[6];
664 uint32_t *wordptr = wordbuf;
665
666
667 l = full_read(0, b1, block_size);
668 src_len = (l > 0 ? l : 0);
669
670
671
672 if (src_len == 0) {
673 write32(0);
674 break;
675 }
676 *wordptr++ = htonl(src_len);
677
678
679 if (h->flags32 & F_ADLER32_D)
680 d_adler32 = lzo_adler32(ADLER32_INIT_VALUE, b1, src_len);
681 if (h->flags32 & F_CRC32_D)
682 d_crc32 = lzo_crc32(CRC32_INIT_VALUE, b1, src_len);
683
684
685 if (h->method == M_LZO1X_1)
686 r = lzo1x_1_compress(b1, src_len, b2, &dst_len, wrk_mem);
687 else IF_LZOP_COMPR_HIGH(if (h->method == M_LZO1X_1_15))
688 r = lzo1x_1_15_compress(b1, src_len, b2, &dst_len, wrk_mem);
689#if ENABLE_LZOP_COMPR_HIGH
690 else
691 r = lzo1x_999_compress_level(b1, src_len, b2, &dst_len,
692 wrk_mem, h->level);
693#endif
694 if (r != 0)
695 bb_error_msg_and_die("%s: %s", "internal error", "compression");
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 );
703 if (r != 0 || new_len != src_len)
704 bb_error_msg_and_die("%s: %s", "internal error", "optimization");
705 }
706 *wordptr++ = htonl(dst_len);
707 } else {
708
709 *wordptr++ = htonl(src_len);
710 }
711
712
713 if (h->flags32 & F_ADLER32_D)
714 *wordptr++ = htonl(d_adler32);
715 if (h->flags32 & F_CRC32_D)
716 *wordptr++ = htonl(d_crc32);
717
718 if (dst_len < src_len) {
719
720 if (h->flags32 & F_ADLER32_C)
721 *wordptr++ = htonl(lzo_adler32(ADLER32_INIT_VALUE, b2, dst_len));
722 if (h->flags32 & F_CRC32_C)
723 *wordptr++ = htonl(lzo_crc32(CRC32_INIT_VALUE, b2, dst_len));
724 }
725 xwrite(1, wordbuf, ((char*)wordptr) - ((char*)wordbuf));
726 if (dst_len < src_len) {
727
728 xwrite(1, b2, dst_len);
729 } else {
730
731 xwrite(1, b1, src_len);
732 }
733
734
735
736 }
737
738 free(wrk_mem);
739 free(b1);
740 free(b2);
741 return 1;
742}
743
744static FAST_FUNC void lzo_check(
745 uint32_t init,
746 uint8_t* buf, unsigned len,
747 uint32_t FAST_FUNC (*fn)(uint32_t, const uint8_t*, unsigned),
748 uint32_t ref)
749{
750
751
752
753
754 uint32_t c = fn(init, buf, len);
755 if (c != ref)
756 bb_simple_error_msg_and_die("checksum error");
757}
758
759
760
761
762
763
764static NOINLINE int lzo_decompress(uint32_t h_flags32)
765{
766 unsigned block_size = LZO_BLOCK_SIZE;
767 int r;
768 uint32_t src_len, dst_len;
769 uint32_t c_adler32 = ADLER32_INIT_VALUE;
770 uint32_t d_adler32 = ADLER32_INIT_VALUE;
771 uint32_t c_crc32 = CRC32_INIT_VALUE, d_crc32 = CRC32_INIT_VALUE;
772 uint8_t *b1;
773 uint32_t mcs_block_size = MAX_COMPRESSED_SIZE(block_size);
774 uint8_t *b2 = NULL;
775
776 for (;;) {
777 uint8_t *dst;
778
779
780 dst_len = read32();
781
782
783 if (dst_len == 0)
784 break;
785
786
787 if (dst_len == 0xffffffffL)
788
789 bb_simple_error_msg_and_die("this file is a split lzop file");
790
791 if (dst_len > MAX_BLOCK_SIZE)
792 bb_simple_error_msg_and_die("corrupted data");
793
794
795 src_len = read32();
796 if (src_len <= 0 || src_len > dst_len)
797 bb_simple_error_msg_and_die("corrupted data");
798
799 if (dst_len > block_size) {
800 if (b2) {
801 free(b2);
802 b2 = NULL;
803 }
804 block_size = dst_len;
805 mcs_block_size = MAX_COMPRESSED_SIZE(block_size);
806 }
807
808
809 if (h_flags32 & F_ADLER32_D)
810 d_adler32 = read32();
811 if (h_flags32 & F_CRC32_D)
812 d_crc32 = read32();
813
814
815 if (src_len < dst_len) {
816 if (h_flags32 & F_ADLER32_C)
817 c_adler32 = read32();
818 if (h_flags32 & F_CRC32_C)
819 c_crc32 = read32();
820 }
821
822 if (b2 == NULL)
823 b2 = xzalloc(mcs_block_size);
824
825 b1 = b2 + mcs_block_size - src_len;
826 xread(0, b1, src_len);
827
828 if (src_len < dst_len) {
829 unsigned d = dst_len;
830
831 if (!(option_mask32 & OPT_F)) {
832
833 if (h_flags32 & F_ADLER32_C)
834 lzo_check(ADLER32_INIT_VALUE,
835 b1, src_len,
836 lzo_adler32, c_adler32);
837 if (h_flags32 & F_CRC32_C)
838 lzo_check(CRC32_INIT_VALUE,
839 b1, src_len,
840 lzo_crc32, c_crc32);
841 }
842
843
844
845
846
847 r = lzo1x_decompress_safe(b1, src_len, b2, &d );
848
849 if (r != 0 || dst_len != d) {
850 bb_simple_error_msg_and_die("corrupted data");
851 }
852 dst = b2;
853 } else {
854
855 dst = b1;
856 }
857
858 if (!(option_mask32 & OPT_F)) {
859
860 if (h_flags32 & F_ADLER32_D)
861 lzo_check(ADLER32_INIT_VALUE,
862 dst, dst_len,
863 lzo_adler32, d_adler32);
864 if (h_flags32 & F_CRC32_D)
865 lzo_check(CRC32_INIT_VALUE,
866 dst, dst_len,
867 lzo_crc32, d_crc32);
868 }
869
870
871 xwrite(1, dst, dst_len);
872 }
873
874 free(b2);
875 return 1;
876}
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907static const unsigned char lzop_magic[9] ALIGN1 = {
908 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a
909};
910
911
912static void check_magic(void)
913{
914 unsigned char magic[sizeof(lzop_magic)];
915 xread(0, magic, sizeof(magic));
916 if (memcmp(magic, lzop_magic, sizeof(lzop_magic)) != 0)
917 bb_simple_error_msg_and_die("bad magic number");
918}
919
920
921
922
923static void write_header(header_t *h)
924{
925 char *end;
926
927 xwrite(1, lzop_magic, sizeof(lzop_magic));
928
929 init_chksum();
930
931
932 end = h->len_and_name+1 + 0;
933
934
935
936 f_write(&h->version_be16, end - (char*)&h->version_be16);
937
938 h->flags32 = htonl(h->flags32);
939
940 write32(chksum_getresult(h->flags32));
941}
942
943static int read_header(header_t *h)
944{
945 int l;
946 uint32_t checksum;
947
948
949
950 unsigned h_version;
951 unsigned h_version_needed_to_extract;
952
953 init_chksum();
954
955
956
957
958
959
960
961
962 f_read(&h->version_be16, ((char*)&h->len_and_name[1]) - ((char*)&h->version_be16));
963
964 h_version = htons(h->version_be16);
965 if (h_version < 0x0940)
966 return 3;
967 h_version_needed_to_extract = htons(h->version_needed_to_extract_be16);
968 if (h_version_needed_to_extract > LZOP_VERSION)
969 return 16;
970 if (h_version_needed_to_extract < 0x0940)
971 return 3;
972
973 if (h->method <= 0)
974 return 14;
975
976
977 if (h->method == M_LZO1X_1) {
978 if (h->level == 0)
979 h->level = 3;
980 } else if (h->method == M_LZO1X_1_15) {
981 if (h->level == 0)
982 h->level = 1;
983 } else if (h->method == M_LZO1X_999) {
984 if (h->level == 0)
985 h->level = 9;
986 } else
987 return -1;
988
989 if (h->level < 1 || h->level > 9)
990 return 15;
991
992 h->flags32 = ntohl(h->flags32);
993 if (h->flags32 & F_H_FILTER)
994 return 16;
995
996 if (h->flags32 & F_RESERVED)
997 return -13;
998
999 l = h->len_and_name[0];
1000 if (l > 0)
1001 f_read(h->len_and_name+1, l);
1002
1003
1004 checksum = chksum_getresult(h->flags32);
1005 if (read32() != checksum)
1006 return 2;
1007
1008
1009 if (h->flags32 & F_H_EXTRA_FIELD) {
1010 uint32_t extra_field_len;
1011 uint32_t extra_field_checksum;
1012 uint32_t k;
1013 char dummy;
1014
1015
1016 init_chksum();
1017 extra_field_len = f_read32();
1018 for (k = 0; k < extra_field_len; k++)
1019 f_read(&dummy, 1);
1020 checksum = chksum_getresult(h->flags32);
1021 extra_field_checksum = read32();
1022 if (extra_field_checksum != checksum)
1023 return 3;
1024 }
1025
1026 return 0;
1027}
1028
1029
1030
1031
1032static void lzo_set_method(header_t *h)
1033{
1034 smallint level;
1035
1036
1037 h->method = M_LZO1X_1;
1038 level = 5;
1039
1040 if (option_mask32 & OPT_1) {
1041 h->method = M_LZO1X_1_15;
1042 level = 1;
1043 }
1044 if (option_mask32 & OPT_789) {
1045#if ENABLE_LZOP_COMPR_HIGH
1046 h->method = M_LZO1X_999;
1047 level = 9;
1048 if (option_mask32 & OPT_7)
1049 level = 7;
1050 else if (option_mask32 & OPT_8)
1051 level = 8;
1052#else
1053 bb_simple_error_msg_and_die("high compression not compiled in");
1054#endif
1055 }
1056
1057 h->level = level;
1058}
1059
1060static int do_lzo_compress(void)
1061{
1062 header_t header;
1063
1064#define h (&header)
1065 memset(h, 0, sizeof(*h));
1066
1067 lzo_set_method(h);
1068
1069 h->version_be16 = htons(LZOP_VERSION & 0xffff);
1070 h->version_needed_to_extract_be16 = htons(0x0940);
1071 h->lib_version_be16 = htons(lzo_version() & 0xffff);
1072
1073 h->flags32 = htonl((F_OS & F_OS_MASK) | (F_CS & F_CS_MASK));
1074
1075 if (!(option_mask32 & OPT_F) || h->method == M_LZO1X_999) {
1076 h->flags32 |= htonl(F_ADLER32_D);
1077 if (option_mask32 & OPT_C)
1078 h->flags32 |= htonl(F_ADLER32_C);
1079 }
1080
1081
1082 write_header(h);
1083
1084 return lzo_compress(h);
1085#undef h
1086}
1087
1088
1089
1090
1091static int do_lzo_decompress(void)
1092{
1093 int r;
1094 header_t header;
1095
1096 check_magic();
1097 r = read_header(&header);
1098 if (r != 0)
1099 bb_error_msg_and_die("header_error %d", r);
1100 return lzo_decompress(header.flags32);
1101}
1102
1103static char* FAST_FUNC make_new_name_lzop(char *filename, const char *expected_ext UNUSED_PARAM)
1104{
1105 if (option_mask32 & OPT_DECOMPRESS) {
1106 char *extension = strrchr(filename, '.');
1107 if (!extension || strcmp(extension + 1, "lzo") != 0)
1108 return xasprintf("%s.out", filename);
1109 *extension = '\0';
1110 return filename;
1111 }
1112 return xasprintf("%s.lzo", filename);
1113}
1114
1115static IF_DESKTOP(long long) int FAST_FUNC pack_lzop(transformer_state_t *xstate UNUSED_PARAM)
1116{
1117 if (option_mask32 & OPT_DECOMPRESS)
1118 return do_lzo_decompress();
1119 return do_lzo_compress();
1120}
1121
1122int lzop_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1123int lzop_main(int argc UNUSED_PARAM, char **argv)
1124{
1125 INIT_G();
1126
1127 getopt32(argv, OPTION_STRING);
1128 argv += optind;
1129
1130 option_mask32 ^= OPT_KEEP;
1131
1132
1133 if (option_mask32 & OPT_k)
1134 option_mask32 |= OPT_KEEP;
1135
1136
1137 if (ENABLE_LZOPCAT && applet_name[4] == 'c')
1138 option_mask32 |= (OPT_STDOUT | OPT_DECOMPRESS);
1139
1140 if (ENABLE_UNLZOP && applet_name[4] == 'o')
1141 option_mask32 |= OPT_DECOMPRESS;
1142
1143 global_crc32_new_table_le();
1144 return bbunpack(argv, pack_lzop, make_new_name_lzop, NULL);
1145}
1146