summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2013-04-03 19:56:39 +0200
committerLennart Poettering <lennart@poettering.net>2013-04-03 20:12:57 +0200
commit768100efd57ffbbefe9beaa33d1dd5ecc7f69173 (patch)
tree13dc0dd86086cf1985dca2bdbc8c63b060b7d5d7
parentf73141d7657b3f60b8669bc8386413d8a8a372c6 (diff)
fileio: write proper env var write-out code
This will properly escape all weird chars when writing env var files. With this in place we can now read and write environment files where the values contain arbitrary weird chars. This enables hostnamed and suchlike to finally properly save pretty host names with backlashes or quotes in them.
-rw-r--r--src/shared/fileio.c37
-rw-r--r--src/test/test-fileio.c27
2 files changed, 58 insertions, 6 deletions
diff --git a/src/shared/fileio.c b/src/shared/fileio.c
index 96e23c5bbb..2ccb9e7edc 100644
--- a/src/shared/fileio.c
+++ b/src/shared/fileio.c
@@ -522,6 +522,37 @@ int load_env_file(const char *fname, const char *newline, char ***rl) {
return 0;
}
+static void write_env_var(FILE *f, const char *v) {
+ const char *p;
+
+ p = strchr(v, '=');
+ if (!p) {
+ /* Fallback */
+ fputs(v, f);
+ fputc('\n', f);
+ return;
+ }
+
+ p++;
+ fwrite(v, 1, p-v, f);
+
+ if (string_has_cc(p) || chars_intersect(p, WHITESPACE "\'\"\\")) {
+ fputc('\"', f);
+
+ for (; *p; p++) {
+ if (strchr("\'\"\\", *p))
+ fputc('\\', f);
+
+ fputc(*p, f);
+ }
+
+ fputc('\"', f);
+ } else
+ fputs(p, f);
+
+ fputc('\n', f);
+}
+
int write_env_file(const char *fname, char **l) {
char **i;
char _cleanup_free_ *p = NULL;
@@ -535,10 +566,8 @@ int write_env_file(const char *fname, char **l) {
fchmod_umask(fileno(f), 0644);
errno = 0;
- STRV_FOREACH(i, l) {
- fputs(*i, f);
- fputc('\n', f);
- }
+ STRV_FOREACH(i, l)
+ write_env_var(f, *i);
fflush(f);
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index 55eb7539fd..7adf2efdd1 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -32,8 +32,9 @@ static void test_parse_env_file(void) {
int fd, r;
FILE *f;
_cleanup_free_ char *one = NULL, *two = NULL, *three = NULL, *four = NULL, *five = NULL, *six = NULL, *seven = NULL;
- _cleanup_strv_free_ char **a = NULL;
+ _cleanup_strv_free_ char **a = NULL, **b = NULL;
char **i;
+ unsigned k;
fd = mkostemp(t, O_CLOEXEC);
assert_se(fd >= 0);
@@ -90,9 +91,31 @@ static void test_parse_env_file(void) {
assert_se(r >= 0);
STRV_FOREACH(i, a)
- log_info("Got: %s", *i);
+ log_info("Got: <%s>", *i);
+
+ assert_se(streq(a[0], "one=BAR"));
+ assert_se(streq(a[1], "two=bar"));
+ assert_se(streq(a[2], "three=333\nxxxx"));
+ assert_se(streq(a[3], "four=44\"44"));
+ assert_se(streq(a[4], "five=55\'55FIVEcinco"));
+ assert_se(streq(a[5], "six=seis sechs sis"));
+ assert_se(streq(a[6], "seven="));
+ assert_se(a[7] == NULL);
+
+ r = write_env_file("/tmp/test-fileio", a);
+ assert_se(r >= 0);
+
+ r = load_env_file("/tmp/test-fileio", NULL, &b);
+ assert_se(r >= 0);
+
+ k = 0;
+ STRV_FOREACH(i, b) {
+ log_info("Got2: <%s>", *i);
+ assert_se(streq(*i, a[k++]));
+ }
unlink(t);
+ unlink("/tmp/test-fileio");
}
int main(int argc, char *argv[]) {