#include "path-util.h"
#include "process-util.h"
#include "rlimit-util.h"
+#include "sd-id128.h"
#include "signal-util.h"
#include "socket-util.h"
#include "string-util.h"
char *l,
void *userdata) {
- char *e, *include;
+ char *e;
assert(filename);
assert(line > 0);
if (*l == '\n')
return 0;
- include = first_word(l, ".include");
- if (include) {
- _cleanup_free_ char *fn = NULL;
-
- /* .includes are a bad idea, we only support them here
- * for historical reasons. They create cyclic include
- * problems and make it difficult to detect
- * configuration file changes with an easy
- * stat(). Better approaches, such as .d/ drop-in
- * snippets exist.
- *
- * Support for them should be eventually removed. */
-
- if (!(flags & CONFIG_PARSE_ALLOW_INCLUDE)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, ".include not allowed here. Ignoring.");
- return 0;
- }
-
- log_syntax(unit, LOG_WARNING, filename, line, 0,
- ".include directives are deprecated, and support for them will be removed in a future version of systemd. "
- "Please use drop-in files instead.");
-
- fn = file_in_same_dir(filename, strstrip(include));
- if (!fn)
- return -ENOMEM;
-
- return config_parse(unit, fn, NULL, sections, lookup, table, flags, userdata);
- }
-
if (!utf8_is_valid(l))
return log_syntax_invalid_utf8(unit, LOG_WARNING, filename, line, l);
ConfigItemLookup lookup,
const void *table,
ConfigParseFlags flags,
- void *userdata) {
+ void *userdata,
+ usec_t *ret_mtime) {
_cleanup_free_ char *section = NULL, *continuation = NULL;
_cleanup_fclose_ FILE *ours = NULL;
unsigned line = 0, section_line = 0;
bool section_ignored = false, bom_seen = false;
- int r;
+ int r, fd;
+ usec_t mtime;
assert(filename);
assert(lookup);
}
}
- fd_warn_permissions(filename, fileno(f));
+ fd = fileno(f);
+ if (fd >= 0) { /* stream might not have an fd, let's be careful hence */
+ struct stat st;
+
+ if (fstat(fd, &st) < 0)
+ return log_full_errno(FLAGS_SET(flags, CONFIG_PARSE_WARN) ? LOG_ERR : LOG_DEBUG, errno,
+ "Failed to fstat(%s): %m", filename);
+
+ (void) stat_warn_permissions(filename, &st);
+ mtime = timespec_load(&st.st_mtim);
+ }
for (;;) {
_cleanup_free_ char *buf = NULL;
return r;
}
if (r < 0) {
- if (CONFIG_PARSE_WARN)
+ if (FLAGS_SET(flags, CONFIG_PARSE_WARN))
log_error_errno(r, "%s:%u: Error while reading configuration file: %m", filename, line);
return r;
}
}
+ if (ret_mtime)
+ *ret_mtime = mtime;
+
return 0;
}
ConfigItemLookup lookup,
const void *table,
ConfigParseFlags flags,
- void *userdata) {
+ void *userdata,
+ usec_t *ret_mtime) {
+ usec_t mtime = 0;
char **fn;
int r;
if (conf_file) {
- r = config_parse(NULL, conf_file, NULL, sections, lookup, table, flags, userdata);
+ r = config_parse(NULL, conf_file, NULL, sections, lookup, table, flags, userdata, &mtime);
if (r < 0)
return r;
}
STRV_FOREACH(fn, files) {
- r = config_parse(NULL, *fn, NULL, sections, lookup, table, flags, userdata);
+ usec_t t;
+
+ r = config_parse(NULL, *fn, NULL, sections, lookup, table, flags, userdata, &t);
if (r < 0)
return r;
+ if (t > mtime) /* Find the newest */
+ mtime = t;
}
+ if (ret_mtime)
+ *ret_mtime = mtime;
+
return 0;
}
ConfigItemLookup lookup,
const void *table,
ConfigParseFlags flags,
- void *userdata) {
+ void *userdata,
+ usec_t *ret_mtime) {
_cleanup_strv_free_ char **files = NULL;
int r;
if (r < 0)
return r;
- return config_parse_many_files(conf_file, files, sections, lookup, table, flags, userdata);
+ return config_parse_many_files(conf_file, files, sections, lookup, table, flags, userdata, ret_mtime);
}
/* Parse each config file in the directories specified as strv. */
ConfigItemLookup lookup,
const void *table,
ConfigParseFlags flags,
- void *userdata) {
+ void *userdata,
+ usec_t *ret_mtime) {
_cleanup_strv_free_ char **dropin_dirs = NULL;
_cleanup_strv_free_ char **files = NULL;
if (r < 0)
return r;
- return config_parse_many_files(conf_file, files, sections, lookup, table, flags, userdata);
+ return config_parse_many_files(conf_file, files, sections, lookup, table, flags, userdata, ret_mtime);
}
#define DEFINE_PARSER(type, vartype, conv_func) \
if (r >= 0 && (uint64_t) (size_t) v != v)
r = -ERANGE;
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value '%s', ignoring: %m", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse size value '%s', ignoring: %m", rvalue);
return 0;
}
assert(data);
r = parse_size(rvalue, 1000, sz);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value '%s', ignoring: %m", rvalue);
- return 0;
- }
+ if (r < 0)
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse size value '%s', ignoring: %m", rvalue);
return 0;
}
r = parse_size(rvalue, 1024, bytes);
if (r < 0)
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue);
return 0;
}
k = parse_boolean(rvalue);
if (k < 0) {
- log_syntax(unit, LOG_ERR, filename, line, k,
+ log_syntax(unit, fatal ? LOG_ERR : LOG_WARNING, filename, line, k,
"Failed to parse boolean value%s: %s",
fatal ? "" : ", ignoring", rvalue);
return fatal ? -ENOEXEC : 0;
return 0;
}
+int config_parse_id128(
+ 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) {
+
+ sd_id128_t t, *result = data;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ r = sd_id128_from_string(rvalue, &t);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse 128bit ID/UUID, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (sd_id128_is_null(t)) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "128bit ID/UUID is all 0, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ *result = t;
+ return 0;
+}
+
int config_parse_tristate(
const char* unit,
const char *filename,
k = parse_boolean(rvalue);
if (k < 0) {
- log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse boolean value, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, k, "Failed to parse boolean value, ignoring: %s", rvalue);
return 0;
}
return 0;
}
- for (;;) {
+ for (const char *p = rvalue;;) {
char *word = NULL;
- r = extract_first_word(&rvalue, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
+ r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
if (r == 0)
- break;
+ return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
- break;
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
+ return 0;
}
r = strv_consume(sv, word);
if (r < 0)
return log_oom();
}
-
- return 0;
}
int config_parse_warn_compat(
x = log_facility_unshifted_from_string(rvalue);
if (x < 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse log facility, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse log facility, ignoring: %s", rvalue);
return 0;
}
x = log_level_from_string(rvalue);
if (x < 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse log level, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse log level, ignoring: %s", rvalue);
return 0;
}
r = signal_from_string(rvalue);
if (r <= 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse signal name, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse signal name, ignoring: %s", rvalue);
return 0;
}
else {
p = personality_from_string(rvalue);
if (p == PERSONALITY_INVALID) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse personality, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse personality, ignoring: %s", rvalue);
return 0;
}
}
}
if (!ifname_valid(rvalue)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is not valid or too long, ignoring assignment: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Interface name is not valid or too long, ignoring assignment: %s", rvalue);
return 0;
}
_cleanup_strv_free_ char **names = NULL;
char ***s = data;
- const char *p;
int r;
assert(filename);
return 0;
}
- p = rvalue;
- for (;;) {
+ for (const char *p = rvalue;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, 0);
+ if (r == -ENOMEM)
+ return log_oom();
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
+ log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to extract interface name, ignoring assignment: %s",
rvalue);
return 0;
break;
if (!ifname_valid_full(word, ltype)) {
- log_syntax(unit, LOG_ERR, filename, line, 0,
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
"Interface name is not valid or too long, ignoring assignment: %s",
word);
continue;
r = parse_ip_port(rvalue, &port);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse port '%s'.", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse port '%s'.", rvalue);
return 0;
}
r = parse_mtu(ltype, rvalue, mtu);
if (r == -ERANGE) {
- log_syntax(unit, LOG_ERR, filename, line, r,
+ log_syntax(unit, LOG_WARNING, filename, line, r,
"Maximum transfer unit (MTU) value out of range. Permitted range is %" PRIu32 "…%" PRIu32 ", ignoring: %s",
(uint32_t) (ltype == AF_INET6 ? IPV6_MIN_MTU : IPV4_MIN_MTU), (uint32_t) UINT32_MAX,
rvalue);
return 0;
}
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
+ log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse MTU value '%s', ignoring: %m", rvalue);
return 0;
}
return 0;
}
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
return 0;
}
r = parse_permille(rvalue);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
+ log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse permille value, ignoring: %s", rvalue);
return 0;
}
return 0;
}
+
+int config_parse_vlanprotocol(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) {
+ int *vlan_protocol = data;
+ assert(filename);
+ assert(lvalue);
+
+ if (isempty(rvalue)) {
+ *vlan_protocol = -1;
+ return 0;
+ }
+
+ if (STR_IN_SET(rvalue, "802.1ad", "802.1AD"))
+ *vlan_protocol = ETH_P_8021AD;
+ else if (STR_IN_SET(rvalue, "802.1q", "802.1Q"))
+ *vlan_protocol = ETH_P_8021Q;
+ else {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Failed to parse VLAN protocol value, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ return 0;
+}