This source file includes following definitions.
- init_zlib_functions
- accumulate_and_process_md5
- final_process_md5
- md5_gz_stream
- unwind_decompress
- DEFUN
- syms_of_decompress
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <config.h>
20
21 #ifdef HAVE_ZLIB
22
23 #include <zlib.h>
24
25 #include "lisp.h"
26 #include "buffer.h"
27 #include "composite.h"
28 #include "md5.h"
29
30 #include <verify.h>
31
32 #ifdef WINDOWSNT
33 # include <windows.h>
34 # include "w32common.h"
35 # include "w32.h"
36
37 DEF_DLL_FN (int, inflateInit2_,
38 (z_streamp strm, int windowBits, const char *version,
39 int stream_size));
40 DEF_DLL_FN (int, inflate, (z_streamp strm, int flush));
41 DEF_DLL_FN (int, inflateEnd, (z_streamp strm));
42
43 static bool zlib_initialized;
44
45 static bool
46 init_zlib_functions (void)
47 {
48 HMODULE library = w32_delayed_load (Qzlib);
49
50 if (!library)
51 return false;
52
53 LOAD_DLL_FN (library, inflateInit2_);
54 LOAD_DLL_FN (library, inflate);
55 LOAD_DLL_FN (library, inflateEnd);
56 return true;
57 }
58
59 # undef inflate
60 # undef inflateEnd
61 # undef inflateInit2_
62
63 # define inflate fn_inflate
64 # define inflateEnd fn_inflateEnd
65 # define inflateInit2_ fn_inflateInit2_
66
67 #endif
68
69
70 #ifdef HAVE_NATIVE_COMP
71
72 # define MD5_BLOCKSIZE 32768
73
74 static char acc_buff[2 * MD5_BLOCKSIZE];
75 static size_t acc_size;
76
77 static void
78 accumulate_and_process_md5 (void *data, size_t len, struct md5_ctx *ctxt)
79 {
80 eassert (len <= MD5_BLOCKSIZE);
81
82
83 memcpy (acc_buff + acc_size, data, len);
84 acc_size += len;
85 if (acc_size >= MD5_BLOCKSIZE)
86 {
87 acc_size -= MD5_BLOCKSIZE;
88 md5_process_block (acc_buff, MD5_BLOCKSIZE, ctxt);
89 memmove (acc_buff, acc_buff + MD5_BLOCKSIZE, acc_size);
90 }
91 }
92
93 static void
94 final_process_md5 (struct md5_ctx *ctxt)
95 {
96 if (acc_size)
97 {
98 md5_process_bytes (acc_buff, acc_size, ctxt);
99 acc_size = 0;
100 }
101 }
102
103 int
104 md5_gz_stream (FILE *source, void *resblock)
105 {
106 z_stream stream;
107 unsigned char in[MD5_BLOCKSIZE];
108 unsigned char out[MD5_BLOCKSIZE];
109
110 # ifdef WINDOWSNT
111 if (!zlib_initialized)
112 zlib_initialized = init_zlib_functions ();
113 if (!zlib_initialized)
114 {
115 message1 ("zlib library not found");
116 return -1;
117 }
118 # endif
119
120 eassert (!acc_size);
121
122 struct md5_ctx ctx;
123 md5_init_ctx (&ctx);
124
125
126 stream.zalloc = Z_NULL;
127 stream.zfree = Z_NULL;
128 stream.opaque = Z_NULL;
129 stream.avail_in = 0;
130 stream.next_in = Z_NULL;
131 int res = inflateInit2 (&stream, MAX_WBITS + 32);
132 if (res != Z_OK)
133 return -1;
134
135 do {
136 stream.avail_in = fread (in, 1, MD5_BLOCKSIZE, source);
137 if (ferror (source)) {
138 inflateEnd (&stream);
139 return -1;
140 }
141 if (stream.avail_in == 0)
142 break;
143 stream.next_in = in;
144
145 do {
146 stream.avail_out = MD5_BLOCKSIZE;
147 stream.next_out = out;
148 res = inflate (&stream, Z_NO_FLUSH);
149
150 if (res != Z_OK && res != Z_STREAM_END)
151 return -1;
152
153 accumulate_and_process_md5 (out, MD5_BLOCKSIZE - stream.avail_out, &ctx);
154 } while (stream.avail_in && !stream.avail_out);
155
156 } while (res != Z_STREAM_END);
157
158 final_process_md5 (&ctx);
159 inflateEnd (&stream);
160
161 if (res != Z_STREAM_END)
162 return -1;
163
164 md5_finish_ctx (&ctx, resblock);
165
166 return 0;
167 }
168 # undef MD5_BLOCKSIZE
169 #endif
170
171
172
173 struct decompress_unwind_data
174 {
175 ptrdiff_t old_point, orig, start, nbytes;
176 z_stream *stream;
177 };
178
179 static void
180 unwind_decompress (void *ddata)
181 {
182 struct decompress_unwind_data *data = ddata;
183 inflateEnd (data->stream);
184
185
186
187 if (data->start)
188 {
189 del_range_2 (data->start, data->start,
190 data->start + data->nbytes, data->start + data->nbytes,
191 0);
192 update_compositions (data->start, data->start, CHECK_HEAD);
193
194
195 signal_after_change (data->orig, data->start - data->orig,
196 data->start - data->orig);
197 }
198
199
200
201 SET_PT (min (data->old_point, ZV));
202 }
203
204 DEFUN ("zlib-available-p", Fzlib_available_p, Szlib_available_p, 0, 0, 0,
205 doc: )
206 (void)
207 {
208 #ifdef WINDOWSNT
209 Lisp_Object found = Fassq (Qzlib, Vlibrary_cache);
210 if (CONSP (found))
211 return XCDR (found);
212 else
213 {
214 Lisp_Object status;
215 zlib_initialized = init_zlib_functions ();
216 status = zlib_initialized ? Qt : Qnil;
217 Vlibrary_cache = Fcons (Fcons (Qzlib, status), Vlibrary_cache);
218 return status;
219 }
220 #else
221 return Qt;
222 #endif
223 }
224
225 DEFUN ("zlib-decompress-region", Fzlib_decompress_region,
226 Szlib_decompress_region,
227 2, 3, 0,
228 doc:
229
230
231
232
233
234
235
236
237 )
238 (Lisp_Object start, Lisp_Object end, Lisp_Object allow_partial)
239 {
240 ptrdiff_t istart, iend, pos_byte;
241 z_stream stream;
242 int inflate_status;
243 struct decompress_unwind_data unwind_data;
244 specpdl_ref count = SPECPDL_INDEX ();
245
246 validate_region (&start, &end);
247
248 if (! NILP (BVAR (current_buffer, enable_multibyte_characters)))
249 error ("This function can be called only in unibyte buffers");
250
251 #ifdef WINDOWSNT
252 if (!zlib_initialized)
253 zlib_initialized = init_zlib_functions ();
254 if (!zlib_initialized)
255 {
256 message1 ("zlib library not found");
257 return Qnil;
258 }
259 #endif
260
261
262
263 istart = XFIXNUM (start);
264 iend = XFIXNUM (end);
265
266
267 modify_text (istart, iend);
268
269 move_gap_both (iend, iend);
270
271 stream.zalloc = Z_NULL;
272 stream.zfree = Z_NULL;
273 stream.opaque = Z_NULL;
274 stream.avail_in = 0;
275 stream.next_in = Z_NULL;
276
277
278
279 if (inflateInit2 (&stream, MAX_WBITS + 32) != Z_OK)
280 return Qnil;
281
282 unwind_data.orig = istart;
283 unwind_data.start = iend;
284 unwind_data.stream = &stream;
285 unwind_data.old_point = PT;
286 unwind_data.nbytes = 0;
287 record_unwind_protect_ptr (unwind_decompress, &unwind_data);
288
289
290 SET_PT (iend);
291
292 pos_byte = istart;
293
294
295 do
296 {
297
298
299
300 ptrdiff_t avail_in = min (iend - pos_byte, UINT_MAX);
301 int avail_out = 16 * 1024;
302 int decompressed;
303
304 if (GAP_SIZE < avail_out)
305 make_gap (avail_out - GAP_SIZE);
306 stream.next_in = BYTE_POS_ADDR (pos_byte);
307 stream.avail_in = avail_in;
308 stream.next_out = GPT_ADDR;
309 stream.avail_out = avail_out;
310 inflate_status = inflate (&stream, Z_NO_FLUSH);
311 pos_byte += avail_in - stream.avail_in;
312 decompressed = avail_out - stream.avail_out;
313 insert_from_gap (decompressed, decompressed, 0);
314 unwind_data.nbytes += decompressed;
315 maybe_quit ();
316 }
317 while (inflate_status == Z_OK);
318
319 Lisp_Object ret = Qt;
320 if (inflate_status != Z_STREAM_END)
321 {
322 if (!NILP (allow_partial))
323 ret = make_int (iend - pos_byte);
324 else
325 return unbind_to (count, Qnil);
326 }
327
328 unwind_data.start = 0;
329
330
331 del_range_2 (istart, istart,
332 iend, iend, 0);
333
334 signal_after_change (istart, iend - istart, unwind_data.nbytes);
335 update_compositions (istart, istart, CHECK_HEAD);
336
337 return unbind_to (count, ret);
338 }
339
340
341
342
343
344 void
345 syms_of_decompress (void)
346 {
347 defsubr (&Szlib_decompress_region);
348 defsubr (&Szlib_available_p);
349 }
350
351 #endif