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#include "libbb.h"
93#include "common_bufsiz.h"
94#include "bb_archive.h"
95#include "liblzo_interface.h"
96
97
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
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
109#define NO_LIT UINT_MAX
110
111
112static 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
121static 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
139
140#define TEST_IP (ip < ip_end)
141#define TEST_OP (op <= op_end)
142
143static 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
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 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
458 char name[255+1];
459} header_t;
460
461struct globals {
462
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
469
470
471
472
473
474
475#define LZOP_VERSION 0x1010
476
477
478
479
480
481
482#define OPTION_STRING "cfUvqdt123456789CFk"
483
484
485enum {
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
510
511
512
513static FAST_FUNC uint32_t
514lzo_adler32(uint32_t adler, const uint8_t* buf, unsigned len)
515{
516 enum {
517 LZO_BASE = 65521,
518
519
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
542static FAST_FUNC uint32_t
543lzo_crc32(uint32_t c, const uint8_t* buf, unsigned len)
544{
545
546
547
548 return ~crc32_block_endian0(~c, buf, len, global_crc32_table);
549}
550
551
552static void init_chksum(chksum_t *ct)
553{
554 ct->f_adler32 = ADLER32_INIT_VALUE;
555 ct->f_crc32 = CRC32_INIT_VALUE;
556}
557
558static void add_bytes_to_chksum(chksum_t *ct, const void* buf, int cnt)
559{
560
561
562
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
567static 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
573static uint32_t read32(void)
574{
575 uint32_t v;
576 xread(0, &v, 4);
577 return ntohl(v);
578}
579
580static void write32(uint32_t v)
581{
582 v = htonl(v);
583 xwrite(1, &v, 4);
584}
585
586static 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
592static 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
598static int f_read8(void)
599{
600 uint8_t v;
601 f_read(&v, 1);
602 return v;
603}
604
605static void f_write8(uint8_t v)
606{
607 f_write(&v, 1);
608}
609
610static unsigned f_read16(void)
611{
612 uint16_t v;
613 f_read(&v, 2);
614 return ntohs(v);
615}
616
617static void f_write16(uint16_t v)
618{
619 v = htons(v);
620 f_write(&v, 2);
621}
622
623static uint32_t f_read32(void)
624{
625 uint32_t v;
626 f_read(&v, 4);
627 return ntohl(v);
628}
629
630static void f_write32(uint32_t v)
631{
632 v = htonl(v);
633 f_write(&v, 4);
634}
635
636
637static int lzo_get_method(header_t *h)
638{
639
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;
651
652
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)
662
663
664#define MAX_COMPRESSED_SIZE(x) ((x) + (x) / 16 + 64 + 3)
665
666
667
668
669static NOINLINE int lzo_compress(const header_t *h)
670{
671 unsigned block_size = LZO_BLOCK_SIZE;
672 int r = 0;
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
690 l = full_read(0, b1, block_size);
691 src_len = (l > 0 ? l : 0);
692
693
694 write32(src_len);
695
696
697 if (src_len == 0)
698 break;
699
700
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
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)
720 bb_error_msg_and_die("internal error - compression failed");
721
722
723 if (dst_len < src_len) {
724
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 || new_len != src_len)
729 bb_error_msg_and_die("internal error - optimization failed");
730 }
731 write32(dst_len);
732 } else {
733
734 write32(src_len);
735 }
736
737
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
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
750 xwrite(1, b2, dst_len);
751 } else {
752
753 xwrite(1, b1, src_len);
754 }
755 }
756
757 free(wrk_mem);
758 free(b1);
759 free(b2);
760 return 1;
761}
762
763static 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
770
771
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
780
781static 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
797 dst_len = read32();
798
799
800 if (dst_len == 0)
801 break;
802
803
804 if (dst_len == 0xffffffffL)
805
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
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
826 if (h->flags & F_ADLER32_D)
827 d_adler32 = read32();
828 if (h->flags & F_CRC32_D)
829 d_crc32 = read32();
830
831
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
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
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
861
862
863
864 r = lzo1x_decompress_safe(b1, src_len, b2, &d, NULL);
865
866 if (r != 0 || dst_len != d) {
867 bb_error_msg_and_die("corrupted data");
868 }
869 dst = b2;
870 } else {
871
872 dst = b1;
873 }
874
875 if (!(option_mask32 & OPT_F)) {
876
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
888 xwrite(1, dst, dst_len);
889 }
890
891 free(b2);
892 return 1;
893}
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924static const unsigned char lzop_magic[9] ALIGN1 = {
925 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a
926};
927
928
929static 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
939
940static 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
966static 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;
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;
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
1017 if (h->flags & F_RESERVED)
1018 return -13;
1019
1020
1021 if (h->flags & F_H_EXTRA_FIELD) {
1022 uint32_t k;
1023
1024
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
1038static 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
1050
1051static 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 {
1070 h->method = M_LZO1X_1;
1071 level = 5;
1072 }
1073
1074 h->level = level;
1075}
1076
1077static 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
1104
1105static 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
1114static 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
1126static 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
1133int lzop_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1134int lzop_main(int argc UNUSED_PARAM, char **argv)
1135{
1136 getopt32(argv, OPTION_STRING);
1137 argv += optind;
1138
1139 option_mask32 ^= OPT_KEEP;
1140
1141
1142 if (option_mask32 & OPT_k)
1143 option_mask32 |= OPT_KEEP;
1144
1145
1146 if (ENABLE_LZOPCAT && applet_name[4] == 'c')
1147 option_mask32 |= (OPT_STDOUT | OPT_DECOMPRESS);
1148
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, NULL);
1154}
1155