1/* This file is part of the KDE libraries
2 Copyright (C) 2000-2005 David Faure <faure@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*/
19
20#include "kbzip2filter.h"
21#include "loggingcategory.h"
22
23#include <config-compression.h>
24
25#if HAVE_BZIP2_SUPPORT
26
27// we don't need that
28#define BZ_NO_STDIO
29extern "C" {
30#include <bzlib.h>
31}
32
33#if NEED_BZ2_PREFIX
34#define bzDecompressInit(x,y,z) BZ2_bzDecompressInit(x,y,z)
35#define bzDecompressEnd(x) BZ2_bzDecompressEnd(x)
36#define bzCompressEnd(x) BZ2_bzCompressEnd(x)
37#define bzDecompress(x) BZ2_bzDecompress(x)
38#define bzCompress(x,y) BZ2_bzCompress(x, y)
39#define bzCompressInit(x,y,z,a) BZ2_bzCompressInit(x, y, z, a);
40#endif
41
42#include <QDebug>
43
44#include <qiodevice.h>
45
46// For docu on this, see /usr/doc/bzip2-0.9.5d/bzip2-0.9.5d/manual_3.html
47
48class Q_DECL_HIDDEN KBzip2Filter::Private
49{
50public:
51 Private()
52 : isInitialized(false)
53 {
54 memset(&zStream, 0, sizeof (zStream));
55 mode = 0;
56 }
57
58 bz_stream zStream;
59 int mode;
60 bool isInitialized;
61};
62
63KBzip2Filter::KBzip2Filter()
64 : d(new Private)
65{
66}
67
68KBzip2Filter::~KBzip2Filter()
69{
70 delete d;
71}
72
73bool KBzip2Filter::init(int mode)
74{
75 if (d->isInitialized) {
76 terminate();
77 }
78
79 d->zStream.next_in = nullptr;
80 d->zStream.avail_in = 0;
81 if (mode == QIODevice::ReadOnly) {
82 const int result = bzDecompressInit(&d->zStream, 0, 0);
83 if (result != BZ_OK) {
84 //qCDebug(KArchiveLog) << "bzDecompressInit returned " << result;
85 return false;
86 }
87 } else if (mode == QIODevice::WriteOnly) {
88 const int result = bzCompressInit(&d->zStream, 5, 0, 0);
89 if (result != BZ_OK) {
90 //qCDebug(KArchiveLog) << "bzDecompressInit returned " << result;
91 return false;
92 }
93 } else {
94 //qCWarning(KArchiveLog) << "Unsupported mode " << mode << ". Only QIODevice::ReadOnly and QIODevice::WriteOnly supported";
95 return false;
96 }
97 d->mode = mode;
98 d->isInitialized = true;
99 return true;
100}
101
102int KBzip2Filter::mode() const
103{
104 return d->mode;
105}
106
107bool KBzip2Filter::terminate()
108{
109 if (d->mode == QIODevice::ReadOnly) {
110 const int result = bzDecompressEnd(&d->zStream);
111 if (result != BZ_OK) {
112 //qCDebug(KArchiveLog) << "bzDecompressEnd returned " << result;
113 return false;
114 }
115 } else if (d->mode == QIODevice::WriteOnly) {
116 const int result = bzCompressEnd(&d->zStream);
117 if (result != BZ_OK) {
118 //qCDebug(KArchiveLog) << "bzCompressEnd returned " << result;
119 return false;
120 }
121 } else {
122 //qCWarning(KArchiveLog) << "Unsupported mode " << d->mode << ". Only QIODevice::ReadOnly and QIODevice::WriteOnly supported";
123 return false;
124 }
125 d->isInitialized = false;
126 return true;
127}
128
129void KBzip2Filter::reset()
130{
131 // bzip2 doesn't seem to have a reset call...
132 terminate();
133 init(d->mode);
134}
135
136void KBzip2Filter::setOutBuffer(char *data, uint maxlen)
137{
138 d->zStream.avail_out = maxlen;
139 d->zStream.next_out = data;
140}
141
142void KBzip2Filter::setInBuffer(const char *data, unsigned int size)
143{
144 d->zStream.avail_in = size;
145 d->zStream.next_in = const_cast<char *>(data);
146}
147
148int KBzip2Filter::inBufferAvailable() const
149{
150 return d->zStream.avail_in;
151}
152
153int KBzip2Filter::outBufferAvailable() const
154{
155 return d->zStream.avail_out;
156}
157
158KBzip2Filter::Result KBzip2Filter::uncompress()
159{
160 //qCDebug(KArchiveLog) << "Calling bzDecompress with avail_in=" << inBufferAvailable() << " avail_out=" << outBufferAvailable();
161 int result = bzDecompress(&d->zStream);
162 if (result < BZ_OK) {
163 qCWarning(KArchiveLog) << "bzDecompress returned" << result;
164 }
165
166 switch (result) {
167 case BZ_OK:
168 return KFilterBase::Ok;
169 case BZ_STREAM_END:
170 return KFilterBase::End;
171 default:
172 return KFilterBase::Error;
173 }
174}
175
176KBzip2Filter::Result KBzip2Filter::compress(bool finish)
177{
178 //qCDebug(KArchiveLog) << "Calling bzCompress with avail_in=" << inBufferAvailable() << " avail_out=" << outBufferAvailable();
179 int result = bzCompress(&d->zStream, finish ? BZ_FINISH : BZ_RUN);
180
181 switch (result) {
182 case BZ_OK:
183 case BZ_FLUSH_OK:
184 case BZ_RUN_OK:
185 case BZ_FINISH_OK:
186 return KFilterBase::Ok;
187 break;
188 case BZ_STREAM_END:
189 //qCDebug(KArchiveLog) << " bzCompress returned " << result;
190 return KFilterBase::End;
191 break;
192 default:
193 //qCDebug(KArchiveLog) << " bzCompress returned " << result;
194 return KFilterBase::Error;
195 break;
196 }
197}
198
199#endif /* HAVE_BZIP2_SUPPORT */
200