]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/journal/compress.c
journal/compress: simplify compress_blob
[thirdparty/systemd.git] / src / journal / compress.c
CommitLineData
e4e61fdb
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2011 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
e4e61fdb
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
e4e61fdb 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
e4e61fdb
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <assert.h>
23#include <stdlib.h>
24#include <string.h>
25#include <lzma.h>
26
93b73b06 27#include "macro.h"
e4e61fdb
LP
28#include "compress.h"
29
30bool compress_blob(const void *src, uint64_t src_size, void *dst, uint64_t *dst_size) {
e4e61fdb 31 lzma_ret ret;
76cc0bf6 32 size_t out_pos = 0;
e4e61fdb
LP
33
34 assert(src);
35 assert(src_size > 0);
36 assert(dst);
37 assert(dst_size);
38
39 /* Returns false if we couldn't compress the data or the
40 * compressed result is longer than the original */
41
76cc0bf6
ZJS
42 ret = lzma_easy_buffer_encode(LZMA_PRESET_DEFAULT, LZMA_CHECK_NONE, NULL,
43 src, src_size, dst, &out_pos, *dst_size);
e4e61fdb
LP
44 if (ret != LZMA_OK)
45 return false;
46
e4e61fdb 47 /* Is it actually shorter? */
76cc0bf6
ZJS
48 if (out_pos == *dst_size)
49 return false;
e4e61fdb 50
76cc0bf6
ZJS
51 *dst_size = out_pos;
52 return true;
e4e61fdb
LP
53}
54
55bool uncompress_blob(const void *src, uint64_t src_size,
93b73b06 56 void **dst, uint64_t *dst_alloc_size, uint64_t* dst_size, uint64_t dst_max) {
e4e61fdb
LP
57
58 lzma_stream s = LZMA_STREAM_INIT;
59 lzma_ret ret;
93b73b06 60 uint64_t space;
e4e61fdb
LP
61 bool b = false;
62
63 assert(src);
64 assert(src_size > 0);
65 assert(dst);
66 assert(dst_alloc_size);
67 assert(dst_size);
68 assert(*dst_alloc_size == 0 || *dst);
69
70 ret = lzma_stream_decoder(&s, UINT64_MAX, 0);
71 if (ret != LZMA_OK)
72 return false;
73
74 if (*dst_alloc_size <= src_size) {
75 void *p;
76
77 p = realloc(*dst, src_size*2);
78 if (!p)
79 return false;
80
81 *dst = p;
82 *dst_alloc_size = src_size*2;
83 }
84
85 s.next_in = src;
86 s.avail_in = src_size;
87
88 s.next_out = *dst;
93b73b06
LP
89 space = dst_max > 0 ? MIN(*dst_alloc_size, dst_max) : *dst_alloc_size;
90 s.avail_out = space;
e4e61fdb
LP
91
92 for (;;) {
93 void *p;
94
95 ret = lzma_code(&s, LZMA_FINISH);
96
97 if (ret == LZMA_STREAM_END)
98 break;
99
100 if (ret != LZMA_OK)
101 goto fail;
102
93b73b06
LP
103 if (dst_max > 0 && (space - s.avail_out) >= dst_max)
104 break;
105
106 p = realloc(*dst, space*2);
e4e61fdb
LP
107 if (!p)
108 goto fail;
109
110 s.next_out = (uint8_t*) p + ((uint8_t*) s.next_out - (uint8_t*) *dst);
93b73b06
LP
111 s.avail_out += space;
112
113 space *= 2;
e4e61fdb
LP
114
115 *dst = p;
93b73b06 116 *dst_alloc_size = space;
e4e61fdb
LP
117 }
118
93b73b06 119 *dst_size = space - s.avail_out;
e4e61fdb
LP
120 b = true;
121
122fail:
123 lzma_end(&s);
124
125 return b;
126}
127
128bool uncompress_startswith(const void *src, uint64_t src_size,
129 void **buffer, uint64_t *buffer_size,
130 const void *prefix, uint64_t prefix_len,
131 uint8_t extra) {
132
133 lzma_stream s = LZMA_STREAM_INIT;
134 lzma_ret ret;
135 bool b = false;
136
137 /* Checks whether the uncompressed blob starts with the
138 * mentioned prefix. The byte extra needs to follow the
139 * prefix */
140
141 assert(src);
142 assert(src_size > 0);
143 assert(buffer);
144 assert(buffer_size);
145 assert(prefix);
146 assert(*buffer_size == 0 || *buffer);
147
148 ret = lzma_stream_decoder(&s, UINT64_MAX, 0);
149 if (ret != LZMA_OK)
150 return false;
151
152 if (*buffer_size <= prefix_len) {
153 void *p;
154
155 p = realloc(*buffer, prefix_len*2);
156 if (!p)
157 return false;
158
159 *buffer = p;
160 *buffer_size = prefix_len*2;
161 }
162
163 s.next_in = src;
164 s.avail_in = src_size;
165
166 s.next_out = *buffer;
167 s.avail_out = *buffer_size;
168
169 for (;;) {
170 void *p;
171
172 ret = lzma_code(&s, LZMA_FINISH);
173
174 if (ret != LZMA_STREAM_END && ret != LZMA_OK)
175 goto fail;
176
177 if ((*buffer_size - s.avail_out > prefix_len) &&
178 memcmp(*buffer, prefix, prefix_len) == 0 &&
179 ((const uint8_t*) *buffer)[prefix_len] == extra)
180 break;
181
182 if (ret == LZMA_STREAM_END)
183 goto fail;
184
185 p = realloc(*buffer, *buffer_size*2);
186 if (!p)
187 goto fail;
188
189 s.next_out = (uint8_t*) p + ((uint8_t*) s.next_out - (uint8_t*) *buffer);
190 s.avail_out += *buffer_size;
191
192 *buffer = p;
193 *buffer_size *= 2;
194 }
195
196 b = true;
197
198fail:
199 lzma_end(&s);
200
201 return b;
202}