/tests/libpakfire/jail
/tests/libpakfire/key
/tests/libpakfire/log_buffer
+/tests/libpakfire/log_file
/tests/libpakfire/log_stream
/tests/libpakfire/main
/tests/libpakfire/makefile
src/pakfire/linter-file.h \
src/pakfire/log_buffer.c \
src/pakfire/log_buffer.h \
+ src/pakfire/log_file.c \
+ src/pakfire/log_file.h \
src/pakfire/log_stream.c \
src/pakfire/log_stream.h \
src/pakfire/logging.c \
tests/libpakfire/jail \
tests/libpakfire/key \
tests/libpakfire/log_buffer \
+ tests/libpakfire/log_file \
tests/libpakfire/log_stream \
tests/libpakfire/makefile \
tests/libpakfire/os \
tests_libpakfire_log_buffer_LDADD = \
$(TESTSUITE_LDADD)
+tests_libpakfire_log_file_SOURCES = \
+ tests/libpakfire/log_file.c
+
+tests_libpakfire_log_file_CPPFLAGS = \
+ $(TESTSUITE_CPPFLAGS)
+
+tests_libpakfire_log_file_CFLAGS = \
+ $(TESTSUITE_CFLAGS)
+
+tests_libpakfire_log_file_LDFLAGS = \
+ $(TESTSUITE_LDFLAGS)
+
+tests_libpakfire_log_file_LDADD = \
+ $(TESTSUITE_LDADD)
+
tests_libpakfire_log_stream_SOURCES = \
tests/libpakfire/log_stream.c
--- /dev/null
+/*#############################################################################
+# #
+# Pakfire - The IPFire package management system #
+# Copyright (C) 2025 Pakfire development team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+#############################################################################*/
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include <pakfire/compress.h>
+#include <pakfire/ctx.h>
+#include <pakfire/log_file.h>
+#include <pakfire/string.h>
+#include <pakfire/util.h>
+
+struct pakfire_log_file {
+ struct pakfire_ctx* ctx;
+ int nrefs;
+
+ // Flags
+ int flags;
+
+ // Path
+ char path[PATH_MAX];
+
+ // File Handle
+ FILE* f;
+};
+
+static void pakfire_log_file_free(struct pakfire_log_file* self) {
+ // Close the log file
+ pakfire_log_file_close(self);
+
+ // Free all held resources
+ if (*self->path)
+ unlink(self->path);
+ if (self->ctx)
+ pakfire_ctx_unref(self->ctx);
+ free(self);
+}
+
+int pakfire_log_file_create(struct pakfire_log_file** file, struct pakfire_ctx* ctx, int flags) {
+ struct pakfire_log_file* self = NULL;
+ int r;
+
+ // Allocate some memory
+ self = calloc(1, sizeof(*self));
+ if (!self)
+ return -errno;
+
+ // Store the context
+ self->ctx = pakfire_ctx_ref(ctx);
+
+ // Initialize the reference counter
+ self->nrefs = 1;
+
+ // Store flags
+ self->flags = flags;
+
+ // Make some path
+ r = pakfire_string_set(self->path, PAKFIRE_TMP_DIR "/pakfire-log.XXXXXX");
+ if (r < 0)
+ goto ERROR;
+
+ // Create a new temporary file
+ self->f = pakfire_mktemp(self->path, 0600);
+ if (!self->f) {
+ r = -errno;
+ goto ERROR;
+ }
+
+ // If we want to write the log file compressed, we replace the file handle
+ if (self->flags & PAKFIRE_LOG_FILE_COMPRESS) {
+ self->f = pakfire_zstdfopen(self->f, "w");
+ if (!self->f) {
+ ERROR(self->ctx, "Could not enable compression for log file: %m\n");
+ r = -errno;
+ goto ERROR;
+ }
+ }
+
+ DEBUG(self->ctx, "Created log file %s\n", self->path);
+
+ // Return the pointer
+ *file = self;
+ return 0;
+
+ERROR:
+ pakfire_log_file_free(self);
+
+ return r;
+}
+
+struct pakfire_log_file* pakfire_log_file_ref(struct pakfire_log_file* self) {
+ self->nrefs++;
+
+ return self;
+}
+
+struct pakfire_log_file* pakfire_log_file_unref(struct pakfire_log_file* self) {
+ if (--self->nrefs > 0)
+ return self;
+
+ pakfire_log_file_free(self);
+ return NULL;
+}
+
+const char* pakfire_log_file_path(struct pakfire_log_file* self) {
+ return self->path;
+}
+
+int pakfire_log_file_close(struct pakfire_log_file* self) {
+ int r;
+
+ if (self->f) {
+ r = fclose(self->f);
+ if (r < 0) {
+ ERROR(self->ctx, "Could not close log file: %s\n", strerror(-r));
+ return r;
+ }
+
+ DEBUG(self->ctx, "Closed log file %s\n", self->path);
+
+ self->f = NULL;
+ }
+
+ return 0;
+}
+
+int pakfire_log_file_write(struct pakfire_log_file* self, const char* buffer, ssize_t length) {
+ int r;
+
+ // Check inputs
+ if (unlikely(!buffer))
+ return -EINVAL;
+
+ // Check if the file is still open
+ if (unlikely(!self->f))
+ return -EBADF;
+
+ // Automatically determine the length
+ if (unlikely(length < 0))
+ length = strlen(buffer);
+
+ // Write the buffer to the file
+ r = fwrite(buffer, 1, length, self->f);
+ if (unlikely(r < length)) {
+ ERROR(self->ctx, "Could not write to log file: %m\n");
+ return -errno;
+ }
+
+ return 0;
+}
--- /dev/null
+/*#############################################################################
+# #
+# Pakfire - The IPFire package management system #
+# Copyright (C) 2025 Pakfire development team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+#############################################################################*/
+
+#ifndef PAKFIRE_LOG_FILE_H
+#define PAKFIRE_LOG_FILE_H
+
+#include <pakfire/ctx.h>
+
+/*
+ Writes the log into a compressed file
+*/
+
+struct pakfire_log_file;
+
+enum pakfire_log_file_flags {
+ PAKFIRE_LOG_FILE_COMPRESS = (1 << 0),
+};
+
+int pakfire_log_file_create(struct pakfire_log_file** file,
+ struct pakfire_ctx* ctx, int flags);
+struct pakfire_log_file* pakfire_log_file_ref(struct pakfire_log_file* self);
+struct pakfire_log_file* pakfire_log_file_unref(struct pakfire_log_file* self);
+
+const char* pakfire_log_file_path(struct pakfire_log_file* self);
+
+int pakfire_log_file_close(struct pakfire_log_file* self);
+
+int pakfire_log_file_write(struct pakfire_log_file* self, const char* buffer, ssize_t length);
+
+#endif /* PAKFIRE_LOG_FILE_H */
--- /dev/null
+/*#############################################################################
+# #
+# Pakfire - The IPFire package management system #
+# Copyright (C) 2025 Pakfire development team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+#############################################################################*/
+
+#include <pakfire/log_file.h>
+#include <pakfire/path.h>
+#include <pakfire/string.h>
+#include <pakfire/util.h>
+
+#include "../testsuite.h"
+
+static int __test_simple(const struct test* t, int flags) {
+ struct pakfire_log_file* file = NULL;
+ char path[PATH_MAX] = "";
+ int r = EXIT_FAILURE;
+
+ // Create a new log file
+ ASSERT_SUCCESS(pakfire_log_file_create(&file, t->ctx, flags));
+
+ // Store a copy of the path
+ ASSERT_SUCCESS(pakfire_string_set(path, pakfire_log_file_path(file)));
+
+ // Write something to the file
+ for (int i = 0; i < 10; i++)
+ ASSERT_SUCCESS(pakfire_log_file_write(file, "BUFFER DATA\n", -1));
+
+ // Everything passed
+ r = EXIT_SUCCESS;
+
+FAIL:
+ if (file)
+ pakfire_log_file_unref(file);
+
+ // Check if the log file was removed
+ if (*path) {
+ if (pakfire_path_exists(path)) {
+ LOG("Log file was not cleaned up\n");
+ return 1;
+ }
+ }
+
+ return r;
+}
+
+static int test_uncompressed(const struct test* t) {
+ return __test_simple(t, 0);
+}
+
+static int test_compressed(const struct test* t) {
+ return __test_simple(t, PAKFIRE_LOG_FILE_COMPRESS);
+}
+
+int main(int argc, const char* argv[]) {
+ testsuite_add_test(test_uncompressed, 0);
+ testsuite_add_test(test_compressed, 0);
+
+ return testsuite_run(argc, argv);
+}