diff --git a/Makefile.am b/Makefile.am index fbd205d..443c04d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -80,6 +80,10 @@ if ENABLE_XZ libkmod_libkmod_la_SOURCES += libkmod/libkmod-file-xz.c endif +if ENABLE_ZLIB +libkmod_libkmod_la_SOURCES += libkmod/libkmod-file-zlib.c +endif + EXTRA_DIST += libkmod/libkmod.sym EXTRA_DIST += libkmod/README \ libkmod/COPYING testsuite/COPYING tools/COPYING COPYING diff --git a/configure.ac b/configure.ac index 5768e5e..85fefe3 100644 --- a/configure.ac +++ b/configure.ac @@ -150,6 +150,7 @@ AS_IF([test "x$with_zlib" != "xno"], [ AC_MSG_NOTICE([zlib support not requested]) ]) CC_FEATURE_APPEND([with_features], [with_zlib], [ZLIB]) +AM_CONDITIONAL([ENABLE_ZLIB], [test "x$with_zlib" != "xno"]) AC_ARG_WITH([openssl], AS_HELP_STRING([--with-openssl], [handle PKCS7 signatures @<:@default=disabled@:>@]), diff --git a/libkmod/libkmod-file-zlib.c b/libkmod/libkmod-file-zlib.c new file mode 100644 index 0000000..80c7bfe --- /dev/null +++ b/libkmod/libkmod-file-zlib.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/* + * Copyright © 2024 Intel Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "libkmod.h" +#include "libkmod-internal.h" +#include "libkmod-internal-file.h" + +#define READ_STEP (4 * 1024 * 1024) + +int kmod_file_load_zlib(struct kmod_file *file) +{ + int err = 0; + off_t did = 0, total = 0; + _cleanup_free_ unsigned char *p = NULL; + gzFile gzf; + int gzfd; + + errno = 0; + gzfd = fcntl(file->fd, F_DUPFD_CLOEXEC, 3); + if (gzfd < 0) + return -errno; + + gzf = gzdopen(gzfd, "rb"); /* takes ownership of the fd */ + if (gzf == NULL) { + close(gzfd); + return -errno; + } + + for (;;) { + int r; + + if (did == total) { + void *tmp = realloc(p, total + READ_STEP); + if (tmp == NULL) { + err = -errno; + goto error; + } + total += READ_STEP; + p = tmp; + } + + r = gzread(gzf, p + did, total - did); + if (r == 0) + break; + else if (r < 0) { + int gzerr; + const char *gz_errmsg = gzerror(gzf, &gzerr); + + ERR(file->ctx, "gzip: %s\n", gz_errmsg); + + /* gzip might not set errno here */ + err = gzerr == Z_ERRNO ? -errno : -EINVAL; + goto error; + } + did += r; + } + + file->memory = p; + file->size = did; + p = NULL; + gzclose(gzf); + return 0; + +error: + gzclose(gzf); /* closes the gzfd */ + return err; +} + diff --git a/libkmod/libkmod-file.c b/libkmod/libkmod-file.c index 29e89ca..140e9ca 100644 --- a/libkmod/libkmod-file.c +++ b/libkmod/libkmod-file.c @@ -29,9 +29,6 @@ #ifdef ENABLE_ZSTD #include #endif -#ifdef ENABLE_ZLIB -#include -#endif #include @@ -175,74 +172,6 @@ static int load_zstd(struct kmod_file *file) static const char magic_zstd[] = {0x28, 0xB5, 0x2F, 0xFD}; static const char magic_xz[] = {0xfd, '7', 'z', 'X', 'Z', 0}; - -#ifdef ENABLE_ZLIB -#define READ_STEP (4 * 1024 * 1024) -static int load_zlib(struct kmod_file *file) -{ - int err = 0; - off_t did = 0, total = 0; - _cleanup_free_ unsigned char *p = NULL; - gzFile gzf; - int gzfd; - - errno = 0; - gzfd = fcntl(file->fd, F_DUPFD_CLOEXEC, 3); - if (gzfd < 0) - return -errno; - - gzf = gzdopen(gzfd, "rb"); /* takes ownership of the fd */ - if (gzf == NULL) { - close(gzfd); - return -errno; - } - - for (;;) { - int r; - - if (did == total) { - void *tmp = realloc(p, total + READ_STEP); - if (tmp == NULL) { - err = -errno; - goto error; - } - total += READ_STEP; - p = tmp; - } - - r = gzread(gzf, p + did, total - did); - if (r == 0) - break; - else if (r < 0) { - int gzerr; - const char *gz_errmsg = gzerror(gzf, &gzerr); - - ERR(file->ctx, "gzip: %s\n", gz_errmsg); - - /* gzip might not set errno here */ - err = gzerr == Z_ERRNO ? -errno : -EINVAL; - goto error; - } - did += r; - } - - file->memory = p; - file->size = did; - p = NULL; - gzclose(gzf); - return 0; - -error: - gzclose(gzf); /* closes the gzfd */ - return err; -} -#else -static int load_zlib(struct kmod_file *file) -{ - return -ENOSYS; -} -#endif - static const char magic_zlib[] = {0x1f, 0x8b}; static int load_reg(struct kmod_file *file) @@ -271,7 +200,7 @@ static const struct comp_type { } comp_types[] = { {sizeof(magic_zstd), KMOD_FILE_COMPRESSION_ZSTD, magic_zstd, load_zstd}, {sizeof(magic_xz), KMOD_FILE_COMPRESSION_XZ, magic_xz, kmod_file_load_xz}, - {sizeof(magic_zlib), KMOD_FILE_COMPRESSION_ZLIB, magic_zlib, load_zlib}, + {sizeof(magic_zlib), KMOD_FILE_COMPRESSION_ZLIB, magic_zlib, kmod_file_load_zlib}, {0, KMOD_FILE_COMPRESSION_NONE, NULL, load_reg} }; diff --git a/libkmod/libkmod-internal-file.h b/libkmod/libkmod-internal-file.h index 1d74aed..ca9f868 100644 --- a/libkmod/libkmod-internal-file.h +++ b/libkmod/libkmod-internal-file.h @@ -25,3 +25,10 @@ int kmod_file_load_xz(struct kmod_file *file); #else static inline int kmod_file_load_xz(struct kmod_file *file) { return -ENOSYS; } #endif + +#ifdef ENABLE_ZLIB +int kmod_file_load_zlib(struct kmod_file *file); +#else +static inline int kmod_file_load_zlib(struct kmod_file *file) { return -ENOSYS; } +#endif +