diff --git a/src/basic/nulstr-util.c b/src/basic/nulstr-util.c index 06fa219bd19..7097a2cc128 100644 --- a/src/basic/nulstr-util.c +++ b/src/basic/nulstr-util.c @@ -4,7 +4,21 @@ #include "string-util.h" #include "strv.h" +const char* nulstr_get(const char *nulstr, const char *needle) { + if (!nulstr) + return NULL; + + NULSTR_FOREACH(i, nulstr) + if (streq(i, needle)) + return i; + + return NULL; +} + char** strv_parse_nulstr_full(const char *s, size_t l, bool drop_trailing_nuls) { + _cleanup_strv_free_ char **v = NULL; + size_t c = 0, i = 0; + /* 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 @@ -13,9 +27,6 @@ char** strv_parse_nulstr_full(const char *s, size_t l, bool drop_trailing_nuls) * Note that contrary to a normal nulstr which cannot contain empty strings, because the input data * is terminated by any two consequent NUL bytes, this parser accepts empty strings in s. */ - _cleanup_strv_free_ char **v = NULL; - size_t c = 0, i = 0; - assert(s || l <= 0); if (drop_trailing_nuls) @@ -36,7 +47,7 @@ char** strv_parse_nulstr_full(const char *s, size_t l, bool drop_trailing_nuls) if (!v) return NULL; - for (const char *p = s; p < s + l; ) { + for (const char *p = s; p < s + l;) { const char *e; e = memchr(p, 0, s + l - p); @@ -44,7 +55,6 @@ char** strv_parse_nulstr_full(const char *s, size_t l, bool drop_trailing_nuls) v[i] = memdup_suffix0(p, e ? e - p : s + l - p); if (!v[i]) return NULL; - i++; if (!e) @@ -74,6 +84,9 @@ char** strv_split_nulstr(const char *s) { } int strv_make_nulstr(char * const *l, char **ret, size_t *ret_size) { + _cleanup_free_ char *m = NULL; + size_t n = 0; + /* Builds a nulstr and returns it together with the size. An extra NUL byte will be appended (⚠️ but * not included in the size! ⚠️). This is done so that the nulstr can be used both in * strv_parse_nulstr() and in NULSTR_FOREACH()/strv_split_nulstr() contexts, i.e. with and without a @@ -84,21 +97,18 @@ int strv_make_nulstr(char * const *l, char **ret, size_t *ret_size) { * NUL bytes (which it will, if not empty). To ensure that this assumption *always* holds, we'll * return a buffer with two NUL bytes in that case, but return a size of zero. */ - _cleanup_free_ char *m = NULL; - size_t n = 0; - assert(ret); STRV_FOREACH(i, l) { size_t z; - z = strlen(*i); + z = strlen(*i) + 1; - if (!GREEDY_REALLOC(m, n + z + 2)) + if (!GREEDY_REALLOC(m, n + z + 1)) /* One extra NUL at the end as marker */ return -ENOMEM; - memcpy(m + n, *i, z + 1); - n += z + 1; + memcpy(m + n, *i, z); + n += z; } if (!m) { @@ -109,7 +119,7 @@ int strv_make_nulstr(char * const *l, char **ret, size_t *ret_size) { n = 0; } else - /* Make sure there is a second extra NUL at the end of resulting nulstr (not counted in return size) */ + /* Extra NUL is not counted in size returned */ m[n] = '\0'; *ret = TAKE_PTR(m); @@ -132,14 +142,3 @@ int set_make_nulstr(Set *s, char **ret, size_t *ret_size) { return strv_make_nulstr(strv, ret, ret_size); } - -const char* nulstr_get(const char *nulstr, const char *needle) { - if (!nulstr) - return NULL; - - NULSTR_FOREACH(i, nulstr) - if (streq(i, needle)) - return i; - - return NULL; -} diff --git a/src/basic/nulstr-util.h b/src/basic/nulstr-util.h index d7bc5fd1ced..d6f2f58e9fd 100644 --- a/src/basic/nulstr-util.h +++ b/src/basic/nulstr-util.h @@ -15,7 +15,6 @@ for (typeof(*(l)) *(i) = (l), *(j) = strchr((i), 0)+1; (i) && *(i); (i) = strchr((j), 0)+1, (j) = *(i) ? strchr((i), 0)+1 : (i)) const char* nulstr_get(const char *nulstr, const char *needle); - static inline bool nulstr_contains(const char *nulstr, const char *needle) { return nulstr_get(nulstr, needle); } @@ -25,9 +24,6 @@ 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); - static inline int strv_from_nulstr(char ***ret, const char *nulstr) { char **t; @@ -40,3 +36,6 @@ static inline int strv_from_nulstr(char ***ret, const char *nulstr) { *ret = t; return 0; } + +int strv_make_nulstr(char * const *l, char **p, size_t *n); +int set_make_nulstr(Set *s, char **ret, size_t *ret_size); diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 32a60e388fc..42b7fef7204 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -121,19 +121,14 @@ static OutputFlags get_output_flags(void) { static int call_get_os_release(sd_bus *bus, const char *method, const char *name, const char *query, ...) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - const char *k, *v, **query_res = NULL; - size_t count = 0, awaited_args = 0; va_list ap; int r; assert(bus); + assert(method); assert(name); assert(query); - NULSTR_FOREACH(iter, query) - awaited_args++; - query_res = newa0(const char *, awaited_args); - r = bus_call_method(bus, bus_machine_mgr, method, &error, &reply, "s", name); if (r < 0) return log_debug_errno(r, "Failed to call '%s()': %s", method, bus_error_message(&error, r)); @@ -142,14 +137,23 @@ static int call_get_os_release(sd_bus *bus, const char *method, const char *name if (r < 0) return bus_log_parse_error(r); + const char **res; + size_t n_fields = 0; + + NULSTR_FOREACH(i, query) + n_fields++; + + res = newa0(const char*, n_fields); + + const char *k, *v; while ((r = sd_bus_message_read(reply, "{ss}", &k, &v)) > 0) { - count = 0; - NULSTR_FOREACH(iter, query) { - if (streq(k, iter)) { - query_res[count] = v; + size_t c = 0; + NULSTR_FOREACH(i, query) { + if (streq(i, k)) { + res[c] = v; break; } - count++; + c++; } } if (r < 0) @@ -160,17 +164,12 @@ static int call_get_os_release(sd_bus *bus, const char *method, const char *name return bus_log_parse_error(r); r = 0; - va_start(ap, query); - for (count = 0; count < awaited_args; count++) { - char **out; - out = va_arg(ap, char **); - assert(out); - if (query_res[count]) { - r = strdup_to(out, query_res[count]); - if (r < 0) - break; - } + va_start(ap, query); + FOREACH_ARRAY(i, res, n_fields) { + r = strdup_to(va_arg(ap, char**), *i); + if (r < 0) + break; } va_end(ap); @@ -203,12 +202,12 @@ static int call_get_addresses( addresses = strdup(prefix); if (!addresses) return log_oom(); - prefix = ""; r = sd_bus_message_enter_container(reply, 'a', "(iay)"); if (r < 0) return bus_log_parse_error(r); + prefix = ""; while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) { int family; const void *a;