journald-server.c revision 4ec3cd7391e119b597375c547cf4ed50fce9f115
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering/***
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering This file is part of systemd.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering Copyright 2011 Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering systemd is free software; you can redistribute it and/or modify it
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering under the terms of the GNU Lesser General Public License as published by
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering (at your option) any later version.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering systemd is distributed in the hope that it will be useful, but
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering Lesser General Public License for more details.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering You should have received a copy of the GNU Lesser General Public License
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering***/
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include <sys/signalfd.h>
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering#include <sys/ioctl.h>
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering#include <linux/sockios.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <sys/statvfs.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <sys/mman.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <sys/timerfd.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include <libudev.h>
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering#include "sd-journal.h"
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include "sd-messages.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "sd-daemon.h"
a09abc4ae0bdc0200324eaa0416f23ff2170ec4eLennart Poettering#include "fileio.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "mkdir.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "hashmap.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "journal-file.h"
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include "socket-util.h"
bb99a35a873c35e80b0b47fe045081022660374dLennart Poettering#include "cgroup-util.h"
bb99a35a873c35e80b0b47fe045081022660374dLennart Poettering#include "list.h"
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering#include "missing.h"
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering#include "conf-parser.h"
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering#include "selinux-util.h"
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering#include "journal-internal.h"
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering#include "journal-vacuum.h"
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering#include "journal-authenticate.h"
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering#include "journald-rate-limit.h"
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering#include "journald-kmsg.h"
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering#include "journald-syslog.h"
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering#include "journald-stream.h"
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering#include "journald-console.h"
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include "journald-native.h"
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include "journald-audit.h"
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include "journald-server.h"
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#ifdef HAVE_ACL
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include <sys/acl.h>
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include <acl/libacl.h>
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include "acl-util.h"
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#endif
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#ifdef HAVE_SELINUX
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include <selinux/selinux.h>
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#endif
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#define USER_JOURNALS_MAX 1024
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#define DEFAULT_SYNC_INTERVAL_USEC (5*USEC_PER_MINUTE)
bb99a35a873c35e80b0b47fe045081022660374dLennart Poettering#define DEFAULT_RATE_LIMIT_INTERVAL (30*USEC_PER_SEC)
bb99a35a873c35e80b0b47fe045081022660374dLennart Poettering#define DEFAULT_RATE_LIMIT_BURST 1000
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#define DEFAULT_MAX_FILE_USEC USEC_PER_MONTH
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#define RECHECK_AVAILABLE_SPACE_USEC (30*USEC_PER_SEC)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringstatic const char* const storage_table[_STORAGE_MAX] = {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering [STORAGE_AUTO] = "auto",
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering [STORAGE_VOLATILE] = "volatile",
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering [STORAGE_PERSISTENT] = "persistent",
a5344d2c3b0f14e954ce1c0ef905c5b44bc5bf0aLennart Poettering [STORAGE_NONE] = "none"
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering};
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart PoetteringDEFINE_STRING_TABLE_LOOKUP(storage, Storage);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart PoetteringDEFINE_CONFIG_PARSE_ENUM(config_parse_storage, storage, Storage, "Failed to parse storage setting");
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringstatic const char* const split_mode_table[_SPLIT_MAX] = {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering [SPLIT_LOGIN] = "login",
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering [SPLIT_UID] = "uid",
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering [SPLIT_NONE] = "none",
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering};
a5344d2c3b0f14e954ce1c0ef905c5b44bc5bf0aLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart PoetteringDEFINE_STRING_TABLE_LOOKUP(split_mode, SplitMode);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart PoetteringDEFINE_CONFIG_PARSE_ENUM(config_parse_split_mode, split_mode, SplitMode, "Failed to parse split mode setting");
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poetteringstatic uint64_t available_space(Server *s, bool verbose) {
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek char ids[33];
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek _cleanup_free_ char *p = NULL;
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering sd_id128_t machine;
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen struct statvfs ss;
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen uint64_t sum = 0, ss_avail = 0, avail = 0;
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen int r;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering _cleanup_closedir_ DIR *d = NULL;
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek usec_t ts;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering const char *f;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering JournalMetrics *m;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering ts = now(CLOCK_MONOTONIC);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering if (s->cached_available_space_timestamp + RECHECK_AVAILABLE_SPACE_USEC > ts
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering && !verbose)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return s->cached_available_space;
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering r = sd_id128_get_machine(&machine);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (r < 0)
44b601bc79e46722bc0f0862ee0ce34a2284ef11Lennart Poettering return 0;
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering
25d042e81516246b1ebf706a57c47ac19abb0b8aLennart Poettering if (s->system_journal) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering f = "/var/log/journal/";
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering m = &s->system_metrics;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering } else {
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering f = "/run/log/journal/";
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering m = &s->runtime_metrics;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering }
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering assert(m);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering p = strappend(f, sd_id128_to_string(machine, ids));
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering if (!p)
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering return 0;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
25d042e81516246b1ebf706a57c47ac19abb0b8aLennart Poettering d = opendir(p);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (!d)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return 0;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (fstatvfs(dirfd(d), &ss) < 0)
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering return 0;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering for (;;) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering struct stat st;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering struct dirent *de;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering errno = 0;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering de = readdir(d);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (!de && errno != 0)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return 0;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (!de)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering break;
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering if (!endswith(de->d_name, ".journal") &&
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering !endswith(de->d_name, ".journal~"))
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering continue;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering continue;
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering if (!S_ISREG(st.st_mode))
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering continue;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering sum += (uint64_t) st.st_blocks * 512UL;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering }
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering ss_avail = ss.f_bsize * ss.f_bavail;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering /* If we reached a high mark, we will always allow this much
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering * again, unless usage goes above max_use. This watermark
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering * value is cached so that we don't give up space on pressure,
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering * but hover below the maximum usage. */
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering if (m->use < sum)
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering m->use = sum;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering avail = LESS_BY(ss_avail, m->keep_free);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering s->cached_available_space = LESS_BY(MIN(m->max_use, avail), sum);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering s->cached_available_space_timestamp = ts;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering if (verbose) {
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering char fb1[FORMAT_BYTES_MAX], fb2[FORMAT_BYTES_MAX], fb3[FORMAT_BYTES_MAX],
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering fb4[FORMAT_BYTES_MAX], fb5[FORMAT_BYTES_MAX];
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering server_driver_message(s, SD_MESSAGE_JOURNAL_USAGE,
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering "%s journal is using %s (max allowed %s, "
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering "trying to leave %s free of %s available → current limit %s).",
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering s->system_journal ? "Permanent" : "Runtime",
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering format_bytes(fb1, sizeof(fb1), sum),
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering format_bytes(fb2, sizeof(fb2), m->max_use),
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering format_bytes(fb3, sizeof(fb3), m->keep_free),
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering format_bytes(fb4, sizeof(fb4), ss_avail),
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering format_bytes(fb5, sizeof(fb5), s->cached_available_space + sum));
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering }
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering return s->cached_available_space;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering}
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringvoid server_fix_perms(Server *s, JournalFile *f, uid_t uid) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering int r;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#ifdef HAVE_ACL
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering acl_t acl;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering acl_entry_t entry;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering acl_permset_t permset;
a5344d2c3b0f14e954ce1c0ef905c5b44bc5bf0aLennart Poettering#endif
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering assert(f);
61c024b328d5493a334242a4d01ba923582093faZbigniew Jędrzejewski-Szmek
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering r = fchmod(f->fd, 0640);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (r < 0)
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering log_warning_errno(r, "Failed to fix access mode on %s, ignoring: %m", f->path);
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek#ifdef HAVE_ACL
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek if (uid <= SYSTEM_UID_MAX)
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek return;
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek acl = acl_get_fd(f->fd);
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek if (!acl) {
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek log_warning_errno(errno, "Failed to read ACL on %s, ignoring: %m", f->path);
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering return;
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering }
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering r = acl_find_uid(acl, uid, &entry);
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen if (r <= 0) {
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (acl_create_entry(&acl, &entry) < 0 ||
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering acl_set_tag_type(entry, ACL_USER) < 0 ||
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering acl_set_qualifier(entry, &uid) < 0) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering log_warning_errno(errno, "Failed to patch ACL on %s, ignoring: %m", f->path);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering goto finish;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering }
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering }
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering /* We do not recalculate the mask unconditionally here,
a5344d2c3b0f14e954ce1c0ef905c5b44bc5bf0aLennart Poettering * so that the fchmod() mask above stays intact. */
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (acl_get_permset(entry, &permset) < 0 ||
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering acl_add_perm(permset, ACL_READ) < 0 ||
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering calc_acl_mask_if_needed(&acl) < 0) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering log_warning_errno(errno, "Failed to patch ACL on %s, ignoring: %m", f->path);
29abad107f8610e73b2fc091216040b579c75453Zbigniew Jędrzejewski-Szmek goto finish;
29abad107f8610e73b2fc091216040b579c75453Zbigniew Jędrzejewski-Szmek }
2a0e0692565f0435657c93498e09cbb2d3517152Shawn Landden
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering if (acl_set_fd(f->fd, acl) < 0)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering log_warning_errno(errno, "Failed to set ACL on %s, ignoring: %m", f->path);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poetteringfinish:
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering acl_free(acl);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#endif
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering}
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringstatic JournalFile* find_journal(Server *s, uid_t uid) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering _cleanup_free_ char *p = NULL;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering int r;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering JournalFile *f;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering sd_id128_t machine;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering assert(s);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering /* We split up user logs only on /var, not on /run. If the
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering * runtime file is open, we write to it exclusively, in order
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering * to guarantee proper order as soon as we flush /run to
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering * /var and close the runtime file. */
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (s->runtime_journal)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return s->runtime_journal;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (uid <= SYSTEM_UID_MAX)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return s->system_journal;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering r = sd_id128_get_machine(&machine);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (r < 0)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return s->system_journal;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering f = ordered_hashmap_get(s->user_journals, UINT32_TO_PTR(uid));
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (f)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return f;
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/user-"UID_FMT".journal",
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering SD_ID128_FORMAT_VAL(machine), uid) < 0)
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering return s->system_journal;
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering while (ordered_hashmap_size(s->user_journals) >= USER_JOURNALS_MAX) {
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering /* Too many open? Then let's close one */
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering f = ordered_hashmap_steal_first(s->user_journals);
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering assert(f);
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering journal_file_close(f);
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering }
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering r = journal_file_open_reliably(p, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &f);
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering if (r < 0)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return s->system_journal;
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering server_fix_perms(s, f, uid);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering r = ordered_hashmap_put(s->user_journals, UINT32_TO_PTR(uid), f);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (r < 0) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering journal_file_close(f);
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering return s->system_journal;
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering }
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering return f;
6c045c0b4c49c88a1d3b9360c05efa5084796d2dZbigniew Jędrzejewski-Szmek}
6c045c0b4c49c88a1d3b9360c05efa5084796d2dZbigniew Jędrzejewski-Szmek
6c045c0b4c49c88a1d3b9360c05efa5084796d2dZbigniew Jędrzejewski-Szmekstatic int do_rotate(Server *s, JournalFile **f, const char* name,
6c045c0b4c49c88a1d3b9360c05efa5084796d2dZbigniew Jędrzejewski-Szmek bool seal, uint32_t uid) {
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering int r;
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering assert(s);
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering if (!*f)
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering return -EINVAL;
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering
8e33886ec582336564ae11b80023abe93d7599c0Zbigniew Jędrzejewski-Szmek r = journal_file_rotate(f, s->compress, seal);
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering if (r < 0)
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering if (*f)
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering log_error_errno(r, "Failed to rotate %s: %m",
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering (*f)->path);
73843b52585d42cc1a970a1c664818ece6942e9eLennart Poettering else
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering log_error_errno(r, "Failed to create new %s journal: %m",
73843b52585d42cc1a970a1c664818ece6942e9eLennart Poettering name);
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering else
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering server_fix_perms(s, *f, uid);
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering return r;
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering}
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poetteringvoid server_rotate(Server *s) {
73843b52585d42cc1a970a1c664818ece6942e9eLennart Poettering JournalFile *f;
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering void *k;
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering Iterator i;
87b0284327e34a4b96c22085fa2cdb3219294991Zbigniew Jędrzejewski-Szmek int r;
61c024b328d5493a334242a4d01ba923582093faZbigniew Jędrzejewski-Szmek
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering log_debug("Rotating...");
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering do_rotate(s, &s->runtime_journal, "runtime", false, 0);
73843b52585d42cc1a970a1c664818ece6942e9eLennart Poettering do_rotate(s, &s->system_journal, "system", s->seal, 0);
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering
73843b52585d42cc1a970a1c664818ece6942e9eLennart Poettering ORDERED_HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) {
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering r = do_rotate(s, &f, "user", s->seal, PTR_TO_UINT32(k));
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering if (r >= 0)
3ee897d6c2401effbc82f5eef35fce405781d6c8Lennart Poettering ordered_hashmap_replace(s->user_journals, k, f);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering else if (!f)
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering /* Old file has been closed and deallocated */
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering ordered_hashmap_remove(s->user_journals, k);
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering }
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering}
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poetteringvoid server_sync(Server *s) {
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering JournalFile *f;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering void *k;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering Iterator i;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering int r;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering if (s->system_journal) {
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering r = journal_file_set_offline(s->system_journal);
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering if (r < 0)
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering log_error_errno(r, "Failed to sync system journal: %m");
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek }
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering ORDERED_HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) {
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering r = journal_file_set_offline(f);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering if (r < 0)
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering log_error_errno(r, "Failed to sync user journal: %m");
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering }
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering if (s->sync_event_source) {
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering r = sd_event_source_set_enabled(s->sync_event_source, SD_EVENT_OFF);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering if (r < 0)
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering log_error_errno(r, "Failed to disable sync timer source: %m");
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek }
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering s->sync_scheduled = false;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering}
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poetteringstatic void do_vacuum(Server *s, char *ids, JournalFile *f, const char* path,
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering JournalMetrics *metrics) {
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering char *p;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering int r;
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering if (!f)
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering return;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering p = strappenda(path, ids);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering r = journal_directory_vacuum(p, metrics->max_use, s->max_retention_usec, &s->oldest_file_usec, false);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering if (r < 0 && r != -ENOENT)
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering log_error_errno(r, "Failed to vacuum %s: %m", p);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering}
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poetteringvoid server_vacuum(Server *s) {
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering char ids[33];
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering sd_id128_t machine;
4cd9a9d9ecf3a8835e21930f3215a5f5b74144beLennart Poettering int r;
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek log_debug("Vacuuming...");
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek s->oldest_file_usec = 0;
61c024b328d5493a334242a4d01ba923582093faZbigniew Jędrzejewski-Szmek
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering r = sd_id128_get_machine(&machine);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering if (r < 0) {
61c024b328d5493a334242a4d01ba923582093faZbigniew Jędrzejewski-Szmek log_error_errno(r, "Failed to get machine ID: %m");
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering return;
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen }
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen sd_id128_to_string(machine, ids);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering do_vacuum(s, ids, s->system_journal, "/var/log/journal/", &s->system_metrics);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering do_vacuum(s, ids, s->runtime_journal, "/run/log/journal/", &s->runtime_metrics);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering s->cached_available_space_timestamp = 0;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering}
61c024b328d5493a334242a4d01ba923582093faZbigniew Jędrzejewski-Szmek
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poetteringstatic void server_cache_machine_id(Server *s) {
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering sd_id128_t id;
61c024b328d5493a334242a4d01ba923582093faZbigniew Jędrzejewski-Szmek int r;
86b9b8e70d54e79db3ff4f67bbd5280ecfc82537Lennart Poettering
86b9b8e70d54e79db3ff4f67bbd5280ecfc82537Lennart Poettering assert(s);
bb99a35a873c35e80b0b47fe045081022660374dLennart Poettering
bb99a35a873c35e80b0b47fe045081022660374dLennart Poettering r = sd_id128_get_machine(&id);
4cd9a9d9ecf3a8835e21930f3215a5f5b74144beLennart Poettering if (r < 0)
4cd9a9d9ecf3a8835e21930f3215a5f5b74144beLennart Poettering return;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering
4cd9a9d9ecf3a8835e21930f3215a5f5b74144beLennart Poettering sd_id128_to_string(id, stpcpy(s->machine_id_field, "_MACHINE_ID="));
8b38f3cc3eb73adf9536cb73d0f319e60d42ea0cLennart Poettering}
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering
4cd9a9d9ecf3a8835e21930f3215a5f5b74144beLennart Poetteringstatic void server_cache_boot_id(Server *s) {
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering sd_id128_t id;
a6e87e90ede66815989ba2db92a07102a69906feLennart Poettering int r;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering assert(s);
4cd9a9d9ecf3a8835e21930f3215a5f5b74144beLennart Poettering
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering r = sd_id128_get_boot(&id);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering if (r < 0)
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering return;
224f2ee221e77c326d1d7761abb6e812432b2163Lennart Poettering
224f2ee221e77c326d1d7761abb6e812432b2163Lennart Poettering sd_id128_to_string(id, stpcpy(s->boot_id_field, "_BOOT_ID="));
224f2ee221e77c326d1d7761abb6e812432b2163Lennart Poettering}
224f2ee221e77c326d1d7761abb6e812432b2163Lennart Poettering
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poetteringstatic void server_cache_hostname(Server *s) {
553acb7b6b8d4f16a4747b1f978e8b7888fbfb2cZbigniew Jędrzejewski-Szmek _cleanup_free_ char *t = NULL;
61c024b328d5493a334242a4d01ba923582093faZbigniew Jędrzejewski-Szmek char *x;
61c024b328d5493a334242a4d01ba923582093faZbigniew Jędrzejewski-Szmek
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering assert(s);
61c024b328d5493a334242a4d01ba923582093faZbigniew Jędrzejewski-Szmek
61c024b328d5493a334242a4d01ba923582093faZbigniew Jędrzejewski-Szmek t = gethostname_malloc();
61c024b328d5493a334242a4d01ba923582093faZbigniew Jędrzejewski-Szmek if (!t)
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering return;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering x = strappend("_HOSTNAME=", t);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering if (!x)
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering return;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering free(s->hostname_field);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering s->hostname_field = x;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering}
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poetteringbool shall_try_append_again(JournalFile *f, int r) {
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering /* -E2BIG Hit configured limit
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering -EFBIG Hit fs limit
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek -EDQUOT Quota limit hit
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering -ENOSPC Disk full
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering -EHOSTDOWN Other machine
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering -EBUSY Unclean shutdown
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen -EPROTONOSUPPORT Unsupported feature
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen -EBADMSG Corrupted
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen -ENODATA Truncated
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering -ESHUTDOWN Already archived */
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering if (r == -E2BIG || r == -EFBIG || r == -EDQUOT || r == -ENOSPC)
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering log_debug("%s: Allocation limit reached, rotating.", f->path);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering else if (r == -EHOSTDOWN)
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering log_info("%s: Journal file from other machine, rotating.", f->path);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering else if (r == -EBUSY)
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering log_info("%s: Unclean shutdown, rotating.", f->path);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering else if (r == -EPROTONOSUPPORT)
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering log_info("%s: Unsupported feature, rotating.", f->path);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering else if (r == -EBADMSG || r == -ENODATA || r == ESHUTDOWN)
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering log_warning("%s: Journal file corrupted, rotating.", f->path);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering else
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering return false;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering return true;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering}
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poetteringstatic void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned n, int priority) {
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering JournalFile *f;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering bool vacuumed = false;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering int r;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering assert(s);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering assert(iovec);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering assert(n > 0);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering f = find_journal(s, uid);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering if (!f)
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering return;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering if (journal_file_rotate_suggested(f, s->max_file_usec)) {
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering log_debug("%s: Journal header limits reached or header out-of-date, rotating.", f->path);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering server_rotate(s);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering server_vacuum(s);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering vacuumed = true;
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering f = find_journal(s, uid);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering if (!f)
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering return;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering }
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering if (r >= 0) {
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering server_schedule_sync(s, priority);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering return;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering }
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering if (vacuumed || !shall_try_append_again(f, r)) {
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering size_t size = 0;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering unsigned i;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering for (i = 0; i < n; i++)
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering size += iovec[i].iov_len;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering log_error_errno(r, "Failed to write entry (%d items, %zu bytes), ignoring: %m", n, size);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering return;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering }
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering server_rotate(s);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering server_vacuum(s);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen f = find_journal(s, uid);
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen if (!f)
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering return;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering log_debug("Retrying write.");
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering if (r < 0) {
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering size_t size = 0;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering unsigned i;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering for (i = 0; i < n; i++)
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering size += iovec[i].iov_len;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering log_error_errno(r, "Failed to write entry (%d items, %zu bytes) despite vacuuming, ignoring: %m", n, size);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering } else
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering server_schedule_sync(s, priority);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering}
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poetteringstatic void dispatch_message_real(
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering Server *s,
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering struct iovec *iovec, unsigned n, unsigned m,
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering const struct ucred *ucred,
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering const struct timeval *tv,
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering const char *label, size_t label_len,
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering const char *unit_id,
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering int priority,
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering pid_t object_pid) {
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering char pid[sizeof("_PID=") + DECIMAL_STR_MAX(pid_t)],
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering uid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)],
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering gid[sizeof("_GID=") + DECIMAL_STR_MAX(gid_t)],
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering owner_uid[sizeof("_SYSTEMD_OWNER_UID=") + DECIMAL_STR_MAX(uid_t)],
source_time[sizeof("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t)],
o_uid[sizeof("OBJECT_UID=") + DECIMAL_STR_MAX(uid_t)],
o_gid[sizeof("OBJECT_GID=") + DECIMAL_STR_MAX(gid_t)],
o_owner_uid[sizeof("OBJECT_SYSTEMD_OWNER_UID=") + DECIMAL_STR_MAX(uid_t)];
uid_t object_uid;
gid_t object_gid;
char *x;
int r;
char *t, *c;
uid_t realuid = 0, owner = 0, journal_uid;
bool owner_valid = false;
#ifdef HAVE_AUDIT
char audit_session[sizeof("_AUDIT_SESSION=") + DECIMAL_STR_MAX(uint32_t)],
audit_loginuid[sizeof("_AUDIT_LOGINUID=") + DECIMAL_STR_MAX(uid_t)],
o_audit_session[sizeof("OBJECT_AUDIT_SESSION=") + DECIMAL_STR_MAX(uint32_t)],
o_audit_loginuid[sizeof("OBJECT_AUDIT_LOGINUID=") + DECIMAL_STR_MAX(uid_t)];
uint32_t audit;
uid_t loginuid;
#endif
assert(s);
assert(iovec);
assert(n > 0);
assert(n + N_IOVEC_META_FIELDS + (object_pid ? N_IOVEC_OBJECT_FIELDS : 0) <= m);
if (ucred) {
realuid = ucred->uid;
sprintf(pid, "_PID="PID_FMT, ucred->pid);
IOVEC_SET_STRING(iovec[n++], pid);
sprintf(uid, "_UID="UID_FMT, ucred->uid);
IOVEC_SET_STRING(iovec[n++], uid);
sprintf(gid, "_GID="GID_FMT, ucred->gid);
IOVEC_SET_STRING(iovec[n++], gid);
r = get_process_comm(ucred->pid, &t);
if (r >= 0) {
x = strappenda("_COMM=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
r = get_process_exe(ucred->pid, &t);
if (r >= 0) {
x = strappenda("_EXE=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
r = get_process_cmdline(ucred->pid, 0, false, &t);
if (r >= 0) {
x = strappenda("_CMDLINE=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
r = get_process_capeff(ucred->pid, &t);
if (r >= 0) {
x = strappenda("_CAP_EFFECTIVE=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
#ifdef HAVE_AUDIT
r = audit_session_from_pid(ucred->pid, &audit);
if (r >= 0) {
sprintf(audit_session, "_AUDIT_SESSION=%"PRIu32, audit);
IOVEC_SET_STRING(iovec[n++], audit_session);
}
r = audit_loginuid_from_pid(ucred->pid, &loginuid);
if (r >= 0) {
sprintf(audit_loginuid, "_AUDIT_LOGINUID="UID_FMT, loginuid);
IOVEC_SET_STRING(iovec[n++], audit_loginuid);
}
#endif
r = cg_pid_get_path_shifted(ucred->pid, s->cgroup_root, &c);
if (r >= 0) {
char *session = NULL;
x = strappenda("_SYSTEMD_CGROUP=", c);
IOVEC_SET_STRING(iovec[n++], x);
r = cg_path_get_session(c, &t);
if (r >= 0) {
session = strappenda("_SYSTEMD_SESSION=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], session);
}
if (cg_path_get_owner_uid(c, &owner) >= 0) {
owner_valid = true;
sprintf(owner_uid, "_SYSTEMD_OWNER_UID="UID_FMT, owner);
IOVEC_SET_STRING(iovec[n++], owner_uid);
}
if (cg_path_get_unit(c, &t) >= 0) {
x = strappenda("_SYSTEMD_UNIT=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
} else if (unit_id && !session) {
x = strappenda("_SYSTEMD_UNIT=", unit_id);
IOVEC_SET_STRING(iovec[n++], x);
}
if (cg_path_get_user_unit(c, &t) >= 0) {
x = strappenda("_SYSTEMD_USER_UNIT=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
} else if (unit_id && session) {
x = strappenda("_SYSTEMD_USER_UNIT=", unit_id);
IOVEC_SET_STRING(iovec[n++], x);
}
if (cg_path_get_slice(c, &t) >= 0) {
x = strappenda("_SYSTEMD_SLICE=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
free(c);
} else if (unit_id) {
x = strappenda("_SYSTEMD_UNIT=", unit_id);
IOVEC_SET_STRING(iovec[n++], x);
}
#ifdef HAVE_SELINUX
if (mac_selinux_use()) {
if (label) {
x = alloca(strlen("_SELINUX_CONTEXT=") + label_len + 1);
*((char*) mempcpy(stpcpy(x, "_SELINUX_CONTEXT="), label, label_len)) = 0;
IOVEC_SET_STRING(iovec[n++], x);
} else {
security_context_t con;
if (getpidcon(ucred->pid, &con) >= 0) {
x = strappenda("_SELINUX_CONTEXT=", con);
freecon(con);
IOVEC_SET_STRING(iovec[n++], x);
}
}
}
#endif
}
assert(n <= m);
if (object_pid) {
r = get_process_uid(object_pid, &object_uid);
if (r >= 0) {
sprintf(o_uid, "OBJECT_UID="UID_FMT, object_uid);
IOVEC_SET_STRING(iovec[n++], o_uid);
}
r = get_process_gid(object_pid, &object_gid);
if (r >= 0) {
sprintf(o_gid, "OBJECT_GID="GID_FMT, object_gid);
IOVEC_SET_STRING(iovec[n++], o_gid);
}
r = get_process_comm(object_pid, &t);
if (r >= 0) {
x = strappenda("OBJECT_COMM=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
r = get_process_exe(object_pid, &t);
if (r >= 0) {
x = strappenda("OBJECT_EXE=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
r = get_process_cmdline(object_pid, 0, false, &t);
if (r >= 0) {
x = strappenda("OBJECT_CMDLINE=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
#ifdef HAVE_AUDIT
r = audit_session_from_pid(object_pid, &audit);
if (r >= 0) {
sprintf(o_audit_session, "OBJECT_AUDIT_SESSION=%"PRIu32, audit);
IOVEC_SET_STRING(iovec[n++], o_audit_session);
}
r = audit_loginuid_from_pid(object_pid, &loginuid);
if (r >= 0) {
sprintf(o_audit_loginuid, "OBJECT_AUDIT_LOGINUID="UID_FMT, loginuid);
IOVEC_SET_STRING(iovec[n++], o_audit_loginuid);
}
#endif
r = cg_pid_get_path_shifted(object_pid, s->cgroup_root, &c);
if (r >= 0) {
x = strappenda("OBJECT_SYSTEMD_CGROUP=", c);
IOVEC_SET_STRING(iovec[n++], x);
r = cg_path_get_session(c, &t);
if (r >= 0) {
x = strappenda("OBJECT_SYSTEMD_SESSION=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
if (cg_path_get_owner_uid(c, &owner) >= 0) {
sprintf(o_owner_uid, "OBJECT_SYSTEMD_OWNER_UID="UID_FMT, owner);
IOVEC_SET_STRING(iovec[n++], o_owner_uid);
}
if (cg_path_get_unit(c, &t) >= 0) {
x = strappenda("OBJECT_SYSTEMD_UNIT=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
if (cg_path_get_user_unit(c, &t) >= 0) {
x = strappenda("OBJECT_SYSTEMD_USER_UNIT=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
free(c);
}
}
assert(n <= m);
if (tv) {
sprintf(source_time, "_SOURCE_REALTIME_TIMESTAMP=%llu", (unsigned long long) timeval_load(tv));
IOVEC_SET_STRING(iovec[n++], source_time);
}
/* Note that strictly speaking storing the boot id here is
* redundant since the entry includes this in-line
* anyway. However, we need this indexed, too. */
if (!isempty(s->boot_id_field))
IOVEC_SET_STRING(iovec[n++], s->boot_id_field);
if (!isempty(s->machine_id_field))
IOVEC_SET_STRING(iovec[n++], s->machine_id_field);
if (!isempty(s->hostname_field))
IOVEC_SET_STRING(iovec[n++], s->hostname_field);
assert(n <= m);
if (s->split_mode == SPLIT_UID && realuid > 0)
/* Split up strictly by any UID */
journal_uid = realuid;
else if (s->split_mode == SPLIT_LOGIN && realuid > 0 && owner_valid && owner > 0)
/* Split up by login UIDs. We do this only if the
* realuid is not root, in order not to accidentally
* leak privileged information to the user that is
* logged by a privileged process that is part of an
* unprivileged session.*/
journal_uid = owner;
else
journal_uid = 0;
write_to_journal(s, journal_uid, iovec, n, priority);
}
void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) {
char mid[11 + 32 + 1];
char buffer[16 + LINE_MAX + 1];
struct iovec iovec[N_IOVEC_META_FIELDS + 4];
int n = 0;
va_list ap;
struct ucred ucred = {};
assert(s);
assert(format);
IOVEC_SET_STRING(iovec[n++], "PRIORITY=6");
IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=driver");
memcpy(buffer, "MESSAGE=", 8);
va_start(ap, format);
vsnprintf(buffer + 8, sizeof(buffer) - 8, format, ap);
va_end(ap);
char_array_0(buffer);
IOVEC_SET_STRING(iovec[n++], buffer);
if (!sd_id128_equal(message_id, SD_ID128_NULL)) {
snprintf(mid, sizeof(mid), LOG_MESSAGE_ID(message_id));
char_array_0(mid);
IOVEC_SET_STRING(iovec[n++], mid);
}
ucred.pid = getpid();
ucred.uid = getuid();
ucred.gid = getgid();
dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL, LOG_INFO, 0);
}
void server_dispatch_message(
Server *s,
struct iovec *iovec, unsigned n, unsigned m,
const struct ucred *ucred,
const struct timeval *tv,
const char *label, size_t label_len,
const char *unit_id,
int priority,
pid_t object_pid) {
int rl, r;
_cleanup_free_ char *path = NULL;
char *c;
assert(s);
assert(iovec || n == 0);
if (n == 0)
return;
if (LOG_PRI(priority) > s->max_level_store)
return;
/* Stop early in case the information will not be stored
* in a journal. */
if (s->storage == STORAGE_NONE)
return;
if (!ucred)
goto finish;
r = cg_pid_get_path_shifted(ucred->pid, s->cgroup_root, &path);
if (r < 0)
goto finish;
/* example: /user/lennart/3/foobar
* /system/dbus.service/foobar
*
* So let's cut of everything past the third /, since that is
* where user directories start */
c = strchr(path, '/');
if (c) {
c = strchr(c+1, '/');
if (c) {
c = strchr(c+1, '/');
if (c)
*c = 0;
}
}
rl = journal_rate_limit_test(s->rate_limit, path,
priority & LOG_PRIMASK, available_space(s, false));
if (rl == 0)
return;
/* Write a suppression message if we suppressed something */
if (rl > 1)
server_driver_message(s, SD_MESSAGE_JOURNAL_DROPPED,
"Suppressed %u messages from %s", rl - 1, path);
finish:
dispatch_message_real(s, iovec, n, m, ucred, tv, label, label_len, unit_id, priority, object_pid);
}
static int system_journal_open(Server *s, bool flush_requested) {
int r;
char *fn;
sd_id128_t machine;
char ids[33];
r = sd_id128_get_machine(&machine);
if (r < 0)
return log_error_errno(r, "Failed to get machine id: %m");
sd_id128_to_string(machine, ids);
if (!s->system_journal &&
(s->storage == STORAGE_PERSISTENT || s->storage == STORAGE_AUTO) &&
(flush_requested
|| access("/run/systemd/journal/flushed", F_OK) >= 0)) {
/* If in auto mode: first try to create the machine
* path, but not the prefix.
*
* If in persistent mode: create /var/log/journal and
* the machine path */
if (s->storage == STORAGE_PERSISTENT)
(void) mkdir("/var/log/journal/", 0755);
fn = strappenda("/var/log/journal/", ids);
(void) mkdir(fn, 0755);
fn = strappenda(fn, "/system.journal");
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 (r >= 0)
server_fix_perms(s, s->system_journal, 0);
else if (r < 0) {
if (r != -ENOENT && r != -EROFS)
log_warning_errno(r, "Failed to open system journal: %m");
r = 0;
}
}
if (!s->runtime_journal &&
(s->storage != STORAGE_NONE)) {
fn = strjoin("/run/log/journal/", ids, "/system.journal", NULL);
if (!fn)
return -ENOMEM;
if (s->system_journal) {
/* Try to open the runtime journal, but only
* if it already exists, so that we can flush
* it into the system journal */
r = journal_file_open(fn, O_RDWR, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
free(fn);
if (r < 0) {
if (r != -ENOENT)
log_warning_errno(r, "Failed to open runtime journal: %m");
r = 0;
}
} else {
/* OK, we really need the runtime journal, so create
* it if necessary. */
(void) mkdir("/run/log", 0755);
(void) mkdir("/run/log/journal", 0755);
(void) mkdir_parents(fn, 0750);
r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
free(fn);
if (r < 0)
return log_error_errno(r, "Failed to open runtime journal: %m");
}
if (s->runtime_journal)
server_fix_perms(s, s->runtime_journal, 0);
}
available_space(s, true);
return r;
}
int server_flush_to_var(Server *s) {
sd_id128_t machine;
sd_journal *j = NULL;
char ts[FORMAT_TIMESPAN_MAX];
usec_t start;
unsigned n = 0;
int r;
assert(s);
if (s->storage != STORAGE_AUTO &&
s->storage != STORAGE_PERSISTENT)
return 0;
if (!s->runtime_journal)
return 0;
system_journal_open(s, true);
if (!s->system_journal)
return 0;
log_debug("Flushing to /var...");
start = now(CLOCK_MONOTONIC);
r = sd_id128_get_machine(&machine);
if (r < 0)
return r;
r = sd_journal_open(&j, SD_JOURNAL_RUNTIME_ONLY);
if (r < 0)
return log_error_errno(r, "Failed to read runtime journal: %m");
sd_journal_set_data_threshold(j, 0);
SD_JOURNAL_FOREACH(j) {
Object *o = NULL;
JournalFile *f;
f = j->current_file;
assert(f && f->current_offset > 0);
n++;
r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
if (r < 0) {
log_error_errno(r, "Can't read entry: %m");
goto finish;
}
r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset, NULL, NULL, NULL);
if (r >= 0)
continue;
if (!shall_try_append_again(s->system_journal, r)) {
log_error_errno(r, "Can't write entry: %m");
goto finish;
}
server_rotate(s);
server_vacuum(s);
if (!s->system_journal) {
log_notice("Didn't flush runtime journal since rotation of system journal wasn't successful.");
r = -EIO;
goto finish;
}
log_debug("Retrying write.");
r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset, NULL, NULL, NULL);
if (r < 0) {
log_error_errno(r, "Can't write entry: %m");
goto finish;
}
}
finish:
journal_file_post_change(s->system_journal);
journal_file_close(s->runtime_journal);
s->runtime_journal = NULL;
if (r >= 0)
rm_rf("/run/log/journal", false, true, false);
sd_journal_close(j);
server_driver_message(s, SD_ID128_NULL, "Time spent on flushing to /var is %s for %u entries.", format_timespan(ts, sizeof(ts), now(CLOCK_MONOTONIC) - start, 0), n);
return r;
}
int process_datagram(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
Server *s = userdata;
assert(s);
assert(fd == s->native_fd || fd == s->syslog_fd || fd == s->audit_fd);
if (revents != EPOLLIN) {
log_error("Got invalid event from epoll for datagram fd: %"PRIx32, revents);
return -EIO;
}
for (;;) {
struct ucred *ucred = NULL;
struct timeval *tv = NULL;
struct cmsghdr *cmsg;
char *label = NULL;
size_t label_len = 0;
struct iovec iovec;
union {
struct cmsghdr cmsghdr;
/* We use NAME_MAX space for the SELinux label
* here. The kernel currently enforces no
* limit, but according to suggestions from
* the SELinux people this will change and it
* will probably be identical to NAME_MAX. For
* now we use that, but this should be updated
* one day when the final limit is known.*/
uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
CMSG_SPACE(sizeof(struct timeval)) +
CMSG_SPACE(sizeof(int)) + /* fd */
CMSG_SPACE(NAME_MAX)]; /* selinux label */
} control = {};
union sockaddr_union sa = {};
struct msghdr msghdr = {
.msg_iov = &iovec,
.msg_iovlen = 1,
.msg_control = &control,
.msg_controllen = sizeof(control),
.msg_name = &sa,
.msg_namelen = sizeof(sa),
};
ssize_t n;
int *fds = NULL;
unsigned n_fds = 0;
int v = 0;
size_t m;
/* Try to get the right size, if we can. (Not all
* sockets support SIOCINQ, hence we just try, but
* don't rely on it. */
(void) ioctl(fd, SIOCINQ, &v);
/* Fix it up, if it is too small. We use the same fixed value as auditd here. Awful!*/
m = PAGE_ALIGN(MAX3((size_t) v + 1,
(size_t) LINE_MAX,
ALIGN(sizeof(struct nlmsghdr)) + ALIGN((size_t) MAX_AUDIT_MESSAGE_LENGTH)) + 1);
if (!GREEDY_REALLOC(s->buffer, s->buffer_size, m))
return log_oom();
iovec.iov_base = s->buffer;
iovec.iov_len = s->buffer_size - 1; /* Leave room for trailing NUL we add later */
n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (n < 0) {
if (errno == EINTR || errno == EAGAIN)
return 0;
log_error_errno(errno, "recvmsg() failed: %m");
return -errno;
}
for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_CREDENTIALS &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
ucred = (struct ucred*) CMSG_DATA(cmsg);
else if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_SECURITY) {
label = (char*) CMSG_DATA(cmsg);
label_len = cmsg->cmsg_len - CMSG_LEN(0);
} else if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SO_TIMESTAMP &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
tv = (struct timeval*) CMSG_DATA(cmsg);
else if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_RIGHTS) {
fds = (int*) CMSG_DATA(cmsg);
n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
}
}
/* And a trailing NUL, just in case */
s->buffer[n] = 0;
if (fd == s->syslog_fd) {
if (n > 0 && n_fds == 0)
server_process_syslog_message(s, strstrip(s->buffer), ucred, tv, label, label_len);
else if (n_fds > 0)
log_warning("Got file descriptors via syslog socket. Ignoring.");
} else if (fd == s->native_fd) {
if (n > 0 && n_fds == 0)
server_process_native_message(s, s->buffer, n, ucred, tv, label, label_len);
else if (n == 0 && n_fds == 1)
server_process_native_file(s, fds[0], ucred, tv, label, label_len);
else if (n_fds > 0)
log_warning("Got too many file descriptors via native socket. Ignoring.");
} else {
assert(fd == s->audit_fd);
if (n > 0 && n_fds == 0)
server_process_audit_message(s, s->buffer, n, ucred, &sa, msghdr.msg_namelen);
else if (n_fds > 0)
log_warning("Got file descriptors via audit socket. Ignoring.");
}
close_many(fds, n_fds);
}
}
static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
Server *s = userdata;
assert(s);
log_info("Received request to flush runtime journal from PID %"PRIu32, si->ssi_pid);
server_flush_to_var(s);
server_sync(s);
server_vacuum(s);
touch("/run/systemd/journal/flushed");
return 0;
}
static int dispatch_sigusr2(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
Server *s = userdata;
assert(s);
log_info("Received request to rotate journal from PID %"PRIu32, si->ssi_pid);
server_rotate(s);
server_vacuum(s);
return 0;
}
static int dispatch_sigterm(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
Server *s = userdata;
assert(s);
log_received_signal(LOG_INFO, si);
sd_event_exit(s->event, 0);
return 0;
}
static int setup_signals(Server *s) {
sigset_t mask;
int r;
assert(s);
assert_se(sigemptyset(&mask) == 0);
sigset_add_many(&mask, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, -1);
assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
r = sd_event_add_signal(s->event, &s->sigusr1_event_source, SIGUSR1, dispatch_sigusr1, s);
if (r < 0)
return r;
r = sd_event_add_signal(s->event, &s->sigusr2_event_source, SIGUSR2, dispatch_sigusr2, s);
if (r < 0)
return r;
r = sd_event_add_signal(s->event, &s->sigterm_event_source, SIGTERM, dispatch_sigterm, s);
if (r < 0)
return r;
r = sd_event_add_signal(s->event, &s->sigint_event_source, SIGINT, dispatch_sigterm, s);
if (r < 0)
return r;
return 0;
}
static int server_parse_proc_cmdline(Server *s) {
_cleanup_free_ char *line = NULL;
const char *w, *state;
size_t l;
int r;
r = proc_cmdline(&line);
if (r < 0) {
log_warning_errno(r, "Failed to read /proc/cmdline, ignoring: %m");
return 0;
}
FOREACH_WORD_QUOTED(w, l, line, state) {
_cleanup_free_ char *word;
word = strndup(w, l);
if (!word)
return -ENOMEM;
if (startswith(word, "systemd.journald.forward_to_syslog=")) {
r = parse_boolean(word + 35);
if (r < 0)
log_warning("Failed to parse forward to syslog switch %s. Ignoring.", word + 35);
else
s->forward_to_syslog = r;
} else if (startswith(word, "systemd.journald.forward_to_kmsg=")) {
r = parse_boolean(word + 33);
if (r < 0)
log_warning("Failed to parse forward to kmsg switch %s. Ignoring.", word + 33);
else
s->forward_to_kmsg = r;
} else if (startswith(word, "systemd.journald.forward_to_console=")) {
r = parse_boolean(word + 36);
if (r < 0)
log_warning("Failed to parse forward to console switch %s. Ignoring.", word + 36);
else
s->forward_to_console = r;
} else if (startswith(word, "systemd.journald.forward_to_wall=")) {
r = parse_boolean(word + 33);
if (r < 0)
log_warning("Failed to parse forward to wall switch %s. Ignoring.", word + 33);
else
s->forward_to_wall = r;
} else if (startswith(word, "systemd.journald"))
log_warning("Invalid systemd.journald parameter. Ignoring.");
}
/* do not warn about state here, since probably systemd already did */
return 0;
}
static int server_parse_config_file(Server *s) {
assert(s);
return config_parse_many("/etc/systemd/journald.conf",
CONF_DIRS_NULSTR("systemd/journald.conf"),
"Journal\0",
config_item_perf_lookup, journald_gperf_lookup,
false, s);
}
static int server_dispatch_sync(sd_event_source *es, usec_t t, void *userdata) {
Server *s = userdata;
assert(s);
server_sync(s);
return 0;
}
int server_schedule_sync(Server *s, int priority) {
int r;
assert(s);
if (priority <= LOG_CRIT) {
/* Immediately sync to disk when this is of priority CRIT, ALERT, EMERG */
server_sync(s);
return 0;
}
if (s->sync_scheduled)
return 0;
if (s->sync_interval_usec > 0) {
usec_t when;
r = sd_event_now(s->event, CLOCK_MONOTONIC, &when);
if (r < 0)
return r;
when += s->sync_interval_usec;
if (!s->sync_event_source) {
r = sd_event_add_time(
s->event,
&s->sync_event_source,
CLOCK_MONOTONIC,
when, 0,
server_dispatch_sync, s);
if (r < 0)
return r;
r = sd_event_source_set_priority(s->sync_event_source, SD_EVENT_PRIORITY_IMPORTANT);
} else {
r = sd_event_source_set_time(s->sync_event_source, when);
if (r < 0)
return r;
r = sd_event_source_set_enabled(s->sync_event_source, SD_EVENT_ONESHOT);
}
if (r < 0)
return r;
s->sync_scheduled = true;
}
return 0;
}
static int dispatch_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
Server *s = userdata;
assert(s);
server_cache_hostname(s);
return 0;
}
static int server_open_hostname(Server *s) {
int r;
assert(s);
s->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY);
if (s->hostname_fd < 0)
return log_error_errno(errno, "Failed to open /proc/sys/kernel/hostname: %m");
r = sd_event_add_io(s->event, &s->hostname_event_source, s->hostname_fd, 0, dispatch_hostname_change, s);
if (r < 0) {
/* kernels prior to 3.2 don't support polling this file. Ignore
* the failure. */
if (r == -EPERM) {
log_warning("Failed to register hostname fd in event loop: %s. Ignoring.",
strerror(-r));
s->hostname_fd = safe_close(s->hostname_fd);
return 0;
}
return log_error_errno(r, "Failed to register hostname fd in event loop: %m");
}
r = sd_event_source_set_priority(s->hostname_event_source, SD_EVENT_PRIORITY_IMPORTANT-10);
if (r < 0)
return log_error_errno(r, "Failed to adjust priority of host name event source: %m");
return 0;
}
int server_init(Server *s) {
int n, r, fd;
assert(s);
zero(*s);
s->syslog_fd = s->native_fd = s->stdout_fd = s->dev_kmsg_fd = s->audit_fd = s->hostname_fd = -1;
s->compress = true;
s->seal = true;
s->sync_interval_usec = DEFAULT_SYNC_INTERVAL_USEC;
s->sync_scheduled = false;
s->rate_limit_interval = DEFAULT_RATE_LIMIT_INTERVAL;
s->rate_limit_burst = DEFAULT_RATE_LIMIT_BURST;
s->forward_to_wall = true;
s->max_file_usec = DEFAULT_MAX_FILE_USEC;
s->max_level_store = LOG_DEBUG;
s->max_level_syslog = LOG_DEBUG;
s->max_level_kmsg = LOG_NOTICE;
s->max_level_console = LOG_INFO;
s->max_level_wall = LOG_EMERG;
memset(&s->system_metrics, 0xFF, sizeof(s->system_metrics));
memset(&s->runtime_metrics, 0xFF, sizeof(s->runtime_metrics));
server_parse_config_file(s);
server_parse_proc_cmdline(s);
if (!!s->rate_limit_interval ^ !!s->rate_limit_burst) {
log_debug("Setting both rate limit interval and burst from "USEC_FMT",%u to 0,0",
s->rate_limit_interval, s->rate_limit_burst);
s->rate_limit_interval = s->rate_limit_burst = 0;
}
mkdir_p("/run/systemd/journal", 0755);
s->user_journals = ordered_hashmap_new(NULL);
if (!s->user_journals)
return log_oom();
s->mmap = mmap_cache_new();
if (!s->mmap)
return log_oom();
r = sd_event_default(&s->event);
if (r < 0)
return log_error_errno(r, "Failed to create event loop: %m");
sd_event_set_watchdog(s->event, true);
n = sd_listen_fds(true);
if (n < 0)
return log_error_errno(n, "Failed to read listening file descriptors from environment: %m");
for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) {
if (sd_is_socket_unix(fd, SOCK_DGRAM, -1, "/run/systemd/journal/socket", 0) > 0) {
if (s->native_fd >= 0) {
log_error("Too many native sockets passed.");
return -EINVAL;
}
s->native_fd = fd;
} else if (sd_is_socket_unix(fd, SOCK_STREAM, 1, "/run/systemd/journal/stdout", 0) > 0) {
if (s->stdout_fd >= 0) {
log_error("Too many stdout sockets passed.");
return -EINVAL;
}
s->stdout_fd = fd;
} else if (sd_is_socket_unix(fd, SOCK_DGRAM, -1, "/dev/log", 0) > 0 ||
sd_is_socket_unix(fd, SOCK_DGRAM, -1, "/run/systemd/journal/dev-log", 0) > 0) {
if (s->syslog_fd >= 0) {
log_error("Too many /dev/log sockets passed.");
return -EINVAL;
}
s->syslog_fd = fd;
} else if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1) > 0) {
if (s->audit_fd >= 0) {
log_error("Too many audit sockets passed.");
return -EINVAL;
}
s->audit_fd = fd;
} else {
log_warning("Unknown socket passed as file descriptor %d, ignoring.", fd);
/* Let's close the fd, better be safe than
sorry. The fd might reference some resource
that we really want to release if we don't
make use of it. */
safe_close(fd);
}
}
r = server_open_syslog_socket(s);
if (r < 0)
return r;
r = server_open_native_socket(s);
if (r < 0)
return r;
r = server_open_stdout_socket(s);
if (r < 0)
return r;
r = server_open_dev_kmsg(s);
if (r < 0)
return r;
r = server_open_audit(s);
if (r < 0)
return r;
r = server_open_kernel_seqnum(s);
if (r < 0)
return r;
r = server_open_hostname(s);
if (r < 0)
return r;
r = setup_signals(s);
if (r < 0)
return r;
s->udev = udev_new();
if (!s->udev)
return -ENOMEM;
s->rate_limit = journal_rate_limit_new(s->rate_limit_interval, s->rate_limit_burst);
if (!s->rate_limit)
return -ENOMEM;
r = cg_get_root_path(&s->cgroup_root);
if (r < 0)
return r;
server_cache_hostname(s);
server_cache_boot_id(s);
server_cache_machine_id(s);
r = system_journal_open(s, false);
if (r < 0)
return r;
return 0;
}
void server_maybe_append_tags(Server *s) {
#ifdef HAVE_GCRYPT
JournalFile *f;
Iterator i;
usec_t n;
n = now(CLOCK_REALTIME);
if (s->system_journal)
journal_file_maybe_append_tag(s->system_journal, n);
ORDERED_HASHMAP_FOREACH(f, s->user_journals, i)
journal_file_maybe_append_tag(f, n);
#endif
}
void server_done(Server *s) {
JournalFile *f;
assert(s);
while (s->stdout_streams)
stdout_stream_free(s->stdout_streams);
if (s->system_journal)
journal_file_close(s->system_journal);
if (s->runtime_journal)
journal_file_close(s->runtime_journal);
while ((f = ordered_hashmap_steal_first(s->user_journals)))
journal_file_close(f);
ordered_hashmap_free(s->user_journals);
sd_event_source_unref(s->syslog_event_source);
sd_event_source_unref(s->native_event_source);
sd_event_source_unref(s->stdout_event_source);
sd_event_source_unref(s->dev_kmsg_event_source);
sd_event_source_unref(s->audit_event_source);
sd_event_source_unref(s->sync_event_source);
sd_event_source_unref(s->sigusr1_event_source);
sd_event_source_unref(s->sigusr2_event_source);
sd_event_source_unref(s->sigterm_event_source);
sd_event_source_unref(s->sigint_event_source);
sd_event_source_unref(s->hostname_event_source);
sd_event_unref(s->event);
safe_close(s->syslog_fd);
safe_close(s->native_fd);
safe_close(s->stdout_fd);
safe_close(s->dev_kmsg_fd);
safe_close(s->audit_fd);
safe_close(s->hostname_fd);
if (s->rate_limit)
journal_rate_limit_free(s->rate_limit);
if (s->kernel_seqnum)
munmap(s->kernel_seqnum, sizeof(uint64_t));
free(s->buffer);
free(s->tty_path);
free(s->cgroup_root);
free(s->hostname_field);
if (s->mmap)
mmap_cache_unref(s->mmap);
if (s->udev)
udev_unref(s->udev);
}