journald: move several configuration related definitions to journald-config.[ch]
No functional change, just refactoring and preparation for later changes.
This commit is contained in:
@@ -0,0 +1,513 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "sd-event.h"
|
||||
|
||||
#include "conf-parser.h"
|
||||
#include "creds-util.h"
|
||||
#include "daemon-util.h"
|
||||
#include "journald-config.h"
|
||||
#include "journald-kmsg.h"
|
||||
#include "journald-manager.h"
|
||||
#include "log.h"
|
||||
#include "parse-util.h"
|
||||
#include "proc-cmdline.h"
|
||||
#include "socket-netlink.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "syslog-util.h"
|
||||
#include "time-util.h"
|
||||
|
||||
#define DEFAULT_SYNC_INTERVAL_USEC (5*USEC_PER_MINUTE)
|
||||
#define DEFAULT_RATE_LIMIT_INTERVAL (30*USEC_PER_SEC)
|
||||
#define DEFAULT_RATE_LIMIT_BURST 10000
|
||||
#define DEFAULT_MAX_FILE_USEC USEC_PER_MONTH
|
||||
|
||||
/* Pick a good default that is likely to fit into AF_UNIX and AF_INET SOCK_DGRAM datagrams, and even leaves some room
|
||||
* for a bit of additional metadata. */
|
||||
#define DEFAULT_LINE_MAX (48*1024)
|
||||
|
||||
#define JOURNAL_CONFIG_INIT \
|
||||
(JournalConfig) { \
|
||||
.forward_to_socket = (SocketAddress) { .sockaddr.sa.sa_family = AF_UNSPEC }, \
|
||||
.storage = _STORAGE_INVALID, \
|
||||
.max_level_store = -1, \
|
||||
.max_level_syslog = -1, \
|
||||
.max_level_kmsg = -1, \
|
||||
.max_level_console = -1, \
|
||||
.max_level_wall = -1, \
|
||||
.max_level_socket = -1, \
|
||||
}
|
||||
|
||||
static void manager_set_defaults(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
m->compress.enabled = true;
|
||||
m->compress.threshold_bytes = UINT64_MAX;
|
||||
|
||||
m->seal = true;
|
||||
|
||||
/* By default, only read from /dev/kmsg if are the main namespace */
|
||||
m->read_kmsg = !m->namespace;
|
||||
|
||||
m->set_audit = true;
|
||||
|
||||
m->sync_interval_usec = DEFAULT_SYNC_INTERVAL_USEC;
|
||||
|
||||
m->ratelimit_interval = DEFAULT_RATE_LIMIT_INTERVAL;
|
||||
m->ratelimit_burst = DEFAULT_RATE_LIMIT_BURST;
|
||||
|
||||
m->system_storage.name = "System Journal";
|
||||
journal_reset_metrics(&m->system_storage.metrics);
|
||||
|
||||
m->runtime_storage.name = "Runtime Journal";
|
||||
journal_reset_metrics(&m->runtime_storage.metrics);
|
||||
|
||||
m->max_file_usec = DEFAULT_MAX_FILE_USEC;
|
||||
|
||||
m->config.forward_to_wall = true;
|
||||
|
||||
m->config.max_level_store = LOG_DEBUG;
|
||||
m->config.max_level_syslog = LOG_DEBUG;
|
||||
m->config.max_level_kmsg = LOG_NOTICE;
|
||||
m->config.max_level_console = LOG_INFO;
|
||||
m->config.max_level_wall = LOG_EMERG;
|
||||
m->config.max_level_socket = LOG_DEBUG;
|
||||
|
||||
m->line_max = DEFAULT_LINE_MAX;
|
||||
}
|
||||
|
||||
static void manager_reset_configs(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
m->config_by_cmdline = JOURNAL_CONFIG_INIT;
|
||||
m->config_by_conf = JOURNAL_CONFIG_INIT;
|
||||
m->config_by_cred = JOURNAL_CONFIG_INIT;
|
||||
}
|
||||
|
||||
static void manager_merge_forward_to_socket(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
/* Conf file takes precedence over credentials. */
|
||||
if (m->config_by_conf.forward_to_socket.sockaddr.sa.sa_family != AF_UNSPEC)
|
||||
m->config.forward_to_socket = m->config_by_conf.forward_to_socket;
|
||||
else if (m->config_by_cred.forward_to_socket.sockaddr.sa.sa_family != AF_UNSPEC)
|
||||
m->config.forward_to_socket = m->config_by_cred.forward_to_socket;
|
||||
else
|
||||
m->config.forward_to_socket = (SocketAddress) { .sockaddr.sa.sa_family = AF_UNSPEC };
|
||||
}
|
||||
|
||||
static void manager_merge_storage(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
/* Conf file takes precedence over credentials. */
|
||||
if (m->config_by_conf.storage != _STORAGE_INVALID)
|
||||
m->config.storage = m->config_by_conf.storage;
|
||||
else if (m->config_by_cred.storage != _STORAGE_INVALID)
|
||||
m->config.storage = m->config_by_cred.storage;
|
||||
else
|
||||
m->config.storage = m->namespace ? STORAGE_PERSISTENT : STORAGE_AUTO;
|
||||
}
|
||||
|
||||
#define MERGE_BOOL(name, default_value) \
|
||||
(m->config.name = (m->config_by_cmdline.name ? m->config_by_cmdline.name : \
|
||||
m->config_by_conf.name ? m->config_by_conf.name : \
|
||||
m->config_by_cred.name ? m->config_by_cred.name : \
|
||||
default_value))
|
||||
|
||||
#define MERGE_NON_NEGATIVE(name, default_value) \
|
||||
(m->config.name = (m->config_by_cmdline.name >= 0 ? m->config_by_cmdline.name : \
|
||||
m->config_by_conf.name >= 0 ? m->config_by_conf.name : \
|
||||
m->config_by_cred.name >= 0 ? m->config_by_cred.name : \
|
||||
default_value))
|
||||
|
||||
static void manager_merge_configs(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
/*
|
||||
* From highest to lowest priority: cmdline, conf, cred
|
||||
*/
|
||||
manager_merge_storage(m);
|
||||
manager_merge_forward_to_socket(m);
|
||||
|
||||
MERGE_BOOL(forward_to_syslog, false);
|
||||
MERGE_BOOL(forward_to_kmsg, false);
|
||||
MERGE_BOOL(forward_to_console, false);
|
||||
MERGE_BOOL(forward_to_wall, true);
|
||||
|
||||
MERGE_NON_NEGATIVE(max_level_store, LOG_DEBUG);
|
||||
MERGE_NON_NEGATIVE(max_level_syslog, LOG_DEBUG);
|
||||
MERGE_NON_NEGATIVE(max_level_kmsg, LOG_NOTICE);
|
||||
MERGE_NON_NEGATIVE(max_level_console, LOG_INFO);
|
||||
MERGE_NON_NEGATIVE(max_level_wall, LOG_EMERG);
|
||||
MERGE_NON_NEGATIVE(max_level_socket, LOG_DEBUG);
|
||||
}
|
||||
|
||||
static void manager_adjust_configs(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
if (!!m->ratelimit_interval != !!m->ratelimit_burst) { /* One set to 0 and the other not? */
|
||||
log_debug("Setting both rate limit interval and burst from %s/%u to 0/0",
|
||||
FORMAT_TIMESPAN(m->ratelimit_interval, USEC_PER_SEC),
|
||||
m->ratelimit_burst);
|
||||
m->ratelimit_interval = m->ratelimit_burst = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
|
||||
Manager *m = ASSERT_PTR(data);
|
||||
int r;
|
||||
|
||||
if (proc_cmdline_key_streq(key, "systemd.journald.forward_to_syslog")) {
|
||||
|
||||
r = value ? parse_boolean(value) : true;
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse forward to syslog switch \"%s\". Ignoring.", value);
|
||||
else
|
||||
m->config_by_cmdline.forward_to_syslog = r;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.forward_to_kmsg")) {
|
||||
|
||||
r = value ? parse_boolean(value) : true;
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse forward to kmsg switch \"%s\". Ignoring.", value);
|
||||
else
|
||||
m->config_by_cmdline.forward_to_kmsg = r;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.forward_to_console")) {
|
||||
|
||||
r = value ? parse_boolean(value) : true;
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse forward to console switch \"%s\". Ignoring.", value);
|
||||
else
|
||||
m->config_by_cmdline.forward_to_console = r;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.forward_to_wall")) {
|
||||
|
||||
r = value ? parse_boolean(value) : true;
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse forward to wall switch \"%s\". Ignoring.", value);
|
||||
else
|
||||
m->config_by_cmdline.forward_to_wall = r;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_console")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
r = log_level_from_string(value);
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse max level console value \"%s\". Ignoring.", value);
|
||||
else
|
||||
m->config_by_cmdline.max_level_console = r;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_store")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
r = log_level_from_string(value);
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse max level store value \"%s\". Ignoring.", value);
|
||||
else
|
||||
m->config_by_cmdline.max_level_store = r;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_syslog")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
r = log_level_from_string(value);
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse max level syslog value \"%s\". Ignoring.", value);
|
||||
else
|
||||
m->config_by_cmdline.max_level_syslog = r;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_kmsg")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
r = log_level_from_string(value);
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse max level kmsg value \"%s\". Ignoring.", value);
|
||||
else
|
||||
m->config_by_cmdline.max_level_kmsg = r;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_wall")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
r = log_level_from_string(value);
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse max level wall value \"%s\". Ignoring.", value);
|
||||
else
|
||||
m->config_by_cmdline.max_level_wall = r;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_socket")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
r = log_level_from_string(value);
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse max level socket value \"%s\". Ignoring.", value);
|
||||
else
|
||||
m->config_by_cmdline.max_level_socket = r;
|
||||
|
||||
} else if (startswith(key, "systemd.journald"))
|
||||
log_warning("Unknown journald kernel command line option \"%s\". Ignoring.", key);
|
||||
|
||||
/* do not warn about state here, since probably systemd already did */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void manager_parse_config_file(Manager *m) {
|
||||
const char *conf_file;
|
||||
|
||||
assert(m);
|
||||
|
||||
if (m->namespace)
|
||||
conf_file = strjoina("systemd/journald@", m->namespace, ".conf");
|
||||
else
|
||||
conf_file = "systemd/journald.conf";
|
||||
|
||||
(void) config_parse_standard_file_with_dropins(
|
||||
conf_file,
|
||||
"Journal\0",
|
||||
config_item_perf_lookup,
|
||||
journald_gperf_lookup,
|
||||
CONFIG_PARSE_WARN,
|
||||
m);
|
||||
}
|
||||
|
||||
static void manager_load_credentials(Manager *m) {
|
||||
_cleanup_free_ void *data = NULL;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
r = read_credential("journal.forward_to_socket", &data, NULL);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to read credential journal.forward_to_socket, ignoring: %m");
|
||||
else {
|
||||
r = socket_address_parse(&m->config_by_cred.forward_to_socket, data);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to parse socket address '%s' from credential journal.forward_to_socket, ignoring: %m", (char *) data);
|
||||
}
|
||||
|
||||
data = mfree(data);
|
||||
|
||||
r = read_credential("journal.storage", &data, NULL);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to read credential journal.storage, ignoring: %m");
|
||||
else {
|
||||
r = storage_from_string(data);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to parse storage '%s' from credential journal.storage, ignoring: %m", (char *) data);
|
||||
else
|
||||
m->config_by_cred.storage = r;
|
||||
}
|
||||
}
|
||||
|
||||
void manager_load_config(Manager *m) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
manager_set_defaults(m);
|
||||
manager_reset_configs(m);
|
||||
|
||||
manager_load_credentials(m);
|
||||
manager_parse_config_file(m);
|
||||
|
||||
if (!m->namespace) {
|
||||
/* Parse kernel command line, but only if we are not a namespace instance */
|
||||
r = proc_cmdline_parse(parse_proc_cmdline_item, m, PROC_CMDLINE_STRIP_RD_PREFIX);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
|
||||
}
|
||||
|
||||
manager_merge_configs(m);
|
||||
|
||||
manager_adjust_configs(m);
|
||||
}
|
||||
|
||||
static void manager_reload_config(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
manager_set_defaults(m);
|
||||
|
||||
m->config_by_conf = JOURNAL_CONFIG_INIT;
|
||||
manager_parse_config_file(m);
|
||||
|
||||
manager_merge_configs(m);
|
||||
manager_adjust_configs(m);
|
||||
}
|
||||
|
||||
int manager_dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
|
||||
Manager *m = ASSERT_PTR(userdata);
|
||||
int r;
|
||||
|
||||
(void) notify_reloading();
|
||||
|
||||
manager_reload_config(m);
|
||||
|
||||
r = manager_reload_dev_kmsg(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = manager_reload_journals(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
log_info("Config file reloaded.");
|
||||
(void) sd_notify(/* unset_environment */ false, NOTIFY_READY_MESSAGE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* const storage_table[_STORAGE_MAX] = {
|
||||
[STORAGE_AUTO] = "auto",
|
||||
[STORAGE_VOLATILE] = "volatile",
|
||||
[STORAGE_PERSISTENT] = "persistent",
|
||||
[STORAGE_NONE] = "none"
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(storage, Storage);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_storage, storage, Storage);
|
||||
|
||||
static const char* const split_mode_table[_SPLIT_MAX] = {
|
||||
[SPLIT_LOGIN] = "login",
|
||||
[SPLIT_UID] = "uid",
|
||||
[SPLIT_NONE] = "none",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(split_mode, SplitMode);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_split_mode, split_mode, SplitMode);
|
||||
|
||||
int config_parse_line_max(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
size_t *sz = ASSERT_PTR(data);
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue))
|
||||
/* Empty assignment means default */
|
||||
*sz = DEFAULT_LINE_MAX;
|
||||
else {
|
||||
uint64_t v;
|
||||
|
||||
r = parse_size(rvalue, 1024, &v);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse LineMax= value, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (v < 79) {
|
||||
/* Why specify 79 here as minimum line length? Simply, because the most common traditional
|
||||
* terminal size is 80ch, and it might make sense to break one character before the natural
|
||||
* line break would occur on that. */
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0, "LineMax= too small, clamping to 79: %s", rvalue);
|
||||
*sz = 79;
|
||||
} else if (v > (uint64_t) (SSIZE_MAX-1)) {
|
||||
/* So, why specify SSIZE_MAX-1 here? Because that's one below the largest size value read()
|
||||
* can return, and we need one extra byte for the trailing NUL byte. Of course IRL such large
|
||||
* memory allocations will fail anyway, hence this limit is mostly theoretical anyway, as we'll
|
||||
* fail much earlier anyway. */
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0, "LineMax= too large, clamping to %" PRIu64 ": %s", (uint64_t) (SSIZE_MAX-1), rvalue);
|
||||
*sz = SSIZE_MAX-1;
|
||||
} else
|
||||
*sz = (size_t) v;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_compress(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
JournalCompressOptions* compress = ASSERT_PTR(data);
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
compress->enabled = true;
|
||||
compress->threshold_bytes = UINT64_MAX;
|
||||
} else if (streq(rvalue, "1")) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"Compress= ambiguously specified as 1, enabling compression with default threshold");
|
||||
compress->enabled = true;
|
||||
} else if (streq(rvalue, "0")) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"Compress= ambiguously specified as 0, disabling compression");
|
||||
compress->enabled = false;
|
||||
} else {
|
||||
r = parse_boolean(rvalue);
|
||||
if (r < 0) {
|
||||
r = parse_size(rvalue, 1024, &compress->threshold_bytes);
|
||||
if (r < 0)
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to parse Compress= value, ignoring: %s", rvalue);
|
||||
else
|
||||
compress->enabled = true;
|
||||
} else
|
||||
compress->enabled = r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_forward_to_socket(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
SocketAddress* addr = ASSERT_PTR(data);
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue))
|
||||
*addr = (SocketAddress) { .sockaddr.sa.sa_family = AF_UNSPEC };
|
||||
else {
|
||||
r = socket_address_parse(addr, rvalue);
|
||||
if (r < 0)
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to parse ForwardToSocket= value, ignoring: %s", rvalue);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "journald-forward.h"
|
||||
#include "socket-util.h"
|
||||
|
||||
typedef enum Storage {
|
||||
STORAGE_AUTO,
|
||||
STORAGE_VOLATILE,
|
||||
STORAGE_PERSISTENT,
|
||||
STORAGE_NONE,
|
||||
_STORAGE_MAX,
|
||||
_STORAGE_INVALID = -EINVAL,
|
||||
} Storage;
|
||||
|
||||
typedef enum SplitMode {
|
||||
SPLIT_UID,
|
||||
SPLIT_LOGIN, /* deprecated */
|
||||
SPLIT_NONE,
|
||||
_SPLIT_MAX,
|
||||
_SPLIT_INVALID = -EINVAL,
|
||||
} SplitMode;
|
||||
|
||||
typedef struct JournalCompressOptions {
|
||||
bool enabled;
|
||||
uint64_t threshold_bytes;
|
||||
} JournalCompressOptions;
|
||||
|
||||
typedef struct JournalConfig {
|
||||
Storage storage;
|
||||
|
||||
bool forward_to_kmsg;
|
||||
bool forward_to_syslog;
|
||||
bool forward_to_console;
|
||||
bool forward_to_wall;
|
||||
|
||||
SocketAddress forward_to_socket;
|
||||
|
||||
int max_level_store;
|
||||
int max_level_syslog;
|
||||
int max_level_kmsg;
|
||||
int max_level_console;
|
||||
int max_level_wall;
|
||||
int max_level_socket;
|
||||
} JournalConfig;
|
||||
|
||||
void manager_load_config(Manager *m);
|
||||
int manager_dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata);
|
||||
|
||||
/* Defined in generated journald-gperf.c */
|
||||
const struct ConfigPerfItem* journald_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
|
||||
|
||||
const char* storage_to_string(Storage s) _const_;
|
||||
Storage storage_from_string(const char *s) _pure_;
|
||||
|
||||
const char* split_mode_to_string(SplitMode s) _const_;
|
||||
SplitMode split_mode_from_string(const char *s) _pure_;
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_storage);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_line_max);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_compress);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_forward_to_socket);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_split_mode);
|
||||
@@ -4,6 +4,11 @@
|
||||
#include "conf-parser-forward.h" /* IWYU pragma: export */
|
||||
#include "forward.h" /* IWYU pragma: export */
|
||||
|
||||
typedef enum Storage Storage;
|
||||
typedef enum SplitMode SplitMode;
|
||||
typedef struct JournalCompressOptions JournalCompressOptions;
|
||||
typedef struct JournalConfig JournalConfig;
|
||||
|
||||
typedef struct Manager Manager;
|
||||
typedef struct StreamSyncReq StreamSyncReq;
|
||||
typedef struct SyncReq SyncReq;
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "journal-internal.h"
|
||||
#include "journal-vacuum.h"
|
||||
#include "journald-audit.h"
|
||||
#include "journald-config.h"
|
||||
#include "journald-context.h"
|
||||
#include "journald-kmsg.h"
|
||||
#include "journald-manager.h"
|
||||
@@ -55,7 +56,6 @@
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "prioq.h"
|
||||
#include "proc-cmdline.h"
|
||||
#include "process-util.h"
|
||||
#include "rm-rf.h"
|
||||
#include "set.h"
|
||||
@@ -63,7 +63,6 @@
|
||||
#include "socket-netlink.h"
|
||||
#include "socket-util.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "syslog-util.h"
|
||||
@@ -73,11 +72,6 @@
|
||||
|
||||
#define USER_JOURNALS_MAX 1024
|
||||
|
||||
#define DEFAULT_SYNC_INTERVAL_USEC (5*USEC_PER_MINUTE)
|
||||
#define DEFAULT_RATE_LIMIT_INTERVAL (30*USEC_PER_SEC)
|
||||
#define DEFAULT_RATE_LIMIT_BURST 10000
|
||||
#define DEFAULT_MAX_FILE_USEC USEC_PER_MONTH
|
||||
|
||||
#define DEFAULT_KMSG_OWN_INTERVAL (5 * USEC_PER_SEC)
|
||||
#define DEFAULT_KMSG_OWN_BURST 50
|
||||
|
||||
@@ -88,10 +82,6 @@
|
||||
/* The period to insert between posting changes for coalescing */
|
||||
#define POST_CHANGE_TIMER_INTERVAL_USEC (250*USEC_PER_MSEC)
|
||||
|
||||
/* Pick a good default that is likely to fit into AF_UNIX and AF_INET SOCK_DGRAM datagrams, and even leaves some room
|
||||
* for a bit of additional metadata. */
|
||||
#define DEFAULT_LINE_MAX (48*1024)
|
||||
|
||||
#define DEFERRED_CLOSES_MAX (4096)
|
||||
|
||||
#define IDLE_TIMEOUT_USEC (30*USEC_PER_SEC)
|
||||
@@ -100,7 +90,6 @@
|
||||
|
||||
static int manager_schedule_sync(Manager *m, int priority);
|
||||
static int manager_refresh_idle_timer(Manager *m);
|
||||
static int dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata);
|
||||
|
||||
static int manager_determine_path_usage(
|
||||
Manager *m,
|
||||
@@ -1863,140 +1852,13 @@ static int manager_setup_signals(Manager *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_event_add_signal(m->event, NULL, SIGHUP|SD_EVENT_SIGNAL_PROCMASK, dispatch_reload_signal, m);
|
||||
r = sd_event_add_signal(m->event, NULL, SIGHUP|SD_EVENT_SIGNAL_PROCMASK, manager_dispatch_reload_signal, m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
|
||||
Manager *m = ASSERT_PTR(data);
|
||||
int r;
|
||||
|
||||
if (proc_cmdline_key_streq(key, "systemd.journald.forward_to_syslog")) {
|
||||
|
||||
r = value ? parse_boolean(value) : true;
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse forward to syslog switch \"%s\". Ignoring.", value);
|
||||
else
|
||||
m->config_by_cmdline.forward_to_syslog = r;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.forward_to_kmsg")) {
|
||||
|
||||
r = value ? parse_boolean(value) : true;
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse forward to kmsg switch \"%s\". Ignoring.", value);
|
||||
else
|
||||
m->config_by_cmdline.forward_to_kmsg = r;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.forward_to_console")) {
|
||||
|
||||
r = value ? parse_boolean(value) : true;
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse forward to console switch \"%s\". Ignoring.", value);
|
||||
else
|
||||
m->config_by_cmdline.forward_to_console = r;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.forward_to_wall")) {
|
||||
|
||||
r = value ? parse_boolean(value) : true;
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse forward to wall switch \"%s\". Ignoring.", value);
|
||||
else
|
||||
m->config_by_cmdline.forward_to_wall = r;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_console")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
r = log_level_from_string(value);
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse max level console value \"%s\". Ignoring.", value);
|
||||
else
|
||||
m->config_by_cmdline.max_level_console = r;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_store")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
r = log_level_from_string(value);
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse max level store value \"%s\". Ignoring.", value);
|
||||
else
|
||||
m->config_by_cmdline.max_level_store = r;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_syslog")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
r = log_level_from_string(value);
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse max level syslog value \"%s\". Ignoring.", value);
|
||||
else
|
||||
m->config_by_cmdline.max_level_syslog = r;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_kmsg")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
r = log_level_from_string(value);
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse max level kmsg value \"%s\". Ignoring.", value);
|
||||
else
|
||||
m->config_by_cmdline.max_level_kmsg = r;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_wall")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
r = log_level_from_string(value);
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse max level wall value \"%s\". Ignoring.", value);
|
||||
else
|
||||
m->config_by_cmdline.max_level_wall = r;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_socket")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
r = log_level_from_string(value);
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse max level socket value \"%s\". Ignoring.", value);
|
||||
else
|
||||
m->config_by_cmdline.max_level_socket = r;
|
||||
|
||||
} else if (startswith(key, "systemd.journald"))
|
||||
log_warning("Unknown journald kernel command line option \"%s\". Ignoring.", key);
|
||||
|
||||
/* do not warn about state here, since probably systemd already did */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int manager_parse_config_file(Manager *m) {
|
||||
const char *conf_file;
|
||||
|
||||
assert(m);
|
||||
|
||||
if (m->namespace)
|
||||
conf_file = strjoina("systemd/journald@", m->namespace, ".conf");
|
||||
else
|
||||
conf_file = "systemd/journald.conf";
|
||||
|
||||
return config_parse_standard_file_with_dropins(
|
||||
conf_file,
|
||||
"Journal\0",
|
||||
config_item_perf_lookup, journald_gperf_lookup,
|
||||
CONFIG_PARSE_WARN,
|
||||
/* userdata= */ m);
|
||||
}
|
||||
|
||||
static int manager_dispatch_sync(sd_event_source *es, usec_t t, void *userdata) {
|
||||
Manager *m = ASSERT_PTR(userdata);
|
||||
|
||||
@@ -2392,187 +2254,7 @@ static int manager_setup_memory_pressure(Manager *m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void manager_load_credentials(Manager *m) {
|
||||
_cleanup_free_ void *data = NULL;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
r = read_credential("journal.forward_to_socket", &data, NULL);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to read credential journal.forward_to_socket, ignoring: %m");
|
||||
else {
|
||||
r = socket_address_parse(&m->config_by_cred.forward_to_socket, data);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to parse socket address '%s' from credential journal.forward_to_socket, ignoring: %m", (char *) data);
|
||||
}
|
||||
|
||||
data = mfree(data);
|
||||
|
||||
r = read_credential("journal.storage", &data, NULL);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to read credential journal.storage, ignoring: %m");
|
||||
else {
|
||||
r = storage_from_string(data);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to parse storage '%s' from credential journal.storage, ignoring: %m", (char *) data);
|
||||
else
|
||||
m->config_by_cred.storage = r;
|
||||
}
|
||||
}
|
||||
|
||||
static void manager_set_defaults(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
m->compress.enabled = true;
|
||||
m->compress.threshold_bytes = UINT64_MAX;
|
||||
|
||||
m->seal = true;
|
||||
|
||||
/* By default, only read from /dev/kmsg if are the main namespace */
|
||||
m->read_kmsg = !m->namespace;
|
||||
|
||||
m->set_audit = true;
|
||||
|
||||
m->sync_interval_usec = DEFAULT_SYNC_INTERVAL_USEC;
|
||||
|
||||
m->ratelimit_interval = DEFAULT_RATE_LIMIT_INTERVAL;
|
||||
m->ratelimit_burst = DEFAULT_RATE_LIMIT_BURST;
|
||||
|
||||
m->system_storage.name = "System Journal";
|
||||
journal_reset_metrics(&m->system_storage.metrics);
|
||||
|
||||
m->runtime_storage.name = "Runtime Journal";
|
||||
journal_reset_metrics(&m->runtime_storage.metrics);
|
||||
|
||||
m->max_file_usec = DEFAULT_MAX_FILE_USEC;
|
||||
|
||||
m->config.forward_to_wall = true;
|
||||
|
||||
m->config.max_level_store = LOG_DEBUG;
|
||||
m->config.max_level_syslog = LOG_DEBUG;
|
||||
m->config.max_level_kmsg = LOG_NOTICE;
|
||||
m->config.max_level_console = LOG_INFO;
|
||||
m->config.max_level_wall = LOG_EMERG;
|
||||
m->config.max_level_socket = LOG_DEBUG;
|
||||
|
||||
m->line_max = DEFAULT_LINE_MAX;
|
||||
}
|
||||
|
||||
static void manager_reset_configs(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
m->config_by_cmdline = JOURNAL_CONFIG_INIT;
|
||||
m->config_by_conf = JOURNAL_CONFIG_INIT;
|
||||
m->config_by_cred = JOURNAL_CONFIG_INIT;
|
||||
}
|
||||
|
||||
static void manager_adjust_configs(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
if (!!m->ratelimit_interval != !!m->ratelimit_burst) { /* One set to 0 and the other not? */
|
||||
log_debug(
|
||||
"Setting both rate limit interval and burst from %s/%u to 0/0",
|
||||
FORMAT_TIMESPAN(m->ratelimit_interval, USEC_PER_SEC),
|
||||
m->ratelimit_burst);
|
||||
m->ratelimit_interval = m->ratelimit_burst = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void manager_merge_forward_to_socket(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
/* Conf file takes precedence over credentials. */
|
||||
if (m->config_by_conf.forward_to_socket.sockaddr.sa.sa_family != AF_UNSPEC)
|
||||
m->config.forward_to_socket = m->config_by_conf.forward_to_socket;
|
||||
else if (m->config_by_cred.forward_to_socket.sockaddr.sa.sa_family != AF_UNSPEC)
|
||||
m->config.forward_to_socket = m->config_by_cred.forward_to_socket;
|
||||
else
|
||||
m->config.forward_to_socket = (SocketAddress) { .sockaddr.sa.sa_family = AF_UNSPEC };
|
||||
}
|
||||
|
||||
static void manager_merge_storage(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
/* Conf file takes precedence over credentials. */
|
||||
if (m->config_by_conf.storage != _STORAGE_INVALID)
|
||||
m->config.storage = m->config_by_conf.storage;
|
||||
else if (m->config_by_cred.storage != _STORAGE_INVALID)
|
||||
m->config.storage = m->config_by_cred.storage;
|
||||
else
|
||||
m->config.storage = m->namespace ? STORAGE_PERSISTENT : STORAGE_AUTO;
|
||||
}
|
||||
|
||||
#define MERGE_BOOL(name, default_value) \
|
||||
(m->config.name = (m->config_by_cmdline.name ? m->config_by_cmdline.name : \
|
||||
m->config_by_conf.name ? m->config_by_conf.name : \
|
||||
m->config_by_cred.name ? m->config_by_cred.name : \
|
||||
default_value))
|
||||
|
||||
#define MERGE_NON_NEGATIVE(name, default_value) \
|
||||
(m->config.name = (m->config_by_cmdline.name >= 0 ? m->config_by_cmdline.name : \
|
||||
m->config_by_conf.name >= 0 ? m->config_by_conf.name : \
|
||||
m->config_by_cred.name >= 0 ? m->config_by_cred.name : \
|
||||
default_value))
|
||||
|
||||
static void manager_merge_configs(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
/*
|
||||
* From highest to lowest priority: cmdline, conf, cred
|
||||
*/
|
||||
manager_merge_storage(m);
|
||||
manager_merge_forward_to_socket(m);
|
||||
|
||||
MERGE_BOOL(forward_to_syslog, false);
|
||||
MERGE_BOOL(forward_to_kmsg, false);
|
||||
MERGE_BOOL(forward_to_console, false);
|
||||
MERGE_BOOL(forward_to_wall, true);
|
||||
|
||||
MERGE_NON_NEGATIVE(max_level_store, LOG_DEBUG);
|
||||
MERGE_NON_NEGATIVE(max_level_syslog, LOG_DEBUG);
|
||||
MERGE_NON_NEGATIVE(max_level_kmsg, LOG_NOTICE);
|
||||
MERGE_NON_NEGATIVE(max_level_console, LOG_INFO);
|
||||
MERGE_NON_NEGATIVE(max_level_wall, LOG_EMERG);
|
||||
MERGE_NON_NEGATIVE(max_level_socket, LOG_DEBUG);
|
||||
}
|
||||
|
||||
static void manager_load_config(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
int r;
|
||||
|
||||
manager_set_defaults(m);
|
||||
manager_reset_configs(m);
|
||||
|
||||
manager_load_credentials(m);
|
||||
manager_parse_config_file(m);
|
||||
|
||||
if (!m->namespace) {
|
||||
/* Parse kernel command line, but only if we are not a namespace instance */
|
||||
r = proc_cmdline_parse(parse_proc_cmdline_item, m, PROC_CMDLINE_STRIP_RD_PREFIX);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
|
||||
}
|
||||
|
||||
manager_merge_configs(m);
|
||||
|
||||
manager_adjust_configs(m);
|
||||
}
|
||||
|
||||
static void manager_reload_config(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
manager_set_defaults(m);
|
||||
|
||||
m->config_by_conf = JOURNAL_CONFIG_INIT;
|
||||
manager_parse_config_file(m);
|
||||
|
||||
manager_merge_configs(m);
|
||||
manager_adjust_configs(m);
|
||||
}
|
||||
|
||||
static int manager_reload_journals(Manager *m) {
|
||||
int manager_reload_journals(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
int r;
|
||||
@@ -2611,28 +2293,6 @@ static int manager_reload_journals(Manager *m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
|
||||
Manager *m = ASSERT_PTR(userdata);
|
||||
int r;
|
||||
|
||||
(void) notify_reloading();
|
||||
|
||||
manager_reload_config(m);
|
||||
|
||||
r = manager_reload_dev_kmsg(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = manager_reload_journals(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
log_info("Config file reloaded.");
|
||||
(void) sd_notify(/* unset_environment */ false, NOTIFY_READY_MESSAGE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int manager_new(Manager **ret, const char *namespace) {
|
||||
_cleanup_(manager_freep) Manager *m = NULL;
|
||||
int r;
|
||||
@@ -2967,148 +2627,3 @@ Manager* manager_free(Manager *m) {
|
||||
|
||||
return mfree(m);
|
||||
}
|
||||
|
||||
static const char* const storage_table[_STORAGE_MAX] = {
|
||||
[STORAGE_AUTO] = "auto",
|
||||
[STORAGE_VOLATILE] = "volatile",
|
||||
[STORAGE_PERSISTENT] = "persistent",
|
||||
[STORAGE_NONE] = "none"
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(storage, Storage);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_storage, storage, Storage);
|
||||
|
||||
static const char* const split_mode_table[_SPLIT_MAX] = {
|
||||
[SPLIT_LOGIN] = "login",
|
||||
[SPLIT_UID] = "uid",
|
||||
[SPLIT_NONE] = "none",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(split_mode, SplitMode);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_split_mode, split_mode, SplitMode);
|
||||
|
||||
int config_parse_line_max(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
size_t *sz = ASSERT_PTR(data);
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue))
|
||||
/* Empty assignment means default */
|
||||
*sz = DEFAULT_LINE_MAX;
|
||||
else {
|
||||
uint64_t v;
|
||||
|
||||
r = parse_size(rvalue, 1024, &v);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse LineMax= value, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (v < 79) {
|
||||
/* Why specify 79 here as minimum line length? Simply, because the most common traditional
|
||||
* terminal size is 80ch, and it might make sense to break one character before the natural
|
||||
* line break would occur on that. */
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0, "LineMax= too small, clamping to 79: %s", rvalue);
|
||||
*sz = 79;
|
||||
} else if (v > (uint64_t) (SSIZE_MAX-1)) {
|
||||
/* So, why specify SSIZE_MAX-1 here? Because that's one below the largest size value read()
|
||||
* can return, and we need one extra byte for the trailing NUL byte. Of course IRL such large
|
||||
* memory allocations will fail anyway, hence this limit is mostly theoretical anyway, as we'll
|
||||
* fail much earlier anyway. */
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0, "LineMax= too large, clamping to %" PRIu64 ": %s", (uint64_t) (SSIZE_MAX-1), rvalue);
|
||||
*sz = SSIZE_MAX-1;
|
||||
} else
|
||||
*sz = (size_t) v;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_compress(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
JournalCompressOptions* compress = ASSERT_PTR(data);
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
compress->enabled = true;
|
||||
compress->threshold_bytes = UINT64_MAX;
|
||||
} else if (streq(rvalue, "1")) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"Compress= ambiguously specified as 1, enabling compression with default threshold");
|
||||
compress->enabled = true;
|
||||
} else if (streq(rvalue, "0")) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"Compress= ambiguously specified as 0, disabling compression");
|
||||
compress->enabled = false;
|
||||
} else {
|
||||
r = parse_boolean(rvalue);
|
||||
if (r < 0) {
|
||||
r = parse_size(rvalue, 1024, &compress->threshold_bytes);
|
||||
if (r < 0)
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to parse Compress= value, ignoring: %s", rvalue);
|
||||
else
|
||||
compress->enabled = true;
|
||||
} else
|
||||
compress->enabled = r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_forward_to_socket(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
SocketAddress* addr = ASSERT_PTR(data);
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue))
|
||||
*addr = (SocketAddress) { .sockaddr.sa.sa_family = AF_UNSPEC };
|
||||
else {
|
||||
r = socket_address_parse(addr, rvalue);
|
||||
if (r < 0)
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to parse ForwardToSocket= value, ignoring: %s", rvalue);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3,33 +3,12 @@
|
||||
|
||||
#include "common-signal.h"
|
||||
#include "journal-file.h"
|
||||
#include "journald-config.h"
|
||||
#include "journald-forward.h"
|
||||
#include "list.h"
|
||||
#include "ratelimit.h"
|
||||
#include "socket-util.h"
|
||||
|
||||
typedef enum Storage {
|
||||
STORAGE_AUTO,
|
||||
STORAGE_VOLATILE,
|
||||
STORAGE_PERSISTENT,
|
||||
STORAGE_NONE,
|
||||
_STORAGE_MAX,
|
||||
_STORAGE_INVALID = -EINVAL,
|
||||
} Storage;
|
||||
|
||||
typedef enum SplitMode {
|
||||
SPLIT_UID,
|
||||
SPLIT_LOGIN, /* deprecated */
|
||||
SPLIT_NONE,
|
||||
_SPLIT_MAX,
|
||||
_SPLIT_INVALID = -EINVAL,
|
||||
} SplitMode;
|
||||
|
||||
typedef struct JournalCompressOptions {
|
||||
bool enabled;
|
||||
uint64_t threshold_bytes;
|
||||
} JournalCompressOptions;
|
||||
|
||||
typedef struct JournalStorageSpace {
|
||||
usec_t timestamp;
|
||||
|
||||
@@ -55,23 +34,6 @@ typedef struct SeqnumData {
|
||||
uint64_t seqnum;
|
||||
} SeqnumData;
|
||||
|
||||
typedef struct JournalConfig {
|
||||
SocketAddress forward_to_socket;
|
||||
Storage storage;
|
||||
|
||||
bool forward_to_kmsg;
|
||||
bool forward_to_syslog;
|
||||
bool forward_to_console;
|
||||
bool forward_to_wall;
|
||||
|
||||
int max_level_store;
|
||||
int max_level_syslog;
|
||||
int max_level_kmsg;
|
||||
int max_level_console;
|
||||
int max_level_wall;
|
||||
int max_level_socket;
|
||||
} JournalConfig;
|
||||
|
||||
typedef struct Manager {
|
||||
char *namespace;
|
||||
|
||||
@@ -188,15 +150,14 @@ typedef struct Manager {
|
||||
LIST_HEAD(SyncReq, sync_req_pending_rqlen);
|
||||
|
||||
/* These structs are used to preserve configurations set by credentials and command line.
|
||||
config - main configuration used by journald manager,
|
||||
config_by_cred - configuration set by credentials,
|
||||
config_by_conf - configuration set by configuration file,
|
||||
config_by_cmdline - configuration set by command line.
|
||||
The priority order of the sub-configurations is:
|
||||
config_by_cmdline > config_by_conf > config_by_cred
|
||||
where A > B means that if the two have the same setting,
|
||||
A's value overrides B's value for that setting.
|
||||
*/
|
||||
* - config - main configuration used by journald manager,
|
||||
* - config_by_cred - configuration set by credentials,
|
||||
* - config_by_conf - configuration set by configuration file,
|
||||
* - config_by_cmdline - configuration set by command line.
|
||||
* The priority order of the sub-configurations is:
|
||||
* config_by_cmdline > config_by_conf > config_by_cred
|
||||
* where A > B means that if the two have the same setting, A's value overrides B's value for that
|
||||
* setting. */
|
||||
JournalConfig config;
|
||||
JournalConfig config_by_cred;
|
||||
JournalConfig config_by_conf;
|
||||
@@ -227,34 +188,6 @@ void manager_dispatch_message(Manager *m, struct iovec *iovec, size_t n, size_t
|
||||
void manager_driver_message_internal(Manager *m, pid_t object_pid, const char *format, ...) _sentinel_;
|
||||
#define manager_driver_message(...) manager_driver_message_internal(__VA_ARGS__, NULL)
|
||||
|
||||
#define JOURNAL_CONFIG_INIT \
|
||||
(JournalConfig) { \
|
||||
.forward_to_socket = (SocketAddress) { .sockaddr.sa.sa_family = AF_UNSPEC }, \
|
||||
.storage = _STORAGE_INVALID, \
|
||||
.max_level_store = -1, \
|
||||
.max_level_syslog = -1, \
|
||||
.max_level_kmsg = -1, \
|
||||
.max_level_console = -1, \
|
||||
.max_level_wall = -1, \
|
||||
.max_level_socket = -1, \
|
||||
}
|
||||
|
||||
/* gperf lookup function */
|
||||
const struct ConfigPerfItem* journald_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_storage);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_line_max);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_compress);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_forward_to_socket);
|
||||
|
||||
const char* storage_to_string(Storage s) _const_;
|
||||
Storage storage_from_string(const char *s) _pure_;
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_split_mode);
|
||||
|
||||
const char* split_mode_to_string(SplitMode s) _const_;
|
||||
SplitMode split_mode_from_string(const char *s) _pure_;
|
||||
|
||||
int manager_new(Manager **ret, const char *namespace);
|
||||
int manager_init(Manager *m);
|
||||
Manager* manager_free(Manager *m);
|
||||
@@ -271,5 +204,6 @@ int manager_process_datagram(sd_event_source *es, int fd, uint32_t revents, void
|
||||
void manager_space_usage_message(Manager *m, JournalStorage *storage);
|
||||
|
||||
int manager_start_or_stop_idle_timer(Manager *m);
|
||||
int manager_reload_journals(Manager *m);
|
||||
|
||||
int manager_map_seqnum_file(Manager *m, const char *fname, size_t size, void **ret);
|
||||
|
||||
@@ -6,6 +6,7 @@ systemd_journald_sources = files(
|
||||
systemd_journald_extract_sources = files(
|
||||
'journald-audit.c',
|
||||
'journald-client.c',
|
||||
'journald-config.c',
|
||||
'journald-console.c',
|
||||
'journald-context.c',
|
||||
'journald-kmsg.c',
|
||||
|
||||
Reference in New Issue
Block a user