1 | /* |
1 | /* |
2 | * Copyright (c) 2006 Stefan Traby <stefan@hello-penguin.com> |
2 | * Copyright (c) 2006 Stefan Traby <stefan@hello-penguin.com> |
|
|
3 | * Copyright (c) 2012 Marc Lehmann <schmorp@schmorp.de> |
3 | * |
4 | * |
4 | * Redistribution and use in source and binary forms, with or without modifica- |
5 | * Redistribution and use in source and binary forms, with or without modifica- |
5 | * tion, are permitted provided that the following conditions are met: |
6 | * tion, are permitted provided that the following conditions are met: |
6 | * |
7 | * |
7 | * 1. Redistributions of source code must retain the above copyright notice, |
8 | * 1. Redistributions of source code must retain the above copyright notice, |
8 | * this list of conditions and the following disclaimer. |
9 | * this list of conditions and the following disclaimer. |
9 | * |
10 | * |
10 | * 2. Redistributions in binary form must reproduce the above copyright |
11 | * 2. Redistributions in binary form must reproduce the above copyright |
11 | * notice, this list of conditions and the following disclaimer in the |
12 | * notice, this list of conditions and the following disclaimer in the |
12 | * documentation and/or other materials provided with the distribution. |
13 | * documentation and/or other materials provided with the distribution. |
13 | * |
14 | * |
14 | * 3. The name of the author may not be used to endorse or promote products |
|
|
15 | * derived from this software without specific prior written permission. |
|
|
16 | * |
|
|
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- |
16 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- |
19 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
17 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
20 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- |
18 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- |
21 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
19 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
… | |
… | |
24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- |
22 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- |
25 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
23 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
26 | * OF THE POSSIBILITY OF SUCH DAMAGE. |
24 | * OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | * |
25 | * |
28 | * Alternatively, the contents of this file may be used under the terms of |
26 | * Alternatively, the contents of this file may be used under the terms of |
29 | * the GNU General Public License version 2 (the "GPL"), in which case the |
27 | * the GNU General Public License ("GPL") version 2 or any later version, |
30 | * provisions of the GPL are applicable instead of the above. If you wish to |
28 | * in which case the provisions of the GPL are applicable instead of |
31 | * allow the use of your version of this file only under the terms of the |
29 | * the above. If you wish to allow the use of your version of this file |
32 | * GPL and not to allow others to use your version of this file under the |
30 | * only under the terms of the GPL and not to allow others to use your |
33 | * BSD license, indicate your decision by deleting the provisions above and |
31 | * version of this file under the BSD license, indicate your decision |
34 | * replace them with the notice and other provisions required by the GPL. If |
32 | * by deleting the provisions above and replace them with the notice |
35 | * you do not delete the provisions above, a recipient may use your version |
33 | * and other provisions required by the GPL. If you do not delete the |
36 | * of this file under either the BSD or the GPL License. |
34 | * provisions above, a recipient may use your version of this file under |
|
|
35 | * either the BSD or the GPL. |
37 | */ |
36 | */ |
38 | |
37 | |
39 | #include "config.h" |
38 | #include "config.h" |
40 | #include <stdio.h> |
39 | #include <stdio.h> |
41 | #include <string.h> |
40 | #include <string.h> |
… | |
… | |
45 | #include <sys/stat.h> |
44 | #include <sys/stat.h> |
46 | #include <fcntl.h> |
45 | #include <fcntl.h> |
47 | #include <errno.h> |
46 | #include <errno.h> |
48 | #include <limits.h> |
47 | #include <limits.h> |
49 | #include "lzf.h" |
48 | #include "lzf.h" |
|
|
49 | #include "lzf_c_best.c" |
50 | |
50 | |
51 | #ifdef HAVE_GETOPT_H |
51 | #ifdef HAVE_GETOPT_H |
52 | # include <getopt.h> |
52 | # include <getopt.h> |
53 | #endif |
53 | #endif |
54 | |
54 | |
… | |
… | |
60 | static off_t nr_read, nr_written; |
60 | static off_t nr_read, nr_written; |
61 | |
61 | |
62 | static const char *imagename; |
62 | static const char *imagename; |
63 | static enum { compress, uncompress, lzcat } mode = compress; |
63 | static enum { compress, uncompress, lzcat } mode = compress; |
64 | static int verbose = 0; |
64 | static int verbose = 0; |
|
|
65 | static int best = 0; |
65 | static int force = 0; |
66 | static int force = 0; |
66 | static long blocksize = BLOCKSIZE; |
67 | static long blocksize = BLOCKSIZE; |
67 | |
68 | |
68 | #ifdef HAVE_GETOPT_LONG |
69 | #ifdef HAVE_GETOPT_LONG |
69 | |
70 | |
70 | struct option longopts[] = { |
71 | struct option longopts[] = { |
71 | {"compress", 0, 0, 'c'}, |
72 | {"compress" , 0, 0, 'c'}, |
72 | {"decompress", 0, 0, 'd'}, |
73 | {"decompress", 0, 0, 'd'}, |
73 | {"uncompress", 0, 0, 'd'}, |
74 | {"uncompress", 0, 0, 'd'}, |
|
|
75 | {"best" , 0, 0, '9'}, |
74 | {"force", 0, 0, 'f'}, |
76 | {"force" , 0, 0, 'f'}, |
75 | {"help", 0, 0, 'h'}, |
77 | {"help" , 0, 0, 'h'}, |
76 | {"verbose", 0, 0, 'v'}, |
78 | {"verbose" , 0, 0, 'v'}, |
77 | {"blocksize", 1, 0, 'b'}, |
79 | {"blocksize" , 1, 0, 'b'}, |
78 | {0, 0, 0, 0} |
80 | {0 , 0, 0, 0} |
79 | }; |
81 | }; |
80 | |
82 | |
81 | static const char *opt = |
83 | static const char *opt = |
82 | "-c --compress compress\n" |
84 | "-c --compress compress\n" |
83 | "-d --decompress decompress\n" |
85 | "-d --decompress decompress\n" |
|
|
86 | "-9 --best best compression\n" |
84 | "-f --force force overwrite of output file\n" |
87 | "-f --force force overwrite of output file\n" |
85 | "-h --help give this help\n" "-v --verbose verbose mode\n" "-b # --blocksize # set blocksize\n" "\n"; |
88 | "-h --help give this help\n" |
|
|
89 | "-v --verbose verbose mode\n" |
|
|
90 | "-b # --blocksize # set blocksize\n" |
|
|
91 | "\n"; |
86 | |
92 | |
87 | #else |
93 | #else |
88 | |
94 | |
89 | static const char *opt = |
95 | static const char *opt = |
90 | "-c compress\n" |
96 | "-c compress\n" |
91 | "-d decompress\n" |
97 | "-d decompress\n" |
|
|
98 | "-9 best compression\n" |
92 | "-f force overwrite of output file\n" |
99 | "-f force overwrite of output file\n" |
93 | "-h give this help\n" |
100 | "-h give this help\n" |
94 | "-v verbose mode\n" |
101 | "-v verbose mode\n" |
95 | "-b # set blocksize\n" |
102 | "-b # set blocksize\n" |
96 | "\n"; |
103 | "\n"; |
… | |
… | |
103 | fprintf (stderr, "\n" |
110 | fprintf (stderr, "\n" |
104 | "lzf, a very lightweight compression/decompression utility written by Stefan Traby.\n" |
111 | "lzf, a very lightweight compression/decompression utility written by Stefan Traby.\n" |
105 | "uses liblzf written by Marc Lehmann <schmorp@schmorp.de> You can find more info at\n" |
112 | "uses liblzf written by Marc Lehmann <schmorp@schmorp.de> You can find more info at\n" |
106 | "http://liblzf.plan9.de/\n" |
113 | "http://liblzf.plan9.de/\n" |
107 | "\n" |
114 | "\n" |
108 | "usage: lzf [-dufhvb] [file ...]\n" |
115 | "usage: lzf [-dufhvb9] [file ...]\n" |
109 | " unlzf [file ...]\n" |
116 | " unlzf [file ...]\n" |
110 | " lzcat [file ...]\n" |
117 | " lzcat [file ...]\n" |
111 | "\n%s", |
118 | "\n%s", |
112 | opt); |
119 | opt); |
113 | |
120 | |
… | |
… | |
184 | u8 *header; |
191 | u8 *header; |
185 | |
192 | |
186 | nr_read = nr_written = 0; |
193 | nr_read = nr_written = 0; |
187 | while ((us = rread (from, &buf1[MAX_HDR_SIZE], blocksize)) > 0) |
194 | while ((us = rread (from, &buf1[MAX_HDR_SIZE], blocksize)) > 0) |
188 | { |
195 | { |
189 | cs = lzf_compress (&buf1[MAX_HDR_SIZE], us, &buf2[MAX_HDR_SIZE], us > 4 ? us - 4 : us); |
196 | cs = (best ? lzf_compress_best : lzf_compress) (&buf1[MAX_HDR_SIZE], us, &buf2[MAX_HDR_SIZE], us > 4 ? us - 4 : us); |
190 | if (cs) |
197 | if (cs) |
191 | { |
198 | { |
192 | header = &buf2[MAX_HDR_SIZE - TYPE1_HDR_SIZE]; |
199 | header = &buf2[MAX_HDR_SIZE - TYPE1_HDR_SIZE]; |
193 | header[0] = 'Z'; |
200 | header[0] = 'Z'; |
194 | header[1] = 'V'; |
201 | header[1] = 'V'; |
… | |
… | |
321 | |
328 | |
322 | if (force) |
329 | if (force) |
323 | m = 0; |
330 | m = 0; |
324 | |
331 | |
325 | fd = open (name, O_CREAT | O_WRONLY | O_TRUNC | m, 600); |
332 | fd = open (name, O_CREAT | O_WRONLY | O_TRUNC | m, 600); |
|
|
333 | #if defined(__MINGW32__) |
|
|
334 | _setmode(fd, _O_BINARY); |
|
|
335 | #endif |
326 | return fd; |
336 | return fd; |
327 | } |
337 | } |
328 | |
338 | |
329 | static int |
339 | static int |
330 | compose_name (const char *fname, char *oname) |
340 | compose_name (const char *fname, char *oname) |
… | |
… | |
374 | |
384 | |
375 | if (mode != lzcat) |
385 | if (mode != lzcat) |
376 | if (compose_name (fname, oname)) |
386 | if (compose_name (fname, oname)) |
377 | return -1; |
387 | return -1; |
378 | |
388 | |
|
|
389 | #if !defined(__MINGW32__) |
379 | rc = lstat (fname, &mystat); |
390 | rc = lstat (fname, &mystat); |
|
|
391 | #else |
|
|
392 | rc = stat (fname, &mystat); |
|
|
393 | #endif |
380 | fd = open (fname, O_RDONLY); |
394 | fd = open (fname, O_RDONLY); |
|
|
395 | #if defined(__MINGW32__) |
|
|
396 | _setmode(fd, _O_BINARY); |
|
|
397 | #endif |
381 | if (rc || fd == -1) |
398 | if (rc || fd == -1) |
382 | { |
399 | { |
383 | fprintf (stderr, "%s: %s: ", imagename, fname); |
400 | fprintf (stderr, "%s: %s: ", imagename, fname); |
384 | perror (""); |
401 | perror (""); |
385 | return -1; |
402 | return -1; |
… | |
… | |
421 | if (!rc && verbose) |
438 | if (!rc && verbose) |
422 | fprintf (stderr, "%s: %5.1f%% -- replaced with %s\n", |
439 | fprintf (stderr, "%s: %5.1f%% -- replaced with %s\n", |
423 | fname, nr_written == 0 ? 0 : 100.0 - nr_read / ((double) nr_written / 100.0), oname); |
440 | fname, nr_written == 0 ? 0 : 100.0 - nr_read / ((double) nr_written / 100.0), oname); |
424 | } |
441 | } |
425 | |
442 | |
|
|
443 | #if !defined(__MINGW32__) |
426 | fchmod (fd2, mystat.st_mode); |
444 | fchmod (fd2, mystat.st_mode); |
|
|
445 | #else |
|
|
446 | chmod (oname, mystat.st_mode); |
|
|
447 | #endif |
427 | close (fd); |
448 | close (fd); |
428 | close (fd2); |
449 | close (fd2); |
429 | |
450 | |
430 | if (!rc) |
451 | if (!rc) |
431 | unlink (fname); |
452 | unlink (fname); |
… | |
… | |
457 | |
478 | |
458 | if (strstr (imagename, "cat")) |
479 | if (strstr (imagename, "cat")) |
459 | mode = lzcat; |
480 | mode = lzcat; |
460 | |
481 | |
461 | #ifdef HAVE_GETOPT_LONG |
482 | #ifdef HAVE_GETOPT_LONG |
462 | while ((optc = getopt_long (argc, argv, "cdfhvb:", longopts, 0)) != -1) |
483 | while ((optc = getopt_long (argc, argv, "cd9fhvb:", longopts, 0)) != -1) |
463 | #else |
484 | #else |
464 | while ((optc = getopt (argc, argv, "cdfhvb:")) != -1) |
485 | while ((optc = getopt (argc, argv, "cd9fhvb:")) != -1) |
465 | #endif |
486 | #endif |
466 | { |
487 | { |
467 | switch (optc) |
488 | switch (optc) |
468 | { |
489 | { |
469 | case 'c': |
490 | case 'c': |
470 | mode = compress; |
491 | mode = compress; |
471 | break; |
492 | break; |
472 | case 'd': |
493 | case 'd': |
473 | mode = uncompress; |
494 | mode = uncompress; |
|
|
495 | break; |
|
|
496 | case '9': |
|
|
497 | best = 1; |
474 | break; |
498 | break; |
475 | case 'f': |
499 | case 'f': |
476 | force = 1; |
500 | force = 1; |
477 | break; |
501 | break; |
478 | case 'h': |
502 | case 'h': |