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
)
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");
57 if (s
->z
.total_in
!= s
->total_in
+ bytes_consumed
)
58 BUG("total_in mismatch");
60 s
->total_out
= s
->z
.total_out
;
61 s
->total_in
= s
->z
.total_in
;
62 s
->next_in
= s
->z
.next_in
;
63 s
->next_out
= s
->z
.next_out
;
64 s
->avail_in
-= bytes_consumed
;
65 s
->avail_out
-= bytes_produced
;
68 void git_inflate_init(git_zstream
*strm
)
73 status
= inflateInit(&strm
->z
);
77 die("inflateInit: %s (%s)", zerr_to_string(status
),
78 strm
->z
.msg
? strm
->z
.msg
: "no message");
81 void git_inflate_init_gzip_only(git_zstream
*strm
)
84 * Use default 15 bits, +16 is to accept only gzip and to
85 * yield Z_DATA_ERROR when fed zlib format.
87 const int windowBits
= 15 + 16;
91 status
= inflateInit2(&strm
->z
, windowBits
);
95 die("inflateInit2: %s (%s)", zerr_to_string(status
),
96 strm
->z
.msg
? strm
->z
.msg
: "no message");
99 void git_inflate_end(git_zstream
*strm
)
104 status
= inflateEnd(&strm
->z
);
105 zlib_post_call(strm
);
108 error("inflateEnd: %s (%s)", zerr_to_string(status
),
109 strm
->z
.msg
? strm
->z
.msg
: "no message");
112 int git_inflate(git_zstream
*strm
, int flush
)
118 /* Never say Z_FINISH unless we are feeding everything */
119 status
= inflate(&strm
->z
,
120 (strm
->z
.avail_in
!= strm
->avail_in
)
122 if (status
== Z_MEM_ERROR
)
123 die("inflate: out of memory");
124 zlib_post_call(strm
);
127 * Let zlib work another round, while we can still
130 if ((strm
->avail_out
&& !strm
->z
.avail_out
) &&
131 (status
== Z_OK
|| status
== Z_BUF_ERROR
))
137 /* Z_BUF_ERROR: normal, needs more space in the output buffer */
145 error("inflate: %s (%s)", zerr_to_string(status
),
146 strm
->z
.msg
? strm
->z
.msg
: "no message");
150 #if defined(NO_DEFLATE_BOUND) || ZLIB_VERNUM < 0x1200
151 #define deflateBound(c,s) ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11)
154 unsigned long git_deflate_bound(git_zstream
*strm
, unsigned long size
)
156 return deflateBound(&strm
->z
, size
);
159 void git_deflate_init(git_zstream
*strm
, int level
)
163 memset(strm
, 0, sizeof(*strm
));
165 status
= deflateInit(&strm
->z
, level
);
166 zlib_post_call(strm
);
169 die("deflateInit: %s (%s)", zerr_to_string(status
),
170 strm
->z
.msg
? strm
->z
.msg
: "no message");
173 static void do_git_deflate_init(git_zstream
*strm
, int level
, int windowBits
)
177 memset(strm
, 0, sizeof(*strm
));
179 status
= deflateInit2(&strm
->z
, level
,
180 Z_DEFLATED
, windowBits
,
181 8, Z_DEFAULT_STRATEGY
);
182 zlib_post_call(strm
);
185 die("deflateInit2: %s (%s)", zerr_to_string(status
),
186 strm
->z
.msg
? strm
->z
.msg
: "no message");
189 void git_deflate_init_gzip(git_zstream
*strm
, int level
)
192 * Use default 15 bits, +16 is to generate gzip header/trailer
193 * instead of the zlib wrapper.
195 do_git_deflate_init(strm
, level
, 15 + 16);
198 void git_deflate_init_raw(git_zstream
*strm
, int level
)
201 * Use default 15 bits, negate the value to get raw compressed
202 * data without zlib header and trailer.
204 do_git_deflate_init(strm
, level
, -15);
207 int git_deflate_abort(git_zstream
*strm
)
212 status
= deflateEnd(&strm
->z
);
213 zlib_post_call(strm
);
217 void git_deflate_end(git_zstream
*strm
)
219 int status
= git_deflate_abort(strm
);
223 error("deflateEnd: %s (%s)", zerr_to_string(status
),
224 strm
->z
.msg
? strm
->z
.msg
: "no message");
227 int git_deflate_end_gently(git_zstream
*strm
)
232 status
= deflateEnd(&strm
->z
);
233 zlib_post_call(strm
);
237 int git_deflate(git_zstream
*strm
, int flush
)
244 /* Never say Z_FINISH unless we are feeding everything */
245 status
= deflate(&strm
->z
,
246 (strm
->z
.avail_in
!= strm
->avail_in
)
248 if (status
== Z_MEM_ERROR
)
249 die("deflate: out of memory");
250 zlib_post_call(strm
);
253 * Let zlib work another round, while we can still
256 if ((strm
->avail_out
&& !strm
->z
.avail_out
) &&
257 (status
== Z_OK
|| status
== Z_BUF_ERROR
))
263 /* Z_BUF_ERROR: normal, needs more space in the output buffer */
271 error("deflate: %s (%s)", zerr_to_string(status
),
272 strm
->z
.msg
? strm
->z
.msg
: "no message");