From: Michael Tremer Date: Thu, 30 Jan 2025 08:17:22 +0000 (+0000) Subject: compress: Add transparent gzip compression X-Git-Tag: 0.9.30~289 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e24c79ffb5211c074177f310f70180ba39b0f37a;p=pakfire.git compress: Add transparent gzip compression Signed-off-by: Michael Tremer --- diff --git a/Jenkinsfile b/Jenkinsfile index 224eb31c1..d69b15978 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -568,7 +568,8 @@ def installBuildDepsRedHat(distro, compier) { python3-devel \ sqlite-devel \ systemd-devel \ - xz-devel + xz-devel \ + zlib-devel """ } @@ -604,7 +605,8 @@ def installBuildDepsArchLinux(distro, compiler) { systemd \ util-linux-libs \ xz \ - zstd + zstd \ + zlib """ } @@ -648,7 +650,8 @@ def installBuildDepsDebian(distro, compiler, arch) { libsqlite3-dev \ libsystemd-dev \ libzstd-dev \ - uuid-dev + uuid-dev \ + libz-dev """ } diff --git a/Makefile.am b/Makefile.am index e28b66cc8..4f2420287 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1253,6 +1253,7 @@ EXTRA_DIST += \ tests/data/beep.nm \ tests/data/kernel.nm \ \ + tests/data/compress/data.gz \ tests/data/compress/data.xz \ tests/data/compress/data.zst \ \ diff --git a/debian/control b/debian/control index 2754baaed..34db9e675 100644 --- a/debian/control +++ b/debian/control @@ -35,6 +35,7 @@ Build-Depends: libzstd-dev, pkg-config, uuid-dev, + libz-dev Standards-Version: 4.6.2 Homepage: https://pakfire.ipfire.org Vcs-Browser: https://git.ipfire.org/?p=pakfire.git;a=summary diff --git a/src/pakfire/compress.c b/src/pakfire/compress.c index 287b2ba10..2a3ae4dde 100644 --- a/src/pakfire/compress.c +++ b/src/pakfire/compress.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -121,6 +122,64 @@ FILE* pakfire_xfopen(FILE* f, const char* mode) { return f; } +/* + gzip +*/ + +static ssize_t gz_read(void* cookie, char* buffer, size_t size) { + return gzread((gzFile)cookie, buffer, size); +} + +static ssize_t gz_write(void* cookie, const char* buffer, size_t size) { + return gzwrite((gzFile)cookie, buffer, size); +} + +static int gz_close(void* cookie) { + return gzclose((gzFile)cookie); +} + +FILE* pakfire_gzfopen(FILE* f, const char* mode) { + gzFile cookie = NULL; + int fd = -EBADF; + + // Check for a valid file descriptor + if (!f) { + errno = EBADF; + return NULL; + } + + // Fetch the file descriptor + fd = fileno(f); + if (fd < 0) { + errno = EBADF; + return NULL; + } + + // Duplicate the file descriptor to pass it to gzip + fd = dup(fd); + if (fd < 0) + return NULL; + + // Close the original file handle + fclose(f); + + // Open the stream + cookie = gzdopen(fd, mode); + if (!cookie) + return NULL; + + // Increase the buffer size for faster reading + gzbuffer(cookie, 128 * 1024); + + static cookie_io_functions_t gz_functions = { + .read = gz_read, + .write = gz_write, + .close = gz_close, + }; + + return fopencookie(cookie, mode, gz_functions); +} + struct xz_cookie { FILE* f; char mode; diff --git a/src/pakfire/compress.h b/src/pakfire/compress.h index 88394e214..f275aebb4 100644 --- a/src/pakfire/compress.h +++ b/src/pakfire/compress.h @@ -30,6 +30,9 @@ // Automatically detect FILE* pakfire_xfopen(FILE* f, const char* mode); +// gzip +FILE* pakfire_gzfopen(FILE* f, const char* mode); + // XZ FILE* pakfire_xzfopen(FILE* f, const char* mode); diff --git a/tests/data/compress/data.gz b/tests/data/compress/data.gz new file mode 100644 index 000000000..1fc309374 Binary files /dev/null and b/tests/data/compress/data.gz differ diff --git a/tests/libpakfire/compress.c b/tests/libpakfire/compress.c index 557f743a0..3673f7d6c 100644 --- a/tests/libpakfire/compress.c +++ b/tests/libpakfire/compress.c @@ -92,6 +92,14 @@ FAIL: return r; } +static int test_gzfopen_read(const struct test* t) { + return read_test(t, pakfire_gzfopen, "data/compress/data.gz"); +} + +static int test_gzfopen_write(const struct test* t) { + return write_test(t, pakfire_gzfopen); +} + static int test_xzfopen_read(const struct test* t) { return read_test(t, pakfire_xzfopen, "data/compress/data.xz"); } @@ -119,6 +127,10 @@ FAIL: } int main(int argc, const char* argv[]) { + // Gzip + testsuite_add_test(test_gzfopen_read, 0); + testsuite_add_test(test_gzfopen_write, 0); + // XZ testsuite_add_test(test_xzfopen_read, 0); testsuite_add_test(test_xzfopen_write, 0);