1 /*
2 Copyright 1996-2014 Han The Thanh, <thanh@pdftex.org>
3 
4 This file is part of pdfTeX.
5 
6 pdfTeX is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 
11 pdfTeX is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License along
17 with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "ptexlib.h"
21 #include "zlib.h"
22 #include <assert.h>
23 
24 #define ZIP_BUF_SIZE  32768
25 
26 #define check_err(f, fn) \
27     if (f != Z_OK)       \
28         pdftex_fail("zlib: %s() failed (error code %d)", fn, f)
29 
30 static char *zipbuf = NULL;
31 static z_stream c_stream;       /* compression stream */
32 
writezip(boolean finish)33 void writezip(boolean finish)
34 {
35     int err;
36     static int level_old = 0;
37     int level = getpdfcompresslevel();
38     assert(level > 0);
39     cur_file_name = NULL;
40     if (pdfstreamlength == 0) {
41         if (zipbuf == NULL) {
42             zipbuf = xtalloc(ZIP_BUF_SIZE, char);
43             c_stream.zalloc = (alloc_func) 0;
44             c_stream.zfree = (free_func) 0;
45             c_stream.opaque = (voidpf) 0;
46             check_err(deflateInit(&c_stream, level), "deflateInit");
47         } else {
48             if (level != level_old) {   /* \pdfcompresslevel change in mid document */
49                 check_err(deflateEnd(&c_stream), "deflateEnd");
50                 c_stream.zalloc = (alloc_func) 0;       /* these 3 lines no need, just to be safe */
51                 c_stream.zfree = (free_func) 0;
52                 c_stream.opaque = (voidpf) 0;
53                 check_err(deflateInit(&c_stream, level), "deflateInit");
54             } else
55                 check_err(deflateReset(&c_stream), "deflateReset");
56         }
57         level_old = level;
58         c_stream.next_out = (Bytef *) zipbuf;
59         c_stream.avail_out = ZIP_BUF_SIZE;
60     }
61     assert(zipbuf != NULL);
62     c_stream.next_in = pdfbuf;
63     c_stream.avail_in = pdfptr;
64     for (;;) {
65         if (c_stream.avail_out == 0) {
66             pdfgone += xfwrite(zipbuf, 1, ZIP_BUF_SIZE, pdffile);
67             pdflastbyte = zipbuf[ZIP_BUF_SIZE - 1];     /* not needed */
68             c_stream.next_out = (Bytef *) zipbuf;
69             c_stream.avail_out = ZIP_BUF_SIZE;
70         }
71         err = deflate(&c_stream, finish ? Z_FINISH : Z_NO_FLUSH);
72         if (finish && err == Z_STREAM_END)
73             break;
74         check_err(err, "deflate");
75         if (!finish && c_stream.avail_in == 0)
76             break;
77     }
78     if (finish) {
79         if (c_stream.avail_out < ZIP_BUF_SIZE) {        /* at least one byte has been output */
80             pdfgone +=
81                 xfwrite(zipbuf, 1, ZIP_BUF_SIZE - c_stream.avail_out, pdffile);
82             pdflastbyte = zipbuf[ZIP_BUF_SIZE - c_stream.avail_out - 1];
83         }
84         xfflush(pdffile);
85     }
86     pdfstreamlength = c_stream.total_out;
87 }
88 
zip_free(void)89 void zip_free(void)
90 {
91     if (zipbuf != NULL) {
92         check_err(deflateEnd(&c_stream), "deflateEnd");
93         free(zipbuf);
94     }
95 }
96