fileio.c revision 7ff7394d9e4e9189c30fd018235e6b1728c6f2d0
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering/***
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering This file is part of systemd.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Copyright 2010 Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering systemd is free software; you can redistribute it and/or modify it
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering under the terms of the GNU Lesser General Public License as published by
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering (at your option) any later version.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering systemd is distributed in the hope that it will be useful, but
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Lesser General Public License for more details.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering You should have received a copy of the GNU Lesser General Public License
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering***/
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering#include <unistd.h>
4871690d9e32608bbd9b18505b5326c2079c9690Allin Cottrell#include "fileio.h"
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering#include "util.h"
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering#include "strv.h"
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering#include "utf8.h"
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering#include "ctype.h"
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekint write_string_to_file(FILE *f, const char *line) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering errno = 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fputs(line, f);
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering if (!endswith(line, "\n"))
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen fputc('\n', f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering fflush(f);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering if (ferror(f))
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering return errno ? -errno : -EIO;
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek
46b131574fdd7d77c15a0919ca9010cad7aa6ac7Lennart Poettering return 0;
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek}
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmekint write_string_file(const char *fn, const char *line) {
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek _cleanup_fclose_ FILE *f = NULL;
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek assert(fn);
46b131574fdd7d77c15a0919ca9010cad7aa6ac7Lennart Poettering assert(line);
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek
f8294e4175918117ca6c131720bcf287eadcd029Josh Triplett f = fopen(fn, "we");
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek if (!f)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return -errno;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return write_string_to_file(f, line);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering}
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringint write_string_file_atomic(const char *fn, const char *line) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_free_ char *p = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering int r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(fn);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(line);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = fopen_temporary(fn, &f, &p);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fchmod_umask(fileno(f), 0644);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering errno = 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fputs(line, f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!endswith(line, "\n"))
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fputc('\n', f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fflush(f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (ferror(f))
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = errno ? -errno : -EIO;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering else {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (rename(p, fn) < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = -errno;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering else
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering r = 0;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering unlink(p);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering}
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringint read_one_line_file(const char *fn, char **line) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering char t[LINE_MAX], *c;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(fn);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(line);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering f = fopen(fn, "re");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!f)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return -errno;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering if (!fgets(t, sizeof(t), f)) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering if (ferror(f))
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return errno ? -errno : -EIO;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering t[0] = 0;
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering c = strdup(t);
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering if (!c)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return -ENOMEM;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering truncate_nl(c);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering *line = c;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering}
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringint read_full_file(const char *fn, char **contents, size_t *size) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering size_t n, l;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_free_ char *buf = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering struct stat st;
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(fn);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(contents);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering f = fopen(fn, "re");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!f)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return -errno;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (fstat(fileno(f), &st) < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return -errno;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering /* Safety check */
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (st.st_size > 4*1024*1024)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return -E2BIG;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering n = st.st_size > 0 ? st.st_size : LINE_MAX;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering l = 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering for (;;) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering char *t;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering size_t k;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering t = realloc(buf, n+1);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!t)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return -ENOMEM;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering buf = t;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering k = fread(buf + l, 1, n - l, f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (k <= 0) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (ferror(f))
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return -errno;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering break;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering l += k;
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek n *= 2;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering /* Safety check */
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (n > 4*1024*1024)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return -E2BIG;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering buf[l] = 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering *contents = buf;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering buf = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (size)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering *size = l;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering}
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int parse_env_file_internal(
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering const char *fname,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering const char *newline,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering int (*push) (const char *filename, unsigned line,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering const char *key, char *value, void *userdata),
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering void *userdata) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_free_ char *contents = NULL, *key = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering size_t key_alloc = 0, n_key = 0, value_alloc = 0, n_value = 0, last_value_whitespace = (size_t) -1, last_key_whitespace = (size_t) -1;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering char *p, *value = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering int r;
e88baee88fad8bc59d33b55a7a2d640ef9e16cd6Zbigniew Jędrzejewski-Szmek unsigned line = 1;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering enum {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering PRE_KEY,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering KEY,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering PRE_VALUE,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering VALUE,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering VALUE_ESCAPE,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering SINGLE_QUOTE_VALUE,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering SINGLE_QUOTE_VALUE_ESCAPE,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering DOUBLE_QUOTE_VALUE,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering DOUBLE_QUOTE_VALUE_ESCAPE,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering COMMENT,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering COMMENT_ESCAPE
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering } state = PRE_KEY;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
e88baee88fad8bc59d33b55a7a2d640ef9e16cd6Zbigniew Jędrzejewski-Szmek assert(fname);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(newline);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = read_full_file(fname, &contents, NULL);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering for (p = contents; *p; p++) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering char c = *p;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering switch (state) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering case PRE_KEY:
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (strchr(COMMENTS, c))
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering state = COMMENT;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering else if (!strchr(WHITESPACE, c)) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering state = KEY;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering last_key_whitespace = (size_t) -1;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!greedy_realloc((void**) &key, &key_alloc, n_key+2)) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = -ENOMEM;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering goto fail;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering key[n_key++] = c;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering break;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering case KEY:
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (strchr(newline, c)) {
e88baee88fad8bc59d33b55a7a2d640ef9e16cd6Zbigniew Jędrzejewski-Szmek state = PRE_KEY;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering line ++;
e88baee88fad8bc59d33b55a7a2d640ef9e16cd6Zbigniew Jędrzejewski-Szmek n_key = 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering } else if (c == '=') {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering state = PRE_VALUE;
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek last_value_whitespace = (size_t) -1;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering } else {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (!strchr(WHITESPACE, c))
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering last_key_whitespace = (size_t) -1;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering else if (last_key_whitespace == (size_t) -1)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering last_key_whitespace = n_key;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (!greedy_realloc((void**) &key, &key_alloc, n_key+2)) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = -ENOMEM;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering goto fail;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering }
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering key[n_key++] = c;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering }
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering break;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering case PRE_VALUE:
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (strchr(newline, c)) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering state = PRE_KEY;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering line ++;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering key[n_key] = 0;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (value)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering value[n_value] = 0;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering /* strip trailing whitespace from key */
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (last_key_whitespace != (size_t) -1)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering key[last_key_whitespace] = 0;
ac50788b0f5aeee09e7d45db28ae8ab7f39cd52eZbigniew Jędrzejewski-Szmek
ac50788b0f5aeee09e7d45db28ae8ab7f39cd52eZbigniew Jędrzejewski-Szmek r = push(fname, line, key, value, userdata);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (r < 0)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering goto fail;
ac50788b0f5aeee09e7d45db28ae8ab7f39cd52eZbigniew Jędrzejewski-Szmek
ac50788b0f5aeee09e7d45db28ae8ab7f39cd52eZbigniew Jędrzejewski-Szmek n_key = 0;
ac50788b0f5aeee09e7d45db28ae8ab7f39cd52eZbigniew Jędrzejewski-Szmek value = NULL;
ac50788b0f5aeee09e7d45db28ae8ab7f39cd52eZbigniew Jędrzejewski-Szmek value_alloc = n_value = 0;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering } else if (c == '\'')
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering state = SINGLE_QUOTE_VALUE;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering else if (c == '\"')
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering state = DOUBLE_QUOTE_VALUE;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering else if (c == '\\')
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering state = VALUE_ESCAPE;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering else if (!strchr(WHITESPACE, c)) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering state = VALUE;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (!greedy_realloc((void**) &value, &value_alloc, n_value+2)) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = -ENOMEM;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering goto fail;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering }
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering value[n_value++] = c;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering }
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering break;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering case VALUE:
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (strchr(newline, c)) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering state = PRE_KEY;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering line ++;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering key[n_key] = 0;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (value)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering value[n_value] = 0;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering /* Chomp off trailing whitespace from value */
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (last_value_whitespace != (size_t) -1)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering value[last_value_whitespace] = 0;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering /* strip trailing whitespace from key */
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (last_key_whitespace != (size_t) -1)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering key[last_key_whitespace] = 0;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = push(fname, line, key, value, userdata);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (r < 0)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering goto fail;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering n_key = 0;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering value = NULL;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering value_alloc = n_value = 0;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering } else if (c == '\\') {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering state = VALUE_ESCAPE;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering last_value_whitespace = (size_t) -1;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering } else {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (!strchr(WHITESPACE, c))
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering last_value_whitespace = (size_t) -1;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering else if (last_value_whitespace == (size_t) -1)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering last_value_whitespace = n_value;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (!greedy_realloc((void**) &value, &value_alloc, n_value+2)) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = -ENOMEM;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering goto fail;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering }
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering value[n_value++] = c;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering }
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering break;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering case VALUE_ESCAPE:
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering state = VALUE;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (!strchr(newline, c)) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering /* Escaped newlines we eat up entirely */
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (!greedy_realloc((void**) &value, &value_alloc, n_value+2)) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = -ENOMEM;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering goto fail;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering value[n_value++] = c;
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering }
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering break;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering case SINGLE_QUOTE_VALUE:
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (c == '\'')
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering state = PRE_VALUE;
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering else if (c == '\\')
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering state = SINGLE_QUOTE_VALUE_ESCAPE;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering else {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!greedy_realloc((void**) &value, &value_alloc, n_value+2)) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = -ENOMEM;
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering goto fail;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering value[n_value++] = c;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering break;
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering case SINGLE_QUOTE_VALUE_ESCAPE:
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering state = SINGLE_QUOTE_VALUE;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!strchr(newline, c)) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!greedy_realloc((void**) &value, &value_alloc, n_value+2)) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = -ENOMEM;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering goto fail;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering value[n_value++] = c;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering break;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen case DOUBLE_QUOTE_VALUE:
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen if (c == '\"')
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen state = PRE_VALUE;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering else if (c == '\\')
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering state = DOUBLE_QUOTE_VALUE_ESCAPE;
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering else {
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering if (!greedy_realloc((void**) &value, &value_alloc, n_value+2)) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = -ENOMEM;
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering goto fail;
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering }
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering value[n_value++] = c;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering break;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering case DOUBLE_QUOTE_VALUE_ESCAPE:
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering state = DOUBLE_QUOTE_VALUE;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!strchr(newline, c)) {
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering if (!greedy_realloc((void**) &value, &value_alloc, n_value+2)) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = -ENOMEM;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering goto fail;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering value[n_value++] = c;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering break;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek case COMMENT:
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (c == '\\')
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering state = COMMENT_ESCAPE;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering else if (strchr(newline, c)) {
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering state = PRE_KEY;
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering line ++;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering break;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering case COMMENT_ESCAPE:
46b131574fdd7d77c15a0919ca9010cad7aa6ac7Lennart Poettering state = COMMENT;
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek break;
03ee5c38cb0da193dd08733fb4c0c2809cee6a99Lennart Poettering }
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (state == PRE_VALUE ||
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt state == VALUE ||
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt state == VALUE_ESCAPE ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering state == SINGLE_QUOTE_VALUE ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering state == SINGLE_QUOTE_VALUE_ESCAPE ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering state == DOUBLE_QUOTE_VALUE ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering state == DOUBLE_QUOTE_VALUE_ESCAPE) {
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt key[n_key] = 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (value)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering value[n_value] = 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (state == VALUE)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (last_value_whitespace != (size_t) -1)
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt value[last_value_whitespace] = 0;
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering /* strip trailing whitespace from key */
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (last_key_whitespace != (size_t) -1)
6baa7db00812437bbc87e73faa1a11b6cf631958Lennart Poettering key[last_key_whitespace] = 0;
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering r = push(fname, line, key, value, userdata);
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt if (r < 0)
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering goto fail;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidtfail:
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering free(value);
8531ae707d4d0203e83304d4af948b8169a5fce1Lennart Poettering return r;
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt}
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int parse_env_file_push(const char *filename, unsigned line,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering const char *key, char *value, void *userdata) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(utf8_is_valid(key));
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering if (value && !utf8_is_valid(value))
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering /* FIXME: filter UTF-8 */
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering log_error("%s:%u: invalid UTF-8 for key %s: '%s', ignoring.",
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering filename, line, key, value);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering else {
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering const char *k;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering va_list* ap = (va_list*) userdata;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering va_list aq;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering va_copy(aq, *ap);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering while ((k = va_arg(aq, const char *))) {
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering char **v;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering v = va_arg(aq, char **);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
if (streq(key, k)) {
va_end(aq);
free(*v);
*v = value;
return 1;
}
}
va_end(aq);
}
free(value);
return 0;
}
int parse_env_file(
const char *fname,
const char *newline, ...) {
va_list ap;
int r;
if (!newline)
newline = NEWLINE;
va_start(ap, newline);
r = parse_env_file_internal(fname, newline, parse_env_file_push, &ap);
va_end(ap);
return r;
}
static int load_env_file_push(const char *filename, unsigned line,
const char *key, char *value, void *userdata) {
assert(utf8_is_valid(key));
if (value && !utf8_is_valid(value))
/* FIXME: filter UTF-8 */
log_error("%s:%u: invalid UTF-8 for key %s: '%s', ignoring.",
filename, line, key, value);
else {
char ***m = userdata;
char *p;
int r;
p = strjoin(key, "=", strempty(value), NULL);
if (!p)
return -ENOMEM;
r = strv_push(m, p);
if (r < 0) {
free(p);
return r;
}
}
free(value);
return 0;
}
int load_env_file(const char *fname, const char *newline, char ***rl) {
char **m = NULL;
int r;
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;
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;
_cleanup_free_ char *p = NULL;
_cleanup_fclose_ FILE *f = NULL;
int r;
r = fopen_temporary(fname, &f, &p);
if (r < 0)
return r;
fchmod_umask(fileno(f), 0644);
errno = 0;
STRV_FOREACH(i, l)
write_env_var(f, *i);
fflush(f);
if (ferror(f))
r = errno ? -errno : -EIO;
else {
if (rename(p, fname) < 0)
r = -errno;
else
r = 0;
}
if (r < 0)
unlink(p);
return r;
}
int executable_is_script(const char *path, char **interpreter) {
int r;
char _cleanup_free_ *line = NULL;
int len;
char *ans;
assert(path);
r = read_one_line_file(path, &line);
if (r < 0)
return r;
if (!startswith(line, "#!"))
return 0;
ans = strstrip(line + 2);
len = strcspn(ans, " \t");
if (len == 0)
return 0;
ans = strndup(ans, len);
if (!ans)
return -ENOMEM;
*interpreter = ans;
return 1;
}
/**
* Retrieve one field from a file like /proc/self/status. pattern
* should start with '\n' and end with a ':'. Whitespace and zeros
* after the ':' will be skipped. field must be freed afterwards.
*/
int get_status_field(const char *filename, const char *pattern, char **field) {
_cleanup_free_ char *status = NULL;
char *t;
size_t len;
int r;
assert(filename);
assert(pattern);
assert(field);
r = read_full_file(filename, &status, NULL);
if (r < 0)
return r;
t = strstr(status, pattern);
if (!t)
return -ENOENT;
t += strlen(pattern);
if (*t) {
t += strspn(t, " \t");
/* Also skip zeros, because when this is used for
* capabilities, we don't want the zeros. This way the
* same capability set always maps to the same string,
* irrespective of the total capability set size. For
* other numbers it shouldn't matter. */
t += strspn(t, "0");
/* Back off one char if there's nothing but whitespace
and zeros */
if (!*t || isspace(*t))
t --;
}
len = strcspn(t, WHITESPACE);
*field = strndup(t, len);
if (!*field)
return -ENOMEM;
return 0;
}