A few bug fixes for Windows.
[openssl.git] / crypto / comp / c_zlib.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <openssl/objects.h>
5 #include <openssl/comp.h>
6
7 COMP_METHOD *COMP_zlib(void );
8
9 static COMP_METHOD zlib_method_nozlib={
10         NID_undef,
11         "(undef)",
12         NULL,
13         NULL,
14         NULL,
15         NULL,
16         NULL,
17         NULL,
18         };
19
20 #ifndef ZLIB
21 #undef ZLIB_SHARED
22 #else
23
24 #include <zlib.h>
25
26 static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out,
27         unsigned int olen, unsigned char *in, unsigned int ilen);
28 static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out,
29         unsigned int olen, unsigned char *in, unsigned int ilen);
30
31 static int zz_uncompress(Bytef *dest, uLongf *destLen, const Bytef *source,
32         uLong sourceLen);
33
34 static COMP_METHOD zlib_method={
35         NID_zlib_compression,
36         LN_zlib_compression,
37         NULL,
38         NULL,
39         zlib_compress_block,
40         zlib_expand_block,
41         NULL,
42         NULL,
43         };
44
45 /* 
46  * When OpenSSL is built on Windows, we do not want to require that
47  * the ZLIB.DLL be available in order for the OpenSSL DLLs to
48  * work.  Therefore, all ZLIB routines are loaded at run time
49  * and we do not link to a .LIB file.
50  */
51 #if defined(WINDOWS) || defined(WIN32)
52 # include <windows.h>
53
54 # define Z_CALLCONV _stdcall
55 # define ZLIB_SHARED
56 #else
57 # define Z_CALLCONV
58 #endif /* !(WINDOWS || WIN32) */
59
60 #ifdef ZLIB_SHARED
61 #include <openssl/dso.h>
62
63 /* Prototypes for built in stubs */
64 static int stub_compress(Bytef *dest,uLongf *destLen,
65         const Bytef *source, uLong sourceLen);
66 static int stub_inflateEnd(z_streamp strm);
67 static int stub_inflate(z_streamp strm, int flush);
68 static int stub_inflateInit_(z_streamp strm, const char * version,
69         int stream_size);
70
71 /* Function pointers */
72 typedef int (Z_CALLCONV *compress_ft)(Bytef *dest,uLongf *destLen,
73         const Bytef *source, uLong sourceLen);
74 typedef int (Z_CALLCONV *inflateEnd_ft)(z_streamp strm);
75 typedef int (Z_CALLCONV *inflate_ft)(z_streamp strm, int flush);
76 typedef int (Z_CALLCONV *inflateInit__ft)(z_streamp strm,
77         const char * version, int stream_size);
78 static compress_ft      p_compress=NULL;
79 static inflateEnd_ft    p_inflateEnd=NULL;
80 static inflate_ft       p_inflate=NULL;
81 static inflateInit__ft  p_inflateInit_=NULL;
82
83 static int zlib_loaded = 0;     /* only attempt to init func pts once */
84 static DSO *zlib_dso = NULL;
85
86 #define compress                stub_compress
87 #define inflateEnd              stub_inflateEnd
88 #define inflate                 stub_inflate
89 #define inflateInit_            stub_inflateInit_
90 #endif /* ZLIB_SHARED */
91
92 static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out,
93              unsigned int olen, unsigned char *in, unsigned int ilen)
94         {
95         unsigned long l;
96         int i;
97         int clear=1;
98
99         if (ilen > 128)
100                 {
101                 out[0]=1;
102                 l=olen-1;
103                 i=compress(&(out[1]),&l,in,(unsigned long)ilen);
104                 if (i != Z_OK)
105                         return(-1);
106                 if (ilen > l)
107                         {
108                         clear=0;
109                         l++;
110                         }
111                 }
112         if (clear)
113                 {
114                 out[0]=0;
115                 memcpy(&(out[1]),in,ilen);
116                 l=ilen+1;
117                 }
118 #ifdef DEBUG_ZLIB
119         fprintf(stderr,"compress(%4d)->%4d %s\n",
120                 ilen,(int)l,(clear)?"clear":"zlib");
121 #endif
122         return((int)l);
123         }
124
125 static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out,
126              unsigned int olen, unsigned char *in, unsigned int ilen)
127         {
128         unsigned long l;
129         int i;
130
131         if (in[0])
132                 {
133                 l=olen;
134                 i=zz_uncompress(out,&l,&(in[1]),(unsigned long)ilen-1);
135                 if (i != Z_OK)
136                         return(-1);
137                 }
138         else
139                 {
140                 memcpy(out,&(in[1]),ilen-1);
141                 l=ilen-1;
142                 }
143 #ifdef DEBUG_ZLIB
144         fprintf(stderr,"expand  (%4d)->%4d %s\n",
145                 ilen,(int)l,in[0]?"zlib":"clear");
146 #endif
147         return((int)l);
148         }
149
150 static int zz_uncompress (Bytef *dest, uLongf *destLen, const Bytef *source,
151              uLong sourceLen)
152 {
153     z_stream stream;
154     int err;
155
156     stream.next_in = (Bytef*)source;
157     stream.avail_in = (uInt)sourceLen;
158     /* Check for source > 64K on 16-bit machine: */
159     if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
160
161     stream.next_out = dest;
162     stream.avail_out = (uInt)*destLen;
163     if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
164
165     stream.zalloc = (alloc_func)0;
166     stream.zfree = (free_func)0;
167
168     err = inflateInit(&stream);
169     if (err != Z_OK) return err;
170
171     err = inflate(&stream, Z_FINISH);
172     if (err != Z_STREAM_END) {
173         inflateEnd(&stream);
174         return err;
175     }
176     *destLen = stream.total_out;
177
178     err = inflateEnd(&stream);
179     return err;
180 }
181
182 #endif
183
184 COMP_METHOD *COMP_zlib(void)
185         {
186         COMP_METHOD *meth = &zlib_method_nozlib;
187
188 #ifdef ZLIB_SHARED
189         if (!zlib_loaded)
190                 {
191 #if defined(WINDOWS) || defined(WIN32)
192                 zlib_dso = DSO_load(NULL, "ZLIB", NULL, 0);
193 #else
194                 zlib_dso = DSO_load(NULL, "z", NULL, 0);
195 #endif
196                 if (zlib_dso != NULL)
197                         {
198                         p_compress
199                                 = (compress_ft) DSO_bind_func(zlib_dso,
200                                         "compress");
201                         p_inflateEnd
202                                 = (inflateEnd_ft) DSO_bind_func(zlib_dso,
203                                         "inflateEnd");
204                         p_inflate
205                                 = (inflate_ft) DSO_bind_func(zlib_dso,
206                                         "inflate");
207                         p_inflateInit_
208                                 = (inflateInit__ft) DSO_bind_func(zlib_dso,
209                                         "inflateInit_");
210                         zlib_loaded++;
211                         meth = &zlib_method;
212                         }
213                 }
214
215 #elif defined(ZLIB)
216         meth = &zlib_method;
217 #endif
218
219         return(meth);
220         }
221
222 #ifdef ZLIB_SHARED
223 /* Stubs for each function to be dynamicly loaded */
224 static int 
225 stub_compress(Bytef *dest,uLongf *destLen,const Bytef *source, uLong sourceLen)
226         {
227         if (p_compress)
228                 return(p_compress(dest,destLen,source,sourceLen));
229         else
230                 return(Z_MEM_ERROR);
231         }
232
233 static int
234 stub_inflateEnd(z_streamp strm)
235         {
236         if ( p_inflateEnd )
237                 return(p_inflateEnd(strm));
238         else
239                 return(Z_MEM_ERROR);
240         }
241
242 static int
243 stub_inflate(z_streamp strm, int flush)
244         {
245         if ( p_inflate )
246                 return(p_inflate(strm,flush));
247         else
248                 return(Z_MEM_ERROR);
249         }
250
251 static int
252 stub_inflateInit_(z_streamp strm, const char * version, int stream_size)
253         {
254         if ( p_inflateInit_ )
255                 return(p_inflateInit_(strm,version,stream_size));
256         else
257                 return(Z_MEM_ERROR);
258         }
259
260 #endif /* ZLIB_SHARED */