]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/journal/compress.c
journal: document new catalog APIs
[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
27#include "compress.h"
28
29bool compress_blob(const void *src, uint64_t src_size, void *dst, uint64_t *dst_size) {
30 lzma_stream s = LZMA_STREAM_INIT;
31 lzma_ret ret;
32 bool b = false;
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
42 ret = lzma_easy_encoder(&s, LZMA_PRESET_DEFAULT, LZMA_CHECK_NONE);
43 if (ret != LZMA_OK)
44 return false;
45
46 s.next_in = src;
47 s.avail_in = src_size;
48 s.next_out = dst;
49 s.avail_out = src_size;
50
51 /* Does it fit? */
52 if (lzma_code(&s, LZMA_FINISH) != LZMA_STREAM_END)
53 goto fail;
54
55 /* Is it actually shorter? */
56 if (s.avail_out == 0)
57 goto fail;
58
59 *dst_size = src_size - s.avail_out;
60 b = true;
61
62fail:
63 lzma_end(&s);
64
65 return b;
66}
67
68bool uncompress_blob(const void *src, uint64_t src_size,
69 void **dst, uint64_t *dst_alloc_size, uint64_t* dst_size) {
70
71 lzma_stream s = LZMA_STREAM_INIT;
72 lzma_ret ret;
73 bool b = false;
74
75 assert(src);
76 assert(src_size > 0);
77 assert(dst);
78 assert(dst_alloc_size);
79 assert(dst_size);
80 assert(*dst_alloc_size == 0 || *dst);
81
82 ret = lzma_stream_decoder(&s, UINT64_MAX, 0);
83 if (ret != LZMA_OK)
84 return false;
85
86 if (*dst_alloc_size <= src_size) {
87 void *p;
88
89 p = realloc(*dst, src_size*2);
90 if (!p)
91 return false;
92
93 *dst = p;
94 *dst_alloc_size = src_size*2;
95 }
96
97 s.next_in = src;
98 s.avail_in = src_size;
99
100 s.next_out = *dst;
101 s.avail_out = *dst_alloc_size;
102
103 for (;;) {
104 void *p;
105
106 ret = lzma_code(&s, LZMA_FINISH);
107
108 if (ret == LZMA_STREAM_END)
109 break;
110
111 if (ret != LZMA_OK)
112 goto fail;
113
114 p = realloc(*dst, *dst_alloc_size*2);
115 if (!p)
116 goto fail;
117
118 s.next_out = (uint8_t*) p + ((uint8_t*) s.next_out - (uint8_t*) *dst);
119 s.avail_out += *dst_alloc_size;
120
121 *dst = p;
122 *dst_alloc_size *= 2;
123 }
124
125 *dst_size = *dst_alloc_size - s.avail_out;
126 b = true;
127
128fail:
129 lzma_end(&s);
130
131 return b;
132}
133
134bool uncompress_startswith(const void *src, uint64_t src_size,
135 void **buffer, uint64_t *buffer_size,
136 const void *prefix, uint64_t prefix_len,
137 uint8_t extra) {
138
139 lzma_stream s = LZMA_STREAM_INIT;
140 lzma_ret ret;
141 bool b = false;
142
143 /* Checks whether the uncompressed blob starts with the
144 * mentioned prefix. The byte extra needs to follow the
145 * prefix */
146
147 assert(src);
148 assert(src_size > 0);
149 assert(buffer);
150 assert(buffer_size);
151 assert(prefix);
152 assert(*buffer_size == 0 || *buffer);
153
154 ret = lzma_stream_decoder(&s, UINT64_MAX, 0);
155 if (ret != LZMA_OK)
156 return false;
157
158 if (*buffer_size <= prefix_len) {
159 void *p;
160
161 p = realloc(*buffer, prefix_len*2);
162 if (!p)
163 return false;
164
165 *buffer = p;
166 *buffer_size = prefix_len*2;
167 }
168
169 s.next_in = src;
170 s.avail_in = src_size;
171
172 s.next_out = *buffer;
173 s.avail_out = *buffer_size;
174
175 for (;;) {
176 void *p;
177
178 ret = lzma_code(&s, LZMA_FINISH);
179
180 if (ret != LZMA_STREAM_END && ret != LZMA_OK)
181 goto fail;
182
183 if ((*buffer_size - s.avail_out > prefix_len) &&
184 memcmp(*buffer, prefix, prefix_len) == 0 &&
185 ((const uint8_t*) *buffer)[prefix_len] == extra)
186 break;
187
188 if (ret == LZMA_STREAM_END)
189 goto fail;
190
191 p = realloc(*buffer, *buffer_size*2);
192 if (!p)
193 goto fail;
194
195 s.next_out = (uint8_t*) p + ((uint8_t*) s.next_out - (uint8_t*) *buffer);
196 s.avail_out += *buffer_size;
197
198 *buffer = p;
199 *buffer_size *= 2;
200 }
201
202 b = true;
203
204fail:
205 lzma_end(&s);
206
207 return b;
208}