VirtualBox

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

最後變更 在這個檔案從95807是 95807,由 vboxsync 提交於 3 年 前

IPRT/zip.h: No errno.h in IPRT_NO_CRT mode. bugref:10261

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

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