VirtualBox

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

Last change on this file since 98092 was 98092, checked in by vboxsync, 2 years ago

IPRT/zip + libs/liblzf: Older versions of system-provided liblzf do not provide explicit C-callers, so define that within zip.cpp. This should fix compilation on older distros like Debian Buster++. Restored original header from the vendor branch.

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

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