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