1 /**************************************************************************\
2 * Copyright (c) Kongsberg Oil & Gas Technologies AS
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * Neither the name of the copyright holder nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #else /* No config.h? Hmm. Assume the zlib library is available for linking. */
36 #define ZLIBGLUE_ASSUME_ZLIB 1
37 #endif /* !HAVE_CONFIG_H */
38
39 #include <cassert>
40 #include <cstdlib>
41 #include <cstring>
42 #include <cstdio>
43
44 #ifdef HAVE_ZLIB /* In case we're _not_ doing runtime linking. */
45 #define ZLIBGLUE_ASSUME_ZLIB 1
46 #include <zlib.h>
47 #endif /* ZLIBGLUE_ASSUME_ZLIB */
48
49 #include <Inventor/C/basic.h>
50 #include <Inventor/C/glue/dl.h>
51 #include <Inventor/C/errors/debugerror.h>
52 #include <Inventor/C/tidbits.h>
53
54 #include "tidbitsp.h"
55 #include "threads/threadsutilp.h"
56 #include "glue/zlib.h"
57 #include "io/gzmemio.h"
58
59 /* workarounds for hacks in the zlib header file. inflateInit2
60 and deflateInit2 are not functions but defines. The real
61 function names are inflateInit2_ and deflateInit2_ *sigh* */
62
63 #ifdef deflateInit
64 #undef deflateInit
65 #endif /* deflateInit */
66
67 #ifdef deflateInit2
68 #undef deflateInit2
69 #endif /* deflateInit2 */
70
71 #ifdef inflateInit
72 #undef inflateInit
73 #endif /* inflateInit */
74
75 #ifdef inflateInit2
76 #undef inflateInit2
77 #endif /* inflateInit */
78
79 #define deflateInit2 deflateInit2_
80 #define inflateInit2 inflateInit2_
81
82 typedef const char * (*cc_zlibglue_zlibVersion_t)(void);
83 typedef int (*cc_zlibglue_deflateInit2_t)(void * stream,
84 int level,
85 int method,
86 int windowbits,
87 int memlevel,
88 int strategy);
89
90 typedef int (*cc_zlibglue_inflateInit2_t)(void * stream,
91 int windowbits,
92 const char * version,
93 int stream_size);
94
95 typedef int (*cc_zlibglue_deflateEnd_t)(void * stream);
96 typedef int (*cc_zlibglue_inflateEnd_t)(void * stream);
97 typedef int (*cc_zlibglue_inflate_t)(void * stream, int flush);
98 typedef int (*cc_zlibglue_inflateReset_t)(void * stream);
99 typedef int (*cc_zlibglue_deflateParams_t)(void * stream, int level, int strategy);
100 typedef int (*cc_zlibglue_deflate_t)(void * stream, int flush);
101
102 typedef void * (*cc_zlibglue_gzopen_t)(const char * path, const char * mode);
103 typedef void * (*cc_zlibglue_gzdopen_t)(int fd, const char * mode);
104 typedef int (*cc_zlibglue_gzsetparams_t)(void * fp, int level, int strategy);
105 typedef int (*cc_zlibglue_gzread_t)(void * fp, void * buf, unsigned int len);
106 typedef int (*cc_zlibglue_gzwrite_t)(void * fp, const void * buf, unsigned int len);
107 typedef off_t (*cc_zlibglue_gzseek_t)(void * fp, off_t offset, int whence);
108 typedef int (*cc_zlibglue_gzrewind_t)(void * fp);
109 typedef off_t (*cc_zlibglue_gztell_t)(void * fp);
110 typedef int (*cc_zlibglue_gzeof_t)(void * fp);
111 typedef int (*cc_zlibglue_gzclose_t)(void * fp);
112 typedef int (*cc_zlibglue_crc32_t)(unsigned long crc, const char * buf, unsigned int len);
113
114 typedef struct {
115 int available;
116 cc_zlibglue_zlibVersion_t zlibVersion;
117 cc_zlibglue_deflateInit2_t deflateInit2;
118 cc_zlibglue_inflateInit2_t inflateInit2;
119 cc_zlibglue_deflateEnd_t deflateEnd;
120 cc_zlibglue_inflateEnd_t inflateEnd;
121 cc_zlibglue_inflate_t inflate;
122 cc_zlibglue_inflateReset_t inflateReset;
123 cc_zlibglue_deflateParams_t deflateParams;
124 cc_zlibglue_deflate_t deflate;
125 cc_zlibglue_gzopen_t gzopen;
126 cc_zlibglue_gzdopen_t gzdopen;
127 cc_zlibglue_gzsetparams_t gzsetparams;
128 cc_zlibglue_gzread_t gzread;
129 cc_zlibglue_gzwrite_t gzwrite;
130 cc_zlibglue_gzseek_t gzseek;
131 cc_zlibglue_gzrewind_t gzrewind;
132 cc_zlibglue_gztell_t gztell;
133 cc_zlibglue_gzeof_t gzeof;
134 cc_zlibglue_gzclose_t gzclose;
135 cc_zlibglue_crc32_t crc32;
136 } cc_zlibglue_t;
137
138 static cc_zlibglue_t * zlib_instance = NULL;
139 static cc_libhandle zlib_libhandle = NULL;
140 static int zlib_failed_to_load = 0;
141
142 /* Cleans up at exit. */
143 static void
zlibglue_cleanup(void)144 zlibglue_cleanup(void)
145 {
146 #ifdef ZLIB_RUNTIME_LINKING
147 if (zlib_libhandle) {
148 cc_dl_close(zlib_libhandle);
149 zlib_libhandle = NULL;
150 }
151 #endif /* ZLIB_RUNTIME_LINKING */
152 assert(zlib_instance);
153 free(zlib_instance);
154 zlib_instance = NULL;
155 zlib_failed_to_load = 0;
156 }
157
158 static const cc_zlibglue_t *
zlibglue_init(void)159 zlibglue_init(void)
160 {
161 CC_SYNC_BEGIN(zlibglue_init);
162
163 if (!zlib_instance && !zlib_failed_to_load) {
164 /* First invocation, do initializations. */
165 cc_zlibglue_t * zi = (cc_zlibglue_t *)malloc(sizeof(cc_zlibglue_t));
166 (void)coin_atexit((coin_atexit_f *)zlibglue_cleanup, CC_ATEXIT_DYNLIBS);
167
168 /* The common case is that zlib is either available from the
169 linking process or we're successfully going to link it in. */
170 zi->available = 1;
171
172 #ifdef ZLIB_RUNTIME_LINKING
173 {
174 int idx;
175 /* FIXME: should we get the system shared library name from an
176 Autoconf check? 20000930 mortene. */
177 const char * possiblelibnames[] = {
178 NULL, /* is set below */
179 "zlib1", "zlib", "libz", "libz.so",
180 "libz.dylib",
181 NULL
182 };
183
184 possiblelibnames[0] = coin_getenv("COIN_ZLIB_LIBNAME");
185 idx = possiblelibnames[0] ? 0 : 1;
186
187 while (!zlib_libhandle && possiblelibnames[idx]) {
188 zlib_libhandle = cc_dl_open(possiblelibnames[idx]);
189 idx++;
190 }
191
192 if (!zlib_libhandle) {
193 zi->available = 0;
194 zlib_failed_to_load = 1;
195 }
196 }
197 /* Define ZLIBGLUE_REGISTER_FUNC macro. Casting the type is
198 necessary for this file to be compatible with C++ compilers. */
199 #define ZLIBGLUE_REGISTER_FUNC(_funcsig_, _funcname_) \
200 do { \
201 zi->_funcname_ = (_funcsig_)cc_dl_sym(zlib_libhandle, SO__QUOTE(_funcname_)); \
202 if (zi->_funcname_ == NULL) zi->available = 0; \
203 } while (0)
204
205 #elif defined(ZLIBGLUE_ASSUME_ZLIB) /* !ZLIB_RUNTIME_LINKING */
206
207 /* Define ZLIBGLUE_REGISTER_FUNC macro. */
208 #define ZLIBGLUE_REGISTER_FUNC(_funcsig_, _funcname_) \
209 zi->_funcname_ = (_funcsig_)_funcname_
210
211 #else /* !ZLIBGLUE_ASSUME_ZLIB */
212 zi->available = 0;
213 /* Define ZLIBGLUE_REGISTER_FUNC macro. */
214 #define ZLIBGLUE_REGISTER_FUNC(_funcsig_, _funcname_) \
215 zi->_funcname_ = NULL
216
217 #endif /* !ZLIBGLUE_ASSUME_ZLIB */
218
219 if (zi->available) {
220 ZLIBGLUE_REGISTER_FUNC(cc_zlibglue_zlibVersion_t, zlibVersion);
221 }
222
223 if (!zi->available || !zi->zlibVersion) {
224 if (!zi->available) {
225 cc_debugerror_post("zlib glue",
226 "Unable to load zlib DLL/shared object.");
227
228 }
229 else {
230 /* something is seriously wrong */
231 cc_debugerror_post("zlib glue",
232 "Loaded zlib DLL ok, but couldn't resolve symbol "
233 "zlibVersion().");
234 }
235 zi->available = 0;
236 zlib_failed_to_load = 1;
237
238 zlib_instance = zi;
239 }
240 else {
241 int major, minor, patch;;
242 if (!coin_parse_versionstring(zi->zlibVersion(), &major, &minor, &patch) ||
243 (major < 1) ||
244 (major == 1 && minor == 0 && patch < 2)) {
245 cc_debugerror_post("zlib glue",
246 "Loaded zlib DLL ok, but version >= 1.0.2 is needed.");
247 zi->available = 0;
248 zlib_failed_to_load = 1;
249 zlib_instance = zi;
250 }
251 else {
252 ZLIBGLUE_REGISTER_FUNC(cc_zlibglue_deflateInit2_t, deflateInit2);
253 ZLIBGLUE_REGISTER_FUNC(cc_zlibglue_inflateInit2_t, inflateInit2);
254 ZLIBGLUE_REGISTER_FUNC(cc_zlibglue_deflateEnd_t, deflateEnd);
255 ZLIBGLUE_REGISTER_FUNC(cc_zlibglue_inflateEnd_t, inflateEnd);
256 ZLIBGLUE_REGISTER_FUNC(cc_zlibglue_inflate_t, inflate);
257 ZLIBGLUE_REGISTER_FUNC(cc_zlibglue_inflateReset_t, inflateReset);
258 ZLIBGLUE_REGISTER_FUNC(cc_zlibglue_deflateParams_t, deflateParams);
259 ZLIBGLUE_REGISTER_FUNC(cc_zlibglue_deflate_t, deflate);
260 ZLIBGLUE_REGISTER_FUNC(cc_zlibglue_gzopen_t, gzopen);
261 ZLIBGLUE_REGISTER_FUNC(cc_zlibglue_gzdopen_t, gzdopen);
262 ZLIBGLUE_REGISTER_FUNC(cc_zlibglue_gzsetparams_t, gzsetparams);
263 ZLIBGLUE_REGISTER_FUNC(cc_zlibglue_gzread_t, gzread);
264 ZLIBGLUE_REGISTER_FUNC(cc_zlibglue_gzwrite_t, gzwrite);
265 ZLIBGLUE_REGISTER_FUNC(cc_zlibglue_gzseek_t, gzseek);
266 ZLIBGLUE_REGISTER_FUNC(cc_zlibglue_gzrewind_t, gzrewind);
267 ZLIBGLUE_REGISTER_FUNC(cc_zlibglue_gztell_t, gztell);
268 ZLIBGLUE_REGISTER_FUNC(cc_zlibglue_gzeof_t, gzeof);
269 ZLIBGLUE_REGISTER_FUNC(cc_zlibglue_gzclose_t, gzclose);
270 ZLIBGLUE_REGISTER_FUNC(cc_zlibglue_crc32_t, crc32);
271
272 /* Do this late, so we can detect recursive calls to this function. */
273 zlib_instance = zi;
274 }
275 }
276 }
277 CC_SYNC_END(zlibglue_init);
278 return zlib_instance;
279 }
280
281
282 int
cc_zlibglue_available(void)283 cc_zlibglue_available(void)
284 {
285 zlibglue_init();
286 return zlib_instance && zlib_instance->available;
287 }
288
289 int
cc_zlibglue_deflateInit2(void * stream,int level,int method,int windowbits,int memlevel,int strategy)290 cc_zlibglue_deflateInit2(void * stream,
291 int level,
292 int method,
293 int windowbits,
294 int memlevel,
295 int strategy)
296 {
297 zlibglue_init();
298 return zlib_instance->deflateInit2(stream,
299 level,
300 method,
301 windowbits,
302 memlevel,
303 strategy);
304 }
305
306 int
cc_zlibglue_inflateInit2(void * stream,int windowbits)307 cc_zlibglue_inflateInit2(void * stream,
308 int windowbits)
309 {
310 zlibglue_init();
311 return zlib_instance->inflateInit2(stream,
312 windowbits,
313 zlib_instance->zlibVersion(),
314 cc_gzm_sizeof_z_stream());
315 }
316
317 int
cc_zlibglue_deflateEnd(void * stream)318 cc_zlibglue_deflateEnd(void * stream)
319 {
320 zlibglue_init();
321 return zlib_instance->deflateEnd(stream);
322 }
323
324 int
cc_zlibglue_inflateEnd(void * stream)325 cc_zlibglue_inflateEnd(void * stream)
326 {
327 zlibglue_init();
328 return zlib_instance->inflateEnd(stream);
329 }
330
331 int
cc_zlibglue_inflate(void * stream,int flush)332 cc_zlibglue_inflate(void * stream, int flush)
333 {
334 zlibglue_init();
335 return zlib_instance->inflate(stream, flush);
336 }
337
338 int
cc_zlibglue_inflateReset(void * stream)339 cc_zlibglue_inflateReset(void * stream)
340 {
341 zlibglue_init();
342 return zlib_instance->inflateReset(stream);
343 }
344
345 int
cc_zlibglue_deflateParams(void * stream,int level,int strategy)346 cc_zlibglue_deflateParams(void * stream, int level, int strategy)
347 {
348 zlibglue_init();
349 return zlib_instance->deflateParams(stream, level, strategy);
350 }
351
352 int
cc_zlibglue_deflate(void * stream,int flush)353 cc_zlibglue_deflate(void * stream, int flush)
354 {
355 zlibglue_init();
356 return zlib_instance->deflate(stream, flush);
357 }
358
359 void *
cc_zlibglue_gzopen(const char * path,const char * mode)360 cc_zlibglue_gzopen(const char * path, const char * mode)
361 {
362 zlibglue_init();
363 return zlib_instance->gzopen(path, mode);
364 }
365
366 void *
cc_zlibglue_gzdopen(int fd,const char * mode)367 cc_zlibglue_gzdopen(int fd, const char * mode)
368 {
369 zlibglue_init();
370 return zlib_instance->gzdopen(fd, mode);
371 }
372
373 int
cc_zlibglue_gzsetparams(void * fp,int level,int strategy)374 cc_zlibglue_gzsetparams(void * fp, int level, int strategy)
375 {
376 zlibglue_init();
377 return zlib_instance->gzsetparams(fp, level, strategy);
378 }
379
380 int
cc_zlibglue_gzread(void * fp,void * buf,unsigned int len)381 cc_zlibglue_gzread(void * fp, void * buf, unsigned int len)
382 {
383 zlibglue_init();
384 return zlib_instance->gzread(fp, buf, len);
385 }
386
387 int
cc_zlibglue_gzwrite(void * fp,const void * buf,unsigned int len)388 cc_zlibglue_gzwrite(void * fp, const void * buf, unsigned int len)
389 {
390 zlibglue_init();
391 return zlib_instance->gzwrite(fp, buf, len);
392 }
393
394 off_t
cc_zlibglue_gzseek(void * fp,off_t offset,int whence)395 cc_zlibglue_gzseek(void * fp, off_t offset, int whence)
396 {
397 zlibglue_init();
398 return zlib_instance->gzseek(fp, offset, whence);
399 }
400
401 int
cc_zlibglue_gzrewind(void * fp)402 cc_zlibglue_gzrewind(void * fp)
403 {
404 zlibglue_init();
405 return zlib_instance->gzrewind(fp);
406 }
407
408 off_t
cc_zlibglue_gztell(void * fp)409 cc_zlibglue_gztell(void * fp)
410 {
411 zlibglue_init();
412 return zlib_instance->gztell(fp);
413 }
414
415 int
cc_zlibglue_gzeof(void * fp)416 cc_zlibglue_gzeof(void * fp)
417 {
418 zlibglue_init();
419 return zlib_instance->gzeof(fp);
420 }
421
422 int
cc_zlibglue_gzclose(void * fp)423 cc_zlibglue_gzclose(void * fp)
424 {
425 zlibglue_init();
426 return zlib_instance->gzclose(fp);
427 }
428
429 int
cc_zlibglue_crc32(unsigned long crc,const char * buf,unsigned int len)430 cc_zlibglue_crc32(unsigned long crc, const char * buf, unsigned int len)
431 {
432 zlibglue_init();
433 return zlib_instance->crc32(crc, buf, len);
434 }
435
436 #undef deflateInit2
437 #undef inflateInit2
438