ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/liblzf/lzf.c
Revision: 1.9
Committed: Fri Sep 29 19:43:01 2006 UTC (17 years, 7 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.8: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 * Copyright (c) 2000-2005 Marc Alexander Lehmann <schmorp@schmorp.de>
3 *
4 * Redistribution and use in source and binary forms, with or without modifica-
5 * tion, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
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
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
19 * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
21 * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * 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
26 * OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * 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
30 * provisions of the GPL are applicable instead of the above. If you wish to
31 * allow the use of your version of this file only under the terms of the
32 * GPL and not to allow others to use your version of this file under the
33 * BSD license, indicate your decision by deleting the provisions above and
34 * replace them with the notice and other provisions required by the GPL. If
35 * you do not delete the provisions above, a recipient may use your version
36 * of this file under either the BSD or the GPL.
37 */
38
39 #include "config.h"
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <assert.h>
45
46 #include <unistd.h>
47 #include <getopt.h>
48
49 #include "lzf.h"
50
51 typedef unsigned char u8;
52
53 static void
54 usage (int ec)
55 {
56 fprintf (stderr, "\n"
57 "lzf, a very lightweight compression/decompression filter\n"
58 "written by Marc Lehmann <schmorp@schmorp.de> You can find more info at\n"
59 "http://liblzf.plan9.de/\n"
60 "\n"
61 "USAGE: lzf -c [-b blocksize] | -d\n"
62 " -c compress\n"
63 " -d decompress\n"
64 " -b specify the blocksize (default 64k-1)\n"
65 "\n"
66 );
67
68 exit (ec);
69 }
70
71 /*
72 * Anatomy: an lzf file consists of any number of blocks in the following format:
73 *
74 * \x00 EOF (optional)
75 * "ZV\0" 2-byte-usize <uncompressed data>
76 * "ZV\1" 2-byte-csize 2-byte-usize <compressed data>
77 * "ZV\2" 4-byte-crc32-0xdebb20e3 (NYI)
78 *
79 */
80
81 static void compress (unsigned int blocksize)
82 {
83 ssize_t us;
84 unsigned int cs;
85 u8 buff1[64*1024];
86 u8 buff2[64*1024];
87 u8 header[3+2+2];
88
89 header[0] = 'Z';
90 header[1] = 'V';
91
92 for(;;) {
93 us = fread (buff1, 1, blocksize, stdin);
94
95 if (us < blocksize)
96 {
97 if (us == 0)
98 break;
99 else if (!feof (stdin))
100 {
101 perror ("compress");
102 exit (1);
103 }
104 }
105
106 cs = lzf_compress (buff1, us, buff2, us - 4);
107
108 if (cs)
109 {
110 header[2] = 1;
111 header[3] = cs >> 8;
112 header[4] = cs & 0xff;
113 header[5] = us >> 8;
114 header[6] = us & 0xff;
115
116 fwrite (header, 3+2+2, 1, stdout);
117 fwrite (buff2, cs, 1, stdout);
118 }
119 else
120 {
121 header[2] = 0;
122 header[3] = us >> 8;
123 header[4] = us & 0xff;
124
125 fwrite (header, 3+2, 1, stdout);
126 fwrite (buff1, us, 1, stdout);
127 }
128 }
129 }
130
131 static void decompress (void)
132 {
133 ssize_t us;
134 unsigned int cs;
135 u8 buff1[64*1024];
136 u8 buff2[64*1024];
137 u8 header[3+2+2];
138
139 for(;;) {
140 int hdrsize = fread (header, 1, 3+2, stdin);
141
142 /* check for \0 record */
143 if (hdrsize)
144 {
145 if (!header[0])
146 break;
147 else if (hdrsize != 3+2)
148 {
149 if (feof (stdin))
150 fprintf (stderr, "decompress: invalid stream - short header\n");
151 else
152 perror ("decompress");
153
154 exit (1);
155 }
156 }
157 else
158 {
159 if (feof (stdin))
160 break;
161 else
162 {
163 perror ("decompress");
164 exit (1);
165 }
166 }
167
168 if (header[0] != 'Z' || header[1] != 'V')
169 {
170 fprintf (stderr, "decompress: invalid stream - no magic number found\n");
171 exit (1);
172 }
173
174 cs = (header[3] << 8) | header[4];
175
176 if (header[2] == 1)
177 {
178 if (fread (header+3+2, 2, 1, stdin) != 1)
179 {
180 perror ("decompress");
181 exit (1);
182 }
183
184 us = (header[5] << 8) | header[6];
185
186 if (fread (buff1, cs, 1, stdin) != 1)
187 {
188 perror ("decompress");
189 exit (1);
190 }
191
192 if (lzf_decompress (buff1, cs, buff2, us) != us)
193 {
194 fprintf (stderr, "decompress: invalid stream - data corrupted\n");
195 exit (1);
196 }
197
198 fwrite (buff2, us, 1, stdout);
199 }
200 else if (header[2] == 0)
201 {
202 if (fread (buff2, cs, 1, stdin) != 1)
203 {
204 perror ("decompress");
205 exit (1);
206 }
207
208 fwrite (buff2, cs, 1, stdout);
209 }
210 else
211 {
212 fprintf (stderr, "decompress: invalid stream - unknown block type\n");
213 exit (1);
214 }
215 }
216 }
217
218 int
219 main (int argc, char *argv[])
220 {
221 int c;
222 unsigned int blocksize = 64*1024-1;
223 enum { m_compress, m_decompress } mode = m_compress;
224
225 while ((c = getopt (argc, argv, "cdb:h")) != -1)
226 switch (c)
227 {
228 case 'c':
229 mode = m_compress;
230 break;
231
232 case 'd':
233 mode = m_decompress;
234 break;
235
236 case 'b':
237 blocksize = atol (optarg);
238 break;
239
240 case 'h':
241 usage (0);
242
243 case ':':
244 fprintf (stderr, "required argument missing, use -h\n");
245 exit (1);
246
247 case '?':
248 fprintf (stderr, "unknown option, use -h\n");
249 exit (1);
250
251 default:
252 usage (1);
253 }
254
255 if (mode == m_compress)
256 compress (blocksize);
257 else if (mode == m_decompress)
258 decompress ();
259 else
260 abort ();
261
262 return 0;
263 }