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, 4 months ago) by pcg
Content type: text/plain
Branch: MAIN
Changes since 1.2: +5 -3 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 /*
2 pcg 1.3 * Copyright (c) 2000-2003 Marc Alexander Lehmann <pcg@goof.com>
3 root 1.1 *
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 pcg 1.3 typedef unsigned char u8;
41    
42 root 1.1 static void
43     usage (int ec)
44     {
45     fprintf (stderr, "\n"
46 pcg 1.3 "lzf, a very lightweight compression/decompression filter\n"
47 root 1.1 "written by Marc Lehmann <pcg@goof.com> You can find more info at\n"
48 pcg 1.3 "http://liblzf.plan9.de/\n"
49 root 1.1 "\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     }