master ohmu/fastfetch-openbsd / src / common / impl / zlib.c
ohmu  ·  2026-10-15
 1#include "common/zlib.h"
 2#include "common/debug.h"
 3
 4#if FF_HAVE_ZLIB && !FF_DISABLE_DLOPEN
 5
 6struct FFZlibData zlibData;
 7
 8// Opens the library and leaves the handle in zlibData, so the groups that follow resolve against the
 9// same mapping instead of opening their own.
10static const char* openZlib(void) {
11    #ifdef _WIN32
12    FF_LIBRARY_LOAD_MESSAGE(zlib, "zlib1" FF_LIBRARY_EXTENSION, 2)
13    #else
14    FF_LIBRARY_LOAD_MESSAGE(zlib, "libz" FF_LIBRARY_EXTENSION, 2)
15    #endif
16
17    zlibData.handle = zlib;
18    zlib = nullptr; // the handle is kept in zlibData, so the cleanup must not close it
19    return nullptr;
20}
21
22const char* ffZlibLoad(FFZlibGroup group) {
23    FF_DEBUG("Loading zlib group: %x", group);
24
25    // Opened once, by whichever group is asked for first; the later ones reuse that mapping. A
26    // failed open is retried by the next group rather than cached, so a system without libz pays at
27    // most one attempt per group -- not one per call.
28    if (zlibData.handle == nullptr) {
29        if (zlibData.attempted == UINT8_MAX) {
30            return "Previous attempt to open zlib failed";
31        }
32
33        const char* error = openZlib();
34        if (error != nullptr) {
35            static_assert(sizeof(zlibData.attempted) == 1, "zlibData.attempted must be 1 byte");
36            zlibData.attempted = UINT8_MAX;
37            return error;
38        }
39    }
40
41    if (group & FF_ZLIB_COMPRESS) {
42        if (zlibData.attempted & FF_ZLIB_COMPRESS) {
43            if (!zlibData.ffcompress2) {
44                return "Previous attempt to load compress failed";
45            }
46        } else {
47            zlibData.attempted |= FF_ZLIB_COMPRESS;
48            FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlibData.handle, zlibData, compressBound)
49            FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlibData.handle, zlibData, compress2)
50        }
51    }
52    if (group & FF_ZLIB_INFLATE) {
53        if (zlibData.attempted & FF_ZLIB_INFLATE) {
54            if (!zlibData.ffinflateEnd) {
55                return "Previous attempt to load inflate failed";
56            }
57        } else {
58            zlibData.attempted |= FF_ZLIB_INFLATE;
59            FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlibData.handle, zlibData, inflateInit2_)
60            FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlibData.handle, zlibData, inflate)
61            FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlibData.handle, zlibData, inflateEnd)
62        }
63    }
64
65    if (group & FF_ZLIB_GZFILE) {
66        if (zlibData.attempted & FF_ZLIB_GZFILE) {
67            if (!zlibData.ffgzclose) {
68                return "Previous attempt to load gzfile failed";
69            }
70        } else {
71            zlibData.attempted |= FF_ZLIB_GZFILE;
72            FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlibData.handle, zlibData, gzopen)
73            FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlibData.handle, zlibData, gzread)
74            FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlibData.handle, zlibData, gzclose)
75        }
76    }
77
78    return nullptr;
79}
80
81#endif