Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 645438
Collapse All | Expand All

(-)a/pigz.c (-210 / +432 lines)
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) {

Return to bug 645438