]> git.ipfire.org Git - people/ms/pakfire.git/commitdiff
jail: Replace communication callbacks by setting callbacks
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 19 Dec 2023 18:50:45 +0000 (18:50 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 19 Dec 2023 18:50:45 +0000 (18:50 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/include/pakfire/jail.h
src/libpakfire/jail.c
tests/libpakfire/jail.c

index e320d6f790aef554e7ff24abb38e65ddd944c889..0d10c16334861d513a6736bb4925795d5bc7ae31 100644 (file)
@@ -83,8 +83,8 @@ int pakfire_jail_exec(
 #include <pakfire/cgroup.h>
 
 // Capture
-int pakfire_jail_capture_stdout(struct pakfire* pakfire, void* data,
-       int priority, const char* line, size_t length);
+int pakfire_jail_capture_stdout(struct pakfire_jail* jail,
+       void* data, const char* line, size_t length);
 
 // Resource limits
 int pakfire_jail_set_cgroup(struct pakfire_jail* jail, struct pakfire_cgroup* cgroup);
index 9433f925158cfb6cbbb3fda1a5bfcf13dfe88cb7..c5a663de5dceeab2b97b826d7fdf80420c20a3d9 100644 (file)
@@ -85,6 +85,7 @@ static const struct environ {
 struct pakfire_log_buffer {
        char data[BUFFER_SIZE];
        size_t used;
+       int priority;
 };
 
 enum pakfire_jail_pty_io {
@@ -181,13 +182,6 @@ struct pakfire_jail_exec {
 #endif /* ENABLE_DEBUG */
        } pipes;
 
-       // Communicate
-       struct pakfire_jail_communicate {
-               pakfire_jail_communicate_in  in;
-               pakfire_jail_communicate_out out;
-               void* data;
-       } communicate;
-
        // Log buffers
        struct pakfire_jail_buffers {
                // Logging
@@ -251,21 +245,6 @@ static void pakfire_jail_free(struct pakfire_jail* jail) {
        free(jail);
 }
 
-/*
-       Passes any log messages on to the default pakfire log callback
-*/
-static int pakfire_jail_default_log_callback(struct pakfire* pakfire, void* data,
-               int priority, const char* line, size_t length) {
-       struct pakfire_ctx* ctx = pakfire_ctx(pakfire);
-
-       if (pakfire_ctx_get_log_level(ctx) >= priority)
-               pakfire_ctx_log(ctx, priority, NULL, 0, NULL, "%.*s", (int)length, line);
-
-       pakfire_ctx_unref(ctx);
-
-       return 0;
-}
-
 static const char* pakfire_jail_uuid(struct pakfire_jail* jail) {
        if (!*jail->__uuid)
                uuid_unparse_lower(jail->uuid, jail->__uuid);
@@ -644,7 +623,7 @@ static int pakfire_jail_fill_buffer(struct pakfire_jail* jail, int fd, struct pa
 }
 
 static int pakfire_jail_drain_buffer_with_callback(struct pakfire_jail* jail,
-               struct pakfire_log_buffer* buffer, int priority, pakfire_jail_communicate_out callback, void* data) {
+               struct pakfire_log_buffer* buffer, pakfire_jail_stdout_callback callback, void* data) {
        const char* eol = NULL;
        int r;
 
@@ -670,9 +649,9 @@ static int pakfire_jail_drain_buffer_with_callback(struct pakfire_jail* jail,
                const size_t length = eol - buffer->data + 1;
 
                // Call the callback
-               r = callback(jail->pakfire, data, priority, buffer->data, length);
+               r = callback(jail, data, buffer->data, length);
                if (r) {
-                       CTX_ERROR(jail->ctx, "The logging callback returned an error: %d\n", r);
+                       CTX_ERROR(jail->ctx, "The standard output callback returned an error: %d\n", r);
                        return r;
                }
 
@@ -719,14 +698,26 @@ static int pakfire_jail_drain_buffer(struct pakfire_jail* jail, int fd, struct p
        return 0;
 }
 
+/*
+       Passes any log messages on to the default pakfire log callback
+*/
+static int pakfire_jail_log(struct pakfire_jail* jail,
+               void* data, const char* line, size_t length) {
+       int* priority = data;
+
+       if (pakfire_ctx_get_log_level(jail->ctx) >= *priority)
+               pakfire_ctx_log(jail->ctx, *priority, NULL, 0, NULL, "%.*s", (int)length, line);
+
+       return 0;
+}
+
 /*
        This function reads as much data as it can from the file descriptor.
        If it finds a whole line in it, it will send it to the logger and repeat the process.
        If not newline character is found, it will try to read more data until it finds one.
 */
 static int pakfire_jail_handle_log(struct pakfire_jail* jail, struct pakfire_jail_exec* ctx,
-               int priority, int fd, struct pakfire_log_buffer* buffer,
-               pakfire_jail_communicate_out callback, void* data) {
+               int fd, struct pakfire_log_buffer* buffer, pakfire_jail_stdout_callback callback, void* data) {
        int r;
 
        // Fill up buffer from fd
@@ -735,7 +726,7 @@ static int pakfire_jail_handle_log(struct pakfire_jail* jail, struct pakfire_jai
                return r;
 
        // Drain the buffer
-       r = pakfire_jail_drain_buffer_with_callback(jail, buffer, priority, callback, data);
+       r = pakfire_jail_drain_buffer_with_callback(jail, buffer, callback, data);
        if (r)
                return r;
 
@@ -754,7 +745,7 @@ static int pakfire_jail_stream_stdin(struct pakfire_jail* jail,
        CTX_DEBUG(jail->ctx, "Streaming standard input...\n");
 
        // Calling the callback
-       r = ctx->communicate.in(jail->pakfire, ctx->communicate.data, fd);
+       r = jail->callbacks.stdin.callback(jail, jail->callbacks.stdin.data, fd);
 
        switch (r) {
                case EOF:
@@ -1078,6 +1069,13 @@ static int pakfire_jail_setup_pty_forwarding(struct pakfire_jail* jail,
        return 0;
 }
 
+static int pakfire_jail_command_output(struct pakfire_jail* jail, void* data,
+               const char* line, const size_t length) {
+       CTX_INFO(jail->ctx, "Command Output: %.*s", (int)length, line);
+
+       return 0;
+}
+
 static int pakfire_jail_forward_pty(struct pakfire_jail* jail, struct pakfire_jail_exec* ctx) {
        int r;
 
@@ -1100,7 +1098,7 @@ static int pakfire_jail_forward_pty(struct pakfire_jail* jail, struct pakfire_ja
 
                // Write to the master
                if (ctx->pty.master.io & PAKFIRE_JAIL_PTY_READY_TO_WRITE) {
-                       if (ctx->communicate.in) {
+                       if (jail->callbacks.stdin.callback) {
                                r = pakfire_jail_stream_stdin(jail, ctx, ctx->pty.master.fd);
                                if (r)
                                        return r;
@@ -1136,9 +1134,9 @@ static int pakfire_jail_forward_pty(struct pakfire_jail* jail, struct pakfire_ja
                // Write to standard output
                if (ctx->pty.stdout.io & PAKFIRE_JAIL_PTY_READY_TO_WRITE) {
                        // If we have a callback, we will send any output to the callback
-                       if (ctx->communicate.out) {
+                       if (jail->callbacks.stdout.callback) {
                                r = pakfire_jail_drain_buffer_with_callback(jail, &ctx->pty.stdout.buffer,
-                                       LOG_INFO, ctx->communicate.out, ctx->communicate.data);
+                                       jail->callbacks.stdout.callback, jail->callbacks.stdout.data);
                                if (r)
                                        return r;
 
@@ -1153,7 +1151,7 @@ static int pakfire_jail_forward_pty(struct pakfire_jail* jail, struct pakfire_ja
                        // Otherwise send the output to the default logger
                        } else {
                                r = pakfire_jail_drain_buffer_with_callback(jail, &ctx->pty.stdout.buffer,
-                                       LOG_INFO, pakfire_jail_default_log_callback, NULL);
+                                       pakfire_jail_command_output, NULL);
                                if (r)
                                        return r;
                        }
@@ -1354,8 +1352,8 @@ static int pakfire_jail_wait(struct pakfire_jail* jail, struct pakfire_jail_exec
                        // Handle log INFO messages
                        } else if (log_INFO == fd) {
                                if (e & EPOLLIN) {
-                                       r = pakfire_jail_handle_log(jail, ctx, LOG_INFO, fd,
-                                               &ctx->buffers.log_INFO, pakfire_jail_default_log_callback, NULL);
+                                       r = pakfire_jail_handle_log(jail, ctx, fd, &ctx->buffers.log_INFO,
+                                               pakfire_jail_log, &ctx->buffers.log_INFO.priority);
                                        if (r)
                                                goto ERROR;
                                }
@@ -1363,8 +1361,8 @@ static int pakfire_jail_wait(struct pakfire_jail* jail, struct pakfire_jail_exec
                        // Handle log ERROR messages
                        } else if (log_ERROR == fd) {
                                if (e & EPOLLIN) {
-                                       r = pakfire_jail_handle_log(jail, ctx, LOG_ERR, fd,
-                                               &ctx->buffers.log_ERROR, pakfire_jail_default_log_callback, NULL);
+                                       r = pakfire_jail_handle_log(jail, ctx, fd, &ctx->buffers.log_ERROR,
+                                               pakfire_jail_log, &ctx->buffers.log_ERROR.priority);
                                        if (r)
                                                goto ERROR;
                                }
@@ -1373,8 +1371,8 @@ static int pakfire_jail_wait(struct pakfire_jail* jail, struct pakfire_jail_exec
                        // Handle log DEBUG messages
                        } else if (log_DEBUG == fd) {
                                if (e & EPOLLIN) {
-                                       r = pakfire_jail_handle_log(jail, ctx, LOG_DEBUG, fd,
-                                               &ctx->buffers.log_DEBUG, pakfire_jail_default_log_callback, NULL);
+                                       r = pakfire_jail_handle_log(jail, ctx, fd, &ctx->buffers.log_DEBUG,
+                                               pakfire_jail_log, &ctx->buffers.log_DEBUG.priority);
                                        if (r)
                                                goto ERROR;
                                }
@@ -1413,22 +1411,17 @@ ERROR:
        return r;
 }
 
-int pakfire_jail_capture_stdout(struct pakfire* pakfire, void* data,
-               int priority, const char* line, size_t length) {
+int pakfire_jail_capture_stdout(struct pakfire_jail* jail, void* data,
+               const char* line, size_t length) {
        char** output = (char**)data;
        int r;
 
        // Append everything from stdout to a buffer
-       if (output && priority == LOG_INFO) {
-               r = asprintf(output, "%s%.*s", (output && *output) ? *output : "", (int)length, line);
-               if (r < 0)
-                       return -errno;
-
-               return 0;
-       }
+       r = asprintf(output, "%s%.*s", (output && *output) ? *output : "", (int)length, line);
+       if (r < 0)
+               return -errno;
 
-       // Send everything else to the default logger
-       return pakfire_jail_default_log_callback(pakfire, NULL, priority, line, length);
+       return 0;
 }
 
 // Capabilities
@@ -2333,10 +2326,20 @@ static int __pakfire_jail_exec(struct pakfire_jail* jail, const char* argv[],
 #endif /* ENABLE_DEBUG */
                },
 
-               .communicate = {
-                       .in   = communicate_in,
-                       .out  = communicate_out,
-                       .data = data,
+               .buffers = {
+                       .log_INFO = {
+                               .priority = LOG_INFO,
+                       },
+
+                       .log_ERROR = {
+                               .priority = LOG_ERR,
+                       },
+
+#ifdef ENABLE_DEBUG
+                       .log_DEBUG = {
+                               .priority = LOG_DEBUG,
+                       },
+#endif /* ENABLE_DEBUG */
                },
 
                .pidfd = -1,
@@ -2625,8 +2628,11 @@ int pakfire_jail_run(struct pakfire* pakfire, const char* argv[], int flags, cha
        if (r)
                goto ERROR;
 
+       // Set the callback that captures the output
+       pakfire_jail_set_stdout_callback(jail, pakfire_jail_capture_stdout, output);
+
        // Execute the command
-       r = pakfire_jail_exec(jail, argv, NULL, pakfire_jail_capture_stdout, output, 0);
+       r = pakfire_jail_exec(jail, argv, NULL, NULL, NULL, 0);
 
 ERROR:
        if (jail)
index d49795a94680604107d074265390b3f2ca5d5095..fafbf565862f064623a8969ccbf0195dd5fd6069 100644 (file)
@@ -199,9 +199,11 @@ static int test_nice(const struct test* t) {
        // Set something sane
        ASSERT_SUCCESS(pakfire_jail_nice(jail, 5));
 
+       // Capture the output of the next execution
+       pakfire_jail_set_stdout_callback(jail, pakfire_jail_capture_stdout, &output);
+
        // Check if the nice level has been set
-       ASSERT_SUCCESS(pakfire_jail_exec(jail, argv,
-               NULL, pakfire_jail_capture_stdout, &output, 0));
+       ASSERT_SUCCESS(pakfire_jail_exec(jail, argv, NULL, NULL, NULL, 0));
        ASSERT_STRING_EQUALS(output, "5\n");
 
        // Success
@@ -343,7 +345,7 @@ FAIL:
        return r;
 }
 
-static int callback_stdin(struct pakfire* pakfire, void* data, int fd) {
+static int callback_stdin(struct pakfire_jail* pakfire, void* data, int fd) {
        int* lines = (int*)data;
        int r;
 
@@ -381,8 +383,10 @@ static int test_communicate(const struct test* t) {
        // Create a new jail
        ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire));
 
+       pakfire_jail_set_stdin_callback(jail, callback_stdin, &lines);
+
        // Check if the mount actually works
-       ASSERT_SUCCESS(pakfire_jail_exec(jail, argv, callback_stdin, NULL, &lines, 0));
+       ASSERT_SUCCESS(pakfire_jail_exec(jail, argv, NULL, NULL, NULL, 0));
 
        // Success
        r = EXIT_SUCCESS;