chiark / gitweb /
readahead: fix calculation of percentage
[elogind.git] / src / journal / compress.c
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
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
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
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
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
29 bool 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
62 fail:
63         lzma_end(&s);
64
65         return b;
66 }
67
68 bool 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
128 fail:
129         lzma_end(&s);
130
131         return b;
132 }
133
134 bool 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
204 fail:
205         lzma_end(&s);
206
207         return b;
208 }