source: trunk/src/exepack_fill.c@ 541

Last change on this file since 541 was 456, checked in by katerina, 10 years ago

Fix for ticket #356 (minor bug in exepack_fill.c).

File size: 8.7 KB
Line 
1/* +++Date last modified: 05-Jul-1997 */
2
3/*
4** Case-sensitive Boyer-Moore-Horspool pattern match
5**
6** public domain by Raymond Gardner 7/92
7**
8** limitation: pattern length + string length must be less than 32767
9**
10** 10/21/93 rdg Fixed bug found by Jeff Dunlop
11**
12** limitation lifted Rainer Wichmann 07/2000
13*/
14#include "config.h"
15
16#ifdef HAVE_BROKEN_INCLUDES
17#define _ANSI_C_SOURCE
18#define _POSIX_SOURCE
19#endif
20
21#include <limits.h> /* rdg 10/93 */
22#include <stddef.h>
23#include <string.h>
24
25typedef unsigned char uchar;
26
27#define LARGE 2147483647 /* rw 7/2000 */
28
29static long patlen; /* rw 7/2000 */
30static long skip[UCHAR_MAX+1]; /* rw 7/2000 */ /* rdg 10/93 */
31static long skip2; /* rw 7/2000 */
32static uchar *pat; /* rw 7/2000 */
33
34void bmh_init(const char *pattern)
35{
36 long i, lastpatchar;
37
38 pat = (uchar *)pattern;
39 patlen = strlen(pattern);
40 for (i = 0; i <= UCHAR_MAX; ++i) /* rdg 10/93 */
41 skip[i] = patlen;
42 for (i = 0; i < patlen; ++i)
43 skip[pat[i]] = patlen - i - 1;
44 lastpatchar = pat[patlen - 1];
45 skip[lastpatchar] = LARGE;
46 skip2 = patlen; /* Horspool's fixed second shift */
47 for (i = 0; i < patlen - 1; ++i)
48 {
49 if (pat[i] == lastpatchar)
50 skip2 = patlen - i - 1;
51 }
52}
53
54char * bmh_search(const char * string, const long stringlen)
55{
56 long i, j; /* rw 7/2000 */
57 char *s;
58
59 i = patlen - 1 - stringlen;
60 if (i >= 0)
61 return NULL;
62 string += stringlen;
63 for ( ;; )
64 {
65 while ( (i += skip[((uchar *)string)[i]]) < 0 )
66 ; /* mighty fast inner loop */
67 if (i < (LARGE - stringlen))
68 return NULL;
69 i -= LARGE;
70 j = patlen - 1;
71 s = (char *)string + (i - j);
72 while (--j >= 0 && s[j] == pat[j])
73 ;
74 if ( j < 0 ) /* rdg 10/93 */
75 return s; /* rdg 10/93 */
76 if ( (i += skip2) >= 0 ) /* rdg 10/93 */
77 return NULL; /* rdg 10/93 */
78 }
79}
80
81/* Everything below: Copyright 2000, Rainer Wichmann */
82
83char * my_locate (const char * pattern, const char * data, const long datalen)
84{
85 bmh_init (pattern);
86 return (bmh_search (data, datalen) );
87}
88
89#include <stdio.h>
90#include <stdlib.h>
91#include <sys/stat.h>
92#include <unistd.h>
93
94
95#include "config.h"
96
97#include "minilzo.h"
98
99/* integer data type that is _exactly_ 32 bit
100 */
101#if defined(HAVE_INT_32)
102#define UINT32 unsigned int
103#elif defined(HAVE_LONG_32)
104#define UINT32 unsigned long
105#elif defined(HAVE_SHORT_32)
106#define UINT32 unsigned short
107#endif
108
109static UINT32 cstate[3], astate[3];
110
111static UINT32 taus_get_long (UINT32 * state)
112{
113#define TAUSWORTHE(s,a,b,c,d) ((s &c) <<d) ^ (((s <<a) ^s) >>b)
114
115 state[0] = TAUSWORTHE (state[0], 13, 19, 4294967294UL, 12);
116 state[1] = TAUSWORTHE (state[1], 2, 25, 4294967288UL, 4);
117 state[2] = TAUSWORTHE (state[2], 3, 11, 4294967280UL, 17);
118
119 return (state[0] ^ state[1] ^ state[2]);
120}
121
122void taus_set_from_state (UINT32 * state, UINT32 * state0)
123{
124 state[0] = state0[0] | (UINT32) 0x03;
125 state[1] = state0[1] | (UINT32) 0x09;
126 state[2] = state0[2] | (UINT32) 0x17;
127
128 /* 'warm up'
129 */
130 taus_get_long (state);
131 taus_get_long (state);
132 taus_get_long (state);
133 taus_get_long (state);
134 taus_get_long (state);
135 taus_get_long (state);
136
137 return;
138}
139
140int replaceData (char * data, long len, char * in, char * out, long size)
141{
142 char * pos;
143 int i;
144
145 pos = my_locate (in, data, len);
146 if (pos == NULL)
147 return (-1);
148
149 for (i = 0; i < size; ++i)
150 {
151 pos[i] = out[i];
152 }
153
154 return 0;
155}
156
157/* Work-memory needed for compression. Allocate memory in units
158 * of `long' (instead of `char') to make sure it is properly aligned.
159 */
160#define HEAP_ALLOC(var,size) long __LZO_MMODEL var [ ((size) + (sizeof(long) - 1)) / sizeof(long) ]
161
162static HEAP_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS);
163
164#include <sys/types.h>
165#include <sys/stat.h>
166#include <fcntl.h>
167
168int main(int argc, char * argv[])
169{
170 FILE * fd;
171 unsigned long clen;
172 char * data;
173 struct stat sbuf;
174
175 char * ptest;
176
177 unsigned long i;
178
179 int status;
180
181 unsigned long len = 0;
182 unsigned long have = 0;
183
184 /* For compression.
185 */
186 lzo_byte * inbuf;
187 lzo_byte * outbuf;
188 int r;
189 lzo_uint in_len;
190 lzo_uint out_len;
191
192 UINT32 len_raw;
193 UINT32 len_cmp;
194
195
196 astate[0] = EXEPACK_STATE_0;
197 astate[1] = EXEPACK_STATE_1;
198 astate[2] = EXEPACK_STATE_2;
199
200
201 if (argc < 4)
202 {
203 fprintf(stderr,
204 "Usage: exepack_fill <container_file> <infile> <outfile>\n");
205 exit (EXIT_FAILURE);
206 }
207
208 if (0 != stat (argv[1], &sbuf))
209 {
210 fprintf(stderr, "exepack_fill: could not access file %s\n", argv[1]);
211 return (-1);
212 }
213 clen = sbuf.st_size;
214
215
216 data = (char *) malloc (clen * sizeof(char));
217 if (data == NULL)
218 return (-1);
219
220 fd = fopen (argv[1], "r");
221 if (fd == NULL)
222 return (-1);
223
224 if (clen != fread (data, 1, clen, fd))
225 return (-1);
226 fclose (fd);
227
228
229 /*******************
230 *
231 * THE DATA
232 *
233 *******************/
234
235
236
237 if (stat (argv[2], &sbuf) < 0)
238 {
239 perror ("exepack_fill");
240 exit (EXIT_FAILURE);
241 }
242
243 len = (unsigned long) sbuf.st_size;
244
245 /* Because the input block may be incompressible,
246 * we must provide a little more output space in case that compression
247 * is not possible.
248 */
249 inbuf = (lzo_byte *) malloc (sizeof(lzo_byte) * len);
250 outbuf = (lzo_byte *) malloc (sizeof(lzo_byte) * (len + len / 64 + 16 + 3));
251 in_len = len;
252
253 if (NULL == inbuf || NULL == outbuf)
254 {
255 fprintf(stderr, "exepack_fill: Out of memory.");
256 exit (EXIT_FAILURE);
257 }
258
259 if (NULL == (fd = fopen(argv[2], "r")))
260 {
261 perror ("exepack_fill");
262 exit (EXIT_FAILURE);
263 }
264
265 have = fread (inbuf, 1, len, fd);
266 fclose (fd);
267
268 if (have != len)
269 {
270 fprintf (stderr, "exepack_mkdata: Error reading %s", argv[2]);
271 exit (EXIT_FAILURE);
272 }
273
274 /*
275 * Step 1: initialize the LZO library
276 */
277 if (lzo_init() != LZO_E_OK)
278 {
279 fprintf(stderr, "exepack_fill: lzo_init() failed\n");
280 return 3;
281 }
282
283 /*
284 * Step 3: compress from `in' to `out' with LZO1X-1
285 */
286 r = lzo1x_1_compress(inbuf, in_len, outbuf, &out_len, wrkmem);
287
288 if (r == LZO_E_OK)
289 printf("exepack_fill: compressed %lu bytes into %lu bytes\n",
290 (long) in_len, (long) out_len);
291 else
292 {
293 /* this should NEVER happen */
294 printf("exepack_fill: internal error - compression failed: %d\n", r);
295 return 2;
296 }
297
298 /* check for an incompressible block
299 */
300 if (out_len >= in_len)
301 {
302 printf("exepack_fill: Incompressible data.\n");
303 }
304
305 taus_set_from_state (cstate, astate);
306 for (i = 0; i < out_len; ++i)
307 {
308 outbuf[i] ^= (taus_get_long (cstate) & 0xff);
309 }
310
311 len_raw = in_len;
312 len_cmp = out_len;
313
314 if ( (unsigned long) len_cmp > (unsigned long) clen)
315 {
316 printf("exepack_fill: Compressed length (%ld) exceeds container length (%ld).\n", (long) len_cmp, (long) clen);
317 return (8);
318 }
319
320
321 /***********
322 *
323 * Fill program
324 *
325 **********/
326
327 status = replaceData (data, clen, "LLLL", (char *) &len_raw, sizeof(UINT32));
328 if (status < 0)
329 {
330 printf("exepack_fill: Could not write raw lenght %d.\n", len_raw);
331 return (8);
332 }
333 status = replaceData (data, clen, "CCCC", (char *) &len_cmp, sizeof(UINT32));
334 if (status < 0)
335 {
336 printf("exepack_fill: Could not write compressed lenght %d.\n",
337 len_cmp);
338 return (8);
339 }
340 status = replaceData (data, clen, "CONTAINER", (char *) outbuf, out_len);
341 if (status < 0)
342 {
343 printf("exepack_fill: Could not write program data.\n");
344 return (8);
345 }
346
347 /***********
348 *
349 * Write program
350 *
351 **********/
352
353 if ( NULL == (fd = fopen(argv[3], "w" )))
354 {
355 perror ("exepack_fill");
356 exit (EXIT_FAILURE);
357 }
358
359 fwrite (data, 1, clen, fd);
360
361 fclose (fd);
362
363 ptest = my_locate("LLLL", data, clen);
364 if (ptest != NULL)
365 {
366 printf("exepack_fill: ERROR: program length not updated.\n");
367 return (8);
368 }
369 ptest = my_locate("CCCC", data, clen);
370 if (ptest != NULL)
371 {
372 printf("exepack_fill: ERROR: compressed program length not updated.\n");
373 return (8);
374 }
375 ptest = my_locate("CONTAINER", data, clen);
376 if (ptest != NULL)
377 {
378 printf("exepack_fill: ERROR: program data not updated.\n");
379 return (8);
380 }
381
382 return 0;
383}
384
Note: See TracBrowser for help on using the repository browser.