[systemd-commits] 5 commits - .gitignore Makefile.am src/ask-password src/binfmt src/cgtop src/core src/cryptsetup src/hostname src/journal src/locale src/login src/nspawn src/readahead src/shared src/shutdownd src/sleep src/sysctl src/test src/timedate src/tmpfiles src/udev src/vconsole

Lennart Poettering lennart at kemper.freedesktop.org
Wed Apr 3 11:13:06 PDT 2013


 .gitignore                            |    1 
 Makefile.am                           |   12 
 src/ask-password/ask-password.c       |    2 
 src/binfmt/binfmt.c                   |    6 
 src/cgtop/cgtop.c                     |    2 
 src/core/cgroup-attr.c                |    2 
 src/core/execute.c                    |    4 
 src/core/load-fragment-gperf.gperf.m4 |   16 -
 src/core/load-fragment.c              |    6 
 src/core/machine-id-setup.c           |    2 
 src/core/main.c                       |    4 
 src/core/mount.c                      |    2 
 src/core/unit.c                       |    2 
 src/cryptsetup/cryptsetup.c           |    2 
 src/hostname/hostnamed.c              |    4 
 src/journal/journalctl.c              |    2 
 src/journal/journald-gperf.gperf      |    8 
 src/locale/localed.c                  |    4 
 src/login/logind-dbus.c               |    4 
 src/login/logind-gperf.gperf          |    4 
 src/login/user-sessions.c             |    2 
 src/nspawn/nspawn.c                   |    2 
 src/readahead/readahead-common.c      |    4 
 src/readahead/readahead.c             |    2 
 src/shared/capability.c               |    2 
 src/shared/cgroup-util.c              |   22 -
 src/shared/conf-parser.c              |    4 
 src/shared/conf-parser.h              |    2 
 src/shared/fileio-label.c             |    4 
 src/shared/fileio-label.h             |    2 
 src/shared/fileio.c                   |  456 ++++++++++++++++++++++++----------
 src/shared/fileio.h                   |    6 
 src/shared/time-util.c                |   10 
 src/shared/time-util.h                |    2 
 src/shutdownd/shutdownd.c             |    2 
 src/sleep/sleep.c                     |   10 
 src/sysctl/sysctl.c                   |    2 
 src/test/test-fileio.c                |  124 +++++++++
 src/test/test-unit-file.c             |   50 +--
 src/timedate/timedated.c              |    2 
 src/tmpfiles/tmpfiles.c               |    2 
 src/udev/udevd.c                      |    4 
 src/vconsole/vconsole-setup.c         |    4 
 43 files changed, 568 insertions(+), 241 deletions(-)

New commits:
commit fec6fc6baeca4d306cc70a61a08aef7b69da0172
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 3 20:04:57 2013 +0200

    fileio: don't check for errors more often than really necessary

