diff options
| author | Michael Biebl <biebl@debian.org> | 2020-06-29 22:15:58 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2020-06-29 22:15:58 +0200 |
| commit | 10ae7d8cd706062742d0cdb1803d49909aef9e06 (patch) | |
| tree | cb89e8b475cec18f22b1abfe45f1d63da7e3f440 /shared | |
| parent | a54ac63bbf9b2c71026ac9028a8ffaf186cf3c82 (diff) | |
New upstream version 1.25.91 upstream/1.25.91
Diffstat (limited to 'shared')
| -rw-r--r-- | shared/nm-glib-aux/nm-shared-utils.c | 146 | ||||
| -rw-r--r-- | shared/nm-glib-aux/nm-shared-utils.h | 21 | ||||
| -rw-r--r-- | shared/nm-glib-aux/nm-str-buf.h | 61 | ||||
| -rw-r--r-- | shared/nm-version-macros.h | 2 | ||||
| -rw-r--r-- | shared/systemd/nm-sd-utils-shared.c | 40 | ||||
| -rw-r--r-- | shared/systemd/nm-sd-utils-shared.h | 4 |
6 files changed, 255 insertions, 19 deletions
diff --git a/shared/nm-glib-aux/nm-shared-utils.c b/shared/nm-glib-aux/nm-shared-utils.c index 39e98a31..e29520b2 100644 --- a/shared/nm-glib-aux/nm-shared-utils.c +++ b/shared/nm-glib-aux/nm-shared-utils.c @@ -1069,6 +1069,47 @@ nm_utils_parse_inaddr_prefix (int addr_family, return TRUE; } +gboolean +nm_utils_parse_next_line (const char **inout_ptr, + gsize *inout_len, + const char **out_line, + gsize *out_line_len) +{ + const char *line_start; + const char *line_end; + + g_return_val_if_fail (inout_ptr, FALSE); + g_return_val_if_fail (inout_len, FALSE); + g_return_val_if_fail (out_line, FALSE); + + if (*inout_len <= 0) + goto error; + + line_start = *inout_ptr; + line_end = memchr (line_start, '\n', *inout_len); + if (!line_end) + line_end = memchr (line_start, '\0', *inout_len); + if (!line_end) { + line_end = line_start + *inout_len; + NM_SET_OUT (inout_len, 0); + } else + NM_SET_OUT (inout_len, *inout_len - (line_end - line_start) - 1); + + NM_SET_OUT (out_line, line_start); + NM_SET_OUT (out_line_len, (gsize) (line_end - line_start)); + + if (*inout_len > 0) + NM_SET_OUT (inout_ptr, line_end + 1); + else + NM_SET_OUT (inout_ptr, NULL); + return TRUE; + +error: + NM_SET_OUT (out_line, NULL); + NM_SET_OUT (out_line_len, 0); + return FALSE; +} + /*****************************************************************************/ gboolean @@ -2021,6 +2062,100 @@ nm_utils_escaped_tokens_options_split (char *str, /*****************************************************************************/ /** + * nm_utils_strsplit_quoted: + * @str: the string to split (e.g. from /proc/cmdline). + * + * This basically does that systemd's extract_first_word() does + * with the flags "EXTRACT_UNQUOTE | EXTRACT_RELAX". This is what + * systemd uses to parse /proc/cmdline, and we do too. + * + * Splits the string. We have nm_utils_strsplit_set() which + * supports a variety of flags. However, extending that already + * complex code to also support quotation and escaping is hard. + * Instead, add a naive implementation. + * + * Returns: (transfer full): the split string. + */ +char ** +nm_utils_strsplit_quoted (const char *str) +{ + gs_unref_ptrarray GPtrArray *arr = NULL; + gs_free char *str_out = NULL; + guint8 ch_lookup[256]; + + nm_assert (str); + + _char_lookup_table_init (ch_lookup, NM_ASCII_WHITESPACES); + + for (;;) { + char quote; + gsize j; + + while (_char_lookup_has (ch_lookup, str[0])) + str++; + + if (str[0] == '\0') + break; + + if (!str_out) + str_out = g_new (char, strlen (str) + 1); + + quote = '\0'; + j = 0; + for (;;) { + if (str[0] == '\\') { + str++; + if (str[0] == '\0') + break; + str_out[j++] = str[0]; + str++; + continue; + } + if (quote) { + if (str[0] == '\0') + break; + if (str[0] == quote) { + quote = '\0'; + str++; + continue; + } + str_out[j++] = str[0]; + str++; + continue; + } + if (str[0] == '\0') + break; + if (NM_IN_SET (str[0], '\'', '"')) { + quote = str[0]; + str++; + continue; + } + if (_char_lookup_has (ch_lookup, str[0])) { + str++; + break; + } + str_out[j++] = str[0]; + str++; + } + + if (!arr) + arr = g_ptr_array_new (); + g_ptr_array_add (arr, g_strndup (str_out, j)); + } + + if (!arr) + return g_new0 (char *, 1); + + g_ptr_array_add (arr, NULL); + + /* We want to return an optimally sized strv array, with no excess + * memory allocated. Hence, clone once more. */ + return nm_memdup (arr->pdata, sizeof (char *) * arr->len); +} + +/*****************************************************************************/ + +/** * nm_utils_strv_find_first: * @list: the strv list to search * @len: the length of the list, or a negative value if @list is %NULL terminated. @@ -4841,6 +4976,8 @@ nm_str_buf_append_printf (NMStrBuf *strbuf, available = strbuf->_priv_allocated - strbuf->_priv_len; + nm_assert (available < G_MAXULONG); + va_start (args, format); l = g_vsnprintf (&strbuf->_priv_str[strbuf->_priv_len], available, @@ -4851,8 +4988,13 @@ nm_str_buf_append_printf (NMStrBuf *strbuf, nm_assert (l >= 0); nm_assert (l < G_MAXINT); - if ((gsize) l > available) { - gsize l2 = ((gsize) l) + 1u; + if ((gsize) l >= available) { + gsize l2; + + if (l == 0) + return; + + l2 = ((gsize) l) + 1u; nm_str_buf_maybe_expand (strbuf, l2, FALSE); diff --git a/shared/nm-glib-aux/nm-shared-utils.h b/shared/nm-glib-aux/nm-shared-utils.h index eeb8be5b..b17c8d1a 100644 --- a/shared/nm-glib-aux/nm-shared-utils.h +++ b/shared/nm-glib-aux/nm-shared-utils.h @@ -680,6 +680,10 @@ nm_utils_escaped_tokens_escape_gstr (const char *str, /*****************************************************************************/ +char **nm_utils_strsplit_quoted (const char *str); + +/*****************************************************************************/ + static inline const char ** nm_utils_escaped_tokens_options_split_list (const char *str) { @@ -803,6 +807,11 @@ gboolean nm_utils_parse_inaddr_prefix (int addr_family, char **out_addr, int *out_prefix); +gboolean nm_utils_parse_next_line (const char **inout_ptr, + gsize *inout_len, + const char **out_line, + gsize *out_line_len); + gint64 nm_g_ascii_strtoll (const char *nptr, char **endptr, guint base); @@ -2024,6 +2033,18 @@ nm_strvarray_add (GArray *array, const char *str) } static inline const char *const* +nm_strvarray_get_strv_non_empty (GArray *arr, guint *length) +{ + if (!arr || arr->len == 0) { + NM_SET_OUT (length, 0); + return NULL; + } + + NM_SET_OUT (length, arr->len); + return &g_array_index (arr, const char *, 0); +} + +static inline const char *const* nm_strvarray_get_strv (GArray **arr, guint *length) { if (!*arr) { diff --git a/shared/nm-glib-aux/nm-str-buf.h b/shared/nm-glib-aux/nm-str-buf.h index 8c73bfaf..da082abe 100644 --- a/shared/nm-glib-aux/nm-str-buf.h +++ b/shared/nm-glib-aux/nm-str-buf.h @@ -35,24 +35,30 @@ static inline void _nm_str_buf_assert (NMStrBuf *strbuf) { nm_assert (strbuf); - nm_assert (strbuf->_priv_str); - nm_assert (strbuf->_priv_allocated > 0); + nm_assert ((!!strbuf->_priv_str) == (strbuf->_priv_allocated > 0)); nm_assert (strbuf->_priv_len <= strbuf->_priv_allocated); } +static inline NMStrBuf +NM_STR_BUF_INIT (gsize allocated, gboolean do_bzero_mem) +{ + NMStrBuf strbuf = { + ._priv_str = allocated ? g_malloc (allocated) : NULL, + ._priv_allocated = allocated, + ._priv_len = 0, + ._priv_do_bzero_mem = do_bzero_mem, + }; + + return strbuf; +} + static inline void nm_str_buf_init (NMStrBuf *strbuf, gsize len, bool do_bzero_mem) { nm_assert (strbuf); - nm_assert (len > 0); - - strbuf->_priv_str = g_malloc (len); - strbuf->_priv_allocated = len; - strbuf->_priv_len = 0; - strbuf->_priv_do_bzero_mem = do_bzero_mem; - + *strbuf = NM_STR_BUF_INIT (len, do_bzero_mem); _nm_str_buf_assert (strbuf); } @@ -66,9 +72,6 @@ nm_str_buf_maybe_expand (NMStrBuf *strbuf, gboolean reserve_exact) { _nm_str_buf_assert (strbuf); - - /* currently we always require to reserve a non-zero number of bytes. */ - nm_assert (reserve > 0); nm_assert (strbuf->_priv_len < G_MAXSIZE - reserve); /* @reserve is the extra space that we require. */ @@ -164,6 +167,19 @@ nm_str_buf_erase (NMStrBuf *strbuf, /*****************************************************************************/ static inline void +nm_str_buf_append_c_repeated (NMStrBuf *strbuf, + char ch, + guint len) +{ + if (len > 0) { + nm_str_buf_maybe_expand (strbuf, len + 1, FALSE); + do { + strbuf->_priv_str[strbuf->_priv_len++] = ch; + } while (--len > 0); + } +} + +static inline void nm_str_buf_append_c (NMStrBuf *strbuf, char ch) { @@ -263,10 +279,16 @@ nm_str_buf_is_initalized (NMStrBuf *strbuf) * is of length "strbuf->len", which may be larger if the * returned string contains NUL characters (binary). The terminating * NUL character is always present after "strbuf->len" characters. + * If currently no buffer is allocated, this will return %NULL. */ -static inline const char * +static inline char * nm_str_buf_get_str (NMStrBuf *strbuf) { + _nm_str_buf_assert (strbuf); + + if (!strbuf->_priv_str) + return NULL; + nm_str_buf_maybe_expand (strbuf, 1, FALSE); strbuf->_priv_str[strbuf->_priv_len] = '\0'; return strbuf->_priv_str; @@ -288,16 +310,23 @@ nm_str_buf_get_str_unsafe (NMStrBuf *strbuf) * Returns: (transfer full): the string of the buffer * which must be freed by the caller. The @strbuf * is afterwards in undefined state, though it can be - * reused after nm_str_buf_init(). */ + * reused after nm_str_buf_init(). + * Note that if no string is allocated yet (after nm_str_buf_init() with + * length zero), this will return %NULL. */ static inline char * nm_str_buf_finalize (NMStrBuf *strbuf, gsize *out_len) { - nm_str_buf_maybe_expand (strbuf, 1, TRUE); - strbuf->_priv_str[strbuf->_priv_len] = '\0'; + _nm_str_buf_assert (strbuf); NM_SET_OUT (out_len, strbuf->_priv_len); + if (!strbuf->_priv_str) + return NULL; + + nm_str_buf_maybe_expand (strbuf, 1, TRUE); + strbuf->_priv_str[strbuf->_priv_len] = '\0'; + /* the buffer is in invalid state afterwards, however, we clear it * so far, that nm_auto_str_buf and nm_str_buf_destroy() is happy. */ return g_steal_pointer (&strbuf->_priv_str); diff --git a/shared/nm-version-macros.h b/shared/nm-version-macros.h index 40bfaaa9..0906a62b 100644 --- a/shared/nm-version-macros.h +++ b/shared/nm-version-macros.h @@ -30,7 +30,7 @@ * Evaluates to the micro version number of NetworkManager which this source * compiled against. */ -#define NM_MICRO_VERSION (90) +#define NM_MICRO_VERSION (91) /** * NM_CHECK_VERSION: diff --git a/shared/systemd/nm-sd-utils-shared.c b/shared/systemd/nm-sd-utils-shared.c index 4444e6c7..4fe82ca0 100644 --- a/shared/systemd/nm-sd-utils-shared.c +++ b/shared/systemd/nm-sd-utils-shared.c @@ -137,3 +137,43 @@ nm_sd_http_url_is_valid_https (const char *url) nm_assert (_http_url_is_valid (url, FALSE) == http_url_is_valid (url)); return _http_url_is_valid (url, TRUE); } + +/*****************************************************************************/ + +int +nmtst_systemd_extract_first_word_all (const char *str, char ***out_strv) +{ + gs_unref_ptrarray GPtrArray *arr = NULL; + + /* we implement a str split function to parse `/proc/cmdline`. This + * code should behave like systemd, which uses extract_first_word() + * for that. + * + * As we want to unit-test our implementation to match systemd, + * expose this function for testing. */ + + g_assert (out_strv); + g_assert (!*out_strv); + + if (!str) + return 0; + + arr = g_ptr_array_new_with_free_func (g_free); + + for (;;) { + gs_free char *word = NULL; + int r; + + r = extract_first_word (&str, &word, NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX); + if (r < 0) + return r; + if (r == 0) + break; + g_ptr_array_add (arr, g_steal_pointer (&word)); + } + + g_ptr_array_add (arr, NULL); + + *out_strv = (char **) g_ptr_array_free (g_steal_pointer (&arr), FALSE); + return 1; +} diff --git a/shared/systemd/nm-sd-utils-shared.h b/shared/systemd/nm-sd-utils-shared.h index a3ca1edc..75e38b84 100644 --- a/shared/systemd/nm-sd-utils-shared.h +++ b/shared/systemd/nm-sd-utils-shared.h @@ -38,4 +38,8 @@ gboolean nm_sd_hostname_is_valid(const char *s, bool allow_trailing_dot); gboolean nm_sd_http_url_is_valid_https (const char *url); +/*****************************************************************************/ + +int nmtst_systemd_extract_first_word_all (const char *str, char ***out_strv); + #endif /* __NM_SD_UTILS_SHARED_H__ */ |