summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/shared/fileio.c88
1 files changed, 57 insertions, 31 deletions
diff --git a/src/shared/fileio.c b/src/shared/fileio.c
index 2b1dab8053..77fd05955a 100644
--- a/src/shared/fileio.c
+++ b/src/shared/fileio.c
@@ -23,6 +23,7 @@
#include "fileio.h"
#include "util.h"
#include "strv.h"
+#include "utf8.h"
int write_string_to_file(FILE *f, const char *line) {
errno = 0;
@@ -177,13 +178,15 @@ int read_full_file(const char *fn, char **contents, size_t *size) {
static int parse_env_file_internal(
const char *fname,
const char *newline,
- int (*push) (const char *key, char *value, void *userdata),
+ int (*push) (const char *filename, unsigned line,
+ 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_value_whitespace = (size_t) -1, last_key_whitespace = (size_t) -1;
char *p, *value = NULL;
int r;
+ unsigned line = 1;
enum {
PRE_KEY,
@@ -230,6 +233,7 @@ static int parse_env_file_internal(
case KEY:
if (strchr(newline, c)) {
state = PRE_KEY;
+ line ++;
n_key = 0;
} else if (c == '=') {
state = PRE_VALUE;
@@ -253,6 +257,7 @@ static int parse_env_file_internal(
case PRE_VALUE:
if (strchr(newline, c)) {
state = PRE_KEY;
+ line ++;
key[n_key] = 0;
if (value)
@@ -262,7 +267,7 @@ static int parse_env_file_internal(
if (last_key_whitespace != (size_t) -1)
key[last_key_whitespace] = 0;
- r = push(key, value, userdata);
+ r = push(fname, line, key, value, userdata);
if (r < 0)
goto fail;
@@ -292,6 +297,7 @@ static int parse_env_file_internal(
case VALUE:
if (strchr(newline, c)) {
state = PRE_KEY;
+ line ++;
key[n_key] = 0;
@@ -306,7 +312,7 @@ static int parse_env_file_internal(
if (last_key_whitespace != (size_t) -1)
key[last_key_whitespace] = 0;
- r = push(key, value, userdata);
+ r = push(fname, line, key, value, userdata);
if (r < 0)
goto fail;
@@ -408,8 +414,10 @@ static int parse_env_file_internal(
case COMMENT:
if (c == '\\')
state = COMMENT_ESCAPE;
- else if (strchr(newline, c))
+ else if (strchr(newline, c)) {
state = PRE_KEY;
+ line ++;
+ }
break;
case COMMENT_ESCAPE:
@@ -439,7 +447,7 @@ static int parse_env_file_internal(
if (last_key_whitespace != (size_t) -1)
key[last_key_whitespace] = 0;
- r = push(key, value, userdata);
+ r = push(fname, line, key, value, userdata);
if (r < 0)
goto fail;
}
@@ -451,27 +459,36 @@ fail:
return r;
}
-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;
+static int parse_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 {
+ const char *k;
+ va_list* ap = (va_list*) userdata;
+ va_list aq;
- va_copy(aq, *ap);
+ va_copy(aq, *ap);
- while ((k = va_arg(aq, const char *))) {
- char **v;
+ while ((k = va_arg(aq, const char *))) {
+ char **v;
- v = va_arg(aq, char **);
+ v = va_arg(aq, char **);
- if (streq(key, k)) {
- va_end(aq);
- free(*v);
- *v = value;
- return 1;
+ if (streq(key, k)) {
+ va_end(aq);
+ free(*v);
+ *v = value;
+ return 1;
+ }
}
- }
- va_end(aq);
+ va_end(aq);
+ }
free(value);
return 0;
@@ -494,19 +511,28 @@ int parse_env_file(
return r;
}
-static int load_env_file_push(const char *key, char *value, void *userdata) {
- char ***m = userdata;
- char *p;
- int r;
+static int load_env_file_push(const char *filename, unsigned line,
+ const char *key, char *value, void *userdata) {
+ assert(utf8_is_valid(key));
- p = strjoin(key, "=", strempty(value), NULL);
- if (!p)
- return -ENOMEM;
+ 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;
- r = strv_push(m, p);
- if (r < 0) {
- free(p);
- return 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);