xref: /netbsd-src/external/gpl3/binutils.old/dist/zlib/uncompr.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
175fd0b74Schristos /* uncompr.c -- decompress a memory buffer
2ede78133Schristos  * Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler
375fd0b74Schristos  * For conditions of distribution and use, see copyright notice in zlib.h
475fd0b74Schristos  */
575fd0b74Schristos 
6*e992f068Schristos /* @(#) Id */
775fd0b74Schristos 
875fd0b74Schristos #define ZLIB_INTERNAL
975fd0b74Schristos #include "zlib.h"
1075fd0b74Schristos 
1175fd0b74Schristos /* ===========================================================================
12ede78133Schristos      Decompresses the source buffer into the destination buffer.  *sourceLen is
13ede78133Schristos    the byte length of the source buffer. Upon entry, *destLen is the total size
14ede78133Schristos    of the destination buffer, which must be large enough to hold the entire
15ede78133Schristos    uncompressed data. (The size of the uncompressed data must have been saved
16ede78133Schristos    previously by the compressor and transmitted to the decompressor by some
17ede78133Schristos    mechanism outside the scope of this compression library.) Upon exit,
18ede78133Schristos    *destLen is the size of the decompressed data and *sourceLen is the number
19ede78133Schristos    of source bytes consumed. Upon return, source + *sourceLen points to the
20ede78133Schristos    first unused input byte.
2175fd0b74Schristos 
22ede78133Schristos      uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough
23ede78133Schristos    memory, Z_BUF_ERROR if there was not enough room in the output buffer, or
24ede78133Schristos    Z_DATA_ERROR if the input data was corrupted, including if the input data is
25ede78133Schristos    an incomplete zlib stream.
2675fd0b74Schristos */
uncompress2(dest,destLen,source,sourceLen)27ede78133Schristos int ZEXPORT uncompress2 (dest, destLen, source, sourceLen)
28ede78133Schristos     Bytef *dest;
29ede78133Schristos     uLongf *destLen;
30ede78133Schristos     const Bytef *source;
31ede78133Schristos     uLong *sourceLen;
32ede78133Schristos {
33ede78133Schristos     z_stream stream;
34ede78133Schristos     int err;
35ede78133Schristos     const uInt max = (uInt)-1;
36ede78133Schristos     uLong len, left;
37ede78133Schristos     Byte buf[1];    /* for detection of incomplete stream when *destLen == 0 */
38ede78133Schristos 
39ede78133Schristos     len = *sourceLen;
40ede78133Schristos     if (*destLen) {
41ede78133Schristos         left = *destLen;
42ede78133Schristos         *destLen = 0;
43ede78133Schristos     }
44ede78133Schristos     else {
45ede78133Schristos         left = 1;
46ede78133Schristos         dest = buf;
47ede78133Schristos     }
48ede78133Schristos 
49ede78133Schristos     stream.next_in = (z_const Bytef *)source;
50ede78133Schristos     stream.avail_in = 0;
51ede78133Schristos     stream.zalloc = (alloc_func)0;
52ede78133Schristos     stream.zfree = (free_func)0;
53ede78133Schristos     stream.opaque = (voidpf)0;
54ede78133Schristos 
55ede78133Schristos     err = inflateInit(&stream);
56ede78133Schristos     if (err != Z_OK) return err;
57ede78133Schristos 
58ede78133Schristos     stream.next_out = dest;
59ede78133Schristos     stream.avail_out = 0;
60ede78133Schristos 
61ede78133Schristos     do {
62ede78133Schristos         if (stream.avail_out == 0) {
63ede78133Schristos             stream.avail_out = left > (uLong)max ? max : (uInt)left;
64ede78133Schristos             left -= stream.avail_out;
65ede78133Schristos         }
66ede78133Schristos         if (stream.avail_in == 0) {
67ede78133Schristos             stream.avail_in = len > (uLong)max ? max : (uInt)len;
68ede78133Schristos             len -= stream.avail_in;
69ede78133Schristos         }
70ede78133Schristos         err = inflate(&stream, Z_NO_FLUSH);
71ede78133Schristos     } while (err == Z_OK);
72ede78133Schristos 
73ede78133Schristos     *sourceLen -= len + stream.avail_in;
74ede78133Schristos     if (dest != buf)
75ede78133Schristos         *destLen = stream.total_out;
76ede78133Schristos     else if (stream.total_out && err == Z_BUF_ERROR)
77ede78133Schristos         left = 1;
78ede78133Schristos 
79ede78133Schristos     inflateEnd(&stream);
80ede78133Schristos     return err == Z_STREAM_END ? Z_OK :
81ede78133Schristos            err == Z_NEED_DICT ? Z_DATA_ERROR  :
82ede78133Schristos            err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR :
83ede78133Schristos            err;
84ede78133Schristos }
85ede78133Schristos 
uncompress(dest,destLen,source,sourceLen)8675fd0b74Schristos int ZEXPORT uncompress (dest, destLen, source, sourceLen)
8775fd0b74Schristos     Bytef *dest;
8875fd0b74Schristos     uLongf *destLen;
8975fd0b74Schristos     const Bytef *source;
9075fd0b74Schristos     uLong sourceLen;
9175fd0b74Schristos {
92ede78133Schristos     return uncompress2(dest, destLen, source, &sourceLen);
9375fd0b74Schristos }
94