diff --git a/src/settings/plugins/ifcfg-rh/shvar.c b/src/settings/plugins/ifcfg-rh/shvar.c index ae1dd5681..5fe59ef8c 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.c +++ b/src/settings/plugins/ifcfg-rh/shvar.c @@ -150,23 +150,31 @@ svEscape (const char *s, char **to_free) } /* remove escaped characters in place */ -void -svUnescape (char *s) +const char * +svUnescape (const char *value, char **to_free) { size_t len, idx_rd = 0, idx_wr = 0; char c; + char *s; + + nm_assert (value); + nm_assert (to_free); + + /* TODO: avoid copying the string if there is nothing to do. */ + s = g_strchomp (g_strdup (value)); + *to_free = s; len = strlen (s); if (len < 2) { if (s[0] == '\\') s[0] = '\0'; - return; + return s; } if ((s[0] == '"' || s[0] == '\'') && s[0] == s[len-1]) { if (len == 2) { s[0] = '\0'; - return; + return s; } if (len == 3) { if (s[1] == '\\') { @@ -175,7 +183,7 @@ svUnescape (char *s) s[0] = s[1]; s[1] = '\0'; } - return; + return s; } s[--len] = '\0'; idx_rd = 1; @@ -184,10 +192,10 @@ svUnescape (char *s) char *p = strchr (s, '\\'); if (!p) - return; + return s; if (p[1] == '\0') { p[0] = '\0'; - return; + return s; } idx_wr = idx_rd = (p - s); } @@ -199,7 +207,7 @@ svUnescape (char *s) if (c == '\\') { if (s[idx_rd] == '\0') { s[idx_wr] = '\0'; - return; + return s; } s[idx_wr++] = s[idx_rd++]; continue; @@ -207,6 +215,7 @@ svUnescape (char *s) s[idx_wr++] = c; } s[idx_wr] = '\0'; + return s; } /*****************************************************************************/ @@ -352,7 +361,7 @@ char * svGetValue (shvarFile *s, const char *key) { const char *line_val; - char *value; + char *copied; g_return_val_if_fail (s != NULL, NULL); g_return_val_if_fail (key != NULL, NULL); @@ -361,9 +370,8 @@ svGetValue (shvarFile *s, const char *key) if (!line_val) return NULL; - value = g_strchomp (g_strdup (line_val)); - svUnescape (value); - return value; + line_val = svUnescape (line_val, &copied); + return copied ?: g_strdup (line_val); } /* Get the value associated with the key, and leave the current pointer diff --git a/src/settings/plugins/ifcfg-rh/shvar.h b/src/settings/plugins/ifcfg-rh/shvar.h index 7525d17e1..43e796d0c 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.h +++ b/src/settings/plugins/ifcfg-rh/shvar.h @@ -81,10 +81,7 @@ gboolean svWriteFile (shvarFile *s, int mode, GError **error); /* Close the file descriptor (if open) and free the shvarFile. */ void svCloseFile (shvarFile *s); -/* Return @s unmodified or an escaped string */ const char *svEscape (const char *s, char **to_free); - -/* Unescape a string in-place */ -void svUnescape (char *s); +const char *svUnescape (const char *s, char **to_free); #endif /* _SHVAR_H */ diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index 1704340c8..ef43f2b79 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -8695,50 +8695,13 @@ test_read_team_port_empty_config (void) g_object_unref (connection); } -/* Old algorithm for "remove escaped characters in place". - * - * This function is obsolete because it has O(n^2) runtime - * complexity and got replaced. Keep it here for testing, - * that both functions behave identical. - **/ -static void -svUnescape_On2 (char *s) -{ - int len, i; - - len = strlen(s); - if (len >= 2 && (s[0] == '"' || s[0] == '\'') && s[0] == s[len-1]) { - i = len - 2; - if (i == 0) - s[0] = '\0'; - else { - memmove(s, s+1, i); - s[i+1] = '\0'; - len = i; - } - } - for (i = 0; i < len; i++) { - if (s[i] == '\\') { - memmove(s+i, s+i+1, len-(i+1)); - len--; - } - s[len] = '\0'; - } -} - static void test_svUnescape_assert (const char *str) { - char *s1 = g_strdup (str); - char *s2 = g_strdup (str); + gs_free char *to_free = NULL; + const char *s; - svUnescape (s1); - svUnescape_On2 (s2); - - g_assert_cmpstr (s1, ==, s2); - - g_free (s1); - g_free (s2); + s = svUnescape (str, &to_free); } static void