2 * zlib wrappers to make sure we don't silently miss errors
5 #include "git-compat-util.h"
8 static const char *zerr_to_string(int status
)
12 return "out of memory";
14 return "wrong version";
16 return "needs dictionary";
18 return "data stream error";
20 return "stream consistency error";
22 return "unknown error";
27 * avail_in and avail_out in zlib are counted in uInt, which typically
28 * limits the size of the buffer we can use to 4GB when interacting
29 * with zlib in a single call to inflate/deflate.
31 /* #define ZLIB_BUF_MAX ((uInt)-1) */
32 #define ZLIB_BUF_MAX ((uInt) 1024 * 1024 * 1024) /* 1GB */
33 static inline uInt
zlib_buf_cap(unsigned long len
)
35 return (ZLIB_BUF_MAX
< len
) ? ZLIB_BUF_MAX
: len
;
38 static void zlib_pre_call(git_zstream
*s
)
40 s
->z
.next_in
= s
->next_in
;
41 s
->z
.next_out
= s
->next_out
;
42 s
->z
.total_in
= s
->total_in
;
43 s
->z
.total_out
= s
->total_out
;
44 s
->z
.avail_in
= zlib_buf_cap(s
->avail_in
);
45 s
->z
.avail_out
= zlib_buf_cap(s
->avail_out
);
48 static void zlib_post_call(git_zstream
*s
, int status
)
50 unsigned long bytes_consumed
;
51 unsigned long bytes_produced
;
53 bytes_consumed
= s
->z
.next_in
- s
->next_in
;
54 bytes_produced
= s
->z
.next_out
- s
->next_out
;
55 if (s
->z
.total_out
!= s
->total_out
+ bytes_produced
)
56 BUG("total_out mismatch");
58 * zlib does not update total_in when it returns Z_NEED_DICT,
59 * causing a mismatch here. Skip the sanity check in that case.
61 if (status
!= Z_NEED_DICT
&&
62 s
->z
.total_in
!= s
->total_in
+ bytes_consumed
)
63 BUG("total_in mismatch");
65 s
->total_out
= s
->z
.total_out
;
66 s
->total_in
= s
->z
.total_in
;
67 /* zlib-ng marks `next_in` as `const`, so we have to cast it away. */
68 s
->next_in
= (unsigned char *) s
->z
.next_in
;
69 s
->next_out
= s
->z
.next_out
;
70 s
->avail_in
-= bytes_consumed
;
71 s
->avail_out
-= bytes_produced
;
74 void git_inflate_init(git_zstream
*strm
)
79 status
= inflateInit(&strm
->z
);
80 zlib_post_call(strm
, status
);
83 die("inflateInit: %s (%s)", zerr_to_string(status
),
84 strm
->z
.msg
? strm
->z
.msg
: "no message");
87 void git_inflate_init_gzip_only(git_zstream
*strm
)
90 * Use default 15 bits, +16 is to accept only gzip and to
91 * yield Z_DATA_ERROR when fed zlib format.
93 const int windowBits
= 15 + 16;
97 status
= inflateInit2(&strm
->z
, windowBits
);
98 zlib_post_call(strm
, status
);
101 die("inflateInit2: %s (%s)", zerr_to_string(status
),
102 strm
->z
.msg
? strm
->z
.msg
: "no message");
105 void git_inflate_end(git_zstream
*strm
)
110 status
= inflateEnd(&strm
->z
);
111 zlib_post_call(strm
, status
);
114 error("inflateEnd: %s (%s)", zerr_to_string(status
),
115 strm
->z
.msg
? strm
->z
.msg
: "no message");
118 int git_inflate(git_zstream
*strm
, int flush
)
124 /* Never say Z_FINISH unless we are feeding everything */
125 status
= inflate(&strm
->z
,
126 (strm
->z
.avail_in
!= strm
->avail_in
)
128 if (status
== Z_MEM_ERROR
)
129 die("inflate: out of memory");
130 zlib_post_call(strm
, status
);
133 * Let zlib work another round, while we can still
136 if ((strm
->avail_out
&& !strm
->z
.avail_out
) &&
137 (status
== Z_OK
|| status
== Z_BUF_ERROR
))
143 /* Z_BUF_ERROR: normal, needs more space in the output buffer */
151 error("inflate: %s (%s)", zerr_to_string(status
),
152 strm
->z
.msg
? strm
->z
.msg
: "no message");
156 unsigned long git_deflate_bound(git_zstream
*strm
, unsigned long size
)
158 return deflateBound(&strm
->z
, size
);
161 void git_deflate_init(git_zstream
*strm
, int level
)
165 memset(strm
, 0, sizeof(*strm
));
167 status
= deflateInit(&strm
->z
, level
);
168 zlib_post_call(strm
, status
);
171 die("deflateInit: %s (%s)", zerr_to_string(status
),
172 strm
->z
.msg
? strm
->z
.msg
: "no message");
175 static void do_git_deflate_init(git_zstream
*strm
, int level
, int windowBits
)
179 memset(strm
, 0, sizeof(*strm
));
181 status
= deflateInit2(&strm
->z
, level
,
182 Z_DEFLATED
, windowBits
,
183 8, Z_DEFAULT_STRATEGY
);
184 zlib_post_call(strm
, status
);
187 die("deflateInit2: %s (%s)", zerr_to_string(status
),
188 strm
->z
.msg
? strm
->z
.msg
: "no message");
191 void git_deflate_init_gzip(git_zstream
*strm
, int level
)
194 * Use default 15 bits, +16 is to generate gzip header/trailer
195 * instead of the zlib wrapper.
197 do_git_deflate_init(strm
, level
, 15 + 16);
200 void git_deflate_init_raw(git_zstream
*strm
, int level
)
203 * Use default 15 bits, negate the value to get raw compressed
204 * data without zlib header and trailer.
206 do_git_deflate_init(strm
, level
, -15);
209 int git_deflate_abort(git_zstream
*strm
)
214 status
= deflateEnd(&strm
->z
);
215 zlib_post_call(strm
, status
);
219 void git_deflate_end(git_zstream
*strm
)
221 int status
= git_deflate_abort(strm
);
225 error("deflateEnd: %s (%s)", zerr_to_string(status
),
226 strm
->z
.msg
? strm
->z
.msg
: "no message");
229 int git_deflate_end_gently(git_zstream
*strm
)
234 status
= deflateEnd(&strm
->z
);
235 zlib_post_call(strm
, status
);
239 int git_deflate(git_zstream
*strm
, int flush
)
246 /* Never say Z_FINISH unless we are feeding everything */
247 status
= deflate(&strm
->z
,
248 (strm
->z
.avail_in
!= strm
->avail_in
)
250 if (status
== Z_MEM_ERROR
)
251 die("deflate: out of memory");
252 zlib_post_call(strm
, status
);
255 * Let zlib work another round, while we can still
258 if ((strm
->avail_out
&& !strm
->z
.avail_out
) &&
259 (status
== Z_OK
|| status
== Z_BUF_ERROR
))
265 /* Z_BUF_ERROR: normal, needs more space in the output buffer */
273 error("deflate: %s (%s)", zerr_to_string(status
),
274 strm
->z
.msg
? strm
->z
.msg
: "no message");