chiark / gitweb /
fileio: write proper env var write-out code
authorLennart Poettering <lennart@poettering.net>
Wed, 3 Apr 2013 17:56:39 +0000 (19:56 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 3 Apr 2013 18:12:57 +0000 (20:12 +0200)
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.

src/shared/fileio.c
src/test/test-fileio.c

index 96e23c5bbb69c314bdaa65c7ebdef98b81a2780a..2ccb9e7edc70453b6e027e758475881431a05357 100644 (file)
@@ -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);
 
index 55eb7539fd89ad1e38a61142d17c10b5a86dc95e..7adf2efdd1b8ae70261006b97e55999822c27736 100644 (file)
@@ -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[]) {