]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/basic/env-file.c
tree-wide: use UINT64_MAX or friends
[thirdparty/systemd.git] / src / basic / env-file.c
index 6a7d6746a17cf1c79f69766a36daaa0feef07017..a3009093607523b9cd22a78c835d0efb9e677030 100644 (file)
@@ -1,6 +1,4 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
-
-#include <stdio_ext.h>
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include "alloc-util.h"
 #include "env-file.h"
@@ -22,7 +20,7 @@ static int parse_env_file_internal(
                 void *userdata,
                 int *n_pushed) {
 
-        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;
+        size_t key_alloc = 0, n_key = 0, value_alloc = 0, n_value = 0, last_value_whitespace = SIZE_MAX, last_key_whitespace = SIZE_MAX;
         _cleanup_free_ char *contents = NULL, *key = NULL, *value = NULL;
         unsigned line = 1;
         char *p;
@@ -35,7 +33,6 @@ static int parse_env_file_internal(
                 VALUE,
                 VALUE_ESCAPE,
                 SINGLE_QUOTE_VALUE,
-                SINGLE_QUOTE_VALUE_ESCAPE,
                 DOUBLE_QUOTE_VALUE,
                 DOUBLE_QUOTE_VALUE_ESCAPE,
                 COMMENT,
@@ -59,7 +56,7 @@ static int parse_env_file_internal(
                                 state = COMMENT;
                         else if (!strchr(WHITESPACE, c)) {
                                 state = KEY;
-                                last_key_whitespace = (size_t) -1;
+                                last_key_whitespace = SIZE_MAX;
 
                                 if (!GREEDY_REALLOC(key, key_alloc, n_key+2))
                                         return -ENOMEM;
@@ -75,11 +72,11 @@ static int parse_env_file_internal(
                                 n_key = 0;
                         } else if (c == '=') {
                                 state = PRE_VALUE;
-                                last_value_whitespace = (size_t) -1;
+                                last_value_whitespace = SIZE_MAX;
                         } else {
                                 if (!strchr(WHITESPACE, c))
-                                        last_key_whitespace = (size_t) -1;
-                                else if (last_key_whitespace == (size_t) -1)
+                                        last_key_whitespace = SIZE_MAX;
+                                else if (last_key_whitespace == SIZE_MAX)
                                          last_key_whitespace = n_key;
 
                                 if (!GREEDY_REALLOC(key, key_alloc, n_key+2))
@@ -100,7 +97,7 @@ static int parse_env_file_internal(
                                         value[n_value] = 0;
 
                                 /* strip trailing whitespace from key */
-                                if (last_key_whitespace != (size_t) -1)
+                                if (last_key_whitespace != SIZE_MAX)
                                         key[last_key_whitespace] = 0;
 
                                 r = push(fname, line, key, value, userdata, n_pushed);
@@ -113,7 +110,7 @@ static int parse_env_file_internal(
 
                         } else if (c == '\'')
                                 state = SINGLE_QUOTE_VALUE;
-                        else if (c == '\"')
+                        else if (c == '"')
                                 state = DOUBLE_QUOTE_VALUE;
                         else if (c == '\\')
                                 state = VALUE_ESCAPE;
@@ -139,11 +136,11 @@ static int parse_env_file_internal(
                                         value[n_value] = 0;
 
                                 /* Chomp off trailing whitespace from value */
-                                if (last_value_whitespace != (size_t) -1)
+                                if (last_value_whitespace != SIZE_MAX)
                                         value[last_value_whitespace] = 0;
 
                                 /* strip trailing whitespace from key */
-                                if (last_key_whitespace != (size_t) -1)
+                                if (last_key_whitespace != SIZE_MAX)
                                         key[last_key_whitespace] = 0;
 
                                 r = push(fname, line, key, value, userdata, n_pushed);
@@ -156,11 +153,11 @@ static int parse_env_file_internal(
 
                         } else if (c == '\\') {
                                 state = VALUE_ESCAPE;
-                                last_value_whitespace = (size_t) -1;
+                                last_value_whitespace = SIZE_MAX;
                         } else {
                                 if (!strchr(WHITESPACE, c))
-                                        last_value_whitespace = (size_t) -1;
-                                else if (last_value_whitespace == (size_t) -1)
+                                        last_value_whitespace = SIZE_MAX;
+                                else if (last_value_whitespace == SIZE_MAX)
                                         last_value_whitespace = n_value;
 
                                 if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
@@ -186,8 +183,6 @@ static int parse_env_file_internal(
                 case SINGLE_QUOTE_VALUE:
                         if (c == '\'')
                                 state = PRE_VALUE;
-                        else if (c == '\\')
-                                state = SINGLE_QUOTE_VALUE_ESCAPE;
                         else {
                                 if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
                                         return -ENOMEM;
@@ -197,19 +192,8 @@ static int parse_env_file_internal(
 
                         break;
 
-                case SINGLE_QUOTE_VALUE_ESCAPE:
-                        state = SINGLE_QUOTE_VALUE;
-
-                        if (!strchr(NEWLINE, c)) {
-                                if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
-                                        return -ENOMEM;
-
-                                value[n_value++] = c;
-                        }
-                        break;
-
                 case DOUBLE_QUOTE_VALUE:
-                        if (c == '\"')
+                        if (c == '"')
                                 state = PRE_VALUE;
                         else if (c == '\\')
                                 state = DOUBLE_QUOTE_VALUE_ESCAPE;
@@ -225,12 +209,21 @@ static int parse_env_file_internal(
                 case DOUBLE_QUOTE_VALUE_ESCAPE:
                         state = DOUBLE_QUOTE_VALUE;
 
-                        if (!strchr(NEWLINE, c)) {
+                        if (strchr(SHELL_NEED_ESCAPE, c)) {
+                                /* If this is a char that needs escaping, just unescape it. */
                                 if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
                                         return -ENOMEM;
-
+                                value[n_value++] = c;
+                        } else if (c != '\n') {
+                                /* If other char than what needs escaping, keep the "\" in place, like the
+                                 * real shell does. */
+                                if (!GREEDY_REALLOC(value, value_alloc, n_value+3))
+                                        return -ENOMEM;
+                                value[n_value++] = '\\';
                                 value[n_value++] = c;
                         }
+
+                        /* Escaped newlines (aka "continuation lines") are eaten up entirely */
                         break;
 
                 case COMMENT:
@@ -253,7 +246,6 @@ static int parse_env_file_internal(
                    VALUE,
                    VALUE_ESCAPE,
                    SINGLE_QUOTE_VALUE,
-                   SINGLE_QUOTE_VALUE_ESCAPE,
                    DOUBLE_QUOTE_VALUE,
                    DOUBLE_QUOTE_VALUE_ESCAPE)) {
 
@@ -263,11 +255,11 @@ static int parse_env_file_internal(
                         value[n_value] = 0;
 
                 if (state == VALUE)
-                        if (last_value_whitespace != (size_t) -1)
+                        if (last_value_whitespace != SIZE_MAX)
                                 value[last_value_whitespace] = 0;
 
                 /* strip trailing whitespace from key */
-                if (last_key_whitespace != (size_t) -1)
+                if (last_key_whitespace != SIZE_MAX)
                         key[last_key_whitespace] = 0;
 
                 r = push(fname, line, key, value, userdata, n_pushed);
@@ -393,11 +385,9 @@ static int load_env_file_push(
         if (!p)
                 return -ENOMEM;
 
-        r = strv_env_replace(m, p);
-        if (r < 0) {
-                free(p);
+        r = strv_env_replace_consume(m, p);
+        if (r < 0)
                 return r;
-        }
 
         if (n_pushed)
                 (*n_pushed)++;
@@ -497,6 +487,8 @@ static int merge_env_file_push(
 
         free_and_replace(value, expanded_value);
 
+        log_debug("%s:%u: setting %s=%s", filename, line, key, value);
+
         return load_env_file_push(filename, line, key, value, env, n_pushed);
 }
 
@@ -527,7 +519,7 @@ static void write_env_var(FILE *f, const char *v) {
         fwrite_unlocked(v, 1, p-v, f);
 
         if (string_has_cc(p, NULL) || chars_intersect(p, WHITESPACE SHELL_NEED_QUOTES)) {
-                fputc_unlocked('\"', f);
+                fputc_unlocked('"', f);
 
                 for (; *p; p++) {
                         if (strchr(SHELL_NEED_ESCAPE, *p))
@@ -536,7 +528,7 @@ static void write_env_var(FILE *f, const char *v) {
                         fputc_unlocked(*p, f);
                 }
 
-                fputc_unlocked('\"', f);
+                fputc_unlocked('"', f);
         } else
                 fputs_unlocked(p, f);
 
@@ -555,7 +547,6 @@ int write_env_file(const char *fname, char **l) {
         if (r < 0)
                 return r;
 
-        (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
         (void) fchmod_umask(fileno(f), 0644);
 
         STRV_FOREACH(i, l)
@@ -569,6 +560,6 @@ int write_env_file(const char *fname, char **l) {
                 r = -errno;
         }
 
-        unlink(p);
+        (void) unlink(p);
         return r;
 }