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