journald.c revision 18b754d345ecb0b15e369978aaffa72e9814b86a
f2561e85982ed25b610cad6253599a051f9ec8e2Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
f2561e85982ed25b610cad6253599a051f9ec8e2Lennart Poettering This file is part of systemd.
f2561e85982ed25b610cad6253599a051f9ec8e2Lennart Poettering Copyright 2011 Lennart Poettering
f2561e85982ed25b610cad6253599a051f9ec8e2Lennart Poettering systemd is free software; you can redistribute it and/or modify it
f2561e85982ed25b610cad6253599a051f9ec8e2Lennart Poettering under the terms of the GNU General Public License as published by
f2561e85982ed25b610cad6253599a051f9ec8e2Lennart Poettering the Free Software Foundation; either version 2 of the License, or
f2561e85982ed25b610cad6253599a051f9ec8e2Lennart Poettering (at your option) any later version.
4ad490007b70e6ac18d3cb04fa2ed92eba1451faLennart Poettering systemd is distributed in the hope that it will be useful, but
4ad490007b70e6ac18d3cb04fa2ed92eba1451faLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
along with systemd; If not, see <http://www.gnu.org/licenses/>.
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <stddef.h>
#include "hashmap.h"
#include "journal-file.h"
#include "socket-util.h"
#include "cgroup-util.h"
#include "list.h"
#include "journal-rate-limit.h"
#include "journal-internal.h"
#include "conf-parser.h"
#include "journald.h"
#include "virt.h"
#include "missing.h"
#ifdef HAVE_ACL
#include "acl-util.h"
#ifdef HAVE_SELINUX
typedef enum StdoutStreamState {
struct StdoutStream {
int fd;
#ifdef HAVE_SELINUX
char *identifier;
int priority;
DIR *d;
JournalMetrics *m;
return s->cached_available_space;
if (s->system_journal) {
m = &s->system_metrics;
m = &s->runtime_metrics;
assert(m);
d = opendir(p);
free(p);
goto finish;
if (!de)
closedir(d);
return avail;
assert(s);
if (s->file_gid_valid)
s->file_gid_valid = true;
#ifdef HAVE_ACL
assert(f);
#ifdef HAVE_ACL
if (uid <= 0)
if (!acl) {
goto finish;
goto finish;
JournalFile *f;
assert(s);
if (s->runtime_journal)
return s->runtime_journal;
if (uid <= 0)
return s->system_journal;
return s->system_journal;
if (asprintf(&p, "/var/log/journal/%s/user-%lu.journal", sd_id128_to_string(machine, ids), (unsigned long) uid) < 0)
return s->system_journal;
assert(f);
free(p);
return s->system_journal;
return s->system_journal;
JournalFile *f;
Iterator i;
if (s->runtime_journal) {
if (s->system_journal) {
r = journal_file_rotate(&f);
if (s->system_journal) {
if (r < 0 && r != -ENOENT)
free(p);
if (s->runtime_journal) {
if (r < 0 && r != -ENOENT)
free(p);
s->cached_available_space_timestamp = 0;
return NULL;
return NULL;
init_path[0] = 0;
return NULL;
path = p;
return path;
static void dispatch_message_real(
Server *s,
JournalFile *f;
bool vacuumed = false;
assert(s);
assert(n > 0);
if (ucred) {
free(t);
if (comm)
free(t);
if (exe)
free(t);
if (cmdline)
free(t);
if (cgroup)
free(t);
if (session)
free(t);
if (unit)
#ifdef HAVE_SELINUX
if (label) {
if (selinux_context) {
if (selinux_context)
if (tv) {
t = gethostname_malloc();
free(t);
if (hostname)
assert(n <= m);
!vacuumed) {
if (r == -E2BIG)
server_rotate(s);
server_vacuum(s);
vacuumed = true;
goto retry;
assert(s);
int priority) {
int rl;
assert(s);
if (!ucred)
goto finish;
if (!path)
goto finish;
if (rl == 0) {
static void forward_syslog_iovec(Server *s, const struct iovec *iovec, unsigned n_iovec, struct ucred *ucred, struct timeval *tv) {
} control;
assert(s);
if (ucred) {
struct ucred u;
u = *ucred;
static void forward_syslog_raw(Server *s, const char *buffer, struct ucred *ucred, struct timeval *tv) {
assert(s);
static void forward_syslog(Server *s, int priority, const char *identifier, const char *message, struct ucred *ucred, struct timeval *tv) {
time_t t;
assert(s);
if (!tm)
if (ucred) {
if (!identifier) {
if (identifier)
} else if (identifier) {
return priority;
static void forward_kmsg(Server *s, int priority, const char *identifier, const char *message, struct ucred *ucred) {
int fd;
assert(s);
if (ucred) {
if (!identifier) {
if (identifier)
} else if (identifier) {
if (fd < 0) {
goto finish;
static void forward_console(Server *s, const char *identifier, const char *message, struct ucred *ucred) {
int n = 0, fd;
assert(s);
if (ucred) {
if (!identifier) {
if (identifier)
} else if (identifier) {
if (fd < 0) {
goto finish;
size_t l, e;
p = *buf;
*pid = t;
t = strndup(p, l);
*identifier = t;
*buf = p + e;
static void process_syslog_message(Server *s, const char *buf, struct ucred *ucred, struct timeval *tv, const char *label, size_t label_len) {
char *message = NULL, *syslog_priority = NULL, *syslog_facility = NULL, *syslog_identifier = NULL, *syslog_pid = NULL;
assert(s);
if (s->forward_to_syslog)
if (s->forward_to_kmsg)
if (s->forward_to_console)
if (identifier) {
if (syslog_identifier)
if (pid) {
if (syslog_pid)
if (message)
static void process_native_message(
Server *s,
assert(s);
p = buffer;
while (remaining > 0) {
remaining--;
if (n+N_IOVEC_META_FIELDS >= m) {
struct iovec *c;
iovec = c;
if (valid_user_field(p, q - p)) {
size_t l;
identifier = t;
message = t;
uint64_t l;
memcpy(k, p, e - p);
if (valid_user_field(p, e - p)) {
free(k);
goto finish;
tn = n++;
if (message) {
if (s->forward_to_syslog)
if (s->forward_to_kmsg)
if (s->forward_to_console)
if (j == tn)
static void process_native_file(
Server *s,
int fd,
ssize_t n;
assert(s);
free(p);
int priority;
assert(s);
assert(p);
if (isempty(p))
if (s->level_prefix)
if (s->identifier) {
if (syslog_identifier)
if (message)
#ifdef HAVE_SELINUX
if (s->security_context) {
dispatch_message(s->server, iovec, n, ELEMENTSOF(iovec), &s->ucred, NULL, label, label_len, priority);
assert(s);
assert(p);
p = strstrip(p);
switch (s->state) {
case STDOUT_STREAM_IDENTIFIER:
if (isempty(p))
if (!s->identifier) {
return -ENOMEM;
case STDOUT_STREAM_PRIORITY:
return -EINVAL;
r = parse_boolean(p);
return -EINVAL;
s->level_prefix = !!r;
r = parse_boolean(p);
return -EINVAL;
s->forward_to_syslog = !!r;
r = parse_boolean(p);
return -EINVAL;
s->forward_to_kmsg = !!r;
r = parse_boolean(p);
return -EINVAL;
s->forward_to_console = !!r;
case STDOUT_STREAM_RUNNING:
return stdout_stream_log(s, p);
assert(s);
p = s->buffer;
char *end;
if (end)
*end = 0;
r = stdout_stream_line(s, p);
p += skip;
p[remaining] = 0;
r = stdout_stream_line(s, p);
p += remaining;
remaining = 0;
if (p > s->buffer) {
ssize_t l;
assert(s);
return -errno;
r = stdout_stream_scan(s, true);
s->length += l;
r = stdout_stream_scan(s, false);
assert(s);
if (s->server) {
if (s->fd >= 0) {
if (s->server)
#ifdef HAVE_SELINUX
if (s->security_context)
free(s);
int fd, r;
assert(s);
if (fd < 0) {
return -errno;
if (!stream) {
return -ENOMEM;
r = -errno;
goto fail;
#ifdef HAVE_SELINUX
r = -errno;
goto fail;
r = -errno;
goto fail;
s->n_stdout_streams ++;
fail:
usec_t r;
assert(t);
p = *_p;
k = undecchar(p[i]);
k = undecchar(p[i]);
char *message = NULL, *syslog_priority = NULL, *syslog_pid = NULL, *syslog_facility = NULL, *syslog_identifier = NULL, *source_time = NULL;
assert(s);
assert(p);
if (isempty(p))
(unsigned long long) usec) >= 0)
if (s->forward_to_syslog)
if (s->forward_to_syslog)
if (identifier) {
if (syslog_identifier)
if (pid) {
if (syslog_pid)
if (message)
assert(s);
p = s->proc_kmsg_buffer;
char *end;
if (end)
*end = 0;
proc_kmsg_line(s, p);
p += skip;
if (p > s->proc_kmsg_buffer) {
char *fn;
if (!s->system_journal) {
if (!fn)
return -ENOMEM;
if (!fn)
return -ENOMEM;
if (!s->runtime_journal) {
if (!fn)
return -ENOMEM;
if (s->system_journal) {
if (r != -ENOENT)
if (s->runtime_journal) {
sd_journal *j;
assert(s);
if (!s->runtime_journal)
if (!s->system_journal)
SD_JOURNAL_FOREACH(j) {
JournalFile *f;
f = j->current_file;
goto finish;
if (r == -E2BIG) {
server_rotate(s);
server_vacuum(s);
goto finish;
ssize_t l;
assert(s);
l = read(s->proc_kmsg_fd, s->proc_kmsg_buffer + s->proc_kmsg_length, sizeof(s->proc_kmsg_buffer) - 1 - s->proc_kmsg_length);
return -errno;
s->proc_kmsg_length += l;
proc_kmsg_scan(s);
assert(s);
if (s->proc_kmsg_fd < 0)
r = server_read_proc_kmsg(s);
assert(s);
ssize_t n;
return -EIO;
if (n != sizeof(sfsi)) {
return -EIO;
return -errno;
return -EIO;
r = server_read_proc_kmsg(s);
return -EIO;
} control;
ssize_t n;
unsigned n_fds = 0;
return -errno;
size_t l;
return -ENOMEM;
s->buffer_size = l;
s->buffer = b;
return -errno;
if (n > 0 && n_fds == 0) {
s->buffer[n] = 0;
} else if (n_fds > 0)
if (n > 0 && n_fds == 0)
else if (n_fds > 0)
return -EIO;
return -EIO;
int one, r;
assert(s);
if (s->syslog_fd < 0) {
if (s->syslog_fd < 0) {
return -errno;
r = bind(s->syslog_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
return -errno;
return -errno;
#ifdef HAVE_SELINUX
return -errno;
return -errno;
int one, r;
assert(s);
if (s->native_fd < 0) {
if (s->native_fd < 0) {
return -errno;
r = bind(s->native_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
return -errno;
return -errno;
#ifdef HAVE_SELINUX
return -errno;
return -errno;
assert(s);
if (s->stdout_fd < 0) {
if (s->stdout_fd < 0) {
return -errno;
r = bind(s->stdout_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
return -errno;
return -errno;
return -errno;
assert(s);
if (!s->import_proc_kmsg)
if (s->proc_kmsg_fd < 0) {
return -errno;
assert(s);
if (s->signal_fd < 0) {
return -errno;
return -errno;
size_t l;
char *word;
if (!word) {
r = -ENOMEM;
goto finish;
s->forward_to_syslog = r;
s->forward_to_kmsg = r;
s->forward_to_console = r;
FILE *f;
const char *fn;
assert(s);
return -errno;
r = config_parse(fn, f, "Journal\0", config_item_perf_lookup, (void*) journald_gperf_lookup, false, s);
fclose(f);
int n, r, fd;
assert(s);
zero(*s);
s->compress = true;
s->forward_to_syslog = true;
s->import_proc_kmsg = true;
if (!s->user_journals) {
return -ENOMEM;
if (s->epoll_fd < 0) {
return -errno;
n = sd_listen_fds(true);
if (s->native_fd >= 0) {
return -EINVAL;
if (s->stdout_fd >= 0) {
return -EINVAL;
if (s->syslog_fd >= 0) {
return -EINVAL;
return -EINVAL;
r = open_syslog_socket(s);
r = open_native_socket(s);
r = open_stdout_socket(s);
r = open_proc_kmsg(s);
r = open_signalfd(s);
if (!s->rate_limit)
return -ENOMEM;
r = system_journal_open(s);
JournalFile *f;
assert(s);
while (s->stdout_streams)
if (s->system_journal)
if (s->runtime_journal)
if (s->epoll_fd >= 0)
if (s->signal_fd >= 0)
if (s->syslog_fd >= 0)
if (s->native_fd >= 0)
if (s->stdout_fd >= 0)
if (s->proc_kmsg_fd >= 0)
if (s->rate_limit)
return EXIT_FAILURE;
log_open();
goto finish;
sd_notify(false,
r = -errno;
goto finish;
goto finish;
sd_notify(false,