lib: Add decompression function
Add decompression function to decompress gzip package by using
zlib APIs. Modification for Zlib success compile in LK.
Change-Id: Ibc840fbc1094c0126ddc13d6422d06f5e196be7a
diff --git a/lib/zlib_inflate/decompress.c b/lib/zlib_inflate/decompress.c
new file mode 100644
index 0000000..692ccfa
--- /dev/null
+++ b/lib/zlib_inflate/decompress.c
@@ -0,0 +1,157 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define NO_GZIP
+
+#include "zutil.h"
+
+#ifdef DYNAMIC_CRC_TABLE
+#include "crc32.h"
+#endif
+
+#include "zconf.h"
+#include "zlib.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+#include "decompress.h"
+#include <sys/types.h> /* for size_t */
+#include <string.h>
+#include <debug.h>
+#include <malloc.h>
+
+#define GZIP_HEADER_LEN 10
+#define GZIP_FILENAME_LIMIT 256
+
+static void zlib_free(voidpf qpaque, void *addr)
+{
+ return free(addr);
+}
+
+static void *zlib_alloc(voidpf qpaque, uInt items, size_t size)
+{
+ return malloc(items * size);
+}
+
+/* decompress gzip file "in_buf", return 0 if decompressed successful,
+ * return -1 if decompressed failed.
+ * in_buf - input gzip file
+ * in_len - input the length file
+ * out_buf - output the decompressed data
+ * out_buf_len - the available length of out_buf
+ * pos - position of the end of gzip file
+ * out_len - the length of decompressed data
+ */
+int decompress(unsigned char *in_buf, unsigned int in_len,
+ unsigned char *out_buf,
+ unsigned int out_buf_len,
+ unsigned int *pos,
+ unsigned int *out_len) {
+ struct z_stream_s *stream;
+ int rc = -1;
+ int i;
+
+ if (in_len < GZIP_HEADER_LEN) {
+ dprintf(INFO, "the input data is not a gzip package.\n");
+ return rc;
+ }
+ if (out_buf_len < in_len) {
+ dprintf(INFO, "the avaiable length of out_buf is not enough.\n");
+ return rc;
+ }
+
+ stream = malloc(sizeof(*stream));
+ if (stream == NULL) {
+ dprintf(INFO, "allocating z_stream failed.\n");
+ return rc;
+ }
+
+ stream->zalloc = zlib_alloc;
+ stream->zfree = zlib_free;
+ stream->next_out = out_buf;
+ stream->avail_out = out_buf_len;
+
+ /* skip over gzip header */
+ stream->next_in = in_buf + GZIP_HEADER_LEN;
+ stream->avail_in = out_buf_len - GZIP_HEADER_LEN;
+ /* skip over asciz filename */
+ if (in_buf[3] & 0x8) {
+ for (i = 0; i < GZIP_FILENAME_LIMIT && *stream->next_in++; i++) {
+ if (stream->avail_in == 0) {
+ dprintf(INFO, "header error");
+ goto gunzip_end;
+ }
+ --stream->avail_in;
+ }
+ }
+
+ rc = inflateInit2(stream, -MAX_WBITS);
+
+ if (rc == Z_OK) {
+ if (stream->avail_in == 0) {
+ stream->next_in = in_buf;
+ stream->avail_in = out_buf_len;
+ }
+ rc = inflate(stream, 0);
+
+ /* Z_STREAM_END is "we unpacked it all" */
+ if (rc == Z_STREAM_END) {
+ rc = 0;
+ } else if (rc != Z_OK) {
+ dprintf(INFO, "uncompression error");
+ rc = -1;
+ }
+ }
+
+ inflateEnd(stream);
+ if (pos)
+ /* alculation the length of the compressed package */
+ *pos = stream->next_in - in_buf + 8;
+
+ if (out_len)
+ *out_len = stream->total_out;
+
+gunzip_end:
+ free(stream);
+ return rc; /* returns 0 if decompressed successful */
+}
+
+/* check if the input "buf" file was a gzip package.
+ * Return true if the input "buf" is a gzip package.
+ */
+int is_gzip_package(unsigned char *buf, unsigned int len)
+{
+ if (len < 10 || !buf || buf[0] != 0x1f ||
+ buf[1] != 0x8b || buf[2] != 0x08)
+ {
+ dprintf(INFO, "Not a gzip file\n");
+ return false;
+ }
+
+ return true;
+}