1 /* Bzip2 encoding (ENCODING_BZIP2) backend */
13 #include <bzlib.h> /* Everything needs this after stdio.h */
18 #include "encoding/bzip2.h"
19 #include "encoding/encoding.h"
20 #include "util/memory.h"
25 int last_read
; /* If err after last bzRead() was BZ_STREAM_END.. */
30 char buf
[BZ_MAX_UNUSED
];
32 unsigned char writing
;
35 unsigned char initialisedOk
;
38 /* TODO: When it'll be official, use bzdopen() from Yoshioka Tsuneo. --pasky */
41 bzip2_open(struct stream_encoded
*stream
, int fd
)
43 struct bz2_enc_data
*data
= mem_alloc(sizeof(*data
));
51 data
->file
= fdopen(fd
, "rb");
53 data
->bzfile
= BZ2_bzReadOpen(&err
, data
->file
, 0, 0, NULL
, 0);
69 if (c
== EOF
) return 1;
74 #define BZ_SETERR(eee) \
76 if (bzerror != NULL) *bzerror = eee; \
77 if (bzf != NULL) bzf->lastErr = eee; \
81 BZ2_bzRead2(int *bzerror
, BZFILE
*b
, void *buf
, int len
)
84 struct bzFile
*bzf
= (struct bzFile
*)b
;
88 if (bzf
== NULL
|| buf
== NULL
|| len
< 0) {
89 BZ_SETERR(BZ_PARAM_ERROR
);
94 BZ_SETERR(BZ_SEQUENCE_ERROR
);
103 bzf
->strm
.avail_out
= len
;
104 bzf
->strm
.next_out
= buf
;
107 if (ferror(bzf
->handle
)) {
108 BZ_SETERR(BZ_IO_ERROR
);
112 if (bzf
->strm
.avail_in
== 0 && !myfeof(bzf
->handle
)) {
113 n
= fread(bzf
->buf
, 1, BZ_MAX_UNUSED
, bzf
->handle
);
114 if (ferror(bzf
->handle
)) {
116 BZ_SETERR(BZ_IO_ERROR
);
124 bzf
->strm
.avail_in
= bzf
->bufN
;
125 bzf
->strm
.next_in
= bzf
->buf
;
128 ret
= BZ2_bzDecompress ( &(bzf
->strm
) );
129 if (ret
!= BZ_OK
&& ret
!= BZ_STREAM_END
) {
134 if (ret
== BZ_OK
&& myfeof(bzf
->handle
) &&
135 bzf
->strm
.avail_in
== 0 && bzf
->strm
.avail_out
> 0) {
137 BZ_SETERR(BZ_UNEXPECTED_EOF
);
140 return len
- bzf
->strm
.avail_out
;
144 if (ret
== BZ_STREAM_END
) {
145 BZ_SETERR(BZ_STREAM_END
);
146 return len
- bzf
->strm
.avail_out
;
149 if (bzf
->strm
.avail_out
== 0) {
154 return 0; /*not reached*/
159 bzip2_read(struct stream_encoded
*stream
, unsigned char *buf
, int len
)
161 struct bz2_enc_data
*data
= (struct bz2_enc_data
*) stream
->data
;
163 struct bzFile
*bzf
= (struct bzFile
*)data
->bzfile
;
168 clearerr(bzf
->handle
);
169 len
= BZ2_bzRead2(&err
, data
->bzfile
, buf
, len
);
171 if (err
== BZ_STREAM_END
)
179 static unsigned char *
180 bzip2_decode(struct stream_encoded
*stream
, unsigned char *data
, int len
,
188 #define BZIP2_SMALL 1
190 #define BZIP2_SMALL 0
193 static unsigned char *
194 bzip2_decode_buffer(unsigned char *data
, int len
, int *new_len
)
197 unsigned char *buffer
= NULL
;
200 memset(&stream
, 0, sizeof(bz_stream
));
201 stream
.next_in
= data
;
202 stream
.avail_in
= len
;
204 if (BZ2_bzDecompressInit(&stream
, 0, BZIP2_SMALL
) != BZ_OK
)
208 unsigned char *new_buffer
;
209 size_t size
= stream
.total_out_lo32
+ MAX_STR_LEN
;
211 /* FIXME: support for 64 bit. real size is
213 * (total_in_hi32 << * 32) + total_in_lo32
216 assertm(!stream
.total_out_hi32
, "64 bzip2 decoding not supported");
218 new_buffer
= mem_realloc(buffer
, size
);
220 error
= BZ_MEM_ERROR
;
225 stream
.next_out
= buffer
+ stream
.total_out_lo32
;
226 stream
.avail_out
= MAX_STR_LEN
;
228 error
= BZ2_bzDecompress(&stream
);
229 if (error
== BZ_STREAM_END
) {
230 *new_len
= stream
.total_out_lo32
;
235 /* Apparently BZ_STREAM_END is not forced when the end of input
236 * is reached. At least lindi- reported that it caused a
237 * reproducable infinite loop. Maybe it has to do with decoding
238 * an incomplete file. */
239 } while (error
== BZ_OK
&& stream
.avail_in
> 0);
241 BZ2_bzDecompressEnd(&stream
);
243 if (error
!= BZ_OK
) {
244 if (buffer
) mem_free(buffer
);
253 bzip2_close(struct stream_encoded
*stream
)
255 struct bz2_enc_data
*data
= (struct bz2_enc_data
*) stream
->data
;
258 BZ2_bzReadClose(&err
, data
->bzfile
);
263 static unsigned char *bzip2_extensions
[] = { ".bz2", ".tbz", NULL
};
265 struct decoding_backend bzip2_decoding_backend
= {