1 /* lzma encoding (ENCODING_LZMA) backend */
19 #include "encoding/encoding.h"
20 #include "encoding/lzma.h"
21 #include "util/memory.h"
23 #define ELINKS_BZ_BUFFER_LENGTH 5000
25 #define ELINKS_LZMA_MEMORY_LIMIT (1024 * 1024 * 128)
27 struct lzma_enc_data
{
28 lzma_stream flzma_stream
;
32 unsigned char buf
[ELINKS_BZ_BUFFER_LENGTH
];
36 lzma_open(struct stream_encoded
*stream
, int fd
)
38 struct lzma_enc_data
*data
= mem_alloc(sizeof(*data
));
46 memset(&data
->flzma_stream
, 0, sizeof(data
->flzma_stream
));
50 err
= lzma_auto_decoder(&data
->flzma_stream
, ELINKS_LZMA_MEMORY_LIMIT
, 0);
62 lzma_read(struct stream_encoded
*stream
, unsigned char *buf
, int len
)
64 struct lzma_enc_data
*data
= (struct lzma_enc_data
*) stream
->data
;
71 if (data
->last_read
) return 0;
73 data
->flzma_stream
.avail_out
= len
;
74 data
->flzma_stream
.next_out
= buf
;
77 if (data
->flzma_stream
.avail_in
== 0) {
78 int l
= safe_read(data
->fdread
, data
->buf
,
79 ELINKS_BZ_BUFFER_LENGTH
);
85 return -1; /* I/O error */
87 /* EOF. It is error: we wait for more bytes */
91 data
->flzma_stream
.next_in
= data
->buf
;
92 data
->flzma_stream
.avail_in
= l
;
95 err
= lzma_code(&data
->flzma_stream
, LZMA_RUN
);
96 if (err
== LZMA_STREAM_END
) {
99 } else if (err
!= LZMA_OK
) {
102 } while (data
->flzma_stream
.avail_out
> 0);
104 assert(len
- data
->flzma_stream
.avail_out
== data
->flzma_stream
.next_out
- buf
);
105 return len
- data
->flzma_stream
.avail_out
;
108 static unsigned char *
109 lzma_decode_buffer(struct stream_encoded
*st
, unsigned char *data
, int len
, int *new_len
)
111 struct lzma_enc_data
*enc_data
= (struct lzma_enc_data
*) st
->data
;
112 lzma_stream
*stream
= &enc_data
->flzma_stream
;
113 unsigned char *buffer
= NULL
;
116 *new_len
= 0; /* default, left there if an error occurs */
118 stream
->next_in
= data
;
119 stream
->avail_in
= len
;
120 stream
->total_out
= 0;
122 if (lzma_auto_decoder(stream
, ELINKS_LZMA_MEMORY_LIMIT
, 0) != LZMA_OK
)
126 unsigned char *new_buffer
;
127 size_t size
= stream
->total_out
+ MAX_STR_LEN
;
129 new_buffer
= mem_realloc(buffer
, size
);
131 error
= LZMA_MEM_ERROR
;
136 stream
->next_out
= buffer
+ stream
->total_out
;
137 stream
->avail_out
= MAX_STR_LEN
;
139 error
= lzma_code(stream
, LZMA_RUN
);
140 if (error
== LZMA_STREAM_END
) {
144 } while (error
== LZMA_OK
&& stream
->avail_in
> 0);
146 if (error
== LZMA_STREAM_END
) {
148 enc_data
->after_end
= 1;
152 if (error
== LZMA_OK
) {
153 *new_len
= stream
->total_out
;
156 if (buffer
) mem_free(buffer
);
162 lzma_close(struct stream_encoded
*stream
)
164 struct lzma_enc_data
*data
= (struct lzma_enc_data
*) stream
->data
;
167 if (!data
->after_end
) {
168 lzma_end(&data
->flzma_stream
);
170 if (data
->fdread
!= -1) {
178 static const unsigned char *const lzma_extensions
[] = { ".lzma", ".xz", NULL
};
180 const struct decoding_backend lzma_decoding_backend
= {