blob: c51fb4d2c2ca27bbedaff808d6b4b2f3e0d43704 [file] [log] [blame]
Matthew Qinff5e6ff2015-03-10 02:56:29 -04001/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation, Inc. nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#define NO_GZIP
30
31#include "zutil.h"
32
33#ifdef DYNAMIC_CRC_TABLE
34#include "crc32.h"
35#endif
36
37#include "zconf.h"
38#include "zlib.h"
39#include "inftrees.h"
40#include "inflate.h"
41#include "inffast.h"
42#include "decompress.h"
43#include <sys/types.h> /* for size_t */
44#include <string.h>
45#include <debug.h>
46#include <malloc.h>
47
48#define GZIP_HEADER_LEN 10
49#define GZIP_FILENAME_LIMIT 256
50
51static void zlib_free(voidpf qpaque, void *addr)
52{
53 return free(addr);
54}
55
56static void *zlib_alloc(voidpf qpaque, uInt items, size_t size)
57{
58 return malloc(items * size);
59}
60
61/* decompress gzip file "in_buf", return 0 if decompressed successful,
62 * return -1 if decompressed failed.
63 * in_buf - input gzip file
64 * in_len - input the length file
65 * out_buf - output the decompressed data
66 * out_buf_len - the available length of out_buf
67 * pos - position of the end of gzip file
68 * out_len - the length of decompressed data
69 */
70int decompress(unsigned char *in_buf, unsigned int in_len,
71 unsigned char *out_buf,
72 unsigned int out_buf_len,
73 unsigned int *pos,
74 unsigned int *out_len) {
75 struct z_stream_s *stream;
76 int rc = -1;
77 int i;
78
79 if (in_len < GZIP_HEADER_LEN) {
80 dprintf(INFO, "the input data is not a gzip package.\n");
81 return rc;
82 }
83 if (out_buf_len < in_len) {
84 dprintf(INFO, "the avaiable length of out_buf is not enough.\n");
85 return rc;
86 }
87
88 stream = malloc(sizeof(*stream));
89 if (stream == NULL) {
90 dprintf(INFO, "allocating z_stream failed.\n");
91 return rc;
92 }
93
94 stream->zalloc = zlib_alloc;
95 stream->zfree = zlib_free;
96 stream->next_out = out_buf;
97 stream->avail_out = out_buf_len;
98
99 /* skip over gzip header */
100 stream->next_in = in_buf + GZIP_HEADER_LEN;
101 stream->avail_in = out_buf_len - GZIP_HEADER_LEN;
102 /* skip over asciz filename */
103 if (in_buf[3] & 0x8) {
104 for (i = 0; i < GZIP_FILENAME_LIMIT && *stream->next_in++; i++) {
105 if (stream->avail_in == 0) {
Matthew Qin6330c2a2015-03-17 04:26:57 -0400106 dprintf(INFO, "header error\n");
Matthew Qinff5e6ff2015-03-10 02:56:29 -0400107 goto gunzip_end;
108 }
109 --stream->avail_in;
110 }
111 }
112
113 rc = inflateInit2(stream, -MAX_WBITS);
Matthew Qin6330c2a2015-03-17 04:26:57 -0400114 if (rc != Z_OK) {
115 dprintf(INFO, "inflateInit2 failed!\n");
116 goto gunzip_end;
117 }
Matthew Qinff5e6ff2015-03-10 02:56:29 -0400118
Matthew Qin6330c2a2015-03-17 04:26:57 -0400119 rc = inflate(stream, 0);
120 /* Z_STREAM_END is "we unpacked it all" */
121 if (rc == Z_STREAM_END) {
122 rc = 0;
123 } else if (rc != Z_OK) {
124 dprintf(INFO, "uncompression error \n");
125 rc = -1;
Matthew Qinff5e6ff2015-03-10 02:56:29 -0400126 }
127
128 inflateEnd(stream);
129 if (pos)
130 /* alculation the length of the compressed package */
131 *pos = stream->next_in - in_buf + 8;
132
133 if (out_len)
134 *out_len = stream->total_out;
135
136gunzip_end:
137 free(stream);
138 return rc; /* returns 0 if decompressed successful */
139}
140
141/* check if the input "buf" file was a gzip package.
142 * Return true if the input "buf" is a gzip package.
143 */
144int is_gzip_package(unsigned char *buf, unsigned int len)
145{
146 if (len < 10 || !buf || buf[0] != 0x1f ||
147 buf[1] != 0x8b || buf[2] != 0x08)
148 {
Matthew Qinff5e6ff2015-03-10 02:56:29 -0400149 return false;
150 }
151
152 return true;
153}