util: rework /proc/cmdline parser to use unquote_first_word()
This commit is contained in:
parent
b5884878a2
commit
f32d2db140
|
@ -101,7 +101,7 @@ static int condition_test_kernel_command_line(Condition *c) {
|
|||
_cleanup_free_ char *word = NULL;
|
||||
bool found;
|
||||
|
||||
r = unquote_first_word(&p, &word);
|
||||
r = unquote_first_word(&p, &word, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
|
|
|
@ -6146,8 +6146,7 @@ int split_pair(const char *s, const char *sep, char **l, char **r) {
|
|||
|
||||
int shall_restore_state(void) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
const char *word, *state;
|
||||
size_t l;
|
||||
const char *p;
|
||||
int r;
|
||||
|
||||
r = proc_cmdline(&line);
|
||||
|
@ -6155,15 +6154,20 @@ int shall_restore_state(void) {
|
|||
return r;
|
||||
|
||||
r = 1;
|
||||
FOREACH_WORD_QUOTED(word, l, line, state) {
|
||||
p = line;
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
const char *e;
|
||||
char n[l+1];
|
||||
int k;
|
||||
|
||||
memcpy(n, word, l);
|
||||
n[l] = 0;
|
||||
k = unquote_first_word(&p, &word, true);
|
||||
if (k < 0)
|
||||
return k;
|
||||
if (k == 0)
|
||||
break;
|
||||
|
||||
e = startswith(n, "systemd.restore_state=");
|
||||
e = startswith(word, "systemd.restore_state=");
|
||||
if (!e)
|
||||
continue;
|
||||
|
||||
|
@ -6186,8 +6190,7 @@ int proc_cmdline(char **ret) {
|
|||
|
||||
int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
const char *w, *state;
|
||||
size_t l;
|
||||
const char *p;
|
||||
int r;
|
||||
|
||||
assert(parse_item);
|
||||
|
@ -6196,11 +6199,16 @@ int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
FOREACH_WORD_QUOTED(w, l, line, state) {
|
||||
char word[l+1], *value;
|
||||
p = line;
|
||||
for (;;) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
char *value = NULL;
|
||||
|
||||
memcpy(word, w, l);
|
||||
word[l] = 0;
|
||||
r = unquote_first_word(&p, &word, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
/* Filter out arguments that are intended only for the
|
||||
* initrd */
|
||||
|
@ -6976,7 +6984,7 @@ int is_dir(const char* path, bool follow) {
|
|||
return !!S_ISDIR(st.st_mode);
|
||||
}
|
||||
|
||||
int unquote_first_word(const char **p, char **ret) {
|
||||
int unquote_first_word(const char **p, char **ret, bool relax) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
size_t allocated = 0, sz = 0;
|
||||
|
||||
|
@ -7035,8 +7043,11 @@ int unquote_first_word(const char **p, char **ret) {
|
|||
break;
|
||||
|
||||
case VALUE_ESCAPE:
|
||||
if (c == 0)
|
||||
if (c == 0) {
|
||||
if (relax)
|
||||
goto finish;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!GREEDY_REALLOC(s, allocated, sz+2))
|
||||
return -ENOMEM;
|
||||
|
@ -7047,9 +7058,11 @@ int unquote_first_word(const char **p, char **ret) {
|
|||
break;
|
||||
|
||||
case SINGLE_QUOTE:
|
||||
if (c == 0)
|
||||
if (c == 0) {
|
||||
if (relax)
|
||||
goto finish;
|
||||
return -EINVAL;
|
||||
else if (c == '\'')
|
||||
} else if (c == '\'')
|
||||
state = VALUE;
|
||||
else if (c == '\\')
|
||||
state = SINGLE_QUOTE_ESCAPE;
|
||||
|
@ -7063,8 +7076,11 @@ int unquote_first_word(const char **p, char **ret) {
|
|||
break;
|
||||
|
||||
case SINGLE_QUOTE_ESCAPE:
|
||||
if (c == 0)
|
||||
if (c == 0) {
|
||||
if (relax)
|
||||
goto finish;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!GREEDY_REALLOC(s, allocated, sz+2))
|
||||
return -ENOMEM;
|
||||
|
@ -7090,8 +7106,11 @@ int unquote_first_word(const char **p, char **ret) {
|
|||
break;
|
||||
|
||||
case DOUBLE_QUOTE_ESCAPE:
|
||||
if (c == 0)
|
||||
if (c == 0) {
|
||||
if (relax)
|
||||
goto finish;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!GREEDY_REALLOC(s, allocated, sz+2))
|
||||
return -ENOMEM;
|
||||
|
@ -7151,7 +7170,7 @@ int unquote_many_words(const char **p, ...) {
|
|||
l = newa0(char*, n);
|
||||
for (c = 0; c < n; c++) {
|
||||
|
||||
r = unquote_first_word(p, &l[c]);
|
||||
r = unquote_first_word(p, &l[c], false);
|
||||
if (r < 0) {
|
||||
int j;
|
||||
|
||||
|
|
|
@ -1018,7 +1018,7 @@ int take_password_lock(const char *root);
|
|||
int is_symlink(const char *path);
|
||||
int is_dir(const char *path, bool follow);
|
||||
|
||||
int unquote_first_word(const char **p, char **ret);
|
||||
int unquote_first_word(const char **p, char **ret, bool relax);
|
||||
int unquote_many_words(const char **p, ...) _sentinel_;
|
||||
|
||||
int free_and_strdup(char **p, const char *s);
|
||||
|
|
|
@ -1173,51 +1173,60 @@ static void test_unquote_first_word(void) {
|
|||
char *t;
|
||||
|
||||
p = original = "foobar waldo";
|
||||
assert_se(unquote_first_word(&p, &t) > 0);
|
||||
assert_se(unquote_first_word(&p, &t, false) > 0);
|
||||
assert_se(streq(t, "foobar"));
|
||||
free(t);
|
||||
assert_se(p == original + 7);
|
||||
|
||||
assert_se(unquote_first_word(&p, &t) > 0);
|
||||
assert_se(unquote_first_word(&p, &t, false) > 0);
|
||||
assert_se(streq(t, "waldo"));
|
||||
free(t);
|
||||
assert_se(p == original + 12);
|
||||
|
||||
assert_se(unquote_first_word(&p, &t) == 0);
|
||||
assert_se(unquote_first_word(&p, &t, false) == 0);
|
||||
assert_se(!t);
|
||||
assert_se(p == original + 12);
|
||||
|
||||
p = original = "\"foobar\" \'waldo\'";
|
||||
assert_se(unquote_first_word(&p, &t) > 0);
|
||||
assert_se(unquote_first_word(&p, &t, false) > 0);
|
||||
assert_se(streq(t, "foobar"));
|
||||
free(t);
|
||||
assert_se(p == original + 9);
|
||||
|
||||
assert_se(unquote_first_word(&p, &t) > 0);
|
||||
assert_se(unquote_first_word(&p, &t, false) > 0);
|
||||
assert_se(streq(t, "waldo"));
|
||||
free(t);
|
||||
assert_se(p == original + 16);
|
||||
|
||||
assert_se(unquote_first_word(&p, &t) == 0);
|
||||
assert_se(unquote_first_word(&p, &t, false) == 0);
|
||||
assert_se(!t);
|
||||
assert_se(p == original + 16);
|
||||
|
||||
p = original = "\"";
|
||||
assert_se(unquote_first_word(&p, &t) == -EINVAL);
|
||||
assert_se(unquote_first_word(&p, &t, false) == -EINVAL);
|
||||
assert_se(p == original + 1);
|
||||
|
||||
p = original = "\'";
|
||||
assert_se(unquote_first_word(&p, &t) == -EINVAL);
|
||||
assert_se(unquote_first_word(&p, &t, false) == -EINVAL);
|
||||
assert_se(p == original + 1);
|
||||
|
||||
p = original = "\'fooo";
|
||||
assert_se(unquote_first_word(&p, &t, false) == -EINVAL);
|
||||
assert_se(p == original + 5);
|
||||
|
||||
p = original = "\'fooo";
|
||||
assert_se(unquote_first_word(&p, &t, true) > 0);
|
||||
assert_se(streq(t, "fooo"));
|
||||
assert_se(p == original + 5);
|
||||
|
||||
p = original = "yay\'foo\'bar";
|
||||
assert_se(unquote_first_word(&p, &t) > 0);
|
||||
assert_se(unquote_first_word(&p, &t, false) > 0);
|
||||
assert_se(streq(t, "yayfoobar"));
|
||||
free(t);
|
||||
assert_se(p == original + 11);
|
||||
|
||||
p = original = " foobar ";
|
||||
assert_se(unquote_first_word(&p, &t) > 0);
|
||||
assert_se(unquote_first_word(&p, &t, false) > 0);
|
||||
assert_se(streq(t, "foobar"));
|
||||
free(t);
|
||||
assert_se(p == original + 12);
|
||||
|
@ -1277,6 +1286,17 @@ static void test_unquote_many_words(void) {
|
|||
free(a);
|
||||
}
|
||||
|
||||
static int parse_item(const char *key, const char *value) {
|
||||
assert_se(key);
|
||||
|
||||
log_info("kernel cmdline option <%s> = <%s>", key, strna(value));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_parse_proc_cmdline(void) {
|
||||
assert_se(parse_proc_cmdline(parse_item) >= 0);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
log_parse_environment();
|
||||
log_open();
|
||||
|
@ -1348,6 +1368,7 @@ int main(int argc, char *argv[]) {
|
|||
test_execute_directory();
|
||||
test_unquote_first_word();
|
||||
test_unquote_many_words();
|
||||
test_parse_proc_cmdline();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue