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