VirtualBox

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

Last change on this file since 56290 was 56290, checked in by vboxsync, 10 years ago

IPRT: Updated (C) year.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 56.1 KB
Line 
1/* $Id: zip.cpp 56290 2015-06-09 14:01:31Z vboxsync $ */
2/** @file
3 * IPRT - Compression.
4 */
5
6/*
7 * Copyright (C) 2006-2015 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 return VINF_SUCCESS;
534}
535
536
537/**
538 * @copydoc RTZipCompDestroy
539 */
540static DECLCALLBACK(int) rtZipZlibCompDestroy(PRTZIPCOMP pZip)
541{
542 /*
543 * Terminate the deflate instance.
544 */
545 int rc = deflateEnd(&pZip->u.Zlib);
546 if (rc != Z_OK)
547 rc = zipErrConvertFromZlib(rc, true /*fCompressing*/);
548 return rc;
549}
550
551
552/**
553 * Initializes the compressor instance.
554 * @returns iprt status code.
555 * @param pZip The compressor instance.
556 * @param enmLevel The desired compression level.
557 * @param fZlibHeader If true, write the Zlib header.
558 */
559static DECLCALLBACK(int) rtZipZlibCompInit(PRTZIPCOMP pZip, RTZIPLEVEL enmLevel, bool fZlibHeader)
560{
561 pZip->pfnCompress = rtZipZlibCompress;
562 pZip->pfnFinish = rtZipZlibCompFinish;
563 pZip->pfnDestroy = rtZipZlibCompDestroy;
564
565 int iLevel = Z_DEFAULT_COMPRESSION;
566 switch (enmLevel)
567 {
568 case RTZIPLEVEL_STORE: iLevel = 0; break;
569 case RTZIPLEVEL_FAST: iLevel = 2; break;
570 case RTZIPLEVEL_DEFAULT: iLevel = Z_DEFAULT_COMPRESSION; break;
571 case RTZIPLEVEL_MAX: iLevel = 9; break;
572 }
573
574 memset(&pZip->u.Zlib, 0, sizeof(pZip->u.Zlib));
575 pZip->u.Zlib.next_out = &pZip->abBuffer[1];
576 pZip->u.Zlib.avail_out = sizeof(pZip->abBuffer) - 1;
577 pZip->u.Zlib.opaque = pZip;
578
579 int rc = deflateInit2(&pZip->u.Zlib, iLevel, Z_DEFLATED, fZlibHeader ? Z_DEF_WBITS : -Z_DEF_WBITS,
580 Z_DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
581 return rc >= 0 ? rc = VINF_SUCCESS : zipErrConvertFromZlib(rc, true /*fCompressing*/);
582}
583
584
585/**
586 * @copydoc RTZipDecompress
587 */
588static DECLCALLBACK(int) rtZipZlibDecompress(PRTZIPDECOMP pZip, void *pvBuf, size_t cbBuf, size_t *pcbWritten)
589{
590 pZip->u.Zlib.next_out = (Bytef *)pvBuf;
591 pZip->u.Zlib.avail_out = (uInt)cbBuf;
592 Assert(pZip->u.Zlib.avail_out == cbBuf);
593
594 /*
595 * Be greedy reading input, even if no output buffer is left. It's possible
596 * that it's just the end of stream marker which needs to be read. Happens
597 * for incompressible blocks just larger than the input buffer size.
598 */
599 while (pZip->u.Zlib.avail_out > 0 || pZip->u.Zlib.avail_in <= 0)
600 {
601 /*
602 * Read more input?
603 */
604 if (pZip->u.Zlib.avail_in <= 0)
605 {
606 size_t cb = sizeof(pZip->abBuffer);
607 int rc = pZip->pfnIn(pZip->pvUser, &pZip->abBuffer[0], sizeof(pZip->abBuffer), &cb);
608 if (RT_FAILURE(rc))
609 return rc;
610 pZip->u.Zlib.avail_in = (uInt)cb; Assert(pZip->u.Zlib.avail_in == cb);
611 pZip->u.Zlib.next_in = &pZip->abBuffer[0];
612 }
613
614 /*
615 * Pass it on to zlib.
616 */
617 int rc = inflate(&pZip->u.Zlib, Z_NO_FLUSH);
618 if (rc == Z_STREAM_END)
619 {
620 if (pcbWritten)
621 *pcbWritten = cbBuf - pZip->u.Zlib.avail_out;
622 else if (pZip->u.Zlib.avail_out > 0)
623 return VERR_NO_DATA;
624 break;
625 }
626 if (rc != Z_OK)
627 return zipErrConvertFromZlib(rc, false /*fCompressing*/);
628 }
629 return VINF_SUCCESS;
630}
631
632
633/**
634 * @copydoc RTZipDecompDestroy
635 */
636static DECLCALLBACK(int) rtZipZlibDecompDestroy(PRTZIPDECOMP pZip)
637{
638 /*
639 * Terminate the deflate instance.
640 */
641 int rc = inflateEnd(&pZip->u.Zlib);
642 if (rc != Z_OK)
643 rc = zipErrConvertFromZlib(rc, false /*fCompressing*/);
644 return rc;
645}
646
647
648/**
649 * Initialize the decompressor instance.
650 * @returns iprt status code.
651 * @param pZip The decompressor instance.
652 * @param fZlibHeader If true, expect the Zlib header.
653 */
654static DECLCALLBACK(int) rtZipZlibDecompInit(PRTZIPDECOMP pZip, bool fZlibHeader)
655{
656 pZip->pfnDecompress = rtZipZlibDecompress;
657 pZip->pfnDestroy = rtZipZlibDecompDestroy;
658
659 memset(&pZip->u.Zlib, 0, sizeof(pZip->u.Zlib));
660 pZip->u.Zlib.opaque = pZip;
661
662 int rc = inflateInit2(&pZip->u.Zlib, fZlibHeader ? Z_DEF_WBITS : -Z_DEF_WBITS);
663 return rc >= 0 ? VINF_SUCCESS : zipErrConvertFromZlib(rc, false /*fCompressing*/);
664}
665
666#endif /* RTZIP_USE_ZLIB */
667
668
669#ifdef RTZIP_USE_BZLIB
670/**
671 * Convert from BZlib errno to iprt status code.
672 * @returns iprt status code.
673 * @param rc BZlib error code.
674 */
675static int zipErrConvertFromBZlib(int rc)
676{
677 /** @todo proper bzlib error conversion. */
678 switch (rc)
679 {
680 case BZ_SEQUENCE_ERROR:
681 AssertMsgFailed(("BZ_SEQUENCE_ERROR shall not happen!\n"));
682 return VERR_GENERAL_FAILURE;
683 case BZ_PARAM_ERROR:
684 return VERR_INVALID_PARAMETER;
685 case BZ_MEM_ERROR:
686 return VERR_NO_MEMORY;
687 case BZ_DATA_ERROR:
688 case BZ_DATA_ERROR_MAGIC:
689 case BZ_IO_ERROR:
690 case BZ_UNEXPECTED_EOF:
691 case BZ_CONFIG_ERROR:
692 return VERR_GENERAL_FAILURE;
693 case BZ_OUTBUFF_FULL:
694 AssertMsgFailed(("BZ_OUTBUFF_FULL shall not happen!\n"));
695 return VERR_GENERAL_FAILURE;
696 default:
697 if (rc >= 0)
698 return VINF_SUCCESS;
699 return VERR_GENERAL_FAILURE;
700 }
701}
702
703
704/**
705 * @copydoc RTZipCompress
706 */
707static DECLCALLBACK(int) rtZipBZlibCompress(PRTZIPCOMP pZip, const void *pvBuf, size_t cbBuf)
708{
709 pZip->u.BZlib.next_in = (char *)pvBuf;
710 pZip->u.BZlib.avail_in = cbBuf;
711 while (pZip->u.BZlib.avail_in > 0)
712 {
713 /*
714 * Flush output buffer?
715 */
716 if (pZip->u.BZlib.avail_out <= 0)
717 {
718 int rc = pZip->pfnOut(pZip->pvUser, &pZip->abBuffer[0], sizeof(pZip->abBuffer) - pZip->u.BZlib.avail_out);
719 if (RT_FAILURE(rc))
720 return rc;
721 pZip->u.BZlib.avail_out = sizeof(pZip->abBuffer);
722 pZip->u.BZlib.next_out = (char *)&pZip->abBuffer[0];
723 }
724
725 /*
726 * Pass it on to zlib.
727 */
728 int rc = BZ2_bzCompress(&pZip->u.BZlib, BZ_RUN);
729 if (rc < 0 && rc != BZ_OUTBUFF_FULL)
730 return zipErrConvertFromBZlib(rc);
731 }
732 return VINF_SUCCESS;
733}
734
735
736/**
737 * @copydoc RTZipCompFinish
738 */
739static DECLCALLBACK(int) rtZipBZlibCompFinish(PRTZIPCOMP pZip)
740{
741 int rc = BZ_FINISH_OK;
742 for (;;)
743 {
744 /*
745 * Flush output buffer?
746 */
747 if (rc == BZ_STREAM_END || pZip->u.BZlib.avail_out <= 0)
748 {
749 int rc2 = pZip->pfnOut(pZip->pvUser, &pZip->abBuffer[0], sizeof(pZip->abBuffer) - pZip->u.BZlib.avail_out);
750 if (RT_FAILURE(rc2))
751 return rc2;
752 pZip->u.BZlib.avail_out = sizeof(pZip->abBuffer);
753 pZip->u.BZlib.next_out = (char *)&pZip->abBuffer[0];
754 if (rc == BZ_STREAM_END)
755 return VINF_SUCCESS;
756 }
757
758 /*
759 * Tell BZlib to finish it.
760 */
761 rc = BZ2_bzCompress(&pZip->u.BZlib, BZ_FINISH);
762 if (rc < 0 && rc != BZ_OUTBUFF_FULL)
763 return zipErrConvertFromBZlib(rc);
764 }
765 return VINF_SUCCESS;
766}
767
768
769/**
770 * @copydoc RTZipCompDestroy
771 */
772static DECLCALLBACK(int) rtZipBZlibCompDestroy(PRTZIPCOMP pZip)
773{
774 /*
775 * Terminate the deflate instance.
776 */
777 int rc = BZ2_bzCompressEnd(&pZip->u.BZlib);
778 if (rc != BZ_OK)
779 rc = zipErrConvertFromBZlib(rc);
780 return rc;
781}
782
783
784/**
785 * Initializes the compressor instance.
786 * @returns iprt status code.
787 * @param pZip The compressor instance.
788 * @param enmLevel The desired compression level.
789 */
790static DECLCALLBACK(int) rtZipBZlibCompInit(PRTZIPCOMP pZip, RTZIPLEVEL enmLevel)
791{
792 pZip->pfnCompress = rtZipBZlibCompress;
793 pZip->pfnFinish = rtZipBZlibCompFinish;
794 pZip->pfnDestroy = rtZipBZlibCompDestroy;
795
796 int iSize = 6;
797 int iWork = 0;
798 switch (enmLevel)
799 {
800 case RTZIPLEVEL_STORE: iSize = 1; iWork = 2; break;
801 case RTZIPLEVEL_FAST: iSize = 2; iWork = 0; break;
802 case RTZIPLEVEL_DEFAULT: iSize = 5; iWork = 0; break;
803 case RTZIPLEVEL_MAX: iSize = 9; iWork = 0; break;
804 }
805
806 memset(&pZip->u.BZlib, 0, sizeof(pZip->u.BZlib));
807 pZip->u.BZlib.next_out = (char *)&pZip->abBuffer[1];
808 pZip->u.BZlib.avail_out = sizeof(pZip->abBuffer) - 1;
809 pZip->u.BZlib.opaque = pZip;
810
811 int rc = BZ2_bzCompressInit(&pZip->u.BZlib, iSize, 0, iWork);
812 return rc >= 0 ? VINF_SUCCESS : zipErrConvertFromBZlib(rc);;
813}
814
815
816/**
817 * @copydoc RTZipDecompress
818 */
819static DECLCALLBACK(int) rtZipBZlibDecompress(PRTZIPDECOMP pZip, void *pvBuf, size_t cbBuf, size_t *pcbWritten)
820{
821 pZip->u.BZlib.next_out = (char *)pvBuf;
822 pZip->u.BZlib.avail_out = cbBuf;
823 while (pZip->u.BZlib.avail_out > 0)
824 {
825 /*
826 * Read more output buffer?
827 */
828 if (pZip->u.BZlib.avail_in <= 0)
829 {
830 size_t cb;
831 int rc = pZip->pfnIn(pZip->pvUser, &pZip->abBuffer[0], sizeof(pZip->abBuffer), &cb);
832 if (RT_FAILURE(rc))
833 return rc;
834 pZip->u.BZlib.avail_in = cb;
835 pZip->u.BZlib.next_in = (char *)&pZip->abBuffer[0];
836 }
837
838 /*
839 * Pass it on to zlib.
840 */
841 int rc = BZ2_bzDecompress(&pZip->u.BZlib);
842 if (rc == BZ_STREAM_END || rc == BZ_OUTBUFF_FULL)
843 {
844 if (pcbWritten)
845 *pcbWritten = cbBuf - pZip->u.BZlib.avail_out;
846 else if (pZip->u.BZlib.avail_out > 0)
847 return VERR_NO_DATA;
848 break;
849 }
850 if (rc < 0)
851 return zipErrConvertFromBZlib(rc);
852 }
853 return VINF_SUCCESS;
854}
855
856
857/**
858 * @copydoc RTZipDecompDestroy
859 */
860static DECLCALLBACK(int) rtZipBZlibDecompDestroy(PRTZIPDECOMP pZip)
861{
862 /*
863 * Terminate the deflate instance.
864 */
865 int rc = BZ2_bzDecompressEnd(&pZip->u.BZlib);
866 if (rc != BZ_OK)
867 rc = zipErrConvertFromBZlib(rc);
868 return rc;
869}
870
871
872/**
873 * Initialize the decompressor instance.
874 * @returns iprt status code.
875 * @param pZip The decompressor instance.
876 */
877static DECLCALLBACK(int) rtZipBZlibDecompInit(PRTZIPDECOMP pZip)
878{
879 pZip->pfnDecompress = rtZipBZlibDecompress;
880 pZip->pfnDestroy = rtZipBZlibDecompDestroy;
881
882 memset(&pZip->u.BZlib, 0, sizeof(pZip->u.BZlib));
883 pZip->u.BZlib.opaque = pZip;
884
885 int rc = BZ2_bzDecompressInit(&pZip->u.BZlib, 0, 0);
886 return rc >= 0 ? VINF_SUCCESS : zipErrConvertFromBZlib(rc);
887}
888
889#endif /* RTZIP_USE_BZLIB */
890
891
892#ifdef RTZIP_USE_LZF
893
894/**
895 * Flushes the output buffer.
896 * @returns iprt status code.
897 * @param pZip The compressor instance.
898 */
899static int rtZipLZFCompFlushOutput(PRTZIPCOMP pZip)
900{
901 size_t cb = pZip->u.LZF.pbOutput - &pZip->abBuffer[0];
902 pZip->u.LZF.pbOutput = &pZip->abBuffer[0];
903 return pZip->pfnOut(pZip->pvUser, &pZip->abBuffer[0], cb);
904}
905
906
907/**
908 * Compresses a buffer using LZF.
909 *
910 * @returns VBox status code.
911 * @param pZip The compressor instance.
912 * @param pbBuf What to compress.
913 * @param cbBuf How much to compress.
914 */
915static int rtZipLZFCompressBuffer(PRTZIPCOMP pZip, const uint8_t *pbBuf, size_t cbBuf)
916{
917 bool fForceFlush = false;
918 while (cbBuf > 0)
919 {
920 /*
921 * Flush output buffer?
922 */
923 unsigned cbFree = (unsigned)(sizeof(pZip->abBuffer) - (pZip->u.LZF.pbOutput - &pZip->abBuffer[0]));
924 if ( fForceFlush
925 || cbFree < RTZIPLZF_MAX_DATA_SIZE + sizeof(RTZIPLZFHDR))
926 {
927 int rc = rtZipLZFCompFlushOutput(pZip);
928 if (RT_FAILURE(rc))
929 return rc;
930 fForceFlush = false;
931 cbFree = sizeof(pZip->abBuffer);
932 }
933
934 /*
935 * Setup the block header.
936 */
937 PRTZIPLZFHDR pHdr = (PRTZIPLZFHDR)pZip->u.LZF.pbOutput; /* warning: This might be unaligned! */
938 pHdr->u16Magic = RTZIPLZFHDR_MAGIC;
939 pHdr->cbData = 0;
940 pHdr->u32CRC = 0;
941 pHdr->cbUncompressed = 0;
942 cbFree -= sizeof(*pHdr);
943 pZip->u.LZF.pbOutput += sizeof(*pHdr);
944
945 /*
946 * Compress data for the block.
947 *
948 * We try compress as much as we have freespace for at first,
949 * but if it turns out the compression is inefficient, we'll
950 * reduce the size of data we try compress till it fits the
951 * output space.
952 */
953 cbFree = RT_MIN(cbFree, RTZIPLZF_MAX_DATA_SIZE);
954 unsigned cbInput = (unsigned)RT_MIN(RTZIPLZF_MAX_UNCOMPRESSED_DATA_SIZE, cbBuf);
955 unsigned cbOutput = lzf_compress(pbBuf, cbInput, pZip->u.LZF.pbOutput, cbFree);
956 if (!cbOutput)
957 {
958 /** @todo add an alternative method which stores the raw data if bad compression. */
959 do
960 {
961 cbInput /= 2;
962 if (!cbInput)
963 {
964 AssertMsgFailed(("lzf_compress bug! cbFree=%zu\n", cbFree));
965 return VERR_INTERNAL_ERROR;
966 }
967 cbOutput = lzf_compress(pbBuf, cbInput, pZip->u.LZF.pbOutput, cbFree);
968 } while (!cbOutput);
969 fForceFlush = true;
970 }
971
972 /*
973 * Update the header and advance the input buffer.
974 */
975 pHdr->cbData = cbOutput;
976 //pHdr->u32CRC = RTCrc32(pbBuf, cbInput); - too slow
977 pHdr->cbUncompressed = cbInput;
978
979 pZip->u.LZF.pbOutput += cbOutput;
980 cbBuf -= cbInput;
981 pbBuf += cbInput;
982 }
983 return VINF_SUCCESS;
984}
985
986
987/**
988 * Flushes the input buffer.
989 * @returns iprt status code.
990 * @param pZip The compressor instance.
991 */
992static int rtZipLZFCompFlushInput(PRTZIPCOMP pZip)
993{
994 size_t cb = pZip->u.LZF.pbInput - &pZip->u.LZF.abInput[0];
995 pZip->u.LZF.pbInput = &pZip->u.LZF.abInput[0];
996 pZip->u.LZF.cbInputFree = sizeof(pZip->u.LZF.abInput);
997 if (cb)
998 return rtZipLZFCompressBuffer(pZip, pZip->u.LZF.abInput, cb);
999 return VINF_SUCCESS;
1000}
1001
1002
1003/**
1004 * @copydoc RTZipCompress
1005 */
1006static DECLCALLBACK(int) rtZipLZFCompress(PRTZIPCOMP pZip, const void *pvBuf, size_t cbBuf)
1007{
1008#define RTZIPLZF_SMALL_CHUNK (128)
1009
1010 /*
1011 * Flush the input buffer if necessary.
1012 */
1013 if ( ( cbBuf <= RTZIPLZF_SMALL_CHUNK
1014 && cbBuf > pZip->u.LZF.cbInputFree)
1015 || ( cbBuf > RTZIPLZF_SMALL_CHUNK
1016 && pZip->u.LZF.cbInputFree != sizeof(pZip->u.LZF.abInput))
1017 )
1018 {
1019 int rc = rtZipLZFCompFlushInput(pZip);
1020 if (RT_FAILURE(rc))
1021 return rc;
1022 }
1023
1024 /*
1025 * If it's a relativly small block put it in the input buffer, elsewise
1026 * compress directly it.
1027 */
1028 if (cbBuf <= RTZIPLZF_SMALL_CHUNK)
1029 {
1030 Assert(pZip->u.LZF.cbInputFree >= cbBuf);
1031 memcpy(pZip->u.LZF.pbInput, pvBuf, cbBuf);
1032 pZip->u.LZF.pbInput += cbBuf;
1033 pZip->u.LZF.cbInputFree -= cbBuf;
1034 }
1035 else
1036 {
1037 Assert(pZip->u.LZF.cbInputFree == sizeof(pZip->u.LZF.abInput));
1038 int rc = rtZipLZFCompressBuffer(pZip, (const uint8_t *)pvBuf, cbBuf);
1039 if (RT_FAILURE(rc))
1040 return rc;
1041 }
1042 return VINF_SUCCESS;
1043}
1044
1045
1046/**
1047 * @copydoc RTZipCompFinish
1048 */
1049static DECLCALLBACK(int) rtZipLZFCompFinish(PRTZIPCOMP pZip)
1050{
1051 int rc = rtZipLZFCompFlushInput(pZip);
1052 if (RT_SUCCESS(rc))
1053 rc = rtZipLZFCompFlushOutput(pZip);
1054 return rc;
1055}
1056
1057
1058/**
1059 * @copydoc RTZipCompDestroy
1060 */
1061static DECLCALLBACK(int) rtZipLZFCompDestroy(PRTZIPCOMP pZip)
1062{
1063 NOREF(pZip);
1064 return VINF_SUCCESS;
1065}
1066
1067
1068/**
1069 * Initializes the compressor instance.
1070 * @returns iprt status code.
1071 * @param pZip The compressor instance.
1072 * @param enmLevel The desired compression level.
1073 */
1074static DECLCALLBACK(int) rtZipLZFCompInit(PRTZIPCOMP pZip, RTZIPLEVEL enmLevel)
1075{
1076 NOREF(enmLevel);
1077 pZip->pfnCompress = rtZipLZFCompress;
1078 pZip->pfnFinish = rtZipLZFCompFinish;
1079 pZip->pfnDestroy = rtZipLZFCompDestroy;
1080
1081 pZip->u.LZF.pbOutput = &pZip->abBuffer[1];
1082 pZip->u.LZF.pbInput = &pZip->u.LZF.abInput[0];
1083 pZip->u.LZF.cbInputFree = sizeof(pZip->u.LZF.abInput);
1084 return VINF_SUCCESS;
1085}
1086
1087
1088/**
1089 * This will validate a header and to all the necessary bitching if it's invalid.
1090 * @returns true if valid.
1091 * @returns false if invalid.
1092 * @param pHdr Pointer to the header.\
1093 */
1094static bool rtZipLZFValidHeader(PCRTZIPLZFHDR pHdr)
1095{
1096 if ( pHdr->u16Magic != RTZIPLZFHDR_MAGIC
1097 || !pHdr->cbData
1098 || pHdr->cbData > RTZIPLZF_MAX_DATA_SIZE
1099 || !pHdr->cbUncompressed
1100 || pHdr->cbUncompressed > RTZIPLZF_MAX_UNCOMPRESSED_DATA_SIZE
1101 )
1102 {
1103 AssertMsgFailed(("Invalid LZF header! %.*%Rhxs\n", sizeof(pHdr), pHdr));
1104 return false;
1105 }
1106 return true;
1107}
1108
1109
1110/**
1111 * @copydoc RTZipDecompress
1112 */
1113static DECLCALLBACK(int) rtZipLZFDecompress(PRTZIPDECOMP pZip, void *pvBuf, size_t cbBuf, size_t *pcbWritten)
1114{
1115 /*
1116 * Decompression loop.
1117 *
1118 * This a bit ugly because we have to deal with reading block...
1119 * To simplify matters we've put a max block size and will never
1120 * fill the input buffer with more than allows us to complete
1121 * any partially read blocks.
1122 *
1123 * When possible we decompress directly to the user buffer, when
1124 * not possible we'll use the spill buffer.
1125 */
1126# ifdef RTZIP_LZF_BLOCK_BY_BLOCK
1127 size_t cbWritten = 0;
1128 while (cbBuf > 0)
1129 {
1130 /*
1131 * Anything in the spill buffer?
1132 */
1133 if (pZip->u.LZF.cbSpill > 0)
1134 {
1135 unsigned cb = (unsigned)RT_MIN(pZip->u.LZF.cbSpill, cbBuf);
1136 memcpy(pvBuf, pZip->u.LZF.pbSpill, cb);
1137 pZip->u.LZF.pbSpill += cb;
1138 pZip->u.LZF.cbSpill -= cb;
1139 cbWritten += cb;
1140 cbBuf -= cb;
1141 if (!cbBuf)
1142 break;
1143 pvBuf = (uint8_t *)pvBuf + cb;
1144 }
1145
1146 /*
1147 * We always read and work one block at a time.
1148 */
1149 RTZIPLZFHDR Hdr;
1150 int rc = pZip->pfnIn(pZip->pvUser, &Hdr, sizeof(Hdr), NULL);
1151 if (RT_FAILURE(rc))
1152 return rc;
1153 if (!rtZipLZFValidHeader(&Hdr))
1154 return VERR_GENERAL_FAILURE; /** @todo Get better error codes for RTZip! */
1155 if (Hdr.cbData > 0)
1156 {
1157 rc = pZip->pfnIn(pZip->pvUser, &pZip->abBuffer[0], Hdr.cbData, NULL);
1158 if (RT_FAILURE(rc))
1159 return rc;
1160 }
1161
1162 /*
1163 * Does the uncompressed data fit into the supplied buffer?
1164 * If so we uncompress it directly into the user buffer, else we'll have to use the spill buffer.
1165 */
1166 unsigned cbUncompressed = Hdr.cbUncompressed;
1167 if (cbUncompressed <= cbBuf)
1168 {
1169 unsigned cbOutput = lzf_decompress(&pZip->abBuffer[0], Hdr.cbData, pvBuf, cbUncompressed);
1170 if (cbOutput != cbUncompressed)
1171 {
1172 AssertMsgFailed(("Decompression error, errno=%d. cbOutput=%#x cbUncompressed=%#x\n",
1173 errno, cbOutput, cbUncompressed));
1174 return VERR_GENERAL_FAILURE; /** @todo Get better error codes for RTZip! */
1175 }
1176 cbBuf -= cbUncompressed;
1177 pvBuf = (uint8_t *)pvBuf + cbUncompressed;
1178 cbWritten += cbUncompressed;
1179 }
1180 else
1181 {
1182 unsigned cbOutput = lzf_decompress(&pZip->abBuffer[0], Hdr.cbData, pZip->u.LZF.abSpill, cbUncompressed);
1183 if (cbOutput != cbUncompressed)
1184 {
1185 AssertMsgFailed(("Decompression error, errno=%d. cbOutput=%#x cbUncompressed=%#x\n",
1186 errno, cbOutput, cbUncompressed));
1187 return VERR_GENERAL_FAILURE; /** @todo Get better error codes for RTZip! */
1188 }
1189 pZip->u.LZF.pbSpill = &pZip->u.LZF.abSpill[0];
1190 pZip->u.LZF.cbSpill = cbUncompressed;
1191 }
1192 }
1193
1194 if (pcbWritten)
1195 *pcbWritten = cbWritten;
1196# else /* !RTZIP_LZF_BLOCK_BY_BLOCK */
1197 while (cbBuf > 0)
1198 {
1199 /*
1200 * Anything in the spill buffer?
1201 */
1202 if (pZip->u.LZF.cbSpill > 0)
1203 {
1204 unsigned cb = (unsigned)RT_MIN(pZip->u.LZF.cbSpill, cbBuf);
1205 memcpy(pvBuf, pZip->u.LZF.pbSpill, cb);
1206 pZip->u.LZF.pbSpill += cb;
1207 pZip->u.LZF.cbSpill -= cb;
1208 cbBuf -= cb;
1209 if (pcbWritten)
1210 *pcbWritten = cb;
1211 if (!cbBuf)
1212 break;
1213 pvBuf = (uint8_t *)pvBuf + cb;
1214 }
1215
1216 /*
1217 * Incomplete header or nothing at all.
1218 */
1219 PCRTZIPLZFHDR pHdr;
1220 if (pZip->u.LZF.cbInput < sizeof(RTZIPLZFHDR))
1221 {
1222 if (pZip->u.LZF.cbInput <= 0)
1223 {
1224 /* empty, fill the buffer. */
1225 size_t cb = 0;
1226 int rc = pZip->pfnIn(pZip->pvUser, &pZip->abBuffer[0],
1227 sizeof(pZip->abBuffer) - RTZIPLZF_MAX_DATA_SIZE, &cb);
1228 if (RT_FAILURE(rc))
1229 return rc;
1230 pZip->u.LZF.pbInput = &pZip->abBuffer[0];
1231 pZip->u.LZF.cbInput = cb;
1232 pHdr = (PCRTZIPLZFHDR)pZip->u.LZF.pbInput;
1233 }
1234 else
1235 {
1236 /* move the header up and fill the buffer. */
1237 size_t cbCur = pZip->u.LZF.cbInput;
1238 memmove(&pZip->abBuffer[0], pZip->u.LZF.pbInput, cbCur);
1239 pZip->u.LZF.pbInput = &pZip->abBuffer[0];
1240
1241 size_t cb = 0;
1242 int rc = pZip->pfnIn(pZip->pvUser, &pZip->abBuffer[cbCur],
1243 sizeof(pZip->abBuffer) - RTZIPLZF_MAX_DATA_SIZE - cbCur, &cb);
1244 if (RT_FAILURE(rc))
1245 return rc;
1246 pHdr = (PCRTZIPLZFHDR)pZip->u.LZF.pbInput;
1247 pZip->u.LZF.cbInput += cb;
1248 }
1249
1250 /*
1251 * Validate the header.
1252 */
1253 if (!rtZipLZFValidHeader(pHdr))
1254 return VERR_GENERAL_FAILURE; /** @todo Get better error codes for RTZip! */
1255 }
1256 else
1257 {
1258 /*
1259 * Validate the header and check if it's an incomplete block.
1260 */
1261 pHdr = (PCRTZIPLZFHDR)pZip->u.LZF.pbInput;
1262 if (!rtZipLZFValidHeader(pHdr))
1263 return VERR_GENERAL_FAILURE; /** @todo Get better error codes for RTZip! */
1264
1265 if (pHdr->cbData > pZip->u.LZF.cbInput - sizeof(*pHdr))
1266 {
1267 /* read the remainder of the block. */
1268 size_t cbToRead = pHdr->cbData - (pZip->u.LZF.cbInput - sizeof(*pHdr));
1269 Assert(&pZip->u.LZF.pbInput[pZip->u.LZF.cbInput + cbToRead] <= &pZip->u.LZF.pbInput[sizeof(pZip->abBuffer)]);
1270 int rc = pZip->pfnIn(pZip->pvUser, &pZip->u.LZF.pbInput[pZip->u.LZF.cbInput],
1271 cbToRead, NULL);
1272 if (RT_FAILURE(rc))
1273 return rc;
1274 pZip->u.LZF.cbInput += cbToRead;
1275 }
1276 }
1277 AssertMsgReturn(sizeof(*pHdr) + pHdr->cbData <= pZip->u.LZF.cbInput,
1278 ("cbData=%#x cbInput=%#x\n", pHdr->cbData, pZip->u.LZF.cbInput),
1279 VERR_GENERAL_FAILURE); /** @todo Get better error codes for RTZip! */
1280
1281 /*
1282 * Does the uncompressed data fit into the supplied buffer?
1283 * If so we uncompress it directly into the user buffer, else we'll have to use the spill buffer.
1284 */
1285 unsigned cbUncompressed = pHdr->cbUncompressed;
1286 if (cbUncompressed <= cbBuf)
1287 {
1288 unsigned cbOutput = lzf_decompress(pHdr + 1, pHdr->cbData, pvBuf, cbUncompressed);
1289 if (cbOutput != cbUncompressed)
1290 {
1291 AssertMsgFailed(("Decompression error, errno=%d. cbOutput=%#x cbUncompressed=%#x\n",
1292 errno, cbOutput, cbUncompressed));
1293 return VERR_GENERAL_FAILURE; /** @todo Get better error codes for RTZip! */
1294 }
1295 cbBuf -= cbUncompressed;
1296 pvBuf = (uint8_t *)pvBuf + cbUncompressed;
1297 }
1298 else
1299 {
1300 unsigned cbOutput = lzf_decompress(pHdr + 1, pHdr->cbData, pZip->u.LZF.abSpill, cbUncompressed);
1301 if (cbOutput != cbUncompressed)
1302 {
1303 AssertMsgFailed(("Decompression error, errno=%d. cbOutput=%#x cbUncompressed=%#x\n",
1304 errno, cbOutput, cbUncompressed));
1305 return VERR_GENERAL_FAILURE; /** @todo Get better error codes for RTZip! */
1306 }
1307 pZip->u.LZF.pbSpill = &pZip->u.LZF.abSpill[0];
1308 pZip->u.LZF.cbSpill = cbUncompressed;
1309 }
1310
1311 /* advance the input buffer */
1312 pZip->u.LZF.cbInput -= pHdr->cbData + sizeof(*pHdr);
1313 pZip->u.LZF.pbInput += pHdr->cbData + sizeof(*pHdr);
1314 if (pcbWritten)
1315 *pcbWritten += cbUncompressed;
1316 }
1317# endif /* !RTZIP_LZF_BLOCK_BY_BLOCK */
1318 return VINF_SUCCESS;
1319}
1320
1321
1322/**
1323 * @copydoc RTZipDecompDestroy
1324 */
1325static DECLCALLBACK(int) rtZipLZFDecompDestroy(PRTZIPDECOMP pZip)
1326{
1327 NOREF(pZip);
1328 return VINF_SUCCESS;
1329}
1330
1331
1332/**
1333 * Initialize the decompressor instance.
1334 * @returns iprt status code.
1335 * @param pZip The decompressor instance.
1336 */
1337static DECLCALLBACK(int) rtZipLZFDecompInit(PRTZIPDECOMP pZip)
1338{
1339 pZip->pfnDecompress = rtZipLZFDecompress;
1340 pZip->pfnDestroy = rtZipLZFDecompDestroy;
1341
1342# ifndef RTZIP_LZF_BLOCK_BY_BLOCK
1343 pZip->u.LZF.pbInput = NULL;
1344 pZip->u.LZF.cbInput = 0;
1345# endif
1346 pZip->u.LZF.cbSpill = 0;
1347 pZip->u.LZF.pbSpill = NULL;
1348
1349 return VINF_SUCCESS;
1350}
1351
1352#endif /* RTZIP_USE_LZF */
1353
1354
1355/**
1356 * Create a compressor instance.
1357 *
1358 * @returns iprt status code.
1359 * @param ppZip Where to store the instance handle.
1360 * @param pvUser User argument which will be passed on to pfnOut and pfnIn.
1361 * @param pfnOut Callback for consuming output of compression.
1362 * @param enmType Type of compressor to create.
1363 * @param enmLevel Compression level.
1364 */
1365RTDECL(int) RTZipCompCreate(PRTZIPCOMP *ppZip, void *pvUser, PFNRTZIPOUT pfnOut, RTZIPTYPE enmType, RTZIPLEVEL enmLevel)
1366{
1367 /*
1368 * Validate input.
1369 */
1370 AssertReturn(enmType >= RTZIPTYPE_INVALID && enmType < RTZIPTYPE_END, VERR_INVALID_PARAMETER);
1371 AssertReturn(enmLevel >= RTZIPLEVEL_STORE && enmLevel <= RTZIPLEVEL_MAX, VERR_INVALID_PARAMETER);
1372 AssertPtrReturn(pfnOut, VERR_INVALID_POINTER);
1373 AssertPtrReturn(ppZip, VERR_INVALID_POINTER);
1374
1375 /*
1376 * Allocate memory for the instance data.
1377 */
1378 PRTZIPCOMP pZip = (PRTZIPCOMP)RTMemAlloc(sizeof(RTZIPCOMP));
1379 if (!pZip)
1380 return VERR_NO_MEMORY;
1381
1382 /*
1383 * Determine auto type.
1384 */
1385 if (enmType == RTZIPTYPE_AUTO)
1386 {
1387 if (enmLevel == RTZIPLEVEL_STORE)
1388 enmType = RTZIPTYPE_STORE;
1389 else
1390 {
1391#if defined(RTZIP_USE_ZLIB) && defined(RTZIP_USE_BZLIB)
1392 if (enmLevel == RTZIPLEVEL_MAX)
1393 enmType = RTZIPTYPE_BZLIB;
1394 else
1395 enmType = RTZIPTYPE_ZLIB;
1396#elif defined(RTZIP_USE_ZLIB)
1397 enmType = RTZIPTYPE_ZLIB;
1398#elif defined(RTZIP_USE_BZLIB)
1399 enmType = RTZIPTYPE_BZLIB;
1400#else
1401 enmType = RTZIPTYPE_STORE;
1402#endif
1403 }
1404 }
1405
1406 /*
1407 * Init instance.
1408 */
1409 pZip->pfnOut = pfnOut;
1410 pZip->enmType = enmType;
1411 pZip->pvUser = pvUser;
1412 pZip->abBuffer[0] = enmType; /* first byte is the compression type. */
1413 int rc = VERR_NOT_IMPLEMENTED;
1414 switch (enmType)
1415 {
1416 case RTZIPTYPE_STORE:
1417#ifdef RTZIP_USE_STORE
1418 rc = rtZipStoreCompInit(pZip, enmLevel);
1419#endif
1420 break;
1421
1422 case RTZIPTYPE_ZLIB:
1423 case RTZIPTYPE_ZLIB_NO_HEADER:
1424#ifdef RTZIP_USE_ZLIB
1425 rc = rtZipZlibCompInit(pZip, enmLevel, enmType == RTZIPTYPE_ZLIB /*fZlibHeader*/);
1426#endif
1427 break;
1428
1429 case RTZIPTYPE_BZLIB:
1430#ifdef RTZIP_USE_BZLIB
1431 rc = rtZipBZlibCompInit(pZip, enmLevel);
1432#endif
1433 break;
1434
1435 case RTZIPTYPE_LZF:
1436#ifdef RTZIP_USE_LZF
1437 rc = rtZipLZFCompInit(pZip, enmLevel);
1438#endif
1439 break;
1440
1441 case RTZIPTYPE_LZJB:
1442 case RTZIPTYPE_LZO:
1443 break;
1444
1445 default:
1446 AssertFailedBreak();
1447 }
1448
1449 if (RT_SUCCESS(rc))
1450 *ppZip = pZip;
1451 else
1452 RTMemFree(pZip);
1453 return rc;
1454}
1455RT_EXPORT_SYMBOL(RTZipCompCreate);
1456
1457
1458/**
1459 * Compresses a chunk of memory.
1460 *
1461 * @returns iprt status code.
1462 * @param pZip The compressor instance.
1463 * @param pvBuf Pointer to buffer containing the bits to compress.
1464 * @param cbBuf Number of bytes to compress.
1465 */
1466RTDECL(int) RTZipCompress(PRTZIPCOMP pZip, const void *pvBuf, size_t cbBuf)
1467{
1468 if (!cbBuf)
1469 return VINF_SUCCESS;
1470 return pZip->pfnCompress(pZip, pvBuf, cbBuf);
1471}
1472RT_EXPORT_SYMBOL(RTZipCompress);
1473
1474
1475/**
1476 * Finishes the compression.
1477 * This will flush all data and terminate the compression data stream.
1478 *
1479 * @returns iprt status code.
1480 * @param pZip The compressor instance.
1481 */
1482RTDECL(int) RTZipCompFinish(PRTZIPCOMP pZip)
1483{
1484 return pZip->pfnFinish(pZip);
1485}
1486RT_EXPORT_SYMBOL(RTZipCompFinish);
1487
1488
1489/**
1490 * Destroys the compressor instance.
1491 *
1492 * @returns iprt status code.
1493 * @param pZip The compressor instance.
1494 */
1495RTDECL(int) RTZipCompDestroy(PRTZIPCOMP pZip)
1496{
1497 /*
1498 * Compressor specific destruction attempt first.
1499 */
1500 int rc = pZip->pfnDestroy(pZip);
1501 AssertRCReturn(rc, rc);
1502
1503 /*
1504 * Free the instance memory.
1505 */
1506 pZip->enmType = RTZIPTYPE_INVALID;
1507 RTMemFree(pZip);
1508 return VINF_SUCCESS;
1509}
1510RT_EXPORT_SYMBOL(RTZipCompDestroy);
1511
1512
1513/**
1514 * @copydoc RTZipDecompress
1515 */
1516static DECLCALLBACK(int) rtZipStubDecompress(PRTZIPDECOMP pZip, void *pvBuf, size_t cbBuf, size_t *pcbWritten)
1517{
1518 NOREF(pZip); NOREF(pvBuf); NOREF(cbBuf); NOREF(pcbWritten);
1519 return VERR_NOT_SUPPORTED;
1520}
1521
1522
1523/**
1524 * @copydoc RTZipDecompDestroy
1525 */
1526static DECLCALLBACK(int) rtZipStubDecompDestroy(PRTZIPDECOMP pZip)
1527{
1528 NOREF(pZip);
1529 return VINF_SUCCESS;
1530}
1531
1532
1533/**
1534 * Create a decompressor instance.
1535 *
1536 * @returns iprt status code.
1537 * @param ppZip Where to store the instance handle.
1538 * @param pvUser User argument which will be passed on to pfnOut and pfnIn.
1539 * @param pfnIn Callback for producing input for decompression.
1540 */
1541RTDECL(int) RTZipDecompCreate(PRTZIPDECOMP *ppZip, void *pvUser, PFNRTZIPIN pfnIn)
1542{
1543 /*
1544 * Validate input.
1545 */
1546 AssertPtrReturn(pfnIn, VERR_INVALID_POINTER);
1547 AssertPtrReturn(ppZip, VERR_INVALID_POINTER);
1548
1549 /*
1550 * Allocate memory for the instance data.
1551 */
1552 PRTZIPDECOMP pZip = (PRTZIPDECOMP)RTMemAlloc(sizeof(RTZIPDECOMP));
1553 if (!pZip)
1554 return VERR_NO_MEMORY;
1555
1556 /*
1557 * Init instance.
1558 */
1559 pZip->pfnIn = pfnIn;
1560 pZip->enmType = RTZIPTYPE_INVALID;
1561 pZip->pvUser = pvUser;
1562 pZip->pfnDecompress = NULL;
1563 pZip->pfnDestroy = rtZipStubDecompDestroy;
1564
1565 *ppZip = pZip;
1566 return VINF_SUCCESS;
1567}
1568RT_EXPORT_SYMBOL(RTZipDecompCreate);
1569
1570
1571/**
1572 * Lazy init of the decompressor.
1573 * @returns iprt status code.
1574 * @param pZip The decompressor instance.
1575 */
1576static int rtzipDecompInit(PRTZIPDECOMP pZip)
1577{
1578 /*
1579 * Read the first byte from the stream so we can determine the type.
1580 */
1581 uint8_t u8Type;
1582 int rc = pZip->pfnIn(pZip->pvUser, &u8Type, sizeof(u8Type), NULL);
1583 if (RT_FAILURE(rc))
1584 return rc;
1585
1586 /*
1587 * Determine type and do type specific init.
1588 */
1589 pZip->enmType = (RTZIPTYPE)u8Type;
1590 rc = VERR_NOT_SUPPORTED;
1591 switch (pZip->enmType)
1592 {
1593 case RTZIPTYPE_STORE:
1594#ifdef RTZIP_USE_STORE
1595 rc = rtZipStoreDecompInit(pZip);
1596#else
1597 AssertMsgFailed(("Store is not include in this build!\n"));
1598#endif
1599 break;
1600
1601 case RTZIPTYPE_ZLIB:
1602 case RTZIPTYPE_ZLIB_NO_HEADER:
1603#ifdef RTZIP_USE_ZLIB
1604 rc = rtZipZlibDecompInit(pZip, pZip->enmType == RTZIPTYPE_ZLIB /*fHeader*/);
1605#else
1606 AssertMsgFailed(("Zlib is not include in this build!\n"));
1607#endif
1608 break;
1609
1610 case RTZIPTYPE_BZLIB:
1611#ifdef RTZIP_USE_BZLIB
1612 rc = rtZipBZlibDecompInit(pZip);
1613#else
1614 AssertMsgFailed(("BZlib is not include in this build!\n"));
1615#endif
1616 break;
1617
1618 case RTZIPTYPE_LZF:
1619#ifdef RTZIP_USE_LZF
1620 rc = rtZipLZFDecompInit(pZip);
1621#else
1622 AssertMsgFailed(("LZF is not include in this build!\n"));
1623#endif
1624 break;
1625
1626 case RTZIPTYPE_LZJB:
1627#ifdef RTZIP_USE_LZJB
1628 AssertMsgFailed(("LZJB streaming support is not implemented yet!\n"));
1629#else
1630 AssertMsgFailed(("LZJB is not include in this build!\n"));
1631#endif
1632 break;
1633
1634 case RTZIPTYPE_LZO:
1635#ifdef RTZIP_USE_LZJB
1636 AssertMsgFailed(("LZO streaming support is not implemented yet!\n"));
1637#else
1638 AssertMsgFailed(("LZO is not include in this build!\n"));
1639#endif
1640 break;
1641
1642 default:
1643 AssertMsgFailed(("Invalid compression type %d (%#x)!\n", pZip->enmType, pZip->enmType));
1644 rc = VERR_INVALID_MAGIC;
1645 break;
1646 }
1647 if (RT_FAILURE(rc))
1648 {
1649 pZip->pfnDecompress = rtZipStubDecompress;
1650 pZip->pfnDestroy = rtZipStubDecompDestroy;
1651 }
1652
1653 return rc;
1654}
1655
1656
1657/**
1658 * Decompresses a chunk of memory.
1659 *
1660 * @returns iprt status code.
1661 * @param pZip The decompressor instance.
1662 * @param pvBuf Where to store the decompressed data.
1663 * @param cbBuf Number of bytes to produce. If pcbWritten is set
1664 * any number of bytes up to cbBuf might be returned.
1665 * @param pcbWritten Number of bytes actually written to the buffer. If NULL
1666 * cbBuf number of bytes must be written.
1667 */
1668RTDECL(int) RTZipDecompress(PRTZIPDECOMP pZip, void *pvBuf, size_t cbBuf, size_t *pcbWritten)
1669{
1670 /*
1671 * Skip empty requests.
1672 */
1673 if (!cbBuf)
1674 return VINF_SUCCESS;
1675
1676 /*
1677 * Lazy init.
1678 */
1679 if (!pZip->pfnDecompress)
1680 {
1681 int rc = rtzipDecompInit(pZip);
1682 if (RT_FAILURE(rc))
1683 return rc;
1684 }
1685
1686 /*
1687 * 'Read' the decompressed stream.
1688 */
1689 return pZip->pfnDecompress(pZip, pvBuf, cbBuf, pcbWritten);
1690}
1691RT_EXPORT_SYMBOL(RTZipDecompress);
1692
1693
1694/**
1695 * Destroys the decompressor instance.
1696 *
1697 * @returns iprt status code.
1698 * @param pZip The decompressor instance.
1699 */
1700RTDECL(int) RTZipDecompDestroy(PRTZIPDECOMP pZip)
1701{
1702 /*
1703 * Destroy compressor instance and flush the output buffer.
1704 */
1705 int rc = pZip->pfnDestroy(pZip);
1706 AssertRCReturn(rc, rc);
1707
1708 /*
1709 * Free the instance memory.
1710 */
1711 pZip->enmType = RTZIPTYPE_INVALID;
1712 RTMemFree(pZip);
1713 return rc;
1714}
1715RT_EXPORT_SYMBOL(RTZipDecompDestroy);
1716
1717
1718RTDECL(int) RTZipBlockCompress(RTZIPTYPE enmType, RTZIPLEVEL enmLevel, uint32_t fFlags,
1719 void const *pvSrc, size_t cbSrc,
1720 void *pvDst, size_t cbDst, size_t *pcbDstActual) RT_NO_THROW
1721{
1722 /* input validation - the crash and burn approach as speed is essential here. */
1723 Assert(enmLevel <= RTZIPLEVEL_MAX && enmLevel >= RTZIPLEVEL_STORE);
1724 Assert(!fFlags);
1725
1726 /*
1727 * Deal with flags involving prefixes.
1728 */
1729 /** @todo later: type and/or compressed length prefix. */
1730
1731 /*
1732 * The type specific part.
1733 */
1734 switch (enmType)
1735 {
1736 case RTZIPTYPE_LZF:
1737 {
1738#ifdef RTZIP_USE_LZF
1739# if 0
1740 static const uint8_t s_abZero4K[] =
1741 {
1742 0x01, 0x00, 0x00, 0xe0, 0xff, 0x00, 0xe0, 0xff,
1743 0x00, 0xe0, 0xff, 0x00, 0xe0, 0xff, 0x00, 0xe0,
1744 0xff, 0x00, 0xe0, 0xff, 0x00, 0xe0, 0xff, 0x00,
1745 0xe0, 0xff, 0x00, 0xe0, 0xff, 0x00, 0xe0, 0xff,
1746 0x00, 0xe0, 0xff, 0x00, 0xe0, 0xff, 0x00, 0xe0,
1747 0xff, 0x00, 0xe0, 0xff, 0x00, 0xe0, 0xff, 0x00,
1748 0xe0, 0x7d, 0x00
1749 };
1750 if ( cbSrc == _4K
1751 && !((uintptr_t)pvSrc & 15)
1752 && ASMMemIsZeroPage(pvSrc))
1753 {
1754 if (RT_UNLIKELY(cbDst < sizeof(s_abZero4K)))
1755 return VERR_BUFFER_OVERFLOW;
1756 memcpy(pvDst, s_abZero4K, sizeof(s_abZero4K));
1757 *pcbDstActual = sizeof(s_abZero4K);
1758 break;
1759 }
1760# endif
1761
1762 unsigned cbDstActual = lzf_compress(pvSrc, (unsigned)cbSrc, pvDst, (unsigned)cbDst); /** @todo deal with size type overflows */
1763 if (RT_UNLIKELY(cbDstActual < 1))
1764 return VERR_BUFFER_OVERFLOW;
1765 *pcbDstActual = cbDstActual;
1766 break;
1767#else
1768 return VERR_NOT_SUPPORTED;
1769#endif
1770 }
1771
1772 case RTZIPTYPE_STORE:
1773 {
1774 if (cbDst < cbSrc)
1775 return VERR_BUFFER_OVERFLOW;
1776 memcpy(pvDst, pvSrc, cbSrc);
1777 *pcbDstActual = cbSrc;
1778 break;
1779 }
1780
1781 case RTZIPTYPE_LZJB:
1782 {
1783#ifdef RTZIP_USE_LZJB
1784 AssertReturn(cbDst > cbSrc, VERR_BUFFER_OVERFLOW);
1785 size_t cbDstActual = lzjb_compress((void *)pvSrc, (uint8_t *)pvDst + 1, cbSrc, cbSrc, 0 /*??*/);
1786 if (cbDstActual == cbSrc)
1787 *(uint8_t *)pvDst = 0;
1788 else
1789 *(uint8_t *)pvDst = 1;
1790 *pcbDstActual = cbDstActual + 1;
1791 break;
1792#else
1793 return VERR_NOT_SUPPORTED;
1794#endif
1795 }
1796
1797 case RTZIPTYPE_LZO:
1798 {
1799#ifdef RTZIP_USE_LZO
1800 uint64_t Scratch[RT_ALIGN(LZO1X_1_MEM_COMPRESS, sizeof(uint64_t)) / sizeof(uint64_t)];
1801 int rc = lzo_init();
1802 if (RT_UNLIKELY(rc != LZO_E_OK))
1803 return VERR_INTERNAL_ERROR;
1804
1805 lzo_uint cbDstInOut = cbDst;
1806 rc = lzo1x_1_compress((const lzo_bytep)pvSrc, cbSrc, (lzo_bytep )pvDst, &cbDstInOut, &Scratch[0]);
1807 if (RT_UNLIKELY(rc != LZO_E_OK))
1808 switch (rc)
1809 {
1810 case LZO_E_OUTPUT_OVERRUN: return VERR_BUFFER_OVERFLOW;
1811 default: return VERR_GENERAL_FAILURE;
1812 }
1813 *pcbDstActual = cbDstInOut;
1814 break;
1815#else
1816 return VERR_NOT_SUPPORTED;
1817#endif
1818 }
1819
1820 case RTZIPTYPE_ZLIB:
1821 case RTZIPTYPE_BZLIB:
1822 return VERR_NOT_SUPPORTED;
1823
1824 default:
1825 AssertMsgFailed(("%d\n", enmType));
1826 return VERR_INVALID_PARAMETER;
1827 }
1828
1829 return VINF_SUCCESS;
1830}
1831RT_EXPORT_SYMBOL(RTZipBlockCompress);
1832
1833
1834RTDECL(int) RTZipBlockDecompress(RTZIPTYPE enmType, uint32_t fFlags,
1835 void const *pvSrc, size_t cbSrc, size_t *pcbSrcActual,
1836 void *pvDst, size_t cbDst, size_t *pcbDstActual) RT_NO_THROW
1837{
1838 /* input validation - the crash and burn approach as speed is essential here. */
1839 Assert(!fFlags);
1840
1841 /*
1842 * Deal with flags involving prefixes.
1843 */
1844 /** @todo later: type and/or compressed length prefix. */
1845
1846 /*
1847 * The type specific part.
1848 */
1849 switch (enmType)
1850 {
1851 case RTZIPTYPE_LZF:
1852 {
1853#ifdef RTZIP_USE_LZF
1854 unsigned cbDstActual = lzf_decompress(pvSrc, (unsigned)cbSrc, pvDst, (unsigned)cbDst); /** @todo deal with size type overflows */
1855 if (RT_UNLIKELY(cbDstActual < 1))
1856 {
1857 if (errno == E2BIG)
1858 return VERR_BUFFER_OVERFLOW;
1859 Assert(errno == EINVAL);
1860 return VERR_GENERAL_FAILURE;
1861 }
1862 if (pcbDstActual)
1863 *pcbDstActual = cbDstActual;
1864 if (pcbSrcActual)
1865 *pcbSrcActual = cbSrc;
1866 break;
1867#else
1868 return VERR_NOT_SUPPORTED;
1869#endif
1870 }
1871
1872 case RTZIPTYPE_STORE:
1873 {
1874 if (cbDst < cbSrc)
1875 return VERR_BUFFER_OVERFLOW;
1876 memcpy(pvDst, pvSrc, cbSrc);
1877 if (pcbDstActual)
1878 *pcbDstActual = cbSrc;
1879 if (pcbSrcActual)
1880 *pcbSrcActual = cbSrc;
1881 break;
1882 }
1883
1884 case RTZIPTYPE_LZJB:
1885 {
1886#ifdef RTZIP_USE_LZJB
1887 if (*(uint8_t *)pvSrc == 1)
1888 {
1889 int rc = lzjb_decompress((uint8_t *)pvSrc + 1, pvDst, cbSrc - 1, cbDst, 0 /*??*/);
1890 if (RT_UNLIKELY(rc != 0))
1891 return VERR_GENERAL_FAILURE;
1892 if (pcbDstActual)
1893 *pcbDstActual = cbDst;
1894 }
1895 else
1896 {
1897 AssertReturn(cbDst >= cbSrc - 1, VERR_BUFFER_OVERFLOW);
1898 memcpy(pvDst, (uint8_t *)pvSrc + 1, cbSrc - 1);
1899 if (pcbDstActual)
1900 *pcbDstActual = cbSrc - 1;
1901 }
1902 if (pcbSrcActual)
1903 *pcbSrcActual = cbSrc;
1904 break;
1905#else
1906 return VERR_NOT_SUPPORTED;
1907#endif
1908 }
1909
1910 case RTZIPTYPE_LZO:
1911 {
1912#ifdef RTZIP_USE_LZO
1913 int rc = lzo_init();
1914 if (RT_UNLIKELY(rc != LZO_E_OK))
1915 return VERR_INTERNAL_ERROR;
1916 lzo_uint cbDstInOut = cbDst;
1917 rc = lzo1x_decompress((const lzo_bytep)pvSrc, cbSrc, (lzo_bytep)pvDst, &cbDstInOut, NULL);
1918 if (RT_UNLIKELY(rc != LZO_E_OK))
1919 switch (rc)
1920 {
1921 case LZO_E_OUTPUT_OVERRUN: return VERR_BUFFER_OVERFLOW;
1922 default:
1923 case LZO_E_INPUT_OVERRUN: return VERR_GENERAL_FAILURE;
1924 }
1925 if (pcbSrcActual)
1926 *pcbSrcActual = cbSrc;
1927 if (pcbDstActual)
1928 *pcbDstActual = cbDstInOut;
1929 break;
1930#else
1931 return VERR_NOT_SUPPORTED;
1932#endif
1933 }
1934
1935 case RTZIPTYPE_ZLIB:
1936 {
1937#ifdef RTZIP_USE_ZLIB
1938 AssertReturn(cbSrc == (uInt)cbSrc, VERR_TOO_MUCH_DATA);
1939 AssertReturn(cbDst == (uInt)cbDst, VERR_OUT_OF_RANGE);
1940
1941 z_stream ZStrm;
1942 RT_ZERO(ZStrm);
1943 ZStrm.next_in = (Bytef *)pvSrc;
1944 ZStrm.avail_in = (uInt)cbSrc;
1945 ZStrm.next_out = (Bytef *)pvDst;
1946 ZStrm.avail_out = (uInt)cbDst;
1947
1948 int rc = inflateInit(&ZStrm);
1949 if (RT_UNLIKELY(rc != Z_OK))
1950 return zipErrConvertFromZlib(rc, false /*fCompressing*/);
1951 rc = inflate(&ZStrm, Z_FINISH);
1952 if (rc != Z_STREAM_END)
1953 {
1954 inflateEnd(&ZStrm);
1955 if ((rc == Z_BUF_ERROR && ZStrm.avail_in == 0) || rc == Z_NEED_DICT)
1956 return VERR_ZIP_CORRUPTED;
1957 if (rc == Z_BUF_ERROR)
1958 return VERR_BUFFER_OVERFLOW;
1959 AssertReturn(rc < Z_OK, VERR_GENERAL_FAILURE);
1960 return zipErrConvertFromZlib(rc, false /*fCompressing*/);
1961 }
1962 rc = inflateEnd(&ZStrm);
1963 if (rc != Z_OK)
1964 return zipErrConvertFromZlib(rc, false /*fCompressing*/);
1965
1966 if (pcbSrcActual)
1967 *pcbSrcActual = cbSrc - ZStrm.avail_in;
1968 if (pcbDstActual)
1969 *pcbDstActual = ZStrm.total_out;
1970 break;
1971#else
1972 return VERR_NOT_SUPPORTED;
1973#endif
1974 }
1975
1976 case RTZIPTYPE_BZLIB:
1977 return VERR_NOT_SUPPORTED;
1978
1979 default:
1980 AssertMsgFailed(("%d\n", enmType));
1981 return VERR_INVALID_PARAMETER;
1982 }
1983 return VINF_SUCCESS;
1984}
1985RT_EXPORT_SYMBOL(RTZipBlockDecompress);
1986
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