prepcore: actually do a full binary comparison on the output end
[profile/ivi/syslinux.git] / lzo / prepcore.c
1 /* ----------------------------------------------------------------------- *
2  *   
3  *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
4  *
5  *   This program is free software; you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
8  *   Boston MA 02110-1301, USA; either version 2 of the License, or
9  *   (at your option) any later version; incorporated herein by reference.
10  *
11  * ----------------------------------------------------------------------- */
12
13 /* 
14    This file is based in part on:
15
16    precomp2.c -- example program: how to generate pre-compressed data
17
18    This file is part of the LZO real-time data compression library.
19
20    Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
21    Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
22    Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
23    Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
24    Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
25    Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
26    Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
27    Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
28    Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
29    Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
30    Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
31    Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
32    Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
33    All Rights Reserved.
34
35    The LZO library is free software; you can redistribute it and/or
36    modify it under the terms of the GNU General Public License as
37    published by the Free Software Foundation; either version 2 of
38    the License, or (at your option) any later version.
39
40    The LZO library is distributed in the hope that it will be useful,
41    but WITHOUT ANY WARRANTY; without even the implied warranty of
42    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
43    GNU General Public License for more details.
44
45    You should have received a copy of the GNU General Public License
46    along with the LZO library; see the file COPYING.
47    If not, write to the Free Software Foundation, Inc.,
48    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
49
50    Markus F.X.J. Oberhumer
51    <markus@oberhumer.com>
52    http://www.oberhumer.com/opensource/lzo/
53  */
54
55 #include "lzo/lzoconf.h"
56 #include "lzo/lzo1x.h"
57
58 LZO_EXTERN(int)
59 lzo1x_999_compress_internal(const lzo_bytep in, lzo_uint in_len,
60                             lzo_bytep out, lzo_uintp out_len,
61                             lzo_voidp wrkmem,
62                             const lzo_bytep dict, lzo_uint dict_len,
63                             lzo_callback_p cb,
64                             int try_lazy,
65                             lzo_uint good_length,
66                             lzo_uint max_lazy,
67                             lzo_uint nice_length,
68                             lzo_uint max_chain, lzo_uint32 flags);
69
70 LZO_EXTERN(int)
71 lzo1y_999_compress_internal(const lzo_bytep in, lzo_uint in_len,
72                             lzo_bytep out, lzo_uintp out_len,
73                             lzo_voidp wrkmem,
74                             const lzo_bytep dict, lzo_uint dict_len,
75                             lzo_callback_p cb,
76                             int try_lazy,
77                             lzo_uint good_length,
78                             lzo_uint max_lazy,
79                             lzo_uint nice_length,
80                             lzo_uint max_chain, lzo_uint32 flags);
81
82 #define PARANOID 1
83
84 #include <assert.h>
85 #include <inttypes.h>
86 #include <stddef.h>
87 #include <stdlib.h>
88 #include <stdio.h>
89 #include <string.h>
90 #include <ctype.h>
91 #include <time.h>
92
93 struct prefix {
94     uint32_t pfx_start;
95     uint32_t pfx_compressed;
96     uint32_t pfx_cdatalen;
97     uint32_t pfx_checksum;
98 };
99
100 static inline uint32_t get_32(const uint32_t * p)
101 {
102 #if defined(__i386__) || defined(__x86_64__)
103     /* Littleendian and unaligned-capable */
104     return *p;
105 #else
106     const uint8_t *pp = (const uint8_t *)p;
107     return (uint32_t) pp[0] + ((uint32_t) pp[1] << 8) +
108         ((uint32_t) pp[2] << 16) + ((uint32_t) pp[3] << 24);
109 #endif
110 }
111
112 static inline void set_32(uint32_t * p, uint32_t v)
113 {
114 #if defined(__i386__) || defined(__x86_64__)
115     /* Littleendian and unaligned-capable */
116     *p = v;
117 #else
118     uint8_t *pp = (uint8_t *) p;
119     pp[0] = (v & 0xff);
120     pp[1] = ((v >> 8) & 0xff);
121     pp[2] = ((v >> 16) & 0xff);
122     pp[3] = ((v >> 24) & 0xff);
123 #endif
124 }
125
126 /*************************************************************************
127 //
128 **************************************************************************/
129
130 int __lzo_cdecl_main main(int argc, char *argv[])
131 {
132     int r;
133     int lazy;
134     const int max_try_lazy = 5;
135     const lzo_uint big = 65536L;        /* can result in very slow compression */
136     const lzo_uint32 flags = 0x1;
137
138     lzo_bytep in;
139     lzo_bytep infile;
140     lzo_uint in_len, infile_len, start, offset, soff;
141
142     lzo_bytep out;
143     lzo_uint out_bufsize;
144     lzo_uint out_len = 0;
145     lzo_uint outfile_len;
146
147     lzo_bytep test;
148
149     lzo_byte wrkmem[LZO1X_999_MEM_COMPRESS];
150
151     lzo_uint best_len;
152     int best_lazy = -1;
153
154     lzo_uint orig_len;
155     lzo_uint32 uncompressed_checksum;
156     lzo_uint32 compressed_checksum;
157
158     FILE *f;
159     const char *progname = NULL;
160     const char *in_name = NULL;
161     const char *out_name = NULL;
162     long l;
163
164     struct prefix *prefix;
165
166     progname = argv[0];
167     if (argc != 3) {
168         printf("usage: %s file output-file\n", progname);
169         exit(1);
170     }
171     in_name = argv[1];
172     if (argc > 2)
173         out_name = argv[2];
174
175 /*
176  * Step 1: initialize the LZO library
177  */
178     if (lzo_init() != LZO_E_OK) {
179         printf("internal error - lzo_init() failed !!!\n");
180         printf
181             ("(this usually indicates a compiler bug - try recompiling\nwithout optimizations, and enable `-DLZO_DEBUG' for diagnostics)\n");
182         exit(1);
183     }
184
185 /*
186  * Step 3: open the input file
187  */
188     f = fopen(in_name, "rb");
189     if (f == NULL) {
190         printf("%s: cannot open file %s\n", progname, in_name);
191         exit(1);
192     }
193     fseek(f, 0, SEEK_END);
194     l = ftell(f);
195     fseek(f, 0, SEEK_SET);
196     if (l <= 0) {
197         printf("%s: %s: empty file\n", progname, in_name);
198         fclose(f);
199         exit(1);
200     }
201     infile_len = (lzo_uint) l;
202     out_bufsize = infile_len + infile_len / 16 + 64 + 3 + 2048;
203
204 /*
205  * Step 4: allocate compression buffers and read the file
206  */
207     infile = (lzo_bytep) malloc(infile_len);
208     out = (lzo_bytep) malloc(out_bufsize);
209     if (infile == NULL || out == NULL) {
210         printf("%s: out of memory\n", progname);
211         exit(1);
212     }
213     infile_len = (lzo_uint) fread(infile, 1, infile_len, f);
214     fclose(f);
215
216 /*
217  * Select the portion which is for compression...
218  */
219     prefix = (struct prefix *)infile;
220     start = get_32(&prefix->pfx_start);
221     offset = get_32(&prefix->pfx_compressed);
222     in = infile + offset;
223     in_len = infile_len - offset;
224     best_len = in_len;
225
226 /*
227  * Step 5: compute a checksum of the uncompressed data
228  */
229     uncompressed_checksum = lzo_adler32(0, NULL, 0);
230     uncompressed_checksum = lzo_adler32(uncompressed_checksum, in, in_len);
231
232 /*
233  * Step 6a: compress from `in' to `out' with LZO1X-999
234  */
235     for (lazy = 0; lazy <= max_try_lazy; lazy++) {
236         out_len = out_bufsize;
237         r = lzo1x_999_compress_internal(in, in_len, out, &out_len, wrkmem,
238                                         NULL, 0, 0,
239                                         lazy, big, big, big, big, flags);
240         if (r != LZO_E_OK) {
241             /* this should NEVER happen */
242             printf("internal error - compression failed: %d\n", r);
243             exit(1);
244         }
245         if (out_len < best_len) {
246             best_len = out_len;
247             best_lazy = lazy;
248         }
249     }
250
251 /*
252  * Step 7: check if compressible
253  */
254     if (best_len >= in_len) {
255         printf("This file contains incompressible data.\n");
256         /* return 0;  -- Sucks to be us -hpa ... */
257     }
258
259 /*
260  * Step 8: compress data again using the best compressor found
261  */
262     out_len = out_bufsize;
263     r = lzo1x_999_compress_internal(in, in_len, out, &out_len, wrkmem,
264                                     NULL, 0, 0,
265                                     best_lazy, big, big, big, big, flags);
266     assert(r == LZO_E_OK);
267     assert(out_len == best_len);
268
269 /*
270  * Step 9: optimize compressed data (compressed data is in `out' buffer)
271  */
272 #if 1
273     /* Optimization does not require any data in the buffer that will
274      * hold the uncompressed data. To prove this, we clear the buffer.
275      */
276     memset(in, 0, in_len);
277 #endif
278
279     orig_len = in_len;
280     r = lzo1x_optimize(out, out_len, in, &orig_len, NULL);
281     if (r != LZO_E_OK || orig_len != in_len) {
282         /* this should NEVER happen */
283         printf("internal error - optimization failed: %d\n", r);
284         exit(1);
285     }
286
287 /*
288  * Step 10: compute a checksum of the compressed data
289  */
290     compressed_checksum = lzo_adler32(0, NULL, 0);
291     compressed_checksum = lzo_adler32(compressed_checksum, out, out_len);
292
293 /*
294  * Step 11: write compressed data to a file
295  */
296     /* Make sure we have up to 2048 bytes of zero after the output */
297     memset(out + out_len, 0, 2048);
298
299     outfile_len = out_len;
300
301     soff = get_32(&prefix->pfx_cdatalen);
302     set_32((uint32_t *) (infile + soff), out_len);
303
304     soff = get_32(&prefix->pfx_checksum);
305     if (soff) {
306         /* ISOLINUX padding and checksumming */
307         uint32_t csum = 0;
308         unsigned int ptr;
309         outfile_len =
310             ((offset - start + out_len + 2047) & ~2047) - (offset - start);
311         for (ptr = 64; ptr < offset; ptr += 4)
312             csum += get_32((uint32_t *) (infile + ptr));
313         for (ptr = 0; ptr < outfile_len; ptr += 4)
314             csum += get_32((uint32_t *) (out + ptr));
315
316         set_32((uint32_t *) (infile + soff), offset - start + outfile_len);
317         set_32((uint32_t *) (infile + soff + 4), csum);
318     }
319
320     f = fopen(out_name, "wb");
321     if (f == NULL) {
322         printf("%s: cannot open output file %s\n", progname, out_name);
323         exit(1);
324     }
325     if (fwrite(infile + start, 1, offset - start, f) != offset - start ||
326         fwrite(out, 1, outfile_len, f) != outfile_len || fclose(f)) {
327         printf("%s: write error !!\n", progname);
328         exit(1);
329     }
330
331 /*
332  * Step 12: verify decompression
333  */
334 #ifdef PARANOID
335     test = calloc(in_len,2);
336     orig_len = in_len*2;
337     r = lzo1x_decompress_safe(out, out_len, test, &orig_len, NULL);
338
339     if (r != LZO_E_OK || orig_len != in_len) {
340         /* this should NEVER happen */
341         printf("internal error - decompression failed: %d\n", r);
342         exit(1);
343     }
344     if (memcmp(test, in, in_len)) {
345         /* this should NEVER happen */
346         printf("internal error - decompression data error\n");
347         exit(1);
348     }
349     /* Now you could also verify decompression under similar conditions as in
350      * your application, e.g. overlapping assembler decompression etc.
351      */
352
353     free(test);
354 #endif
355
356     free(infile);
357     free(out);
358
359     return 0;
360 }