journald-server.c revision d378991747d67fff1d4dc39e7fb2bc8f49f1b561
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering This file is part of systemd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright 2011 Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is free software; you can redistribute it and/or modify it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering under the terms of the GNU Lesser General Public License as published by
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (at your option) any later version.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is distributed in the hope that it will be useful, but
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Lesser General Public License for more details.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering You should have received a copy of the GNU Lesser General Public License
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#define DEFAULT_SYNC_INTERVAL_USEC (5*USEC_PER_MINUTE)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#define DEFAULT_RATE_LIMIT_INTERVAL (10*USEC_PER_SEC)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#define RECHECK_AVAILABLE_SPACE_USEC (30*USEC_PER_SEC)
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poetteringstatic const char* const storage_table[] = {
dc61b7e45d89a69f0469ab7b3289cdde7fcc55abTorstein HusebøDEFINE_STRING_TABLE_LOOKUP(storage, Storage);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart PoetteringDEFINE_CONFIG_PARSE_ENUM(config_parse_storage, storage, Storage, "Failed to parse storage setting");
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringstatic const char* const split_mode_table[] = {
9c491563837983385bf9fa244590e76e142f4fa3Daniel MackDEFINE_STRING_TABLE_LOOKUP(split_mode, SplitMode);
a8812dd7f161a3e459c1730ac92ff2bbc9986ff1Lennart PoetteringDEFINE_CONFIG_PARSE_ENUM(config_parse_split_mode, split_mode, SplitMode, "Failed to parse split mode setting");
a8812dd7f161a3e459c1730ac92ff2bbc9986ff1Lennart Poetteringstatic uint64_t available_space(Server *s) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *f;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering uint64_t sum = 0, avail = 0, ss_avail = 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (s->cached_available_space_timestamp + RECHECK_AVAILABLE_SPACE_USEC > ts)
f3abbe25403444688e1a1a23b9dbcc9aeefc0507Lennart Poettering p = strappend(f, sd_id128_to_string(machine, ids));
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
dbfbb6e776d613cb9be76d13de076d08450c9d29Daniel Mack avail = sum >= m->max_use ? 0 : m->max_use - sum;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ss_avail = ss_avail < m->keep_free ? 0 : ss_avail - m->keep_free;
8af5b883227ac8dfa796742b9edcc1647a5d4d6cLennart Poettering s->cached_available_space_timestamp = ts;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringstatic void server_read_file_gid(Server *s) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *g = "systemd-journal";
9c5e12a4314e7192e834e1b855e5e80111e636a6Tom Gundersen log_warning("Failed to resolve '%s' group: %s", g, strerror(-r));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering /* if we couldn't read the gid, then it will be 0, but that's
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * fine and we shouldn't try to resolve the group again, so
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * let's just pretend it worked right-away. */
2001c80560e3dae69e14fd994d3978c187af48b8Lennart Poetteringvoid server_fix_perms(Server *s, JournalFile *f, uid_t uid) {
d830ebbdf67d8cb32d33d8fdd47cf467fd6d3815Lennart Poettering r = fchmod_and_fchown(f->fd, 0640, 0, s->file_gid);
d830ebbdf67d8cb32d33d8fdd47cf467fd6d3815Lennart Poettering log_warning("Failed to fix access mode/rights on %s, ignoring: %s", f->path, strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Failed to read ACL on %s, ignoring: %m", f->path);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (acl_create_entry(&acl, &entry) < 0 ||
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Failed to patch ACL on %s, ignoring: %m", f->path);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (acl_get_permset(entry, &permset) < 0 ||
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Failed to patch ACL on %s, ignoring: %m", f->path);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering log_warning("Failed to set ACL on %s, ignoring: %m", f->path);
0db4c90afd7d9c7c8884bf8b3ec459edc74a03daDaniel Mackstatic JournalFile* find_journal(Server *s, uid_t uid) {
106784ebb7b303ae471851100a773ad2aebf5b80Daniel Mack /* We split up user logs only on /var, not on /run. If the
106784ebb7b303ae471851100a773ad2aebf5b80Daniel Mack * runtime file is open, we write to it exclusively, in order
931851e8e492a4d2715e22dcde50a5e7ccef4b49Lennart Poettering * to guarantee proper order as soon as we flush /run to
51323288fc628a5cac50914df915545d685b793eLennart Poettering * /var and close the runtime file. */
51323288fc628a5cac50914df915545d685b793eLennart Poettering f = hashmap_get(s->user_journals, UINT32_TO_PTR(uid));
return s->system_journal;
assert(f);
r = journal_file_open_reliably(p, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, s->system_journal, &f);
free(p);
return s->system_journal;
return s->system_journal;
JournalFile *f;
Iterator i;
if (s->runtime_journal) {
if (s->runtime_journal)
if (s->system_journal) {
if (s->system_journal)
JournalFile *f;
Iterator i;
if (s->system_journal) {
r = journal_file_set_offline(f);
s->sync_scheduled = false;
s->oldest_file_usec = 0;
if (s->system_journal) {
log_oom();
r = journal_directory_vacuum(p, s->system_metrics.max_use, s->system_metrics.keep_free, s->max_retention_usec, &s->oldest_file_usec);
if (r < 0 && r != -ENOENT)
free(p);
if (s->runtime_journal) {
log_oom();
r = journal_directory_vacuum(p, s->runtime_metrics.max_use, s->runtime_metrics.keep_free, s->max_retention_usec, &s->oldest_file_usec);
if (r < 0 && r != -ENOENT)
free(p);
s->cached_available_space_timestamp = 0;
char *path;
return NULL;
return NULL;
init_path[0] = 0;
return path;
else if (r == -EHOSTDOWN)
else if (r == -EBUSY)
else if (r == -EPROTONOSUPPORT)
JournalFile *f;
bool vacuumed = false;
assert(s);
assert(n > 0);
server_rotate(s);
server_vacuum(s);
vacuumed = true;
server_rotate(s);
server_vacuum(s);
static void dispatch_message_real(
Server *s,
const char *unit_id) {
#ifdef HAVE_AUDIT
bool owner_valid = false;
assert(s);
assert(n > 0);
if (ucred) {
#ifdef HAVE_AUDIT
free(t);
if (comm)
free(t);
if (exe)
free(t);
if (cmdline)
#ifdef HAVE_AUDIT
free(t);
if (cgroup)
#ifdef HAVE_LOGIND
free(t);
if (session)
owner_valid = true;
free(t);
free(t);
} else if (unit_id) {
if (session)
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);
journal_uid = 0;
assert(s);
void server_dispatch_message(
Server *s,
const char *unit_id,
int priority) {
int rl;
assert(s);
if (!ucred)
goto finish;
if (!path)
goto finish;
if (rl == 0)
char *fn;
if (!s->system_journal &&
if (!fn)
return -ENOMEM;
if (!fn)
return -ENOMEM;
r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &s->system_journal);
if (!s->runtime_journal &&
if (!fn)
return -ENOMEM;
if (s->system_journal) {
r = journal_file_open(fn, O_RDWR, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
if (r != -ENOENT)
r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
if (s->runtime_journal) {
assert(s);
if (!s->runtime_journal)
if (!s->system_journal)
SD_JOURNAL_FOREACH(j) {
JournalFile *f;
f = j->current_file;
goto finish;
goto finish;
server_rotate(s);
server_vacuum(s);
goto finish;
sd_journal_close(j);
assert(s);
ssize_t n;
return -EIO;
if (n != sizeof(sfsi)) {
return -EIO;
return -errno;
server_sync(s);
server_rotate(s);
server_vacuum(s);
uint64_t t;
server_sync(s);
return -EIO;
r = server_read_dev_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;
assert(s);
if (s->signal_fd < 0) {
return -errno;
return -errno;
char *w, *state;
size_t l;
if (!word)
return -ENOMEM;
s->forward_to_syslog = r;
s->forward_to_kmsg = r;
s->forward_to_console = r;
assert(s);
return -errno;
(void*) journald_gperf_lookup, false, s);
assert(s);
if (s->sync_timer_fd < 0)
return -errno;
return -errno;
assert(s);
if (s->sync_scheduled)
if (s->sync_interval_usec) {
return -errno;
s->sync_scheduled = true;
int n, r, fd;
assert(s);
zero(*s);
s->compress = true;
s->seal = true;
s->sync_scheduled = false;
s->forward_to_syslog = true;
(long long unsigned) s->rate_limit_interval,
s->rate_limit_burst);
if (!s->user_journals)
return log_oom();
if (!s->mmap)
return log_oom();
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 = server_open_syslog_socket(s);
r = server_open_native_socket(s);
r = server_open_stdout_socket(s);
r = server_open_dev_kmsg(s);
r = server_open_kernel_seqnum(s);
r = server_open_sync_timer(s);
r = open_signalfd(s);
if (!s->udev)
return -ENOMEM;
s->rate_limit_burst);
if (!s->rate_limit)
return -ENOMEM;
r = system_journal_open(s);
#ifdef HAVE_GCRYPT
JournalFile *f;
Iterator i;
usec_t n;
if (s->system_journal)
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->dev_kmsg_fd >= 0)
if (s->sync_timer_fd >= 0)
if (s->rate_limit)
if (s->kernel_seqnum)
if (s->mmap)
if (s->udev)