source: Vago/quazip-0.7.2/quazip/qioapi.cpp@ 1067

Last change on this file since 1067 was 1049, checked in by s10k, 8 years ago
File size: 11.3 KB
Line 
1/* ioapi.c -- IO base function header for compress/uncompress .zip
2 files using zlib + zip or unzip API
3
4 Version 1.01e, February 12th, 2005
5
6 Copyright (C) 1998-2005 Gilles Vollant
7
8 Modified by Sergey A. Tachenov to integrate with Qt.
9*/
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14
15#include "zlib.h"
16#include "ioapi.h"
17#include "quazip_global.h"
18#include <QIODevice>
19#if (QT_VERSION >= 0x050100)
20#define QUAZIP_QSAVEFILE_BUG_WORKAROUND
21#endif
22#ifdef QUAZIP_QSAVEFILE_BUG_WORKAROUND
23#include <QSaveFile>
24#endif
25
26/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
27
28#ifndef SEEK_CUR
29#define SEEK_CUR 1
30#endif
31
32#ifndef SEEK_END
33#define SEEK_END 2
34#endif
35
36#ifndef SEEK_SET
37#define SEEK_SET 0
38#endif
39
40voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,voidpf file,int mode)
41{
42 if (pfilefunc->zfile_func64.zopen64_file != NULL)
43 return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,file,mode);
44 else
45 {
46 return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,file,mode);
47 }
48}
49
50int call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)
51{
52 if (pfilefunc->zfile_func64.zseek64_file != NULL)
53 return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin);
54 else
55 {
56 uLong offsetTruncated = (uLong)offset;
57 if (offsetTruncated != offset)
58 return -1;
59 else
60 return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin);
61 }
62}
63
64ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)
65{
66 if (pfilefunc->zfile_func64.zseek64_file != NULL)
67 return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream);
68 else
69 {
70 uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream);
71 if ((tell_uLong) == ((uLong)-1))
72 return (ZPOS64_T)-1;
73 else
74 return tell_uLong;
75 }
76}
77
78/// @cond internal
79struct QIODevice_descriptor {
80 // Position only used for writing to sequential devices.
81 qint64 pos;
82 inline QIODevice_descriptor():
83 pos(0)
84 {}
85};
86/// @endcond
87
88voidpf ZCALLBACK qiodevice_open_file_func (
89 voidpf opaque,
90 voidpf file,
91 int mode)
92{
93 QIODevice_descriptor *d = reinterpret_cast<QIODevice_descriptor*>(opaque);
94 QIODevice *iodevice = reinterpret_cast<QIODevice*>(file);
95 QIODevice::OpenMode desiredMode;
96 if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
97 desiredMode = QIODevice::ReadOnly;
98 else if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
99 desiredMode = QIODevice::ReadWrite;
100 else if (mode & ZLIB_FILEFUNC_MODE_CREATE)
101 desiredMode = QIODevice::WriteOnly;
102 if (iodevice->isOpen()) {
103 if ((iodevice->openMode() & desiredMode) == desiredMode) {
104 if (desiredMode != QIODevice::WriteOnly
105 && iodevice->isSequential()) {
106 // We can use sequential devices only for writing.
107 delete d;
108 return NULL;
109 } else {
110 if ((desiredMode & QIODevice::WriteOnly) != 0) {
111 // open for writing, need to seek existing device
112 if (!iodevice->isSequential()) {
113 iodevice->seek(0);
114 } else {
115 d->pos = iodevice->pos();
116 }
117 }
118 }
119 return iodevice;
120 } else {
121 delete d;
122 return NULL;
123 }
124 }
125 iodevice->open(desiredMode);
126 if (iodevice->isOpen()) {
127 if (desiredMode != QIODevice::WriteOnly && iodevice->isSequential()) {
128 // We can use sequential devices only for writing.
129 iodevice->close();
130 delete d;
131 return NULL;
132 } else {
133 return iodevice;
134 }
135 } else {
136 delete d;
137 return NULL;
138 }
139}
140
141
142uLong ZCALLBACK qiodevice_read_file_func (
143 voidpf opaque,
144 voidpf stream,
145 void* buf,
146 uLong size)
147{
148 QIODevice_descriptor *d = reinterpret_cast<QIODevice_descriptor*>(opaque);
149 QIODevice *iodevice = reinterpret_cast<QIODevice*>(stream);
150 qint64 ret64 = iodevice->read((char*)buf,size);
151 uLong ret;
152 ret = (uLong) ret64;
153 if (ret64 != -1) {
154 d->pos += ret64;
155 }
156 return ret;
157}
158
159
160uLong ZCALLBACK qiodevice_write_file_func (
161 voidpf opaque,
162 voidpf stream,
163 const void* buf,
164 uLong size)
165{
166 QIODevice_descriptor *d = reinterpret_cast<QIODevice_descriptor*>(opaque);
167 QIODevice *iodevice = reinterpret_cast<QIODevice*>(stream);
168 uLong ret;
169 qint64 ret64 = iodevice->write((char*)buf,size);
170 if (ret64 != -1) {
171 d->pos += ret64;
172 }
173 ret = (uLong) ret64;
174 return ret;
175}
176
177uLong ZCALLBACK qiodevice_tell_file_func (
178 voidpf opaque,
179 voidpf stream)
180{
181 QIODevice_descriptor *d = reinterpret_cast<QIODevice_descriptor*>(opaque);
182 QIODevice *iodevice = reinterpret_cast<QIODevice*>(stream);
183 uLong ret;
184 qint64 ret64;
185 if (iodevice->isSequential()) {
186 ret64 = d->pos;
187 } else {
188 ret64 = iodevice->pos();
189 }
190 ret = static_cast<uLong>(ret64);
191 return ret;
192}
193
194ZPOS64_T ZCALLBACK qiodevice64_tell_file_func (
195 voidpf opaque,
196 voidpf stream)
197{
198 QIODevice_descriptor *d = reinterpret_cast<QIODevice_descriptor*>(opaque);
199 QIODevice *iodevice = reinterpret_cast<QIODevice*>(stream);
200 qint64 ret;
201 if (iodevice->isSequential()) {
202 ret = d->pos;
203 } else {
204 ret = iodevice->pos();
205 }
206 return static_cast<ZPOS64_T>(ret);
207}
208
209int ZCALLBACK qiodevice_seek_file_func (
210 voidpf /*opaque UNUSED*/,
211 voidpf stream,
212 uLong offset,
213 int origin)
214{
215 QIODevice *iodevice = reinterpret_cast<QIODevice*>(stream);
216 if (iodevice->isSequential()) {
217 if (origin == ZLIB_FILEFUNC_SEEK_END
218 && offset == 0) {
219 // sequential devices are always at end (needed in mdAppend)
220 return 0;
221 } else {
222 qWarning("qiodevice_seek_file_func() called for sequential device");
223 return -1;
224 }
225 }
226 uLong qiodevice_seek_result=0;
227 int ret;
228 switch (origin)
229 {
230 case ZLIB_FILEFUNC_SEEK_CUR :
231 qiodevice_seek_result = ((QIODevice*)stream)->pos() + offset;
232 break;
233 case ZLIB_FILEFUNC_SEEK_END :
234 qiodevice_seek_result = ((QIODevice*)stream)->size() - offset;
235 break;
236 case ZLIB_FILEFUNC_SEEK_SET :
237 qiodevice_seek_result = offset;
238 break;
239 default:
240 return -1;
241 }
242 ret = !iodevice->seek(qiodevice_seek_result);
243 return ret;
244}
245
246int ZCALLBACK qiodevice64_seek_file_func (
247 voidpf /*opaque UNUSED*/,
248 voidpf stream,
249 ZPOS64_T offset,
250 int origin)
251{
252 QIODevice *iodevice = reinterpret_cast<QIODevice*>(stream);
253 if (iodevice->isSequential()) {
254 if (origin == ZLIB_FILEFUNC_SEEK_END
255 && offset == 0) {
256 // sequential devices are always at end (needed in mdAppend)
257 return 0;
258 } else {
259 qWarning("qiodevice_seek_file_func() called for sequential device");
260 return -1;
261 }
262 }
263 qint64 qiodevice_seek_result=0;
264 int ret;
265 switch (origin)
266 {
267 case ZLIB_FILEFUNC_SEEK_CUR :
268 qiodevice_seek_result = ((QIODevice*)stream)->pos() + offset;
269 break;
270 case ZLIB_FILEFUNC_SEEK_END :
271 qiodevice_seek_result = ((QIODevice*)stream)->size() - offset;
272 break;
273 case ZLIB_FILEFUNC_SEEK_SET :
274 qiodevice_seek_result = offset;
275 break;
276 default:
277 return -1;
278 }
279 ret = !iodevice->seek(qiodevice_seek_result);
280 return ret;
281}
282
283int ZCALLBACK qiodevice_close_file_func (
284 voidpf opaque,
285 voidpf stream)
286{
287 QIODevice_descriptor *d = reinterpret_cast<QIODevice_descriptor*>(opaque);
288 delete d;
289 QIODevice *device = reinterpret_cast<QIODevice*>(stream);
290#ifdef QUAZIP_QSAVEFILE_BUG_WORKAROUND
291 // QSaveFile terribly breaks the is-a idiom:
292 // it IS a QIODevice, but it is NOT compatible with it: close() is private
293 QSaveFile *file = qobject_cast<QSaveFile*>(device);
294 if (file != NULL) {
295 // We have to call the ugly commit() instead:
296 return file->commit() ? 0 : -1;
297 }
298#endif
299 device->close();
300 return 0;
301}
302
303int ZCALLBACK qiodevice_fakeclose_file_func (
304 voidpf opaque,
305 voidpf /*stream*/)
306{
307 QIODevice_descriptor *d = reinterpret_cast<QIODevice_descriptor*>(opaque);
308 delete d;
309 return 0;
310}
311
312int ZCALLBACK qiodevice_error_file_func (
313 voidpf /*opaque UNUSED*/,
314 voidpf /*stream UNUSED*/)
315{
316 // can't check for error due to the QIODevice API limitation
317 return 0;
318}
319
320void fill_qiodevice_filefunc (
321 zlib_filefunc_def* pzlib_filefunc_def)
322{
323 pzlib_filefunc_def->zopen_file = qiodevice_open_file_func;
324 pzlib_filefunc_def->zread_file = qiodevice_read_file_func;
325 pzlib_filefunc_def->zwrite_file = qiodevice_write_file_func;
326 pzlib_filefunc_def->ztell_file = qiodevice_tell_file_func;
327 pzlib_filefunc_def->zseek_file = qiodevice_seek_file_func;
328 pzlib_filefunc_def->zclose_file = qiodevice_close_file_func;
329 pzlib_filefunc_def->zerror_file = qiodevice_error_file_func;
330 pzlib_filefunc_def->opaque = new QIODevice_descriptor;
331}
332
333void fill_qiodevice64_filefunc (
334 zlib_filefunc64_def* pzlib_filefunc_def)
335{
336 // Open functions are the same for Qt.
337 pzlib_filefunc_def->zopen64_file = qiodevice_open_file_func;
338 pzlib_filefunc_def->zread_file = qiodevice_read_file_func;
339 pzlib_filefunc_def->zwrite_file = qiodevice_write_file_func;
340 pzlib_filefunc_def->ztell64_file = qiodevice64_tell_file_func;
341 pzlib_filefunc_def->zseek64_file = qiodevice64_seek_file_func;
342 pzlib_filefunc_def->zclose_file = qiodevice_close_file_func;
343 pzlib_filefunc_def->zerror_file = qiodevice_error_file_func;
344 pzlib_filefunc_def->opaque = new QIODevice_descriptor;
345 pzlib_filefunc_def->zfakeclose_file = qiodevice_fakeclose_file_func;
346}
347
348void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32)
349{
350 p_filefunc64_32->zfile_func64.zopen64_file = NULL;
351 p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file;
352 p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
353 p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file;
354 p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file;
355 p_filefunc64_32->zfile_func64.ztell64_file = NULL;
356 p_filefunc64_32->zfile_func64.zseek64_file = NULL;
357 p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file;
358 p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
359 p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque;
360 p_filefunc64_32->zfile_func64.zfakeclose_file = NULL;
361 p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file;
362 p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file;
363}
Note: See TracBrowser for help on using the repository browser.