#include <pakfire/arch.h>
#include <pakfire/cgroup.h>
#include <pakfire/jail.h>
+#include <pakfire/log_stream.h>
#include <pakfire/logging.h>
#include <pakfire/mount.h>
#include <pakfire/pakfire.h>
// Log pipes
struct pakfire_jail_pipes {
// Logging
- int log_INFO[2];
- int log_ERROR[2];
+ struct pakfire_log_stream* INFO;
+ struct pakfire_log_stream* ERROR;
#ifdef ENABLE_DEBUG
- int log_DEBUG[2];
+ struct pakfire_log_stream* DEBUG;
#endif /* ENABLE_DEBUG */
- } pipes;
-
- // Log buffers
- struct pakfire_jail_buffers {
- // Logging
- struct pakfire_log_buffer log_INFO;
- struct pakfire_log_buffer log_ERROR;
-#ifdef ENABLE_DEBUG
- struct pakfire_log_buffer log_DEBUG;
-#endif /* ENABLE_DEBUG */
- } buffers;
+ } log;
struct pakfire_cgroup* cgroup;
struct pakfire_cgroup_stats cgroup_stats;
*/
static void pakfire_jail_log_redirect(void* data, int priority, const char* file,
int line, const char* fn, const char* format, va_list args) {
- struct pakfire_jail_pipes* pipes = (struct pakfire_jail_pipes*)data;
- int fd;
+ struct pakfire_jail_exec* ctx = data;
switch (priority) {
case LOG_INFO:
- fd = pipes->log_INFO[1];
+ pakfire_log_stream_write(ctx->log.INFO, format, args);
break;
case LOG_ERR:
- fd = pipes->log_ERROR[1];
+ pakfire_log_stream_write(ctx->log.ERROR, format, args);
break;
#ifdef ENABLE_DEBUG
case LOG_DEBUG:
- fd = pipes->log_DEBUG[1];
+ pakfire_log_stream_write(ctx->log.DEBUG, format, args);
break;
#endif /* ENABLE_DEBUG */
default:
return;
}
-
- // End if we do not have a file descriptor to write to
- if (fd < 0)
- return;
-
- // Optionally log the function name
- if (fn)
- dprintf(fd, "%s: ", fn);
-
- // Send the log message
- vdprintf(fd, format, args);
}
static int pakfire_jail_fill_buffer(struct pakfire_jail* jail, int fd, struct pakfire_log_buffer* buffer) {
}
/*
- Passes any log messages on to the default pakfire log callback
+ Passes any log messages on to the context logger
*/
-static int pakfire_jail_log(struct pakfire_ctx* ctx, 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);
+static int pakfire_jail_INFO(struct pakfire_log_stream* stream, const char* line, size_t length, void* data) {
+ struct pakfire_jail* jail = data;
+ CTX_INFO(jail->ctx, "%.*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 fd, struct pakfire_log_buffer* buffer, pakfire_jail_stdout_callback callback, void* data) {
- int r;
+static int pakfire_jail_ERROR(struct pakfire_log_stream* stream, const char* line, size_t length, void* data) {
+ struct pakfire_jail* jail = data;
- // Fill up buffer from fd
- r = pakfire_jail_fill_buffer(jail, fd, buffer);
- if (r)
- return r;
+ CTX_ERROR(jail->ctx, "%.*s", (int)length, line);
+ return 0;
+}
- // Drain the buffer
- r = pakfire_jail_drain_buffer_with_callback(jail, buffer, callback, data);
- if (r)
- return r;
+#ifdef ENABLE_DEBUG
+static int pakfire_jail_DEBUG(struct pakfire_log_stream* stream, const char* line, size_t length, void* data) {
+ struct pakfire_jail* jail = data;
+ CTX_DEBUG(jail->ctx, "%.*s", (int)length, line);
return 0;
}
+#endif /* ENABLE_DEBUG */
static int pakfire_jail_stream_stdin(struct pakfire_jail* jail,
struct pakfire_jail_exec* ctx, const int fd) {
return 0;
}
-static int pakfire_jail_setup_pipe(struct pakfire_jail* jail, int (*fds)[2], const int flags) {
- int r = pipe2(*fds, flags);
- if (r < 0) {
- CTX_ERROR(jail->ctx, "Could not setup pipe: %m\n");
- return 1;
- }
-
- return 0;
-}
-
static void pakfire_jail_close_pipe(struct pakfire_jail* jail, int fds[2]) {
for (unsigned int i = 0; i < 2; i++)
if (fds[i] >= 0)
// Timer
const int timerfd = pakfire_jail_create_timer(jail);
- // Logging
- const int log_INFO = pakfire_jail_get_pipe_to_read(jail, &ctx->pipes.log_INFO);
- const int log_ERROR = pakfire_jail_get_pipe_to_read(jail, &ctx->pipes.log_ERROR);
-#ifdef ENABLE_DEBUG
- const int log_DEBUG = pakfire_jail_get_pipe_to_read(jail, &ctx->pipes.log_DEBUG);
-#endif /* ENABLE_DEBUG */
-
// Make a list of all file descriptors we are interested in
const struct pakfire_wait_fds {
const int fd;
// Child Process
{ ctx->pidfd, EPOLLIN },
- // Log Pipes
- { log_INFO, EPOLLIN },
- { log_ERROR, EPOLLIN },
-#ifdef ENABLE_DEBUG
- { log_DEBUG, EPOLLIN },
-#endif /* ENABLE_DEBUG */
-
// UNIX Domain Socket
{ socket_recv, EPOLLIN },
}
}
- // Handle log INFO messages
- } else if (log_INFO == fd) {
- if (e & EPOLLIN) {
- r = pakfire_jail_handle_log(jail, ctx, fd, &ctx->buffers.log_INFO,
- pakfire_jail_log, &ctx->buffers.log_INFO.priority);
- if (r)
- goto ERROR;
- }
-
- // Handle log ERROR messages
- } else if (log_ERROR == fd) {
- if (e & EPOLLIN) {
- r = pakfire_jail_handle_log(jail, ctx, fd, &ctx->buffers.log_ERROR,
- pakfire_jail_log, &ctx->buffers.log_ERROR.priority);
- if (r)
- goto ERROR;
- }
-
-#ifdef ENABLE_DEBUG
- // Handle log DEBUG messages
- } else if (log_DEBUG == fd) {
- if (e & EPOLLIN) {
- r = pakfire_jail_handle_log(jail, ctx, fd, &ctx->buffers.log_DEBUG,
- pakfire_jail_log, &ctx->buffers.log_DEBUG.priority);
- if (r)
- goto ERROR;
- }
-#endif /* ENABLE_DEBUG */
-
// Log a message for anything else
} else {
CTX_DEBUG(jail->ctx, "Received invalid file descriptor %d\n", fd);
int r;
// Redirect any logging to our log pipe
- pakfire_ctx_set_log_callback(jail->ctx, pakfire_jail_log_redirect, &ctx->pipes);
+ pakfire_ctx_set_log_callback(jail->ctx, pakfire_jail_log_redirect, ctx);
// Fetch my own PID
pid_t pid = getpid();
// Close the socket
close(socket_send);
- // Close other end of log pipes
- close(ctx->pipes.log_INFO[0]);
- close(ctx->pipes.log_ERROR[0]);
+ // Setup logging
+ r = pakfire_log_stream_in_child(ctx->log.INFO);
+ if (r)
+ return r;
+
+ r = pakfire_log_stream_in_child(ctx->log.ERROR);
+ if (r)
+ return r;
+
#ifdef ENABLE_DEBUG
- close(ctx->pipes.log_DEBUG[0]);
+ r = pakfire_log_stream_in_child(ctx->log.DEBUG);
+ if (r)
+ return r;
#endif /* ENABLE_DEBUG */
// Reset open file limit (http://0pointer.net/blog/file-descriptor-limits.html)
.socket = { -1, -1 },
- .pipes = {
- .log_INFO = { -1, -1 },
- .log_ERROR = { -1, -1 },
-#ifdef ENABLE_DEBUG
- .log_DEBUG = { -1, -1 },
-#endif /* ENABLE_DEBUG */
- },
-
- .buffers = {
- .log_INFO = {
- .priority = LOG_INFO,
- },
-
- .log_ERROR = {
- .priority = LOG_ERR,
- },
-
-#ifdef ENABLE_DEBUG
- .log_DEBUG = {
- .priority = LOG_DEBUG,
- },
-#endif /* ENABLE_DEBUG */
- },
-
.pidfd = -1,
// PTY
// Setup pipes for logging
// INFO
- r = pakfire_jail_setup_pipe(jail, &ctx.pipes.log_INFO, O_CLOEXEC);
+ r = pakfire_log_stream_create(&ctx.log.INFO, jail->ctx, pakfire_jail_INFO, jail);
if (r)
goto ERROR;
// ERROR
- r = pakfire_jail_setup_pipe(jail, &ctx.pipes.log_ERROR, O_CLOEXEC);
+ r = pakfire_log_stream_create(&ctx.log.ERROR, jail->ctx, pakfire_jail_ERROR, jail);
if (r)
goto ERROR;
#ifdef ENABLE_DEBUG
// DEBUG
- r = pakfire_jail_setup_pipe(jail, &ctx.pipes.log_DEBUG, O_CLOEXEC);
+ r = pakfire_log_stream_create(&ctx.log.DEBUG, jail->ctx, pakfire_jail_DEBUG, jail);
if (r)
goto ERROR;
#endif /* ENABLE_DEBUG */
close(ctx.pidfd);
if (ctx.pty.master.fd >= 0)
close(ctx.pty.master.fd);
- pakfire_jail_close_pipe(jail, ctx.pipes.log_INFO);
- pakfire_jail_close_pipe(jail, ctx.pipes.log_ERROR);
+
+ // Logging
+ if (ctx.log.INFO)
+ pakfire_log_stream_unref(ctx.log.INFO);
+ if (ctx.log.ERROR)
+ pakfire_log_stream_unref(ctx.log.ERROR);
#ifdef ENABLE_DEBUG
- pakfire_jail_close_pipe(jail, ctx.pipes.log_DEBUG);
+ if (ctx.log.DEBUG)
+ pakfire_log_stream_unref(ctx.log.DEBUG);
#endif /* ENABLE_DEBUG */
pakfire_jail_close_pipe(jail, ctx.socket);