mirror of
https://github.com/systemd/systemd.git
synced 2025-03-09 12:58:26 +03:00
Merge pull request #26958 from yuwata/nulstr-optionally-drop-trailing-nulstr
nulstr: make strv_parse_nulstr() optionally drop trailing NULs
This commit is contained in:
commit
12962485e4
@ -4,7 +4,7 @@
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
char** strv_parse_nulstr(const char *s, size_t l) {
|
||||
char** strv_parse_nulstr_full(const char *s, size_t l, bool drop_trailing_nuls) {
|
||||
/* l is the length of the input data, which will be split at NULs into elements of the resulting
|
||||
* strv. Hence, the number of items in the resulting strv will be equal to one plus the number of NUL
|
||||
* bytes in the l bytes starting at s, unless s[l-1] is NUL, in which case the final empty string is
|
||||
@ -18,6 +18,10 @@ char** strv_parse_nulstr(const char *s, size_t l) {
|
||||
|
||||
assert(s || l <= 0);
|
||||
|
||||
if (drop_trailing_nuls)
|
||||
while (l > 0 && s[l-1] == '\0')
|
||||
l--;
|
||||
|
||||
if (l <= 0)
|
||||
return new0(char*, 1);
|
||||
|
||||
|
@ -20,7 +20,10 @@ static inline bool nulstr_contains(const char *nulstr, const char *needle) {
|
||||
return nulstr_get(nulstr, needle);
|
||||
}
|
||||
|
||||
char** strv_parse_nulstr(const char *s, size_t l);
|
||||
char** strv_parse_nulstr_full(const char *s, size_t l, bool drop_trailing_nuls);
|
||||
static inline char** strv_parse_nulstr(const char *s, size_t l) {
|
||||
return strv_parse_nulstr_full(s, l, false);
|
||||
}
|
||||
char** strv_split_nulstr(const char *s);
|
||||
int strv_make_nulstr(char * const *l, char **p, size_t *n);
|
||||
int set_make_nulstr(Set *s, char **ret, size_t *ret_size);
|
||||
|
@ -222,18 +222,12 @@ int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags
|
||||
|
||||
_cleanup_strv_free_ char **args = NULL;
|
||||
|
||||
args = strv_parse_nulstr(t, k);
|
||||
/* Drop trailing NULs, otherwise strv_parse_nulstr() adds additional empty strings at the end.
|
||||
* See also issue #21186. */
|
||||
args = strv_parse_nulstr_full(t, k, /* drop_trailing_nuls = */ true);
|
||||
if (!args)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Drop trailing empty strings. See issue #21186. */
|
||||
STRV_FOREACH_BACKWARDS(p, args) {
|
||||
if (!isempty(*p))
|
||||
break;
|
||||
|
||||
*p = mfree(*p);
|
||||
}
|
||||
|
||||
ans = quote_command_line(args, shflags);
|
||||
if (!ans)
|
||||
return -ENOMEM;
|
||||
|
@ -19,87 +19,66 @@ TEST(strv_split_nulstr) {
|
||||
assert_se(streq(l[3], "str3"));
|
||||
}
|
||||
|
||||
TEST(strv_parse_nulstr) {
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
const char nulstr[] = "hoge\0hoge2\0hoge3\0\0hoge5\0\0xxx";
|
||||
#define strv_parse_nulstr_full_one(s, n, e0, e1) \
|
||||
({ \
|
||||
_cleanup_strv_free_ char **v0 = NULL, **v1 = NULL; \
|
||||
\
|
||||
assert_se(v0 = strv_parse_nulstr_full(s, n, false)); \
|
||||
assert_se(strv_equal(v0, e0)); \
|
||||
assert_se(v1 = strv_parse_nulstr_full(s, n, true)); \
|
||||
assert_se(strv_equal(v1, e1)); \
|
||||
})
|
||||
|
||||
l = strv_parse_nulstr(nulstr, sizeof(nulstr)-1);
|
||||
assert_se(l);
|
||||
puts("Parse nulstr:");
|
||||
strv_print(l);
|
||||
TEST(strv_parse_nulstr_full) {
|
||||
const char nulstr1[] = "hoge\0hoge2\0hoge3\0\0hoge5\0\0xxx";
|
||||
const char nulstr2[] = "hoge\0hoge2\0hoge3\0\0hoge5\0\0xxx\0\0\0";
|
||||
|
||||
assert_se(streq(l[0], "hoge"));
|
||||
assert_se(streq(l[1], "hoge2"));
|
||||
assert_se(streq(l[2], "hoge3"));
|
||||
assert_se(streq(l[3], ""));
|
||||
assert_se(streq(l[4], "hoge5"));
|
||||
assert_se(streq(l[5], ""));
|
||||
assert_se(streq(l[6], "xxx"));
|
||||
strv_free(l);
|
||||
strv_parse_nulstr_full_one(nulstr1, sizeof(nulstr1) - 1,
|
||||
STRV_MAKE("hoge", "hoge2", "hoge3", "", "hoge5", "", "xxx"),
|
||||
STRV_MAKE("hoge", "hoge2", "hoge3", "", "hoge5", "", "xxx"));
|
||||
|
||||
l = strv_parse_nulstr((const char[0]) {}, 0);
|
||||
assert_se(l);
|
||||
assert_se(strv_isempty(l));
|
||||
strv_free(l);
|
||||
strv_parse_nulstr_full_one(nulstr2, sizeof(nulstr2) - 1,
|
||||
STRV_MAKE("hoge", "hoge2", "hoge3", "", "hoge5", "", "xxx", "", ""),
|
||||
STRV_MAKE("hoge", "hoge2", "hoge3", "", "hoge5", "", "xxx"));
|
||||
|
||||
l = strv_parse_nulstr((const char[1]) { 0 }, 1);
|
||||
assert_se(l);
|
||||
assert_se(strv_equal(l, STRV_MAKE("")));
|
||||
strv_free(l);
|
||||
strv_parse_nulstr_full_one(((const char[0]) {}), 0,
|
||||
STRV_MAKE_EMPTY, STRV_MAKE_EMPTY);
|
||||
|
||||
l = strv_parse_nulstr((const char[1]) { 'x' }, 1);
|
||||
assert_se(l);
|
||||
assert_se(strv_equal(l, STRV_MAKE("x")));
|
||||
strv_free(l);
|
||||
strv_parse_nulstr_full_one(((const char[1]) { 0 }), 1,
|
||||
STRV_MAKE(""), STRV_MAKE_EMPTY);
|
||||
|
||||
l = strv_parse_nulstr((const char[2]) { 0, 0 }, 2);
|
||||
assert_se(l);
|
||||
assert_se(strv_equal(l, STRV_MAKE("", "")));
|
||||
strv_free(l);
|
||||
strv_parse_nulstr_full_one(((const char[1]) { 'x' }), 1,
|
||||
STRV_MAKE("x"), STRV_MAKE("x"));
|
||||
|
||||
l = strv_parse_nulstr((const char[2]) { 'x', 0 }, 2);
|
||||
assert_se(l);
|
||||
assert_se(strv_equal(l, STRV_MAKE("x")));
|
||||
strv_free(l);
|
||||
strv_parse_nulstr_full_one(((const char[2]) { 0, 0 }), 2,
|
||||
STRV_MAKE("", ""), STRV_MAKE_EMPTY);
|
||||
|
||||
l = strv_parse_nulstr((const char[3]) { 0, 0, 0 }, 3);
|
||||
assert_se(l);
|
||||
assert_se(strv_equal(l, STRV_MAKE("", "", "")));
|
||||
strv_free(l);
|
||||
strv_parse_nulstr_full_one(((const char[2]) { 'x', 0 }), 2,
|
||||
STRV_MAKE("x"), STRV_MAKE("x"));
|
||||
|
||||
l = strv_parse_nulstr((const char[3]) { 'x', 0, 0 }, 3);
|
||||
assert_se(l);
|
||||
assert_se(strv_equal(l, STRV_MAKE("x", "")));
|
||||
strv_free(l);
|
||||
strv_parse_nulstr_full_one(((const char[3]) { 0, 0, 0 }), 3,
|
||||
STRV_MAKE("", "", ""), STRV_MAKE_EMPTY);
|
||||
|
||||
l = strv_parse_nulstr((const char[3]) { 0, 'x', 0 }, 3);
|
||||
assert_se(l);
|
||||
assert_se(strv_equal(l, STRV_MAKE("", "x")));
|
||||
strv_free(l);
|
||||
strv_parse_nulstr_full_one(((const char[3]) { 'x', 0, 0 }), 3,
|
||||
STRV_MAKE("x", ""), STRV_MAKE("x"));
|
||||
|
||||
l = strv_parse_nulstr((const char[3]) { 0, 0, 'x' }, 3);
|
||||
assert_se(l);
|
||||
assert_se(strv_equal(l, STRV_MAKE("", "", "x")));
|
||||
strv_free(l);
|
||||
strv_parse_nulstr_full_one(((const char[3]) { 0, 'x', 0 }), 3,
|
||||
STRV_MAKE("", "x"), STRV_MAKE("", "x"));
|
||||
|
||||
l = strv_parse_nulstr((const char[3]) { 'x', 'x', 0 }, 3);
|
||||
assert_se(l);
|
||||
assert_se(strv_equal(l, STRV_MAKE("xx")));
|
||||
strv_free(l);
|
||||
strv_parse_nulstr_full_one(((const char[3]) { 0, 0, 'x' }), 3,
|
||||
STRV_MAKE("", "", "x"), STRV_MAKE("", "", "x"));
|
||||
|
||||
l = strv_parse_nulstr((const char[3]) { 0, 'x', 'x' }, 3);
|
||||
assert_se(l);
|
||||
assert_se(strv_equal(l, STRV_MAKE("", "xx")));
|
||||
strv_free(l);
|
||||
strv_parse_nulstr_full_one(((const char[3]) { 'x', 'x', 0 }), 3,
|
||||
STRV_MAKE("xx"), STRV_MAKE("xx"));
|
||||
|
||||
l = strv_parse_nulstr((const char[3]) { 'x', 0, 'x' }, 3);
|
||||
assert_se(l);
|
||||
assert_se(strv_equal(l, STRV_MAKE("x", "x")));
|
||||
strv_free(l);
|
||||
strv_parse_nulstr_full_one(((const char[3]) { 0, 'x', 'x' }), 3,
|
||||
STRV_MAKE("", "xx"), STRV_MAKE("", "xx"));
|
||||
|
||||
l = strv_parse_nulstr((const char[3]) { 'x', 'x', 'x' }, 3);
|
||||
assert_se(l);
|
||||
assert_se(strv_equal(l, STRV_MAKE("xxx")));
|
||||
strv_parse_nulstr_full_one(((const char[3]) { 'x', 0, 'x' }), 3,
|
||||
STRV_MAKE("x", "x"), STRV_MAKE("x", "x"));
|
||||
|
||||
strv_parse_nulstr_full_one(((const char[3]) { 'x', 'x', 'x' }), 3,
|
||||
STRV_MAKE("xxx"), STRV_MAKE("xxx"));
|
||||
}
|
||||
|
||||
static void test_strv_make_nulstr_one(char **l) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user