ifcfg-rh: refactor svSetValue() and svEscape() not to clone string needlessly

In the most cases we don't expect that our values need
escaping. No need to do an additional copy of the unmodified
string.
This commit is contained in:
Thomas Haller 2015-05-20 13:54:25 +02:00
parent 7478c4b54a
commit 32871deecc
3 changed files with 26 additions and 23 deletions

View file

@ -36,6 +36,7 @@
#include "shvar.h"
#include "gsystem-local-alloc.h"
#include "nm-core-internal.h"
#include "nm-logging.h"
@ -206,8 +207,8 @@ static const char escapees[] = "\"'\\$~`"; /* must be escaped */
static const char spaces[] = " \t|&;()<>"; /* only require "" */
static const char newlines[] = "\n\r"; /* will be removed */
char *
svEscape (const char *s)
const char *
svEscape (const char *s, char **to_free)
{
char *new;
int i, j, mangle = 0, space = 0, newline = 0;
@ -223,8 +224,10 @@ svEscape (const char *s)
if (strchr (newlines, s[i]))
newline++;
}
if (!mangle && !space && !newline)
return strdup (s);
if (!mangle && !space && !newline) {
*to_free = NULL;
return s;
}
newlen = slen + mangle - newline + 3; /* 3 is extra ""\0 */
new = g_malloc (newlen);
@ -243,6 +246,7 @@ svEscape (const char *s)
new[j++] = '\0';
g_assert (j == slen + mangle - newline + 3);
*to_free = new;
return new;
}
@ -354,17 +358,19 @@ svGetValueInt64 (shvarFile *s, const char *key, guint base, gint64 min, gint64 m
void
svSetValue (shvarFile *s, const char *key, const char *value, gboolean verbatim)
{
char *newval = NULL, *oldval = NULL;
gs_free char *newval_free = NULL;
gs_free char *oldval = NULL;
const char *newval;
char *keyValue;
g_return_if_fail (s != NULL);
g_return_if_fail (key != NULL);
/* value may be NULL */
if (value)
newval = verbatim ? g_strdup (value) : svEscape (value);
keyValue = g_strdup_printf ("%s=%s", key, newval ? newval : "");
if (!value || verbatim)
newval = value;
else
newval = svEscape (value, &newval_free);
oldval = svGetValue (s, key, FALSE);
if (!newval || !newval[0]) {
@ -376,15 +382,15 @@ svSetValue (shvarFile *s, const char *key, const char *value, gboolean verbatim)
g_list_free_1 (s->current);
s->modified = TRUE;
}
g_free (keyValue);
goto end;
return;
}
keyValue = g_strdup_printf ("%s=%s", key, newval);
if (!oldval) {
/* append line */
s->lineList = g_list_append (s->lineList, keyValue);
s->modified = TRUE;
goto end;
return;
}
if (strcmp (oldval, newval) != 0) {
@ -397,11 +403,6 @@ svSetValue (shvarFile *s, const char *key, const char *value, gboolean verbatim)
s->modified = TRUE;
} else
g_free (keyValue);
end:
g_free (newval);
g_free (oldval);
return;
}
/* Write the current contents iff modified. Returns FALSE on error

View file

@ -84,8 +84,8 @@ gboolean svWriteFile (shvarFile *s, int mode, GError **error);
/* Close the file descriptor (if open) and free the shvarFile. */
void svCloseFile (shvarFile *s);
/* Return a new escaped string */
char *svEscape (const char *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);

View file

@ -889,20 +889,22 @@ write_wireless_setting (NMConnection *connection,
svSetValue (ifcfg, "ESSID", str->str, TRUE);
g_string_free (str, TRUE);
} else {
const char *tmp_escaped;
/* Printable SSIDs always get quoted */
memset (buf, 0, sizeof (buf));
memcpy (buf, ssid_data, ssid_len);
tmp = svEscape (buf);
tmp_escaped = svEscape (buf, &tmp);
/* svEscape will usually quote the string, but just for consistency,
* if svEscape doesn't quote the ESSID, we quote it ourselves.
*/
if (tmp[0] != '"' && tmp[strlen (tmp) - 1] != '"') {
tmp2 = g_strdup_printf ("\"%s\"", tmp);
if (tmp_escaped[0] != '"' && tmp_escaped[strlen (tmp_escaped) - 1] != '"') {
tmp2 = g_strdup_printf ("\"%s\"", tmp_escaped);
svSetValue (ifcfg, "ESSID", tmp2, TRUE);
g_free (tmp2);
} else
svSetValue (ifcfg, "ESSID", tmp, TRUE);
svSetValue (ifcfg, "ESSID", tmp_escaped, TRUE);
g_free (tmp);
}