ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/liblzf/lzf.c
Revision: 1.3
Committed: Tue Dec 23 04:52:00 2003 UTC (20 years, 9 months ago) by pcg
Content type: text/plain
Branch: MAIN
Changes since 1.2: +5 -3 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 * Copyright (c) 2000-2003 Marc Alexander Lehmann <pcg@goof.com>
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
29 #include "config.h"
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <assert.h>
34
35 #include <unistd.h>
36 #include <getopt.h>
37
38 #include "lzf.h"
39
40 typedef unsigned char u8;
41
42 static void
43 usage (int ec)
44 {
45 fprintf (stderr, "\n"
46 "lzf, a very lightweight compression/decompression filter\n"
47 "written by Marc Lehmann <pcg@goof.com> You can find more info at\n"
48 "http://liblzf.plan9.de/\n"
49 "\n"
50 "USAGE: lzf -c [-b blocksize] | -d\n"
51 " -c compress\n"
52 " -d decompress\n"
53 " -b specify the blocksize (default 64k-1)\n"
54 "\n"
55 );
56
57 exit (ec);
58 }
59
60 /*
61 * Anatomy: an lzf file consists of any number of blocks in the following format:
62 *
63 * "ZV\0" 2-byte-usize <uncompressed data>
64 * "ZV\1" 2-byte-csize 2-byte-usize <compressed data>
65 * "ZV\2" 4-byte-crc32-0xdebb20e3 (NYI)
66 *
67 */
68
69 static void compress (unsigned int blocksize)
70 {
71 ssize_t us;
72 unsigned int cs;
73 u8 buff1[64*1024];
74 u8 buff2[64*1024];
75 u8 header[3+2+2];
76
77 header[0] = 'Z';
78 header[1] = 'V';
79
80 for(;;) {
81 us = fread (buff1, 1, blocksize, stdin);
82
83 if (us < blocksize)
84 {
85 if (us == 0)
86 break;
87 else if (!feof (stdin))
88 {
89 perror ("compress");
90 exit (1);
91 }
92 }
93
94 cs = lzf_compress (buff1, us, buff2, us - 4);
95
96 if (cs)
97 {
98 header[2] = 1;
99 header[3] = cs >> 8;
100 header[4] = cs & 0xff;
101 header[5] = us >> 8;
102 header[6] = us & 0xff;
103
104 fwrite (header, 3+2+2, 1, stdout);
105 fwrite (buff2, cs, 1, stdout);
106 }
107 else
108 {
109 header[2] = 0;
110 header[3] = us >> 8;
111 header[4] = us & 0xff;
112
113 fwrite (header, 3+2, 1, stdout);
114 fwrite (buff1, us, 1, stdout);
115 }
116 } while (!feof (stdin));
117 }
118
119 static void decompress (void)
120 {
121 ssize_t us;
122 unsigned int cs;
123 u8 buff1[64*1024];
124 u8 buff2[64*1024];
125 u8 header[3+2+2];
126
127 for(;;) {
128 if (fread (header, 3+2, 1, stdin) != 1)
129 {
130 if (feof (stdin))
131 break;
132 else
133 {
134 perror ("decompress");
135 exit (1);
136 }
137 }
138
139 if (header[0] != 'Z' || header[1] != 'V')
140 {
141 fprintf (stderr, "decompress: invalid stream - no magic number found\n");
142 exit (1);
143 }
144
145 cs = (header[3] << 8) | header[4];
146
147 if (header[2] == 1)
148 {
149 if (fread (header+3+2, 2, 1, stdin) != 1)
150 {
151 perror ("decompress");
152 exit (1);
153 }
154
155 us = (header[5] << 8) | header[6];
156
157 if (fread (buff1, cs, 1, stdin) != 1)
158 {
159 perror ("decompress");
160 exit (1);
161 }
162
163 if (lzf_decompress (buff1, cs, buff2, us) != us)
164 {
165 fprintf (stderr, "decompress: invalid stream - data corrupted\n");
166 exit (1);
167 }
168
169 fwrite (buff2, us, 1, stdout);
170 }
171 else if (header[2] == 0)
172 {
173 if (fread (buff2, cs, 1, stdin) != 1)
174 {
175 perror ("decompress");
176 exit (1);
177 }
178
179 fwrite (buff2, cs, 1, stdout);
180 }
181 else
182 {
183 fprintf (stderr, "decompress: invalid stream - unknown block type\n");
184 exit (1);
185 }
186 }
187 }
188
189 int
190 main (int argc, char *argv[])
191 {
192 int c;
193 unsigned int blocksize = 64*1024-1;
194 enum { m_compress, m_decompress } mode = m_compress;
195
196 while ((c = getopt (argc, argv, "cdb:h")) != -1)
197 switch (c)
198 {
199 case 'c':
200 mode = m_compress;
201 break;
202
203 case 'd':
204 mode = m_decompress;
205 break;
206
207 case 'b':
208 blocksize = atol (optarg);
209 break;
210
211 case 'h':
212 usage (0);
213
214 case ':':
215 fprintf (stderr, "required argument missing, use -h\n");
216 exit (1);
217
218 case '?':
219 fprintf (stderr, "unknown option, use -h\n");
220 exit (1);
221
222 default:
223 usage (1);
224 }
225
226 if (mode == m_compress)
227 compress (blocksize);
228 else if (mode == m_decompress)
229 decompress ();
230 else
231 abort ();
232
233 return 0;
234 }