VirtualBox

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

Last change on this file since 78306 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

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