]> git.ipfire.org Git - thirdparty/kmod.git/commitdiff
libkmod/zlib: Allow to load libz.so on demand
authorLucas De Marchi <lucas.de.marchi@gmail.com>
Sat, 30 Nov 2024 06:38:11 +0000 (00:38 -0600)
committerLucas De Marchi <lucas.de.marchi@gmail.com>
Fri, 6 Dec 2024 21:06:42 +0000 (13:06 -0800)
Use dlfcn helpers to load libz once it's needed.

Signed-off-by: Lucas De Marchi <lucas.de.marchi@gmail.com>
Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
Link: https://github.com/kmod-project/kmod/pull/262
libkmod/libkmod-file-zlib.c

index a7e27b80b89e410101ddf67ef936109b25e218ba..fd382939aaea6c3f74299fd6644e8a2eefeadf21 100644 (file)
@@ -3,6 +3,9 @@
  * Copyright © 2024 Intel Corporation
  */
 
+/* TODO: replace with build system define once supported */
+#define DLSYM_LOCALLY_ENABLED 0
+
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 
 #define READ_STEP (4 * 1024 * 1024)
 
+#define DL_SYMBOL_TABLE(M) \
+       M(gzclose)         \
+       M(gzdopen)         \
+       M(gzerror)         \
+       M(gzread)
+
+DL_SYMBOL_TABLE(DECLARE_SYM)
+
+static int dlopen_zlib(void)
+{
+       static void *dl = NULL;
+
+       if (!DLSYM_LOCALLY_ENABLED)
+               return 0;
+
+       return dlsym_many(&dl, "libz.so.1", DL_SYMBOL_TABLE(DLSYM_ARG) NULL);
+}
+
 int kmod_file_load_zlib(struct kmod_file *file)
 {
        _cleanup_free_ unsigned char *p = NULL;
@@ -28,12 +49,19 @@ int kmod_file_load_zlib(struct kmod_file *file)
        gzFile gzf;
        int gzfd;
 
+       ret = dlopen_zlib();
+       if (ret < 0) {
+               ERR(file->ctx, "zlib: can't load and resolve symbols (%s)",
+                   strerror(-ret));
+               return -EINVAL;
+       }
+
        errno = 0;
        gzfd = fcntl(file->fd, F_DUPFD_CLOEXEC, 3);
        if (gzfd < 0)
                return -errno;
 
-       gzf = gzdopen(gzfd, "rb"); /* takes ownership of the fd */
+       gzf = sym_gzdopen(gzfd, "rb"); /* takes ownership of the fd */
        if (gzf == NULL) {
                close(gzfd);
                return -errno;
@@ -52,12 +80,12 @@ int kmod_file_load_zlib(struct kmod_file *file)
                        p = tmp;
                }
 
-               r = gzread(gzf, p + did, total - did);
+               r = sym_gzread(gzf, p + did, total - did);
                if (r == 0)
                        break;
                else if (r < 0) {
                        int gzerr;
-                       const char *gz_errmsg = gzerror(gzf, &gzerr);
+                       const char *gz_errmsg = sym_gzerror(gzf, &gzerr);
 
                        ERR(file->ctx, "gzip: %s\n", gz_errmsg);
 
@@ -70,11 +98,11 @@ int kmod_file_load_zlib(struct kmod_file *file)
 
        file->memory = TAKE_PTR(p);
        file->size = did;
-       gzclose(gzf);
+       sym_gzclose(gzf);
 
        return 0;
 
 error:
-       gzclose(gzf); /* closes the gzfd */
+       sym_gzclose(gzf);
        return ret;
 }