1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 
3 /*
4  *  GThumb
5  *
6  *  Copyright (C) 2009 The Free Software Foundation, Inc.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <config.h>
23 #include <string.h>
24 #include <zlib.h>
25 #include "zlib-utils.h"
26 
27 
28 #define BUFFER_SIZE (16 * 1024)
29 
30 
31 gboolean
zlib_decompress_buffer(void * zipped_buffer,gsize zipped_size,void ** buffer,gsize * size)32 zlib_decompress_buffer (void   *zipped_buffer,
33 			gsize   zipped_size,
34 		        void  **buffer,
35 		        gsize  *size)
36 {
37 	z_stream  strm;
38 	int       ret;
39 	guint     n;
40 	gsize     count;
41 	guchar   *local_buffer = NULL;
42 	guchar    tmp_buffer[BUFFER_SIZE];
43 
44 	strm.zalloc = Z_NULL;
45 	strm.zfree = Z_NULL;
46 	strm.opaque = Z_NULL;
47 	strm.avail_in = 0;
48 	strm.next_in = Z_NULL;
49 	ret = inflateInit2 (&strm, 16+15);
50 	if (ret != Z_OK)
51 		return FALSE;
52 
53 	count = 0;
54 	strm.avail_in = zipped_size;
55 	strm.next_in = zipped_buffer;
56 	do {
57 		do {
58 			strm.avail_out = BUFFER_SIZE;
59 			strm.next_out = tmp_buffer;
60 			ret = inflate (&strm, Z_NO_FLUSH);
61 
62 			switch (ret) {
63 			case Z_NEED_DICT:
64 			case Z_DATA_ERROR:
65 			case Z_MEM_ERROR:
66 				g_free (local_buffer);
67 				inflateEnd (&strm);
68 				return FALSE;
69 			}
70 
71 			n = BUFFER_SIZE - strm.avail_out;
72 			local_buffer = g_realloc (local_buffer, count + n + 1);
73 			memcpy (local_buffer + count, tmp_buffer, n);
74 			count += n;
75 		}
76 		while (strm.avail_out == 0);
77 	}
78 	while (ret != Z_STREAM_END);
79 
80 	inflateEnd (&strm);
81 
82 	*buffer = local_buffer;
83 	*size = count;
84 
85 	return ret == Z_STREAM_END;
86 }
87