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