00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 #include <stdio.h>
00060 #include <stdlib.h>
00061 #include <string.h>
00062 #include <errno.h>
00063 #include <fcntl.h>
00064 #include <unistd.h>
00065 #include <sys/types.h>
00066 #include <sys/stat.h>
00067 #include <utime.h>
00068 #include "zlib.h"
00069
00070
00071
00072 #define local static
00073
00074
00075 #define SIZE 32768U
00076 #define PIECE 16384
00077
00078
00079
00080 struct ind {
00081 int infile;
00082 unsigned char *inbuf;
00083 };
00084
00085
00086
00087
00088 local unsigned in(void *in_desc, unsigned char **buf)
00089 {
00090 int ret;
00091 unsigned len;
00092 unsigned char *next;
00093 struct ind *me = (struct ind *)in_desc;
00094
00095 next = me->inbuf;
00096 *buf = next;
00097 len = 0;
00098 do {
00099 ret = PIECE;
00100 if ((unsigned)ret > SIZE - len)
00101 ret = (int)(SIZE - len);
00102 ret = (int)read(me->infile, next, ret);
00103 if (ret == -1) {
00104 len = 0;
00105 break;
00106 }
00107 next += ret;
00108 len += ret;
00109 } while (ret != 0 && len < SIZE);
00110 return len;
00111 }
00112
00113
00114
00115
00116
00117
00118 struct outd {
00119 int outfile;
00120 int check;
00121 unsigned long crc;
00122 unsigned long total;
00123 };
00124
00125
00126
00127
00128
00129
00130 local int out(void *out_desc, unsigned char *buf, unsigned len)
00131 {
00132 int ret;
00133 struct outd *me = (struct outd *)out_desc;
00134
00135 if (me->check) {
00136 me->crc = crc32(me->crc, buf, len);
00137 me->total += len;
00138 }
00139 if (me->outfile != -1)
00140 do {
00141 ret = PIECE;
00142 if ((unsigned)ret > len)
00143 ret = (int)len;
00144 ret = (int)write(me->outfile, buf, ret);
00145 if (ret == -1)
00146 return 1;
00147 buf += ret;
00148 len -= ret;
00149 } while (len != 0);
00150 return 0;
00151 }
00152
00153
00154 #define NEXT() (have ? 0 : (have = in(indp, &next)), \
00155 last = have ? (have--, (int)(*next++)) : -1)
00156
00157
00158
00159
00160 unsigned char inbuf[SIZE];
00161 unsigned char outbuf[SIZE];
00162 unsigned short prefix[65536];
00163 unsigned char suffix[65536];
00164 unsigned char match[65280 + 2];
00165
00166
00167
00168
00169
00170 #define FLUSHCODE() \
00171 do { \
00172 left = 0; \
00173 rem = 0; \
00174 if (chunk > have) { \
00175 chunk -= have; \
00176 have = 0; \
00177 if (NEXT() == -1) \
00178 break; \
00179 chunk--; \
00180 if (chunk > have) { \
00181 chunk = have = 0; \
00182 break; \
00183 } \
00184 } \
00185 have -= chunk; \
00186 next += chunk; \
00187 chunk = 0; \
00188 } while (0)
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199 local int lunpipe(unsigned have, unsigned char *next, struct ind *indp,
00200 int outfile, z_stream *strm)
00201 {
00202 int last;
00203 unsigned chunk;
00204 int left;
00205 unsigned rem;
00206 int bits;
00207 unsigned code;
00208 unsigned mask;
00209 int max;
00210 unsigned flags;
00211 unsigned end;
00212 unsigned temp;
00213 unsigned prev;
00214 unsigned final;
00215 unsigned stack;
00216 unsigned outcnt;
00217 struct outd outd;
00218 unsigned char *p;
00219
00220
00221 outd.outfile = outfile;
00222 outd.check = 0;
00223
00224
00225 flags = NEXT();
00226 if (last == -1)
00227 return Z_BUF_ERROR;
00228 if (flags & 0x60) {
00229 strm->msg = (char *)"unknown lzw flags set";
00230 return Z_DATA_ERROR;
00231 }
00232 max = flags & 0x1f;
00233 if (max < 9 || max > 16) {
00234 strm->msg = (char *)"lzw bits out of range";
00235 return Z_DATA_ERROR;
00236 }
00237 if (max == 9)
00238 max = 10;
00239 flags &= 0x80;
00240
00241
00242 bits = 9;
00243 mask = 0x1ff;
00244 end = flags ? 256 : 255;
00245
00246
00247
00248 if (NEXT() == -1)
00249 return Z_OK;
00250 final = prev = (unsigned)last;
00251 if (NEXT() == -1)
00252 return Z_BUF_ERROR;
00253 if (last & 1) {
00254 strm->msg = (char *)"invalid lzw code";
00255 return Z_DATA_ERROR;
00256 }
00257 rem = (unsigned)last >> 1;
00258 left = 7;
00259 chunk = bits - 2;
00260 outbuf[0] = (unsigned char)final;
00261 outcnt = 1;
00262
00263
00264 stack = 0;
00265 for (;;) {
00266
00267 if (end >= mask && bits < max) {
00268 FLUSHCODE();
00269 bits++;
00270 mask <<= 1;
00271 mask++;
00272 }
00273
00274
00275 if (chunk == 0)
00276 chunk = bits;
00277 code = rem;
00278 if (NEXT() == -1) {
00279
00280 if (outcnt && out(&outd, outbuf, outcnt)) {
00281 strm->next_in = outbuf;
00282 return Z_BUF_ERROR;
00283 }
00284 return Z_OK;
00285 }
00286 code += (unsigned)last << left;
00287 left += 8;
00288 chunk--;
00289 if (bits > left) {
00290 if (NEXT() == -1)
00291 return Z_BUF_ERROR;
00292 code += (unsigned)last << left;
00293 left += 8;
00294 chunk--;
00295 }
00296 code &= mask;
00297 left -= bits;
00298 rem = (unsigned)last >> (8 - left);
00299
00300
00301 if (code == 256 && flags) {
00302 FLUSHCODE();
00303 bits = 9;
00304 mask = 0x1ff;
00305 end = 255;
00306 continue;
00307 }
00308
00309
00310 temp = code;
00311 if (code > end) {
00312
00313
00314
00315
00316
00317
00318
00319
00320 if (code != end + 1 || prev > end) {
00321 strm->msg = (char *)"invalid lzw code";
00322 return Z_DATA_ERROR;
00323 }
00324 match[stack++] = (unsigned char)final;
00325 code = prev;
00326 }
00327
00328
00329 p = match + stack;
00330 while (code >= 256) {
00331 *p++ = suffix[code];
00332 code = prefix[code];
00333 }
00334 stack = p - match;
00335 match[stack++] = (unsigned char)code;
00336 final = code;
00337
00338
00339 if (end < mask) {
00340 end++;
00341 prefix[end] = (unsigned short)prev;
00342 suffix[end] = (unsigned char)final;
00343 }
00344
00345
00346 prev = temp;
00347
00348
00349 while (stack > SIZE - outcnt) {
00350 while (outcnt < SIZE)
00351 outbuf[outcnt++] = match[--stack];
00352 if (out(&outd, outbuf, outcnt)) {
00353 strm->next_in = outbuf;
00354 return Z_BUF_ERROR;
00355 }
00356 outcnt = 0;
00357 }
00358 p = match + stack;
00359 do {
00360 outbuf[outcnt++] = *--p;
00361 } while (p > match);
00362 stack = 0;
00363
00364
00365
00366
00367 }
00368 }
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382 local int gunpipe(z_stream *strm, int infile, int outfile)
00383 {
00384 int ret, first, last;
00385 unsigned have, flags, len;
00386 unsigned char *next = NULL;
00387 struct ind ind, *indp;
00388 struct outd outd;
00389
00390
00391 ind.infile = infile;
00392 ind.inbuf = inbuf;
00393 indp = &ind;
00394
00395
00396 have = 0;
00397 first = 1;
00398 strm->next_in = Z_NULL;
00399 for (;;) {
00400
00401 if (NEXT() == -1) {
00402 ret = Z_OK;
00403 break;
00404 }
00405 if (last != 31 || (NEXT() != 139 && last != 157)) {
00406 strm->msg = (char *)"incorrect header check";
00407 ret = first ? Z_DATA_ERROR : Z_ERRNO;
00408 break;
00409 }
00410 first = 0;
00411
00412
00413 if (last == 157) {
00414 ret = lunpipe(have, next, indp, outfile, strm);
00415 break;
00416 }
00417
00418
00419 ret = Z_BUF_ERROR;
00420 if (NEXT() != 8) {
00421 if (last == -1) break;
00422 strm->msg = (char *)"unknown compression method";
00423 ret = Z_DATA_ERROR;
00424 break;
00425 }
00426 flags = NEXT();
00427 NEXT();
00428 NEXT();
00429 NEXT();
00430 NEXT();
00431 NEXT();
00432 NEXT();
00433 if (last == -1) break;
00434 if (flags & 0xe0) {
00435 strm->msg = (char *)"unknown header flags set";
00436 ret = Z_DATA_ERROR;
00437 break;
00438 }
00439 if (flags & 4) {
00440 len = NEXT();
00441 len += (unsigned)(NEXT()) << 8;
00442 if (last == -1) break;
00443 while (len > have) {
00444 len -= have;
00445 have = 0;
00446 if (NEXT() == -1) break;
00447 len--;
00448 }
00449 if (last == -1) break;
00450 have -= len;
00451 next += len;
00452 }
00453 if (flags & 8)
00454 while (NEXT() != 0 && last != -1)
00455 ;
00456 if (flags & 16)
00457 while (NEXT() != 0 && last != -1)
00458 ;
00459 if (flags & 2) {
00460 NEXT();
00461 NEXT();
00462 }
00463 if (last == -1) break;
00464
00465
00466 outd.outfile = outfile;
00467 outd.check = 1;
00468 outd.crc = crc32(0L, Z_NULL, 0);
00469 outd.total = 0;
00470
00471
00472 strm->next_in = next;
00473 strm->avail_in = have;
00474 ret = inflateBack(strm, in, indp, out, &outd);
00475 if (ret != Z_STREAM_END) break;
00476 next = strm->next_in;
00477 have = strm->avail_in;
00478 strm->next_in = Z_NULL;
00479
00480
00481 ret = Z_BUF_ERROR;
00482 if (NEXT() != (int)(outd.crc & 0xff) ||
00483 NEXT() != (int)((outd.crc >> 8) & 0xff) ||
00484 NEXT() != (int)((outd.crc >> 16) & 0xff) ||
00485 NEXT() != (int)((outd.crc >> 24) & 0xff)) {
00486
00487 if (last != -1) {
00488 strm->msg = (char *)"incorrect data check";
00489 ret = Z_DATA_ERROR;
00490 }
00491 break;
00492 }
00493 if (NEXT() != (int)(outd.total & 0xff) ||
00494 NEXT() != (int)((outd.total >> 8) & 0xff) ||
00495 NEXT() != (int)((outd.total >> 16) & 0xff) ||
00496 NEXT() != (int)((outd.total >> 24) & 0xff)) {
00497
00498 if (last != -1) {
00499 strm->msg = (char *)"incorrect length check";
00500 ret = Z_DATA_ERROR;
00501 }
00502 break;
00503 }
00504
00505
00506 }
00507
00508
00509 return ret;
00510 }
00511
00512
00513
00514
00515
00516 local void copymeta(char *from, char *to)
00517 {
00518 struct stat was;
00519 struct utimbuf when;
00520
00521
00522 if (stat(from, &was) != 0 || (was.st_mode & S_IFMT) != S_IFREG)
00523 return;
00524
00525
00526 (void)chmod(to, was.st_mode & 07777);
00527
00528
00529 (void)chown(to, was.st_uid, was.st_gid);
00530
00531
00532 when.actime = was.st_atime;
00533 when.modtime = was.st_mtime;
00534 (void)utime(to, &when);
00535 }
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547 local int gunzip(z_stream *strm, char *inname, char *outname, int test)
00548 {
00549 int ret;
00550 int infile, outfile;
00551
00552
00553 if (inname == NULL || *inname == 0) {
00554 inname = "-";
00555 infile = 0;
00556 }
00557 else {
00558 infile = open(inname, O_RDONLY, 0);
00559 if (infile == -1) {
00560 fprintf(stderr, "gun cannot open %s\n", inname);
00561 return 0;
00562 }
00563 }
00564 if (test)
00565 outfile = -1;
00566 else if (outname == NULL || *outname == 0) {
00567 outname = "-";
00568 outfile = 1;
00569 }
00570 else {
00571 outfile = open(outname, O_CREAT | O_TRUNC | O_WRONLY, 0666);
00572 if (outfile == -1) {
00573 close(infile);
00574 fprintf(stderr, "gun cannot create %s\n", outname);
00575 return 0;
00576 }
00577 }
00578 errno = 0;
00579
00580
00581 ret = gunpipe(strm, infile, outfile);
00582 if (outfile > 2) close(outfile);
00583 if (infile > 2) close(infile);
00584
00585
00586 switch (ret) {
00587 case Z_OK:
00588 case Z_ERRNO:
00589 if (infile > 2 && outfile > 2) {
00590 copymeta(inname, outname);
00591 unlink(inname);
00592 }
00593 if (ret == Z_ERRNO)
00594 fprintf(stderr, "gun warning: trailing garbage ignored in %s\n",
00595 inname);
00596 break;
00597 case Z_DATA_ERROR:
00598 if (outfile > 2) unlink(outname);
00599 fprintf(stderr, "gun data error on %s: %s\n", inname, strm->msg);
00600 break;
00601 case Z_MEM_ERROR:
00602 if (outfile > 2) unlink(outname);
00603 fprintf(stderr, "gun out of memory error--aborting\n");
00604 return 1;
00605 case Z_BUF_ERROR:
00606 if (outfile > 2) unlink(outname);
00607 if (strm->next_in != Z_NULL) {
00608 fprintf(stderr, "gun write error on %s: %s\n",
00609 outname, strerror(errno));
00610 }
00611 else if (errno) {
00612 fprintf(stderr, "gun read error on %s: %s\n",
00613 inname, strerror(errno));
00614 }
00615 else {
00616 fprintf(stderr, "gun unexpected end of file on %s\n",
00617 inname);
00618 }
00619 break;
00620 default:
00621 if (outfile > 2) unlink(outname);
00622 fprintf(stderr, "gun internal error--aborting\n");
00623 return 1;
00624 }
00625 return 0;
00626 }
00627
00628
00629
00630 int main(int argc, char **argv)
00631 {
00632 int ret, len, test;
00633 char *outname;
00634 unsigned char *window;
00635 z_stream strm;
00636
00637
00638 window = match;
00639 strm.zalloc = Z_NULL;
00640 strm.zfree = Z_NULL;
00641 strm.opaque = Z_NULL;
00642 ret = inflateBackInit(&strm, 15, window);
00643 if (ret != Z_OK) {
00644 fprintf(stderr, "gun out of memory error--aborting\n");
00645 return 1;
00646 }
00647
00648
00649 argc--;
00650 argv++;
00651 test = 0;
00652 if (argc && strcmp(*argv, "-h") == 0) {
00653 fprintf(stderr, "gun 1.6 (17 Jan 2010)\n");
00654 fprintf(stderr, "Copyright (C) 2003-2010 Mark Adler\n");
00655 fprintf(stderr, "usage: gun [-t] [file1.gz [file2.Z ...]]\n");
00656 return 0;
00657 }
00658 if (argc && strcmp(*argv, "-t") == 0) {
00659 test = 1;
00660 argc--;
00661 argv++;
00662 }
00663 if (argc)
00664 do {
00665 if (test)
00666 outname = NULL;
00667 else {
00668 len = (int)strlen(*argv);
00669 if (strcmp(*argv + len - 3, ".gz") == 0 ||
00670 strcmp(*argv + len - 3, "-gz") == 0)
00671 len -= 3;
00672 else if (strcmp(*argv + len - 2, ".z") == 0 ||
00673 strcmp(*argv + len - 2, "-z") == 0 ||
00674 strcmp(*argv + len - 2, "_z") == 0 ||
00675 strcmp(*argv + len - 2, ".Z") == 0)
00676 len -= 2;
00677 else {
00678 fprintf(stderr, "gun error: no gz type on %s--skipping\n",
00679 *argv);
00680 continue;
00681 }
00682 outname = malloc(len + 1);
00683 if (outname == NULL) {
00684 fprintf(stderr, "gun out of memory error--aborting\n");
00685 ret = 1;
00686 break;
00687 }
00688 memcpy(outname, *argv, len);
00689 outname[len] = 0;
00690 }
00691 ret = gunzip(&strm, *argv, outname, test);
00692 if (outname != NULL) free(outname);
00693 if (ret) break;
00694 } while (argv++, --argc);
00695 else
00696 ret = gunzip(&strm, NULL, NULL, test);
00697
00698
00699 inflateBackEnd(&strm);
00700 return ret;
00701 }