#include "util.h"
#include "strv.h"
-int write_string_file(const char *fn, const char *line) {
- _cleanup_fclose_ FILE *f = NULL;
-
- assert(fn);
- assert(line);
-
- f = fopen(fn, "we");
- if (!f)
- return -errno;
+int write_string_to_file(FILE *f, const char *line) {
errno = 0;
- if (fputs(line, f) < 0)
- return errno ? -errno : -EIO;
-
+ fputs(line, f);
if (!endswith(line, "\n"))
fputc('\n', f);
return 0;
}
+int write_string_file(const char *fn, const char *line) {
+ _cleanup_fclose_ FILE *f = NULL;
+
+ assert(fn);
+ assert(line);
+
+ f = fopen(fn, "we");
+ if (!f)
+ return -errno;
+
+ return write_string_to_file(f, line);
+}
+
int write_string_file_atomic(const char *fn, const char *line) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *p = NULL;
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);
r = 0;
}
-finish:
if (r < 0)
unlink(p);
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;
+ 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;
char *p, *value = NULL;
int r;
enum {
PRE_KEY,
KEY,
- PRE_EQUAL,
PRE_VALUE,
VALUE,
VALUE_ESCAPE,
state = COMMENT;
else if (!strchr(WHITESPACE, c)) {
state = KEY;
+ last_key_whitespace = (size_t) -1;
+
if (!greedy_realloc((void**) &key, &key_alloc, n_key+2)) {
r = -ENOMEM;
goto fail;
if (strchr(newline, c)) {
state = PRE_KEY;
n_key = 0;
- } else if (strchr(WHITESPACE, c))
- state = PRE_EQUAL;
- else if (c == '=')
+ } else if (c == '=') {
state = PRE_VALUE;
- else {
+ last_value_whitespace = (size_t) -1;
+ } else {
+ if (!strchr(WHITESPACE, c))
+ last_key_whitespace = (size_t) -1;
+ else if (last_key_whitespace == (size_t) -1)
+ last_key_whitespace = n_key;
+
if (!greedy_realloc((void**) &key, &key_alloc, n_key+2)) {
r = -ENOMEM;
goto fail;
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;
- }
-
- break;
-
case PRE_VALUE:
if (strchr(newline, c)) {
state = PRE_KEY;
if (value)
value[n_value] = 0;
+ /* strip trailing whitespace from key */
+ if (last_key_whitespace != (size_t) -1)
+ key[last_key_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 = SINGLE_QUOTE_VALUE;
else if (c == '\"')
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;
+ /* Chomp off trailing whitespace from value */
+ if (last_value_whitespace != (size_t) -1)
+ value[last_value_whitespace] = 0;
+
+ /* strip trailing whitespace from key */
+ if (last_key_whitespace != (size_t) -1)
+ key[last_key_whitespace] = 0;
r = push(key, value, userdata);
if (r < 0)
n_key = 0;
value = NULL;
value_alloc = n_value = 0;
+
} else if (c == '\\') {
state = VALUE_ESCAPE;
- last_whitespace = (size_t) -1;
+ last_value_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;
+ last_value_whitespace = (size_t) -1;
+ else if (last_value_whitespace == (size_t) -1)
+ last_value_whitespace = n_value;
if (!greedy_realloc((void**) &value, &value_alloc, n_value+2)) {
r = -ENOMEM;
if (value)
value[n_value] = 0;
+ if (state == VALUE)
+ if (last_value_whitespace != (size_t) -1)
+ value[last_value_whitespace] = 0;
+
+ /* strip trailing whitespace from key */
+ if (last_key_whitespace != (size_t) -1)
+ key[last_key_whitespace] = 0;
+
r = push(key, value, userdata);
if (r < 0)
goto fail;
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;
- FILE _cleanup_fclose_ *f = NULL;
+ _cleanup_free_ char *p = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
int r;
r = fopen_temporary(fname, &f, &p);
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);
- 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