-
Notifications
You must be signed in to change notification settings - Fork 1
/
xzdec.c
96 lines (86 loc) · 1.74 KB
/
xzdec.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <stdlib.h>
#include "xz.h"
#define BUFFER_INCREMENT (1024 * 1024 * 10)
int xz_decompress(unsigned char *encoded, int encoded_size,
unsigned char **decoded, int *decoded_size)
{
static int xz_initialized = 0;
enum xz_ret ret;
struct xz_dec *xz;
struct xz_buf buf;
unsigned char *dec_buffer;
unsigned char *temp;
int dec_size;
if (!xz_initialized)
{
xz_crc32_init();
xz_initialized = 1;
}
*decoded = NULL;
*decoded_size = 0;
buf.in = encoded;
buf.in_pos = 0;
buf.in_size = encoded_size;
dec_size = BUFFER_INCREMENT;
dec_buffer = (unsigned char *)malloc(dec_size);
if (!dec_buffer)
{
return 0;
}
buf.out = dec_buffer;
buf.out_pos = 0;
buf.out_size = dec_size;
xz = xz_dec_init(XZ_DYNALLOC, (uint32_t)-1);
if (!xz)
{
free(dec_buffer);
return 0;
}
do
{
ret = xz_dec_run(xz, &buf);
if (ret == XZ_OK)
{
/* things are okay, but more buffer space is needed */
dec_size += BUFFER_INCREMENT;
temp = realloc(dec_buffer, dec_size);
if (!temp)
{
free(dec_buffer);
xz_dec_end(xz);
return 0;
}
else
dec_buffer = temp;
buf.out_size = dec_size;
buf.out = dec_buffer;
}
else
{
/* any other status is an exit condition (either error or stream end) */
break;
}
} while (ret != XZ_STREAM_END);
if (ret == XZ_STREAM_END)
{
/* resize the final buffer */
dec_size = buf.out_pos;
temp = realloc(dec_buffer, dec_size);
if (!temp)
{
free(dec_buffer);
xz_dec_end(xz);
return 0;
}
*decoded = temp;
*decoded_size = dec_size;
xz_dec_end(xz);
return 1;
}
else
{
xz_dec_end(xz);
free(dec_buffer);
return 0;
}
}