1
0
mirror of https://github.com/systemd/systemd.git synced 2024-11-02 10:51:20 +03:00

proc-cmdline: split out rd. prefix handling in proc_cmdline_parse_given() and proc_cmdline_get_key()

This introduces a wrapper around extrac_first_word() called
proc_cmdline_extract_first(), which suppresses "rd." parameters
depending on the specified calls.

This allows us to share more code between proc_cmdline_parse_given() and
proc_cmdline_get_key(), and makes it easier to reuse this logic for
other purposes.
This commit is contained in:
Lennart Poettering 2018-11-12 12:39:34 +01:00
parent f6dd5e7c18
commit 1e7a599671

View File

@ -39,42 +39,71 @@ int proc_cmdline(char **ret) {
return read_one_line_file("/proc/cmdline", ret);
}
static int proc_cmdline_extract_first(const char **p, char **ret_word, ProcCmdlineFlags flags) {
const char *q = *p;
int r;
for (;;) {
_cleanup_free_ char *word = NULL;
const char *c;
r = extract_first_word(&q, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
if (r < 0)
return r;
if (r == 0)
break;
/* Filter out arguments that are intended only for the initrd */
c = startswith(word, "rd.");
if (c) {
if (!in_initrd())
continue;
if (FLAGS_SET(flags, PROC_CMDLINE_STRIP_RD_PREFIX)) {
r = free_and_strdup(&word, c);
if (r < 0)
return r;
}
} else if (FLAGS_SET(flags, PROC_CMDLINE_RD_STRICT) && in_initrd())
continue; /* And optionally filter out arguments that are intended only for the host */
*p = q;
*ret_word = TAKE_PTR(word);
return 1;
}
*p = q;
*ret_word = NULL;
return 0;
}
int proc_cmdline_parse_given(const char *line, proc_cmdline_parse_t parse_item, void *data, ProcCmdlineFlags flags) {
const char *p;
int r;
assert(parse_item);
/* The PROC_CMDLINE_VALUE_OPTIONAL flag doesn't really make sense for proc_cmdline_parse(), let's make this
* clear. */
assert(!FLAGS_SET(flags, PROC_CMDLINE_VALUE_OPTIONAL));
p = line;
for (;;) {
_cleanup_free_ char *word = NULL;
char *value, *key, *q;
char *value;
r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
r = proc_cmdline_extract_first(&p, &word, flags);
if (r < 0)
return r;
if (r == 0)
break;
key = word;
/* Filter out arguments that are intended only for the initrd */
q = startswith(word, "rd.");
if (q) {
if (!in_initrd())
continue;
if (FLAGS_SET(flags, PROC_CMDLINE_STRIP_RD_PREFIX))
key = q;
} else if (FLAGS_SET(flags, PROC_CMDLINE_RD_STRICT) && in_initrd())
continue; /* And optionally filter out arguments that are intended only for the host */
value = strchr(key, '=');
value = strchr(word, '=');
if (value)
*(value++) = 0;
r = parse_item(key, value, data);
r = parse_item(word, value, data);
if (r < 0)
return r;
}
@ -127,29 +156,29 @@ bool proc_cmdline_key_streq(const char *x, const char *y) {
return true;
}
int proc_cmdline_get_key(const char *key, ProcCmdlineFlags flags, char **value) {
int proc_cmdline_get_key(const char *key, ProcCmdlineFlags flags, char **ret_value) {
_cleanup_free_ char *line = NULL, *ret = NULL;
bool found = false;
const char *p;
int r;
/* Looks for a specific key on the kernel command line. Supports two modes:
/* Looks for a specific key on the kernel command line. Supports three modes:
*
* a) The "value" parameter is used. In this case a parameter beginning with the "key" string followed by "="
* is searched, and the value following this is returned in "value".
* a) The "ret_value" parameter is used. In this case a parameter beginning with the "key" string followed by
* "=" is searched for, and the value following it is returned in "ret_value".
*
* b) as above, but the PROC_CMDLINE_VALUE_OPTIONAL flag is set. In this case if the key is found as a
* separate word (i.e. not followed by "=" but instead by whitespace or the end of the command line), then
* this is also accepted, and "value" is returned as NULL.
* b) as above, but the PROC_CMDLINE_VALUE_OPTIONAL flag is set. In this case if the key is found as a separate
* word (i.e. not followed by "=" but instead by whitespace or the end of the command line), then this is
* also accepted, and "value" is returned as NULL.
*
* c) The "value" parameter is NULL. In this case a search for the exact "key" parameter is performed.
* c) The "ret_value" parameter is NULL. In this case a search for the exact "key" parameter is performed.
*
* In all three cases, > 0 is returned if the key is found, 0 if not. */
if (isempty(key))
return -EINVAL;
if (FLAGS_SET(flags, PROC_CMDLINE_VALUE_OPTIONAL) && !value)
if (FLAGS_SET(flags, PROC_CMDLINE_VALUE_OPTIONAL) && !ret_value)
return -EINVAL;
r = proc_cmdline(&line);
@ -159,31 +188,17 @@ int proc_cmdline_get_key(const char *key, ProcCmdlineFlags flags, char **value)
p = line;
for (;;) {
_cleanup_free_ char *word = NULL;
const char *e, *k, *q;
r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
r = proc_cmdline_extract_first(&p, &word, flags);
if (r < 0)
return r;
if (r == 0)
break;
k = word;
if (ret_value) {
const char *e;
/* Automatically filter out arguments that are intended only for the initrd, if we are not in the
* initrd. */
q = startswith(word, "rd.");
if (q) {
if (!in_initrd())
continue;
if (FLAGS_SET(flags, PROC_CMDLINE_STRIP_RD_PREFIX))
k = q;
} else if (FLAGS_SET(flags, PROC_CMDLINE_RD_STRICT) && in_initrd())
continue;
if (value) {
e = proc_cmdline_key_startswith(k, key);
e = proc_cmdline_key_startswith(word, key);
if (!e)
continue;
@ -198,13 +213,15 @@ int proc_cmdline_get_key(const char *key, ProcCmdlineFlags flags, char **value)
found = true;
} else {
if (streq(k, key))
if (streq(word, key)) {
found = true;
break; /* we found what we were looking for */
}
}
}
if (value)
*value = TAKE_PTR(ret);
if (ret_value)
*ret_value = TAKE_PTR(ret);
return found;
}