VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/zip/zip.cpp@ 67482

Last change on this file since 67482 was 62564, checked in by vboxsync, 8 years ago

IPRT: Mark unused parameters.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 56.6 KB
Line 
1/* $Id: zip.cpp 62564 2016-07-26 14:43:03Z vboxsync $ */
2/** @file
3 * IPRT - Compression.
4 */
5
6/*
7 * Copyright (C) 2006-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Defined Constants And Macros *
30*********************************************************************************************************************************/
31#define RTZIP_USE_STORE 1
32#define RTZIP_USE_ZLIB 1
33//#define RTZIP_USE_BZLIB 1
34#define RTZIP_USE_LZF 1
35#define RTZIP_LZF_BLOCK_BY_BLOCK
36//#define RTZIP_USE_LZJB 1
37//#define RTZIP_USE_LZO 1
38
39/** @todo FastLZ? QuickLZ? Others? */
40
41
42/*********************************************************************************************************************************
43* Header Files *
44*********************************************************************************************************************************/
45#ifdef RTZIP_USE_BZLIB
46# include <bzlib.h>
47#endif
48#ifdef RTZIP_USE_ZLIB
49# include <zlib.h>
50#endif
51#ifdef RTZIP_USE_LZF
52# include <lzf.h>
53# include <iprt/crc.h>
54#endif
55#ifdef RTZIP_USE_LZJB
56# include "lzjb.h"
57#endif
58#ifdef RTZIP_USE_LZO
59# include <lzo/lzo1x.h>
60#endif
61
62#include <iprt/zip.h>
63#include "internal/iprt.h"
64
65/*#include <iprt/asm.h>*/
66#include <iprt/alloc.h>
67#include <iprt/assert.h>
68#include <iprt/err.h>
69#include <iprt/log.h>
70#include <iprt/string.h>
71
72#include <errno.h>
73
74
75/*********************************************************************************************************************************
76* Structures and Typedefs *
77*********************************************************************************************************************************/
78
79#ifdef RTZIP_USE_LZF
80
81/**
82 * LZF block header.
83 */
84#pragma pack(1) /* paranoia */
85typedef struct RTZIPLZFHDR
86{
87 /** Magic word (RTZIPLZFHDR_MAGIC). */
88 uint16_t u16Magic;
89 /** The number of bytes of data following this header. */
90 uint16_t cbData;
91 /** The CRC32 of the block. */
92 uint32_t u32CRC;
93 /** The size of the uncompressed data in bytes. */
94 uint16_t cbUncompressed;
95} RTZIPLZFHDR;
96#pragma pack()
97/** Pointer to a LZF block header. */
98typedef RTZIPLZFHDR *PRTZIPLZFHDR;
99/** Pointer to a const LZF block header. */
100typedef const RTZIPLZFHDR *PCRTZIPLZFHDR;
101
102/** The magic of a LZF block header. */
103#define RTZIPLZFHDR_MAGIC ('Z' | ('V' << 8))
104
105/** The max compressed data size.
106 * The maximum size of a block is currently 16KB.
107 * This is very important so we don't have to move input buffers around. */
108#define RTZIPLZF_MAX_DATA_SIZE (16384 - sizeof(RTZIPLZFHDR))
109
110/** The max uncompressed data size.
111 * This is important so we don't overflow the spill buffer in the decompressor. */
112#define RTZIPLZF_MAX_UNCOMPRESSED_DATA_SIZE (32*_1K)
113
114#endif /* RTZIP_USE_LZF */
115
116
117/**
118 * Compressor/Decompressor instance data.
119 */
120typedef struct RTZIPCOMP
121{
122 /** Output buffer. */
123 uint8_t abBuffer[_128K];
124 /** Compression output consumer. */
125 PFNRTZIPOUT pfnOut;
126 /** User argument for the callback. */
127 void *pvUser;
128
129 /**
130 * @copydoc RTZipCompress
131 */
132 DECLCALLBACKMEMBER(int, pfnCompress)(PRTZIPCOMP pZip, const void *pvBuf, size_t cbBuf);
133
134 /**
135 * @copydoc RTZipCompFinish
136 */
137 DECLCALLBACKMEMBER(int, pfnFinish)(PRTZIPCOMP pZip);
138
139 /**
140 * @copydoc RTZipCompDestroy
141 */
142 DECLCALLBACKMEMBER(int, pfnDestroy)(PRTZIPCOMP pZip);
143
144 /** Compression type. */
145 RTZIPTYPE enmType;
146 /** Type specific data. */
147 union
148 {
149#ifdef RTZIP_USE_STORE
150 /** Simple storing. */
151 struct
152 {
153 /** Current buffer position. (where to start write) */
154 uint8_t *pb;
155 } Store;
156#endif
157#ifdef RTZIP_USE_ZLIB
158 /** Zlib stream. */
159 z_stream Zlib;
160#endif
161#ifdef RTZIP_USE_BZLIB
162 /** BZlib stream. */
163 bz_stream BZlib;
164#endif
165#ifdef RTZIP_USE_LZF
166 /** LZF stream. */
167 struct
168 {
169 /** Current output buffer position. */
170 uint8_t *pbOutput;
171 /** The input buffer position. */
172 uint8_t *pbInput;
173 /** The number of free bytes in the input buffer. */
174 size_t cbInputFree;
175 /** The input buffer. */
176 uint8_t abInput[RTZIPLZF_MAX_UNCOMPRESSED_DATA_SIZE];
177 } LZF;
178#endif
179
180 } u;
181} RTZIPCOMP;
182
183
184
185/**
186 * Decompressor instance data.
187 */
188typedef struct RTZIPDECOMP
189{
190 /** Input buffer. */
191 uint8_t abBuffer[_128K];
192 /** Decompression input producer. */
193 PFNRTZIPIN pfnIn;
194 /** User argument for the callback. */
195 void *pvUser;
196
197 /**
198 * @copydoc RTZipDecompress
199 */
200 DECLCALLBACKMEMBER(int, pfnDecompress)(PRTZIPDECOMP pZip, void *pvBuf, size_t cbBuf, size_t *pcbWritten);
201
202 /**
203 * @copydoc RTZipDecompDestroy
204 */
205 DECLCALLBACKMEMBER(int, pfnDestroy)(PRTZIPDECOMP pZip);
206
207 /** Compression type. */
208 RTZIPTYPE enmType;
209 /** Type specific data. */
210 union
211 {
212#ifdef RTZIP_USE_STORE
213 /** Simple storing. */
214 struct
215 {
216 /** Current buffer position. (where to start read) */
217 uint8_t *pb;
218 /** Number of bytes left in the buffer. */
219 size_t cbBuffer;
220 } Store;
221#endif
222#ifdef RTZIP_USE_ZLIB
223 /** Zlib stream. */
224 z_stream Zlib;
225#endif
226#ifdef RTZIP_USE_BZLIB
227 /** BZlib stream. */
228 bz_stream BZlib;
229#endif
230#ifdef RTZIP_USE_LZF
231 /** LZF 'stream'. */
232 struct
233 {
234# ifndef RTZIP_LZF_BLOCK_BY_BLOCK
235 /** Current input buffer position. */
236 uint8_t *pbInput;
237 /** The number of bytes left in the input buffer. */
238 size_t cbInput;
239# endif
240 /** The spill buffer.
241 * LZF is a block based compressor and not a stream compressor. So,
242 * we have to decompress full blocks if we want to get any of the data.
243 * This buffer is to store the spill after decompressing a block. */
244 uint8_t abSpill[RTZIPLZF_MAX_UNCOMPRESSED_DATA_SIZE];
245 /** The number of bytes left spill buffer. */
246 unsigned cbSpill;
247 /** The current spill buffer position. */
248 uint8_t *pbSpill;
249 } LZF;
250#endif
251
252 } u;
253} RTZIPDECOM;
254
255
256
257#ifdef RTZIP_USE_STORE
258
259/**
260 * @copydoc RTZipCompress
261 */
262static DECLCALLBACK(int) rtZipStoreCompress(PRTZIPCOMP pZip, const void *pvBuf, size_t cbBuf)
263{
264 uint8_t *pbDst = pZip->u.Store.pb;
265 while (cbBuf)
266 {
267 /*
268 * Flush.
269 */
270 size_t cb = sizeof(pZip->abBuffer) - (size_t)(pbDst - &pZip->abBuffer[0]); /* careful here, g++ 4.1.2 screws up easily */
271 if (cb == 0)
272 {
273 int rc = pZip->pfnOut(pZip->pvUser, &pZip->abBuffer[0], sizeof(pZip->abBuffer));
274 if (RT_FAILURE(rc))
275 return rc;
276
277 cb = sizeof(pZip->abBuffer);
278 pbDst = &pZip->abBuffer[0];
279 }
280
281 /*
282 * Add to the buffer and advance.
283 */
284 if (cbBuf < cb)
285 cb = cbBuf;
286 memcpy(pbDst, pvBuf, cb);
287
288 pbDst += cb;
289 cbBuf -= cb;
290 pvBuf = (uint8_t *)pvBuf + cb;
291 }
292 pZip->u.Store.pb = pbDst;
293 return VINF_SUCCESS;
294}
295
296
297/**
298 * @copydoc RTZipCompFinish
299 */
300static DECLCALLBACK(int) rtZipStoreCompFinish(PRTZIPCOMP pZip)
301{
302 size_t cb = (uintptr_t)pZip->u.Store.pb - (uintptr_t)&pZip->abBuffer[0];
303 if (cb > 0)
304 {
305 int rc = pZip->pfnOut(pZip->pvUser, &pZip->abBuffer[0], cb);
306 if (RT_FAILURE(rc))
307 return rc;
308 }
309 return VINF_SUCCESS;
310}
311
312
313/**
314 * @copydoc RTZipCompDestroy
315 */
316static DECLCALLBACK(int) rtZipStoreCompDestroy(PRTZIPCOMP pZip)
317{
318 NOREF(pZip);
319 return VINF_SUCCESS;
320}
321
322
323/**
324 * Initializes the compressor instance.
325 * @returns iprt status code.
326 * @param pZip The compressor instance.
327 * @param enmLevel The desired compression level.
328 */
329static DECLCALLBACK(int) rtZipStoreCompInit(PRTZIPCOMP pZip, RTZIPLEVEL enmLevel)
330{
331 NOREF(enmLevel);
332 pZip->pfnCompress = rtZipStoreCompress;
333 pZip->pfnFinish = rtZipStoreCompFinish;
334 pZip->pfnDestroy = rtZipStoreCompDestroy;
335
336 pZip->u.Store.pb = &pZip->abBuffer[1];
337 return VINF_SUCCESS;
338}
339
340
341/**
342 * @copydoc RTZipDecompress
343 */
344static DECLCALLBACK(int) rtZipStoreDecompress(PRTZIPDECOMP pZip, void *pvBuf, size_t cbBuf, size_t *pcbWritten)
345{
346 size_t cbWritten = 0;
347 while (cbBuf)
348 {
349 /*
350 * Fill buffer.
351 */
352 size_t cb = pZip->u.Store.cbBuffer;
353 if (cb <= 0)
354 {
355 int rc = pZip->pfnIn(pZip->pvUser, &pZip->abBuffer[0], sizeof(pZip->abBuffer), &cb);
356 if (RT_FAILURE(rc))
357 return rc;
358 pZip->u.Store.cbBuffer = cb;
359 pZip->u.Store.pb = &pZip->abBuffer[0];
360 }
361
362 /*
363 * No more data?
364 */
365 if (cb == 0)
366 {
367 if (pcbWritten)
368 {
369 *pcbWritten = cbWritten;
370 return VINF_SUCCESS;
371 }
372 return VERR_NO_DATA;
373 }
374
375 /*
376 * Add to the buffer and advance.
377 */
378 if (cbBuf < cb)
379 cb = cbBuf;
380 memcpy(pvBuf, pZip->u.Store.pb, cb);
381 pZip->u.Store.pb += cb;
382 pZip->u.Store.cbBuffer -= cb;
383 cbBuf -= cb;
384 pvBuf = (char *)pvBuf + cb;
385 cbWritten += cb;
386 }
387 if (pcbWritten)
388 *pcbWritten = cbWritten;
389 return VINF_SUCCESS;
390}
391
392
393/**
394 * @copydoc RTZipDecompDestroy
395 */
396static DECLCALLBACK(int) rtZipStoreDecompDestroy(PRTZIPDECOMP pZip)
397{
398 NOREF(pZip);
399 return VINF_SUCCESS;
400}
401
402
403/**
404 * Initialize the decompressor instance.
405 * @returns iprt status code.
406 * @param pZip The decompressor instance.
407 */
408static DECLCALLBACK(int) rtZipStoreDecompInit(PRTZIPDECOMP pZip)
409{
410 pZip->pfnDecompress = rtZipStoreDecompress;
411 pZip->pfnDestroy = rtZipStoreDecompDestroy;
412
413 pZip->u.Store.pb = &pZip->abBuffer[0];
414 pZip->u.Store.cbBuffer = 0;
415 return VINF_SUCCESS;
416}
417
418#endif /* RTZIP_USE_STORE */
419
420
421#ifdef RTZIP_USE_ZLIB
422
423/*
424 * Missing definitions from zutil.h. We need these constants for calling
425 * inflateInit2() / deflateInit2().
426 */
427# ifndef Z_DEF_WBITS
428# define Z_DEF_WBITS MAX_WBITS
429# endif
430# ifndef Z_DEF_MEM_LEVEL
431# define Z_DEF_MEM_LEVEL 8
432# endif
433
434/**
435 * Convert from zlib errno to iprt status code.
436 * @returns iprt status code.
437 * @param rc Zlib error code.
438 * @param fCompressing Set if we're compressing, clear if decompressing.
439 */
440static int zipErrConvertFromZlib(int rc, bool fCompressing)
441{
442 switch (rc)
443 {
444 case Z_OK:
445 return VINF_SUCCESS;
446
447 case Z_STREAM_ERROR:
448 return VERR_ZIP_CORRUPTED;
449
450 case Z_DATA_ERROR:
451 return fCompressing ? VERR_ZIP_ERROR : VERR_ZIP_CORRUPTED;
452
453 case Z_MEM_ERROR:
454 return VERR_ZIP_NO_MEMORY;
455
456 case Z_BUF_ERROR:
457 return VERR_ZIP_ERROR;
458
459 case Z_VERSION_ERROR:
460 return VERR_ZIP_UNSUPPORTED_VERSION;
461
462 case Z_ERRNO: /* We shouldn't see this status! */
463 default:
464 AssertMsgFailed(("%d\n", rc));
465 if (rc >= 0)
466 return VINF_SUCCESS;
467 return VERR_ZIP_ERROR;
468 }
469}
470
471
472/**
473 * @copydoc RTZipCompress
474 */
475static DECLCALLBACK(int) rtZipZlibCompress(PRTZIPCOMP pZip, const void *pvBuf, size_t cbBuf)
476{
477 pZip->u.Zlib.next_in = (Bytef *)pvBuf;
478 pZip->u.Zlib.avail_in = (uInt)cbBuf; Assert(pZip->u.Zlib.avail_in == cbBuf);
479 while (pZip->u.Zlib.avail_in > 0)
480 {
481 /*
482 * Flush output buffer?
483 */
484 if (pZip->u.Zlib.avail_out <= 0)
485 {
486 int rc = pZip->pfnOut(pZip->pvUser, &pZip->abBuffer[0], sizeof(pZip->abBuffer) - pZip->u.Zlib.avail_out);
487 if (RT_FAILURE(rc))
488 return rc;
489 pZip->u.Zlib.avail_out = sizeof(pZip->abBuffer);
490 pZip->u.Zlib.next_out = &pZip->abBuffer[0];
491 }
492
493 /*
494 * Pass it on to zlib.
495 */
496 int rc = deflate(&pZip->u.Zlib, Z_NO_FLUSH);
497 if (rc != Z_OK)
498 return zipErrConvertFromZlib(rc, true /*fCompressing*/);
499 }
500 return VINF_SUCCESS;
501}
502
503
504/**
505 * @copydoc RTZipCompFinish
506 */
507static DECLCALLBACK(int) rtZipZlibCompFinish(PRTZIPCOMP pZip)
508{
509 int rc = Z_OK;
510 for (;;)
511 {
512 /*
513 * Flush outstanding stuff. writes.
514 */
515 if (rc == Z_STREAM_END || pZip->u.Zlib.avail_out <= 0)
516 {
517 int rc2 = pZip->pfnOut(pZip->pvUser, &pZip->abBuffer[0], sizeof(pZip->abBuffer) - pZip->u.Zlib.avail_out);
518 if (RT_FAILURE(rc2))
519 return rc2;
520 pZip->u.Zlib.avail_out = sizeof(pZip->abBuffer);
521 pZip->u.Zlib.next_out = &pZip->abBuffer[0];
522 if (rc == Z_STREAM_END)
523 return VINF_SUCCESS;
524 }
525
526 /*
527 * Tell zlib to flush.
528 */
529 rc = deflate(&pZip->u.Zlib, Z_FINISH);
530 if (rc != Z_OK && rc != Z_STREAM_END)
531 return zipErrConvertFromZlib(rc, true /*fCompressing*/);
532 }
533}
534
535
536/**
537 * @copydoc RTZipCompDestroy
538 */
539static DECLCALLBACK(int) rtZipZlibCompDestroy(PRTZIPCOMP pZip)
540{
541 /*
542 * Terminate the deflate instance.
543 */
544 int rc = deflateEnd(&pZip->u.Zlib);
545 if (rc != Z_OK)
546 rc = zipErrConvertFromZlib(rc, true /*fCompressing*/);
547 return rc;
548}
549
550
551/**
552 * Initializes the compressor instance.
553 * @returns iprt status code.
554 * @param pZip The compressor instance.
555 * @param enmLevel The desired compression level.
556 * @param fZlibHeader If true, write the Zlib header.
557 */
558static DECLCALLBACK(int) rtZipZlibCompInit(PRTZIPCOMP pZip, RTZIPLEVEL enmLevel, bool fZlibHeader)
559{
560 pZip->pfnCompress = rtZipZlibCompress;
561 pZip->pfnFinish = rtZipZlibCompFinish;
562 pZip->pfnDestroy = rtZipZlibCompDestroy;
563
564 int iLevel = Z_DEFAULT_COMPRESSION;
565 switch (enmLevel)
566 {
567 case RTZIPLEVEL_STORE: iLevel = 0; break;
568 case RTZIPLEVEL_FAST: iLevel = 2; break;
569 case RTZIPLEVEL_DEFAULT: iLevel = Z_DEFAULT_COMPRESSION; break;
570 case RTZIPLEVEL_MAX: iLevel = 9; break;
571 }
572
573 memset(&pZip->u.Zlib, 0, sizeof(pZip->u.Zlib));
574 pZip->u.Zlib.next_out = &pZip->abBuffer[1];
575 pZip->u.Zlib.avail_out = sizeof(pZip->abBuffer) - 1;
576 pZip->u.Zlib.opaque = pZip;
577
578 int rc = deflateInit2(&pZip->u.Zlib, iLevel, Z_DEFLATED, fZlibHeader ? Z_DEF_WBITS : -Z_DEF_WBITS,
579 Z_DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
580 return rc >= 0 ? rc = VINF_SUCCESS : zipErrConvertFromZlib(rc, true /*fCompressing*/);
581}
582
583
584/**
585 * @copydoc RTZipDecompress
586 */
587static DECLCALLBACK(int) rtZipZlibDecompress(PRTZIPDECOMP pZip, void *pvBuf, size_t cbBuf, size_t *pcbWritten)
588{
589 pZip->u.Zlib.next_out = (Bytef *)pvBuf;
590 pZip->u.Zlib.avail_out = (uInt)cbBuf;
591 Assert(pZip->u.Zlib.avail_out == cbBuf);
592
593 /*
594 * Be greedy reading input, even if no output buffer is left. It's possible
595 * that it's just the end of stream marker which needs to be read. Happens
596 * for incompressible blocks just larger than the input buffer size.
597 */
598 while (pZip->u.Zlib.avail_out > 0 || pZip->u.Zlib.avail_in <= 0)
599 {
600 /*
601 * Read more input?
602 */
603 if (pZip->u.Zlib.avail_in <= 0)
604 {
605 size_t cb = sizeof(pZip->abBuffer);
606 int rc = pZip->pfnIn(pZip->pvUser, &pZip->abBuffer[0], sizeof(pZip->abBuffer), &cb);
607 if (RT_FAILURE(rc))
608 return rc;
609 pZip->u.Zlib.avail_in = (uInt)cb; Assert(pZip->u.Zlib.avail_in == cb);
610 pZip->u.Zlib.next_in = &pZip->abBuffer[0];
611 }
612
613 /*
614 * Pass it on to zlib.
615 */
616 int rc = inflate(&pZip->u.Zlib, Z_NO_FLUSH);
617 if (rc == Z_STREAM_END)
618 {
619 if (pcbWritten)
620 *pcbWritten = cbBuf - pZip->u.Zlib.avail_out;
621 else if (pZip->u.Zlib.avail_out > 0)
622 return VERR_NO_DATA;
623 break;
624 }
625 if (rc != Z_OK)
626 return zipErrConvertFromZlib(rc, false /*fCompressing*/);
627 }
628 return VINF_SUCCESS;
629}
630
631
632/**
633 * @copydoc RTZipDecompDestroy
634 */
635static DECLCALLBACK(int) rtZipZlibDecompDestroy(PRTZIPDECOMP pZip)
636{
637 /*
638 * Terminate the deflate instance.
639 */
640 int rc = inflateEnd(&pZip->u.Zlib);
641 if (rc != Z_OK)
642 rc = zipErrConvertFromZlib(rc, false /*fCompressing*/);
643 return rc;
644}
645
646
647/**
648 * Initialize the decompressor instance.
649 * @returns iprt status code.
650 * @param pZip The decompressor instance.
651 * @param fZlibHeader If true, expect the Zlib header.
652 */
653static DECLCALLBACK(int) rtZipZlibDecompInit(PRTZIPDECOMP pZip, bool fZlibHeader)
654{
655 pZip->pfnDecompress = rtZipZlibDecompress;
656 pZip->pfnDestroy = rtZipZlibDecompDestroy;
657
658 memset(&pZip->u.Zlib, 0, sizeof(pZip->u.Zlib));
659 pZip->u.Zlib.opaque = pZip;
660
661 int rc = inflateInit2(&pZip->u.Zlib, fZlibHeader ? Z_DEF_WBITS : -Z_DEF_WBITS);
662 return rc >= 0 ? VINF_SUCCESS : zipErrConvertFromZlib(rc, false /*fCompressing*/);
663}
664
665#endif /* RTZIP_USE_ZLIB */
666
667
668#ifdef RTZIP_USE_BZLIB
669/**
670 * Convert from BZlib errno to iprt status code.
671 * @returns iprt status code.
672 * @param rc BZlib error code.
673 */
674static int zipErrConvertFromBZlib(int rc)
675{
676 /** @todo proper bzlib error conversion. */
677 switch (rc)
678 {
679 case BZ_SEQUENCE_ERROR:
680 AssertMsgFailed(("BZ_SEQUENCE_ERROR shall not happen!\n"));
681 return VERR_GENERAL_FAILURE;
682 case BZ_PARAM_ERROR:
683 return VERR_INVALID_PARAMETER;
684 case BZ_MEM_ERROR:
685 return VERR_NO_MEMORY;
686 case BZ_DATA_ERROR:
687 case BZ_DATA_ERROR_MAGIC:
688 case BZ_IO_ERROR:
689 case BZ_UNEXPECTED_EOF:
690 case BZ_CONFIG_ERROR:
691 return VERR_GENERAL_FAILURE;
692 case BZ_OUTBUFF_FULL:
693 AssertMsgFailed(("BZ_OUTBUFF_FULL shall not happen!\n"));
694 return VERR_GENERAL_FAILURE;
695 default:
696 if (rc >= 0)
697 return VINF_SUCCESS;
698 return VERR_GENERAL_FAILURE;
699 }
700}
701
702
703/**
704 * @copydoc RTZipCompress
705 */
706static DECLCALLBACK(int) rtZipBZlibCompress(PRTZIPCOMP pZip, const void *pvBuf, size_t cbBuf)
707{
708 pZip->u.BZlib.next_in = (char *)pvBuf;
709 pZip->u.BZlib.avail_in = cbBuf;
710 while (pZip->u.BZlib.avail_in > 0)
711 {
712 /*
713 * Flush output buffer?
714 */
715 if (pZip->u.BZlib.avail_out <= 0)
716 {
717 int rc = pZip->pfnOut(pZip->pvUser, &pZip->abBuffer[0], sizeof(pZip->abBuffer) - pZip->u.BZlib.avail_out);
718 if (RT_FAILURE(rc))
719 return rc;
720 pZip->u.BZlib.avail_out = sizeof(pZip->abBuffer);
721 pZip->u.BZlib.next_out = (char *)&pZip->abBuffer[0];
722 }
723
724 /*
725 * Pass it on to zlib.
726 */
727 int rc = BZ2_bzCompress(&pZip->u.BZlib, BZ_RUN);
728 if (rc < 0 && rc != BZ_OUTBUFF_FULL)
729 return zipErrConvertFromBZlib(rc);
730 }
731 return VINF_SUCCESS;
732}
733
734
735/**
736 * @copydoc RTZipCompFinish
737 */
738static DECLCALLBACK(int) rtZipBZlibCompFinish(PRTZIPCOMP pZip)
739{
740 int rc = BZ_FINISH_OK;
741 for (;;)
742 {
743 /*
744 * Flush output buffer?
745 */
746 if (rc == BZ_STREAM_END || pZip->u.BZlib.avail_out <= 0)
747 {
748 int rc2 = pZip->pfnOut(pZip->pvUser, &pZip->abBuffer[0], sizeof(pZip->abBuffer) - pZip->u.BZlib.avail_out);
749 if (RT_FAILURE(rc2))
750 return rc2;
751 pZip->u.BZlib.avail_out = sizeof(pZip->abBuffer);
752 pZip->u.BZlib.next_out = (char *)&pZip->abBuffer[0];
753 if (rc == BZ_STREAM_END)
754 return VINF_SUCCESS;
755 }
756
757 /*
758 * Tell BZlib to finish it.
759 */
760 rc = BZ2_bzCompress(&pZip->u.BZlib, BZ_FINISH);
761 if (rc < 0 && rc != BZ_OUTBUFF_FULL)
762 return zipErrConvertFromBZlib(rc);
763 }
764 return VINF_SUCCESS;
765}
766
767
768/**
769 * @copydoc RTZipCompDestroy
770 */
771static DECLCALLBACK(int) rtZipBZlibCompDestroy(PRTZIPCOMP pZip)
772{
773 /*
774 * Terminate the deflate instance.
775 */
776 int rc = BZ2_bzCompressEnd(&pZip->u.BZlib);
777 if (rc != BZ_OK)
778 rc = zipErrConvertFromBZlib(rc);
779 return rc;
780}
781
782
783/**
784 * Initializes the compressor instance.
785 * @returns iprt status code.
786 * @param pZip The compressor instance.
787 * @param enmLevel The desired compression level.
788 */
789static DECLCALLBACK(int) rtZipBZlibCompInit(PRTZIPCOMP pZip, RTZIPLEVEL enmLevel)
790{
791 pZip->pfnCompress = rtZipBZlibCompress;
792 pZip->pfnFinish = rtZipBZlibCompFinish;
793 pZip->pfnDestroy = rtZipBZlibCompDestroy;
794
795 int iSize = 6;
796 int iWork = 0;
797 switch (enmLevel)
798 {
799 case RTZIPLEVEL_STORE: iSize = 1; iWork = 2; break;
800 case RTZIPLEVEL_FAST: iSize = 2; iWork = 0; break;
801 case RTZIPLEVEL_DEFAULT: iSize = 5; iWork = 0; break;
802 case RTZIPLEVEL_MAX: iSize = 9; iWork = 0; break;
803 }
804
805 memset(&pZip->u.BZlib, 0, sizeof(pZip->u.BZlib));
806 pZip->u.BZlib.next_out = (char *)&pZip->abBuffer[1];
807 pZip->u.BZlib.avail_out = sizeof(pZip->abBuffer) - 1;
808 pZip->u.BZlib.opaque = pZip;
809
810 int rc = BZ2_bzCompressInit(&pZip->u.BZlib, iSize, 0, iWork);
811 return rc >= 0 ? VINF_SUCCESS : zipErrConvertFromBZlib(rc);;
812}
813
814
815/**
816 * @copydoc RTZipDecompress
817 */
818static DECLCALLBACK(int) rtZipBZlibDecompress(PRTZIPDECOMP pZip, void *pvBuf, size_t cbBuf, size_t *pcbWritten)
819{
820 pZip->u.BZlib.next_out = (char *)pvBuf;
821 pZip->u.BZlib.avail_out = cbBuf;
822 while (pZip->u.BZlib.avail_out > 0)
823 {
824 /*
825 * Read more output buffer?
826 */
827 if (pZip->u.BZlib.avail_in <= 0)
828 {
829 size_t cb;
830 int rc = pZip->pfnIn(pZip->pvUser, &pZip->abBuffer[0], sizeof(pZip->abBuffer), &cb);
831 if (RT_FAILURE(rc))
832 return rc;
833 pZip->u.BZlib.avail_in = cb;
834 pZip->u.BZlib.next_in = (char *)&pZip->abBuffer[0];
835 }
836
837 /*
838 * Pass it on to zlib.
839 */
840 int rc = BZ2_bzDecompress(&pZip->u.BZlib);
841 if (rc == BZ_STREAM_END || rc == BZ_OUTBUFF_FULL)
842 {
843 if (pcbWritten)
844 *pcbWritten = cbBuf - pZip->u.BZlib.avail_out;
845 else if (pZip->u.BZlib.avail_out > 0)
846 return VERR_NO_DATA;
847 break;
848 }
849 if (rc < 0)
850 return zipErrConvertFromBZlib(rc);
851 }
852 return VINF_SUCCESS;
853}
854
855
856/**
857 * @copydoc RTZipDecompDestroy
858 */
859static DECLCALLBACK(int) rtZipBZlibDecompDestroy(PRTZIPDECOMP pZip)
860{
861 /*
862 * Terminate the deflate instance.
863 */
864 int rc = BZ2_bzDecompressEnd(&pZip->u.BZlib);
865 if (rc != BZ_OK)
866 rc = zipErrConvertFromBZlib(rc);
867 return rc;
868}
869
870
871/**
872 * Initialize the decompressor instance.
873 * @returns iprt status code.
874 * @param pZip The decompressor instance.
875 */
876static DECLCALLBACK(int) rtZipBZlibDecompInit(PRTZIPDECOMP pZip)
877{
878 pZip->pfnDecompress = rtZipBZlibDecompress;
879 pZip->pfnDestroy = rtZipBZlibDecompDestroy;
880
881 memset(&pZip->u.BZlib, 0, sizeof(pZip->u.BZlib));
882 pZip->u.BZlib.opaque = pZip;
883
884 int rc = BZ2_bzDecompressInit(&pZip->u.BZlib, 0, 0);
885 return rc >= 0 ? VINF_SUCCESS : zipErrConvertFromBZlib(rc);
886}
887
888#endif /* RTZIP_USE_BZLIB */
889
890
891#ifdef RTZIP_USE_LZF
892
893/**
894 * Flushes the output buffer.
895 * @returns iprt status code.
896 * @param pZip The compressor instance.
897 */
898static int rtZipLZFCompFlushOutput(PRTZIPCOMP pZip)
899{
900 size_t cb = pZip->u.LZF.pbOutput - &pZip->abBuffer[0];
901 pZip->u.LZF.pbOutput = &pZip->abBuffer[0];
902 return pZip->pfnOut(pZip->pvUser, &pZip->abBuffer[0], cb);
903}
904
905
906/**
907 * Compresses a buffer using LZF.
908 *
909 * @returns VBox status code.
910 * @param pZip The compressor instance.
911 * @param pbBuf What to compress.
912 * @param cbBuf How much to compress.
913 */
914static int rtZipLZFCompressBuffer(PRTZIPCOMP pZip, const uint8_t *pbBuf, size_t cbBuf)
915{
916 bool fForceFlush = false;
917 while (cbBuf > 0)
918 {
919 /*
920 * Flush output buffer?
921 */
922 unsigned cbFree = (unsigned)(sizeof(pZip->abBuffer) - (pZip->u.LZF.pbOutput - &pZip->abBuffer[0]));
923 if ( fForceFlush
924 || cbFree < RTZIPLZF_MAX_DATA_SIZE + sizeof(RTZIPLZFHDR))
925 {
926 int rc = rtZipLZFCompFlushOutput(pZip);
927 if (RT_FAILURE(rc))
928 return rc;
929 fForceFlush = false;
930 cbFree = sizeof(pZip->abBuffer);
931 }
932
933 /*
934 * Setup the block header.
935 */
936 PRTZIPLZFHDR pHdr = (PRTZIPLZFHDR)pZip->u.LZF.pbOutput; /* warning: This might be unaligned! */
937 pHdr->u16Magic = RTZIPLZFHDR_MAGIC;
938 pHdr->cbData = 0;
939 pHdr->u32CRC = 0;
940 pHdr->cbUncompressed = 0;
941 cbFree -= sizeof(*pHdr);
942 pZip->u.LZF.pbOutput += sizeof(*pHdr);
943
944 /*
945 * Compress data for the block.
946 *
947 * We try compress as much as we have freespace for at first,
948 * but if it turns out the compression is inefficient, we'll
949 * reduce the size of data we try compress till it fits the
950 * output space.
951 */
952 cbFree = RT_MIN(cbFree, RTZIPLZF_MAX_DATA_SIZE);
953 unsigned cbInput = (unsigned)RT_MIN(RTZIPLZF_MAX_UNCOMPRESSED_DATA_SIZE, cbBuf);
954 unsigned cbOutput = lzf_compress(pbBuf, cbInput, pZip->u.LZF.pbOutput, cbFree);
955 if (!cbOutput)
956 {
957 /** @todo add an alternative method which stores the raw data if bad compression. */
958 do
959 {
960 cbInput /= 2;
961 if (!cbInput)
962 {
963 AssertMsgFailed(("lzf_compress bug! cbFree=%zu\n", cbFree));
964 return VERR_INTERNAL_ERROR;
965 }
966 cbOutput = lzf_compress(pbBuf, cbInput, pZip->u.LZF.pbOutput, cbFree);
967 } while (!cbOutput);
968 fForceFlush = true;
969 }
970
971 /*
972 * Update the header and advance the input buffer.
973 */
974 pHdr->cbData = cbOutput;
975 //pHdr->u32CRC = RTCrc32(pbBuf, cbInput); - too slow
976 pHdr->cbUncompressed = cbInput;
977
978 pZip->u.LZF.pbOutput += cbOutput;
979 cbBuf -= cbInput;
980 pbBuf += cbInput;
981 }
982 return VINF_SUCCESS;
983}
984
985
986/**
987 * Flushes the input buffer.
988 * @returns iprt status code.
989 * @param pZip The compressor instance.
990 */
991static int rtZipLZFCompFlushInput(PRTZIPCOMP pZip)
992{
993 size_t cb = pZip->u.LZF.pbInput - &pZip->u.LZF.abInput[0];
994 pZip->u.LZF.pbInput = &pZip->u.LZF.abInput[0];
995 pZip->u.LZF.cbInputFree = sizeof(pZip->u.LZF.abInput);
996 if (cb)
997 return rtZipLZFCompressBuffer(pZip, pZip->u.LZF.abInput, cb);
998 return VINF_SUCCESS;
999}
1000
1001
1002/**
1003 * @copydoc RTZipCompress
1004 */
1005static DECLCALLBACK(int) rtZipLZFCompress(PRTZIPCOMP pZip, const void *pvBuf, size_t cbBuf)
1006{
1007#define RTZIPLZF_SMALL_CHUNK (128)
1008
1009 /*
1010 * Flush the input buffer if necessary.
1011 */
1012 if ( ( cbBuf <= RTZIPLZF_SMALL_CHUNK
1013 && cbBuf > pZip->u.LZF.cbInputFree)
1014 || ( cbBuf > RTZIPLZF_SMALL_CHUNK
1015 && pZip->u.LZF.cbInputFree != sizeof(pZip->u.LZF.abInput))
1016 )
1017 {
1018 int rc = rtZipLZFCompFlushInput(pZip);
1019 if (RT_FAILURE(rc))
1020 return rc;
1021 }
1022
1023 /*
1024 * If it's a relativly small block put it in the input buffer, elsewise
1025 * compress directly it.
1026 */
1027 if (cbBuf <= RTZIPLZF_SMALL_CHUNK)
1028 {
1029 Assert(pZip->u.LZF.cbInputFree >= cbBuf);
1030 memcpy(pZip->u.LZF.pbInput, pvBuf, cbBuf);
1031 pZip->u.LZF.pbInput += cbBuf;
1032 pZip->u.LZF.cbInputFree -= cbBuf;
1033 }
1034 else
1035 {
1036 Assert(pZip->u.LZF.cbInputFree == sizeof(pZip->u.LZF.abInput));
1037 int rc = rtZipLZFCompressBuffer(pZip, (const uint8_t *)pvBuf, cbBuf);
1038 if (RT_FAILURE(rc))
1039 return rc;
1040 }
1041 return VINF_SUCCESS;
1042}
1043
1044
1045/**
1046 * @copydoc RTZipCompFinish
1047 */
1048static DECLCALLBACK(int) rtZipLZFCompFinish(PRTZIPCOMP pZip)
1049{
1050 int rc = rtZipLZFCompFlushInput(pZip);
1051 if (RT_SUCCESS(rc))
1052 rc = rtZipLZFCompFlushOutput(pZip);
1053 return rc;
1054}
1055
1056
1057/**
1058 * @copydoc RTZipCompDestroy
1059 */
1060static DECLCALLBACK(int) rtZipLZFCompDestroy(PRTZIPCOMP pZip)
1061{
1062 NOREF(pZip);
1063 return VINF_SUCCESS;
1064}
1065
1066
1067/**
1068 * Initializes the compressor instance.
1069 * @returns iprt status code.
1070 * @param pZip The compressor instance.
1071 * @param enmLevel The desired compression level.
1072 */
1073static DECLCALLBACK(int) rtZipLZFCompInit(PRTZIPCOMP pZip, RTZIPLEVEL enmLevel)
1074{
1075 NOREF(enmLevel);
1076 pZip->pfnCompress = rtZipLZFCompress;
1077 pZip->pfnFinish = rtZipLZFCompFinish;
1078 pZip->pfnDestroy = rtZipLZFCompDestroy;
1079
1080 pZip->u.LZF.pbOutput = &pZip->abBuffer[1];
1081 pZip->u.LZF.pbInput = &pZip->u.LZF.abInput[0];
1082 pZip->u.LZF.cbInputFree = sizeof(pZip->u.LZF.abInput);
1083 return VINF_SUCCESS;
1084}
1085
1086
1087/**
1088 * This will validate a header and to all the necessary bitching if it's invalid.
1089 * @returns true if valid.
1090 * @returns false if invalid.
1091 * @param pHdr Pointer to the header.\
1092 */
1093static bool rtZipLZFValidHeader(PCRTZIPLZFHDR pHdr)
1094{
1095 if ( pHdr->u16Magic != RTZIPLZFHDR_MAGIC
1096 || !pHdr->cbData
1097 || pHdr->cbData > RTZIPLZF_MAX_DATA_SIZE
1098 || !pHdr->cbUncompressed
1099 || pHdr->cbUncompressed > RTZIPLZF_MAX_UNCOMPRESSED_DATA_SIZE
1100 )
1101 {
1102 AssertMsgFailed(("Invalid LZF header! %.*Rhxs\n", sizeof(*pHdr), pHdr));
1103 return false;
1104 }
1105 return true;
1106}
1107
1108
1109/**
1110 * @copydoc RTZipDecompress
1111 */
1112static DECLCALLBACK(int) rtZipLZFDecompress(PRTZIPDECOMP pZip, void *pvBuf, size_t cbBuf, size_t *pcbWritten)
1113{
1114 /*
1115 * Decompression loop.
1116 *
1117 * This a bit ugly because we have to deal with reading block...
1118 * To simplify matters we've put a max block size and will never
1119 * fill the input buffer with more than allows us to complete
1120 * any partially read blocks.
1121 *
1122 * When possible we decompress directly to the user buffer, when
1123 * not possible we'll use the spill buffer.
1124 */
1125# ifdef RTZIP_LZF_BLOCK_BY_BLOCK
1126 size_t cbWritten = 0;
1127 while (cbBuf > 0)
1128 {
1129 /*
1130 * Anything in the spill buffer?
1131 */
1132 if (pZip->u.LZF.cbSpill > 0)
1133 {
1134 unsigned cb = (unsigned)RT_MIN(pZip->u.LZF.cbSpill, cbBuf);
1135 memcpy(pvBuf, pZip->u.LZF.pbSpill, cb);
1136 pZip->u.LZF.pbSpill += cb;
1137 pZip->u.LZF.cbSpill -= cb;
1138 cbWritten += cb;
1139 cbBuf -= cb;
1140 if (!cbBuf)
1141 break;
1142 pvBuf = (uint8_t *)pvBuf + cb;
1143 }
1144
1145 /*
1146 * We always read and work one block at a time.
1147 */
1148 RTZIPLZFHDR Hdr;
1149 int rc = pZip->pfnIn(pZip->pvUser, &Hdr, sizeof(Hdr), NULL);
1150 if (RT_FAILURE(rc))
1151 return rc;
1152 if (!rtZipLZFValidHeader(&Hdr))
1153 return VERR_GENERAL_FAILURE; /** @todo Get better error codes for RTZip! */
1154 if (Hdr.cbData > 0)
1155 {
1156 rc = pZip->pfnIn(pZip->pvUser, &pZip->abBuffer[0], Hdr.cbData, NULL);
1157 if (RT_FAILURE(rc))
1158 return rc;
1159 }
1160
1161 /*
1162 * Does the uncompressed data fit into the supplied buffer?
1163 * If so we uncompress it directly into the user buffer, else we'll have to use the spill buffer.
1164 */
1165 unsigned cbUncompressed = Hdr.cbUncompressed;
1166 if (cbUncompressed <= cbBuf)
1167 {
1168 unsigned cbOutput = lzf_decompress(&pZip->abBuffer[0], Hdr.cbData, pvBuf, cbUncompressed);
1169 if (cbOutput != cbUncompressed)
1170 {
1171 AssertMsgFailed(("Decompression error, errno=%d. cbOutput=%#x cbUncompressed=%#x\n",
1172 errno, cbOutput, cbUncompressed));
1173 return VERR_GENERAL_FAILURE; /** @todo Get better error codes for RTZip! */
1174 }
1175 cbBuf -= cbUncompressed;
1176 pvBuf = (uint8_t *)pvBuf + cbUncompressed;
1177 cbWritten += cbUncompressed;
1178 }
1179 else
1180 {
1181 unsigned cbOutput = lzf_decompress(&pZip->abBuffer[0], Hdr.cbData, pZip->u.LZF.abSpill, cbUncompressed);
1182 if (cbOutput != cbUncompressed)
1183 {
1184 AssertMsgFailed(("Decompression error, errno=%d. cbOutput=%#x cbUncompressed=%#x\n",
1185 errno, cbOutput, cbUncompressed));
1186 return VERR_GENERAL_FAILURE; /** @todo Get better error codes for RTZip! */
1187 }
1188 pZip->u.LZF.pbSpill = &pZip->u.LZF.abSpill[0];
1189 pZip->u.LZF.cbSpill = cbUncompressed;
1190 }
1191 }
1192
1193 if (pcbWritten)
1194 *pcbWritten = cbWritten;
1195# else /* !RTZIP_LZF_BLOCK_BY_BLOCK */
1196 while (cbBuf > 0)
1197 {
1198 /*
1199 * Anything in the spill buffer?
1200 */
1201 if (pZip->u.LZF.cbSpill > 0)
1202 {
1203 unsigned cb = (unsigned)RT_MIN(pZip->u.LZF.cbSpill, cbBuf);
1204 memcpy(pvBuf, pZip->u.LZF.pbSpill, cb);
1205 pZip->u.LZF.pbSpill += cb;
1206 pZip->u.LZF.cbSpill -= cb;
1207 cbBuf -= cb;
1208 if (pcbWritten)
1209 *pcbWritten = cb;
1210 if (!cbBuf)
1211 break;
1212 pvBuf = (uint8_t *)pvBuf + cb;
1213 }
1214
1215 /*
1216 * Incomplete header or nothing at all.
1217 */
1218 PCRTZIPLZFHDR pHdr;
1219 if (pZip->u.LZF.cbInput < sizeof(RTZIPLZFHDR))
1220 {
1221 if (pZip->u.LZF.cbInput <= 0)
1222 {
1223 /* empty, fill the buffer. */
1224 size_t cb = 0;
1225 int rc = pZip->pfnIn(pZip->pvUser, &pZip->abBuffer[0],
1226 sizeof(pZip->abBuffer) - RTZIPLZF_MAX_DATA_SIZE, &cb);
1227 if (RT_FAILURE(rc))
1228 return rc;
1229 pZip->u.LZF.pbInput = &pZip->abBuffer[0];
1230 pZip->u.LZF.cbInput = cb;
1231 pHdr = (PCRTZIPLZFHDR)pZip->u.LZF.pbInput;
1232 }
1233 else
1234 {
1235 /* move the header up and fill the buffer. */
1236 size_t cbCur = pZip->u.LZF.cbInput;
1237 memmove(&pZip->abBuffer[0], pZip->u.LZF.pbInput, cbCur);
1238 pZip->u.LZF.pbInput = &pZip->abBuffer[0];
1239
1240 size_t cb = 0;
1241 int rc = pZip->pfnIn(pZip->pvUser, &pZip->abBuffer[cbCur],
1242 sizeof(pZip->abBuffer) - RTZIPLZF_MAX_DATA_SIZE - cbCur, &cb);
1243 if (RT_FAILURE(rc))
1244 return rc;
1245 pHdr = (PCRTZIPLZFHDR)pZip->u.LZF.pbInput;
1246 pZip->u.LZF.cbInput += cb;
1247 }
1248
1249 /*
1250 * Validate the header.
1251 */
1252 if (!rtZipLZFValidHeader(pHdr))
1253 return VERR_GENERAL_FAILURE; /** @todo Get better error codes for RTZip! */
1254 }
1255 else
1256 {
1257 /*
1258 * Validate the header and check if it's an incomplete block.
1259 */
1260 pHdr = (PCRTZIPLZFHDR)pZip->u.LZF.pbInput;
1261 if (!rtZipLZFValidHeader(pHdr))
1262 return VERR_GENERAL_FAILURE; /** @todo Get better error codes for RTZip! */
1263
1264 if (pHdr->cbData > pZip->u.LZF.cbInput - sizeof(*pHdr))
1265 {
1266 /* read the remainder of the block. */
1267 size_t cbToRead = pHdr->cbData - (pZip->u.LZF.cbInput - sizeof(*pHdr));
1268 Assert(&pZip->u.LZF.pbInput[pZip->u.LZF.cbInput + cbToRead] <= &pZip->u.LZF.pbInput[sizeof(pZip->abBuffer)]);
1269 int rc = pZip->pfnIn(pZip->pvUser, &pZip->u.LZF.pbInput[pZip->u.LZF.cbInput],
1270 cbToRead, NULL);
1271 if (RT_FAILURE(rc))
1272 return rc;
1273 pZip->u.LZF.cbInput += cbToRead;
1274 }
1275 }
1276 AssertMsgReturn(sizeof(*pHdr) + pHdr->cbData <= pZip->u.LZF.cbInput,
1277 ("cbData=%#x cbInput=%#x\n", pHdr->cbData, pZip->u.LZF.cbInput),
1278 VERR_GENERAL_FAILURE); /** @todo Get better error codes for RTZip! */
1279
1280 /*
1281 * Does the uncompressed data fit into the supplied buffer?
1282 * If so we uncompress it directly into the user buffer, else we'll have to use the spill buffer.
1283 */
1284 unsigned cbUncompressed = pHdr->cbUncompressed;
1285 if (cbUncompressed <= cbBuf)
1286 {
1287 unsigned cbOutput = lzf_decompress(pHdr + 1, pHdr->cbData, pvBuf, cbUncompressed);
1288 if (cbOutput != cbUncompressed)
1289 {
1290 AssertMsgFailed(("Decompression error, errno=%d. cbOutput=%#x cbUncompressed=%#x\n",
1291 errno, cbOutput, cbUncompressed));
1292 return VERR_GENERAL_FAILURE; /** @todo Get better error codes for RTZip! */
1293 }
1294 cbBuf -= cbUncompressed;
1295 pvBuf = (uint8_t *)pvBuf + cbUncompressed;
1296 }
1297 else
1298 {
1299 unsigned cbOutput = lzf_decompress(pHdr + 1, pHdr->cbData, pZip->u.LZF.abSpill, cbUncompressed);
1300 if (cbOutput != cbUncompressed)
1301 {
1302 AssertMsgFailed(("Decompression error, errno=%d. cbOutput=%#x cbUncompressed=%#x\n",
1303 errno, cbOutput, cbUncompressed));
1304 return VERR_GENERAL_FAILURE; /** @todo Get better error codes for RTZip! */
1305 }
1306 pZip->u.LZF.pbSpill = &pZip->u.LZF.abSpill[0];
1307 pZip->u.LZF.cbSpill = cbUncompressed;
1308 }
1309
1310 /* advance the input buffer */
1311 pZip->u.LZF.cbInput -= pHdr->cbData + sizeof(*pHdr);
1312 pZip->u.LZF.pbInput += pHdr->cbData + sizeof(*pHdr);
1313 if (pcbWritten)
1314 *pcbWritten += cbUncompressed;
1315 }
1316# endif /* !RTZIP_LZF_BLOCK_BY_BLOCK */
1317 return VINF_SUCCESS;
1318}
1319
1320
1321/**
1322 * @copydoc RTZipDecompDestroy
1323 */
1324static DECLCALLBACK(int) rtZipLZFDecompDestroy(PRTZIPDECOMP pZip)
1325{
1326 NOREF(pZip);
1327 return VINF_SUCCESS;
1328}
1329
1330
1331/**
1332 * Initialize the decompressor instance.
1333 * @returns iprt status code.
1334 * @param pZip The decompressor instance.
1335 */
1336static DECLCALLBACK(int) rtZipLZFDecompInit(PRTZIPDECOMP pZip)
1337{
1338 pZip->pfnDecompress = rtZipLZFDecompress;
1339 pZip->pfnDestroy = rtZipLZFDecompDestroy;
1340
1341# ifndef RTZIP_LZF_BLOCK_BY_BLOCK
1342 pZip->u.LZF.pbInput = NULL;
1343 pZip->u.LZF.cbInput = 0;
1344# endif
1345 pZip->u.LZF.cbSpill = 0;
1346 pZip->u.LZF.pbSpill = NULL;
1347
1348 return VINF_SUCCESS;
1349}
1350
1351#endif /* RTZIP_USE_LZF */
1352
1353
1354/**
1355 * Create a compressor instance.
1356 *
1357 * @returns iprt status code.
1358 * @param ppZip Where to store the instance handle.
1359 * @param pvUser User argument which will be passed on to pfnOut and pfnIn.
1360 * @param pfnOut Callback for consuming output of compression.
1361 * @param enmType Type of compressor to create.
1362 * @param enmLevel Compression level.
1363 */
1364RTDECL(int) RTZipCompCreate(PRTZIPCOMP *ppZip, void *pvUser, PFNRTZIPOUT pfnOut, RTZIPTYPE enmType, RTZIPLEVEL enmLevel)
1365{
1366 /*
1367 * Validate input.
1368 */
1369 AssertReturn(enmType >= RTZIPTYPE_INVALID && enmType < RTZIPTYPE_END, VERR_INVALID_PARAMETER);
1370 AssertReturn(enmLevel >= RTZIPLEVEL_STORE && enmLevel <= RTZIPLEVEL_MAX, VERR_INVALID_PARAMETER);
1371 AssertPtrReturn(pfnOut, VERR_INVALID_POINTER);
1372 AssertPtrReturn(ppZip, VERR_INVALID_POINTER);
1373
1374 /*
1375 * Allocate memory for the instance data.
1376 */
1377 PRTZIPCOMP pZip = (PRTZIPCOMP)RTMemAlloc(sizeof(RTZIPCOMP));
1378 if (!pZip)
1379 return VERR_NO_MEMORY;
1380
1381 /*
1382 * Determine auto type.
1383 */
1384 if (enmType == RTZIPTYPE_AUTO)
1385 {
1386 if (enmLevel == RTZIPLEVEL_STORE)
1387 enmType = RTZIPTYPE_STORE;
1388 else
1389 {
1390#if defined(RTZIP_USE_ZLIB) && defined(RTZIP_USE_BZLIB)
1391 if (enmLevel == RTZIPLEVEL_MAX)
1392 enmType = RTZIPTYPE_BZLIB;
1393 else
1394 enmType = RTZIPTYPE_ZLIB;
1395#elif defined(RTZIP_USE_ZLIB)
1396 enmType = RTZIPTYPE_ZLIB;
1397#elif defined(RTZIP_USE_BZLIB)
1398 enmType = RTZIPTYPE_BZLIB;
1399#else
1400 enmType = RTZIPTYPE_STORE;
1401#endif
1402 }
1403 }
1404
1405 /*
1406 * Init instance.
1407 */
1408 pZip->pfnOut = pfnOut;
1409 pZip->enmType = enmType;
1410 pZip->pvUser = pvUser;
1411 pZip->abBuffer[0] = enmType; /* first byte is the compression type. */
1412 int rc = VERR_NOT_IMPLEMENTED;
1413 switch (enmType)
1414 {
1415 case RTZIPTYPE_STORE:
1416#ifdef RTZIP_USE_STORE
1417 rc = rtZipStoreCompInit(pZip, enmLevel);
1418#endif
1419 break;
1420
1421 case RTZIPTYPE_ZLIB:
1422 case RTZIPTYPE_ZLIB_NO_HEADER:
1423#ifdef RTZIP_USE_ZLIB
1424 rc = rtZipZlibCompInit(pZip, enmLevel, enmType == RTZIPTYPE_ZLIB /*fZlibHeader*/);
1425#endif
1426 break;
1427
1428 case RTZIPTYPE_BZLIB:
1429#ifdef RTZIP_USE_BZLIB
1430 rc = rtZipBZlibCompInit(pZip, enmLevel);
1431#endif
1432 break;
1433
1434 case RTZIPTYPE_LZF:
1435#ifdef RTZIP_USE_LZF
1436 rc = rtZipLZFCompInit(pZip, enmLevel);
1437#endif
1438 break;
1439
1440 case RTZIPTYPE_LZJB:
1441 case RTZIPTYPE_LZO:
1442 break;
1443
1444 default:
1445 AssertFailedBreak();
1446 }
1447
1448 if (RT_SUCCESS(rc))
1449 *ppZip = pZip;
1450 else
1451 RTMemFree(pZip);
1452 return rc;
1453}
1454RT_EXPORT_SYMBOL(RTZipCompCreate);
1455
1456
1457/**
1458 * Compresses a chunk of memory.
1459 *
1460 * @returns iprt status code.
1461 * @param pZip The compressor instance.
1462 * @param pvBuf Pointer to buffer containing the bits to compress.
1463 * @param cbBuf Number of bytes to compress.
1464 */
1465RTDECL(int) RTZipCompress(PRTZIPCOMP pZip, const void *pvBuf, size_t cbBuf)
1466{
1467 if (!cbBuf)
1468 return VINF_SUCCESS;
1469 return pZip->pfnCompress(pZip, pvBuf, cbBuf);
1470}
1471RT_EXPORT_SYMBOL(RTZipCompress);
1472
1473
1474/**
1475 * Finishes the compression.
1476 * This will flush all data and terminate the compression data stream.
1477 *
1478 * @returns iprt status code.
1479 * @param pZip The compressor instance.
1480 */
1481RTDECL(int) RTZipCompFinish(PRTZIPCOMP pZip)
1482{
1483 return pZip->pfnFinish(pZip);
1484}
1485RT_EXPORT_SYMBOL(RTZipCompFinish);
1486
1487
1488/**
1489 * Destroys the compressor instance.
1490 *
1491 * @returns iprt status code.
1492 * @param pZip The compressor instance.
1493 */
1494RTDECL(int) RTZipCompDestroy(PRTZIPCOMP pZip)
1495{
1496 /*
1497 * Compressor specific destruction attempt first.
1498 */
1499 int rc = pZip->pfnDestroy(pZip);
1500 AssertRCReturn(rc, rc);
1501
1502 /*
1503 * Free the instance memory.
1504 */
1505 pZip->enmType = RTZIPTYPE_INVALID;
1506 RTMemFree(pZip);
1507 return VINF_SUCCESS;
1508}
1509RT_EXPORT_SYMBOL(RTZipCompDestroy);
1510
1511
1512/**
1513 * @copydoc RTZipDecompress
1514 */
1515static DECLCALLBACK(int) rtZipStubDecompress(PRTZIPDECOMP pZip, void *pvBuf, size_t cbBuf, size_t *pcbWritten)
1516{
1517 NOREF(pZip); NOREF(pvBuf); NOREF(cbBuf); NOREF(pcbWritten);
1518 return VERR_NOT_SUPPORTED;
1519}
1520
1521
1522/**
1523 * @copydoc RTZipDecompDestroy
1524 */
1525static DECLCALLBACK(int) rtZipStubDecompDestroy(PRTZIPDECOMP pZip)
1526{
1527 NOREF(pZip);
1528 return VINF_SUCCESS;
1529}
1530
1531
1532/**
1533 * Create a decompressor instance.
1534 *
1535 * @returns iprt status code.
1536 * @param ppZip Where to store the instance handle.
1537 * @param pvUser User argument which will be passed on to pfnOut and pfnIn.
1538 * @param pfnIn Callback for producing input for decompression.
1539 */
1540RTDECL(int) RTZipDecompCreate(PRTZIPDECOMP *ppZip, void *pvUser, PFNRTZIPIN pfnIn)
1541{
1542 /*
1543 * Validate input.
1544 */
1545 AssertPtrReturn(pfnIn, VERR_INVALID_POINTER);
1546 AssertPtrReturn(ppZip, VERR_INVALID_POINTER);
1547
1548 /*
1549 * Allocate memory for the instance data.
1550 */
1551 PRTZIPDECOMP pZip = (PRTZIPDECOMP)RTMemAlloc(sizeof(RTZIPDECOMP));
1552 if (!pZip)
1553 return VERR_NO_MEMORY;
1554
1555 /*
1556 * Init instance.
1557 */
1558 pZip->pfnIn = pfnIn;
1559 pZip->enmType = RTZIPTYPE_INVALID;
1560 pZip->pvUser = pvUser;
1561 pZip->pfnDecompress = NULL;
1562 pZip->pfnDestroy = rtZipStubDecompDestroy;
1563
1564 *ppZip = pZip;
1565 return VINF_SUCCESS;
1566}
1567RT_EXPORT_SYMBOL(RTZipDecompCreate);
1568
1569
1570/**
1571 * Lazy init of the decompressor.
1572 * @returns iprt status code.
1573 * @param pZip The decompressor instance.
1574 */
1575static int rtzipDecompInit(PRTZIPDECOMP pZip)
1576{
1577 /*
1578 * Read the first byte from the stream so we can determine the type.
1579 */
1580 uint8_t u8Type;
1581 int rc = pZip->pfnIn(pZip->pvUser, &u8Type, sizeof(u8Type), NULL);
1582 if (RT_FAILURE(rc))
1583 return rc;
1584
1585 /*
1586 * Determine type and do type specific init.
1587 */
1588 pZip->enmType = (RTZIPTYPE)u8Type;
1589 rc = VERR_NOT_SUPPORTED;
1590 switch (pZip->enmType)
1591 {
1592 case RTZIPTYPE_STORE:
1593#ifdef RTZIP_USE_STORE
1594 rc = rtZipStoreDecompInit(pZip);
1595#else
1596 AssertMsgFailed(("Store is not include in this build!\n"));
1597#endif
1598 break;
1599
1600 case RTZIPTYPE_ZLIB:
1601 case RTZIPTYPE_ZLIB_NO_HEADER:
1602#ifdef RTZIP_USE_ZLIB
1603 rc = rtZipZlibDecompInit(pZip, pZip->enmType == RTZIPTYPE_ZLIB /*fHeader*/);
1604#else
1605 AssertMsgFailed(("Zlib is not include in this build!\n"));
1606#endif
1607 break;
1608
1609 case RTZIPTYPE_BZLIB:
1610#ifdef RTZIP_USE_BZLIB
1611 rc = rtZipBZlibDecompInit(pZip);
1612#else
1613 AssertMsgFailed(("BZlib is not include in this build!\n"));
1614#endif
1615 break;
1616
1617 case RTZIPTYPE_LZF:
1618#ifdef RTZIP_USE_LZF
1619 rc = rtZipLZFDecompInit(pZip);
1620#else
1621 AssertMsgFailed(("LZF is not include in this build!\n"));
1622#endif
1623 break;
1624
1625 case RTZIPTYPE_LZJB:
1626#ifdef RTZIP_USE_LZJB
1627 AssertMsgFailed(("LZJB streaming support is not implemented yet!\n"));
1628#else
1629 AssertMsgFailed(("LZJB is not include in this build!\n"));
1630#endif
1631 break;
1632
1633 case RTZIPTYPE_LZO:
1634#ifdef RTZIP_USE_LZJB
1635 AssertMsgFailed(("LZO streaming support is not implemented yet!\n"));
1636#else
1637 AssertMsgFailed(("LZO is not include in this build!\n"));
1638#endif
1639 break;
1640
1641 default:
1642 AssertMsgFailed(("Invalid compression type %d (%#x)!\n", pZip->enmType, pZip->enmType));
1643 rc = VERR_INVALID_MAGIC;
1644 break;
1645 }
1646 if (RT_FAILURE(rc))
1647 {
1648 pZip->pfnDecompress = rtZipStubDecompress;
1649 pZip->pfnDestroy = rtZipStubDecompDestroy;
1650 }
1651
1652 return rc;
1653}
1654
1655
1656/**
1657 * Decompresses a chunk of memory.
1658 *
1659 * @returns iprt status code.
1660 * @param pZip The decompressor instance.
1661 * @param pvBuf Where to store the decompressed data.
1662 * @param cbBuf Number of bytes to produce. If pcbWritten is set
1663 * any number of bytes up to cbBuf might be returned.
1664 * @param pcbWritten Number of bytes actually written to the buffer. If NULL
1665 * cbBuf number of bytes must be written.
1666 */
1667RTDECL(int) RTZipDecompress(PRTZIPDECOMP pZip, void *pvBuf, size_t cbBuf, size_t *pcbWritten)
1668{
1669 /*
1670 * Skip empty requests.
1671 */
1672 if (!cbBuf)
1673 return VINF_SUCCESS;
1674
1675 /*
1676 * Lazy init.
1677 */
1678 if (!pZip->pfnDecompress)
1679 {
1680 int rc = rtzipDecompInit(pZip);
1681 if (RT_FAILURE(rc))
1682 return rc;
1683 }
1684
1685 /*
1686 * 'Read' the decompressed stream.
1687 */
1688 return pZip->pfnDecompress(pZip, pvBuf, cbBuf, pcbWritten);
1689}
1690RT_EXPORT_SYMBOL(RTZipDecompress);
1691
1692
1693/**
1694 * Destroys the decompressor instance.
1695 *
1696 * @returns iprt status code.
1697 * @param pZip The decompressor instance.
1698 */
1699RTDECL(int) RTZipDecompDestroy(PRTZIPDECOMP pZip)
1700{
1701 /*
1702 * Destroy compressor instance and flush the output buffer.
1703 */
1704 int rc = pZip->pfnDestroy(pZip);
1705 AssertRCReturn(rc, rc);
1706
1707 /*
1708 * Free the instance memory.
1709 */
1710 pZip->enmType = RTZIPTYPE_INVALID;
1711 RTMemFree(pZip);
1712 return rc;
1713}
1714RT_EXPORT_SYMBOL(RTZipDecompDestroy);
1715
1716
1717RTDECL(int) RTZipBlockCompress(RTZIPTYPE enmType, RTZIPLEVEL enmLevel, uint32_t fFlags,
1718 void const *pvSrc, size_t cbSrc,
1719 void *pvDst, size_t cbDst, size_t *pcbDstActual) RT_NO_THROW_DEF
1720{
1721 /* input validation - the crash and burn approach as speed is essential here. */
1722 Assert(enmLevel <= RTZIPLEVEL_MAX && enmLevel >= RTZIPLEVEL_STORE); RT_NOREF_PV(enmLevel);
1723 Assert(!fFlags); RT_NOREF_PV(fFlags);
1724
1725 /*
1726 * Deal with flags involving prefixes.
1727 */
1728 /** @todo later: type and/or compressed length prefix. */
1729
1730 /*
1731 * The type specific part.
1732 */
1733 switch (enmType)
1734 {
1735 case RTZIPTYPE_LZF:
1736 {
1737#ifdef RTZIP_USE_LZF
1738# if 0
1739 static const uint8_t s_abZero4K[] =
1740 {
1741 0x01, 0x00, 0x00, 0xe0, 0xff, 0x00, 0xe0, 0xff,
1742 0x00, 0xe0, 0xff, 0x00, 0xe0, 0xff, 0x00, 0xe0,
1743 0xff, 0x00, 0xe0, 0xff, 0x00, 0xe0, 0xff, 0x00,
1744 0xe0, 0xff, 0x00, 0xe0, 0xff, 0x00, 0xe0, 0xff,
1745 0x00, 0xe0, 0xff, 0x00, 0xe0, 0xff, 0x00, 0xe0,
1746 0xff, 0x00, 0xe0, 0xff, 0x00, 0xe0, 0xff, 0x00,
1747 0xe0, 0x7d, 0x00
1748 };
1749 if ( cbSrc == _4K
1750 && !((uintptr_t)pvSrc & 15)
1751 && ASMMemIsZeroPage(pvSrc))
1752 {
1753 if (RT_UNLIKELY(cbDst < sizeof(s_abZero4K)))
1754 return VERR_BUFFER_OVERFLOW;
1755 memcpy(pvDst, s_abZero4K, sizeof(s_abZero4K));
1756 *pcbDstActual = sizeof(s_abZero4K);
1757 break;
1758 }
1759# endif
1760
1761 unsigned cbDstActual = lzf_compress(pvSrc, (unsigned)cbSrc, pvDst, (unsigned)cbDst); /** @todo deal with size type overflows */
1762 if (RT_UNLIKELY(cbDstActual < 1))
1763 return VERR_BUFFER_OVERFLOW;
1764 *pcbDstActual = cbDstActual;
1765 break;
1766#else
1767 return VERR_NOT_SUPPORTED;
1768#endif
1769 }
1770
1771 case RTZIPTYPE_STORE:
1772 {
1773 if (cbDst < cbSrc)
1774 return VERR_BUFFER_OVERFLOW;
1775 memcpy(pvDst, pvSrc, cbSrc);
1776 *pcbDstActual = cbSrc;
1777 break;
1778 }
1779
1780 case RTZIPTYPE_LZJB:
1781 {
1782#ifdef RTZIP_USE_LZJB
1783 AssertReturn(cbDst > cbSrc, VERR_BUFFER_OVERFLOW);
1784 size_t cbDstActual = lzjb_compress((void *)pvSrc, (uint8_t *)pvDst + 1, cbSrc, cbSrc, 0 /*??*/);
1785 if (cbDstActual == cbSrc)
1786 *(uint8_t *)pvDst = 0;
1787 else
1788 *(uint8_t *)pvDst = 1;
1789 *pcbDstActual = cbDstActual + 1;
1790 break;
1791#else
1792 return VERR_NOT_SUPPORTED;
1793#endif
1794 }
1795
1796 case RTZIPTYPE_LZO:
1797 {
1798#ifdef RTZIP_USE_LZO
1799 uint64_t Scratch[RT_ALIGN(LZO1X_1_MEM_COMPRESS, sizeof(uint64_t)) / sizeof(uint64_t)];
1800 int rc = lzo_init();
1801 if (RT_UNLIKELY(rc != LZO_E_OK))
1802 return VERR_INTERNAL_ERROR;
1803
1804 lzo_uint cbDstInOut = cbDst;
1805 rc = lzo1x_1_compress((const lzo_bytep)pvSrc, cbSrc, (lzo_bytep )pvDst, &cbDstInOut, &Scratch[0]);
1806 if (RT_UNLIKELY(rc != LZO_E_OK))
1807 switch (rc)
1808 {
1809 case LZO_E_OUTPUT_OVERRUN: return VERR_BUFFER_OVERFLOW;
1810 default: return VERR_GENERAL_FAILURE;
1811 }
1812 *pcbDstActual = cbDstInOut;
1813 break;
1814#else
1815 return VERR_NOT_SUPPORTED;
1816#endif
1817 }
1818
1819 case RTZIPTYPE_ZLIB:
1820 case RTZIPTYPE_BZLIB:
1821 return VERR_NOT_SUPPORTED;
1822
1823 default:
1824 AssertMsgFailed(("%d\n", enmType));
1825 return VERR_INVALID_PARAMETER;
1826 }
1827
1828 return VINF_SUCCESS;
1829}
1830RT_EXPORT_SYMBOL(RTZipBlockCompress);
1831
1832
1833RTDECL(int) RTZipBlockDecompress(RTZIPTYPE enmType, uint32_t fFlags,
1834 void const *pvSrc, size_t cbSrc, size_t *pcbSrcActual,
1835 void *pvDst, size_t cbDst, size_t *pcbDstActual) RT_NO_THROW_DEF
1836{
1837 /* input validation - the crash and burn approach as speed is essential here. */
1838 Assert(!fFlags); RT_NOREF_PV(fFlags);
1839
1840 /*
1841 * Deal with flags involving prefixes.
1842 */
1843 /** @todo later: type and/or compressed length prefix. */
1844
1845 /*
1846 * The type specific part.
1847 */
1848 switch (enmType)
1849 {
1850 case RTZIPTYPE_LZF:
1851 {
1852#ifdef RTZIP_USE_LZF
1853 unsigned cbDstActual = lzf_decompress(pvSrc, (unsigned)cbSrc, pvDst, (unsigned)cbDst); /** @todo deal with size type overflows */
1854 if (RT_UNLIKELY(cbDstActual < 1))
1855 {
1856 if (errno == E2BIG)
1857 return VERR_BUFFER_OVERFLOW;
1858 Assert(errno == EINVAL);
1859 return VERR_GENERAL_FAILURE;
1860 }
1861 if (pcbDstActual)
1862 *pcbDstActual = cbDstActual;
1863 if (pcbSrcActual)
1864 *pcbSrcActual = cbSrc;
1865 break;
1866#else
1867 return VERR_NOT_SUPPORTED;
1868#endif
1869 }
1870
1871 case RTZIPTYPE_STORE:
1872 {
1873 if (cbDst < cbSrc)
1874 return VERR_BUFFER_OVERFLOW;
1875 memcpy(pvDst, pvSrc, cbSrc);
1876 if (pcbDstActual)
1877 *pcbDstActual = cbSrc;
1878 if (pcbSrcActual)
1879 *pcbSrcActual = cbSrc;
1880 break;
1881 }
1882
1883 case RTZIPTYPE_LZJB:
1884 {
1885#ifdef RTZIP_USE_LZJB
1886 if (*(uint8_t *)pvSrc == 1)
1887 {
1888 int rc = lzjb_decompress((uint8_t *)pvSrc + 1, pvDst, cbSrc - 1, cbDst, 0 /*??*/);
1889 if (RT_UNLIKELY(rc != 0))
1890 return VERR_GENERAL_FAILURE;
1891 if (pcbDstActual)
1892 *pcbDstActual = cbDst;
1893 }
1894 else
1895 {
1896 AssertReturn(cbDst >= cbSrc - 1, VERR_BUFFER_OVERFLOW);
1897 memcpy(pvDst, (uint8_t *)pvSrc + 1, cbSrc - 1);
1898 if (pcbDstActual)
1899 *pcbDstActual = cbSrc - 1;
1900 }
1901 if (pcbSrcActual)
1902 *pcbSrcActual = cbSrc;
1903 break;
1904#else
1905 return VERR_NOT_SUPPORTED;
1906#endif
1907 }
1908
1909 case RTZIPTYPE_LZO:
1910 {
1911#ifdef RTZIP_USE_LZO
1912 int rc = lzo_init();
1913 if (RT_UNLIKELY(rc != LZO_E_OK))
1914 return VERR_INTERNAL_ERROR;
1915 lzo_uint cbDstInOut = cbDst;
1916 rc = lzo1x_decompress((const lzo_bytep)pvSrc, cbSrc, (lzo_bytep)pvDst, &cbDstInOut, NULL);
1917 if (RT_UNLIKELY(rc != LZO_E_OK))
1918 switch (rc)
1919 {
1920 case LZO_E_OUTPUT_OVERRUN: return VERR_BUFFER_OVERFLOW;
1921 default:
1922 case LZO_E_INPUT_OVERRUN: return VERR_GENERAL_FAILURE;
1923 }
1924 if (pcbSrcActual)
1925 *pcbSrcActual = cbSrc;
1926 if (pcbDstActual)
1927 *pcbDstActual = cbDstInOut;
1928 break;
1929#else
1930 return VERR_NOT_SUPPORTED;
1931#endif
1932 }
1933
1934 case RTZIPTYPE_ZLIB:
1935 {
1936#ifdef RTZIP_USE_ZLIB
1937 AssertReturn(cbSrc == (uInt)cbSrc, VERR_TOO_MUCH_DATA);
1938 AssertReturn(cbDst == (uInt)cbDst, VERR_OUT_OF_RANGE);
1939
1940 z_stream ZStrm;
1941 RT_ZERO(ZStrm);
1942 ZStrm.next_in = (Bytef *)pvSrc;
1943 ZStrm.avail_in = (uInt)cbSrc;
1944 ZStrm.next_out = (Bytef *)pvDst;
1945 ZStrm.avail_out = (uInt)cbDst;
1946
1947 int rc = inflateInit(&ZStrm);
1948 if (RT_UNLIKELY(rc != Z_OK))
1949 return zipErrConvertFromZlib(rc, false /*fCompressing*/);
1950 rc = inflate(&ZStrm, Z_FINISH);
1951 if (rc != Z_STREAM_END)
1952 {
1953 inflateEnd(&ZStrm);
1954 if ((rc == Z_BUF_ERROR && ZStrm.avail_in == 0) || rc == Z_NEED_DICT)
1955 return VERR_ZIP_CORRUPTED;
1956 if (rc == Z_BUF_ERROR)
1957 return VERR_BUFFER_OVERFLOW;
1958 AssertReturn(rc < Z_OK, VERR_GENERAL_FAILURE);
1959 return zipErrConvertFromZlib(rc, false /*fCompressing*/);
1960 }
1961 rc = inflateEnd(&ZStrm);
1962 if (rc != Z_OK)
1963 return zipErrConvertFromZlib(rc, false /*fCompressing*/);
1964
1965 if (pcbSrcActual)
1966 *pcbSrcActual = cbSrc - ZStrm.avail_in;
1967 if (pcbDstActual)
1968 *pcbDstActual = ZStrm.total_out;
1969 break;
1970#else
1971 return VERR_NOT_SUPPORTED;
1972#endif
1973 }
1974
1975 case RTZIPTYPE_BZLIB:
1976 return VERR_NOT_SUPPORTED;
1977
1978 default:
1979 AssertMsgFailed(("%d\n", enmType));
1980 return VERR_INVALID_PARAMETER;
1981 }
1982 return VINF_SUCCESS;
1983}
1984RT_EXPORT_SYMBOL(RTZipBlockDecompress);
1985
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette