diff options
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/bzip2/bzip2.c')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/bzip2/bzip2.c | 2034 |
1 files changed, 2034 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/bzip2/bzip2.c b/libraries/irrlicht-1.8/source/Irrlicht/bzip2/bzip2.c new file mode 100644 index 0000000..6de9d1d --- /dev/null +++ b/libraries/irrlicht-1.8/source/Irrlicht/bzip2/bzip2.c | |||
@@ -0,0 +1,2034 @@ | |||
1 | |||
2 | /*-----------------------------------------------------------*/ | ||
3 | /*--- A block-sorting, lossless compressor bzip2.c ---*/ | ||
4 | /*-----------------------------------------------------------*/ | ||
5 | |||
6 | /* ------------------------------------------------------------------ | ||
7 | This file is part of bzip2/libbzip2, a program and library for | ||
8 | lossless, block-sorting data compression. | ||
9 | |||
10 | bzip2/libbzip2 version 1.0.6 of 6 September 2010 | ||
11 | Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org> | ||
12 | |||
13 | Please read the WARNING, DISCLAIMER and PATENTS sections in the | ||
14 | README file. | ||
15 | |||
16 | This program is released under the terms of the license contained | ||
17 | in the file LICENSE. | ||
18 | ------------------------------------------------------------------ */ | ||
19 | |||
20 | |||
21 | /* Place a 1 beside your platform, and 0 elsewhere. | ||
22 | Generic 32-bit Unix. | ||
23 | Also works on 64-bit Unix boxes. | ||
24 | This is the default. | ||
25 | */ | ||
26 | #define BZ_UNIX 1 | ||
27 | |||
28 | /*-- | ||
29 | Win32, as seen by Jacob Navia's excellent | ||
30 | port of (Chris Fraser & David Hanson)'s excellent | ||
31 | lcc compiler. Or with MS Visual C. | ||
32 | This is selected automatically if compiled by a compiler which | ||
33 | defines _WIN32, not including the Cygwin GCC. | ||
34 | --*/ | ||
35 | #define BZ_LCCWIN32 0 | ||
36 | |||
37 | #if defined(_WIN32) && !defined(__CYGWIN__) | ||
38 | #undef BZ_LCCWIN32 | ||
39 | #define BZ_LCCWIN32 1 | ||
40 | #undef BZ_UNIX | ||
41 | #define BZ_UNIX 0 | ||
42 | #endif | ||
43 | |||
44 | |||
45 | /*---------------------------------------------*/ | ||
46 | /*-- | ||
47 | Some stuff for all platforms. | ||
48 | --*/ | ||
49 | |||
50 | #include <stdio.h> | ||
51 | #include <stdlib.h> | ||
52 | #include <string.h> | ||
53 | #include <signal.h> | ||
54 | #include <math.h> | ||
55 | #include <errno.h> | ||
56 | #include <ctype.h> | ||
57 | #include "bzlib.h" | ||
58 | |||
59 | #define ERROR_IF_EOF(i) { if ((i) == EOF) ioError(); } | ||
60 | #define ERROR_IF_NOT_ZERO(i) { if ((i) != 0) ioError(); } | ||
61 | #define ERROR_IF_MINUS_ONE(i) { if ((i) == (-1)) ioError(); } | ||
62 | |||
63 | |||
64 | /*---------------------------------------------*/ | ||
65 | /*-- | ||
66 | Platform-specific stuff. | ||
67 | --*/ | ||
68 | |||
69 | #if BZ_UNIX | ||
70 | # include <fcntl.h> | ||
71 | # include <sys/types.h> | ||
72 | # include <utime.h> | ||
73 | # include <unistd.h> | ||
74 | # include <sys/stat.h> | ||
75 | # include <sys/times.h> | ||
76 | |||
77 | # define PATH_SEP '/' | ||
78 | # define MY_LSTAT lstat | ||
79 | # define MY_STAT stat | ||
80 | # define MY_S_ISREG S_ISREG | ||
81 | # define MY_S_ISDIR S_ISDIR | ||
82 | |||
83 | # define APPEND_FILESPEC(root, name) \ | ||
84 | root=snocString((root), (name)) | ||
85 | |||
86 | # define APPEND_FLAG(root, name) \ | ||
87 | root=snocString((root), (name)) | ||
88 | |||
89 | # define SET_BINARY_MODE(fd) /**/ | ||
90 | |||
91 | # ifdef __GNUC__ | ||
92 | # define NORETURN __attribute__ ((noreturn)) | ||
93 | # else | ||
94 | # define NORETURN /**/ | ||
95 | # endif | ||
96 | |||
97 | # ifdef __DJGPP__ | ||
98 | # include <io.h> | ||
99 | # include <fcntl.h> | ||
100 | # undef MY_LSTAT | ||
101 | # undef MY_STAT | ||
102 | # define MY_LSTAT stat | ||
103 | # define MY_STAT stat | ||
104 | # undef SET_BINARY_MODE | ||
105 | # define SET_BINARY_MODE(fd) \ | ||
106 | do { \ | ||
107 | int retVal = setmode ( fileno ( fd ), \ | ||
108 | O_BINARY ); \ | ||
109 | ERROR_IF_MINUS_ONE ( retVal ); \ | ||
110 | } while ( 0 ) | ||
111 | # endif | ||
112 | |||
113 | # ifdef __CYGWIN__ | ||
114 | # include <io.h> | ||
115 | # include <fcntl.h> | ||
116 | # undef SET_BINARY_MODE | ||
117 | # define SET_BINARY_MODE(fd) \ | ||
118 | do { \ | ||
119 | int retVal = setmode ( fileno ( fd ), \ | ||
120 | O_BINARY ); \ | ||
121 | ERROR_IF_MINUS_ONE ( retVal ); \ | ||
122 | } while ( 0 ) | ||
123 | # endif | ||
124 | #endif /* BZ_UNIX */ | ||
125 | |||
126 | |||
127 | |||
128 | #if BZ_LCCWIN32 | ||
129 | # include <io.h> | ||
130 | # include <fcntl.h> | ||
131 | # include <sys\stat.h> | ||
132 | |||
133 | # define NORETURN /**/ | ||
134 | # define PATH_SEP '\\' | ||
135 | # define MY_LSTAT _stat | ||
136 | # define MY_STAT _stat | ||
137 | # define MY_S_ISREG(x) ((x) & _S_IFREG) | ||
138 | # define MY_S_ISDIR(x) ((x) & _S_IFDIR) | ||
139 | |||
140 | # define APPEND_FLAG(root, name) \ | ||
141 | root=snocString((root), (name)) | ||
142 | |||
143 | # define APPEND_FILESPEC(root, name) \ | ||
144 | root = snocString ((root), (name)) | ||
145 | |||
146 | # define SET_BINARY_MODE(fd) \ | ||
147 | do { \ | ||
148 | int retVal = setmode ( fileno ( fd ), \ | ||
149 | O_BINARY ); \ | ||
150 | ERROR_IF_MINUS_ONE ( retVal ); \ | ||
151 | } while ( 0 ) | ||
152 | |||
153 | #endif /* BZ_LCCWIN32 */ | ||
154 | |||
155 | |||
156 | /*---------------------------------------------*/ | ||
157 | /*-- | ||
158 | Some more stuff for all platforms :-) | ||
159 | --*/ | ||
160 | |||
161 | typedef char Char; | ||
162 | typedef unsigned char Bool; | ||
163 | typedef unsigned char UChar; | ||
164 | typedef int Int32; | ||
165 | typedef unsigned int UInt32; | ||
166 | typedef short Int16; | ||
167 | typedef unsigned short UInt16; | ||
168 | |||
169 | #define True ((Bool)1) | ||
170 | #define False ((Bool)0) | ||
171 | |||
172 | /*-- | ||
173 | IntNative is your platform's `native' int size. | ||
174 | Only here to avoid probs with 64-bit platforms. | ||
175 | --*/ | ||
176 | typedef int IntNative; | ||
177 | |||
178 | |||
179 | /*---------------------------------------------------*/ | ||
180 | /*--- Misc (file handling) data decls ---*/ | ||
181 | /*---------------------------------------------------*/ | ||
182 | |||
183 | Int32 verbosity; | ||
184 | Bool keepInputFiles, smallMode, deleteOutputOnInterrupt; | ||
185 | Bool forceOverwrite, testFailsExist, unzFailsExist, noisy; | ||
186 | Int32 numFileNames, numFilesProcessed, blockSize100k; | ||
187 | Int32 exitValue; | ||
188 | |||
189 | /*-- source modes; F==file, I==stdin, O==stdout --*/ | ||
190 | #define SM_I2O 1 | ||
191 | #define SM_F2O 2 | ||
192 | #define SM_F2F 3 | ||
193 | |||
194 | /*-- operation modes --*/ | ||
195 | #define OM_Z 1 | ||
196 | #define OM_UNZ 2 | ||
197 | #define OM_TEST 3 | ||
198 | |||
199 | Int32 opMode; | ||
200 | Int32 srcMode; | ||
201 | |||
202 | #define FILE_NAME_LEN 1034 | ||
203 | |||
204 | Int32 longestFileName; | ||
205 | Char inName [FILE_NAME_LEN]; | ||
206 | Char outName[FILE_NAME_LEN]; | ||
207 | Char tmpName[FILE_NAME_LEN]; | ||
208 | Char *progName; | ||
209 | Char progNameReally[FILE_NAME_LEN]; | ||
210 | FILE *outputHandleJustInCase; | ||
211 | Int32 workFactor; | ||
212 | |||
213 | static void panic ( const Char* ) NORETURN; | ||
214 | static void ioError ( void ) NORETURN; | ||
215 | static void outOfMemory ( void ) NORETURN; | ||
216 | static void configError ( void ) NORETURN; | ||
217 | static void crcError ( void ) NORETURN; | ||
218 | static void cleanUpAndFail ( Int32 ) NORETURN; | ||
219 | static void compressedStreamEOF ( void ) NORETURN; | ||
220 | |||
221 | static void copyFileName ( Char*, Char* ); | ||
222 | static void* myMalloc ( Int32 ); | ||
223 | static void applySavedFileAttrToOutputFile ( IntNative fd ); | ||
224 | |||
225 | |||
226 | |||
227 | /*---------------------------------------------------*/ | ||
228 | /*--- An implementation of 64-bit ints. Sigh. ---*/ | ||
229 | /*--- Roll on widespread deployment of ANSI C9X ! ---*/ | ||
230 | /*---------------------------------------------------*/ | ||
231 | |||
232 | typedef | ||
233 | struct { UChar b[8]; } | ||
234 | UInt64; | ||
235 | |||
236 | |||
237 | static | ||
238 | void uInt64_from_UInt32s ( UInt64* n, UInt32 lo32, UInt32 hi32 ) | ||
239 | { | ||
240 | n->b[7] = (UChar)((hi32 >> 24) & 0xFF); | ||
241 | n->b[6] = (UChar)((hi32 >> 16) & 0xFF); | ||
242 | n->b[5] = (UChar)((hi32 >> 8) & 0xFF); | ||
243 | n->b[4] = (UChar) (hi32 & 0xFF); | ||
244 | n->b[3] = (UChar)((lo32 >> 24) & 0xFF); | ||
245 | n->b[2] = (UChar)((lo32 >> 16) & 0xFF); | ||
246 | n->b[1] = (UChar)((lo32 >> 8) & 0xFF); | ||
247 | n->b[0] = (UChar) (lo32 & 0xFF); | ||
248 | } | ||
249 | |||
250 | |||
251 | static | ||
252 | double uInt64_to_double ( UInt64* n ) | ||
253 | { | ||
254 | Int32 i; | ||
255 | double base = 1.0; | ||
256 | double sum = 0.0; | ||
257 | for (i = 0; i < 8; i++) { | ||
258 | sum += base * (double)(n->b[i]); | ||
259 | base *= 256.0; | ||
260 | } | ||
261 | return sum; | ||
262 | } | ||
263 | |||
264 | |||
265 | static | ||
266 | Bool uInt64_isZero ( UInt64* n ) | ||
267 | { | ||
268 | Int32 i; | ||
269 | for (i = 0; i < 8; i++) | ||
270 | if (n->b[i] != 0) return 0; | ||
271 | return 1; | ||
272 | } | ||
273 | |||
274 | |||
275 | /* Divide *n by 10, and return the remainder. */ | ||
276 | static | ||
277 | Int32 uInt64_qrm10 ( UInt64* n ) | ||
278 | { | ||
279 | UInt32 rem, tmp; | ||
280 | Int32 i; | ||
281 | rem = 0; | ||
282 | for (i = 7; i >= 0; i--) { | ||
283 | tmp = rem * 256 + n->b[i]; | ||
284 | n->b[i] = tmp / 10; | ||
285 | rem = tmp % 10; | ||
286 | } | ||
287 | return rem; | ||
288 | } | ||
289 | |||
290 | |||
291 | /* ... and the Whole Entire Point of all this UInt64 stuff is | ||
292 | so that we can supply the following function. | ||
293 | */ | ||
294 | static | ||
295 | void uInt64_toAscii ( char* outbuf, UInt64* n ) | ||
296 | { | ||
297 | Int32 i, q; | ||
298 | UChar buf[32]; | ||
299 | Int32 nBuf = 0; | ||
300 | UInt64 n_copy = *n; | ||
301 | do { | ||
302 | q = uInt64_qrm10 ( &n_copy ); | ||
303 | buf[nBuf] = q + '0'; | ||
304 | nBuf++; | ||
305 | } while (!uInt64_isZero(&n_copy)); | ||
306 | outbuf[nBuf] = 0; | ||
307 | for (i = 0; i < nBuf; i++) | ||
308 | outbuf[i] = buf[nBuf-i-1]; | ||
309 | } | ||
310 | |||
311 | |||
312 | /*---------------------------------------------------*/ | ||
313 | /*--- Processing of complete files and streams ---*/ | ||
314 | /*---------------------------------------------------*/ | ||
315 | |||
316 | /*---------------------------------------------*/ | ||
317 | static | ||
318 | Bool myfeof ( FILE* f ) | ||
319 | { | ||
320 | Int32 c = fgetc ( f ); | ||
321 | if (c == EOF) return True; | ||
322 | ungetc ( c, f ); | ||
323 | return False; | ||
324 | } | ||
325 | |||
326 | |||
327 | /*---------------------------------------------*/ | ||
328 | static | ||
329 | void compressStream ( FILE *stream, FILE *zStream ) | ||
330 | { | ||
331 | BZFILE* bzf = NULL; | ||
332 | UChar ibuf[5000]; | ||
333 | Int32 nIbuf; | ||
334 | UInt32 nbytes_in_lo32, nbytes_in_hi32; | ||
335 | UInt32 nbytes_out_lo32, nbytes_out_hi32; | ||
336 | Int32 bzerr, bzerr_dummy, ret; | ||
337 | |||
338 | SET_BINARY_MODE(stream); | ||
339 | SET_BINARY_MODE(zStream); | ||
340 | |||
341 | if (ferror(stream)) goto errhandler_io; | ||
342 | if (ferror(zStream)) goto errhandler_io; | ||
343 | |||
344 | bzf = BZ2_bzWriteOpen ( &bzerr, zStream, | ||
345 | blockSize100k, verbosity, workFactor ); | ||
346 | if (bzerr != BZ_OK) goto errhandler; | ||
347 | |||
348 | if (verbosity >= 2) fprintf ( stderr, "\n" ); | ||
349 | |||
350 | while (True) { | ||
351 | |||
352 | if (myfeof(stream)) break; | ||
353 | nIbuf = fread ( ibuf, sizeof(UChar), 5000, stream ); | ||
354 | if (ferror(stream)) goto errhandler_io; | ||
355 | if (nIbuf > 0) BZ2_bzWrite ( &bzerr, bzf, (void*)ibuf, nIbuf ); | ||
356 | if (bzerr != BZ_OK) goto errhandler; | ||
357 | |||
358 | } | ||
359 | |||
360 | BZ2_bzWriteClose64 ( &bzerr, bzf, 0, | ||
361 | &nbytes_in_lo32, &nbytes_in_hi32, | ||
362 | &nbytes_out_lo32, &nbytes_out_hi32 ); | ||
363 | if (bzerr != BZ_OK) goto errhandler; | ||
364 | |||
365 | if (ferror(zStream)) goto errhandler_io; | ||
366 | ret = fflush ( zStream ); | ||
367 | if (ret == EOF) goto errhandler_io; | ||
368 | if (zStream != stdout) { | ||
369 | Int32 fd = fileno ( zStream ); | ||
370 | if (fd < 0) goto errhandler_io; | ||
371 | applySavedFileAttrToOutputFile ( fd ); | ||
372 | ret = fclose ( zStream ); | ||
373 | outputHandleJustInCase = NULL; | ||
374 | if (ret == EOF) goto errhandler_io; | ||
375 | } | ||
376 | outputHandleJustInCase = NULL; | ||
377 | if (ferror(stream)) goto errhandler_io; | ||
378 | ret = fclose ( stream ); | ||
379 | if (ret == EOF) goto errhandler_io; | ||
380 | |||
381 | if (verbosity >= 1) { | ||
382 | if (nbytes_in_lo32 == 0 && nbytes_in_hi32 == 0) { | ||
383 | fprintf ( stderr, " no data compressed.\n"); | ||
384 | } else { | ||
385 | Char buf_nin[32], buf_nout[32]; | ||
386 | UInt64 nbytes_in, nbytes_out; | ||
387 | double nbytes_in_d, nbytes_out_d; | ||
388 | uInt64_from_UInt32s ( &nbytes_in, | ||
389 | nbytes_in_lo32, nbytes_in_hi32 ); | ||
390 | uInt64_from_UInt32s ( &nbytes_out, | ||
391 | nbytes_out_lo32, nbytes_out_hi32 ); | ||
392 | nbytes_in_d = uInt64_to_double ( &nbytes_in ); | ||
393 | nbytes_out_d = uInt64_to_double ( &nbytes_out ); | ||
394 | uInt64_toAscii ( buf_nin, &nbytes_in ); | ||
395 | uInt64_toAscii ( buf_nout, &nbytes_out ); | ||
396 | fprintf ( stderr, "%6.3f:1, %6.3f bits/byte, " | ||
397 | "%5.2f%% saved, %s in, %s out.\n", | ||
398 | nbytes_in_d / nbytes_out_d, | ||
399 | (8.0 * nbytes_out_d) / nbytes_in_d, | ||
400 | 100.0 * (1.0 - nbytes_out_d / nbytes_in_d), | ||
401 | buf_nin, | ||
402 | buf_nout | ||
403 | ); | ||
404 | } | ||
405 | } | ||
406 | |||
407 | return; | ||
408 | |||
409 | errhandler: | ||
410 | BZ2_bzWriteClose64 ( &bzerr_dummy, bzf, 1, | ||
411 | &nbytes_in_lo32, &nbytes_in_hi32, | ||
412 | &nbytes_out_lo32, &nbytes_out_hi32 ); | ||
413 | switch (bzerr) { | ||
414 | case BZ_CONFIG_ERROR: | ||
415 | configError(); break; | ||
416 | case BZ_MEM_ERROR: | ||
417 | outOfMemory (); break; | ||
418 | case BZ_IO_ERROR: | ||
419 | errhandler_io: | ||
420 | ioError(); break; | ||
421 | default: | ||
422 | panic ( "compress:unexpected error" ); | ||
423 | } | ||
424 | |||
425 | panic ( "compress:end" ); | ||
426 | /*notreached*/ | ||
427 | } | ||
428 | |||
429 | |||
430 | |||
431 | /*---------------------------------------------*/ | ||
432 | static | ||
433 | Bool uncompressStream ( FILE *zStream, FILE *stream ) | ||
434 | { | ||
435 | BZFILE* bzf = NULL; | ||
436 | Int32 bzerr, bzerr_dummy, ret, nread, streamNo, i; | ||
437 | UChar obuf[5000]; | ||
438 | UChar unused[BZ_MAX_UNUSED]; | ||
439 | Int32 nUnused; | ||
440 | void* unusedTmpV; | ||
441 | UChar* unusedTmp; | ||
442 | |||
443 | nUnused = 0; | ||
444 | streamNo = 0; | ||
445 | |||
446 | SET_BINARY_MODE(stream); | ||
447 | SET_BINARY_MODE(zStream); | ||
448 | |||
449 | if (ferror(stream)) goto errhandler_io; | ||
450 | if (ferror(zStream)) goto errhandler_io; | ||
451 | |||
452 | while (True) { | ||
453 | |||
454 | bzf = BZ2_bzReadOpen ( | ||
455 | &bzerr, zStream, verbosity, | ||
456 | (int)smallMode, unused, nUnused | ||
457 | ); | ||
458 | if (bzf == NULL || bzerr != BZ_OK) goto errhandler; | ||
459 | streamNo++; | ||
460 | |||
461 | while (bzerr == BZ_OK) { | ||
462 | nread = BZ2_bzRead ( &bzerr, bzf, obuf, 5000 ); | ||
463 | if (bzerr == BZ_DATA_ERROR_MAGIC) goto trycat; | ||
464 | if ((bzerr == BZ_OK || bzerr == BZ_STREAM_END) && nread > 0) | ||
465 | fwrite ( obuf, sizeof(UChar), nread, stream ); | ||
466 | if (ferror(stream)) goto errhandler_io; | ||
467 | } | ||
468 | if (bzerr != BZ_STREAM_END) goto errhandler; | ||
469 | |||
470 | BZ2_bzReadGetUnused ( &bzerr, bzf, &unusedTmpV, &nUnused ); | ||
471 | if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" ); | ||
472 | |||
473 | unusedTmp = (UChar*)unusedTmpV; | ||
474 | for (i = 0; i < nUnused; i++) unused[i] = unusedTmp[i]; | ||
475 | |||
476 | BZ2_bzReadClose ( &bzerr, bzf ); | ||
477 | if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" ); | ||
478 | |||
479 | if (nUnused == 0 && myfeof(zStream)) break; | ||
480 | } | ||
481 | |||
482 | closeok: | ||
483 | if (ferror(zStream)) goto errhandler_io; | ||
484 | if (stream != stdout) { | ||
485 | Int32 fd = fileno ( stream ); | ||
486 | if (fd < 0) goto errhandler_io; | ||
487 | applySavedFileAttrToOutputFile ( fd ); | ||
488 | } | ||
489 | ret = fclose ( zStream ); | ||
490 | if (ret == EOF) goto errhandler_io; | ||
491 | |||
492 | if (ferror(stream)) goto errhandler_io; | ||
493 | ret = fflush ( stream ); | ||
494 | if (ret != 0) goto errhandler_io; | ||
495 | if (stream != stdout) { | ||
496 | ret = fclose ( stream ); | ||
497 | outputHandleJustInCase = NULL; | ||
498 | if (ret == EOF) goto errhandler_io; | ||
499 | } | ||
500 | outputHandleJustInCase = NULL; | ||
501 | if (verbosity >= 2) fprintf ( stderr, "\n " ); | ||
502 | return True; | ||
503 | |||
504 | trycat: | ||
505 | if (forceOverwrite) { | ||
506 | rewind(zStream); | ||
507 | while (True) { | ||
508 | if (myfeof(zStream)) break; | ||
509 | nread = fread ( obuf, sizeof(UChar), 5000, zStream ); | ||
510 | if (ferror(zStream)) goto errhandler_io; | ||
511 | if (nread > 0) fwrite ( obuf, sizeof(UChar), nread, stream ); | ||
512 | if (ferror(stream)) goto errhandler_io; | ||
513 | } | ||
514 | goto closeok; | ||
515 | } | ||
516 | |||
517 | errhandler: | ||
518 | BZ2_bzReadClose ( &bzerr_dummy, bzf ); | ||
519 | switch (bzerr) { | ||
520 | case BZ_CONFIG_ERROR: | ||
521 | configError(); break; | ||
522 | case BZ_IO_ERROR: | ||
523 | errhandler_io: | ||
524 | ioError(); break; | ||
525 | case BZ_DATA_ERROR: | ||
526 | crcError(); | ||
527 | case BZ_MEM_ERROR: | ||
528 | outOfMemory(); | ||
529 | case BZ_UNEXPECTED_EOF: | ||
530 | compressedStreamEOF(); | ||
531 | case BZ_DATA_ERROR_MAGIC: | ||
532 | if (zStream != stdin) fclose(zStream); | ||
533 | if (stream != stdout) fclose(stream); | ||
534 | if (streamNo == 1) { | ||
535 | return False; | ||
536 | } else { | ||
537 | if (noisy) | ||
538 | fprintf ( stderr, | ||
539 | "\n%s: %s: trailing garbage after EOF ignored\n", | ||
540 | progName, inName ); | ||
541 | return True; | ||
542 | } | ||
543 | default: | ||
544 | panic ( "decompress:unexpected error" ); | ||
545 | } | ||
546 | |||
547 | panic ( "decompress:end" ); | ||
548 | return True; /*notreached*/ | ||
549 | } | ||
550 | |||
551 | |||
552 | /*---------------------------------------------*/ | ||
553 | static | ||
554 | Bool testStream ( FILE *zStream ) | ||
555 | { | ||
556 | BZFILE* bzf = NULL; | ||
557 | Int32 bzerr, bzerr_dummy, ret, nread, streamNo, i; | ||
558 | UChar obuf[5000]; | ||
559 | UChar unused[BZ_MAX_UNUSED]; | ||
560 | Int32 nUnused; | ||
561 | void* unusedTmpV; | ||
562 | UChar* unusedTmp; | ||
563 | |||
564 | nUnused = 0; | ||
565 | streamNo = 0; | ||
566 | |||
567 | SET_BINARY_MODE(zStream); | ||
568 | if (ferror(zStream)) goto errhandler_io; | ||
569 | |||
570 | while (True) { | ||
571 | |||
572 | bzf = BZ2_bzReadOpen ( | ||
573 | &bzerr, zStream, verbosity, | ||
574 | (int)smallMode, unused, nUnused | ||
575 | ); | ||
576 | if (bzf == NULL || bzerr != BZ_OK) goto errhandler; | ||
577 | streamNo++; | ||
578 | |||
579 | while (bzerr == BZ_OK) { | ||
580 | nread = BZ2_bzRead ( &bzerr, bzf, obuf, 5000 ); | ||
581 | if (bzerr == BZ_DATA_ERROR_MAGIC) goto errhandler; | ||
582 | } | ||
583 | if (bzerr != BZ_STREAM_END) goto errhandler; | ||
584 | |||
585 | BZ2_bzReadGetUnused ( &bzerr, bzf, &unusedTmpV, &nUnused ); | ||
586 | if (bzerr != BZ_OK) panic ( "test:bzReadGetUnused" ); | ||
587 | |||
588 | unusedTmp = (UChar*)unusedTmpV; | ||
589 | for (i = 0; i < nUnused; i++) unused[i] = unusedTmp[i]; | ||
590 | |||
591 | BZ2_bzReadClose ( &bzerr, bzf ); | ||
592 | if (bzerr != BZ_OK) panic ( "test:bzReadGetUnused" ); | ||
593 | if (nUnused == 0 && myfeof(zStream)) break; | ||
594 | |||
595 | } | ||
596 | |||
597 | if (ferror(zStream)) goto errhandler_io; | ||
598 | ret = fclose ( zStream ); | ||
599 | if (ret == EOF) goto errhandler_io; | ||
600 | |||
601 | if (verbosity >= 2) fprintf ( stderr, "\n " ); | ||
602 | return True; | ||
603 | |||
604 | errhandler: | ||
605 | BZ2_bzReadClose ( &bzerr_dummy, bzf ); | ||
606 | if (verbosity == 0) | ||
607 | fprintf ( stderr, "%s: %s: ", progName, inName ); | ||
608 | switch (bzerr) { | ||
609 | case BZ_CONFIG_ERROR: | ||
610 | configError(); break; | ||
611 | case BZ_IO_ERROR: | ||
612 | errhandler_io: | ||
613 | ioError(); break; | ||
614 | case BZ_DATA_ERROR: | ||
615 | fprintf ( stderr, | ||
616 | "data integrity (CRC) error in data\n" ); | ||
617 | return False; | ||
618 | case BZ_MEM_ERROR: | ||
619 | outOfMemory(); | ||
620 | case BZ_UNEXPECTED_EOF: | ||
621 | fprintf ( stderr, | ||
622 | "file ends unexpectedly\n" ); | ||
623 | return False; | ||
624 | case BZ_DATA_ERROR_MAGIC: | ||
625 | if (zStream != stdin) fclose(zStream); | ||
626 | if (streamNo == 1) { | ||
627 | fprintf ( stderr, | ||
628 | "bad magic number (file not created by bzip2)\n" ); | ||
629 | return False; | ||
630 | } else { | ||
631 | if (noisy) | ||
632 | fprintf ( stderr, | ||
633 | "trailing garbage after EOF ignored\n" ); | ||
634 | return True; | ||
635 | } | ||
636 | default: | ||
637 | panic ( "test:unexpected error" ); | ||
638 | } | ||
639 | |||
640 | panic ( "test:end" ); | ||
641 | return True; /*notreached*/ | ||
642 | } | ||
643 | |||
644 | |||
645 | /*---------------------------------------------------*/ | ||
646 | /*--- Error [non-] handling grunge ---*/ | ||
647 | /*---------------------------------------------------*/ | ||
648 | |||
649 | /*---------------------------------------------*/ | ||
650 | static | ||
651 | void setExit ( Int32 v ) | ||
652 | { | ||
653 | if (v > exitValue) exitValue = v; | ||
654 | } | ||
655 | |||
656 | |||
657 | /*---------------------------------------------*/ | ||
658 | static | ||
659 | void cadvise ( void ) | ||
660 | { | ||
661 | if (noisy) | ||
662 | fprintf ( | ||
663 | stderr, | ||
664 | "\nIt is possible that the compressed file(s) have become corrupted.\n" | ||
665 | "You can use the -tvv option to test integrity of such files.\n\n" | ||
666 | "You can use the `bzip2recover' program to attempt to recover\n" | ||
667 | "data from undamaged sections of corrupted files.\n\n" | ||
668 | ); | ||
669 | } | ||
670 | |||
671 | |||
672 | /*---------------------------------------------*/ | ||
673 | static | ||
674 | void showFileNames ( void ) | ||
675 | { | ||
676 | if (noisy) | ||
677 | fprintf ( | ||
678 | stderr, | ||
679 | "\tInput file = %s, output file = %s\n", | ||
680 | inName, outName | ||
681 | ); | ||
682 | } | ||
683 | |||
684 | |||
685 | /*---------------------------------------------*/ | ||
686 | static | ||
687 | void cleanUpAndFail ( Int32 ec ) | ||
688 | { | ||
689 | IntNative retVal; | ||
690 | struct MY_STAT statBuf; | ||
691 | |||
692 | if ( srcMode == SM_F2F | ||
693 | && opMode != OM_TEST | ||
694 | && deleteOutputOnInterrupt ) { | ||
695 | |||
696 | /* Check whether input file still exists. Delete output file | ||
697 | only if input exists to avoid loss of data. Joerg Prante, 5 | ||
698 | January 2002. (JRS 06-Jan-2002: other changes in 1.0.2 mean | ||
699 | this is less likely to happen. But to be ultra-paranoid, we | ||
700 | do the check anyway.) */ | ||
701 | retVal = MY_STAT ( inName, &statBuf ); | ||
702 | if (retVal == 0) { | ||
703 | if (noisy) | ||
704 | fprintf ( stderr, | ||
705 | "%s: Deleting output file %s, if it exists.\n", | ||
706 | progName, outName ); | ||
707 | if (outputHandleJustInCase != NULL) | ||
708 | fclose ( outputHandleJustInCase ); | ||
709 | retVal = remove ( outName ); | ||
710 | if (retVal != 0) | ||
711 | fprintf ( stderr, | ||
712 | "%s: WARNING: deletion of output file " | ||
713 | "(apparently) failed.\n", | ||
714 | progName ); | ||
715 | } else { | ||
716 | fprintf ( stderr, | ||
717 | "%s: WARNING: deletion of output file suppressed\n", | ||
718 | progName ); | ||
719 | fprintf ( stderr, | ||
720 | "%s: since input file no longer exists. Output file\n", | ||
721 | progName ); | ||
722 | fprintf ( stderr, | ||
723 | "%s: `%s' may be incomplete.\n", | ||
724 | progName, outName ); | ||
725 | fprintf ( stderr, | ||
726 | "%s: I suggest doing an integrity test (bzip2 -tv)" | ||
727 | " of it.\n", | ||
728 | progName ); | ||
729 | } | ||
730 | } | ||
731 | |||
732 | if (noisy && numFileNames > 0 && numFilesProcessed < numFileNames) { | ||
733 | fprintf ( stderr, | ||
734 | "%s: WARNING: some files have not been processed:\n" | ||
735 | "%s: %d specified on command line, %d not processed yet.\n\n", | ||
736 | progName, progName, | ||
737 | numFileNames, numFileNames - numFilesProcessed ); | ||
738 | } | ||
739 | setExit(ec); | ||
740 | exit(exitValue); | ||
741 | } | ||
742 | |||
743 | |||
744 | /*---------------------------------------------*/ | ||
745 | static | ||
746 | void panic ( const Char* s ) | ||
747 | { | ||
748 | fprintf ( stderr, | ||
749 | "\n%s: PANIC -- internal consistency error:\n" | ||
750 | "\t%s\n" | ||
751 | "\tThis is a BUG. Please report it to me at:\n" | ||
752 | "\tjseward@bzip.org\n", | ||
753 | progName, s ); | ||
754 | showFileNames(); | ||
755 | cleanUpAndFail( 3 ); | ||
756 | } | ||
757 | |||
758 | |||
759 | /*---------------------------------------------*/ | ||
760 | static | ||
761 | void crcError ( void ) | ||
762 | { | ||
763 | fprintf ( stderr, | ||
764 | "\n%s: Data integrity error when decompressing.\n", | ||
765 | progName ); | ||
766 | showFileNames(); | ||
767 | cadvise(); | ||
768 | cleanUpAndFail( 2 ); | ||
769 | } | ||
770 | |||
771 | |||
772 | /*---------------------------------------------*/ | ||
773 | static | ||
774 | void compressedStreamEOF ( void ) | ||
775 | { | ||
776 | if (noisy) { | ||
777 | fprintf ( stderr, | ||
778 | "\n%s: Compressed file ends unexpectedly;\n\t" | ||
779 | "perhaps it is corrupted? *Possible* reason follows.\n", | ||
780 | progName ); | ||
781 | perror ( progName ); | ||
782 | showFileNames(); | ||
783 | cadvise(); | ||
784 | } | ||
785 | cleanUpAndFail( 2 ); | ||
786 | } | ||
787 | |||
788 | |||
789 | /*---------------------------------------------*/ | ||
790 | static | ||
791 | void ioError ( void ) | ||
792 | { | ||
793 | fprintf ( stderr, | ||
794 | "\n%s: I/O or other error, bailing out. " | ||
795 | "Possible reason follows.\n", | ||
796 | progName ); | ||
797 | perror ( progName ); | ||
798 | showFileNames(); | ||
799 | cleanUpAndFail( 1 ); | ||
800 | } | ||
801 | |||
802 | |||
803 | /*---------------------------------------------*/ | ||
804 | static | ||
805 | void mySignalCatcher ( IntNative n ) | ||
806 | { | ||
807 | fprintf ( stderr, | ||
808 | "\n%s: Control-C or similar caught, quitting.\n", | ||
809 | progName ); | ||
810 | cleanUpAndFail(1); | ||
811 | } | ||
812 | |||
813 | |||
814 | /*---------------------------------------------*/ | ||
815 | static | ||
816 | void mySIGSEGVorSIGBUScatcher ( IntNative n ) | ||
817 | { | ||
818 | if (opMode == OM_Z) | ||
819 | fprintf ( | ||
820 | stderr, | ||
821 | "\n%s: Caught a SIGSEGV or SIGBUS whilst compressing.\n" | ||
822 | "\n" | ||
823 | " Possible causes are (most likely first):\n" | ||
824 | " (1) This computer has unreliable memory or cache hardware\n" | ||
825 | " (a surprisingly common problem; try a different machine.)\n" | ||
826 | " (2) A bug in the compiler used to create this executable\n" | ||
827 | " (unlikely, if you didn't compile bzip2 yourself.)\n" | ||
828 | " (3) A real bug in bzip2 -- I hope this should never be the case.\n" | ||
829 | " The user's manual, Section 4.3, has more info on (1) and (2).\n" | ||
830 | " \n" | ||
831 | " If you suspect this is a bug in bzip2, or are unsure about (1)\n" | ||
832 | " or (2), feel free to report it to me at: jseward@bzip.org.\n" | ||
833 | " Section 4.3 of the user's manual describes the info a useful\n" | ||
834 | " bug report should have. If the manual is available on your\n" | ||
835 | " system, please try and read it before mailing me. If you don't\n" | ||
836 | " have the manual or can't be bothered to read it, mail me anyway.\n" | ||
837 | "\n", | ||
838 | progName ); | ||
839 | else | ||
840 | fprintf ( | ||
841 | stderr, | ||
842 | "\n%s: Caught a SIGSEGV or SIGBUS whilst decompressing.\n" | ||
843 | "\n" | ||
844 | " Possible causes are (most likely first):\n" | ||
845 | " (1) The compressed data is corrupted, and bzip2's usual checks\n" | ||
846 | " failed to detect this. Try bzip2 -tvv my_file.bz2.\n" | ||
847 | " (2) This computer has unreliable memory or cache hardware\n" | ||
848 | " (a surprisingly common problem; try a different machine.)\n" | ||
849 | " (3) A bug in the compiler used to create this executable\n" | ||
850 | " (unlikely, if you didn't compile bzip2 yourself.)\n" | ||
851 | " (4) A real bug in bzip2 -- I hope this should never be the case.\n" | ||
852 | " The user's manual, Section 4.3, has more info on (2) and (3).\n" | ||
853 | " \n" | ||
854 | " If you suspect this is a bug in bzip2, or are unsure about (2)\n" | ||
855 | " or (3), feel free to report it to me at: jseward@bzip.org.\n" | ||
856 | " Section 4.3 of the user's manual describes the info a useful\n" | ||
857 | " bug report should have. If the manual is available on your\n" | ||
858 | " system, please try and read it before mailing me. If you don't\n" | ||
859 | " have the manual or can't be bothered to read it, mail me anyway.\n" | ||
860 | "\n", | ||
861 | progName ); | ||
862 | |||
863 | showFileNames(); | ||
864 | if (opMode == OM_Z) | ||
865 | cleanUpAndFail( 3 ); else | ||
866 | { cadvise(); cleanUpAndFail( 2 ); } | ||
867 | } | ||
868 | |||
869 | |||
870 | /*---------------------------------------------*/ | ||
871 | static | ||
872 | void outOfMemory ( void ) | ||
873 | { | ||
874 | fprintf ( stderr, | ||
875 | "\n%s: couldn't allocate enough memory\n", | ||
876 | progName ); | ||
877 | showFileNames(); | ||
878 | cleanUpAndFail(1); | ||
879 | } | ||
880 | |||
881 | |||
882 | /*---------------------------------------------*/ | ||
883 | static | ||
884 | void configError ( void ) | ||
885 | { | ||
886 | fprintf ( stderr, | ||
887 | "bzip2: I'm not configured correctly for this platform!\n" | ||
888 | "\tI require Int32, Int16 and Char to have sizes\n" | ||
889 | "\tof 4, 2 and 1 bytes to run properly, and they don't.\n" | ||
890 | "\tProbably you can fix this by defining them correctly,\n" | ||
891 | "\tand recompiling. Bye!\n" ); | ||
892 | setExit(3); | ||
893 | exit(exitValue); | ||
894 | } | ||
895 | |||
896 | |||
897 | /*---------------------------------------------------*/ | ||
898 | /*--- The main driver machinery ---*/ | ||
899 | /*---------------------------------------------------*/ | ||
900 | |||
901 | /* All rather crufty. The main problem is that input files | ||
902 | are stat()d multiple times before use. This should be | ||
903 | cleaned up. | ||
904 | */ | ||
905 | |||
906 | /*---------------------------------------------*/ | ||
907 | static | ||
908 | void pad ( Char *s ) | ||
909 | { | ||
910 | Int32 i; | ||
911 | if ( (Int32)strlen(s) >= longestFileName ) return; | ||
912 | for (i = 1; i <= longestFileName - (Int32)strlen(s); i++) | ||
913 | fprintf ( stderr, " " ); | ||
914 | } | ||
915 | |||
916 | |||
917 | /*---------------------------------------------*/ | ||
918 | static | ||
919 | void copyFileName ( Char* to, Char* from ) | ||
920 | { | ||
921 | if ( strlen(from) > FILE_NAME_LEN-10 ) { | ||
922 | fprintf ( | ||
923 | stderr, | ||
924 | "bzip2: file name\n`%s'\n" | ||
925 | "is suspiciously (more than %d chars) long.\n" | ||
926 | "Try using a reasonable file name instead. Sorry! :-)\n", | ||
927 | from, FILE_NAME_LEN-10 | ||
928 | ); | ||
929 | setExit(1); | ||
930 | exit(exitValue); | ||
931 | } | ||
932 | |||
933 | strncpy(to,from,FILE_NAME_LEN-10); | ||
934 | to[FILE_NAME_LEN-10]='\0'; | ||
935 | } | ||
936 | |||
937 | |||
938 | /*---------------------------------------------*/ | ||
939 | static | ||
940 | Bool fileExists ( Char* name ) | ||
941 | { | ||
942 | FILE *tmp = fopen ( name, "rb" ); | ||
943 | Bool exists = (tmp != NULL); | ||
944 | if (tmp != NULL) fclose ( tmp ); | ||
945 | return exists; | ||
946 | } | ||
947 | |||
948 | |||
949 | /*---------------------------------------------*/ | ||
950 | /* Open an output file safely with O_EXCL and good permissions. | ||
951 | This avoids a race condition in versions < 1.0.2, in which | ||
952 | the file was first opened and then had its interim permissions | ||
953 | set safely. We instead use open() to create the file with | ||
954 | the interim permissions required. (--- --- rw-). | ||
955 | |||
956 | For non-Unix platforms, if we are not worrying about | ||
957 | security issues, simple this simply behaves like fopen. | ||
958 | */ | ||
959 | static | ||
960 | FILE* fopen_output_safely ( Char* name, const char* mode ) | ||
961 | { | ||
962 | # if BZ_UNIX | ||
963 | FILE* fp; | ||
964 | IntNative fh; | ||
965 | fh = open(name, O_WRONLY|O_CREAT|O_EXCL, S_IWUSR|S_IRUSR); | ||
966 | if (fh == -1) return NULL; | ||
967 | fp = fdopen(fh, mode); | ||
968 | if (fp == NULL) close(fh); | ||
969 | return fp; | ||
970 | # else | ||
971 | return fopen(name, mode); | ||
972 | # endif | ||
973 | } | ||
974 | |||
975 | |||
976 | /*---------------------------------------------*/ | ||
977 | /*-- | ||
978 | if in doubt, return True | ||
979 | --*/ | ||
980 | static | ||
981 | Bool notAStandardFile ( Char* name ) | ||
982 | { | ||
983 | IntNative i; | ||
984 | struct MY_STAT statBuf; | ||
985 | |||
986 | i = MY_LSTAT ( name, &statBuf ); | ||
987 | if (i != 0) return True; | ||
988 | if (MY_S_ISREG(statBuf.st_mode)) return False; | ||
989 | return True; | ||
990 | } | ||
991 | |||
992 | |||
993 | /*---------------------------------------------*/ | ||
994 | /*-- | ||
995 | rac 11/21/98 see if file has hard links to it | ||
996 | --*/ | ||
997 | static | ||
998 | Int32 countHardLinks ( Char* name ) | ||
999 | { | ||
1000 | IntNative i; | ||
1001 | struct MY_STAT statBuf; | ||
1002 | |||
1003 | i = MY_LSTAT ( name, &statBuf ); | ||
1004 | if (i != 0) return 0; | ||
1005 | return (statBuf.st_nlink - 1); | ||
1006 | } | ||
1007 | |||
1008 | |||
1009 | /*---------------------------------------------*/ | ||
1010 | /* Copy modification date, access date, permissions and owner from the | ||
1011 | source to destination file. We have to copy this meta-info off | ||
1012 | into fileMetaInfo before starting to compress / decompress it, | ||
1013 | because doing it afterwards means we get the wrong access time. | ||
1014 | |||
1015 | To complicate matters, in compress() and decompress() below, the | ||
1016 | sequence of tests preceding the call to saveInputFileMetaInfo() | ||
1017 | involves calling fileExists(), which in turn establishes its result | ||
1018 | by attempting to fopen() the file, and if successful, immediately | ||
1019 | fclose()ing it again. So we have to assume that the fopen() call | ||
1020 | does not cause the access time field to be updated. | ||
1021 | |||
1022 | Reading of the man page for stat() (man 2 stat) on RedHat 7.2 seems | ||
1023 | to imply that merely doing open() will not affect the access time. | ||
1024 | Therefore we merely need to hope that the C library only does | ||
1025 | open() as a result of fopen(), and not any kind of read()-ahead | ||
1026 | cleverness. | ||
1027 | |||
1028 | It sounds pretty fragile to me. Whether this carries across | ||
1029 | robustly to arbitrary Unix-like platforms (or even works robustly | ||
1030 | on this one, RedHat 7.2) is unknown to me. Nevertheless ... | ||
1031 | */ | ||
1032 | #if BZ_UNIX | ||
1033 | static | ||
1034 | struct MY_STAT fileMetaInfo; | ||
1035 | #endif | ||
1036 | |||
1037 | static | ||
1038 | void saveInputFileMetaInfo ( Char *srcName ) | ||
1039 | { | ||
1040 | # if BZ_UNIX | ||
1041 | IntNative retVal; | ||
1042 | /* Note use of stat here, not lstat. */ | ||
1043 | retVal = MY_STAT( srcName, &fileMetaInfo ); | ||
1044 | ERROR_IF_NOT_ZERO ( retVal ); | ||
1045 | # endif | ||
1046 | } | ||
1047 | |||
1048 | |||
1049 | static | ||
1050 | void applySavedTimeInfoToOutputFile ( Char *dstName ) | ||
1051 | { | ||
1052 | # if BZ_UNIX | ||
1053 | IntNative retVal; | ||
1054 | struct utimbuf uTimBuf; | ||
1055 | |||
1056 | uTimBuf.actime = fileMetaInfo.st_atime; | ||
1057 | uTimBuf.modtime = fileMetaInfo.st_mtime; | ||
1058 | |||
1059 | retVal = utime ( dstName, &uTimBuf ); | ||
1060 | ERROR_IF_NOT_ZERO ( retVal ); | ||
1061 | # endif | ||
1062 | } | ||
1063 | |||
1064 | static | ||
1065 | void applySavedFileAttrToOutputFile ( IntNative fd ) | ||
1066 | { | ||
1067 | # if BZ_UNIX | ||
1068 | IntNative retVal; | ||
1069 | |||
1070 | retVal = fchmod ( fd, fileMetaInfo.st_mode ); | ||
1071 | ERROR_IF_NOT_ZERO ( retVal ); | ||
1072 | |||
1073 | (void) fchown ( fd, fileMetaInfo.st_uid, fileMetaInfo.st_gid ); | ||
1074 | /* chown() will in many cases return with EPERM, which can | ||
1075 | be safely ignored. | ||
1076 | */ | ||
1077 | # endif | ||
1078 | } | ||
1079 | |||
1080 | |||
1081 | /*---------------------------------------------*/ | ||
1082 | static | ||
1083 | Bool containsDubiousChars ( Char* name ) | ||
1084 | { | ||
1085 | # if BZ_UNIX | ||
1086 | /* On unix, files can contain any characters and the file expansion | ||
1087 | * is performed by the shell. | ||
1088 | */ | ||
1089 | return False; | ||
1090 | # else /* ! BZ_UNIX */ | ||
1091 | /* On non-unix (Win* platforms), wildcard characters are not allowed in | ||
1092 | * filenames. | ||
1093 | */ | ||
1094 | for (; *name != '\0'; name++) | ||
1095 | if (*name == '?' || *name == '*') return True; | ||
1096 | return False; | ||
1097 | # endif /* BZ_UNIX */ | ||
1098 | } | ||
1099 | |||
1100 | |||
1101 | /*---------------------------------------------*/ | ||
1102 | #define BZ_N_SUFFIX_PAIRS 4 | ||
1103 | |||
1104 | const Char* zSuffix[BZ_N_SUFFIX_PAIRS] | ||
1105 | = { ".bz2", ".bz", ".tbz2", ".tbz" }; | ||
1106 | const Char* unzSuffix[BZ_N_SUFFIX_PAIRS] | ||
1107 | = { "", "", ".tar", ".tar" }; | ||
1108 | |||
1109 | static | ||
1110 | Bool hasSuffix ( Char* s, const Char* suffix ) | ||
1111 | { | ||
1112 | Int32 ns = strlen(s); | ||
1113 | Int32 nx = strlen(suffix); | ||
1114 | if (ns < nx) return False; | ||
1115 | if (strcmp(s + ns - nx, suffix) == 0) return True; | ||
1116 | return False; | ||
1117 | } | ||
1118 | |||
1119 | static | ||
1120 | Bool mapSuffix ( Char* name, | ||
1121 | const Char* oldSuffix, | ||
1122 | const Char* newSuffix ) | ||
1123 | { | ||
1124 | if (!hasSuffix(name,oldSuffix)) return False; | ||
1125 | name[strlen(name)-strlen(oldSuffix)] = 0; | ||
1126 | strcat ( name, newSuffix ); | ||
1127 | return True; | ||
1128 | } | ||
1129 | |||
1130 | |||
1131 | /*---------------------------------------------*/ | ||
1132 | static | ||
1133 | void compress ( Char *name ) | ||
1134 | { | ||
1135 | FILE *inStr; | ||
1136 | FILE *outStr; | ||
1137 | Int32 n, i; | ||
1138 | struct MY_STAT statBuf; | ||
1139 | |||
1140 | deleteOutputOnInterrupt = False; | ||
1141 | |||
1142 | if (name == NULL && srcMode != SM_I2O) | ||
1143 | panic ( "compress: bad modes\n" ); | ||
1144 | |||
1145 | switch (srcMode) { | ||
1146 | case SM_I2O: | ||
1147 | copyFileName ( inName, (Char*)"(stdin)" ); | ||
1148 | copyFileName ( outName, (Char*)"(stdout)" ); | ||
1149 | break; | ||
1150 | case SM_F2F: | ||
1151 | copyFileName ( inName, name ); | ||
1152 | copyFileName ( outName, name ); | ||
1153 | strcat ( outName, ".bz2" ); | ||
1154 | break; | ||
1155 | case SM_F2O: | ||
1156 | copyFileName ( inName, name ); | ||
1157 | copyFileName ( outName, (Char*)"(stdout)" ); | ||
1158 | break; | ||
1159 | } | ||
1160 | |||
1161 | if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) { | ||
1162 | if (noisy) | ||
1163 | fprintf ( stderr, "%s: There are no files matching `%s'.\n", | ||
1164 | progName, inName ); | ||
1165 | setExit(1); | ||
1166 | return; | ||
1167 | } | ||
1168 | if ( srcMode != SM_I2O && !fileExists ( inName ) ) { | ||
1169 | fprintf ( stderr, "%s: Can't open input file %s: %s.\n", | ||
1170 | progName, inName, strerror(errno) ); | ||
1171 | setExit(1); | ||
1172 | return; | ||
1173 | } | ||
1174 | for (i = 0; i < BZ_N_SUFFIX_PAIRS; i++) { | ||
1175 | if (hasSuffix(inName, zSuffix[i])) { | ||
1176 | if (noisy) | ||
1177 | fprintf ( stderr, | ||
1178 | "%s: Input file %s already has %s suffix.\n", | ||
1179 | progName, inName, zSuffix[i] ); | ||
1180 | setExit(1); | ||
1181 | return; | ||
1182 | } | ||
1183 | } | ||
1184 | if ( srcMode == SM_F2F || srcMode == SM_F2O ) { | ||
1185 | MY_STAT(inName, &statBuf); | ||
1186 | if ( MY_S_ISDIR(statBuf.st_mode) ) { | ||
1187 | fprintf( stderr, | ||
1188 | "%s: Input file %s is a directory.\n", | ||
1189 | progName,inName); | ||
1190 | setExit(1); | ||
1191 | return; | ||
1192 | } | ||
1193 | } | ||
1194 | if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) { | ||
1195 | if (noisy) | ||
1196 | fprintf ( stderr, "%s: Input file %s is not a normal file.\n", | ||
1197 | progName, inName ); | ||
1198 | setExit(1); | ||
1199 | return; | ||
1200 | } | ||
1201 | if ( srcMode == SM_F2F && fileExists ( outName ) ) { | ||
1202 | if (forceOverwrite) { | ||
1203 | remove(outName); | ||
1204 | } else { | ||
1205 | fprintf ( stderr, "%s: Output file %s already exists.\n", | ||
1206 | progName, outName ); | ||
1207 | setExit(1); | ||
1208 | return; | ||
1209 | } | ||
1210 | } | ||
1211 | if ( srcMode == SM_F2F && !forceOverwrite && | ||
1212 | (n=countHardLinks ( inName )) > 0) { | ||
1213 | fprintf ( stderr, "%s: Input file %s has %d other link%s.\n", | ||
1214 | progName, inName, n, n > 1 ? "s" : "" ); | ||
1215 | setExit(1); | ||
1216 | return; | ||
1217 | } | ||
1218 | |||
1219 | if ( srcMode == SM_F2F ) { | ||
1220 | /* Save the file's meta-info before we open it. Doing it later | ||
1221 | means we mess up the access times. */ | ||
1222 | saveInputFileMetaInfo ( inName ); | ||
1223 | } | ||
1224 | |||
1225 | switch ( srcMode ) { | ||
1226 | |||
1227 | case SM_I2O: | ||
1228 | inStr = stdin; | ||
1229 | outStr = stdout; | ||
1230 | if ( isatty ( fileno ( stdout ) ) ) { | ||
1231 | fprintf ( stderr, | ||
1232 | "%s: I won't write compressed data to a terminal.\n", | ||
1233 | progName ); | ||
1234 | fprintf ( stderr, "%s: For help, type: `%s --help'.\n", | ||
1235 | progName, progName ); | ||
1236 | setExit(1); | ||
1237 | return; | ||
1238 | }; | ||
1239 | break; | ||
1240 | |||
1241 | case SM_F2O: | ||
1242 | inStr = fopen ( inName, "rb" ); | ||
1243 | outStr = stdout; | ||
1244 | if ( isatty ( fileno ( stdout ) ) ) { | ||
1245 | fprintf ( stderr, | ||
1246 | "%s: I won't write compressed data to a terminal.\n", | ||
1247 | progName ); | ||
1248 | fprintf ( stderr, "%s: For help, type: `%s --help'.\n", | ||
1249 | progName, progName ); | ||
1250 | if ( inStr != NULL ) fclose ( inStr ); | ||
1251 | setExit(1); | ||
1252 | return; | ||
1253 | }; | ||
1254 | if ( inStr == NULL ) { | ||
1255 | fprintf ( stderr, "%s: Can't open input file %s: %s.\n", | ||
1256 | progName, inName, strerror(errno) ); | ||
1257 | setExit(1); | ||
1258 | return; | ||
1259 | }; | ||
1260 | break; | ||
1261 | |||
1262 | case SM_F2F: | ||
1263 | inStr = fopen ( inName, "rb" ); | ||
1264 | outStr = fopen_output_safely ( outName, "wb" ); | ||
1265 | if ( outStr == NULL) { | ||
1266 | fprintf ( stderr, "%s: Can't create output file %s: %s.\n", | ||
1267 | progName, outName, strerror(errno) ); | ||
1268 | if ( inStr != NULL ) fclose ( inStr ); | ||
1269 | setExit(1); | ||
1270 | return; | ||
1271 | } | ||
1272 | if ( inStr == NULL ) { | ||
1273 | fprintf ( stderr, "%s: Can't open input file %s: %s.\n", | ||
1274 | progName, inName, strerror(errno) ); | ||
1275 | if ( outStr != NULL ) fclose ( outStr ); | ||
1276 | setExit(1); | ||
1277 | return; | ||
1278 | }; | ||
1279 | break; | ||
1280 | |||
1281 | default: | ||
1282 | panic ( "compress: bad srcMode" ); | ||
1283 | break; | ||
1284 | } | ||
1285 | |||
1286 | if (verbosity >= 1) { | ||
1287 | fprintf ( stderr, " %s: ", inName ); | ||
1288 | pad ( inName ); | ||
1289 | fflush ( stderr ); | ||
1290 | } | ||
1291 | |||
1292 | /*--- Now the input and output handles are sane. Do the Biz. ---*/ | ||
1293 | outputHandleJustInCase = outStr; | ||
1294 | deleteOutputOnInterrupt = True; | ||
1295 | compressStream ( inStr, outStr ); | ||
1296 | outputHandleJustInCase = NULL; | ||
1297 | |||
1298 | /*--- If there was an I/O error, we won't get here. ---*/ | ||
1299 | if ( srcMode == SM_F2F ) { | ||
1300 | applySavedTimeInfoToOutputFile ( outName ); | ||
1301 | deleteOutputOnInterrupt = False; | ||
1302 | if ( !keepInputFiles ) { | ||
1303 | IntNative retVal = remove ( inName ); | ||
1304 | ERROR_IF_NOT_ZERO ( retVal ); | ||
1305 | } | ||
1306 | } | ||
1307 | |||
1308 | deleteOutputOnInterrupt = False; | ||
1309 | } | ||
1310 | |||
1311 | |||
1312 | /*---------------------------------------------*/ | ||
1313 | static | ||
1314 | void uncompress ( Char *name ) | ||
1315 | { | ||
1316 | FILE *inStr; | ||
1317 | FILE *outStr; | ||
1318 | Int32 n, i; | ||
1319 | Bool magicNumberOK; | ||
1320 | Bool cantGuess; | ||
1321 | struct MY_STAT statBuf; | ||
1322 | |||
1323 | deleteOutputOnInterrupt = False; | ||
1324 | |||
1325 | if (name == NULL && srcMode != SM_I2O) | ||
1326 | panic ( "uncompress: bad modes\n" ); | ||
1327 | |||
1328 | cantGuess = False; | ||
1329 | switch (srcMode) { | ||
1330 | case SM_I2O: | ||
1331 | copyFileName ( inName, (Char*)"(stdin)" ); | ||
1332 | copyFileName ( outName, (Char*)"(stdout)" ); | ||
1333 | break; | ||
1334 | case SM_F2F: | ||
1335 | copyFileName ( inName, name ); | ||
1336 | copyFileName ( outName, name ); | ||
1337 | for (i = 0; i < BZ_N_SUFFIX_PAIRS; i++) | ||
1338 | if (mapSuffix(outName,zSuffix[i],unzSuffix[i])) | ||
1339 | goto zzz; | ||
1340 | cantGuess = True; | ||
1341 | strcat ( outName, ".out" ); | ||
1342 | break; | ||
1343 | case SM_F2O: | ||
1344 | copyFileName ( inName, name ); | ||
1345 | copyFileName ( outName, (Char*)"(stdout)" ); | ||
1346 | break; | ||
1347 | } | ||
1348 | |||
1349 | zzz: | ||
1350 | if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) { | ||
1351 | if (noisy) | ||
1352 | fprintf ( stderr, "%s: There are no files matching `%s'.\n", | ||
1353 | progName, inName ); | ||
1354 | setExit(1); | ||
1355 | return; | ||
1356 | } | ||
1357 | if ( srcMode != SM_I2O && !fileExists ( inName ) ) { | ||
1358 | fprintf ( stderr, "%s: Can't open input file %s: %s.\n", | ||
1359 | progName, inName, strerror(errno) ); | ||
1360 | setExit(1); | ||
1361 | return; | ||
1362 | } | ||
1363 | if ( srcMode == SM_F2F || srcMode == SM_F2O ) { | ||
1364 | MY_STAT(inName, &statBuf); | ||
1365 | if ( MY_S_ISDIR(statBuf.st_mode) ) { | ||
1366 | fprintf( stderr, | ||
1367 | "%s: Input file %s is a directory.\n", | ||
1368 | progName,inName); | ||
1369 | setExit(1); | ||
1370 | return; | ||
1371 | } | ||
1372 | } | ||
1373 | if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) { | ||
1374 | if (noisy) | ||
1375 | fprintf ( stderr, "%s: Input file %s is not a normal file.\n", | ||
1376 | progName, inName ); | ||
1377 | setExit(1); | ||
1378 | return; | ||
1379 | } | ||
1380 | if ( /* srcMode == SM_F2F implied && */ cantGuess ) { | ||
1381 | if (noisy) | ||
1382 | fprintf ( stderr, | ||
1383 | "%s: Can't guess original name for %s -- using %s\n", | ||
1384 | progName, inName, outName ); | ||
1385 | /* just a warning, no return */ | ||
1386 | } | ||
1387 | if ( srcMode == SM_F2F && fileExists ( outName ) ) { | ||
1388 | if (forceOverwrite) { | ||
1389 | remove(outName); | ||
1390 | } else { | ||
1391 | fprintf ( stderr, "%s: Output file %s already exists.\n", | ||
1392 | progName, outName ); | ||
1393 | setExit(1); | ||
1394 | return; | ||
1395 | } | ||
1396 | } | ||
1397 | if ( srcMode == SM_F2F && !forceOverwrite && | ||
1398 | (n=countHardLinks ( inName ) ) > 0) { | ||
1399 | fprintf ( stderr, "%s: Input file %s has %d other link%s.\n", | ||
1400 | progName, inName, n, n > 1 ? "s" : "" ); | ||
1401 | setExit(1); | ||
1402 | return; | ||
1403 | } | ||
1404 | |||
1405 | if ( srcMode == SM_F2F ) { | ||
1406 | /* Save the file's meta-info before we open it. Doing it later | ||
1407 | means we mess up the access times. */ | ||
1408 | saveInputFileMetaInfo ( inName ); | ||
1409 | } | ||
1410 | |||
1411 | switch ( srcMode ) { | ||
1412 | |||
1413 | case SM_I2O: | ||
1414 | inStr = stdin; | ||
1415 | outStr = stdout; | ||
1416 | if ( isatty ( fileno ( stdin ) ) ) { | ||
1417 | fprintf ( stderr, | ||
1418 | "%s: I won't read compressed data from a terminal.\n", | ||
1419 | progName ); | ||
1420 | fprintf ( stderr, "%s: For help, type: `%s --help'.\n", | ||
1421 | progName, progName ); | ||
1422 | setExit(1); | ||
1423 | return; | ||
1424 | }; | ||
1425 | break; | ||
1426 | |||
1427 | case SM_F2O: | ||
1428 | inStr = fopen ( inName, "rb" ); | ||
1429 | outStr = stdout; | ||
1430 | if ( inStr == NULL ) { | ||
1431 | fprintf ( stderr, "%s: Can't open input file %s:%s.\n", | ||
1432 | progName, inName, strerror(errno) ); | ||
1433 | if ( inStr != NULL ) fclose ( inStr ); | ||
1434 | setExit(1); | ||
1435 | return; | ||
1436 | }; | ||
1437 | break; | ||
1438 | |||
1439 | case SM_F2F: | ||
1440 | inStr = fopen ( inName, "rb" ); | ||
1441 | outStr = fopen_output_safely ( outName, "wb" ); | ||
1442 | if ( outStr == NULL) { | ||
1443 | fprintf ( stderr, "%s: Can't create output file %s: %s.\n", | ||
1444 | progName, outName, strerror(errno) ); | ||
1445 | if ( inStr != NULL ) fclose ( inStr ); | ||
1446 | setExit(1); | ||
1447 | return; | ||
1448 | } | ||
1449 | if ( inStr == NULL ) { | ||
1450 | fprintf ( stderr, "%s: Can't open input file %s: %s.\n", | ||
1451 | progName, inName, strerror(errno) ); | ||
1452 | if ( outStr != NULL ) fclose ( outStr ); | ||
1453 | setExit(1); | ||
1454 | return; | ||
1455 | }; | ||
1456 | break; | ||
1457 | |||
1458 | default: | ||
1459 | panic ( "uncompress: bad srcMode" ); | ||
1460 | break; | ||
1461 | } | ||
1462 | |||
1463 | if (verbosity >= 1) { | ||
1464 | fprintf ( stderr, " %s: ", inName ); | ||
1465 | pad ( inName ); | ||
1466 | fflush ( stderr ); | ||
1467 | } | ||
1468 | |||
1469 | /*--- Now the input and output handles are sane. Do the Biz. ---*/ | ||
1470 | outputHandleJustInCase = outStr; | ||
1471 | deleteOutputOnInterrupt = True; | ||
1472 | magicNumberOK = uncompressStream ( inStr, outStr ); | ||
1473 | outputHandleJustInCase = NULL; | ||
1474 | |||
1475 | /*--- If there was an I/O error, we won't get here. ---*/ | ||
1476 | if ( magicNumberOK ) { | ||
1477 | if ( srcMode == SM_F2F ) { | ||
1478 | applySavedTimeInfoToOutputFile ( outName ); | ||
1479 | deleteOutputOnInterrupt = False; | ||
1480 | if ( !keepInputFiles ) { | ||
1481 | IntNative retVal = remove ( inName ); | ||
1482 | ERROR_IF_NOT_ZERO ( retVal ); | ||
1483 | } | ||
1484 | } | ||
1485 | } else { | ||
1486 | unzFailsExist = True; | ||
1487 | deleteOutputOnInterrupt = False; | ||
1488 | if ( srcMode == SM_F2F ) { | ||
1489 | IntNative retVal = remove ( outName ); | ||
1490 | ERROR_IF_NOT_ZERO ( retVal ); | ||
1491 | } | ||
1492 | } | ||
1493 | deleteOutputOnInterrupt = False; | ||
1494 | |||
1495 | if ( magicNumberOK ) { | ||
1496 | if (verbosity >= 1) | ||
1497 | fprintf ( stderr, "done\n" ); | ||
1498 | } else { | ||
1499 | setExit(2); | ||
1500 | if (verbosity >= 1) | ||
1501 | fprintf ( stderr, "not a bzip2 file.\n" ); else | ||
1502 | fprintf ( stderr, | ||
1503 | "%s: %s is not a bzip2 file.\n", | ||
1504 | progName, inName ); | ||
1505 | } | ||
1506 | |||
1507 | } | ||
1508 | |||
1509 | |||
1510 | /*---------------------------------------------*/ | ||
1511 | static | ||
1512 | void testf ( Char *name ) | ||
1513 | { | ||
1514 | FILE *inStr; | ||
1515 | Bool allOK; | ||
1516 | struct MY_STAT statBuf; | ||
1517 | |||
1518 | deleteOutputOnInterrupt = False; | ||
1519 | |||
1520 | if (name == NULL && srcMode != SM_I2O) | ||
1521 | panic ( "testf: bad modes\n" ); | ||
1522 | |||
1523 | copyFileName ( outName, (Char*)"(none)" ); | ||
1524 | switch (srcMode) { | ||
1525 | case SM_I2O: copyFileName ( inName, (Char*)"(stdin)" ); break; | ||
1526 | case SM_F2F: copyFileName ( inName, name ); break; | ||
1527 | case SM_F2O: copyFileName ( inName, name ); break; | ||
1528 | } | ||
1529 | |||
1530 | if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) { | ||
1531 | if (noisy) | ||
1532 | fprintf ( stderr, "%s: There are no files matching `%s'.\n", | ||
1533 | progName, inName ); | ||
1534 | setExit(1); | ||
1535 | return; | ||
1536 | } | ||
1537 | if ( srcMode != SM_I2O && !fileExists ( inName ) ) { | ||
1538 | fprintf ( stderr, "%s: Can't open input %s: %s.\n", | ||
1539 | progName, inName, strerror(errno) ); | ||
1540 | setExit(1); | ||
1541 | return; | ||
1542 | } | ||
1543 | if ( srcMode != SM_I2O ) { | ||
1544 | MY_STAT(inName, &statBuf); | ||
1545 | if ( MY_S_ISDIR(statBuf.st_mode) ) { | ||
1546 | fprintf( stderr, | ||
1547 | "%s: Input file %s is a directory.\n", | ||
1548 | progName,inName); | ||
1549 | setExit(1); | ||
1550 | return; | ||
1551 | } | ||
1552 | } | ||
1553 | |||
1554 | switch ( srcMode ) { | ||
1555 | |||
1556 | case SM_I2O: | ||
1557 | if ( isatty ( fileno ( stdin ) ) ) { | ||
1558 | fprintf ( stderr, | ||
1559 | "%s: I won't read compressed data from a terminal.\n", | ||
1560 | progName ); | ||
1561 | fprintf ( stderr, "%s: For help, type: `%s --help'.\n", | ||
1562 | progName, progName ); | ||
1563 | setExit(1); | ||
1564 | return; | ||
1565 | }; | ||
1566 | inStr = stdin; | ||
1567 | break; | ||
1568 | |||
1569 | case SM_F2O: case SM_F2F: | ||
1570 | inStr = fopen ( inName, "rb" ); | ||
1571 | if ( inStr == NULL ) { | ||
1572 | fprintf ( stderr, "%s: Can't open input file %s:%s.\n", | ||
1573 | progName, inName, strerror(errno) ); | ||
1574 | setExit(1); | ||
1575 | return; | ||
1576 | }; | ||
1577 | break; | ||
1578 | |||
1579 | default: | ||
1580 | panic ( "testf: bad srcMode" ); | ||
1581 | break; | ||
1582 | } | ||
1583 | |||
1584 | if (verbosity >= 1) { | ||
1585 | fprintf ( stderr, " %s: ", inName ); | ||
1586 | pad ( inName ); | ||
1587 | fflush ( stderr ); | ||
1588 | } | ||
1589 | |||
1590 | /*--- Now the input handle is sane. Do the Biz. ---*/ | ||
1591 | outputHandleJustInCase = NULL; | ||
1592 | allOK = testStream ( inStr ); | ||
1593 | |||
1594 | if (allOK && verbosity >= 1) fprintf ( stderr, "ok\n" ); | ||
1595 | if (!allOK) testFailsExist = True; | ||
1596 | } | ||
1597 | |||
1598 | |||
1599 | /*---------------------------------------------*/ | ||
1600 | static | ||
1601 | void license ( void ) | ||
1602 | { | ||
1603 | fprintf ( stderr, | ||
1604 | |||
1605 | "bzip2, a block-sorting file compressor. " | ||
1606 | "Version %s.\n" | ||
1607 | " \n" | ||
1608 | " Copyright (C) 1996-2010 by Julian Seward.\n" | ||
1609 | " \n" | ||
1610 | " This program is free software; you can redistribute it and/or modify\n" | ||
1611 | " it under the terms set out in the LICENSE file, which is included\n" | ||
1612 | " in the bzip2-1.0.6 source distribution.\n" | ||
1613 | " \n" | ||
1614 | " This program is distributed in the hope that it will be useful,\n" | ||
1615 | " but WITHOUT ANY WARRANTY; without even the implied warranty of\n" | ||
1616 | " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" | ||
1617 | " LICENSE file for more details.\n" | ||
1618 | " \n", | ||
1619 | BZ2_bzlibVersion() | ||
1620 | ); | ||
1621 | } | ||
1622 | |||
1623 | |||
1624 | /*---------------------------------------------*/ | ||
1625 | static | ||
1626 | void usage ( Char *fullProgName ) | ||
1627 | { | ||
1628 | fprintf ( | ||
1629 | stderr, | ||
1630 | "bzip2, a block-sorting file compressor. " | ||
1631 | "Version %s.\n" | ||
1632 | "\n usage: %s [flags and input files in any order]\n" | ||
1633 | "\n" | ||
1634 | " -h --help print this message\n" | ||
1635 | " -d --decompress force decompression\n" | ||
1636 | " -z --compress force compression\n" | ||
1637 | " -k --keep keep (don't delete) input files\n" | ||
1638 | " -f --force overwrite existing output files\n" | ||
1639 | " -t --test test compressed file integrity\n" | ||
1640 | " -c --stdout output to standard out\n" | ||
1641 | " -q --quiet suppress noncritical error messages\n" | ||
1642 | " -v --verbose be verbose (a 2nd -v gives more)\n" | ||
1643 | " -L --license display software version & license\n" | ||
1644 | " -V --version display software version & license\n" | ||
1645 | " -s --small use less memory (at most 2500k)\n" | ||
1646 | " -1 .. -9 set block size to 100k .. 900k\n" | ||
1647 | " --fast alias for -1\n" | ||
1648 | " --best alias for -9\n" | ||
1649 | "\n" | ||
1650 | " If invoked as `bzip2', default action is to compress.\n" | ||
1651 | " as `bunzip2', default action is to decompress.\n" | ||
1652 | " as `bzcat', default action is to decompress to stdout.\n" | ||
1653 | "\n" | ||
1654 | " If no file names are given, bzip2 compresses or decompresses\n" | ||
1655 | " from standard input to standard output. You can combine\n" | ||
1656 | " short flags, so `-v -4' means the same as -v4 or -4v, &c.\n" | ||
1657 | # if BZ_UNIX | ||
1658 | "\n" | ||
1659 | # endif | ||
1660 | , | ||
1661 | |||
1662 | BZ2_bzlibVersion(), | ||
1663 | fullProgName | ||
1664 | ); | ||
1665 | } | ||
1666 | |||
1667 | |||
1668 | /*---------------------------------------------*/ | ||
1669 | static | ||
1670 | void redundant ( Char* flag ) | ||
1671 | { | ||
1672 | fprintf ( | ||
1673 | stderr, | ||
1674 | "%s: %s is redundant in versions 0.9.5 and above\n", | ||
1675 | progName, flag ); | ||
1676 | } | ||
1677 | |||
1678 | |||
1679 | /*---------------------------------------------*/ | ||
1680 | /*-- | ||
1681 | All the garbage from here to main() is purely to | ||
1682 | implement a linked list of command-line arguments, | ||
1683 | into which main() copies argv[1 .. argc-1]. | ||
1684 | |||
1685 | The purpose of this exercise is to facilitate | ||
1686 | the expansion of wildcard characters * and ? in | ||
1687 | filenames for OSs which don't know how to do it | ||
1688 | themselves, like MSDOS, Windows 95 and NT. | ||
1689 | |||
1690 | The actual Dirty Work is done by the platform- | ||
1691 | specific macro APPEND_FILESPEC. | ||
1692 | --*/ | ||
1693 | |||
1694 | typedef | ||
1695 | struct zzzz { | ||
1696 | Char *name; | ||
1697 | struct zzzz *link; | ||
1698 | } | ||
1699 | Cell; | ||
1700 | |||
1701 | |||
1702 | /*---------------------------------------------*/ | ||
1703 | static | ||
1704 | void *myMalloc ( Int32 n ) | ||
1705 | { | ||
1706 | void* p; | ||
1707 | |||
1708 | p = malloc ( (size_t)n ); | ||
1709 | if (p == NULL) outOfMemory (); | ||
1710 | return p; | ||
1711 | } | ||
1712 | |||
1713 | |||
1714 | /*---------------------------------------------*/ | ||
1715 | static | ||
1716 | Cell *mkCell ( void ) | ||
1717 | { | ||
1718 | Cell *c; | ||
1719 | |||
1720 | c = (Cell*) myMalloc ( sizeof ( Cell ) ); | ||
1721 | c->name = NULL; | ||
1722 | c->link = NULL; | ||
1723 | return c; | ||
1724 | } | ||
1725 | |||
1726 | |||
1727 | /*---------------------------------------------*/ | ||
1728 | static | ||
1729 | Cell *snocString ( Cell *root, Char *name ) | ||
1730 | { | ||
1731 | if (root == NULL) { | ||
1732 | Cell *tmp = mkCell(); | ||
1733 | tmp->name = (Char*) myMalloc ( 5 + strlen(name) ); | ||
1734 | strcpy ( tmp->name, name ); | ||
1735 | return tmp; | ||
1736 | } else { | ||
1737 | Cell *tmp = root; | ||
1738 | while (tmp->link != NULL) tmp = tmp->link; | ||
1739 | tmp->link = snocString ( tmp->link, name ); | ||
1740 | return root; | ||
1741 | } | ||
1742 | } | ||
1743 | |||
1744 | |||
1745 | /*---------------------------------------------*/ | ||
1746 | static | ||
1747 | void addFlagsFromEnvVar ( Cell** argList, Char* varName ) | ||
1748 | { | ||
1749 | Int32 i, j, k; | ||
1750 | Char *envbase, *p; | ||
1751 | |||
1752 | envbase = getenv(varName); | ||
1753 | if (envbase != NULL) { | ||
1754 | p = envbase; | ||
1755 | i = 0; | ||
1756 | while (True) { | ||
1757 | if (p[i] == 0) break; | ||
1758 | p += i; | ||
1759 | i = 0; | ||
1760 | while (isspace((Int32)(p[0]))) p++; | ||
1761 | while (p[i] != 0 && !isspace((Int32)(p[i]))) i++; | ||
1762 | if (i > 0) { | ||
1763 | k = i; if (k > FILE_NAME_LEN-10) k = FILE_NAME_LEN-10; | ||
1764 | for (j = 0; j < k; j++) tmpName[j] = p[j]; | ||
1765 | tmpName[k] = 0; | ||
1766 | APPEND_FLAG(*argList, tmpName); | ||
1767 | } | ||
1768 | } | ||
1769 | } | ||
1770 | } | ||
1771 | |||
1772 | |||
1773 | /*---------------------------------------------*/ | ||
1774 | #define ISFLAG(s) (strcmp(aa->name, (s))==0) | ||
1775 | |||
1776 | IntNative main ( IntNative argc, Char *argv[] ) | ||
1777 | { | ||
1778 | Int32 i, j; | ||
1779 | Char *tmp; | ||
1780 | Cell *argList; | ||
1781 | Cell *aa; | ||
1782 | Bool decode; | ||
1783 | |||
1784 | /*-- Be really really really paranoid :-) --*/ | ||
1785 | if (sizeof(Int32) != 4 || sizeof(UInt32) != 4 || | ||
1786 | sizeof(Int16) != 2 || sizeof(UInt16) != 2 || | ||
1787 | sizeof(Char) != 1 || sizeof(UChar) != 1) | ||
1788 | configError(); | ||
1789 | |||
1790 | /*-- Initialise --*/ | ||
1791 | outputHandleJustInCase = NULL; | ||
1792 | smallMode = False; | ||
1793 | keepInputFiles = False; | ||
1794 | forceOverwrite = False; | ||
1795 | noisy = True; | ||
1796 | verbosity = 0; | ||
1797 | blockSize100k = 9; | ||
1798 | testFailsExist = False; | ||
1799 | unzFailsExist = False; | ||
1800 | numFileNames = 0; | ||
1801 | numFilesProcessed = 0; | ||
1802 | workFactor = 30; | ||
1803 | deleteOutputOnInterrupt = False; | ||
1804 | exitValue = 0; | ||
1805 | i = j = 0; /* avoid bogus warning from egcs-1.1.X */ | ||
1806 | |||
1807 | /*-- Set up signal handlers for mem access errors --*/ | ||
1808 | signal (SIGSEGV, mySIGSEGVorSIGBUScatcher); | ||
1809 | # if BZ_UNIX | ||
1810 | # ifndef __DJGPP__ | ||
1811 | signal (SIGBUS, mySIGSEGVorSIGBUScatcher); | ||
1812 | # endif | ||
1813 | # endif | ||
1814 | |||
1815 | copyFileName ( inName, (Char*)"(none)" ); | ||
1816 | copyFileName ( outName, (Char*)"(none)" ); | ||
1817 | |||
1818 | copyFileName ( progNameReally, argv[0] ); | ||
1819 | progName = &progNameReally[0]; | ||
1820 | for (tmp = &progNameReally[0]; *tmp != '\0'; tmp++) | ||
1821 | if (*tmp == PATH_SEP) progName = tmp + 1; | ||
1822 | |||
1823 | |||
1824 | /*-- Copy flags from env var BZIP2, and | ||
1825 | expand filename wildcards in arg list. | ||
1826 | --*/ | ||
1827 | argList = NULL; | ||
1828 | addFlagsFromEnvVar ( &argList, (Char*)"BZIP2" ); | ||
1829 | addFlagsFromEnvVar ( &argList, (Char*)"BZIP" ); | ||
1830 | for (i = 1; i <= argc-1; i++) | ||
1831 | APPEND_FILESPEC(argList, argv[i]); | ||
1832 | |||
1833 | |||
1834 | /*-- Find the length of the longest filename --*/ | ||
1835 | longestFileName = 7; | ||
1836 | numFileNames = 0; | ||
1837 | decode = True; | ||
1838 | for (aa = argList; aa != NULL; aa = aa->link) { | ||
1839 | if (ISFLAG("--")) { decode = False; continue; } | ||
1840 | if (aa->name[0] == '-' && decode) continue; | ||
1841 | numFileNames++; | ||
1842 | if (longestFileName < (Int32)strlen(aa->name) ) | ||
1843 | longestFileName = (Int32)strlen(aa->name); | ||
1844 | } | ||
1845 | |||
1846 | |||
1847 | /*-- Determine source modes; flag handling may change this too. --*/ | ||
1848 | if (numFileNames == 0) | ||
1849 | srcMode = SM_I2O; else srcMode = SM_F2F; | ||
1850 | |||
1851 | |||
1852 | /*-- Determine what to do (compress/uncompress/test/cat). --*/ | ||
1853 | /*-- Note that subsequent flag handling may change this. --*/ | ||
1854 | opMode = OM_Z; | ||
1855 | |||
1856 | if ( (strstr ( progName, "unzip" ) != 0) || | ||
1857 | (strstr ( progName, "UNZIP" ) != 0) ) | ||
1858 | opMode = OM_UNZ; | ||
1859 | |||
1860 | if ( (strstr ( progName, "z2cat" ) != 0) || | ||
1861 | (strstr ( progName, "Z2CAT" ) != 0) || | ||
1862 | (strstr ( progName, "zcat" ) != 0) || | ||
1863 | (strstr ( progName, "ZCAT" ) != 0) ) { | ||
1864 | opMode = OM_UNZ; | ||
1865 | srcMode = (numFileNames == 0) ? SM_I2O : SM_F2O; | ||
1866 | } | ||
1867 | |||
1868 | |||
1869 | /*-- Look at the flags. --*/ | ||
1870 | for (aa = argList; aa != NULL; aa = aa->link) { | ||
1871 | if (ISFLAG("--")) break; | ||
1872 | if (aa->name[0] == '-' && aa->name[1] != '-') { | ||
1873 | for (j = 1; aa->name[j] != '\0'; j++) { | ||
1874 | switch (aa->name[j]) { | ||
1875 | case 'c': srcMode = SM_F2O; break; | ||
1876 | case 'd': opMode = OM_UNZ; break; | ||
1877 | case 'z': opMode = OM_Z; break; | ||
1878 | case 'f': forceOverwrite = True; break; | ||
1879 | case 't': opMode = OM_TEST; break; | ||
1880 | case 'k': keepInputFiles = True; break; | ||
1881 | case 's': smallMode = True; break; | ||
1882 | case 'q': noisy = False; break; | ||
1883 | case '1': blockSize100k = 1; break; | ||
1884 | case '2': blockSize100k = 2; break; | ||
1885 | case '3': blockSize100k = 3; break; | ||
1886 | case '4': blockSize100k = 4; break; | ||
1887 | case '5': blockSize100k = 5; break; | ||
1888 | case '6': blockSize100k = 6; break; | ||
1889 | case '7': blockSize100k = 7; break; | ||
1890 | case '8': blockSize100k = 8; break; | ||
1891 | case '9': blockSize100k = 9; break; | ||
1892 | case 'V': | ||
1893 | case 'L': license(); break; | ||
1894 | case 'v': verbosity++; break; | ||
1895 | case 'h': usage ( progName ); | ||
1896 | exit ( 0 ); | ||
1897 | break; | ||
1898 | default: fprintf ( stderr, "%s: Bad flag `%s'\n", | ||
1899 | progName, aa->name ); | ||
1900 | usage ( progName ); | ||
1901 | exit ( 1 ); | ||
1902 | break; | ||
1903 | } | ||
1904 | } | ||
1905 | } | ||
1906 | } | ||
1907 | |||
1908 | /*-- And again ... --*/ | ||
1909 | for (aa = argList; aa != NULL; aa = aa->link) { | ||
1910 | if (ISFLAG("--")) break; | ||
1911 | if (ISFLAG("--stdout")) srcMode = SM_F2O; else | ||
1912 | if (ISFLAG("--decompress")) opMode = OM_UNZ; else | ||
1913 | if (ISFLAG("--compress")) opMode = OM_Z; else | ||
1914 | if (ISFLAG("--force")) forceOverwrite = True; else | ||
1915 | if (ISFLAG("--test")) opMode = OM_TEST; else | ||
1916 | if (ISFLAG("--keep")) keepInputFiles = True; else | ||
1917 | if (ISFLAG("--small")) smallMode = True; else | ||
1918 | if (ISFLAG("--quiet")) noisy = False; else | ||
1919 | if (ISFLAG("--version")) license(); else | ||
1920 | if (ISFLAG("--license")) license(); else | ||
1921 | if (ISFLAG("--exponential")) workFactor = 1; else | ||
1922 | if (ISFLAG("--repetitive-best")) redundant(aa->name); else | ||
1923 | if (ISFLAG("--repetitive-fast")) redundant(aa->name); else | ||
1924 | if (ISFLAG("--fast")) blockSize100k = 1; else | ||
1925 | if (ISFLAG("--best")) blockSize100k = 9; else | ||
1926 | if (ISFLAG("--verbose")) verbosity++; else | ||
1927 | if (ISFLAG("--help")) { usage ( progName ); exit ( 0 ); } | ||
1928 | else | ||
1929 | if (strncmp ( aa->name, "--", 2) == 0) { | ||
1930 | fprintf ( stderr, "%s: Bad flag `%s'\n", progName, aa->name ); | ||
1931 | usage ( progName ); | ||
1932 | exit ( 1 ); | ||
1933 | } | ||
1934 | } | ||
1935 | |||
1936 | if (verbosity > 4) verbosity = 4; | ||
1937 | if (opMode == OM_Z && smallMode && blockSize100k > 2) | ||
1938 | blockSize100k = 2; | ||
1939 | |||
1940 | if (opMode == OM_TEST && srcMode == SM_F2O) { | ||
1941 | fprintf ( stderr, "%s: -c and -t cannot be used together.\n", | ||
1942 | progName ); | ||
1943 | exit ( 1 ); | ||
1944 | } | ||
1945 | |||
1946 | if (srcMode == SM_F2O && numFileNames == 0) | ||
1947 | srcMode = SM_I2O; | ||
1948 | |||
1949 | if (opMode != OM_Z) blockSize100k = 0; | ||
1950 | |||
1951 | if (srcMode == SM_F2F) { | ||
1952 | signal (SIGINT, mySignalCatcher); | ||
1953 | signal (SIGTERM, mySignalCatcher); | ||
1954 | # if BZ_UNIX | ||
1955 | signal (SIGHUP, mySignalCatcher); | ||
1956 | # endif | ||
1957 | } | ||
1958 | |||
1959 | if (opMode == OM_Z) { | ||
1960 | if (srcMode == SM_I2O) { | ||
1961 | compress ( NULL ); | ||
1962 | } else { | ||
1963 | decode = True; | ||
1964 | for (aa = argList; aa != NULL; aa = aa->link) { | ||
1965 | if (ISFLAG("--")) { decode = False; continue; } | ||
1966 | if (aa->name[0] == '-' && decode) continue; | ||
1967 | numFilesProcessed++; | ||
1968 | compress ( aa->name ); | ||
1969 | } | ||
1970 | } | ||
1971 | } | ||
1972 | else | ||
1973 | |||
1974 | if (opMode == OM_UNZ) { | ||
1975 | unzFailsExist = False; | ||
1976 | if (srcMode == SM_I2O) { | ||
1977 | uncompress ( NULL ); | ||
1978 | } else { | ||
1979 | decode = True; | ||
1980 | for (aa = argList; aa != NULL; aa = aa->link) { | ||
1981 | if (ISFLAG("--")) { decode = False; continue; } | ||
1982 | if (aa->name[0] == '-' && decode) continue; | ||
1983 | numFilesProcessed++; | ||
1984 | uncompress ( aa->name ); | ||
1985 | } | ||
1986 | } | ||
1987 | if (unzFailsExist) { | ||
1988 | setExit(2); | ||
1989 | exit(exitValue); | ||
1990 | } | ||
1991 | } | ||
1992 | |||
1993 | else { | ||
1994 | testFailsExist = False; | ||
1995 | if (srcMode == SM_I2O) { | ||
1996 | testf ( NULL ); | ||
1997 | } else { | ||
1998 | decode = True; | ||
1999 | for (aa = argList; aa != NULL; aa = aa->link) { | ||
2000 | if (ISFLAG("--")) { decode = False; continue; } | ||
2001 | if (aa->name[0] == '-' && decode) continue; | ||
2002 | numFilesProcessed++; | ||
2003 | testf ( aa->name ); | ||
2004 | } | ||
2005 | } | ||
2006 | if (testFailsExist && noisy) { | ||
2007 | fprintf ( stderr, | ||
2008 | "\n" | ||
2009 | "You can use the `bzip2recover' program to attempt to recover\n" | ||
2010 | "data from undamaged sections of corrupted files.\n\n" | ||
2011 | ); | ||
2012 | setExit(2); | ||
2013 | exit(exitValue); | ||
2014 | } | ||
2015 | } | ||
2016 | |||
2017 | /* Free the argument list memory to mollify leak detectors | ||
2018 | (eg) Purify, Checker. Serves no other useful purpose. | ||
2019 | */ | ||
2020 | aa = argList; | ||
2021 | while (aa != NULL) { | ||
2022 | Cell* aa2 = aa->link; | ||
2023 | if (aa->name != NULL) free(aa->name); | ||
2024 | free(aa); | ||
2025 | aa = aa2; | ||
2026 | } | ||
2027 | |||
2028 | return exitValue; | ||
2029 | } | ||
2030 | |||
2031 | |||
2032 | /*-----------------------------------------------------------*/ | ||
2033 | /*--- end bzip2.c ---*/ | ||
2034 | /*-----------------------------------------------------------*/ | ||