Lines 1-6
Link Here
|
1 |
/* pigz.c -- parallel implementation of gzip |
1 |
/* pigz.c -- parallel implementation of gzip |
2 |
* Copyright (C) 2007-2017 Mark Adler |
2 |
* Copyright (C) 2007-2017 Mark Adler |
3 |
* Version 2.4 26 Dec 2017 Mark Adler |
3 |
* Version 2.4.1x xx Dec 2017 Mark Adler |
4 |
*/ |
4 |
*/ |
5 |
|
5 |
|
6 |
/* |
6 |
/* |
Lines 188-194
Link Here
|
188 |
Fix sign error in compression reduction percentage |
188 |
Fix sign error in compression reduction percentage |
189 |
*/ |
189 |
*/ |
190 |
|
190 |
|
191 |
#define VERSION "pigz 2.4\n" |
191 |
#define VERSION "pigz 2.4.1x" |
192 |
|
192 |
|
193 |
/* To-do: |
193 |
/* To-do: |
194 |
- make source portable for Windows, VMS, etc. (see gzip source code) |
194 |
- make source portable for Windows, VMS, etc. (see gzip source code) |
Lines 352-359
Link Here
|
352 |
#if __STDC_VERSION__-0 >= 199901L || __GNUC__-0 >= 3 |
352 |
#if __STDC_VERSION__-0 >= 199901L || __GNUC__-0 >= 3 |
353 |
# include <inttypes.h> // intmax_t, uintmax_t |
353 |
# include <inttypes.h> // intmax_t, uintmax_t |
354 |
typedef uintmax_t length_t; |
354 |
typedef uintmax_t length_t; |
|
|
355 |
typedef uint32_t crc_t; |
355 |
#else |
356 |
#else |
356 |
typedef unsigned long length_t; |
357 |
typedef unsigned long length_t; |
|
|
358 |
typedef unsigned long crc_t; |
357 |
#endif |
359 |
#endif |
358 |
|
360 |
|
359 |
#ifdef PIGZ_DEBUG |
361 |
#ifdef PIGZ_DEBUG |
Lines 493-500
Link Here
|
493 |
#define INBUFS(p) (((p)<<1)+3) |
495 |
#define INBUFS(p) (((p)<<1)+3) |
494 |
#define OUTPOOL(s) ((s)+((s)>>4)+DICT) |
496 |
#define OUTPOOL(s) ((s)+((s)>>4)+DICT) |
495 |
|
497 |
|
496 |
// Input buffer size. |
498 |
// Input buffer size, and augmentation for re-inserting a central header. |
497 |
#define BUF 32768U |
499 |
#define BUF 32768 |
|
|
500 |
#define CEN 42 |
501 |
#define EXT (BUF + CEN) // provide enough room to unget a header |
498 |
|
502 |
|
499 |
// Globals (modified by main thread only when it's the only thread). |
503 |
// Globals (modified by main thread only when it's the only thread). |
500 |
local struct { |
504 |
local struct { |
Lines 512-521
local struct {
Link Here
|
512 |
int force; // true to overwrite, compress links, cat |
516 |
int force; // true to overwrite, compress links, cat |
513 |
int sync; // true to flush output file |
517 |
int sync; // true to flush output file |
514 |
int form; // gzip = 0, zlib = 1, zip = 2 or 3 |
518 |
int form; // gzip = 0, zlib = 1, zip = 2 or 3 |
515 |
unsigned char magic1; // first byte of possible header when decoding |
519 |
int magic1; // first byte of possible header when decoding |
516 |
int recurse; // true to dive down into directory structure |
520 |
int recurse; // true to dive down into directory structure |
517 |
char *sufx; // suffix to use (".gz" or user supplied) |
521 |
char *sufx; // suffix to use (".gz" or user supplied) |
518 |
char *name; // name for gzip header |
522 |
char *name; // name for gzip or zip header |
|
|
523 |
char *alias; // name for zip header when input is stdin |
524 |
char *comment; // comment for gzip or zip header. |
519 |
time_t mtime; // time stamp from input file for gzip header |
525 |
time_t mtime; // time stamp from input file for gzip header |
520 |
int list; // true to list files instead of compress |
526 |
int list; // true to list files instead of compress |
521 |
int first; // true if we need to print listing header |
527 |
int first; // true if we need to print listing header |
Lines 528-543
local struct {
Link Here
|
528 |
int procs; // maximum number of compression threads (>= 1) |
534 |
int procs; // maximum number of compression threads (>= 1) |
529 |
int setdict; // true to initialize dictionary in each thread |
535 |
int setdict; // true to initialize dictionary in each thread |
530 |
size_t block; // uncompressed input size per thread (>= 32K) |
536 |
size_t block; // uncompressed input size per thread (>= 32K) |
|
|
537 |
crc_t shift; // pre-calculated CRC-32 shift for length block |
531 |
|
538 |
|
532 |
// saved gzip/zip header data for decompression, testing, and listing |
539 |
// saved gzip/zip header data for decompression, testing, and listing |
533 |
time_t stamp; // time stamp from gzip header |
540 |
time_t stamp; // time stamp from gzip header |
534 |
char *hname; // name from header (allocated) |
541 |
char *hname; // name from header (allocated) |
|
|
542 |
char *hcomm; // comment from header (allocated) |
535 |
unsigned long zip_crc; // local header crc |
543 |
unsigned long zip_crc; // local header crc |
536 |
length_t zip_clen; // local header compressed length |
544 |
length_t zip_clen; // local header compressed length |
537 |
length_t zip_ulen; // local header uncompressed length |
545 |
length_t zip_ulen; // local header uncompressed length |
|
|
546 |
int zip64; // true if has zip64 extended information |
538 |
|
547 |
|
539 |
// globals for decompression and listing buffered reading |
548 |
// globals for decompression and listing buffered reading |
540 |
unsigned char in_buf[BUF]; // input buffer |
549 |
unsigned char in_buf[EXT]; // input buffer |
541 |
unsigned char *in_next; // next unused byte in buffer |
550 |
unsigned char *in_next; // next unused byte in buffer |
542 |
size_t in_left; // number of unused bytes in buffer |
551 |
size_t in_left; // number of unused bytes in buffer |
543 |
int in_eof; // true if reached end of file on input |
552 |
int in_eof; // true if reached end of file on input |
Lines 548-554
local struct {
Link Here
|
548 |
|
557 |
|
549 |
#ifndef NOTHREAD |
558 |
#ifndef NOTHREAD |
550 |
// globals for decompression parallel reading |
559 |
// globals for decompression parallel reading |
551 |
unsigned char in_buf2[BUF]; // second buffer for parallel reads |
560 |
unsigned char in_buf2[EXT]; // second buffer for parallel reads |
552 |
size_t in_len; // data waiting in next buffer |
561 |
size_t in_len; // data waiting in next buffer |
553 |
int in_which; // -1: start, 0: in_buf2, 1: in_buf |
562 |
int in_which; // -1: start, 0: in_buf2, 1: in_buf |
554 |
lock *load_state; // value = 0 to wait, 1 to read a buffer |
563 |
lock *load_state; // value = 0 to wait, 1 to read a buffer |
Lines 576-588
local int complain(char *fmt, ...) {
Link Here
|
576 |
|
585 |
|
577 |
// Memory tracking. |
586 |
// Memory tracking. |
578 |
|
587 |
|
|
|
588 |
#define MAXMEM 131072 // maximum number of tracked pointers |
589 |
|
579 |
local struct mem_track_s { |
590 |
local struct mem_track_s { |
580 |
size_t num; // current number of allocations |
591 |
size_t num; // current number of allocations |
581 |
size_t size; // total size of current allocations |
592 |
size_t size; // total size of current allocations |
|
|
593 |
size_t tot; // maximum number of allocations |
582 |
size_t max; // maximum size of allocations |
594 |
size_t max; // maximum size of allocations |
583 |
#ifndef NOTHREAD |
595 |
#ifndef NOTHREAD |
584 |
lock *lock; // lock for access across threads |
596 |
lock *lock; // lock for access across threads |
585 |
#endif |
597 |
#endif |
|
|
598 |
size_t have; // number in array (possibly != num) |
599 |
void *mem[MAXMEM]; // sorted array of allocated pointers |
586 |
} mem_track; |
600 |
} mem_track; |
587 |
|
601 |
|
588 |
#ifndef NOTHREAD |
602 |
#ifndef NOTHREAD |
Lines 593-642
local struct mem_track_s {
Link Here
|
593 |
# define mem_track_drop(m) |
607 |
# define mem_track_drop(m) |
594 |
#endif |
608 |
#endif |
595 |
|
609 |
|
596 |
local void *malloc_track(struct mem_track_s *mem, size_t size) { |
610 |
// Return the leftmost insert location of ptr in the sorted list mem->mem[], |
597 |
void *ptr; |
611 |
// which currently has mem->have elements. If ptr is already in the list, the |
|
|
612 |
// returned value will point to its first occurrence. The return location will |
613 |
// be one after the last element if ptr is greater than all of the elements. |
614 |
local size_t search_track(struct mem_track_s *mem, void *ptr) { |
615 |
ptrdiff_t left = 0; |
616 |
ptrdiff_t right = mem->have - 1; |
617 |
while (left <= right) { |
618 |
ptrdiff_t mid = (left + right) >> 1; |
619 |
if (mem->mem[mid] < ptr) |
620 |
left = mid + 1; |
621 |
else |
622 |
right = mid - 1; |
623 |
} |
624 |
return left; |
625 |
} |
598 |
|
626 |
|
599 |
ptr = malloc(size); |
627 |
// Insert ptr in the sorted list mem->mem[] and update the memory allocation |
600 |
if (ptr != NULL) { |
628 |
// statistics. |
601 |
size = MALLOC_SIZE(ptr); |
629 |
local void insert_track(struct mem_track_s *mem, void *ptr) { |
602 |
mem_track_grab(mem); |
630 |
mem_track_grab(mem); |
603 |
mem->num++; |
631 |
assert(mem->have < MAXMEM && "increase MAXMEM in source and try again"); |
604 |
mem->size += size; |
632 |
size_t i = search_track(mem, ptr); |
605 |
if (mem->size > mem->max) |
633 |
if (i < mem->have && mem->mem[i] == ptr) |
606 |
mem->max = mem->size; |
634 |
complain("mem_track: duplicate pointer %p\n", ptr); |
607 |
mem_track_drop(mem); |
635 |
memmove(&mem->mem[i + 1], &mem->mem[i], |
|
|
636 |
(mem->have - i) * sizeof(void *)); |
637 |
mem->mem[i] = ptr; |
638 |
mem->have++; |
639 |
mem->num++; |
640 |
mem->size += MALLOC_SIZE(ptr); |
641 |
if (mem->num > mem->tot) |
642 |
mem->tot = mem->num; |
643 |
if (mem->size > mem->max) |
644 |
mem->max = mem->size; |
645 |
mem_track_drop(mem); |
646 |
} |
647 |
|
648 |
// Find and delete ptr from the sorted list mem->mem[] and update the memory |
649 |
// allocation statistics. |
650 |
local void delete_track(struct mem_track_s *mem, void *ptr) { |
651 |
mem_track_grab(mem); |
652 |
size_t i = search_track(mem, ptr); |
653 |
if (i < mem->num && mem->mem[i] == ptr) { |
654 |
memmove(&mem->mem[i], &mem->mem[i + 1], |
655 |
(mem->have - (i + 1)) * sizeof(void *)); |
656 |
mem->have--; |
608 |
} |
657 |
} |
|
|
658 |
else |
659 |
complain("mem_track: missing pointer %p\n", ptr); |
660 |
mem->num--; |
661 |
mem->size -= MALLOC_SIZE(ptr); |
662 |
mem_track_drop(mem); |
663 |
} |
664 |
|
665 |
local void *malloc_track(struct mem_track_s *mem, size_t size) { |
666 |
void *ptr = malloc(size); |
667 |
if (ptr != NULL) |
668 |
insert_track(mem, ptr); |
609 |
return ptr; |
669 |
return ptr; |
610 |
} |
670 |
} |
611 |
|
671 |
|
612 |
local void *realloc_track(struct mem_track_s *mem, void *ptr, size_t size) { |
672 |
local void *realloc_track(struct mem_track_s *mem, void *ptr, size_t size) { |
613 |
size_t was; |
|
|
614 |
|
615 |
if (ptr == NULL) |
673 |
if (ptr == NULL) |
616 |
return malloc_track(mem, size); |
674 |
return malloc_track(mem, size); |
617 |
was = MALLOC_SIZE(ptr); |
675 |
delete_track(mem, ptr); |
618 |
ptr = realloc(ptr, size); |
676 |
void *got = realloc(ptr, size); |
619 |
if (ptr != NULL) { |
677 |
insert_track(mem, got == NULL ? ptr : got); |
620 |
size = MALLOC_SIZE(ptr); |
678 |
return got; |
621 |
mem_track_grab(mem); |
|
|
622 |
mem->size -= was; |
623 |
mem->size += size; |
624 |
if (mem->size > mem->max) |
625 |
mem->max = mem->size; |
626 |
mem_track_drop(mem); |
627 |
} |
628 |
return ptr; |
629 |
} |
679 |
} |
630 |
|
680 |
|
631 |
local void free_track(struct mem_track_s *mem, void *ptr) { |
681 |
local void free_track(struct mem_track_s *mem, void *ptr) { |
632 |
size_t size; |
|
|
633 |
|
634 |
if (ptr != NULL) { |
682 |
if (ptr != NULL) { |
635 |
size = MALLOC_SIZE(ptr); |
683 |
delete_track(mem, ptr); |
636 |
mem_track_grab(mem); |
|
|
637 |
mem->num--; |
638 |
mem->size -= size; |
639 |
mem_track_drop(mem); |
640 |
free(ptr); |
684 |
free(ptr); |
641 |
} |
685 |
} |
642 |
} |
686 |
} |
Lines 708-714
local void log_init(void) {
Link Here
|
708 |
if (log_tail == NULL) { |
752 |
if (log_tail == NULL) { |
709 |
mem_track.num = 0; |
753 |
mem_track.num = 0; |
710 |
mem_track.size = 0; |
754 |
mem_track.size = 0; |
|
|
755 |
mem_track.num = 0; |
711 |
mem_track.max = 0; |
756 |
mem_track.max = 0; |
|
|
757 |
mem_track.have = 0; |
712 |
#ifndef NOTHREAD |
758 |
#ifndef NOTHREAD |
713 |
mem_track.lock = new_lock(0); |
759 |
mem_track.lock = new_lock(0); |
714 |
yarn_mem(yarn_malloc, yarn_free); |
760 |
yarn_mem(yarn_malloc, yarn_free); |
Lines 818-825
local void log_dump(void) {
Link Here
|
818 |
complain("memory leak: %lu allocs of %lu bytes total", |
864 |
complain("memory leak: %lu allocs of %lu bytes total", |
819 |
mem_track.num, mem_track.size); |
865 |
mem_track.num, mem_track.size); |
820 |
if (mem_track.max) |
866 |
if (mem_track.max) |
821 |
fprintf(stderr, "%lu bytes of memory used\n", |
867 |
fprintf(stderr, "%lu bytes of memory used in %lu allocs\n", |
822 |
(unsigned long)mem_track.max); |
868 |
mem_track.max, mem_track.tot); |
823 |
} |
869 |
} |
824 |
|
870 |
|
825 |
// Debugging macro. |
871 |
// Debugging macro. |
Lines 1017-1023
local unsigned put(int out, ...) {
Link Here
|
1017 |
|
1063 |
|
1018 |
// write wrap[] to out and return the number of bytes written |
1064 |
// write wrap[] to out and return the number of bytes written |
1019 |
writen(out, wrap, count); |
1065 |
writen(out, wrap, count); |
1020 |
free(wrap); |
1066 |
FREE(wrap); |
1021 |
return count; |
1067 |
return count; |
1022 |
} |
1068 |
} |
1023 |
|
1069 |
|
Lines 1042-1054
local length_t put_header(void) {
Link Here
|
1042 |
4, (val_t)0, // crc (not here) |
1088 |
4, (val_t)0, // crc (not here) |
1043 |
4, (val_t)LOW32, // compressed length (not here) |
1089 |
4, (val_t)LOW32, // compressed length (not here) |
1044 |
4, (val_t)LOW32, // uncompressed length (not here) |
1090 |
4, (val_t)LOW32, // uncompressed length (not here) |
1045 |
2, (val_t)(g.name == NULL ? 1 : strlen(g.name)), // name length |
1091 |
2, (val_t)(strlen(g.name == NULL ? g.alias : g.name)), // name len |
1046 |
2, (val_t)29, // length of extra field (see below) |
1092 |
2, (val_t)29, // length of extra field (see below) |
1047 |
0); |
1093 |
0); |
1048 |
|
1094 |
|
1049 |
// write file name (use "-" for stdin) |
1095 |
// write file name (use g.alias for stdin) |
1050 |
len += writen(g.outd, g.name == NULL ? "-" : g.name, |
1096 |
len += writen(g.outd, g.name == NULL ? g.alias : g.name, |
1051 |
g.name == NULL ? 1 : strlen(g.name)); |
1097 |
strlen(g.name == NULL ? g.alias : g.name)); |
1052 |
|
1098 |
|
1053 |
// write Zip64 and extended timestamp extra field blocks (29 bytes) |
1099 |
// write Zip64 and extended timestamp extra field blocks (29 bytes) |
1054 |
len += put(g.outd, |
1100 |
len += put(g.outd, |
Lines 1063-1068
local length_t put_header(void) {
Link Here
|
1063 |
0); |
1109 |
0); |
1064 |
} |
1110 |
} |
1065 |
else if (g.form) { // zlib |
1111 |
else if (g.form) { // zlib |
|
|
1112 |
if (g.comment != NULL) |
1113 |
complain("can't store comment in zlib format -- ignoring"); |
1066 |
unsigned head; |
1114 |
unsigned head; |
1067 |
head = (0x78 << 8) + // deflate, 32K window |
1115 |
head = (0x78 << 8) + // deflate, 32K window |
1068 |
(g.level >= 9 ? 3 << 6 : |
1116 |
(g.level >= 9 ? 3 << 6 : |
Lines 1079-1091
local length_t put_header(void) {
Link Here
|
1079 |
1, (val_t)31, |
1127 |
1, (val_t)31, |
1080 |
1, (val_t)139, |
1128 |
1, (val_t)139, |
1081 |
1, (val_t)8, // deflate |
1129 |
1, (val_t)8, // deflate |
1082 |
1, (val_t)(g.name != NULL ? 8 : 0), |
1130 |
1, (val_t)((g.name != NULL ? 8 : 0) + |
|
|
1131 |
(g.comment != NULL ? 16 : 0)), |
1083 |
4, (val_t)g.mtime, |
1132 |
4, (val_t)g.mtime, |
1084 |
1, (val_t)(g.level >= 9 ? 2 : g.level == 1 ? 4 : 0), |
1133 |
1, (val_t)(g.level >= 9 ? 2 : g.level == 1 ? 4 : 0), |
1085 |
1, (val_t)3, // unix |
1134 |
1, (val_t)3, // unix |
1086 |
0); |
1135 |
0); |
1087 |
if (g.name != NULL) |
1136 |
if (g.name != NULL) |
1088 |
len += writen(g.outd, g.name, strlen(g.name) + 1); |
1137 |
len += writen(g.outd, g.name, strlen(g.name) + 1); |
|
|
1138 |
if (g.comment != NULL) |
1139 |
len += writen(g.outd, g.comment, strlen(g.comment) + 1); |
1089 |
} |
1140 |
} |
1090 |
return len; |
1141 |
return len; |
1091 |
} |
1142 |
} |
Lines 1119-1136
local void put_trailer(length_t ulen, length_t clen,
Link Here
|
1119 |
4, (val_t)check, // crc |
1170 |
4, (val_t)check, // crc |
1120 |
4, (val_t)(zip64 ? LOW32 : clen), // compressed length |
1171 |
4, (val_t)(zip64 ? LOW32 : clen), // compressed length |
1121 |
4, (val_t)(zip64 ? LOW32 : ulen), // uncompressed length |
1172 |
4, (val_t)(zip64 ? LOW32 : ulen), // uncompressed length |
1122 |
2, (val_t)(g.name == NULL ? 1 : strlen(g.name)), // name length |
1173 |
2, (val_t)(strlen(g.name == NULL ? g.alias : g.name)), // name len |
1123 |
2, (val_t)(zip64 ? 29 : 9), // extra field size (see below) |
1174 |
2, (val_t)(zip64 ? 29 : 9), // extra field size (see below) |
1124 |
2, (val_t)0, // no file comment |
1175 |
2, (val_t)(g.comment == NULL ? 0 : strlen(g.comment)), // comment |
1125 |
2, (val_t)0, // disk number 0 |
1176 |
2, (val_t)0, // disk number 0 |
1126 |
2, (val_t)0, // internal file attributes |
1177 |
2, (val_t)0, // internal file attributes |
1127 |
4, (val_t)0, // external file attributes (ignored) |
1178 |
4, (val_t)0, // external file attributes (ignored) |
1128 |
4, (val_t)0, // offset of local header |
1179 |
4, (val_t)0, // offset of local header |
1129 |
0); |
1180 |
0); |
1130 |
|
1181 |
|
1131 |
// write file name (use "-" for stdin) |
1182 |
// write file name (use g.alias for stdin) |
1132 |
cent += writen(g.outd, g.name == NULL ? "-" : g.name, |
1183 |
cent += writen(g.outd, g.name == NULL ? g.alias : g.name, |
1133 |
g.name == NULL ? 1 : strlen(g.name)); |
1184 |
strlen(g.name == NULL ? g.alias : g.name)); |
1134 |
|
1185 |
|
1135 |
// write Zip64 extra field block (20 bytes) |
1186 |
// write Zip64 extra field block (20 bytes) |
1136 |
if (zip64) |
1187 |
if (zip64) |
Lines 1149-1154
local void put_trailer(length_t ulen, length_t clen,
Link Here
|
1149 |
4, (val_t)g.mtime, // mod time |
1200 |
4, (val_t)g.mtime, // mod time |
1150 |
0); |
1201 |
0); |
1151 |
|
1202 |
|
|
|
1203 |
// write comment, if requested |
1204 |
if (g.comment != NULL) |
1205 |
cent += writen(g.outd, g.comment, strlen(g.comment)); |
1206 |
|
1152 |
// here zip64 is true if the offset of the central directory does not |
1207 |
// here zip64 is true if the offset of the central directory does not |
1153 |
// fit in 32 bits, in which case insert the Zip64 end records to |
1208 |
// fit in 32 bits, in which case insert the Zip64 end records to |
1154 |
// provide a 64-bit offset |
1209 |
// provide a 64-bit offset |
Lines 1256-1331
local long zlib_vernum(void) {
Link Here
|
1256 |
// We copy the combination routines from zlib here, in order to avoid linkage |
1311 |
// We copy the combination routines from zlib here, in order to avoid linkage |
1257 |
// issues with the zlib 1.2.3 builds on Sun, Ubuntu, and others. |
1312 |
// issues with the zlib 1.2.3 builds on Sun, Ubuntu, and others. |
1258 |
|
1313 |
|
1259 |
local unsigned long gf2_matrix_times(unsigned long *mat, unsigned long vec) { |
1314 |
// CRC-32 polynomial, reflected. |
1260 |
unsigned long sum; |
1315 |
#define POLY 0xedb88320 |
1261 |
|
1316 |
|
1262 |
sum = 0; |
1317 |
// Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC |
1263 |
while (vec) { |
1318 |
// polynomial, reflected. For speed, this requires that a not be zero. |
1264 |
if (vec & 1) |
1319 |
local crc_t multmodp(crc_t a, crc_t b) { |
1265 |
sum ^= *mat; |
1320 |
crc_t m = (crc_t)1 << 31; |
1266 |
vec >>= 1; |
1321 |
crc_t p = 0; |
1267 |
mat++; |
1322 |
for (;;) { |
|
|
1323 |
if (a & m) { |
1324 |
p ^= b; |
1325 |
if ((a & (m - 1)) == 0) |
1326 |
break; |
1327 |
} |
1328 |
m >>= 1; |
1329 |
b = b & 1 ? (b >> 1) ^ POLY : b >> 1; |
1268 |
} |
1330 |
} |
1269 |
return sum; |
1331 |
return p; |
1270 |
} |
1332 |
} |
1271 |
|
1333 |
|
1272 |
local void gf2_matrix_square(unsigned long *square, unsigned long *mat) { |
1334 |
// Table of x^2^n modulo p(x). |
1273 |
int n; |
1335 |
local const crc_t x2n_table[] = { |
1274 |
|
1336 |
0x40000000, 0x20000000, 0x08000000, 0x00800000, 0x00008000, |
1275 |
for (n = 0; n < 32; n++) |
1337 |
0xedb88320, 0xb1e6b092, 0xa06a2517, 0xed627dae, 0x88d14467, |
1276 |
square[n] = gf2_matrix_times(mat, mat[n]); |
1338 |
0xd7bbfe6a, 0xec447f11, 0x8e7ea170, 0x6427800e, 0x4d47bae0, |
|
|
1339 |
0x09fe548f, 0x83852d0f, 0x30362f1a, 0x7b5a9cc3, 0x31fec169, |
1340 |
0x9fec022a, 0x6c8dedc4, 0x15d6874d, 0x5fde7a4e, 0xbad90e37, |
1341 |
0x2e4e5eef, 0x4eaba214, 0xa8a472c0, 0x429a969e, 0x148d302a, |
1342 |
0xc40ba6d0, 0xc4e22c3c}; |
1343 |
|
1344 |
// Return x^(n*2^k) modulo p(x). |
1345 |
local crc_t x2nmodp(size_t n, unsigned k) { |
1346 |
crc_t p = (crc_t)1 << 31; // x^0 == 1 |
1347 |
while (n) { |
1348 |
if (n & 1) |
1349 |
p = multmodp(x2n_table[k & 31], p); |
1350 |
n >>= 1; |
1351 |
k++; |
1352 |
} |
1353 |
return p; |
1277 |
} |
1354 |
} |
1278 |
|
1355 |
|
|
|
1356 |
// This uses the pre-computed g.shift value most of the time. Only the last |
1357 |
// combination requires a new x2nmodp() calculation. |
1279 |
local unsigned long crc32_comb(unsigned long crc1, unsigned long crc2, |
1358 |
local unsigned long crc32_comb(unsigned long crc1, unsigned long crc2, |
1280 |
size_t len2) { |
1359 |
size_t len2) { |
1281 |
int n; |
1360 |
return multmodp(len2 == g.block ? g.shift : x2nmodp(len2, 3), crc1) ^ crc2; |
1282 |
unsigned long row; |
|
|
1283 |
unsigned long even[32]; // even-power-of-two zeros operator |
1284 |
unsigned long odd[32]; // odd-power-of-two zeros operator |
1285 |
|
1286 |
// degenerate case |
1287 |
if (len2 == 0) |
1288 |
return crc1; |
1289 |
|
1290 |
// put operator for one zero bit in odd |
1291 |
odd[0] = 0xedb88320UL; // CRC-32 polynomial |
1292 |
row = 1; |
1293 |
for (n = 1; n < 32; n++) { |
1294 |
odd[n] = row; |
1295 |
row <<= 1; |
1296 |
} |
1297 |
|
1298 |
// put operator for two zero bits in even |
1299 |
gf2_matrix_square(even, odd); |
1300 |
|
1301 |
// put operator for four zero bits in odd |
1302 |
gf2_matrix_square(odd, even); |
1303 |
|
1304 |
// apply len2 zeros to crc1 (first square will put the operator for one |
1305 |
// zero byte, eight zero bits, in even) |
1306 |
do { |
1307 |
// apply zeros operator for this bit of len2 |
1308 |
gf2_matrix_square(even, odd); |
1309 |
if (len2 & 1) |
1310 |
crc1 = gf2_matrix_times(even, crc1); |
1311 |
len2 >>= 1; |
1312 |
|
1313 |
// if no more bits set, then done |
1314 |
if (len2 == 0) |
1315 |
break; |
1316 |
|
1317 |
// another iteration of the loop with odd and even swapped |
1318 |
gf2_matrix_square(odd, even); |
1319 |
if (len2 & 1) |
1320 |
crc1 = gf2_matrix_times(odd, crc1); |
1321 |
len2 >>= 1; |
1322 |
|
1323 |
// if no more bits set, then done |
1324 |
} while (len2 != 0); |
1325 |
|
1326 |
// return combined crc |
1327 |
crc1 ^= crc2; |
1328 |
return crc1; |
1329 |
} |
1361 |
} |
1330 |
|
1362 |
|
1331 |
#define BASE 65521U // largest prime smaller than 65536 |
1363 |
#define BASE 65521U // largest prime smaller than 65536 |
Lines 1403-1411
local struct space *get_space(struct pool *pool) {
Link Here
|
1403 |
// if a space is available, pull it from the list and return it |
1435 |
// if a space is available, pull it from the list and return it |
1404 |
if (pool->head != NULL) { |
1436 |
if (pool->head != NULL) { |
1405 |
space = pool->head; |
1437 |
space = pool->head; |
1406 |
possess(space->use); |
|
|
1407 |
pool->head = space->next; |
1438 |
pool->head = space->next; |
1408 |
twist(pool->have, BY, -1); // one less in pool |
1439 |
twist(pool->have, BY, -1); // one less in pool |
|
|
1440 |
possess(space->use); |
1409 |
twist(space->use, TO, 1); // initially one user |
1441 |
twist(space->use, TO, 1); // initially one user |
1410 |
space->len = 0; |
1442 |
space->len = 0; |
1411 |
return space; |
1443 |
return space; |
Lines 1443-1449
local void grow_space(struct space *space) {
Link Here
|
1443 |
// Increment the use count to require one more drop before returning this space |
1475 |
// Increment the use count to require one more drop before returning this space |
1444 |
// to the pool. |
1476 |
// to the pool. |
1445 |
local void use_space(struct space *space) { |
1477 |
local void use_space(struct space *space) { |
|
|
1478 |
long use; |
1479 |
|
1446 |
possess(space->use); |
1480 |
possess(space->use); |
|
|
1481 |
use = peek_lock(space->use); |
1482 |
assert(use != 0); |
1447 |
twist(space->use, BY, +1); |
1483 |
twist(space->use, BY, +1); |
1448 |
} |
1484 |
} |
1449 |
|
1485 |
|
Lines 1457-1462
local void drop_space(struct space *space) {
Link Here
|
1457 |
possess(space->use); |
1493 |
possess(space->use); |
1458 |
use = peek_lock(space->use); |
1494 |
use = peek_lock(space->use); |
1459 |
assert(use != 0); |
1495 |
assert(use != 0); |
|
|
1496 |
twist(space->use, BY, -1); |
1460 |
if (use == 1) { |
1497 |
if (use == 1) { |
1461 |
pool = space->pool; |
1498 |
pool = space->pool; |
1462 |
possess(pool->have); |
1499 |
possess(pool->have); |
Lines 1464-1470
local void drop_space(struct space *space) {
Link Here
|
1464 |
pool->head = space; |
1501 |
pool->head = space; |
1465 |
twist(pool->have, BY, +1); |
1502 |
twist(pool->have, BY, +1); |
1466 |
} |
1503 |
} |
1467 |
twist(space->use, BY, -1); |
|
|
1468 |
} |
1504 |
} |
1469 |
|
1505 |
|
1470 |
// Free the memory and lock resources of a pool. Return number of spaces for |
1506 |
// Free the memory and lock resources of a pool. Return number of spaces for |
Lines 1926-1931
local void write_thread(void *dummy) {
Link Here
|
1926 |
wait_for(job->calc, TO_BE, 1); |
1962 |
wait_for(job->calc, TO_BE, 1); |
1927 |
release(job->calc); |
1963 |
release(job->calc); |
1928 |
check = COMB(check, job->check, len); |
1964 |
check = COMB(check, job->check, len); |
|
|
1965 |
Trace(("-- combined #%ld%s", seq, more ? "" : " (last)")); |
1929 |
|
1966 |
|
1930 |
// free the job |
1967 |
// free the job |
1931 |
free_lock(job->calc); |
1968 |
free_lock(job->calc); |
Lines 2362-2371
local void single_compress(int reset) {
Link Here
|
2362 |
} |
2399 |
} |
2363 |
} |
2400 |
} |
2364 |
else |
2401 |
else |
2365 |
#else |
|
|
2366 |
{ |
2367 |
DEFLATE_WRITE(Z_SYNC_FLUSH); |
2402 |
DEFLATE_WRITE(Z_SYNC_FLUSH); |
2368 |
} |
2403 |
#else |
|
|
2404 |
DEFLATE_WRITE(Z_SYNC_FLUSH); |
2369 |
#endif |
2405 |
#endif |
2370 |
if (!g.setdict) // two markers when independent |
2406 |
if (!g.setdict) // two markers when independent |
2371 |
DEFLATE_WRITE(Z_FULL_FLUSH); |
2407 |
DEFLATE_WRITE(Z_FULL_FLUSH); |
Lines 2545-2551
local size_t load(void) {
Link Here
|
2545 |
} |
2581 |
} |
2546 |
|
2582 |
|
2547 |
// Terminate the load() operation. Empty buffer, mark end, close file (if not |
2583 |
// Terminate the load() operation. Empty buffer, mark end, close file (if not |
2548 |
// stdin), and free the name obtained from the header, if any. |
2584 |
// stdin), and free the name and comment obtained from the header, if present. |
2549 |
local void load_end(void) { |
2585 |
local void load_end(void) { |
2550 |
#ifndef NOTHREAD |
2586 |
#ifndef NOTHREAD |
2551 |
// if the read thread is running, then end it |
2587 |
// if the read thread is running, then end it |
Lines 2568-2573
local void load_end(void) {
Link Here
|
2568 |
if (g.ind != 0) |
2604 |
if (g.ind != 0) |
2569 |
close(g.ind); |
2605 |
close(g.ind); |
2570 |
RELEASE(g.hname); |
2606 |
RELEASE(g.hname); |
|
|
2607 |
RELEASE(g.hcomm); |
2571 |
} |
2608 |
} |
2572 |
|
2609 |
|
2573 |
// Initialize for reading new input. |
2610 |
// Initialize for reading new input. |
Lines 2584-2590
local void in_init(void) {
Link Here
|
2584 |
// Buffered reading macros for decompression and listing. |
2621 |
// Buffered reading macros for decompression and listing. |
2585 |
#define GET() (g.in_left == 0 && (g.in_eof || load() == 0) ? 0 : \ |
2622 |
#define GET() (g.in_left == 0 && (g.in_eof || load() == 0) ? 0 : \ |
2586 |
(g.in_left--, *g.in_next++)) |
2623 |
(g.in_left--, *g.in_next++)) |
2587 |
#define UNGET(n) (g.in_left += (n), g.in_next -= (n)) |
|
|
2588 |
#define GET2() (tmp2 = GET(), tmp2 + ((unsigned)(GET()) << 8)) |
2624 |
#define GET2() (tmp2 = GET(), tmp2 + ((unsigned)(GET()) << 8)) |
2589 |
#define GET4() (tmp4 = GET2(), tmp4 + ((unsigned long)(GET2()) << 16)) |
2625 |
#define GET4() (tmp4 = GET2(), tmp4 + ((unsigned long)(GET2()) << 16)) |
2590 |
#define SKIP(dist) \ |
2626 |
#define SKIP(dist) \ |
Lines 2618-2623
local void in_init(void) {
Link Here
|
2618 |
g.in_next += togo; \ |
2654 |
g.in_next += togo; \ |
2619 |
} while (0) |
2655 |
} while (0) |
2620 |
|
2656 |
|
|
|
2657 |
// Get a zero-terminated string into allocated memory, with crc update. |
2658 |
#define GETZC(str) \ |
2659 |
do { \ |
2660 |
unsigned char *end; \ |
2661 |
size_t copy, have, size = 0; \ |
2662 |
have = 0; \ |
2663 |
do { \ |
2664 |
if (g.in_left == 0 && load() == 0) \ |
2665 |
return -3; \ |
2666 |
end = memchr(g.in_next, 0, g.in_left); \ |
2667 |
copy = end == NULL ? g.in_left : (size_t)(end - g.in_next) + 1; \ |
2668 |
have = vmemcpy(&str, &size, have, g.in_next, copy); \ |
2669 |
g.in_left -= copy; \ |
2670 |
g.in_next += copy; \ |
2671 |
} while (end == NULL); \ |
2672 |
crc = crc32z(crc, (unsigned char *)str, have); \ |
2673 |
} while (0) |
2674 |
|
2621 |
// Pull LSB order or MSB order integers from an unsigned char buffer. |
2675 |
// Pull LSB order or MSB order integers from an unsigned char buffer. |
2622 |
#define PULL2L(p) ((p)[0] + ((unsigned)((p)[1]) << 8)) |
2676 |
#define PULL2L(p) ((p)[0] + ((unsigned)((p)[1]) << 8)) |
2623 |
#define PULL4L(p) (PULL2L(p) + ((unsigned long)(PULL2L((p) + 2)) << 16)) |
2677 |
#define PULL4L(p) (PULL2L(p) + ((unsigned long)(PULL2L((p) + 2)) << 16)) |
Lines 2663-2668
local int read_extra(unsigned len, int save) {
Link Here
|
2663 |
len -= size; |
2717 |
len -= size; |
2664 |
if (id == 0x0001) { |
2718 |
if (id == 0x0001) { |
2665 |
// Zip64 Extended Information Extra Field |
2719 |
// Zip64 Extended Information Extra Field |
|
|
2720 |
g.zip64 = 1; |
2666 |
if (g.zip_ulen == LOW32 && size >= 8) { |
2721 |
if (g.zip_ulen == LOW32 && size >= 8) { |
2667 |
g.zip_ulen = GET4(); |
2722 |
g.zip_ulen = GET4(); |
2668 |
SKIP(4); |
2723 |
SKIP(4); |
Lines 2720-2745
local int get_header(int save) {
Link Here
|
2720 |
if (save) { |
2775 |
if (save) { |
2721 |
g.stamp = 0; |
2776 |
g.stamp = 0; |
2722 |
RELEASE(g.hname); |
2777 |
RELEASE(g.hname); |
|
|
2778 |
RELEASE(g.hcomm); |
2723 |
} |
2779 |
} |
2724 |
|
2780 |
|
2725 |
// see if it's a gzip, zlib, or lzw file |
2781 |
// see if it's a gzip, zlib, or lzw file |
2726 |
g.form = -1; |
|
|
2727 |
g.magic1 = GET(); |
2782 |
g.magic1 = GET(); |
2728 |
if (g.in_eof) |
2783 |
if (g.in_eof) { |
|
|
2784 |
g.magic1 = -1; |
2729 |
return -1; |
2785 |
return -1; |
|
|
2786 |
} |
2730 |
magic = (unsigned)g.magic1 << 8; |
2787 |
magic = (unsigned)g.magic1 << 8; |
2731 |
magic += GET(); |
2788 |
magic += GET(); |
2732 |
if (g.in_eof) { |
2789 |
if (g.in_eof) |
2733 |
UNGET(1); |
|
|
2734 |
return -2; |
2790 |
return -2; |
2735 |
} |
|
|
2736 |
if (magic % 31 == 0 && (magic & 0x8f20) == 0x0800) { |
2791 |
if (magic % 31 == 0 && (magic & 0x8f20) == 0x0800) { |
2737 |
// it's zlib |
2792 |
// it's zlib |
2738 |
g.form = 1; |
2793 |
g.form = 1; |
2739 |
return 8; |
2794 |
return 8; |
2740 |
} |
2795 |
} |
2741 |
if (magic == 0x1f9d) // it's lzw |
2796 |
if (magic == 0x1f9d) { // it's lzw |
|
|
2797 |
g.form = -1; |
2742 |
return 257; |
2798 |
return 257; |
|
|
2799 |
} |
2743 |
if (magic == 0x504b) { // it's zip |
2800 |
if (magic == 0x504b) { // it's zip |
2744 |
magic = GET2(); // the rest of the signature |
2801 |
magic = GET2(); // the rest of the signature |
2745 |
if (g.in_eof) |
2802 |
if (g.in_eof) |
Lines 2748-2756
local int get_header(int save) {
Link Here
|
2748 |
return -5; // central header or archive extra |
2805 |
return -5; // central header or archive extra |
2749 |
if (magic != 0x0403) |
2806 |
if (magic != 0x0403) |
2750 |
return -4; // not a local header |
2807 |
return -4; // not a local header |
|
|
2808 |
g.zip64 = 0; |
2751 |
SKIP(2); |
2809 |
SKIP(2); |
2752 |
flags = GET2(); |
2810 |
flags = GET2(); |
2753 |
if (flags & 0xfff0) |
2811 |
if (flags & 0xf7f0) |
2754 |
return -4; |
2812 |
return -4; |
2755 |
method = GET(); // return low byte of method or 256 |
2813 |
method = GET(); // return low byte of method or 256 |
2756 |
if (GET() != 0 || flags & 1) |
2814 |
if (GET() != 0 || flags & 1) |
Lines 2790-2796
local int get_header(int save) {
Link Here
|
2790 |
return g.in_eof ? -3 : (int)method; |
2848 |
return g.in_eof ? -3 : (int)method; |
2791 |
} |
2849 |
} |
2792 |
if (magic != 0x1f8b) { // not gzip |
2850 |
if (magic != 0x1f8b) { // not gzip |
2793 |
UNGET(2); |
2851 |
g.in_left++; // return the second byte |
|
|
2852 |
g.in_next--; |
2794 |
return -2; |
2853 |
return -2; |
2795 |
} |
2854 |
} |
2796 |
|
2855 |
|
Lines 2815-2843
local int get_header(int save) {
Link Here
|
2815 |
SKIPC(GET2C()); |
2874 |
SKIPC(GET2C()); |
2816 |
|
2875 |
|
2817 |
// read file name, if present, into allocated memory |
2876 |
// read file name, if present, into allocated memory |
2818 |
if ((flags & 8) && save) { |
2877 |
if (flags & 8) { |
2819 |
unsigned char *end; |
2878 |
if (save) |
2820 |
size_t copy, have, size = 0; |
2879 |
GETZC(g.hname); |
2821 |
have = 0; |
2880 |
else |
2822 |
do { |
2881 |
while (GETC() != 0) |
2823 |
if (g.in_left == 0 && load() == 0) |
2882 |
; |
2824 |
return -3; |
|
|
2825 |
end = memchr(g.in_next, 0, g.in_left); |
2826 |
copy = end == NULL ? g.in_left : (size_t)(end - g.in_next) + 1; |
2827 |
have = vmemcpy(&g.hname, &size, have, g.in_next, copy); |
2828 |
g.in_left -= copy; |
2829 |
g.in_next += copy; |
2830 |
} while (end == NULL); |
2831 |
crc = crc32z(crc, (unsigned char *)g.hname, have); |
2832 |
} |
2883 |
} |
2833 |
else if (flags & 8) |
|
|
2834 |
while (GETC() != 0) |
2835 |
; |
2836 |
|
2884 |
|
2837 |
// skip comment |
2885 |
// read comment, if present, into allocated memory |
2838 |
if (flags & 16) |
2886 |
if (flags & 16) { |
2839 |
while (GETC() != 0) |
2887 |
if (save) |
2840 |
; |
2888 |
GETZC(g.hcomm); |
|
|
2889 |
else |
2890 |
while (GETC() != 0) |
2891 |
; |
2892 |
} |
2841 |
|
2893 |
|
2842 |
// check header crc |
2894 |
// check header crc |
2843 |
if ((flags & 2) && GET2() != (crc & 0xffff)) |
2895 |
if ((flags & 2) && GET2() != (crc & 0xffff)) |
Lines 2848-2853
local int get_header(int save) {
Link Here
|
2848 |
return g.in_eof ? -3 : (int)method; |
2900 |
return g.in_eof ? -3 : (int)method; |
2849 |
} |
2901 |
} |
2850 |
|
2902 |
|
|
|
2903 |
// Process the remainder of a zip file after the first entry. Return true if |
2904 |
// the next signature is another local file header. If listing verbosely, then |
2905 |
// search the remainder of the zip file for the central file header |
2906 |
// corresponding to the first zip entry, and save the file comment, if any. |
2907 |
local int more_zip_entries(void) { |
2908 |
unsigned long sig; |
2909 |
int ret, n; |
2910 |
unsigned char *first; |
2911 |
unsigned tmp2; // for macro |
2912 |
unsigned long tmp4; // for macro |
2913 |
unsigned char const central[] = {0x50, 0x4b, 1, 2}; |
2914 |
|
2915 |
sig = GET4(); |
2916 |
ret = !g.in_eof && sig == 0x04034b50; // true if another entry follows |
2917 |
if (!g.list || g.verbosity < 2) |
2918 |
return ret; |
2919 |
|
2920 |
// if it was a central file header signature, then already four bytes |
2921 |
// into a central directory header -- otherwise search for the next one |
2922 |
n = sig == 0x02014b50 ? 4 : 0; // number of bytes into central header |
2923 |
for (;;) { |
2924 |
// assure that more input is available |
2925 |
if (g.in_left == 0 && load() == 0) // never found it! |
2926 |
return ret; |
2927 |
if (n == 0) { |
2928 |
// look for first byte in central signature |
2929 |
first = memchr(g.in_next, central[0], g.in_left); |
2930 |
if (first == NULL) { |
2931 |
// not found -- go get the next buffer and keep looking |
2932 |
g.in_left = 0; |
2933 |
} |
2934 |
else { |
2935 |
// found -- continue search at next byte |
2936 |
n++; |
2937 |
g.in_left -= first - g.in_next + 1; |
2938 |
g.in_next = first + 1; |
2939 |
} |
2940 |
} |
2941 |
else if (n < 4) { |
2942 |
// look for the remaining bytes in the central signature |
2943 |
if (g.in_next[0] == central[n]) { |
2944 |
n++; |
2945 |
g.in_next++; |
2946 |
g.in_left--; |
2947 |
} |
2948 |
else |
2949 |
n = 0; // mismatch -- restart search with this byte |
2950 |
} |
2951 |
else { |
2952 |
// Now in a suspected central file header, just past the signature. |
2953 |
// Read the rest of the fixed-length portion of the header. |
2954 |
unsigned char head[CEN]; |
2955 |
size_t need = CEN, part = 0, len, i; |
2956 |
|
2957 |
if (need > g.in_left) { // will only need to do this once |
2958 |
part = g.in_left; |
2959 |
memcpy(head + CEN - need, g.in_next, part); |
2960 |
need -= part; |
2961 |
g.in_left = 0; |
2962 |
if (load() == 0) // never found it! |
2963 |
return ret; |
2964 |
} |
2965 |
memcpy(head + CEN - need, g.in_next, need); |
2966 |
|
2967 |
// Determine to sufficient probability that this is the droid we're |
2968 |
// looking for, by checking the CRC and the local header offset. |
2969 |
if (PULL4L(head + 12) == g.out_check && PULL4L(head + 38) == 0) { |
2970 |
// Update the number of bytes consumed from the current buffer. |
2971 |
g.in_next += need; |
2972 |
g.in_left -= need; |
2973 |
|
2974 |
// Get the comment length. |
2975 |
len = PULL2L(head + 28); |
2976 |
if (len == 0) // no comment |
2977 |
return ret; |
2978 |
|
2979 |
// Skip the file name and extra field. |
2980 |
SKIP(PULL2L(head + 24) + (unsigned long)PULL2L(head + 26)); |
2981 |
|
2982 |
// Save the comment field. |
2983 |
need = len; |
2984 |
g.hcomm = alloc(NULL, len + 1); |
2985 |
while (need > g.in_left) { |
2986 |
memcpy(g.hcomm + len - need, g.in_next, g.in_left); |
2987 |
need -= g.in_left; |
2988 |
g.in_left = 0; |
2989 |
if (load() == 0) { // premature EOF |
2990 |
RELEASE(g.hcomm); |
2991 |
return ret; |
2992 |
} |
2993 |
} |
2994 |
memcpy(g.hcomm + len - need, g.in_next, need); |
2995 |
g.in_next += need; |
2996 |
g.in_left -= need; |
2997 |
for (i = 0; i < len; i++) |
2998 |
if (g.hcomm[i] == 0) |
2999 |
g.hcomm[i] = ' '; |
3000 |
g.hcomm[len] = 0; |
3001 |
return ret; |
3002 |
} |
3003 |
else { |
3004 |
// Nope, false alarm. Restart the search at the first byte |
3005 |
// after what we thought was the central file header signature. |
3006 |
if (part) { |
3007 |
// Move buffer data up and insert the part of the header |
3008 |
// data read from the previous buffer. |
3009 |
memmove(g.in_next + part, g.in_next, g.in_left); |
3010 |
memcpy(g.in_next, head, part); |
3011 |
g.in_left += part; |
3012 |
} |
3013 |
n = 0; |
3014 |
} |
3015 |
} |
3016 |
} |
3017 |
} |
3018 |
|
2851 |
// --- list contents of compressed input (gzip, zlib, or lzw) --- |
3019 |
// --- list contents of compressed input (gzip, zlib, or lzw) --- |
2852 |
|
3020 |
|
2853 |
// Find standard compressed file suffix, return length of suffix. |
3021 |
// Find standard compressed file suffix, return length of suffix. |
Lines 2882-2888
local size_t compressed_suffix(char *nm) {
Link Here
|
2882 |
#define NAMEMAX1 48 // name display limit at verbosity 1 |
3050 |
#define NAMEMAX1 48 // name display limit at verbosity 1 |
2883 |
#define NAMEMAX2 16 // name display limit at verbosity 2 |
3051 |
#define NAMEMAX2 16 // name display limit at verbosity 2 |
2884 |
|
3052 |
|
2885 |
// Print gzip or lzw file information. |
3053 |
// Print gzip, lzw, zlib, or zip file information. |
2886 |
local void show_info(int method, unsigned long check, length_t len, int cont) { |
3054 |
local void show_info(int method, unsigned long check, length_t len, int cont) { |
2887 |
size_t max; // maximum name length for current verbosity |
3055 |
size_t max; // maximum name length for current verbosity |
2888 |
size_t n; // name length without suffix |
3056 |
size_t n; // name length without suffix |
Lines 2961-2966
local void show_info(int method, unsigned long check, length_t len, int cont) {
Link Here
|
2961 |
g.in_tot, len, red, tag); |
3129 |
g.in_tot, len, red, tag); |
2962 |
#endif |
3130 |
#endif |
2963 |
} |
3131 |
} |
|
|
3132 |
if (g.verbosity > 1 && g.hcomm != NULL) |
3133 |
puts(g.hcomm); |
2964 |
} |
3134 |
} |
2965 |
|
3135 |
|
2966 |
// List content information about the gzip file at ind (only works if the gzip |
3136 |
// List content information about the gzip file at ind (only works if the gzip |
Lines 2994-2999
local void list_info(void) {
Link Here
|
2994 |
|
3164 |
|
2995 |
// list zip file |
3165 |
// list zip file |
2996 |
if (g.form > 1) { |
3166 |
if (g.form > 1) { |
|
|
3167 |
more_zip_entries(); // get first entry comment, if any |
2997 |
g.in_tot = g.zip_clen; |
3168 |
g.in_tot = g.zip_clen; |
2998 |
show_info(method, g.zip_crc, g.zip_ulen, 0); |
3169 |
show_info(method, g.zip_crc, g.zip_ulen, 0); |
2999 |
return; |
3170 |
return; |
Lines 3087-3092
local void list_info(void) {
Link Here
|
3087 |
// --- copy input to output (when acting like cat) --- |
3258 |
// --- copy input to output (when acting like cat) --- |
3088 |
|
3259 |
|
3089 |
local void cat(void) { |
3260 |
local void cat(void) { |
|
|
3261 |
// copy the first header byte read, if any |
3262 |
if (g.magic1 != -1) { |
3263 |
unsigned char buf[1] = {g.magic1}; |
3264 |
g.out_tot += writen(g.outd, buf, 1); |
3265 |
} |
3266 |
|
3090 |
// copy the remainder of the input to the output |
3267 |
// copy the remainder of the input to the output |
3091 |
while (g.in_left) { |
3268 |
while (g.in_left) { |
3092 |
g.out_tot += writen(g.outd, g.in_next, g.in_left); |
3269 |
g.out_tot += writen(g.outd, g.in_next, g.in_left); |
Lines 3177-3182
local void outb_check(void *dummy) {
Link Here
|
3177 |
// write and check threads and return for more decompression while that's going |
3354 |
// write and check threads and return for more decompression while that's going |
3178 |
// on (or just write and check if no threads or if proc == 1). |
3355 |
// on (or just write and check if no threads or if proc == 1). |
3179 |
local int outb(void *desc, unsigned char *buf, unsigned len) { |
3356 |
local int outb(void *desc, unsigned char *buf, unsigned len) { |
|
|
3357 |
(void)desc; |
3358 |
|
3180 |
#ifndef NOTHREAD |
3359 |
#ifndef NOTHREAD |
3181 |
static thread *wr, *ch; |
3360 |
static thread *wr, *ch; |
3182 |
|
3361 |
|
Lines 3205-3218
local int outb(void *desc, unsigned char *buf, unsigned len) {
Link Here
|
3205 |
// if requested with len == 0, clean up -- terminate and join write and |
3384 |
// if requested with len == 0, clean up -- terminate and join write and |
3206 |
// check threads, free lock |
3385 |
// check threads, free lock |
3207 |
if (len == 0 && outb_write_more != NULL) { |
3386 |
if (len == 0 && outb_write_more != NULL) { |
3208 |
if (desc != NULL) { |
3387 |
join(ch); |
3209 |
destruct(ch); |
3388 |
join(wr); |
3210 |
destruct(wr); |
|
|
3211 |
} |
3212 |
else { |
3213 |
join(ch); |
3214 |
join(wr); |
3215 |
} |
3216 |
free_lock(outb_check_more); |
3389 |
free_lock(outb_check_more); |
3217 |
free_lock(outb_write_more); |
3390 |
free_lock(outb_write_more); |
3218 |
outb_write_more = NULL; |
3391 |
outb_write_more = NULL; |
Lines 3225-3232
local int outb(void *desc, unsigned char *buf, unsigned len) {
Link Here
|
3225 |
} |
3398 |
} |
3226 |
#endif |
3399 |
#endif |
3227 |
|
3400 |
|
3228 |
(void)desc; |
|
|
3229 |
|
3230 |
// if just one process or no threads, then do it without threads |
3401 |
// if just one process or no threads, then do it without threads |
3231 |
if (len) { |
3402 |
if (len) { |
3232 |
if (g.decode == 1) |
3403 |
if (g.decode == 1) |
Lines 3237-3255
local int outb(void *desc, unsigned char *buf, unsigned len) {
Link Here
|
3237 |
return 0; |
3408 |
return 0; |
3238 |
} |
3409 |
} |
3239 |
|
3410 |
|
|
|
3411 |
// Zip file data descriptor signature. This signature may or may not precede |
3412 |
// the CRC and lengths, with either resulting in a valid zip file! There is |
3413 |
// some odd code below that tries to detect and accommodate both cases. |
3414 |
#define SIG 0x08074b50 |
3415 |
|
3240 |
// Inflate for decompression or testing. Decompress from ind to outd unless |
3416 |
// Inflate for decompression or testing. Decompress from ind to outd unless |
3241 |
// decode != 1, in which case just test ind, and then also list if list != 0; |
3417 |
// decode != 1, in which case just test ind, and then also list if list != 0; |
3242 |
// look for and decode multiple, concatenated gzip and/or zlib streams; read |
3418 |
// look for and decode multiple, concatenated gzip and/or zlib streams; read |
3243 |
// and check the gzip, zlib, or zip trailer. |
3419 |
// and check the gzip, zlib, or zip trailer. |
3244 |
local void infchk(void) { |
3420 |
local void infchk(void) { |
3245 |
int ret, cont, was; |
3421 |
int ret, cont, more; |
3246 |
unsigned long check, len; |
3422 |
unsigned long check, len; |
3247 |
z_stream strm; |
3423 |
z_stream strm; |
3248 |
unsigned tmp2; |
3424 |
unsigned tmp2; |
3249 |
unsigned long tmp4; |
3425 |
unsigned long tmp4; |
3250 |
length_t clen; |
3426 |
length_t clen; |
3251 |
|
3427 |
|
3252 |
cont = 0; |
3428 |
cont = more = 0; |
3253 |
do { |
3429 |
do { |
3254 |
// header already read -- set up for decompression |
3430 |
// header already read -- set up for decompression |
3255 |
g.in_tot = g.in_left; // track compressed data length |
3431 |
g.in_tot = g.in_left; // track compressed data length |
Lines 3286-3321
local void infchk(void) {
Link Here
|
3286 |
// read and check trailer |
3462 |
// read and check trailer |
3287 |
if (g.form > 1) { // zip local trailer (if any) |
3463 |
if (g.form > 1) { // zip local trailer (if any) |
3288 |
if (g.form == 3) { // data descriptor follows |
3464 |
if (g.form == 3) { // data descriptor follows |
3289 |
// read original version of data descriptor |
3465 |
// get data descriptor values, assuming no signature |
3290 |
g.zip_crc = GET4(); |
3466 |
g.zip_crc = GET4(); |
3291 |
g.zip_clen = GET4(); |
3467 |
g.zip_clen = GET4(); |
3292 |
g.zip_ulen = GET4(); |
3468 |
g.zip_ulen = GET4(); // ZIP64 -> high clen, not ulen |
3293 |
if (g.in_eof) |
3469 |
|
3294 |
throw(EDOM, "%s: corrupted entry -- missing trailer", |
3470 |
// deduce whether or not a signature precedes the values |
3295 |
g.inf); |
3471 |
if (g.zip_crc == SIG && // might be the signature |
3296 |
|
3472 |
// if the expected CRC is not SIG, then it's a signature |
3297 |
// if crc doesn't match, try info-zip variant with sig |
3473 |
(g.out_check != SIG || // assume signature |
3298 |
if (g.zip_crc != g.out_check) { |
3474 |
// now we're in a very rare case where CRC == SIG -- the |
3299 |
if (g.zip_crc != 0x08074b50UL || g.zip_clen != g.out_check) |
3475 |
// first four bytes could be the signature or the CRC |
3300 |
throw(EDOM, "%s: corrupted entry -- crc32 mismatch", |
3476 |
(g.zip_clen == SIG && // if not, then no signature |
3301 |
g.inf); |
3477 |
// now we have the first two words are SIG and the |
3302 |
g.zip_crc = g.zip_clen; |
3478 |
// expected CRC is SIG, so it could be a signature and |
3303 |
g.zip_clen = g.zip_ulen; |
3479 |
// the CRC, or it could be the CRC and a compressed |
3304 |
g.zip_ulen = GET4(); |
3480 |
// length that is *also* SIG (!) -- so check the low 32 |
3305 |
} |
3481 |
// bits of the expected compressed length for SIG |
3306 |
|
3482 |
((clen & LOW32) != SIG || // assume signature and CRC |
3307 |
// handle incredibly rare cases where crc equals signature |
3483 |
// now the expected CRC *and* the expected low 32 bits |
3308 |
else if (g.zip_crc == 0x08074b50UL && |
3484 |
// of the compressed length are SIG -- this is so |
3309 |
g.zip_clen == g.zip_crc && |
3485 |
// incredibly unlikely, clearly someone is messing with |
3310 |
((clen & LOW32) != g.zip_crc || |
3486 |
// us, but we continue ... if the next four bytes are |
3311 |
g.zip_ulen == g.zip_crc)) { |
3487 |
// not SIG, then there is not a signature -- check those |
|
|
3488 |
// bytes, currently in g.zip_ulen: |
3489 |
(g.zip_ulen == SIG && // if not, then no signature |
3490 |
// we have three SIGs in a row in the descriptor, and |
3491 |
// both the expected CRC and the expected clen are SIG |
3492 |
// -- the first one is a signature if we don't expect |
3493 |
// the third word to be SIG, which is either the low 32 |
3494 |
// bits of ulen, or if ZIP64, the high 32 bits of clen: |
3495 |
(g.zip64 ? clen >> 32 : g.out_tot) != SIG |
3496 |
// if that last compare was equal, then the expected |
3497 |
// values for the CRC, the low 32 bits of clen, *and* |
3498 |
// the low 32 bits of ulen are all SIG (!!), or in the |
3499 |
// case of ZIP64, even crazier, the CRC and *both* |
3500 |
// 32-bit halves of clen are all SIG (clen > 500 |
3501 |
// petabytes!!!) ... we can no longer discriminate the |
3502 |
// hypotheses, so we will assume no signature |
3503 |
))))) { |
3504 |
// first four bytes were actually the descriptor -- shift |
3505 |
// the values down and get another four bytes |
3312 |
g.zip_crc = g.zip_clen; |
3506 |
g.zip_crc = g.zip_clen; |
3313 |
g.zip_clen = g.zip_ulen; |
3507 |
g.zip_clen = g.zip_ulen; |
3314 |
g.zip_ulen = GET4(); |
3508 |
g.zip_ulen = GET4(); |
3315 |
} |
3509 |
} |
3316 |
|
3510 |
|
3317 |
// if second length doesn't match, try 64-bit lengths |
3511 |
// if ZIP64, then ulen is really the high word of clen -- get |
3318 |
if (g.zip_ulen != (g.out_tot & LOW32)) { |
3512 |
// the actual ulen and skip its high word as well (we only |
|
|
3513 |
// compare the low 32 bits of the lengths to verify) |
3514 |
if (g.zip64) { |
3319 |
g.zip_ulen = GET4(); |
3515 |
g.zip_ulen = GET4(); |
3320 |
(void)GET4(); |
3516 |
(void)GET4(); |
3321 |
} |
3517 |
} |
Lines 3323-3333
local void infchk(void) {
Link Here
|
3323 |
throw(EDOM, "%s: corrupted entry -- missing trailer", |
3519 |
throw(EDOM, "%s: corrupted entry -- missing trailer", |
3324 |
g.inf); |
3520 |
g.inf); |
3325 |
} |
3521 |
} |
|
|
3522 |
check = g.zip_crc; |
3523 |
if (check != g.out_check) |
3524 |
throw(EDOM, "%s: corrupted entry -- crc32 mismatch", g.inf); |
3326 |
if (g.zip_clen != (clen & LOW32) || |
3525 |
if (g.zip_clen != (clen & LOW32) || |
3327 |
g.zip_ulen != (g.out_tot & LOW32)) |
3526 |
g.zip_ulen != (g.out_tot & LOW32)) |
3328 |
throw(EDOM, "%s: corrupted entry -- length mismatch", |
3527 |
throw(EDOM, "%s: corrupted entry -- length mismatch", |
3329 |
g.inf); |
3528 |
g.inf); |
3330 |
check = g.zip_crc; |
3529 |
more = more_zip_entries(); // see if more entries, get comment |
3331 |
} |
3530 |
} |
3332 |
else if (g.form == 1) { // zlib (big-endian) trailer |
3531 |
else if (g.form == 1) { // zlib (big-endian) trailer |
3333 |
check = (unsigned long)(GET()) << 24; |
3532 |
check = (unsigned long)(GET()) << 24; |
Lines 3359-3374
local void infchk(void) {
Link Here
|
3359 |
|
3558 |
|
3360 |
// if a gzip entry follows a gzip entry, decompress it (don't replace |
3559 |
// if a gzip entry follows a gzip entry, decompress it (don't replace |
3361 |
// saved header information from first entry) |
3560 |
// saved header information from first entry) |
3362 |
was = g.form; |
3561 |
} while (g.form == 0 && (ret = get_header(0)) == 8); |
3363 |
} while (was == 0 && (ret = get_header(0)) == 8 && g.form == 0); |
|
|
3364 |
|
3562 |
|
3365 |
// gzip -cdf copies junk after gzip stream directly to output |
3563 |
// gzip -cdf copies junk after gzip stream directly to output |
3366 |
if (was == 0 && ret == -2 && g.force && g.pipeout && g.decode != 2 && |
3564 |
if (g.form == 0 && ret == -2 && g.force && g.pipeout && g.decode != 2 && |
3367 |
!g.list) |
3565 |
!g.list) |
3368 |
cat(); |
3566 |
cat(); |
3369 |
else if (was > 1 && get_header(0) != -5) |
3567 |
|
|
|
3568 |
// check for more entries in zip file |
3569 |
else if (more) |
3370 |
complain("warning: %s: entries after the first were ignored", g.inf); |
3570 |
complain("warning: %s: entries after the first were ignored", g.inf); |
3371 |
else if ((was == 0 && ret != -1) || (was == 1 && (GET(), !g.in_eof))) |
3571 |
|
|
|
3572 |
// check for non-gzip after gzip stream, or anything after zlib stream |
3573 |
else if ((g.verbosity > 1 && g.form == 0 && ret != -1) || |
3574 |
(g.form == 1 && (GET(), !g.in_eof))) |
3372 |
complain("warning: %s: trailing junk was ignored", g.inf); |
3575 |
complain("warning: %s: trailing junk was ignored", g.inf); |
3373 |
} |
3576 |
} |
3374 |
|
3577 |
|
Lines 3817-3823
local void process(char *path) {
Link Here
|
3817 |
punt(err); |
4020 |
punt(err); |
3818 |
complain("skipping: %s", err.why); |
4021 |
complain("skipping: %s", err.why); |
3819 |
drop(err); |
4022 |
drop(err); |
3820 |
outb(&g, NULL, 0); |
4023 |
outb(NULL, NULL, 0); |
3821 |
} |
4024 |
} |
3822 |
load_end(); |
4025 |
load_end(); |
3823 |
return; |
4026 |
return; |
Lines 3918-3924
local void process(char *path) {
Link Here
|
3918 |
punt(err); |
4121 |
punt(err); |
3919 |
complain("skipping: %s", err.why); |
4122 |
complain("skipping: %s", err.why); |
3920 |
drop(err); |
4123 |
drop(err); |
3921 |
outb(g.outf, NULL, 0); |
4124 |
outb(NULL, NULL, 0); |
3922 |
if (g.outd != -1 && g.outd != 1) { |
4125 |
if (g.outd != -1 && g.outd != 1) { |
3923 |
close(g.outd); |
4126 |
close(g.outd); |
3924 |
g.outd = -1; |
4127 |
g.outd = -1; |
Lines 3974-3981
local char *helptext[] = {
Link Here
|
3974 |
" -0 to -9, -11 Compression level (level 11, zopfli, is much slower)", |
4177 |
" -0 to -9, -11 Compression level (level 11, zopfli, is much slower)", |
3975 |
#endif |
4178 |
#endif |
3976 |
" --fast, --best Compression levels 1 and 9 respectively", |
4179 |
" --fast, --best Compression levels 1 and 9 respectively", |
|
|
4180 |
" -A, --alias xxx Use xxx as the name for any --zip entry from stdin", |
3977 |
" -b, --blocksize mmm Set compression block size to mmmK (default 128K)", |
4181 |
" -b, --blocksize mmm Set compression block size to mmmK (default 128K)", |
3978 |
" -c, --stdout Write all processed output to stdout (won't delete)", |
4182 |
" -c, --stdout Write all processed output to stdout (won't delete)", |
|
|
4183 |
" -C, --comment ccc Put comment ccc in the gzip or zip header", |
3979 |
" -d, --decompress Decompress the compressed input", |
4184 |
" -d, --decompress Decompress the compressed input", |
3980 |
" -f, --force Force overwrite, compress .gz, links, and to terminal", |
4185 |
" -f, --force Force overwrite, compress .gz, links, and to terminal", |
3981 |
#ifndef NOZOPFLI |
4186 |
#ifndef NOZOPFLI |
Lines 4071-4076
local void defaults(void) {
Link Here
|
4071 |
g.procs = nprocs(8); |
4276 |
g.procs = nprocs(8); |
4072 |
#endif |
4277 |
#endif |
4073 |
g.block = 131072UL; // 128K |
4278 |
g.block = 131072UL; // 128K |
|
|
4279 |
g.shift = x2nmodp(g.block, 3); |
4074 |
g.rsync = 0; // don't do rsync blocking |
4280 |
g.rsync = 0; // don't do rsync blocking |
4075 |
g.setdict = 1; // initialize dictionary each thread |
4281 |
g.setdict = 1; // initialize dictionary each thread |
4076 |
g.verbosity = 1; // normal message level |
4282 |
g.verbosity = 1; // normal message level |
Lines 4079-4084
local void defaults(void) {
Link Here
|
4079 |
// where 01 is name and 10 is time |
4285 |
// where 01 is name and 10 is time |
4080 |
g.pipeout = 0; // don't force output to stdout |
4286 |
g.pipeout = 0; // don't force output to stdout |
4081 |
g.sufx = ".gz"; // compressed file suffix |
4287 |
g.sufx = ".gz"; // compressed file suffix |
|
|
4288 |
g.comment = NULL; // no comment |
4082 |
g.decode = 0; // compress |
4289 |
g.decode = 0; // compress |
4083 |
g.list = 0; // compress |
4290 |
g.list = 0; // compress |
4084 |
g.keep = 0; // delete input file once compressed |
4291 |
g.keep = 0; // delete input file once compressed |
Lines 4090-4097
local void defaults(void) {
Link Here
|
4090 |
|
4297 |
|
4091 |
// Long options conversion to short options. |
4298 |
// Long options conversion to short options. |
4092 |
local char *longopts[][2] = { |
4299 |
local char *longopts[][2] = { |
4093 |
{"LZW", "Z"}, {"lzw", "Z"}, {"ascii", "a"}, {"best", "9"}, {"bits", "Z"}, |
4300 |
{"LZW", "Z"}, {"lzw", "Z"}, {"alias", "A"}, {"ascii", "a"}, {"best", "9"}, |
4094 |
{"blocksize", "b"}, {"decompress", "d"}, {"fast", "1"}, {"force", "f"}, |
4301 |
{"bits", "Z"}, {"blocksize", "b"}, {"decompress", "d"}, {"fast", "1"}, |
|
|
4302 |
{"force", "f"}, {"comment", "C"}, |
4095 |
#ifndef NOZOPFLI |
4303 |
#ifndef NOZOPFLI |
4096 |
{"first", "F"}, {"iterations", "I"}, {"maxsplits", "J"}, {"oneblock", "O"}, |
4304 |
{"first", "F"}, {"iterations", "I"}, {"maxsplits", "J"}, {"oneblock", "O"}, |
4097 |
#endif |
4305 |
#endif |
Lines 4136-4142
local int option(char *arg) {
Link Here
|
4136 |
|
4344 |
|
4137 |
// if no argument or dash option, check status of get |
4345 |
// if no argument or dash option, check status of get |
4138 |
if (get && (arg == NULL || *arg == '-')) { |
4346 |
if (get && (arg == NULL || *arg == '-')) { |
4139 |
bad[1] = "bpSIM"[get - 1]; |
4347 |
bad[1] = "bpSIJAC"[get - 1]; |
4140 |
throw(EINVAL, "missing parameter after %s", bad); |
4348 |
throw(EINVAL, "missing parameter after %s", bad); |
4141 |
} |
4349 |
} |
4142 |
if (arg == NULL) |
4350 |
if (arg == NULL) |
Lines 4168-4176
local int option(char *arg) {
Link Here
|
4168 |
// options until we have the parameter |
4376 |
// options until we have the parameter |
4169 |
if (get) { |
4377 |
if (get) { |
4170 |
if (get == 3) |
4378 |
if (get == 3) |
4171 |
throw(EINVAL, "invalid usage: " |
4379 |
throw(EINVAL, |
4172 |
"-s must be followed by space"); |
4380 |
"invalid usage: -S must be followed by space"); |
4173 |
break; // allow -pnnn and -bnnn, fall to parameter code |
4381 |
if (get == 7) |
|
|
4382 |
throw(EINVAL, |
4383 |
"invalid usage: -C must be followed by space"); |
4384 |
break; // allow -*nnn to fall to parameter code |
4174 |
} |
4385 |
} |
4175 |
|
4386 |
|
4176 |
// process next single character option or compression level |
4387 |
// process next single character option or compression level |
Lines 4187-4192
local int option(char *arg) {
Link Here
|
4187 |
if (g.level == 10 || g.level > 11) |
4398 |
if (g.level == 10 || g.level > 11) |
4188 |
throw(EINVAL, "only levels 0..9 and 11 are allowed"); |
4399 |
throw(EINVAL, "only levels 0..9 and 11 are allowed"); |
4189 |
break; |
4400 |
break; |
|
|
4401 |
case 'A': get = 6; break; |
4402 |
case 'C': get = 7; break; |
4190 |
#ifndef NOZOPFLI |
4403 |
#ifndef NOZOPFLI |
4191 |
case 'F': g.zopts.blocksplittinglast = 1; break; |
4404 |
case 'F': g.zopts.blocksplittinglast = 1; break; |
4192 |
case 'I': get = 4; break; |
4405 |
case 'I': get = 4; break; |
Lines 4194-4204
local int option(char *arg) {
Link Here
|
4194 |
#endif |
4407 |
#endif |
4195 |
case 'K': g.form = 2; g.sufx = ".zip"; break; |
4408 |
case 'K': g.form = 2; g.sufx = ".zip"; break; |
4196 |
case 'L': |
4409 |
case 'L': |
4197 |
fputs(VERSION, stderr); |
4410 |
puts(VERSION); |
4198 |
fputs("Copyright (C) 2007-2017 Mark Adler\n", stderr); |
4411 |
puts("Copyright (C) 2007-2017 Mark Adler"); |
4199 |
fputs("Subject to the terms of the zlib license.\n", |
4412 |
puts("Subject to the terms of the zlib license."); |
4200 |
stderr); |
4413 |
puts("No warranty is provided or implied."); |
4201 |
fputs("No warranty is provided or implied.\n", stderr); |
|
|
4202 |
exit(0); |
4414 |
exit(0); |
4203 |
case 'M': g.headis |= 0xa; break; |
4415 |
case 'M': g.headis |= 0xa; break; |
4204 |
case 'N': g.headis = 0xf; break; |
4416 |
case 'N': g.headis = 0xf; break; |
Lines 4209-4217
local int option(char *arg) {
Link Here
|
4209 |
case 'S': get = 3; break; |
4421 |
case 'S': get = 3; break; |
4210 |
// -T defined below as an alternative for -m |
4422 |
// -T defined below as an alternative for -m |
4211 |
case 'V': |
4423 |
case 'V': |
4212 |
fputs(VERSION, stderr); |
4424 |
puts(VERSION); |
4213 |
if (g.verbosity > 1) |
4425 |
if (g.verbosity > 1) |
4214 |
fprintf(stderr, "zlib %s\n", zlibVersion()); |
4426 |
printf("zlib %s\n", zlibVersion()); |
4215 |
exit(0); |
4427 |
exit(0); |
4216 |
case 'Y': g.sync = 1; break; |
4428 |
case 'Y': g.sync = 1; break; |
4217 |
case 'Z': |
4429 |
case 'Z': |
Lines 4245-4257
local int option(char *arg) {
Link Here
|
4245 |
return 1; |
4457 |
return 1; |
4246 |
} |
4458 |
} |
4247 |
|
4459 |
|
4248 |
// process option parameter for -b, -p, -S, -I, or -J |
4460 |
// process option parameter for -b, -p, -A, -S, -I, or -J |
4249 |
if (get) { |
4461 |
if (get) { |
4250 |
size_t n; |
4462 |
size_t n; |
4251 |
|
4463 |
|
4252 |
if (get == 1) { |
4464 |
if (get == 1) { |
4253 |
n = num(arg); |
4465 |
n = num(arg); |
4254 |
g.block = n << 10; // chunk size |
4466 |
g.block = n << 10; // chunk size |
|
|
4467 |
g.shift = x2nmodp(g.block, 3); |
4255 |
if (g.block < DICT) |
4468 |
if (g.block < DICT) |
4256 |
throw(EINVAL, "block size too small (must be >= 32K)"); |
4469 |
throw(EINVAL, "block size too small (must be >= 32K)"); |
4257 |
if (n != g.block >> 10 || |
4470 |
if (n != g.block >> 10 || |
Lines 4282-4288
local int option(char *arg) {
Link Here
|
4282 |
g.zopts.numiterations = (int)num(arg); // optimize iterations |
4495 |
g.zopts.numiterations = (int)num(arg); // optimize iterations |
4283 |
else if (get == 5) |
4496 |
else if (get == 5) |
4284 |
g.zopts.blocksplittingmax = (int)num(arg); // max block splits |
4497 |
g.zopts.blocksplittingmax = (int)num(arg); // max block splits |
|
|
4498 |
else if (get == 6) |
4499 |
g.alias = arg; // zip name for stdin |
4285 |
#endif |
4500 |
#endif |
|
|
4501 |
else if (get == 7) |
4502 |
g.comment = arg; // header comment |
4286 |
get = 0; |
4503 |
get = 0; |
4287 |
return 1; |
4504 |
return 1; |
4288 |
} |
4505 |
} |
Lines 4294-4300
local int option(char *arg) {
Link Here
|
4294 |
#ifndef NOTHREAD |
4511 |
#ifndef NOTHREAD |
4295 |
// handle error received from yarn function |
4512 |
// handle error received from yarn function |
4296 |
local void cut_yarn(int err) { |
4513 |
local void cut_yarn(int err) { |
4297 |
throw(err, err == ENOMEM ? "not enough memory" : "internal threads error"); |
4514 |
throw(err, "internal threads error"); |
4298 |
} |
4515 |
} |
4299 |
#endif |
4516 |
#endif |
4300 |
|
4517 |
|
Lines 4315-4323
int main(int argc, char **argv) {
Link Here
|
4315 |
#ifndef NOTHREAD |
4532 |
#ifndef NOTHREAD |
4316 |
g.in_which = -1; |
4533 |
g.in_which = -1; |
4317 |
#endif |
4534 |
#endif |
|
|
4535 |
g.alias = "-"; |
4318 |
g.outf = NULL; |
4536 |
g.outf = NULL; |
4319 |
g.first = 1; |
4537 |
g.first = 1; |
4320 |
g.hname = NULL; |
4538 |
g.hname = NULL; |
|
|
4539 |
g.hcomm = NULL; |
4321 |
|
4540 |
|
4322 |
// save pointer to program name for error messages |
4541 |
// save pointer to program name for error messages |
4323 |
p = strrchr(argv[0], '/'); |
4542 |
p = strrchr(argv[0], '/'); |
Lines 4342-4347
int main(int argc, char **argv) {
Link Here
|
4342 |
if (zlib_vernum() < 0x1230) |
4561 |
if (zlib_vernum() < 0x1230) |
4343 |
throw(EINVAL, "zlib version less than 1.2.3"); |
4562 |
throw(EINVAL, "zlib version less than 1.2.3"); |
4344 |
|
4563 |
|
|
|
4564 |
// create CRC table, in case zlib compiled with dynamic tables |
4565 |
get_crc_table(); |
4566 |
|
4345 |
// process user environment variable defaults in GZIP |
4567 |
// process user environment variable defaults in GZIP |
4346 |
opts = getenv("GZIP"); |
4568 |
opts = getenv("GZIP"); |
4347 |
if (opts != NULL) { |
4569 |
if (opts != NULL) { |