[3320] | 1 | /*
|
---|
| 2 | This file is part of the lzop file compressor.
|
---|
| 3 |
|
---|
| 4 | Copyright (C) 1996..2003 Markus Franz Xaver Johannes Oberhumer
|
---|
| 5 | All Rights Reserved.
|
---|
| 6 |
|
---|
| 7 | Markus F.X.J. Oberhumer <markus@oberhumer.com>
|
---|
| 8 | http://www.oberhumer.com/opensource/lzop/
|
---|
| 9 |
|
---|
| 10 | lzop and the LZO library are free software; you can redistribute them
|
---|
| 11 | and/or modify them under the terms of the GNU General Public License as
|
---|
| 12 | published by the Free Software Foundation; either version 2 of
|
---|
| 13 | the License, or (at your option) any later version.
|
---|
| 14 |
|
---|
| 15 | This program is distributed in the hope that it will be useful,
|
---|
| 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
| 18 | GNU General Public License for more details.
|
---|
| 19 |
|
---|
| 20 | You should have received a copy of the GNU General Public License
|
---|
| 21 | along with this program; see the file COPYING.
|
---|
| 22 | If not, write to the Free Software Foundation, Inc.,
|
---|
| 23 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
---|
| 24 |
|
---|
| 25 | "Minimalized" for busybox by Alain Knaff
|
---|
| 26 | */
|
---|
| 27 |
|
---|
| 28 | #include "libbb.h"
|
---|
| 29 | #include "archive.h"
|
---|
| 30 | #include "liblzo_interface.h"
|
---|
| 31 |
|
---|
| 32 | /* lzo-2.03/src/lzo_ptr.h */
|
---|
| 33 | #define pd(a,b) ((unsigned)((a)-(b)))
|
---|
| 34 |
|
---|
| 35 | #define lzo_version() LZO_VERSION
|
---|
| 36 | #define lzo_sizeof_dict_t (sizeof(uint8_t*))
|
---|
| 37 |
|
---|
| 38 | /* lzo-2.03/include/lzo/lzo1x.h */
|
---|
| 39 | #define LZO1X_1_MEM_COMPRESS (16384 * lzo_sizeof_dict_t)
|
---|
| 40 | #define LZO1X_1_15_MEM_COMPRESS (32768 * lzo_sizeof_dict_t)
|
---|
| 41 | #define LZO1X_999_MEM_COMPRESS (14 * 16384 * sizeof(short))
|
---|
| 42 |
|
---|
| 43 | /* lzo-2.03/src/lzo1x_oo.c */
|
---|
| 44 | #define NO_LIT UINT_MAX
|
---|
| 45 |
|
---|
| 46 | /**********************************************************************/
|
---|
| 47 | static void copy2(uint8_t* ip, const uint8_t* m_pos, unsigned off)
|
---|
| 48 | {
|
---|
| 49 | ip[0] = m_pos[0];
|
---|
| 50 | if (off == 1)
|
---|
| 51 | ip[1] = m_pos[0];
|
---|
| 52 | else
|
---|
| 53 | ip[1] = m_pos[1];
|
---|
| 54 | }
|
---|
| 55 |
|
---|
| 56 | static void copy3(uint8_t* ip, const uint8_t* m_pos, unsigned off)
|
---|
| 57 | {
|
---|
| 58 | ip[0] = m_pos[0];
|
---|
| 59 | if (off == 1) {
|
---|
| 60 | ip[2] = ip[1] = m_pos[0];
|
---|
| 61 | }
|
---|
| 62 | else if (off == 2) {
|
---|
| 63 | ip[1] = m_pos[1];
|
---|
| 64 | ip[2] = m_pos[0];
|
---|
| 65 | }
|
---|
| 66 | else {
|
---|
| 67 | ip[1] = m_pos[1];
|
---|
| 68 | ip[2] = m_pos[2];
|
---|
| 69 | }
|
---|
| 70 | }
|
---|
| 71 |
|
---|
| 72 | /**********************************************************************/
|
---|
| 73 | // optimize a block of data.
|
---|
| 74 | /**********************************************************************/
|
---|
| 75 | #define TEST_IP (ip < ip_end)
|
---|
| 76 | #define TEST_OP (op <= op_end)
|
---|
| 77 |
|
---|
| 78 | static NOINLINE int lzo1x_optimize(uint8_t *in, unsigned in_len,
|
---|
| 79 | uint8_t *out, unsigned *out_len,
|
---|
| 80 | void* wrkmem UNUSED_PARAM)
|
---|
| 81 | {
|
---|
| 82 | uint8_t* op;
|
---|
| 83 | uint8_t* ip;
|
---|
| 84 | unsigned t;
|
---|
| 85 | uint8_t* m_pos;
|
---|
| 86 | uint8_t* const ip_end = in + in_len;
|
---|
| 87 | uint8_t* const op_end = out + *out_len;
|
---|
| 88 | uint8_t* litp = NULL;
|
---|
| 89 | unsigned lit = 0;
|
---|
| 90 | unsigned next_lit = NO_LIT;
|
---|
| 91 | unsigned nl;
|
---|
| 92 | unsigned long o_m1_a = 0, o_m1_b = 0, o_m2 = 0, o_m3_a = 0, o_m3_b = 0;
|
---|
| 93 |
|
---|
| 94 | // LZO_UNUSED(wrkmem);
|
---|
| 95 |
|
---|
| 96 | *out_len = 0;
|
---|
| 97 |
|
---|
| 98 | op = out;
|
---|
| 99 | ip = in;
|
---|
| 100 |
|
---|
| 101 | if (*ip > 17) {
|
---|
| 102 | t = *ip++ - 17;
|
---|
| 103 | if (t < 4)
|
---|
| 104 | goto match_next;
|
---|
| 105 | goto first_literal_run;
|
---|
| 106 | }
|
---|
| 107 |
|
---|
| 108 | while (TEST_IP && TEST_OP) {
|
---|
| 109 | t = *ip++;
|
---|
| 110 | if (t >= 16)
|
---|
| 111 | goto match;
|
---|
| 112 | /* a literal run */
|
---|
| 113 | litp = ip - 1;
|
---|
| 114 | if (t == 0) {
|
---|
| 115 | t = 15;
|
---|
| 116 | while (*ip == 0)
|
---|
| 117 | t += 255, ip++;
|
---|
| 118 | t += *ip++;
|
---|
| 119 | }
|
---|
| 120 | lit = t + 3;
|
---|
| 121 | /* copy literals */
|
---|
| 122 | copy_literal_run:
|
---|
| 123 | *op++ = *ip++;
|
---|
| 124 | *op++ = *ip++;
|
---|
| 125 | *op++ = *ip++;
|
---|
| 126 | first_literal_run:
|
---|
| 127 | do *op++ = *ip++; while (--t > 0);
|
---|
| 128 |
|
---|
| 129 | t = *ip++;
|
---|
| 130 |
|
---|
| 131 | if (t >= 16)
|
---|
| 132 | goto match;
|
---|
| 133 | #if defined(LZO1X)
|
---|
| 134 | m_pos = op - 1 - 0x800;
|
---|
| 135 | #elif defined(LZO1Y)
|
---|
| 136 | m_pos = op - 1 - 0x400;
|
---|
| 137 | #endif
|
---|
| 138 | m_pos -= t >> 2;
|
---|
| 139 | m_pos -= *ip++ << 2;
|
---|
| 140 | *op++ = *m_pos++;
|
---|
| 141 | *op++ = *m_pos++;
|
---|
| 142 | *op++ = *m_pos++;
|
---|
| 143 | lit = 0;
|
---|
| 144 | goto match_done;
|
---|
| 145 |
|
---|
| 146 |
|
---|
| 147 | /* handle matches */
|
---|
| 148 | do {
|
---|
| 149 | if (t < 16) { /* a M1 match */
|
---|
| 150 | m_pos = op - 1;
|
---|
| 151 | m_pos -= t >> 2;
|
---|
| 152 | m_pos -= *ip++ << 2;
|
---|
| 153 |
|
---|
| 154 | if (litp == NULL)
|
---|
| 155 | goto copy_m1;
|
---|
| 156 |
|
---|
| 157 | nl = ip[-2] & 3;
|
---|
| 158 | /* test if a match follows */
|
---|
| 159 | if (nl == 0 && lit == 1 && ip[0] >= 16) {
|
---|
| 160 | next_lit = nl;
|
---|
| 161 | /* adjust length of previous short run */
|
---|
| 162 | lit += 2;
|
---|
| 163 | *litp = (unsigned char)((*litp & ~3) | lit);
|
---|
| 164 | /* copy over the 2 literals that replace the match */
|
---|
| 165 | copy2(ip-2, m_pos, pd(op, m_pos));
|
---|
| 166 | o_m1_a++;
|
---|
| 167 | }
|
---|
| 168 | /* test if a literal run follows */
|
---|
| 169 | else
|
---|
| 170 | if (nl == 0
|
---|
| 171 | && ip[0] < 16
|
---|
| 172 | && ip[0] != 0
|
---|
| 173 | && (lit + 2 + ip[0] < 16)
|
---|
| 174 | ) {
|
---|
| 175 | t = *ip++;
|
---|
| 176 | /* remove short run */
|
---|
| 177 | *litp &= ~3;
|
---|
| 178 | /* copy over the 2 literals that replace the match */
|
---|
| 179 | copy2(ip-3+1,m_pos,pd(op,m_pos));
|
---|
| 180 | /* move literals 1 byte ahead */
|
---|
| 181 | litp += 2;
|
---|
| 182 | if (lit > 0)
|
---|
| 183 | memmove(litp+1, litp, lit);
|
---|
| 184 | /* insert new length of long literal run */
|
---|
| 185 | lit += 2 + t + 3;
|
---|
| 186 | *litp = (unsigned char)(lit - 3);
|
---|
| 187 |
|
---|
| 188 | o_m1_b++;
|
---|
| 189 | *op++ = *m_pos++; *op++ = *m_pos++;
|
---|
| 190 | goto copy_literal_run;
|
---|
| 191 | }
|
---|
| 192 | copy_m1:
|
---|
| 193 | *op++ = *m_pos++;
|
---|
| 194 | *op++ = *m_pos++;
|
---|
| 195 | } else {
|
---|
| 196 | match:
|
---|
| 197 | if (t >= 64) { /* a M2 match */
|
---|
| 198 | m_pos = op - 1;
|
---|
| 199 | #if defined(LZO1X)
|
---|
| 200 | m_pos -= (t >> 2) & 7;
|
---|
| 201 | m_pos -= *ip++ << 3;
|
---|
| 202 | t = (t >> 5) - 1;
|
---|
| 203 | #elif defined(LZO1Y)
|
---|
| 204 | m_pos -= (t >> 2) & 3;
|
---|
| 205 | m_pos -= *ip++ << 2;
|
---|
| 206 | t = (t >> 4) - 3;
|
---|
| 207 | #endif
|
---|
| 208 | if (litp == NULL)
|
---|
| 209 | goto copy_m;
|
---|
| 210 |
|
---|
| 211 | nl = ip[-2] & 3;
|
---|
| 212 | /* test if in beetween two long literal runs */
|
---|
| 213 | if (t == 1 && lit > 3 && nl == 0
|
---|
| 214 | && ip[0] < 16 && ip[0] != 0 && (lit + 3 + ip[0] < 16)
|
---|
| 215 | ) {
|
---|
| 216 | t = *ip++;
|
---|
| 217 | /* copy over the 3 literals that replace the match */
|
---|
| 218 | copy3(ip-1-2,m_pos,pd(op,m_pos));
|
---|
| 219 | /* set new length of previous literal run */
|
---|
| 220 | lit += 3 + t + 3;
|
---|
| 221 | *litp = (unsigned char)(lit - 3);
|
---|
| 222 | o_m2++;
|
---|
| 223 | *op++ = *m_pos++;
|
---|
| 224 | *op++ = *m_pos++;
|
---|
| 225 | *op++ = *m_pos++;
|
---|
| 226 | goto copy_literal_run;
|
---|
| 227 | }
|
---|
| 228 | } else {
|
---|
| 229 | if (t >= 32) { /* a M3 match */
|
---|
| 230 | t &= 31;
|
---|
| 231 | if (t == 0) {
|
---|
| 232 | t = 31;
|
---|
| 233 | while (*ip == 0)
|
---|
| 234 | t += 255, ip++;
|
---|
| 235 | t += *ip++;
|
---|
| 236 | }
|
---|
| 237 | m_pos = op - 1;
|
---|
| 238 | m_pos -= *ip++ >> 2;
|
---|
| 239 | m_pos -= *ip++ << 6;
|
---|
| 240 | } else { /* a M4 match */
|
---|
| 241 | m_pos = op;
|
---|
| 242 | m_pos -= (t & 8) << 11;
|
---|
| 243 | t &= 7;
|
---|
| 244 | if (t == 0) {
|
---|
| 245 | t = 7;
|
---|
| 246 | while (*ip == 0)
|
---|
| 247 | t += 255, ip++;
|
---|
| 248 | t += *ip++;
|
---|
| 249 | }
|
---|
| 250 | m_pos -= *ip++ >> 2;
|
---|
| 251 | m_pos -= *ip++ << 6;
|
---|
| 252 | if (m_pos == op)
|
---|
| 253 | goto eof_found;
|
---|
| 254 | m_pos -= 0x4000;
|
---|
| 255 | }
|
---|
| 256 | if (litp == NULL)
|
---|
| 257 | goto copy_m;
|
---|
| 258 |
|
---|
| 259 | nl = ip[-2] & 3;
|
---|
| 260 | /* test if in beetween two matches */
|
---|
| 261 | if (t == 1 && lit == 0 && nl == 0 && ip[0] >= 16) {
|
---|
| 262 | next_lit = nl;
|
---|
| 263 | /* make a previous short run */
|
---|
| 264 | lit += 3;
|
---|
| 265 | *litp = (unsigned char)((*litp & ~3) | lit);
|
---|
| 266 | /* copy over the 3 literals that replace the match */
|
---|
| 267 | copy3(ip-3,m_pos,pd(op,m_pos));
|
---|
| 268 | o_m3_a++;
|
---|
| 269 | }
|
---|
| 270 | /* test if a literal run follows */
|
---|
| 271 | else if (t == 1 && lit <= 3 && nl == 0
|
---|
| 272 | && ip[0] < 16 && ip[0] != 0 && (lit + 3 + ip[0] < 16)
|
---|
| 273 | ) {
|
---|
| 274 | t = *ip++;
|
---|
| 275 | /* remove short run */
|
---|
| 276 | *litp &= ~3;
|
---|
| 277 | /* copy over the 3 literals that replace the match */
|
---|
| 278 | copy3(ip-4+1,m_pos,pd(op,m_pos));
|
---|
| 279 | /* move literals 1 byte ahead */
|
---|
| 280 | litp += 2;
|
---|
| 281 | if (lit > 0)
|
---|
| 282 | memmove(litp+1,litp,lit);
|
---|
| 283 | /* insert new length of long literal run */
|
---|
| 284 | lit += 3 + t + 3;
|
---|
| 285 | *litp = (unsigned char)(lit - 3);
|
---|
| 286 |
|
---|
| 287 | o_m3_b++;
|
---|
| 288 | *op++ = *m_pos++;
|
---|
| 289 | *op++ = *m_pos++;
|
---|
| 290 | *op++ = *m_pos++;
|
---|
| 291 | goto copy_literal_run;
|
---|
| 292 | }
|
---|
| 293 | }
|
---|
| 294 | copy_m:
|
---|
| 295 | *op++ = *m_pos++;
|
---|
| 296 | *op++ = *m_pos++;
|
---|
| 297 | do *op++ = *m_pos++; while (--t > 0);
|
---|
| 298 | }
|
---|
| 299 |
|
---|
| 300 | match_done:
|
---|
| 301 | if (next_lit == NO_LIT) {
|
---|
| 302 | t = ip[-2] & 3;
|
---|
| 303 | lit = t;
|
---|
| 304 | litp = ip - 2;
|
---|
| 305 | }
|
---|
| 306 | else
|
---|
| 307 | t = next_lit;
|
---|
| 308 | next_lit = NO_LIT;
|
---|
| 309 | if (t == 0)
|
---|
| 310 | break;
|
---|
| 311 | /* copy literals */
|
---|
| 312 | match_next:
|
---|
| 313 | do *op++ = *ip++; while (--t > 0);
|
---|
| 314 | t = *ip++;
|
---|
| 315 | } while (TEST_IP && TEST_OP);
|
---|
| 316 | }
|
---|
| 317 |
|
---|
| 318 | /* no EOF code was found */
|
---|
| 319 | *out_len = pd(op, out);
|
---|
| 320 | return LZO_E_EOF_NOT_FOUND;
|
---|
| 321 |
|
---|
| 322 | eof_found:
|
---|
| 323 | // LZO_UNUSED(o_m1_a); LZO_UNUSED(o_m1_b); LZO_UNUSED(o_m2);
|
---|
| 324 | // LZO_UNUSED(o_m3_a); LZO_UNUSED(o_m3_b);
|
---|
| 325 | *out_len = pd(op, out);
|
---|
| 326 | return (ip == ip_end ? LZO_E_OK :
|
---|
| 327 | (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
|
---|
| 328 | }
|
---|
| 329 |
|
---|
| 330 | /**********************************************************************/
|
---|
| 331 | #define F_OS F_OS_UNIX
|
---|
| 332 | #define F_CS F_CS_NATIVE
|
---|
| 333 |
|
---|
| 334 | /**********************************************************************/
|
---|
| 335 | #define ADLER32_INIT_VALUE 1
|
---|
| 336 | #define CRC32_INIT_VALUE 0
|
---|
| 337 |
|
---|
| 338 | /**********************************************************************/
|
---|
| 339 | enum {
|
---|
| 340 | M_LZO1X_1 = 1,
|
---|
| 341 | M_LZO1X_1_15 = 2,
|
---|
| 342 | M_LZO1X_999 = 3,
|
---|
| 343 | };
|
---|
| 344 |
|
---|
| 345 | /**********************************************************************/
|
---|
| 346 | /* header flags */
|
---|
| 347 | #define F_ADLER32_D 0x00000001L
|
---|
| 348 | #define F_ADLER32_C 0x00000002L
|
---|
| 349 | #define F_H_EXTRA_FIELD 0x00000040L
|
---|
| 350 | #define F_H_GMTDIFF 0x00000080L
|
---|
| 351 | #define F_CRC32_D 0x00000100L
|
---|
| 352 | #define F_CRC32_C 0x00000200L
|
---|
| 353 | #define F_H_FILTER 0x00000800L
|
---|
| 354 | #define F_H_CRC32 0x00001000L
|
---|
| 355 | #define F_MASK 0x00003FFFL
|
---|
| 356 |
|
---|
| 357 | /* operating system & file system that created the file [mostly unused] */
|
---|
| 358 | #define F_OS_UNIX 0x03000000L
|
---|
| 359 | #define F_OS_SHIFT 24
|
---|
| 360 | #define F_OS_MASK 0xff000000L
|
---|
| 361 |
|
---|
| 362 | /* character set for file name encoding [mostly unused] */
|
---|
| 363 | #define F_CS_NATIVE 0x00000000L
|
---|
| 364 | #define F_CS_SHIFT 20
|
---|
| 365 | #define F_CS_MASK 0x00f00000L
|
---|
| 366 |
|
---|
| 367 | /* these bits must be zero */
|
---|
| 368 | #define F_RESERVED ((F_MASK | F_OS_MASK | F_CS_MASK) ^ 0xffffffffL)
|
---|
| 369 |
|
---|
| 370 | typedef struct chksum_t {
|
---|
| 371 | uint32_t f_adler32;
|
---|
| 372 | uint32_t f_crc32;
|
---|
| 373 | } chksum_t;
|
---|
| 374 |
|
---|
| 375 | typedef struct header_t {
|
---|
| 376 | unsigned version;
|
---|
| 377 | unsigned lib_version;
|
---|
| 378 | unsigned version_needed_to_extract;
|
---|
| 379 | uint32_t flags;
|
---|
| 380 | uint32_t mode;
|
---|
| 381 | uint32_t mtime;
|
---|
| 382 | uint32_t gmtdiff;
|
---|
| 383 | uint32_t header_checksum;
|
---|
| 384 |
|
---|
| 385 | uint32_t extra_field_len;
|
---|
| 386 | uint32_t extra_field_checksum;
|
---|
| 387 |
|
---|
| 388 | unsigned char method;
|
---|
| 389 | unsigned char level;
|
---|
| 390 |
|
---|
| 391 | /* info */
|
---|
| 392 | char name[255+1];
|
---|
| 393 | } header_t;
|
---|
| 394 |
|
---|
| 395 | struct globals {
|
---|
| 396 | /*const uint32_t *lzo_crc32_table;*/
|
---|
| 397 | chksum_t chksum_in;
|
---|
| 398 | chksum_t chksum_out;
|
---|
| 399 | } FIX_ALIASING;
|
---|
| 400 | #define G (*(struct globals*)&bb_common_bufsiz1)
|
---|
| 401 | #define INIT_G() do { } while (0)
|
---|
| 402 | //#define G (*ptr_to_globals)
|
---|
| 403 | //#define INIT_G() do {
|
---|
| 404 | // SET_PTR_TO_GLOBALS(xzalloc(sizeof(G)));
|
---|
| 405 | //} while (0)
|
---|
| 406 |
|
---|
| 407 |
|
---|
| 408 | /**********************************************************************/
|
---|
| 409 | #define LZOP_VERSION 0x1010
|
---|
| 410 | //#define LZOP_VERSION_STRING "1.01"
|
---|
| 411 | //#define LZOP_VERSION_DATE "Apr 27th 2003"
|
---|
| 412 |
|
---|
| 413 | #define OPTION_STRING "cfvdt123456789CF"
|
---|
| 414 |
|
---|
| 415 | enum {
|
---|
| 416 | OPT_STDOUT = (1 << 0),
|
---|
| 417 | OPT_FORCE = (1 << 1),
|
---|
| 418 | OPT_VERBOSE = (1 << 2),
|
---|
| 419 | OPT_DECOMPRESS = (1 << 3),
|
---|
| 420 | OPT_TEST = (1 << 4),
|
---|
| 421 | OPT_1 = (1 << 5),
|
---|
| 422 | OPT_2 = (1 << 6),
|
---|
| 423 | OPT_3 = (1 << 7),
|
---|
| 424 | OPT_4 = (1 << 8),
|
---|
| 425 | OPT_5 = (1 << 9),
|
---|
| 426 | OPT_6 = (1 << 10),
|
---|
| 427 | OPT_789 = (7 << 11),
|
---|
| 428 | OPT_7 = (1 << 11),
|
---|
| 429 | OPT_8 = (1 << 12),
|
---|
| 430 | OPT_C = (1 << 14),
|
---|
| 431 | OPT_F = (1 << 15),
|
---|
| 432 | };
|
---|
| 433 |
|
---|
| 434 | /**********************************************************************/
|
---|
| 435 | // adler32 checksum
|
---|
| 436 | // adapted from free code by Mark Adler <madler@alumni.caltech.edu>
|
---|
| 437 | // see http://www.zlib.org/
|
---|
| 438 | /**********************************************************************/
|
---|
| 439 | static FAST_FUNC uint32_t
|
---|
| 440 | lzo_adler32(uint32_t adler, const uint8_t* buf, unsigned len)
|
---|
| 441 | {
|
---|
| 442 | enum {
|
---|
| 443 | LZO_BASE = 65521, /* largest prime smaller than 65536 */
|
---|
| 444 | /* NMAX is the largest n such that
|
---|
| 445 | * 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
|
---|
| 446 | LZO_NMAX = 5552,
|
---|
| 447 | };
|
---|
| 448 | uint32_t s1 = adler & 0xffff;
|
---|
| 449 | uint32_t s2 = (adler >> 16) & 0xffff;
|
---|
| 450 | unsigned k;
|
---|
| 451 |
|
---|
| 452 | if (buf == NULL)
|
---|
| 453 | return 1;
|
---|
| 454 |
|
---|
| 455 | while (len > 0) {
|
---|
| 456 | k = len < LZO_NMAX ? (unsigned) len : LZO_NMAX;
|
---|
| 457 | len -= k;
|
---|
| 458 | if (k != 0) do {
|
---|
| 459 | s1 += *buf++;
|
---|
| 460 | s2 += s1;
|
---|
| 461 | } while (--k > 0);
|
---|
| 462 | s1 %= LZO_BASE;
|
---|
| 463 | s2 %= LZO_BASE;
|
---|
| 464 | }
|
---|
| 465 | return (s2 << 16) | s1;
|
---|
| 466 | }
|
---|
| 467 |
|
---|
| 468 | static FAST_FUNC uint32_t
|
---|
| 469 | lzo_crc32(uint32_t c, const uint8_t* buf, unsigned len)
|
---|
| 470 | {
|
---|
| 471 | //if (buf == NULL) - impossible
|
---|
| 472 | // return 0;
|
---|
| 473 |
|
---|
| 474 | return ~crc32_block_endian0(~c, buf, len, global_crc32_table);
|
---|
| 475 | }
|
---|
| 476 |
|
---|
| 477 | /**********************************************************************/
|
---|
| 478 | static void init_chksum(chksum_t *ct)
|
---|
| 479 | {
|
---|
| 480 | ct->f_adler32 = ADLER32_INIT_VALUE;
|
---|
| 481 | ct->f_crc32 = CRC32_INIT_VALUE;
|
---|
| 482 | }
|
---|
| 483 |
|
---|
| 484 | static void add_bytes_to_chksum(chksum_t *ct, const void* buf, int cnt)
|
---|
| 485 | {
|
---|
| 486 | /* We need to handle the two checksums at once, because at the
|
---|
| 487 | * beginning of the header, we don't know yet which one we'll
|
---|
| 488 | * eventually need */
|
---|
| 489 | ct->f_adler32 = lzo_adler32(ct->f_adler32, (const uint8_t*)buf, cnt);
|
---|
| 490 | ct->f_crc32 = lzo_crc32(ct->f_crc32, (const uint8_t*)buf, cnt);
|
---|
| 491 | }
|
---|
| 492 |
|
---|
| 493 | static uint32_t chksum_getresult(chksum_t *ct, const header_t *h)
|
---|
| 494 | {
|
---|
| 495 | return (h->flags & F_H_CRC32) ? ct->f_crc32 : ct->f_adler32;
|
---|
| 496 | }
|
---|
| 497 |
|
---|
| 498 | /**********************************************************************/
|
---|
| 499 | static uint32_t read32(void)
|
---|
| 500 | {
|
---|
| 501 | uint32_t v;
|
---|
| 502 | xread(0, &v, 4);
|
---|
| 503 | return ntohl(v);
|
---|
| 504 | }
|
---|
| 505 |
|
---|
| 506 | static void write32(uint32_t v)
|
---|
| 507 | {
|
---|
| 508 | v = htonl(v);
|
---|
| 509 | xwrite(1, &v, 4);
|
---|
| 510 | }
|
---|
| 511 |
|
---|
| 512 | static void f_write(const void* buf, int cnt)
|
---|
| 513 | {
|
---|
| 514 | xwrite(1, buf, cnt);
|
---|
| 515 | add_bytes_to_chksum(&G.chksum_out, buf, cnt);
|
---|
| 516 | }
|
---|
| 517 |
|
---|
| 518 | static void f_read(void* buf, int cnt)
|
---|
| 519 | {
|
---|
| 520 | xread(0, buf, cnt);
|
---|
| 521 | add_bytes_to_chksum(&G.chksum_in, buf, cnt);
|
---|
| 522 | }
|
---|
| 523 |
|
---|
| 524 | static int f_read8(void)
|
---|
| 525 | {
|
---|
| 526 | uint8_t v;
|
---|
| 527 | f_read(&v, 1);
|
---|
| 528 | return v;
|
---|
| 529 | }
|
---|
| 530 |
|
---|
| 531 | static void f_write8(uint8_t v)
|
---|
| 532 | {
|
---|
| 533 | f_write(&v, 1);
|
---|
| 534 | }
|
---|
| 535 |
|
---|
| 536 | static unsigned f_read16(void)
|
---|
| 537 | {
|
---|
| 538 | uint16_t v;
|
---|
| 539 | f_read(&v, 2);
|
---|
| 540 | return ntohs(v);
|
---|
| 541 | }
|
---|
| 542 |
|
---|
| 543 | static void f_write16(uint16_t v)
|
---|
| 544 | {
|
---|
| 545 | v = htons(v);
|
---|
| 546 | f_write(&v, 2);
|
---|
| 547 | }
|
---|
| 548 |
|
---|
| 549 | static uint32_t f_read32(void)
|
---|
| 550 | {
|
---|
| 551 | uint32_t v;
|
---|
| 552 | f_read(&v, 4);
|
---|
| 553 | return ntohl(v);
|
---|
| 554 | }
|
---|
| 555 |
|
---|
| 556 | static void f_write32(uint32_t v)
|
---|
| 557 | {
|
---|
| 558 | v = htonl(v);
|
---|
| 559 | f_write(&v, 4);
|
---|
| 560 | }
|
---|
| 561 |
|
---|
| 562 | /**********************************************************************/
|
---|
| 563 | static int lzo_get_method(header_t *h)
|
---|
| 564 | {
|
---|
| 565 | /* check method */
|
---|
| 566 | if (h->method == M_LZO1X_1) {
|
---|
| 567 | if (h->level == 0)
|
---|
| 568 | h->level = 3;
|
---|
| 569 | } else if (h->method == M_LZO1X_1_15) {
|
---|
| 570 | if (h->level == 0)
|
---|
| 571 | h->level = 1;
|
---|
| 572 | } else if (h->method == M_LZO1X_999) {
|
---|
| 573 | if (h->level == 0)
|
---|
| 574 | h->level = 9;
|
---|
| 575 | } else
|
---|
| 576 | return -1; /* not a LZO method */
|
---|
| 577 |
|
---|
| 578 | /* check compression level */
|
---|
| 579 | if (h->level < 1 || h->level > 9)
|
---|
| 580 | return 15;
|
---|
| 581 |
|
---|
| 582 | return 0;
|
---|
| 583 | }
|
---|
| 584 |
|
---|
| 585 | /**********************************************************************/
|
---|
| 586 | #define LZO_BLOCK_SIZE (256 * 1024l)
|
---|
| 587 | #define MAX_BLOCK_SIZE (64 * 1024l * 1024l) /* DO NOT CHANGE */
|
---|
| 588 |
|
---|
| 589 | /* LZO may expand uncompressible data by a small amount */
|
---|
| 590 | #define MAX_COMPRESSED_SIZE(x) ((x) + (x) / 16 + 64 + 3)
|
---|
| 591 |
|
---|
| 592 | /**********************************************************************/
|
---|
| 593 | // compress a file
|
---|
| 594 | /**********************************************************************/
|
---|
| 595 | static NOINLINE smallint lzo_compress(const header_t *h)
|
---|
| 596 | {
|
---|
| 597 | unsigned block_size = LZO_BLOCK_SIZE;
|
---|
| 598 | int r = 0; /* LZO_E_OK */
|
---|
| 599 | uint8_t *const b1 = xzalloc(block_size);
|
---|
| 600 | uint8_t *const b2 = xzalloc(MAX_COMPRESSED_SIZE(block_size));
|
---|
| 601 | unsigned src_len = 0, dst_len = 0;
|
---|
| 602 | uint32_t d_adler32 = ADLER32_INIT_VALUE;
|
---|
| 603 | uint32_t d_crc32 = CRC32_INIT_VALUE;
|
---|
| 604 | int l;
|
---|
| 605 | smallint ok = 1;
|
---|
| 606 | uint8_t *wrk_mem = NULL;
|
---|
| 607 |
|
---|
| 608 | if (h->method == M_LZO1X_1)
|
---|
| 609 | wrk_mem = xzalloc(LZO1X_1_MEM_COMPRESS);
|
---|
| 610 | else if (h->method == M_LZO1X_1_15)
|
---|
| 611 | wrk_mem = xzalloc(LZO1X_1_15_MEM_COMPRESS);
|
---|
| 612 | else if (h->method == M_LZO1X_999)
|
---|
| 613 | wrk_mem = xzalloc(LZO1X_999_MEM_COMPRESS);
|
---|
| 614 |
|
---|
| 615 | for (;;) {
|
---|
| 616 | /* read a block */
|
---|
| 617 | l = full_read(0, b1, block_size);
|
---|
| 618 | src_len = (l > 0 ? l : 0);
|
---|
| 619 |
|
---|
| 620 | /* write uncompressed block size */
|
---|
| 621 | write32(src_len);
|
---|
| 622 |
|
---|
| 623 | /* exit if last block */
|
---|
| 624 | if (src_len == 0)
|
---|
| 625 | break;
|
---|
| 626 |
|
---|
| 627 | /* compute checksum of uncompressed block */
|
---|
| 628 | if (h->flags & F_ADLER32_D)
|
---|
| 629 | d_adler32 = lzo_adler32(ADLER32_INIT_VALUE, b1, src_len);
|
---|
| 630 | if (h->flags & F_CRC32_D)
|
---|
| 631 | d_crc32 = lzo_crc32(CRC32_INIT_VALUE, b1, src_len);
|
---|
| 632 |
|
---|
| 633 | /* compress */
|
---|
| 634 | if (h->method == M_LZO1X_1)
|
---|
| 635 | r = lzo1x_1_compress(b1, src_len, b2, &dst_len, wrk_mem);
|
---|
| 636 | else if (h->method == M_LZO1X_1_15)
|
---|
| 637 | r = lzo1x_1_15_compress(b1, src_len, b2, &dst_len, wrk_mem);
|
---|
| 638 | #if ENABLE_LZOP_COMPR_HIGH
|
---|
| 639 | else if (h->method == M_LZO1X_999)
|
---|
| 640 | r = lzo1x_999_compress_level(b1, src_len, b2, &dst_len,
|
---|
| 641 | wrk_mem, h->level);
|
---|
| 642 | #endif
|
---|
| 643 | else
|
---|
| 644 | bb_error_msg_and_die("internal error");
|
---|
| 645 |
|
---|
| 646 | if (r != 0) /* not LZO_E_OK */
|
---|
| 647 | bb_error_msg_and_die("internal error - compression failed");
|
---|
| 648 |
|
---|
| 649 | /* write compressed block size */
|
---|
| 650 | if (dst_len < src_len) {
|
---|
| 651 | /* optimize */
|
---|
| 652 | if (h->method == M_LZO1X_999) {
|
---|
| 653 | unsigned new_len = src_len;
|
---|
| 654 | r = lzo1x_optimize(b2, dst_len, b1, &new_len, NULL);
|
---|
| 655 | if (r != 0 /*LZO_E_OK*/ || new_len != src_len)
|
---|
| 656 | bb_error_msg_and_die("internal error - optimization failed");
|
---|
| 657 | }
|
---|
| 658 | write32(dst_len);
|
---|
| 659 | } else {
|
---|
| 660 | /* data actually expanded => store data uncompressed */
|
---|
| 661 | write32(src_len);
|
---|
| 662 | }
|
---|
| 663 |
|
---|
| 664 | /* write checksum of uncompressed block */
|
---|
| 665 | if (h->flags & F_ADLER32_D)
|
---|
| 666 | write32(d_adler32);
|
---|
| 667 | if (h->flags & F_CRC32_D)
|
---|
| 668 | write32(d_crc32);
|
---|
| 669 |
|
---|
| 670 | if (dst_len < src_len) {
|
---|
| 671 | /* write checksum of compressed block */
|
---|
| 672 | if (h->flags & F_ADLER32_C)
|
---|
| 673 | write32(lzo_adler32(ADLER32_INIT_VALUE, b2, dst_len));
|
---|
| 674 | if (h->flags & F_CRC32_C)
|
---|
| 675 | write32(lzo_crc32(CRC32_INIT_VALUE, b2, dst_len));
|
---|
| 676 | /* write compressed block data */
|
---|
| 677 | xwrite(1, b2, dst_len);
|
---|
| 678 | } else {
|
---|
| 679 | /* write uncompressed block data */
|
---|
| 680 | xwrite(1, b1, src_len);
|
---|
| 681 | }
|
---|
| 682 | }
|
---|
| 683 |
|
---|
| 684 | free(wrk_mem);
|
---|
| 685 | free(b1);
|
---|
| 686 | free(b2);
|
---|
| 687 | return ok;
|
---|
| 688 | }
|
---|
| 689 |
|
---|
| 690 | static FAST_FUNC void lzo_check(
|
---|
| 691 | uint32_t init,
|
---|
| 692 | uint8_t* buf, unsigned len,
|
---|
| 693 | uint32_t FAST_FUNC (*fn)(uint32_t, const uint8_t*, unsigned),
|
---|
| 694 | uint32_t ref)
|
---|
| 695 | {
|
---|
| 696 | /* This function, by having the same order of parameters
|
---|
| 697 | * as fn, and by being marked FAST_FUNC (same as fn),
|
---|
| 698 | * saves a dozen bytes of code.
|
---|
| 699 | */
|
---|
| 700 | uint32_t c = fn(init, buf, len);
|
---|
| 701 | if (c != ref)
|
---|
| 702 | bb_error_msg_and_die("checksum error");
|
---|
| 703 | }
|
---|
| 704 |
|
---|
| 705 | /**********************************************************************/
|
---|
| 706 | // decompress a file
|
---|
| 707 | /**********************************************************************/
|
---|
| 708 | static NOINLINE smallint lzo_decompress(const header_t *h)
|
---|
| 709 | {
|
---|
| 710 | unsigned block_size = LZO_BLOCK_SIZE;
|
---|
| 711 | int r;
|
---|
| 712 | uint32_t src_len, dst_len;
|
---|
| 713 | uint32_t c_adler32 = ADLER32_INIT_VALUE;
|
---|
| 714 | uint32_t d_adler32 = ADLER32_INIT_VALUE;
|
---|
| 715 | uint32_t c_crc32 = CRC32_INIT_VALUE, d_crc32 = CRC32_INIT_VALUE;
|
---|
| 716 | smallint ok = 1;
|
---|
| 717 | uint8_t *b1;
|
---|
| 718 | uint32_t mcs_block_size = MAX_COMPRESSED_SIZE(block_size);
|
---|
| 719 | uint8_t *b2 = NULL;
|
---|
| 720 |
|
---|
| 721 | for (;;) {
|
---|
| 722 | uint8_t *dst;
|
---|
| 723 |
|
---|
| 724 | /* read uncompressed block size */
|
---|
| 725 | dst_len = read32();
|
---|
| 726 |
|
---|
| 727 | /* exit if last block */
|
---|
| 728 | if (dst_len == 0)
|
---|
| 729 | break;
|
---|
| 730 |
|
---|
| 731 | /* error if split file */
|
---|
| 732 | if (dst_len == 0xffffffffL)
|
---|
| 733 | /* should not happen - not yet implemented */
|
---|
| 734 | bb_error_msg_and_die("this file is a split lzop file");
|
---|
| 735 |
|
---|
| 736 | if (dst_len > MAX_BLOCK_SIZE)
|
---|
| 737 | bb_error_msg_and_die("corrupted data");
|
---|
| 738 |
|
---|
| 739 | /* read compressed block size */
|
---|
| 740 | src_len = read32();
|
---|
| 741 | if (src_len <= 0 || src_len > dst_len)
|
---|
| 742 | bb_error_msg_and_die("corrupted data");
|
---|
| 743 |
|
---|
| 744 | if (dst_len > block_size) {
|
---|
| 745 | if (b2) {
|
---|
| 746 | free(b2);
|
---|
| 747 | b2 = NULL;
|
---|
| 748 | }
|
---|
| 749 | block_size = dst_len;
|
---|
| 750 | mcs_block_size = MAX_COMPRESSED_SIZE(block_size);
|
---|
| 751 | }
|
---|
| 752 |
|
---|
| 753 | /* read checksum of uncompressed block */
|
---|
| 754 | if (h->flags & F_ADLER32_D)
|
---|
| 755 | d_adler32 = read32();
|
---|
| 756 | if (h->flags & F_CRC32_D)
|
---|
| 757 | d_crc32 = read32();
|
---|
| 758 |
|
---|
| 759 | /* read checksum of compressed block */
|
---|
| 760 | if (src_len < dst_len) {
|
---|
| 761 | if (h->flags & F_ADLER32_C)
|
---|
| 762 | c_adler32 = read32();
|
---|
| 763 | if (h->flags & F_CRC32_C)
|
---|
| 764 | c_crc32 = read32();
|
---|
| 765 | }
|
---|
| 766 |
|
---|
| 767 | if (b2 == NULL)
|
---|
| 768 | b2 = xzalloc(mcs_block_size);
|
---|
| 769 | /* read the block into the end of our buffer */
|
---|
| 770 | b1 = b2 + mcs_block_size - src_len;
|
---|
| 771 | xread(0, b1, src_len);
|
---|
| 772 |
|
---|
| 773 | if (src_len < dst_len) {
|
---|
| 774 | unsigned d = dst_len;
|
---|
| 775 |
|
---|
| 776 | if (!(option_mask32 & OPT_F)) {
|
---|
| 777 | /* verify checksum of compressed block */
|
---|
| 778 | if (h->flags & F_ADLER32_C)
|
---|
| 779 | lzo_check(ADLER32_INIT_VALUE,
|
---|
| 780 | b1, src_len,
|
---|
| 781 | lzo_adler32, c_adler32);
|
---|
| 782 | if (h->flags & F_CRC32_C)
|
---|
| 783 | lzo_check(CRC32_INIT_VALUE,
|
---|
| 784 | b1, src_len,
|
---|
| 785 | lzo_crc32, c_crc32);
|
---|
| 786 | }
|
---|
| 787 |
|
---|
| 788 | /* decompress */
|
---|
| 789 | // if (option_mask32 & OPT_F)
|
---|
| 790 | // r = lzo1x_decompress(b1, src_len, b2, &d, NULL);
|
---|
| 791 | // else
|
---|
| 792 | r = lzo1x_decompress_safe(b1, src_len, b2, &d, NULL);
|
---|
| 793 |
|
---|
| 794 | if (r != 0 /*LZO_E_OK*/ || dst_len != d) {
|
---|
| 795 | bb_error_msg_and_die("corrupted data");
|
---|
| 796 | }
|
---|
| 797 | dst = b2;
|
---|
| 798 | } else {
|
---|
| 799 | /* "stored" block => no decompression */
|
---|
| 800 | dst = b1;
|
---|
| 801 | }
|
---|
| 802 |
|
---|
| 803 | if (!(option_mask32 & OPT_F)) {
|
---|
| 804 | /* verify checksum of uncompressed block */
|
---|
| 805 | if (h->flags & F_ADLER32_D)
|
---|
| 806 | lzo_check(ADLER32_INIT_VALUE,
|
---|
| 807 | dst, dst_len,
|
---|
| 808 | lzo_adler32, d_adler32);
|
---|
| 809 | if (h->flags & F_CRC32_D)
|
---|
| 810 | lzo_check(CRC32_INIT_VALUE,
|
---|
| 811 | dst, dst_len,
|
---|
| 812 | lzo_crc32, d_crc32);
|
---|
| 813 | }
|
---|
| 814 |
|
---|
| 815 | /* write uncompressed block data */
|
---|
| 816 | xwrite(1, dst, dst_len);
|
---|
| 817 | }
|
---|
| 818 |
|
---|
| 819 | free(b2);
|
---|
| 820 | return ok;
|
---|
| 821 | }
|
---|
| 822 |
|
---|
| 823 | /**********************************************************************/
|
---|
| 824 | // lzop file signature (shamelessly borrowed from PNG)
|
---|
| 825 | /**********************************************************************/
|
---|
| 826 | /*
|
---|
| 827 | * The first nine bytes of a lzop file always contain the following values:
|
---|
| 828 | *
|
---|
| 829 | * 0 1 2 3 4 5 6 7 8
|
---|
| 830 | * --- --- --- --- --- --- --- --- ---
|
---|
| 831 | * (hex) 89 4c 5a 4f 00 0d 0a 1a 0a
|
---|
| 832 | * (decimal) 137 76 90 79 0 13 10 26 10
|
---|
| 833 | * (C notation - ASCII) \211 L Z O \0 \r \n \032 \n
|
---|
| 834 | */
|
---|
| 835 |
|
---|
| 836 | /* (vda) comparison with lzop v1.02rc1 ("lzop -1 <FILE" cmd):
|
---|
| 837 | * Only slight differences in header:
|
---|
| 838 | * -00000000 89 4c 5a 4f 00 0d 0a 1a 0a 10 20 20 20 09 40 02
|
---|
| 839 | * +00000000 89 4c 5a 4f 00 0d 0a 1a 0a 10 10 20 30 09 40 02
|
---|
| 840 | * ^^^^^ ^^^^^
|
---|
| 841 | * version lib_version
|
---|
| 842 | * -00000010 01 03 00 00 0d 00 00 81 a4 49 f7 a6 3f 00 00 00
|
---|
| 843 | * +00000010 01 03 00 00 01 00 00 00 00 00 00 00 00 00 00 00
|
---|
| 844 | * ^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^
|
---|
| 845 | * flags mode mtime
|
---|
| 846 | * -00000020 00 00 2d 67 04 17 00 04 00 00 00 03 ed ec 9d 6d
|
---|
| 847 | * +00000020 00 00 10 5f 00 c1 00 04 00 00 00 03 ed ec 9d 6d
|
---|
| 848 | * ^^^^^^^^^^^
|
---|
| 849 | * chksum_out
|
---|
| 850 | * The rest is identical.
|
---|
| 851 | */
|
---|
| 852 | static const unsigned char lzop_magic[9] = {
|
---|
| 853 | 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a
|
---|
| 854 | };
|
---|
| 855 |
|
---|
| 856 | /* This coding is derived from Alexander Lehmann's pngcheck code. */
|
---|
| 857 | static void check_magic(void)
|
---|
| 858 | {
|
---|
| 859 | unsigned char magic[sizeof(lzop_magic)];
|
---|
| 860 | xread(0, magic, sizeof(magic));
|
---|
| 861 | if (memcmp(magic, lzop_magic, sizeof(lzop_magic)) != 0)
|
---|
| 862 | bb_error_msg_and_die("bad magic number");
|
---|
| 863 | }
|
---|
| 864 |
|
---|
| 865 | /**********************************************************************/
|
---|
| 866 | // lzop file header
|
---|
| 867 | /**********************************************************************/
|
---|
| 868 | static void write_header(const header_t *h)
|
---|
| 869 | {
|
---|
| 870 | int l;
|
---|
| 871 |
|
---|
| 872 | xwrite(1, lzop_magic, sizeof(lzop_magic));
|
---|
| 873 |
|
---|
| 874 | init_chksum(&G.chksum_out);
|
---|
| 875 |
|
---|
| 876 | f_write16(h->version);
|
---|
| 877 | f_write16(h->lib_version);
|
---|
| 878 | f_write16(h->version_needed_to_extract);
|
---|
| 879 | f_write8(h->method);
|
---|
| 880 | f_write8(h->level);
|
---|
| 881 | f_write32(h->flags);
|
---|
| 882 | f_write32(h->mode);
|
---|
| 883 | f_write32(h->mtime);
|
---|
| 884 | f_write32(h->gmtdiff);
|
---|
| 885 |
|
---|
| 886 | l = (int) strlen(h->name);
|
---|
| 887 | f_write8(l);
|
---|
| 888 | if (l)
|
---|
| 889 | f_write(h->name, l);
|
---|
| 890 |
|
---|
| 891 | f_write32(chksum_getresult(&G.chksum_out, h));
|
---|
| 892 | }
|
---|
| 893 |
|
---|
| 894 | static int read_header(header_t *h)
|
---|
| 895 | {
|
---|
| 896 | int r;
|
---|
| 897 | int l;
|
---|
| 898 | uint32_t checksum;
|
---|
| 899 |
|
---|
| 900 | memset(h, 0, sizeof(*h));
|
---|
| 901 | h->version_needed_to_extract = 0x0900; /* first lzop version */
|
---|
| 902 | h->level = 0;
|
---|
| 903 |
|
---|
| 904 | init_chksum(&G.chksum_in);
|
---|
| 905 |
|
---|
| 906 | h->version = f_read16();
|
---|
| 907 | if (h->version < 0x0900)
|
---|
| 908 | return 3;
|
---|
| 909 | h->lib_version = f_read16();
|
---|
| 910 | if (h->version >= 0x0940) {
|
---|
| 911 | h->version_needed_to_extract = f_read16();
|
---|
| 912 | if (h->version_needed_to_extract > LZOP_VERSION)
|
---|
| 913 | return 16;
|
---|
| 914 | if (h->version_needed_to_extract < 0x0900)
|
---|
| 915 | return 3;
|
---|
| 916 | }
|
---|
| 917 | h->method = f_read8();
|
---|
| 918 | if (h->version >= 0x0940)
|
---|
| 919 | h->level = f_read8();
|
---|
| 920 | h->flags = f_read32();
|
---|
| 921 | if (h->flags & F_H_FILTER)
|
---|
| 922 | return 16; /* filter not supported */
|
---|
| 923 | h->mode = f_read32();
|
---|
| 924 | h->mtime = f_read32();
|
---|
| 925 | if (h->version >= 0x0940)
|
---|
| 926 | h->gmtdiff = f_read32();
|
---|
| 927 |
|
---|
| 928 | l = f_read8();
|
---|
| 929 | if (l > 0)
|
---|
| 930 | f_read(h->name, l);
|
---|
| 931 | h->name[l] = 0;
|
---|
| 932 |
|
---|
| 933 | checksum = chksum_getresult(&G.chksum_in, h);
|
---|
| 934 | h->header_checksum = f_read32();
|
---|
| 935 | if (h->header_checksum != checksum)
|
---|
| 936 | return 2;
|
---|
| 937 |
|
---|
| 938 | if (h->method <= 0)
|
---|
| 939 | return 14;
|
---|
| 940 | r = lzo_get_method(h);
|
---|
| 941 | if (r != 0)
|
---|
| 942 | return r;
|
---|
| 943 |
|
---|
| 944 | /* check reserved flags */
|
---|
| 945 | if (h->flags & F_RESERVED)
|
---|
| 946 | return -13;
|
---|
| 947 |
|
---|
| 948 | /* skip extra field [not used yet] */
|
---|
| 949 | if (h->flags & F_H_EXTRA_FIELD) {
|
---|
| 950 | uint32_t k;
|
---|
| 951 |
|
---|
| 952 | /* note: the checksum also covers the length */
|
---|
| 953 | init_chksum(&G.chksum_in);
|
---|
| 954 | h->extra_field_len = f_read32();
|
---|
| 955 | for (k = 0; k < h->extra_field_len; k++)
|
---|
| 956 | f_read8();
|
---|
| 957 | checksum = chksum_getresult(&G.chksum_in, h);
|
---|
| 958 | h->extra_field_checksum = f_read32();
|
---|
| 959 | if (h->extra_field_checksum != checksum)
|
---|
| 960 | return 3;
|
---|
| 961 | }
|
---|
| 962 |
|
---|
| 963 | return 0;
|
---|
| 964 | }
|
---|
| 965 |
|
---|
| 966 | static void p_header(header_t *h)
|
---|
| 967 | {
|
---|
| 968 | int r;
|
---|
| 969 |
|
---|
| 970 | r = read_header(h);
|
---|
| 971 | if (r == 0)
|
---|
| 972 | return;
|
---|
| 973 | bb_error_msg_and_die("header_error %d", r);
|
---|
| 974 | }
|
---|
| 975 |
|
---|
| 976 | /**********************************************************************/
|
---|
| 977 | // compress
|
---|
| 978 | /**********************************************************************/
|
---|
| 979 | static void lzo_set_method(header_t *h)
|
---|
| 980 | {
|
---|
| 981 | int level = 1;
|
---|
| 982 |
|
---|
| 983 | if (option_mask32 & OPT_1) {
|
---|
| 984 | h->method = M_LZO1X_1_15;
|
---|
| 985 | } else if (option_mask32 & OPT_789) {
|
---|
| 986 | #if ENABLE_LZOP_COMPR_HIGH
|
---|
| 987 | h->method = M_LZO1X_999;
|
---|
| 988 | if (option_mask32 & OPT_7)
|
---|
| 989 | level = 7;
|
---|
| 990 | else if (option_mask32 & OPT_8)
|
---|
| 991 | level = 8;
|
---|
| 992 | else
|
---|
| 993 | level = 9;
|
---|
| 994 | #else
|
---|
| 995 | bb_error_msg_and_die("high compression not compiled in");
|
---|
| 996 | #endif
|
---|
| 997 | } else { /* levels 2..6 or none (defaults to level 3) */
|
---|
| 998 | h->method = M_LZO1X_1;
|
---|
| 999 | level = 5; /* levels 2-6 are actually the same */
|
---|
| 1000 | }
|
---|
| 1001 |
|
---|
| 1002 | h->level = level;
|
---|
| 1003 | }
|
---|
| 1004 |
|
---|
| 1005 | static smallint do_lzo_compress(void)
|
---|
| 1006 | {
|
---|
| 1007 | header_t header;
|
---|
| 1008 |
|
---|
| 1009 | #define h (&header)
|
---|
| 1010 | memset(h, 0, sizeof(*h));
|
---|
| 1011 |
|
---|
| 1012 | lzo_set_method(h);
|
---|
| 1013 |
|
---|
| 1014 | h->version = (LZOP_VERSION & 0xffff);
|
---|
| 1015 | h->version_needed_to_extract = 0x0940;
|
---|
| 1016 | h->lib_version = lzo_version() & 0xffff;
|
---|
| 1017 |
|
---|
| 1018 | h->flags = (F_OS & F_OS_MASK) | (F_CS & F_CS_MASK);
|
---|
| 1019 |
|
---|
| 1020 | if (!(option_mask32 & OPT_F) || h->method == M_LZO1X_999) {
|
---|
| 1021 | h->flags |= F_ADLER32_D;
|
---|
| 1022 | if (option_mask32 & OPT_C)
|
---|
| 1023 | h->flags |= F_ADLER32_C;
|
---|
| 1024 | }
|
---|
| 1025 | write_header(h);
|
---|
| 1026 | return lzo_compress(h);
|
---|
| 1027 | #undef h
|
---|
| 1028 | }
|
---|
| 1029 |
|
---|
| 1030 | /**********************************************************************/
|
---|
| 1031 | // decompress
|
---|
| 1032 | /**********************************************************************/
|
---|
| 1033 | static smallint do_lzo_decompress(void)
|
---|
| 1034 | {
|
---|
| 1035 | header_t header;
|
---|
| 1036 |
|
---|
| 1037 | check_magic();
|
---|
| 1038 | p_header(&header);
|
---|
| 1039 | return lzo_decompress(&header);
|
---|
| 1040 | }
|
---|
| 1041 |
|
---|
| 1042 | static char* FAST_FUNC make_new_name_lzop(char *filename, const char *expected_ext UNUSED_PARAM)
|
---|
| 1043 | {
|
---|
| 1044 | if (option_mask32 & OPT_DECOMPRESS) {
|
---|
| 1045 | char *extension = strrchr(filename, '.');
|
---|
| 1046 | if (!extension || strcmp(extension + 1, "lzo") != 0)
|
---|
| 1047 | return xasprintf("%s.out", filename);
|
---|
| 1048 | *extension = '\0';
|
---|
| 1049 | return filename;
|
---|
| 1050 | }
|
---|
| 1051 | return xasprintf("%s.lzo", filename);
|
---|
| 1052 | }
|
---|
| 1053 |
|
---|
| 1054 | static IF_DESKTOP(long long) int FAST_FUNC pack_lzop(unpack_info_t *info UNUSED_PARAM)
|
---|
| 1055 | {
|
---|
| 1056 | if (option_mask32 & OPT_DECOMPRESS)
|
---|
| 1057 | return do_lzo_decompress();
|
---|
| 1058 | return do_lzo_compress();
|
---|
| 1059 | }
|
---|
| 1060 |
|
---|
| 1061 | int lzop_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
---|
| 1062 | int lzop_main(int argc UNUSED_PARAM, char **argv)
|
---|
| 1063 | {
|
---|
| 1064 | getopt32(argv, OPTION_STRING);
|
---|
| 1065 | argv += optind;
|
---|
| 1066 | /* lzopcat? */
|
---|
| 1067 | if (applet_name[4] == 'c')
|
---|
| 1068 | option_mask32 |= (OPT_STDOUT | OPT_DECOMPRESS);
|
---|
| 1069 | /* unlzop? */
|
---|
| 1070 | if (applet_name[0] == 'u')
|
---|
| 1071 | option_mask32 |= OPT_DECOMPRESS;
|
---|
| 1072 |
|
---|
| 1073 | global_crc32_table = crc32_filltable(NULL, 0);
|
---|
| 1074 | return bbunpack(argv, pack_lzop, make_new_name_lzop, /*unused:*/ NULL);
|
---|
| 1075 | }
|
---|