Botan 1.10.17
bzip2.cpp
Go to the documentation of this file.
1/*
2* Bzip Compressor
3* (C) 2001 Peter J Jones
4* 2001-2007 Jack Lloyd
5* 2006 Matt Johnston
6*
7* Distributed under the terms of the Botan license
8*/
9
10#include <botan/bzip2.h>
11#include <botan/exceptn.h>
12
13#include <map>
14#include <cstring>
15#define BZ_NO_STDIO
16#include <bzlib.h>
17
18namespace Botan {
19
20namespace {
21
22/*
23* Allocation Information for Bzip
24*/
25class Bzip_Alloc_Info
26 {
27 public:
28 std::map<void*, size_t> current_allocs;
29 Allocator* alloc;
30
31 Bzip_Alloc_Info() { alloc = Allocator::get(false); }
32 };
33
34/*
35* Allocation Function for Bzip
36*/
37void* bzip_malloc(void* info_ptr, int n, int size)
38 {
39 Bzip_Alloc_Info* info = static_cast<Bzip_Alloc_Info*>(info_ptr);
40 void* ptr = info->alloc->allocate(n * size);
41 info->current_allocs[ptr] = n * size;
42 return ptr;
43 }
44
45/*
46* Allocation Function for Bzip
47*/
48void bzip_free(void* info_ptr, void* ptr)
49 {
50 Bzip_Alloc_Info* info = static_cast<Bzip_Alloc_Info*>(info_ptr);
51 std::map<void*, size_t>::const_iterator i = info->current_allocs.find(ptr);
52 if(i == info->current_allocs.end())
53 throw Invalid_Argument("bzip_free: Got pointer not allocated by us");
54 info->alloc->deallocate(ptr, i->second);
55 }
56
57}
58
59/**
60* Wrapper Type for Bzip2 Stream
61*/
62class Bzip_Stream
63 {
64 public:
65 /**
66 * Underlying stream
67 */
68 bz_stream stream;
69
70 /**
71 * Constructor
72 */
73 Bzip_Stream()
74 {
75 std::memset(&stream, 0, sizeof(bz_stream));
76 stream.bzalloc = bzip_malloc;
77 stream.bzfree = bzip_free;
78 stream.opaque = new Bzip_Alloc_Info;
79 }
80
81 /**
82 * Destructor
83 */
84 ~Bzip_Stream()
85 {
86 Bzip_Alloc_Info* info = static_cast<Bzip_Alloc_Info*>(stream.opaque);
87 delete info;
88 std::memset(&stream, 0, sizeof(bz_stream));
89 }
90 };
91
92/*
93* Bzip_Compression Constructor
94*/
96 level((l >= 9) ? 9 : l), buffer(DEFAULT_BUFFERSIZE)
97 {
98 bz = 0;
99 }
100
101/*
102* Start Compressing with Bzip
103*/
105 {
106 clear();
107 bz = new Bzip_Stream;
108 if(BZ2_bzCompressInit(&(bz->stream), level, 0, 0) != BZ_OK)
109 throw Memory_Exhaustion();
110 }
111
112/*
113* Compress Input with Bzip
114*/
115void Bzip_Compression::write(const byte input[], size_t length)
116 {
117 bz->stream.next_in = reinterpret_cast<char*>(const_cast<byte*>(input));
118 bz->stream.avail_in = length;
119
120 while(bz->stream.avail_in != 0)
121 {
122 bz->stream.next_out = reinterpret_cast<char*>(buffer.begin());
123 bz->stream.avail_out = buffer.size();
124 BZ2_bzCompress(&(bz->stream), BZ_RUN);
125 send(buffer, buffer.size() - bz->stream.avail_out);
126 }
127 }
128
129/*
130* Finish Compressing with Bzip
131*/
133 {
134 bz->stream.next_in = 0;
135 bz->stream.avail_in = 0;
136
137 int rc = BZ_OK;
138 while(rc != BZ_STREAM_END)
139 {
140 bz->stream.next_out = reinterpret_cast<char*>(buffer.begin());
141 bz->stream.avail_out = buffer.size();
142 rc = BZ2_bzCompress(&(bz->stream), BZ_FINISH);
143 send(buffer, buffer.size() - bz->stream.avail_out);
144 }
145 clear();
146 }
147
148/*
149* Flush the Bzip Compressor
150*/
152 {
153 bz->stream.next_in = 0;
154 bz->stream.avail_in = 0;
155
156 int rc = BZ_OK;
157 while(rc != BZ_RUN_OK)
158 {
159 bz->stream.next_out = reinterpret_cast<char*>(buffer.begin());
160 bz->stream.avail_out = buffer.size();
161 rc = BZ2_bzCompress(&(bz->stream), BZ_FLUSH);
162 send(buffer, buffer.size() - bz->stream.avail_out);
163 }
164 }
165
166/*
167* Clean up Compression Context
168*/
169void Bzip_Compression::clear()
170 {
171 zeroise(buffer);
172
173 if(bz)
174 {
175 BZ2_bzCompressEnd(&(bz->stream));
176 delete bz;
177 bz = 0;
178 }
179 }
180
181/*
182* Bzip_Decompression Constructor
183*/
185 small_mem(s), buffer(DEFAULT_BUFFERSIZE)
186 {
187 no_writes = true;
188 bz = 0;
189 }
190
191/*
192* Decompress Input with Bzip
193*/
194void Bzip_Decompression::write(const byte input_arr[], size_t length)
195 {
196 if(length) no_writes = false;
197
198 char* input = reinterpret_cast<char*>(const_cast<byte*>(input_arr));
199
200 bz->stream.next_in = input;
201 bz->stream.avail_in = length;
202
203 while(bz->stream.avail_in != 0)
204 {
205 bz->stream.next_out = reinterpret_cast<char*>(buffer.begin());
206 bz->stream.avail_out = buffer.size();
207
208 int rc = BZ2_bzDecompress(&(bz->stream));
209
210 if(rc != BZ_OK && rc != BZ_STREAM_END)
211 {
212 clear();
213
214 if(rc == BZ_DATA_ERROR)
215 throw Decoding_Error("Bzip_Decompression: Data integrity error");
216 else if(rc == BZ_DATA_ERROR_MAGIC)
217 throw Decoding_Error("Bzip_Decompression: Invalid input");
218 else if(rc == BZ_MEM_ERROR)
219 throw Memory_Exhaustion();
220 else
221 throw std::runtime_error("Bzip2 decompression: Unknown error");
222 }
223
224 send(buffer, buffer.size() - bz->stream.avail_out);
225
226 if(rc == BZ_STREAM_END)
227 {
228 size_t read_from_block = length - bz->stream.avail_in;
229 start_msg();
230 bz->stream.next_in = input + read_from_block;
231 bz->stream.avail_in = length - read_from_block;
232 input += read_from_block;
233 length -= read_from_block;
234 }
235 }
236 }
237
238/*
239* Start Decompressing with Bzip
240*/
242 {
243 clear();
244 bz = new Bzip_Stream;
245
246 if(BZ2_bzDecompressInit(&(bz->stream), 0, small_mem) != BZ_OK)
247 throw Memory_Exhaustion();
248
249 no_writes = true;
250 }
251
252/*
253* Finish Decompressing with Bzip
254*/
256 {
257 if(no_writes) return;
258 bz->stream.next_in = 0;
259 bz->stream.avail_in = 0;
260
261 int rc = BZ_OK;
262 while(rc != BZ_STREAM_END)
263 {
264 bz->stream.next_out = reinterpret_cast<char*>(buffer.begin());
265 bz->stream.avail_out = buffer.size();
266 rc = BZ2_bzDecompress(&(bz->stream));
267
268 if(rc != BZ_OK && rc != BZ_STREAM_END)
269 {
270 clear();
271 throw Decoding_Error("Bzip_Decompression: Error finalizing");
272 }
273
274 send(buffer, buffer.size() - bz->stream.avail_out);
275 }
276
277 clear();
278 }
279
280/*
281* Clean up Decompression Context
282*/
283void Bzip_Decompression::clear()
284 {
285 zeroise(buffer);
286
287 if(bz)
288 {
289 BZ2_bzDecompressEnd(&(bz->stream));
290 delete bz;
291 bz = 0;
292 }
293 }
294
295}
static Allocator * get(bool locking)
Definition defalloc.cpp:90
void write(const byte input[], size_t length)
Definition bzip2.cpp:115
Bzip_Compression(size_t=9)
Definition bzip2.cpp:95
void write(const byte input[], size_t length)
Definition bzip2.cpp:194
Bzip_Decompression(bool=false)
Definition bzip2.cpp:184
void send(const byte in[], size_t length)
Definition filter.cpp:28
void zeroise(MemoryRegion< T > &vec)
Definition secmem.h:428
Decoding_Error(const std::string &name)
Definition exceptn.h:140