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