From: Michael Tremer Date: Mon, 24 Mar 2025 18:46:34 +0000 (+0000) Subject: jail: Refactor streaming data into the jail X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ac335a5b1a6c9d6ebcfcbda60549451478f52660;p=pakfire.git jail: Refactor streaming data into the jail Signed-off-by: Michael Tremer --- diff --git a/src/pakfire/jail.c b/src/pakfire/jail.c index 2e66363d..3692929e 100644 --- a/src/pakfire/jail.c +++ b/src/pakfire/jail.c @@ -49,6 +49,7 @@ #include #include +#include #include #include #include @@ -152,6 +153,10 @@ struct pakfire_jail_exec { #endif /* ENABLE_DEBUG */ } streams; + // Standard Input Buffer + struct pakfire_buffer stdin; + int stdin_done; + // Timeout sd_event_source* timeout; @@ -401,6 +406,7 @@ static int pakfire_jail_stdin(sd_event_source* source, int fd, unsigned int even struct pakfire_jail_exec* exec = data; struct pakfire_jail* self = exec->jail; ssize_t bytes_written = 0; + ssize_t bytes_read = 0; // Fail if no callback is set if (unlikely(!exec->callbacks.input)) { @@ -408,22 +414,46 @@ static int pakfire_jail_stdin(sd_event_source* source, int fd, unsigned int even goto CLOSE; } - // Call the callback - bytes_written = exec->callbacks.input(self->ctx, fd, exec->callbacks.input_data); - if (bytes_written < 0) { - ERROR(self->ctx, "The input callback failed: %s\n", strerror(-bytes_written)); - return bytes_written; + for (;;) { + if (!exec->stdin_done) { + bytes_read = pakfire_buffer_fill(&exec->stdin, self->ctx, + exec->callbacks.input, exec->callbacks.input_data); + if (bytes_read < 0) { + ERROR(self->ctx, "The input callback failed: %s\n", strerror(-bytes_read)); + return bytes_read; + } - // Close the file descriptor if we are done reading - } else if (bytes_written == 0) { - goto CLOSE; + // If we could not read any more from the callback, we are done + if (bytes_read == 0) + exec->stdin_done = 1; + } + + // Write buffered data to the pipe + bytes_written = pakfire_buffer_write(&exec->stdin, fd); + if (bytes_written < 0) { + switch (-bytes_written) { + case EAGAIN: + return 0; + + default: + ERROR(self->ctx, "Failed to write to standard input: %s\n", strerror(-bytes_written)); + return bytes_written; + } + } + + // Close if we have read all input data and flushed the entire buffer + if (exec->stdin_done && pakfire_buffer_is_empty(&exec->stdin)) + goto CLOSE; } return 0; CLOSE: + // Close the standard input file descriptors pakfire_jail_close_pipe(self, exec->pipes.stdin); + DEBUG(self->ctx, "Closed standard input\n"); + return 0; } @@ -1642,7 +1672,7 @@ static int pakfire_jail_child(struct pakfire_jail* jail, struct pakfire_jail_exe // Run a command in the jail static int __pakfire_jail_exec(struct pakfire_jail* jail, pakfire_jail_callback callback, void* data, int flags, - pakfire_pty_stdin_callback stdin_callback, void* stdin_data, + pakfire_jail_input_callback input_callback, void* input_data, pakfire_pty_stdout_callback stdout_callback, void* stdout_data, char** output, size_t* output_length) { struct pakfire_log_stream* stdout = NULL; @@ -1696,6 +1726,9 @@ static int __pakfire_jail_exec(struct pakfire_jail* jail, goto ERROR; } + // Set the size for the input buffer + pakfire_buffer_set_max_length(&ctx.stdin, 4096); + // Are we running in interactive mode? if (pakfire_jail_exec_has_flag(&ctx, PAKFIRE_JAIL_INTERACTIVE)) { // Setup the PTY @@ -1720,6 +1753,10 @@ static int __pakfire_jail_exec(struct pakfire_jail* jail, r = pakfire_jail_setup_pipe(jail, &ctx.pipes.stdin, 0); if (r < 0) goto ERROR; + + // Store the callback + ctx.callbacks.input = input_callback; + ctx.callbacks.input_data = input_data; } // Create a pipe for standard output @@ -1785,12 +1822,6 @@ static int __pakfire_jail_exec(struct pakfire_jail* jail, goto ERROR; } -#if 0 - // Configure the callbacks - if (stdin_callback) - pakfire_pty_set_stdin_callback(ctx.pty, stdin_callback, stdin_data); -#endif - // Setup pipes for logging // INFO r = pakfire_log_stream_create(&ctx.streams.INFO, jail->ctx, pakfire_jail_INFO, jail); @@ -1977,7 +2008,7 @@ int pakfire_jail_exec_capture_output(struct pakfire_jail* jail, int pakfire_jail_communicate( struct pakfire_jail* jail, const char* argv[], struct pakfire_env* env, int flags, - pakfire_pty_stdin_callback stdin_callback, void* stdin_data, + pakfire_jail_input_callback input_callback, void* input_data, pakfire_pty_stdout_callback stdout_callback, void* stdout_data) { struct pakfire_jail_command command = { .jail = jail, @@ -1986,12 +2017,12 @@ int pakfire_jail_communicate( }; return __pakfire_jail_exec(jail, pakfire_jail_launch_command, &command, flags, - stdin_callback, stdin_data, stdout_callback, stdout_data, NULL, NULL); + input_callback, input_data, stdout_callback, stdout_data, NULL, NULL); } int pakfire_jail_exec_script(struct pakfire_jail* jail, const char* script, const size_t size, const char* args[], struct pakfire_env* env, - pakfire_pty_stdin_callback stdin_callback, void* stdin_data, + pakfire_jail_input_callback input_callback, void* input_data, pakfire_pty_stdout_callback stdout_callback, void* stdout_data) { char path[PATH_MAX]; const char** argv = NULL; @@ -2052,7 +2083,7 @@ int pakfire_jail_exec_script(struct pakfire_jail* jail, // Run the script r = pakfire_jail_communicate(jail, argv, env, 0, - stdin_callback, stdin_data, stdout_callback, stdout_data); + input_callback, input_data, stdout_callback, stdout_data); ERROR: if (argv) diff --git a/src/pakfire/jail.h b/src/pakfire/jail.h index bfb5c490..16829960 100644 --- a/src/pakfire/jail.h +++ b/src/pakfire/jail.h @@ -21,6 +21,7 @@ #ifndef PAKFIRE_JAIL_H #define PAKFIRE_JAIL_H +#include #include #include #include @@ -28,6 +29,9 @@ struct pakfire_jail; +// Input callback +typedef pakfire_buffer_input_callback pakfire_jail_input_callback; + int pakfire_jail_create(struct pakfire_jail** jail, struct pakfire* pakfire); struct pakfire_jail* pakfire_jail_ref(struct pakfire_jail* jail); @@ -66,7 +70,7 @@ int pakfire_jail_set_cgroup(struct pakfire_jail* jail, struct pakfire_cgroup* cg int pakfire_jail_communicate( struct pakfire_jail* jail, const char* argv[], struct pakfire_env* env, int flags, - pakfire_pty_stdin_callback stdin_callback, void* stdin_data, + pakfire_jail_input_callback input_callback, void* input_data, pakfire_log_stream_callback stdout_callback, void* stdout_data); // Convenience functions @@ -77,7 +81,7 @@ int pakfire_jail_run_script(struct pakfire* pakfire, int pakfire_jail_exec_script(struct pakfire_jail* jail, const char* script, const size_t size, const char* args[], struct pakfire_env* env, - pakfire_pty_stdin_callback stdin_callback, void* stdin_data, + pakfire_jail_input_callback input_callback, void* input_data, pakfire_pty_stdout_callback stdout_callback, void* stdout_data); int pakfire_jail_shell(struct pakfire_jail* jail, struct pakfire_env* env);