diff --git a/src/shared/fileio.c b/src/shared/fileio.c
index 2ccb9e7..400a416 100644
--- a/src/shared/fileio.c
+++ b/src/shared/fileio.c
@@ -35,9 +35,7 @@ int write_string_file(const char *fn, const char *line) {
                 return -errno;
 
         errno = 0;
-        if (fputs(line, f) < 0)
-                return errno ? -errno : -EIO;
-
+        fputs(line, f);
         if (!endswith(line, "\n"))
                 fputc('\n', f);
 
@@ -64,11 +62,7 @@ int write_string_file_atomic(const char *fn, const char *line) {
         fchmod_umask(fileno(f), 0644);
 
         errno = 0;
-        if (fputs(line, f) < 0) {
-                r = -errno;
-                goto finish;
-        }
-
+        fputs(line, f);
         if (!endswith(line, "\n"))
                 fputc('\n', f);
 
@@ -83,7 +77,6 @@ int write_string_file_atomic(const char *fn, const char *line) {
                         r = 0;
         }
 
-finish:
         if (r < 0)
                 unlink(p);
 
@@ -571,12 +564,9 @@ int write_env_file(const char *fname, char **l) {
 
         fflush(f);
 
-        if (ferror(f)) {
-                if (errno > 0)
-                        r = -errno;
-                else
-                        r = -EIO;
-        } else {
+        if (ferror(f))
+                r = errno ? -errno : -EIO;
+        else {
                 if (rename(p, fname) < 0)
                         r = -errno;
                 else

commit 768100efd57ffbbefe9beaa33d1dd5ecc7f69173
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 3 19:56:39 2013 +0200

    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.

diff --git a/src/shared/fileio.c b/src/shared/fileio.c
index 96e23c5..2ccb9e7 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 55eb753..7adf2ef 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[]) {

commit f73141d7657b3f60b8669bc8386413d8a8a372c6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 3 19:04:03 2013 +0200

    shared: rework env file reader
    
    Implement this with a proper state machine, so that newlines and
    escaped chars can appear in string assignments. This should bring the
    parser much closer to shell.

diff --git a/.gitignore b/.gitignore
index d38a8a1..c0a340a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -95,6 +95,7 @@
 /test-efivars
 /test-engine
 /test-env-replace
+/test-fileio
 /test-hostname
 /test-id128
 /test-inhibit
diff --git a/Makefile.am b/Makefile.am
index bcd26a4..9341e28 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1087,7 +1087,8 @@ noinst_tests += \
 	test-calendarspec \
 	test-strip-tab-ansi \
 	test-cgroup-util \
-	test-prioq
+	test-prioq \
+	test-fileio
 
 EXTRA_DIST += \
 	test/sched_idle_bad.service \
@@ -1187,6 +1188,15 @@ test_prioq_CFLAGS = \
 test_prioq_LDADD = \
 	libsystemd-core.la
 
+test_fileio_SOURCES = \
+	src/test/test-fileio.c
+
+test_fileio_CFLAGS = \
+	$(AM_CFLAGS)
+
+test_fileio_LDADD = \
+	libsystemd-core.la
+
 test_log_SOURCES = \
 	src/test/test-log.c
 
diff --git a/src/core/execute.c b/src/core/execute.c
index 91815b8..2c13d1f 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -1741,7 +1741,7 @@ int exec_context_load_environment(const ExecContext *c, char ***l) {
                         return -EINVAL;
                 }
                 for (n = 0; n < count; n++) {
-                        k = load_env_file(pglob.gl_pathv[n], &p);
+                        k = load_env_file(pglob.gl_pathv[n], NULL, &p);
                         if (k < 0) {
                                 if (ignore)
                                         continue;
diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
index b4d6d51..aaa2d65 100644
--- a/src/hostname/hostnamed.c
+++ b/src/hostname/hostnamed.c
@@ -303,7 +303,7 @@ static int write_data_other(void) {
         char **l = NULL;
         int r, p;
 
-        r = load_env_file("/etc/machine-info", &l);
+        r = load_env_file("/etc/machine-info", NULL, &l);
         if (r < 0 && r != -ENOENT)
                 return r;
 
diff --git a/src/locale/localed.c b/src/locale/localed.c
index 60083b7..df812ee 100644
--- a/src/locale/localed.c
+++ b/src/locale/localed.c
@@ -355,7 +355,7 @@ static int write_data_locale(void) {
         int r, p;
         char **l = NULL;
 
-        r = load_env_file("/etc/locale.conf", &l);
+        r = load_env_file("/etc/locale.conf", NULL, &l);
         if (r < 0 && r != -ENOENT)
                 return r;
 
@@ -494,7 +494,7 @@ static int write_data_vconsole(void) {
         int r;
         char **l = NULL;
 
-        r = load_env_file("/etc/vconsole.conf", &l);
+        r = load_env_file("/etc/vconsole.conf", NULL, &l);
         if (r < 0 && r != -ENOENT)
                 return r;
 
diff --git a/src/shared/fileio.c b/src/shared/fileio.c
index 5b8be5c..96e23c5 100644
--- a/src/shared/fileio.c
+++ b/src/shared/fileio.c
@@ -177,169 +177,348 @@ int read_full_file(const char *fn, char **contents, size_t *size) {
         return 0;
 }
 
-int parse_env_file(
+static int parse_env_file_internal(
                 const char *fname,
-                const char *separator, ...) {
+                const char *newline,
+                int (*push) (const char *key, char *value, void *userdata),
+                void *userdata) {
+
+        _cleanup_free_ char *contents = NULL, *key = NULL;
+        size_t key_alloc = 0, n_key = 0, value_alloc = 0, n_value = 0, last_whitespace = (size_t) -1;
+        char *p, *value = NULL;
+        int r;
 
-        int r = 0;
-        char *contents = NULL, *p;
+        enum {
+                PRE_KEY,
+                KEY,
+                PRE_EQUAL,
+                PRE_VALUE,
+                VALUE,
+                VALUE_ESCAPE,
+                SINGLE_QUOTE_VALUE,
+                SINGLE_QUOTE_VALUE_ESCAPE,
+                DOUBLE_QUOTE_VALUE,
+                DOUBLE_QUOTE_VALUE_ESCAPE,
+                COMMENT,
+                COMMENT_ESCAPE
+        } state = PRE_KEY;
 
         assert(fname);
-        assert(separator);
+        assert(newline);
 
         r = read_full_file(fname, &contents, NULL);
         if (r < 0)
                 return r;
 
-        p = contents;
-        for (;;) {
-                const char *key = NULL;
+        for (p = contents; *p; p++) {
+                char c = *p;
+
+                switch (state) {
+
+                case PRE_KEY:
+                        if (strchr(COMMENTS, c))
+                                state = COMMENT;
+                        else if (!strchr(WHITESPACE, c)) {
+                                state = KEY;
+                                if (!greedy_realloc((void**) &key, &key_alloc, n_key+2)) {
+                                        r = -ENOMEM;
+                                        goto fail;
+                                }
+
+                                key[n_key++] = c;
+                        }
+                        break;
+
+                case KEY:
+                        if (strchr(newline, c)) {
+                                state = PRE_KEY;
+                                n_key = 0;
+                        } else if (strchr(WHITESPACE, c))
+                                state = PRE_EQUAL;
+                        else if (c == '=')
+                                state = PRE_VALUE;
+                        else {
+                                if (!greedy_realloc((void**) &key, &key_alloc, n_key+2)) {
+                                        r = -ENOMEM;
+                                        goto fail;
+                                }
+
+                                key[n_key++] = c;
+                        }
 
-                p += strspn(p, separator);
-                p += strspn(p, WHITESPACE);
+                        break;
+
+                case PRE_EQUAL:
+                        if (strchr(newline, c)) {
+                                state = PRE_KEY;
+                                n_key = 0;
+                        } else if (c == '=')
+                                state = PRE_VALUE;
+                        else if (!strchr(WHITESPACE, c)) {
+                                n_key = 0;
+                                state = COMMENT;
+                        }
 
-                if (!*p)
                         break;
 
-                if (!strchr(COMMENTS, *p)) {
-                        va_list ap;
-                        char **value;
+                case PRE_VALUE:
+                        if (strchr(newline, c)) {
+                                state = PRE_KEY;
+                                key[n_key] = 0;
 
-                        va_start(ap, separator);
-                        while ((key = va_arg(ap, char *))) {
-                                size_t n;
-                                char *v;
+                                if (value)
+                                        value[n_value] = 0;
 
-                                value = va_arg(ap, char **);
+                                r = push(key, value, userdata);
+                                if (r < 0)
+                                        goto fail;
+
+                                n_key = 0;
+                                value = NULL;
+                                value_alloc = n_value = 0;
+                        } else if (c == '\'')
+                                state = SINGLE_QUOTE_VALUE;
+                        else if (c == '\"')
+                                state = DOUBLE_QUOTE_VALUE;
+                        else if (c == '\\')
+                                state = VALUE_ESCAPE;
+                        else if (!strchr(WHITESPACE, c)) {
+                                state = VALUE;
+
+                                if (!greedy_realloc((void**) &value, &value_alloc, n_value+2)) {
+                                        r = -ENOMEM;
+                                        goto fail;
+                                }
+
+                                value[n_value++] = c;
+                        }
+
+                        break;
+
+                case VALUE:
+                        if (strchr(newline, c)) {
+                                state = PRE_KEY;
+                                key[n_key] = 0;
+
+                                if (value)
+                                        value[n_value] = 0;
+
+                                /* Chomp off trailing whitespace */
+                                if (last_whitespace != (size_t) -1)
+                                        value[last_whitespace] = 0;
+
+                                r = push(key, value, userdata);
+                                if (r < 0)
+                                        goto fail;
+
+                                n_key = 0;
+                                value = NULL;
+                                value_alloc = n_value = 0;
+                        } else if (c == '\\') {
+                                state = VALUE_ESCAPE;
+                                last_whitespace = (size_t) -1;
+                        } else {
+                                if (!strchr(WHITESPACE, c))
+                                        last_whitespace = (size_t) -1;
+                                else if (last_whitespace == (size_t) -1)
+                                        last_whitespace = n_value;
+
+                                if (!greedy_realloc((void**) &value, &value_alloc, n_value+2)) {
+                                        r = -ENOMEM;
+                                        goto fail;
+                                }
+
+                                value[n_value++] = c;
+                        }
+
+                        break;
+
+                case VALUE_ESCAPE:
+                        state = VALUE;
+
+                        if (!strchr(newline, c)) {
+                                /* Escaped newlines we eat up entirely */
+                                if (!greedy_realloc((void**) &value, &value_alloc, n_value+2)) {
+                                        r = -ENOMEM;
+                                        goto fail;
+                                }
+
+                                value[n_value++] = c;
+                        }
+                        break;
+
+                case SINGLE_QUOTE_VALUE:
+                        if (c == '\'')
+                                state = PRE_VALUE;
+                        else if (c == '\\')
+                                state = SINGLE_QUOTE_VALUE_ESCAPE;
+                        else {
+                                if (!greedy_realloc((void**) &value, &value_alloc, n_value+2)) {
+                                        r = -ENOMEM;
+                                        goto fail;
+                                }
 
-                                n = strlen(key);
-                                if (!strneq(p, key, n) ||
-                                    p[n] != '=')
-                                        continue;
+                                value[n_value++] = c;
+                        }
 
-                                p += n + 1;
-                                n = strcspn(p, separator);
+                        break;
 
-                                if (n >= 2 &&
-                                    strchr(QUOTES, p[0]) &&
-                                    p[n-1] == p[0])
-                                        v = strndup(p+1, n-2);
-                                else
-                                        v = strndup(p, n);
+                case SINGLE_QUOTE_VALUE_ESCAPE:
+                        state = SINGLE_QUOTE_VALUE;
 
-                                if (!v) {
+                        if (!strchr(newline, c)) {
+                                if (!greedy_realloc((void**) &value, &value_alloc, n_value+2)) {
                                         r = -ENOMEM;
-                                        va_end(ap);
                                         goto fail;
                                 }
 
-                                if (v[0] == '\0') {
-                                        /* return empty value strings as NULL */
-                                        free(v);
-                                        v = NULL;
+                                value[n_value++] = c;
+                        }
+                        break;
+
+                case DOUBLE_QUOTE_VALUE:
+                        if (c == '\"')
+                                state = PRE_VALUE;
+                        else if (c == '\\')
+                                state = DOUBLE_QUOTE_VALUE_ESCAPE;
+                        else {
+                                if (!greedy_realloc((void**) &value, &value_alloc, n_value+2)) {
+                                        r = -ENOMEM;
+                                        goto fail;
                                 }
 
-                                free(*value);
-                                *value = v;
+                                value[n_value++] = c;
+                        }
+
+                        break;
+
+                case DOUBLE_QUOTE_VALUE_ESCAPE:
+                        state = DOUBLE_QUOTE_VALUE;
 
-                                p += n;
+                        if (!strchr(newline, c)) {
+                                if (!greedy_realloc((void**) &value, &value_alloc, n_value+2)) {
+                                        r = -ENOMEM;
+                                        goto fail;
+                                }
 
-                                r ++;
-                                break;
+                                value[n_value++] = c;
                         }
-                        va_end(ap);
+                        break;
+
+                case COMMENT:
+                        if (c == '\\')
+                                state = COMMENT_ESCAPE;
+                        else if (strchr(newline, c))
+                                state = PRE_KEY;
+                        break;
+
+                case COMMENT_ESCAPE:
+                        state = COMMENT;
+                        break;
                 }
+        }
+
+        if (state == PRE_VALUE ||
+            state == VALUE ||
+            state == VALUE_ESCAPE ||
+            state == SINGLE_QUOTE_VALUE ||
+            state == SINGLE_QUOTE_VALUE_ESCAPE ||
+            state == DOUBLE_QUOTE_VALUE ||
+            state == DOUBLE_QUOTE_VALUE_ESCAPE) {
 
-                if (!key)
-                        p += strcspn(p, separator);
+                key[n_key] = 0;
+
+                if (value)
+                        value[n_value] = 0;
+
+                r = push(key, value, userdata);
+                if (r < 0)
+                        goto fail;
         }
 
+        return 0;
+
 fail:
-        free(contents);
+        free(value);
         return r;
 }
 
-int load_env_file(const char *fname, char ***rl) {
+static int parse_env_file_push(const char *key, char *value, void *userdata) {
+        const char *k;
+        va_list* ap = (va_list*) userdata;
+        va_list aq;
 
-        _cleanup_fclose_ FILE *f;
-        _cleanup_strv_free_ char **m = NULL;
-        _cleanup_free_ char *c = NULL;
+        va_copy(aq, *ap);
 
-        assert(fname);
-        assert(rl);
+        while ((k = va_arg(aq, const char *))) {
+                char **v;
 
-        /* This reads an environment file, but will not complain about
-         * any invalid assignments, that needs to be done by the
-         * caller */
+                v = va_arg(aq, char **);
 
-        f = fopen(fname, "re");
-        if (!f)
-                return -errno;
+                if (streq(key, k)) {
+                        va_end(aq);
+                        free(*v);
+                        *v = value;
+                        return 1;
+                }
+        }
 
-        while (!feof(f)) {
-                char l[LINE_MAX], *p, *cs, *b;
+        va_end(aq);
 
-                if (!fgets(l, sizeof(l), f)) {
-                        if (ferror(f))
-                                return -errno;
+        free(value);
+        return 0;
+}
 
-                        /* The previous line was a continuation line?
-                         * Let's process it now, before we leave the
-                         * loop */
-                        if (c)
-                                goto process;
+int parse_env_file(
+                const char *fname,
+                const char *newline, ...) {
 
-                        break;
-                }
+        va_list ap;
+        int r;
 
-                /* Is this a continuation line? If so, just append
-                 * this to c, and go to next line right-away */
-                cs = endswith(l, "\\\n");
-                if (cs) {
-                        *cs = '\0';
-                        b = strappend(c, l);
-                        if (!b)
-                                return -ENOMEM;
-
-                        free(c);
-                        c = b;
-                        continue;
-                }
+        if (!newline)
+                newline = NEWLINE;
 
-                /* If the previous line was a continuation line,
-                 * append the current line to it */
-                if (c) {
-                        b = strappend(c, l);
-                        if (!b)
-                                return -ENOMEM;
+        va_start(ap, newline);
+        r = parse_env_file_internal(fname, newline, parse_env_file_push, &ap);
+        va_end(ap);
 
-                        free(c);
-                        c = b;
-                }
+        return r;
+}
 
-        process:
-                p = strstrip(c ? c : l);
+static int load_env_file_push(const char *key, char *value, void *userdata) {
+        char ***m = userdata;
+        char *p;
+        int r;
 
-                if (*p && !strchr(COMMENTS, *p)) {
-                        _cleanup_free_ char *u;
-                        int k;
+        p = strjoin(key, "=", strempty(value), NULL);
+        if (!p)
+                return -ENOMEM;
 
-                        u = normalize_env_assignment(p);
-                        if (!u)
-                                return -ENOMEM;
+        r = strv_push(m, p);
+        if (r < 0) {
+                free(p);
+                return r;
+        }
 
-                        k = strv_extend(&m, u);
-                        if (k < 0)
-                                return -ENOMEM;
-                }
+        free(value);
+        return 0;
+}
+
+int load_env_file(const char *fname, const char *newline, char ***rl) {
+        char **m = NULL;
+        int r;
 
-                free(c);
-                c = NULL;
+        if (!newline)
+                newline = NEWLINE;
+
+        r = parse_env_file_internal(fname, newline, load_env_file_push, &m);
+        if (r < 0) {
+                strv_free(m);
+                return r;
         }
 
         *rl = m;
-        m = NULL;
-
         return 0;
 }
 
diff --git a/src/shared/fileio.h b/src/shared/fileio.h
index 612968b..34ed3c1 100644
--- a/src/shared/fileio.h
+++ b/src/shared/fileio.h
@@ -29,5 +29,5 @@ int read_one_line_file(const char *fn, char **line);
 int read_full_file(const char *fn, char **contents, size_t *size);
 
 int parse_env_file(const char *fname, const char *separator, ...) _sentinel_;
-int load_env_file(const char *fname, char ***l);
+int load_env_file(const char *fname, const char *separator, char ***l);
 int write_env_file(const char *fname, char **l);
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
new file mode 100644
index 0000000..55eb753
--- /dev/null
+++ b/src/test/test-fileio.c
@@ -0,0 +1,101 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "util.h"
+#include "fileio.h"
+#include "strv.h"
+
+static void test_parse_env_file(void) {
+        char t[] = "/tmp/test-parse-env-file-XXXXXX";
+        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;
+        char **i;
+
+        fd = mkostemp(t, O_CLOEXEC);
+        assert_se(fd >= 0);
+
+        f = fdopen(fd, "w");
+        assert_se(f);
+
+        fputs("one=BAR   \n"
+              "# comment\n"
+              " # comment \n"
+              "  two   =   bar    \n"
+              "invalid line\n"
+              "three = \"333\n"
+              "xxxx\"\n"
+              "four = \'44\\\"44\'\n"
+              "five = \'55\\\'55\' \"FIVE\" cinco   \n"
+              "six = seis sechs\\\n"
+              " sis\n"
+              "seven=", f);
+
+        fflush(f);
+        fclose(f);
+
+        r = parse_env_file(
+                        t, NULL,
+                       "one", &one,
+                       "two", &two,
+                       "three", &three,
+                       "four", &four,
+                       "five", &five,
+                       "six", &six,
+                       "seven", &seven,
+                       NULL);
+
+        assert_se(r >= 0);
+
+        log_info("one=[%s]", strna(one));
+        log_info("two=[%s]", strna(two));
+        log_info("three=[%s]", strna(three));
+        log_info("four=[%s]", strna(four));
+        log_info("five=[%s]", strna(five));
+        log_info("six=[%s]", strna(six));
+        log_info("seven=[%s]", strna(seven));
+
+        assert_se(streq(one, "BAR"));
+        assert_se(streq(two, "bar"));
+        assert_se(streq(three, "333\nxxxx"));
+        assert_se(streq(four, "44\"44"));
+        assert_se(streq(five, "55\'55FIVEcinco"));
+        assert_se(streq(six, "seis sechs sis"));
+        assert_se(seven == NULL);
+
+        r = load_env_file(t, NULL, &a);
+        assert_se(r >= 0);
+
+        STRV_FOREACH(i, a)
+                log_info("Got: %s", *i);
+
+        unlink(t);
+}
+
+int main(int argc, char *argv[]) {
+        test_parse_env_file();
+        return 0;
+}
diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
index c1a2d4a..3cf8463 100644
--- a/src/test/test-unit-file.c
+++ b/src/test/test-unit-file.c
@@ -180,19 +180,19 @@ static void test_config_parse_exec(void) {
         exec_command_free_list(c);
 }
 
-#define env_file_1 \
-        "a\n"      \
-        "b\\\n"    \
-        "c\n"      \
-        "d\\\n"    \
-        "e\\\n"    \
-        "f\n"      \
-        "g\\ \n"   \
-        "h\n"      \
-        "i\\"
-
-#define env_file_2 \
-        "a\\\n"
+#define env_file_1                              \
+        "a=a\n"                                 \
+        "b=b\\\n"                               \
+        "c\n"                                   \
+        "d=d\\\n"                               \
+        "e\\\n"                                 \
+        "f\n"                                   \
+        "g=g\\ \n"                              \
+        "h=h\n"                                 \
+        "i=i\\"
+
+#define env_file_2                              \
+        "a=a\\\n"
 
 #define env_file_3 \
         "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \
@@ -208,14 +208,14 @@ static void test_load_env_file_1(void) {
         assert(fd >= 0);
         assert_se(write(fd, env_file_1, sizeof(env_file_1)) == sizeof(env_file_1));
 
-        r = load_env_file(name, &data);
+        r = load_env_file(name, NULL, &data);
         assert(r == 0);
-        assert(streq(data[0], "a"));
-        assert(streq(data[1], "bc"));
-        assert(streq(data[2], "def"));
-        assert(streq(data[3], "g\\"));
-        assert(streq(data[4], "h"));
-        assert(streq(data[5], "i\\"));
+        assert(streq(data[0], "a=a"));
+        assert(streq(data[1], "b=bc"));
+        assert(streq(data[2], "d=def"));
+        assert(streq(data[3], "g=g "));
+        assert(streq(data[4], "h=h"));
+        assert(streq(data[5], "i=i"));
         assert(data[6] == NULL);
         unlink(name);
 }
@@ -229,9 +229,9 @@ static void test_load_env_file_2(void) {
         assert(fd >= 0);
         assert_se(write(fd, env_file_2, sizeof(env_file_2)) == sizeof(env_file_2));
 
-        r = load_env_file(name, &data);
+        r = load_env_file(name, NULL, &data);
         assert(r == 0);
-        assert(streq(data[0], "a"));
+        assert(streq(data[0], "a=a"));
         assert(data[1] == NULL);
         unlink(name);
 }
@@ -245,7 +245,7 @@ static void test_load_env_file_3(void) {
         assert(fd >= 0);
         assert_se(write(fd, env_file_3, sizeof(env_file_3)) == sizeof(env_file_3));
 
-        r = load_env_file(name, &data);
+        r = load_env_file(name, NULL, &data);
         assert(r == 0);
         assert(data == NULL);
         unlink(name);
@@ -272,7 +272,7 @@ static void test_install_printf(void) {
         assert_se((host = gethostname_malloc()));
 
 #define expect(src, pattern, result)                                    \
-        {                                                               \
+        do {                                                            \
                 char _cleanup_free_ *t = install_full_printf(&src, pattern); \
                 char _cleanup_free_                                     \
                         *d1 = strdup(i.name),                           \
@@ -289,7 +289,7 @@ static void test_install_printf(void) {
                 strcpy(i.name, d1);                                     \
                 strcpy(i.path, d2);                                     \
                 strcpy(i.user, d3);                                     \
-        }
+        } while(false)
 
         assert_se(setenv("USER", "root", 1) == 0);
 

commit 7f602784de4fd378120e8ebfe6d830862b9cae03
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Apr 2 20:38:16 2013 +0200

    util: rename parse_usec() to parse_sec() sinds the default unit is seconds
    
    Internally we store all time values in usec_t, however parse_usec()
    actually was used mostly to parse values in seconds (unless explicit
    units were specified to define a different unit). Hence, be clear about
    this and name the function about what we pass into it, not what we get
    out of it.

diff --git a/src/ask-password/ask-password.c b/src/ask-password/ask-password.c
index 5f67570..238cf12 100644
--- a/src/ask-password/ask-password.c
+++ b/src/ask-password/ask-password.c
@@ -102,7 +102,7 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_TIMEOUT:
-                        if (parse_usec(optarg, &arg_timeout) < 0) {
+                        if (parse_sec(optarg, &arg_timeout) < 0) {
                                 log_error("Failed to parse --timeout parameter %s", optarg);
                                 return -EINVAL;
                         }
diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c
index 3016734..280470d 100644
--- a/src/cgtop/cgtop.c
+++ b/src/cgtop/cgtop.c
@@ -629,7 +629,7 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case 'd':
-                        r = parse_usec(optarg, &arg_delay);
+                        r = parse_sec(optarg, &arg_delay);
                         if (r < 0 || arg_delay <= 0) {
                                 log_error("Failed to parse delay parameter.");
                                 return -EINVAL;
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 3643bcd..d5e579f 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -90,7 +90,7 @@ $1.ControlGroupModify,           config_parse_bool,                  0,
 $1.ControlGroupPersistent,       config_parse_tristate,              0,                             offsetof($1, exec_context.control_group_persistent)'
 )m4_dnl
 m4_define(`KILL_CONTEXT_CONFIG_ITEMS',
-`$1.SendSIGKILL,                  config_parse_bool,                  0,                             offsetof($1, kill_context.send_sigkill)
+`$1.SendSIGKILL,                 config_parse_bool,                  0,                             offsetof($1, kill_context.send_sigkill)
 $1.KillMode,                     config_parse_kill_mode,             0,                             offsetof($1, kill_context.kill_mode)
 $1.KillSignal,                   config_parse_kill_signal,           0,                             offsetof($1, kill_context.kill_signal)'
 )m4_dnl
@@ -122,7 +122,7 @@ Unit.DefaultDependencies,        config_parse_bool,                  0,
 Unit.OnFailureIsolate,           config_parse_bool,                  0,                             offsetof(Unit, on_failure_isolate)
 Unit.IgnoreOnIsolate,            config_parse_bool,                  0,                             offsetof(Unit, ignore_on_isolate)
 Unit.IgnoreOnSnapshot,           config_parse_bool,                  0,                             offsetof(Unit, ignore_on_snapshot)
-Unit.JobTimeoutSec,              config_parse_usec,                  0,                             offsetof(Unit, job_timeout)
+Unit.JobTimeoutSec,              config_parse_sec,                   0,                             offsetof(Unit, job_timeout)
 Unit.ConditionPathExists,        config_parse_unit_condition_path,   CONDITION_PATH_EXISTS,         0
 Unit.ConditionPathExistsGlob,    config_parse_unit_condition_path,   CONDITION_PATH_EXISTS_GLOB,    0
 Unit.ConditionPathIsDirectory,   config_parse_unit_condition_path,   CONDITION_PATH_IS_DIRECTORY,   0
@@ -147,12 +147,12 @@ Service.ExecStartPost,           config_parse_exec,                  SERVICE_EXE
 Service.ExecReload,              config_parse_exec,                  SERVICE_EXEC_RELOAD,           offsetof(Service, exec_command)
 Service.ExecStop,                config_parse_exec,                  SERVICE_EXEC_STOP,             offsetof(Service, exec_command)
 Service.ExecStopPost,            config_parse_exec,                  SERVICE_EXEC_STOP_POST,        offsetof(Service, exec_command)
-Service.RestartSec,              config_parse_usec,                  0,                             offsetof(Service, restart_usec)
+Service.RestartSec,              config_parse_sec,                   0,                             offsetof(Service, restart_usec)
 Service.TimeoutSec,              config_parse_service_timeout,       0,                             offsetof(Service, timeout_start_usec)
 Service.TimeoutStartSec,         config_parse_service_timeout,       0,                             offsetof(Service, timeout_start_usec)
 Service.TimeoutStopSec,          config_parse_service_timeout,       0,                             offsetof(Service, timeout_stop_usec)
-Service.WatchdogSec,             config_parse_usec,                  0,                             offsetof(Service, watchdog_usec)
-Service.StartLimitInterval,      config_parse_usec,                  0,                             offsetof(Service, start_limit.interval)
+Service.WatchdogSec,             config_parse_sec,                   0,                             offsetof(Service, watchdog_usec)
+Service.StartLimitInterval,      config_parse_sec,                   0,                             offsetof(Service, start_limit.interval)
 Service.StartLimitBurst,         config_parse_unsigned,              0,                             offsetof(Service, start_limit.burst)
 Service.StartLimitAction,        config_parse_start_limit_action,    0,                             offsetof(Service, start_limit_action)
 Service.Type,                    config_parse_service_type,          0,                             offsetof(Service, type)
@@ -188,7 +188,7 @@ Socket.ExecStartPre,             config_parse_exec,                  SOCKET_EXEC
 Socket.ExecStartPost,            config_parse_exec,                  SOCKET_EXEC_START_POST,        offsetof(Socket, exec_command)
 Socket.ExecStopPre,              config_parse_exec,                  SOCKET_EXEC_STOP_PRE,          offsetof(Socket, exec_command)
 Socket.ExecStopPost,             config_parse_exec,                  SOCKET_EXEC_STOP_POST,         offsetof(Socket, exec_command)
-Socket.TimeoutSec,               config_parse_usec,                  0,                             offsetof(Socket, timeout_usec)
+Socket.TimeoutSec,               config_parse_sec,                   0,                             offsetof(Socket, timeout_usec)
 Socket.DirectoryMode,            config_parse_mode,                  0,                             offsetof(Socket, directory_mode)
 Socket.SocketMode,               config_parse_mode,                  0,                             offsetof(Socket, socket_mode)
 Socket.Accept,                   config_parse_bool,                  0,                             offsetof(Socket, accept)
@@ -221,7 +221,7 @@ Mount.Where,                     config_parse_path,                  0,
 Mount.Options,                   config_parse_string,                0,                             offsetof(Mount, parameters_fragment.options)
 Mount.Type,                      config_parse_string,                0,                             offsetof(Mount, parameters_fragment.fstype)
 Mount.FsckPassNo,                config_parse_fsck_passno,           0,                             offsetof(Mount, parameters_fragment.passno)
-Mount.TimeoutSec,                config_parse_usec,                  0,                             offsetof(Mount, timeout_usec)
+Mount.TimeoutSec,                config_parse_sec,                   0,                             offsetof(Mount, timeout_usec)
 Mount.DirectoryMode,             config_parse_mode,                  0,                             offsetof(Mount, directory_mode)
 EXEC_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl
 KILL_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl
@@ -231,7 +231,7 @@ Automount.DirectoryMode,         config_parse_mode,                  0,
 m4_dnl
 Swap.What,                       config_parse_path,                  0,                             offsetof(Swap, parameters_fragment.what)
 Swap.Priority,                   config_parse_int,                   0,                             offsetof(Swap, parameters_fragment.priority)
-Swap.TimeoutSec,                 config_parse_usec,                  0,                             offsetof(Swap, timeout_usec)
+Swap.TimeoutSec,                 config_parse_sec,                   0,                             offsetof(Swap, timeout_usec)
 EXEC_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl
 KILL_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl
 m4_dnl
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 65a2a39..42c181d 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -1186,7 +1186,7 @@ int config_parse_timer(
 
                 id = CLOCK_REALTIME;
         } else {
-                if (parse_usec(rvalue, &u) < 0) {
+                if (parse_sec(rvalue, &u) < 0) {
                         log_error("[%s:%u] Failed to parse timer value, ignoring: %s", filename, line, rvalue);
                         return 0;
                 }
@@ -1471,7 +1471,7 @@ int config_parse_service_timeout(
         assert(rvalue);
         assert(s);
 
-        r = config_parse_usec(filename, line, section, lvalue, ltype, rvalue, data, userdata);
+        r = config_parse_sec(filename, line, section, lvalue, ltype, rvalue, data, userdata);
         if (r < 0)
                 return r;
 
@@ -2395,7 +2395,7 @@ void unit_dump_config_items(FILE *f) {
                 { config_parse_socket_listen,         "SOCKET [...]" },
                 { config_parse_socket_bind,           "SOCKETBIND" },
                 { config_parse_socket_bindtodevice,   "NETWORKINTERFACE" },
-                { config_parse_usec,                  "SECONDS" },
+                { config_parse_sec,                   "SECONDS" },
                 { config_parse_nsec,                  "NANOSECONDS" },
                 { config_parse_path_strv,             "PATH [...]" },
                 { config_parse_unit_requires_mounts_for, "PATH [...]" },
diff --git a/src/core/main.c b/src/core/main.c
index 35cd772..aa28cc6 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -684,8 +684,8 @@ static int parse_config_file(void) {
                 { "Manager", "DefaultStandardOutput", config_parse_output,       0, &arg_default_std_output  },
                 { "Manager", "DefaultStandardError",  config_parse_output,       0, &arg_default_std_error   },
                 { "Manager", "JoinControllers",       config_parse_join_controllers, 0, &arg_join_controllers },
-                { "Manager", "RuntimeWatchdogSec",    config_parse_usec,         0, &arg_runtime_watchdog    },
-                { "Manager", "ShutdownWatchdogSec",   config_parse_usec,         0, &arg_shutdown_watchdog   },
+                { "Manager", "RuntimeWatchdogSec",    config_parse_sec,          0, &arg_runtime_watchdog    },
+                { "Manager", "ShutdownWatchdogSec",   config_parse_sec,          0, &arg_shutdown_watchdog   },
                 { "Manager", "CapabilityBoundingSet", config_parse_bounding_set, 0, &arg_capability_bounding_set_drop },
                 { "Manager", "TimerSlackNSec",        config_parse_nsec,         0, &arg_timer_slack_nsec    },
                 { "Manager", "DefaultLimitCPU",       config_parse_limit,        0, &arg_default_rlimit[RLIMIT_CPU]},
diff --git a/src/core/mount.c b/src/core/mount.c
index 130dc39..51a81a9 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -520,7 +520,7 @@ static int mount_fix_timeouts(Mount *m) {
         if (!t)
                 return -ENOMEM;
 
-        r = parse_usec(t, &u);
+        r = parse_sec(t, &u);
         free(t);
 
         if (r < 0) {
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
index d5dc233..51d4f99 100644
--- a/src/cryptsetup/cryptsetup.c
+++ b/src/cryptsetup/cryptsetup.c
@@ -127,7 +127,7 @@ static int parse_one_option(const char *option) {
                 opt_type = CRYPT_PLAIN;
         else if (startswith(option, "timeout=")) {
 
-                if (parse_usec(option+8, &opt_timeout) < 0) {
+                if (parse_sec(option+8, &opt_timeout) < 0) {
                         log_error("timeout= parse failure, ignoring.");
                         return 0;
                 }
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index 8661e5e..642e20d 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -355,7 +355,7 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_INTERVAL:
-                        r = parse_usec(optarg, &arg_interval);
+                        r = parse_sec(optarg, &arg_interval);
                         if (r < 0 || arg_interval <= 0) {
                                 log_error("Failed to parse sealing key change interval: %s", optarg);
                                 return -EINVAL;
diff --git a/src/journal/journald-gperf.gperf b/src/journal/journald-gperf.gperf
index 57b45f9..2ecba3b 100644
--- a/src/journal/journald-gperf.gperf
+++ b/src/journal/journald-gperf.gperf
@@ -18,8 +18,8 @@ struct ConfigPerfItem;
 Journal.Storage,            config_parse_storage,   0, offsetof(Server, storage)
 Journal.Compress,           config_parse_bool,      0, offsetof(Server, compress)
 Journal.Seal,               config_parse_bool,      0, offsetof(Server, seal)
-Journal.SyncIntervalSec,    config_parse_usec,      0, offsetof(Server, sync_interval_usec)
-Journal.RateLimitInterval,  config_parse_usec,      0, offsetof(Server, rate_limit_interval)
+Journal.SyncIntervalSec,    config_parse_sec,       0, offsetof(Server, sync_interval_usec)
+Journal.RateLimitInterval,  config_parse_sec,       0, offsetof(Server, rate_limit_interval)
 Journal.RateLimitBurst,     config_parse_unsigned,  0, offsetof(Server, rate_limit_burst)
 Journal.SystemMaxUse,       config_parse_bytes_off, 0, offsetof(Server, system_metrics.max_use)
 Journal.SystemMaxFileSize,  config_parse_bytes_off, 0, offsetof(Server, system_metrics.max_size)
@@ -27,8 +27,8 @@ Journal.SystemKeepFree,     config_parse_bytes_off, 0, offsetof(Server, system_m
 Journal.RuntimeMaxUse,      config_parse_bytes_off, 0, offsetof(Server, runtime_metrics.max_use)
 Journal.RuntimeMaxFileSize, config_parse_bytes_off, 0, offsetof(Server, runtime_metrics.max_size)
 Journal.RuntimeKeepFree,    config_parse_bytes_off, 0, offsetof(Server, runtime_metrics.keep_free)
-Journal.MaxRetentionSec,    config_parse_usec,      0, offsetof(Server, max_retention_usec)
-Journal.MaxFileSec,         config_parse_usec,      0, offsetof(Server, max_file_usec)
+Journal.MaxRetentionSec,    config_parse_sec,       0, offsetof(Server, max_retention_usec)
+Journal.MaxFileSec,         config_parse_sec,       0, offsetof(Server, max_file_usec)
 Journal.ForwardToSyslog,    config_parse_bool,      0, offsetof(Server, forward_to_syslog)
 Journal.ForwardToKMsg,      config_parse_bool,      0, offsetof(Server, forward_to_kmsg)
 Journal.ForwardToConsole,   config_parse_bool,      0, offsetof(Server, forward_to_console)
diff --git a/src/login/logind-gperf.gperf b/src/login/logind-gperf.gperf
index 076d116..735d2db 100644
--- a/src/login/logind-gperf.gperf
+++ b/src/login/logind-gperf.gperf
@@ -21,7 +21,7 @@ Login.KillOnlyUsers,               config_parse_strv,          0, offsetof(Manag
 Login.KillExcludeUsers,            config_parse_strv,          0, offsetof(Manager, kill_exclude_users)
 Login.Controllers,                 config_parse_strv,          0, offsetof(Manager, controllers)
 Login.ResetControllers,            config_parse_strv,          0, offsetof(Manager, reset_controllers)
-Login.InhibitDelayMaxSec,          config_parse_usec,          0, offsetof(Manager, inhibit_delay_max)
+Login.InhibitDelayMaxSec,          config_parse_sec,           0, offsetof(Manager, inhibit_delay_max)
 Login.HandlePowerKey,              config_parse_handle_action, 0, offsetof(Manager, handle_power_key)
 Login.HandleSuspendKey,            config_parse_handle_action, 0, offsetof(Manager, handle_suspend_key)
 Login.HandleHibernateKey,          config_parse_handle_action, 0, offsetof(Manager, handle_hibernate_key)
@@ -31,4 +31,4 @@ Login.SuspendKeyIgnoreInhibited,   config_parse_bool,          0, offsetof(Manag
 Login.HibernateKeyIgnoreInhibited, config_parse_bool,          0, offsetof(Manager, hibernate_key_ignore_inhibited)
 Login.LidSwitchIgnoreInhibited,    config_parse_bool,          0, offsetof(Manager, lid_switch_ignore_inhibited)
 Login.IdleAction,                  config_parse_handle_action, 0, offsetof(Manager, idle_action)
-Login.IdleActionSec,               config_parse_usec,          0, offsetof(Manager, idle_action_usec)
+Login.IdleActionSec,               config_parse_sec,           0, offsetof(Manager, idle_action_usec)
diff --git a/src/readahead/readahead.c b/src/readahead/readahead.c
index abeecc7..29255c9 100644
--- a/src/readahead/readahead.c
+++ b/src/readahead/readahead.c
@@ -108,7 +108,7 @@ static int parse_argv(int argc, char *argv[]) {
                 }
 
                 case ARG_TIMEOUT:
-                        if (parse_usec(optarg, &arg_timeout) < 0 || arg_timeout <= 0) {
+                        if (parse_sec(optarg, &arg_timeout) < 0 || arg_timeout <= 0) {
                                 log_error("Failed to parse timeout %s.", optarg);
                                 return -EINVAL;
                         }
diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c
index c2cf5a6..a87df38 100644
--- a/src/shared/conf-parser.c
+++ b/src/shared/conf-parser.c
@@ -792,7 +792,7 @@ int config_parse_path_strv(
         return 0;
 }
 
-int config_parse_usec(
+int config_parse_sec(
                 const char *filename,
                 unsigned line,
                 const char *section,
@@ -809,7 +809,7 @@ int config_parse_usec(
         assert(rvalue);
         assert(data);
 
-        if (parse_usec(rvalue, usec) < 0) {
+        if (parse_sec(rvalue, usec) < 0) {
                 log_error("[%s:%u] Failed to parse time value, ignoring: %s", filename, line, rvalue);
                 return 0;
         }
diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h
index 9096c60..88194f6 100644
--- a/src/shared/conf-parser.h
+++ b/src/shared/conf-parser.h
@@ -101,7 +101,7 @@ int config_parse_string(const char *filename, unsigned line, const char *section
 int config_parse_path(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_strv(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_path_strv(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_usec(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_sec(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_nsec(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_mode(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_facility(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/shared/time-util.c b/src/shared/time-util.c
index 0c6deb6..e27aaf6 100644
--- a/src/shared/time-util.c
+++ b/src/shared/time-util.c
@@ -256,7 +256,7 @@ char *format_timespan(char *buf, size_t l, usec_t t) {
                 return p;
         }
 
-        /* The result of this function can be parsed with parse_usec */
+        /* The result of this function can be parsed with parse_sec */
 
         for (i = 0; i < ELEMENTSOF(table); i++) {
                 int k;
@@ -382,14 +382,14 @@ int parse_timestamp(const char *t, usec_t *usec) {
 
         } else if (t[0] == '+') {
 
-                r = parse_usec(t+1, &plus);
+                r = parse_sec(t+1, &plus);
                 if (r < 0)
                         return r;
 
                 goto finish;
         } else if (t[0] == '-') {
 
-                r = parse_usec(t+1, &minus);
+                r = parse_sec(t+1, &minus);
                 if (r < 0)
                         return r;
 
@@ -402,7 +402,7 @@ int parse_timestamp(const char *t, usec_t *usec) {
                 if (!z)
                         return -ENOMEM;
 
-                r = parse_usec(z, &minus);
+                r = parse_sec(z, &minus);
                 if (r < 0)
                         return r;
 
@@ -497,7 +497,7 @@ finish:
         return 0;
 }
 
-int parse_usec(const char *t, usec_t *usec) {
+int parse_sec(const char *t, usec_t *usec) {
         static const struct {
                 const char *suffix;
                 usec_t usec;
diff --git a/src/shared/time-util.h b/src/shared/time-util.h
index ec263c1..2e3b0f5 100644
--- a/src/shared/time-util.h
+++ b/src/shared/time-util.h
@@ -80,5 +80,5 @@ void dual_timestamp_deserialize(const char *value, dual_timestamp *t);
 
 int parse_timestamp(const char *t, usec_t *usec);
 
-int parse_usec(const char *t, usec_t *usec);
+int parse_sec(const char *t, usec_t *usec);
 int parse_nsec(const char *t, nsec_t *nsec);
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 0b168f0..84f4986 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -1171,7 +1171,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
                         a++;
                 }
 
-                if (parse_usec(a, &i->age) < 0) {
+                if (parse_sec(a, &i->age) < 0) {
                         log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
                         return -EBADMSG;
                 }

commit 574d5f2dfc25226afc718aa5ba1a145fe5cad221
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Apr 2 20:31:42 2013 +0200

    util: rename write_one_line_file() to write_string_file()
    
    You can write much more than just one line with this call (and we
    frequently do), so let's correct the naming.

diff --git a/src/binfmt/binfmt.c b/src/binfmt/binfmt.c
index 909eef7..9ca1e60 100644
--- a/src/binfmt/binfmt.c
+++ b/src/binfmt/binfmt.c
@@ -62,7 +62,7 @@ static int delete_rule(const char *rule) {
         if (!fn)
                 return log_oom();
 
-        return write_one_line_file(fn, "-1");
+        return write_string_file(fn, "-1");
 }
 
 static int apply_rule(const char *rule) {
@@ -70,7 +70,7 @@ static int apply_rule(const char *rule) {
 
         delete_rule(rule);
 
-        r = write_one_line_file("/proc/sys/fs/binfmt_misc/register", rule);
+        r = write_string_file("/proc/sys/fs/binfmt_misc/register", rule);
         if (r < 0) {
                 log_error("Failed to add binary format: %s", strerror(-r));
                 return r;
@@ -197,7 +197,7 @@ int main(int argc, char *argv[]) {
                 }
 
                 /* Flush out all rules */
-                write_one_line_file("/proc/sys/fs/binfmt_misc/status", "-1");
+                write_string_file("/proc/sys/fs/binfmt_misc/status", "-1");
 
                 STRV_FOREACH(f, files) {
                         k = apply_file(*f, true);
diff --git a/src/core/cgroup-attr.c b/src/core/cgroup-attr.c
index 2ab4d46..7e3e08e 100644
--- a/src/core/cgroup-attr.c
+++ b/src/core/cgroup-attr.c
@@ -44,7 +44,7 @@ int cgroup_attribute_apply(CGroupAttribute *a, CGroupBonding *b) {
         if (r < 0)
                 return r;
 
-        r = write_one_line_file(path, v ? v : a->value);
+        r = write_string_file(path, v ? v : a->value);
         if (r < 0)
                 log_warning("Failed to write '%s' to %s: %s", v ? v : a->value, path, strerror(-r));
 
diff --git a/src/core/execute.c b/src/core/execute.c
index f735357..91815b8 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -1195,7 +1195,7 @@ int exec_spawn(ExecCommand *command,
                         snprintf(t, sizeof(t), "%i", context->oom_score_adjust);
                         char_array_0(t);
 
-                        if (write_one_line_file("/proc/self/oom_score_adj", t) < 0) {
+                        if (write_string_file("/proc/self/oom_score_adj", t) < 0) {
                                 err = -errno;
                                 r = EXIT_OOM_ADJUST;
                                 goto fail_child;
diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c
index 146c565..51074fe 100644
--- a/src/core/machine-id-setup.c
+++ b/src/core/machine-id-setup.c
@@ -216,7 +216,7 @@ int machine_id_setup(void) {
          * /run/machine-id as a replacement */
 
         m = umask(0022);
-        r = write_one_line_file("/run/machine-id", id);
+        r = write_string_file("/run/machine-id", id);
         umask(m);
 
         if (r < 0) {
diff --git a/src/core/unit.c b/src/core/unit.c
index 91a00ed..a0d3656 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -2910,7 +2910,7 @@ int unit_write_drop_in(Unit *u, bool runtime, const char *name, const char *data
                 return r;
 
         mkdir_p(p, 0755);
-        return write_one_line_file_atomic_label(q, data);
+        return write_string_file_atomic_label(q, data);
 }
 
 int unit_remove_drop_in(Unit *u, bool runtime, const char *name) {
diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
index 859b5a0..b4d6d51 100644
--- a/src/hostname/hostnamed.c
+++ b/src/hostname/hostnamed.c
@@ -289,7 +289,7 @@ static int write_data_static_hostname(void) {
 
                 return 0;
         }
-        return write_one_line_file_atomic_label("/etc/hostname", data[PROP_STATIC_HOSTNAME]);
+        return write_string_file_atomic_label("/etc/hostname", data[PROP_STATIC_HOSTNAME]);
 }
 
 static int write_data_other(void) {
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 4ae8362..aa212d1 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -886,7 +886,7 @@ static int trigger_device(Manager *m, struct udev_device *d) {
                         goto finish;
                 }
 
-                write_one_line_file(t, "change");
+                write_string_file(t, "change");
                 free(t);
         }
 
@@ -936,7 +936,7 @@ static int attach_device(Manager *m, const char *seat, const char *sysfs) {
 
         mkdir_p_label("/etc/udev/rules.d", 0755);
         label_init("/etc");
-        r = write_one_line_file_atomic_label(file, rule);
+        r = write_string_file_atomic_label(file, rule);
         if (r < 0)
                 goto finish;
 
diff --git a/src/login/user-sessions.c b/src/login/user-sessions.c
index c6f8fa7..41d3204 100644
--- a/src/login/user-sessions.c
+++ b/src/login/user-sessions.c
@@ -70,7 +70,7 @@ int main(int argc, char*argv[]) {
                 int r, q;
                 char *cgroup_user_tree = NULL;
 
-                r = write_one_line_file_atomic("/run/nologin", "System is going down.");
+                r = write_string_file_atomic("/run/nologin", "System is going down.");
                 if (r < 0)
                         log_error("Failed to create /run/nologin: %s", strerror(-r));
 
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index b8b692b..01ef12b 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -528,7 +528,7 @@ static int setup_boot_id(const char *dest) {
                  SD_ID128_FORMAT_VAL(rnd));
         char_array_0(as_uuid);
 
-        r = write_one_line_file(from, as_uuid);
+        r = write_string_file(from, as_uuid);
         if (r < 0) {
                 log_error("Failed to write boot id: %s", strerror(-r));
                 return r;
diff --git a/src/readahead/readahead-common.c b/src/readahead/readahead-common.c
index 81bb16c..ed81c14 100644
--- a/src/readahead/readahead-common.c
+++ b/src/readahead/readahead-common.c
@@ -316,7 +316,7 @@ int block_bump_request_nr(const char *p) {
                 goto finish;
         }
 
-        r = write_one_line_file(ap, line);
+        r = write_string_file(ap, line);
         if (r < 0)
                 goto finish;
 
@@ -399,7 +399,7 @@ int block_set_readahead(const char *p, uint64_t bytes) {
                 goto finish;
         }
 
-        r = write_one_line_file(ap, line);
+        r = write_string_file(ap, line);
         if (r < 0)
                 goto finish;
 
diff --git a/src/shared/capability.c b/src/shared/capability.c
index cad718d..3219520 100644
--- a/src/shared/capability.c
+++ b/src/shared/capability.c
@@ -204,7 +204,7 @@ static int drop_from_file(const char *fn, uint64_t drop) {
         if (asprintf(&p, "%u %u", lo, hi) < 0)
                 return -ENOMEM;
 
-        r = write_one_line_file(fn, p);
+        r = write_string_file(fn, p);
         free(p);
 
         return r;
diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c
index be00b40..15e1b7c 100644
--- a/src/shared/cgroup-util.c
+++ b/src/shared/cgroup-util.c
@@ -677,9 +677,9 @@ int cg_delete(const char *controller, const char *path) {
 }
 
 int cg_attach(const char *controller, const char *path, pid_t pid) {
-        char *fs;
+        _cleanup_free_ char *fs = NULL;
+        char c[DECIMAL_STR_MAX(pid_t) + 2];
         int r;
-        char c[32];
 
         assert(controller);
         assert(path);
@@ -693,16 +693,12 @@ int cg_attach(const char *controller, const char *path, pid_t pid) {
                 pid = getpid();
 
         snprintf(c, sizeof(c), "%lu\n", (unsigned long) pid);
-        char_array_0(c);
-
-        r = write_one_line_file(fs, c);
-        free(fs);
 
-        return r;
+        return write_string_file(fs, c);
 }
 
 int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) {
-        char *fs;
+        _cleanup_free_ char *fs = NULL;
         int r;
 
         assert(controller);
@@ -715,10 +711,7 @@ int cg_set_group_access(const char *controller, const char *path, mode_t mode, u
         if (r < 0)
                 return r;
 
-        r = chmod_and_chown(fs, mode, uid, gid);
-        free(fs);
-
-        return r;
+        return chmod_and_chown(fs, mode, uid, gid);
 }
 
 int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid, int sticky) {
@@ -857,7 +850,8 @@ int cg_install_release_agent(const char *controller, const char *agent) {
                         goto finish;
                 }
 
-                if ((r = write_one_line_file(fs, line)) < 0)
+                r = write_string_file(fs, line);
+                if (r < 0)
                         goto finish;
 
         } else if (!streq(sc, agent)) {
@@ -878,7 +872,7 @@ int cg_install_release_agent(const char *controller, const char *agent) {
         sc = strstrip(contents);
 
         if (streq(sc, "0")) {
-                if ((r = write_one_line_file(fs, "1\n")) < 0)
+                if ((r = write_string_file(fs, "1\n")) < 0)
                         goto finish;
 
                 r = 1;
diff --git a/src/shared/fileio-label.c b/src/shared/fileio-label.c
index 5bf127b..0711826 100644
--- a/src/shared/fileio-label.c
+++ b/src/shared/fileio-label.c
@@ -26,14 +26,14 @@
 #include "fileio-label.h"
 #include "label.h"
 
-int write_one_line_file_atomic_label(const char *fn, const char *line) {
+int write_string_file_atomic_label(const char *fn, const char *line) {
         int r;
 
         r = label_context_set(fn, S_IFREG);
         if (r  < 0)
                 return r;
 
-        write_one_line_file_atomic(fn, line);
+        write_string_file_atomic(fn, line);
 
         label_context_clear();
 
diff --git a/src/shared/fileio-label.h b/src/shared/fileio-label.h
index cc5ce34..fce4fe0 100644
--- a/src/shared/fileio-label.h
+++ b/src/shared/fileio-label.h
@@ -25,5 +25,5 @@
 #include <stdio.h>
 #include "fileio.h"
 
-int write_one_line_file_atomic_label(const char *fn, const char *line);
+int write_string_file_atomic_label(const char *fn, const char *line);
 int write_env_file_label(const char *fname, char **l);
diff --git a/src/shared/fileio.c b/src/shared/fileio.c
index 1c7d485..5b8be5c 100644
--- a/src/shared/fileio.c
+++ b/src/shared/fileio.c
@@ -24,7 +24,7 @@
 #include "util.h"
 #include "strv.h"
 
-int write_one_line_file(const char *fn, const char *line) {
+int write_string_file(const char *fn, const char *line) {
         _cleanup_fclose_ FILE *f = NULL;
 
         assert(fn);
@@ -49,7 +49,7 @@ int write_one_line_file(const char *fn, const char *line) {
         return 0;
 }
 
-int write_one_line_file_atomic(const char *fn, const char *line) {
+int write_string_file_atomic(const char *fn, const char *line) {
         _cleanup_fclose_ FILE *f = NULL;
         _cleanup_free_ char *p = NULL;
         int r;
diff --git a/src/shared/fileio.h b/src/shared/fileio.h
index 0023204..612968b 100644
--- a/src/shared/fileio.h
+++ b/src/shared/fileio.h
@@ -23,8 +23,8 @@
 #include <stddef.h>
 #include "macro.h"
 
-int write_one_line_file(const char *fn, const char *line);
-int write_one_line_file_atomic(const char *fn, const char *line);
+int write_string_file(const char *fn, const char *line);
+int write_string_file_atomic(const char *fn, const char *line);
 int read_one_line_file(const char *fn, char **line);
 int read_full_file(const char *fn, char **contents, size_t *size);
 
diff --git a/src/shutdownd/shutdownd.c b/src/shutdownd/shutdownd.c
index 119385d..ee2a328 100644
--- a/src/shutdownd/shutdownd.c
+++ b/src/shutdownd/shutdownd.c
@@ -421,7 +421,7 @@ int main(int argc, char *argv[]) {
 
                         log_info("Creating /run/nologin, blocking further logins...");
 
-                        e = write_one_line_file_atomic("/run/nologin", "System is going down.");
+                        e = write_string_file_atomic("/run/nologin", "System is going down.");
                         if (e < 0)
                                 log_error("Failed to create /run/nologin: %s", strerror(-e));
                         else
diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c
index 0707625..f5e78c1 100644
--- a/src/sleep/sleep.c
+++ b/src/sleep/sleep.c
@@ -57,12 +57,12 @@ int main(int argc, char *argv[]) {
 
         /* Configure the hibernation mode */
         if (streq(argv[1], "hibernate")) {
-                if (write_one_line_file("/sys/power/disk", "platform") < 0)
-                        write_one_line_file("/sys/power/disk", "shutdown");
+                if (write_string_file("/sys/power/disk", "platform") < 0)
+                        write_string_file("/sys/power/disk", "shutdown");
         } else if (streq(argv[1], "hybrid-sleep")) {
-                if (write_one_line_file("/sys/power/disk", "suspend") < 0)
-                        if (write_one_line_file("/sys/power/disk", "platform") < 0)
-                                write_one_line_file("/sys/power/disk", "shutdown");
+                if (write_string_file("/sys/power/disk", "suspend") < 0)
+                        if (write_string_file("/sys/power/disk", "platform") < 0)
+                                write_string_file("/sys/power/disk", "shutdown");
         }
 
         f = fopen("/sys/power/state", "we");
diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c
index 79f3f77..e0ba78a 100644
--- a/src/sysctl/sysctl.c
+++ b/src/sysctl/sysctl.c
@@ -88,7 +88,7 @@ static int apply_sysctl(const char *property, const char *value) {
                 }
         }
 
-        k = write_one_line_file(p, value);
+        k = write_string_file(p, value);
         if (k < 0) {
                 log_full(k == -ENOENT ? LOG_DEBUG : LOG_WARNING,
                          "Failed to write '%s' to '%s': %s", value, p, strerror(-k));
diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
index 1d4d739..e068724 100644
--- a/src/timedate/timedated.c
+++ b/src/timedate/timedated.c
@@ -275,7 +275,7 @@ static int write_data_local_rtc(void) {
                 }
         }
         label_init("/etc");
-        r = write_one_line_file_atomic_label("/etc/adjtime", w);
+        r = write_string_file_atomic_label("/etc/adjtime", w);
         free(w);
 
         return r;
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index 42cf994..2d9093d 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -267,7 +267,7 @@ static void worker_new(struct event *event)
                 prctl(PR_SET_PDEATHSIG, SIGTERM);
 
                 /* reset OOM score, we only protect the main daemon */
-                write_one_line_file("/proc/self/oom_score_adj", "0");
+                write_string_file("/proc/self/oom_score_adj", "0");
 
                 for (;;) {
                         struct udev_event *udev_event;
@@ -1168,7 +1168,7 @@ int main(int argc, char *argv[])
 
                 setsid();
 
-                write_one_line_file("/proc/self/oom_score_adj", "-1000");
+                write_string_file("/proc/self/oom_score_adj", "-1000");
         } else {
                 sd_notify(1, "READY=1");
         }
diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c
index e11fd58..84d7c5c 100644
--- a/src/vconsole/vconsole-setup.c
+++ b/src/vconsole/vconsole-setup.c
@@ -57,7 +57,7 @@ static int disable_utf8(int fd) {
         if (loop_write(fd, "\033%@", 3, false) < 0)
                 r = -errno;
 
-        k = write_one_line_file("/sys/module/vt/parameters/default_utf8", "0");
+        k = write_string_file("/sys/module/vt/parameters/default_utf8", "0");
         if (k < 0)
                 r = k;
 
@@ -89,7 +89,7 @@ static int enable_utf8(int fd) {
         if (loop_write(fd, "\033%G", 3, false) < 0)
                 r = -errno;
 
-        k = write_one_line_file("/sys/module/vt/parameters/default_utf8", "1");
+        k = write_string_file("/sys/module/vt/parameters/default_utf8", "1");
         if (k < 0)
                 r = k;
 



More information about the systemd-commits mailing list