LCOV - code coverage report
Current view: top level - shared - conf-parser.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 290 468 62.0 %
Date: 2019-08-22 15:41:25 Functions: 23 38 60.5 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <errno.h>
       4             : #include <limits.h>
       5             : #include <stdint.h>
       6             : #include <stdio.h>
       7             : #include <stdlib.h>
       8             : #include <string.h>
       9             : #include <sys/types.h>
      10             : 
      11             : #include "alloc-util.h"
      12             : #include "conf-files.h"
      13             : #include "conf-parser.h"
      14             : #include "def.h"
      15             : #include "extract-word.h"
      16             : #include "fd-util.h"
      17             : #include "fileio.h"
      18             : #include "fs-util.h"
      19             : #include "log.h"
      20             : #include "macro.h"
      21             : #include "missing.h"
      22             : #include "nulstr-util.h"
      23             : #include "parse-util.h"
      24             : #include "path-util.h"
      25             : #include "process-util.h"
      26             : #include "rlimit-util.h"
      27             : #include "signal-util.h"
      28             : #include "socket-util.h"
      29             : #include "string-util.h"
      30             : #include "strv.h"
      31             : #include "syslog-util.h"
      32             : #include "time-util.h"
      33             : #include "utf8.h"
      34             : 
      35        5226 : int config_item_table_lookup(
      36             :                 const void *table,
      37             :                 const char *section,
      38             :                 const char *lvalue,
      39             :                 ConfigParserCallback *func,
      40             :                 int *ltype,
      41             :                 void **data,
      42             :                 void *userdata) {
      43             : 
      44             :         const ConfigTableItem *t;
      45             : 
      46        5226 :         assert(table);
      47        5226 :         assert(lvalue);
      48        5226 :         assert(func);
      49        5226 :         assert(ltype);
      50        5226 :         assert(data);
      51             : 
      52       29202 :         for (t = table; t->lvalue; t++) {
      53             : 
      54       24575 :                 if (!streq(lvalue, t->lvalue))
      55       23976 :                         continue;
      56             : 
      57         599 :                 if (!streq_ptr(section, t->section))
      58           0 :                         continue;
      59             : 
      60         599 :                 *func = t->parse;
      61         599 :                 *ltype = t->ltype;
      62         599 :                 *data = t->data;
      63         599 :                 return 1;
      64             :         }
      65             : 
      66        4627 :         return 0;
      67             : }
      68             : 
      69         379 : int config_item_perf_lookup(
      70             :                 const void *table,
      71             :                 const char *section,
      72             :                 const char *lvalue,
      73             :                 ConfigParserCallback *func,
      74             :                 int *ltype,
      75             :                 void **data,
      76             :                 void *userdata) {
      77             : 
      78         379 :         ConfigPerfItemLookup lookup = (ConfigPerfItemLookup) table;
      79             :         const ConfigPerfItem *p;
      80             : 
      81         379 :         assert(table);
      82         379 :         assert(lvalue);
      83         379 :         assert(func);
      84         379 :         assert(ltype);
      85         379 :         assert(data);
      86             : 
      87         379 :         if (section) {
      88             :                 const char *key;
      89             : 
      90        2653 :                 key = strjoina(section, ".", lvalue);
      91         379 :                 p = lookup(key, strlen(key));
      92             :         } else
      93           0 :                 p = lookup(lvalue, strlen(lvalue));
      94         379 :         if (!p)
      95           0 :                 return 0;
      96             : 
      97         379 :         *func = p->parse;
      98         379 :         *ltype = p->ltype;
      99         379 :         *data = (uint8_t*) userdata + p->offset;
     100         379 :         return 1;
     101             : }
     102             : 
     103             : /* Run the user supplied parser for an assignment */
     104        5605 : static int next_assignment(
     105             :                 const char *unit,
     106             :                 const char *filename,
     107             :                 unsigned line,
     108             :                 ConfigItemLookup lookup,
     109             :                 const void *table,
     110             :                 const char *section,
     111             :                 unsigned section_line,
     112             :                 const char *lvalue,
     113             :                 const char *rvalue,
     114             :                 ConfigParseFlags flags,
     115             :                 void *userdata) {
     116             : 
     117        5605 :         ConfigParserCallback func = NULL;
     118        5605 :         int ltype = 0;
     119        5605 :         void *data = NULL;
     120             :         int r;
     121             : 
     122        5605 :         assert(filename);
     123        5605 :         assert(line > 0);
     124        5605 :         assert(lookup);
     125        5605 :         assert(lvalue);
     126        5605 :         assert(rvalue);
     127             : 
     128        5605 :         r = lookup(table, section, lvalue, &func, &ltype, &data, userdata);
     129        5605 :         if (r < 0)
     130           0 :                 return r;
     131        5605 :         if (r > 0) {
     132         978 :                 if (func)
     133         971 :                         return func(unit, filename, line, section, section_line,
     134             :                                     lvalue, ltype, rvalue, data, userdata);
     135             : 
     136           7 :                 return 0;
     137             :         }
     138             : 
     139             :         /* Warn about unknown non-extension fields. */
     140        4627 :         if (!(flags & CONFIG_PARSE_RELAXED) && !startswith(lvalue, "X-"))
     141           0 :                 log_syntax(unit, LOG_WARNING, filename, line, 0,
     142             :                            "Unknown key name '%s' in section '%s', ignoring.", lvalue, section);
     143             : 
     144        4627 :         return 0;
     145             : }
     146             : 
     147             : /* Parse a single logical line */
     148        8401 : static int parse_line(
     149             :                 const char* unit,
     150             :                 const char *filename,
     151             :                 unsigned line,
     152             :                 const char *sections,
     153             :                 ConfigItemLookup lookup,
     154             :                 const void *table,
     155             :                 ConfigParseFlags flags,
     156             :                 char **section,
     157             :                 unsigned *section_line,
     158             :                 bool *section_ignored,
     159             :                 char *l,
     160             :                 void *userdata) {
     161             : 
     162             :         char *e, *include;
     163             : 
     164        8401 :         assert(filename);
     165        8401 :         assert(line > 0);
     166        8401 :         assert(lookup);
     167        8401 :         assert(l);
     168             : 
     169        8401 :         l = strstrip(l);
     170        8401 :         if (!*l)
     171        1223 :                 return 0;
     172             : 
     173        7178 :         if (*l == '\n')
     174           0 :                 return 0;
     175             : 
     176        7178 :         include = first_word(l, ".include");
     177        7178 :         if (include) {
     178           0 :                 _cleanup_free_ char *fn = NULL;
     179             : 
     180             :                 /* .includes are a bad idea, we only support them here
     181             :                  * for historical reasons. They create cyclic include
     182             :                  * problems and make it difficult to detect
     183             :                  * configuration file changes with an easy
     184             :                  * stat(). Better approaches, such as .d/ drop-in
     185             :                  * snippets exist.
     186             :                  *
     187             :                  * Support for them should be eventually removed. */
     188             : 
     189           0 :                 if (!(flags & CONFIG_PARSE_ALLOW_INCLUDE)) {
     190           0 :                         log_syntax(unit, LOG_ERR, filename, line, 0, ".include not allowed here. Ignoring.");
     191           0 :                         return 0;
     192             :                 }
     193             : 
     194           0 :                 log_syntax(unit, LOG_WARNING, filename, line, 0,
     195             :                            ".include directives are deprecated, and support for them will be removed in a future version of systemd. "
     196             :                            "Please use drop-in files instead.");
     197             : 
     198           0 :                 fn = file_in_same_dir(filename, strstrip(include));
     199           0 :                 if (!fn)
     200           0 :                         return -ENOMEM;
     201             : 
     202           0 :                 return config_parse(unit, fn, NULL, sections, lookup, table, flags, userdata);
     203             :         }
     204             : 
     205        7178 :         if (!utf8_is_valid(l))
     206           0 :                 return log_syntax_invalid_utf8(unit, LOG_WARNING, filename, line, l);
     207             : 
     208        7178 :         if (*l == '[') {
     209             :                 size_t k;
     210             :                 char *n;
     211             : 
     212        1573 :                 k = strlen(l);
     213        1573 :                 assert(k > 0);
     214             : 
     215        1573 :                 if (l[k-1] != ']') {
     216           0 :                         log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid section header '%s'", l);
     217           0 :                         return -EBADMSG;
     218             :                 }
     219             : 
     220        1573 :                 n = strndup(l+1, k-2);
     221        1573 :                 if (!n)
     222           0 :                         return -ENOMEM;
     223             : 
     224        1573 :                 if (sections && !nulstr_contains(sections, n)) {
     225             : 
     226           0 :                         if (!(flags & CONFIG_PARSE_RELAXED) && !startswith(n, "X-"))
     227           0 :                                 log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown section '%s'. Ignoring.", n);
     228             : 
     229           0 :                         free(n);
     230           0 :                         *section = mfree(*section);
     231           0 :                         *section_line = 0;
     232           0 :                         *section_ignored = true;
     233             :                 } else {
     234        1573 :                         free_and_replace(*section, n);
     235        1573 :                         *section_line = line;
     236        1573 :                         *section_ignored = false;
     237             :                 }
     238             : 
     239        1573 :                 return 0;
     240             :         }
     241             : 
     242        5605 :         if (sections && !*section) {
     243           0 :                 if (!(flags & CONFIG_PARSE_RELAXED) && !*section_ignored)
     244           0 :                         log_syntax(unit, LOG_WARNING, filename, line, 0, "Assignment outside of section. Ignoring.");
     245             : 
     246           0 :                 return 0;
     247             :         }
     248             : 
     249        5605 :         e = strchr(l, '=');
     250        5605 :         if (!e)
     251           0 :                 return log_syntax(unit, LOG_WARNING, filename, line, 0,
     252             :                                   "Missing '=', ignoring line.");
     253        5605 :         if (e == l)
     254           0 :                 return log_syntax(unit, LOG_WARNING, filename, line, 0,
     255             :                                   "Missing key name before '=', ignoring line.");
     256             : 
     257        5605 :         *e = 0;
     258        5605 :         e++;
     259             : 
     260        5605 :         return next_assignment(unit,
     261             :                                filename,
     262             :                                line,
     263             :                                lookup,
     264             :                                table,
     265             :                                *section,
     266             :                                *section_line,
     267        5605 :                                strstrip(l),
     268        5605 :                                strstrip(e),
     269             :                                flags,
     270             :                                userdata);
     271             : }
     272             : 
     273             : /* Go through the file and parse each line */
     274         862 : int config_parse(const char *unit,
     275             :                  const char *filename,
     276             :                  FILE *f,
     277             :                  const char *sections,
     278             :                  ConfigItemLookup lookup,
     279             :                  const void *table,
     280             :                  ConfigParseFlags flags,
     281             :                  void *userdata) {
     282             : 
     283         862 :         _cleanup_free_ char *section = NULL, *continuation = NULL;
     284         862 :         _cleanup_fclose_ FILE *ours = NULL;
     285         862 :         unsigned line = 0, section_line = 0;
     286         862 :         bool section_ignored = false;
     287             :         int r;
     288             : 
     289         862 :         assert(filename);
     290         862 :         assert(lookup);
     291             : 
     292         862 :         if (!f) {
     293          19 :                 f = ours = fopen(filename, "re");
     294          19 :                 if (!f) {
     295             :                         /* Only log on request, except for ENOENT,
     296             :                          * since we return 0 to the caller. */
     297          13 :                         if ((flags & CONFIG_PARSE_WARN) || errno == ENOENT)
     298          13 :                                 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
     299             :                                                "Failed to open configuration file '%s': %m", filename);
     300          13 :                         return errno == ENOENT ? 0 : -errno;
     301             :                 }
     302             :         }
     303             : 
     304         849 :         fd_warn_permissions(filename, fileno(f));
     305             : 
     306       12045 :         for (;;) {
     307       12894 :                 _cleanup_free_ char *buf = NULL;
     308       12894 :                 bool escaped = false;
     309             :                 char *l, *p, *e;
     310             : 
     311       12894 :                 r = read_line(f, LONG_LINE_MAX, &buf);
     312       12894 :                 if (r == 0)
     313         847 :                         break;
     314       12047 :                 if (r == -ENOBUFS) {
     315           1 :                         if (flags & CONFIG_PARSE_WARN)
     316           1 :                                 log_error_errno(r, "%s:%u: Line too long", filename, line);
     317             : 
     318           1 :                         return r;
     319             :                 }
     320       12046 :                 if (r < 0) {
     321             :                         if (CONFIG_PARSE_WARN)
     322           0 :                                 log_error_errno(r, "%s:%u: Error while reading configuration file: %m", filename, line);
     323             : 
     324           0 :                         return r;
     325             :                 }
     326             : 
     327       12046 :                 l = skip_leading_chars(buf, WHITESPACE);
     328       12046 :                 if (*l != '\0' && strchr(COMMENTS, *l))
     329        2604 :                         continue;
     330             : 
     331        9442 :                 l = buf;
     332        9442 :                 if (!(flags & CONFIG_PARSE_REFUSE_BOM)) {
     333             :                         char *q;
     334             : 
     335        9442 :                         q = startswith(buf, UTF8_BYTE_ORDER_MARK);
     336        9442 :                         if (q) {
     337           0 :                                 l = q;
     338           0 :                                 flags |= CONFIG_PARSE_REFUSE_BOM;
     339             :                         }
     340             :                 }
     341             : 
     342        9442 :                 if (continuation) {
     343        1040 :                         if (strlen(continuation) + strlen(l) > LONG_LINE_MAX) {
     344           1 :                                 if (flags & CONFIG_PARSE_WARN)
     345           1 :                                         log_error("%s:%u: Continuation line too long", filename, line);
     346           1 :                                 return -ENOBUFS;
     347             :                         }
     348             : 
     349        1039 :                         if (!strextend(&continuation, l, NULL)) {
     350           0 :                                 if (flags & CONFIG_PARSE_WARN)
     351           0 :                                         log_oom();
     352           0 :                                 return -ENOMEM;
     353             :                         }
     354             : 
     355        1039 :                         p = continuation;
     356             :                 } else
     357        8402 :                         p = l;
     358             : 
     359   523112148 :                 for (e = p; *e; e++) {
     360   523102707 :                         if (escaped)
     361          41 :                                 escaped = false;
     362   523102666 :                         else if (*e == '\\')
     363        1083 :                                 escaped = true;
     364             :                 }
     365             : 
     366        9441 :                 if (escaped) {
     367        1042 :                         *(e-1) = ' ';
     368             : 
     369        1042 :                         if (!continuation) {
     370          15 :                                 continuation = strdup(l);
     371          15 :                                 if (!continuation) {
     372           0 :                                         if (flags & CONFIG_PARSE_WARN)
     373           0 :                                                 log_oom();
     374           0 :                                         return -ENOMEM;
     375             :                                 }
     376             :                         }
     377             : 
     378        1042 :                         continue;
     379             :                 }
     380             : 
     381        8399 :                 r = parse_line(unit,
     382             :                                filename,
     383             :                                ++line,
     384             :                                sections,
     385             :                                lookup,
     386             :                                table,
     387             :                                flags,
     388             :                                &section,
     389             :                                &section_line,
     390             :                                &section_ignored,
     391             :                                p,
     392             :                                userdata);
     393        8399 :                 if (r < 0) {
     394           0 :                         if (flags & CONFIG_PARSE_WARN)
     395           0 :                                 log_warning_errno(r, "%s:%u: Failed to parse file: %m", filename, line);
     396           0 :                         return r;
     397             :                 }
     398             : 
     399        8399 :                 continuation = mfree(continuation);
     400             :         }
     401             : 
     402         847 :         if (continuation) {
     403           2 :                 r = parse_line(unit,
     404             :                                filename,
     405             :                                ++line,
     406             :                                sections,
     407             :                                lookup,
     408             :                                table,
     409             :                                flags,
     410             :                                &section,
     411             :                                &section_line,
     412             :                                &section_ignored,
     413             :                                continuation,
     414             :                                userdata);
     415           2 :                 if (r < 0) {
     416           0 :                         if (flags & CONFIG_PARSE_WARN)
     417           0 :                                 log_warning_errno(r, "%s:%u: Failed to parse file: %m", filename, line);
     418           0 :                         return r;
     419             :                 }
     420             :         }
     421             : 
     422         847 :         return 0;
     423             : }
     424             : 
     425          16 : static int config_parse_many_files(
     426             :                 const char *conf_file,
     427             :                 char **files,
     428             :                 const char *sections,
     429             :                 ConfigItemLookup lookup,
     430             :                 const void *table,
     431             :                 ConfigParseFlags flags,
     432             :                 void *userdata) {
     433             : 
     434             :         char **fn;
     435             :         int r;
     436             : 
     437          16 :         if (conf_file) {
     438          16 :                 r = config_parse(NULL, conf_file, NULL, sections, lookup, table, flags, userdata);
     439          16 :                 if (r < 0)
     440           0 :                         return r;
     441             :         }
     442             : 
     443          16 :         STRV_FOREACH(fn, files) {
     444           0 :                 r = config_parse(NULL, *fn, NULL, sections, lookup, table, flags, userdata);
     445           0 :                 if (r < 0)
     446           0 :                         return r;
     447             :         }
     448             : 
     449          16 :         return 0;
     450             : }
     451             : 
     452             : /* Parse each config file in the directories specified as nulstr. */
     453          13 : int config_parse_many_nulstr(
     454             :                 const char *conf_file,
     455             :                 const char *conf_file_dirs,
     456             :                 const char *sections,
     457             :                 ConfigItemLookup lookup,
     458             :                 const void *table,
     459             :                 ConfigParseFlags flags,
     460             :                 void *userdata) {
     461             : 
     462          13 :         _cleanup_strv_free_ char **files = NULL;
     463             :         int r;
     464             : 
     465          13 :         r = conf_files_list_nulstr(&files, ".conf", NULL, 0, conf_file_dirs);
     466          13 :         if (r < 0)
     467           0 :                 return r;
     468             : 
     469          13 :         return config_parse_many_files(conf_file, files, sections, lookup, table, flags, userdata);
     470             : }
     471             : 
     472             : /* Parse each config file in the directories specified as strv. */
     473           3 : int config_parse_many(
     474             :                 const char *conf_file,
     475             :                 const char* const* conf_file_dirs,
     476             :                 const char *dropin_dirname,
     477             :                 const char *sections,
     478             :                 ConfigItemLookup lookup,
     479             :                 const void *table,
     480             :                 ConfigParseFlags flags,
     481             :                 void *userdata) {
     482             : 
     483           3 :         _cleanup_strv_free_ char **dropin_dirs = NULL;
     484           3 :         _cleanup_strv_free_ char **files = NULL;
     485             :         const char *suffix;
     486             :         int r;
     487             : 
     488          15 :         suffix = strjoina("/", dropin_dirname);
     489           3 :         r = strv_extend_strv_concat(&dropin_dirs, (char**) conf_file_dirs, suffix);
     490           3 :         if (r < 0)
     491           0 :                 return r;
     492             : 
     493           3 :         r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char* const*) dropin_dirs);
     494           3 :         if (r < 0)
     495           0 :                 return r;
     496             : 
     497           3 :         return config_parse_many_files(conf_file, files, sections, lookup, table, flags, userdata);
     498             : }
     499             : 
     500             : #define DEFINE_PARSER(type, vartype, conv_func)                         \
     501             :         DEFINE_CONFIG_PARSE_PTR(config_parse_##type, conv_func, vartype, "Failed to parse " #type " value")
     502             : 
     503           7 : DEFINE_PARSER(int, int, safe_atoi);
     504           0 : DEFINE_PARSER(long, long, safe_atoli);
     505           0 : DEFINE_PARSER(uint8, uint8_t, safe_atou8);
     506           0 : DEFINE_PARSER(uint16, uint16_t, safe_atou16);
     507           0 : DEFINE_PARSER(uint32, uint32_t, safe_atou32);
     508           0 : DEFINE_PARSER(uint64, uint64_t, safe_atou64);
     509           7 : DEFINE_PARSER(unsigned, unsigned, safe_atou);
     510           0 : DEFINE_PARSER(double, double, safe_atod);
     511           7 : DEFINE_PARSER(nsec, nsec_t, parse_nsec);
     512           7 : DEFINE_PARSER(sec, usec_t, parse_sec);
     513           0 : DEFINE_PARSER(sec_def_infinity, usec_t, parse_sec_def_infinity);
     514           8 : DEFINE_PARSER(mode, mode_t, parse_mode);
     515             : 
     516           9 : int config_parse_iec_size(const char* unit,
     517             :                             const char *filename,
     518             :                             unsigned line,
     519             :                             const char *section,
     520             :                             unsigned section_line,
     521             :                             const char *lvalue,
     522             :                             int ltype,
     523             :                             const char *rvalue,
     524             :                             void *data,
     525             :                             void *userdata) {
     526             : 
     527           9 :         size_t *sz = data;
     528             :         uint64_t v;
     529             :         int r;
     530             : 
     531           9 :         assert(filename);
     532           9 :         assert(lvalue);
     533           9 :         assert(rvalue);
     534           9 :         assert(data);
     535             : 
     536           9 :         r = parse_size(rvalue, 1024, &v);
     537             :         if (r >= 0 && (uint64_t) (size_t) v != v)
     538             :                 r = -ERANGE;
     539           9 :         if (r < 0) {
     540           3 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value '%s', ignoring: %m", rvalue);
     541           3 :                 return 0;
     542             :         }
     543             : 
     544           6 :         *sz = (size_t) v;
     545           6 :         return 0;
     546             : }
     547             : 
     548           9 : int config_parse_si_size(
     549             :                 const char* unit,
     550             :                 const char *filename,
     551             :                 unsigned line,
     552             :                 const char *section,
     553             :                 unsigned section_line,
     554             :                 const char *lvalue,
     555             :                 int ltype,
     556             :                 const char *rvalue,
     557             :                 void *data,
     558             :                 void *userdata) {
     559             : 
     560           9 :         size_t *sz = data;
     561             :         uint64_t v;
     562             :         int r;
     563             : 
     564           9 :         assert(filename);
     565           9 :         assert(lvalue);
     566           9 :         assert(rvalue);
     567           9 :         assert(data);
     568             : 
     569           9 :         r = parse_size(rvalue, 1000, &v);
     570             :         if (r >= 0 && (uint64_t) (size_t) v != v)
     571             :                 r = -ERANGE;
     572           9 :         if (r < 0) {
     573           3 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value '%s', ignoring: %m", rvalue);
     574           3 :                 return 0;
     575             :         }
     576             : 
     577           6 :         *sz = (size_t) v;
     578           6 :         return 0;
     579             : }
     580             : 
     581           2 : int config_parse_iec_uint64(
     582             :                 const char* unit,
     583             :                 const char *filename,
     584             :                 unsigned line,
     585             :                 const char *section,
     586             :                 unsigned section_line,
     587             :                 const char *lvalue,
     588             :                 int ltype,
     589             :                 const char *rvalue,
     590             :                 void *data,
     591             :                 void *userdata) {
     592             : 
     593           2 :         uint64_t *bytes = data;
     594             :         int r;
     595             : 
     596           2 :         assert(filename);
     597           2 :         assert(lvalue);
     598           2 :         assert(rvalue);
     599           2 :         assert(data);
     600             : 
     601           2 :         r = parse_size(rvalue, 1024, bytes);
     602           2 :         if (r < 0)
     603           0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue);
     604             : 
     605           2 :         return 0;
     606             : }
     607             : 
     608          20 : int config_parse_bool(const char* unit,
     609             :                       const char *filename,
     610             :                       unsigned line,
     611             :                       const char *section,
     612             :                       unsigned section_line,
     613             :                       const char *lvalue,
     614             :                       int ltype,
     615             :                       const char *rvalue,
     616             :                       void *data,
     617             :                       void *userdata) {
     618             : 
     619             :         int k;
     620          20 :         bool *b = data;
     621          20 :         bool fatal = ltype;
     622             : 
     623          20 :         assert(filename);
     624          20 :         assert(lvalue);
     625          20 :         assert(rvalue);
     626          20 :         assert(data);
     627             : 
     628          20 :         k = parse_boolean(rvalue);
     629          20 :         if (k < 0) {
     630           0 :                 log_syntax(unit, LOG_ERR, filename, line, k,
     631             :                            "Failed to parse boolean value%s: %s",
     632             :                            fatal ? "" : ", ignoring", rvalue);
     633           0 :                 return fatal ? -ENOEXEC : 0;
     634             :         }
     635             : 
     636          20 :         *b = k;
     637          20 :         return 0;
     638             : }
     639             : 
     640           0 : int config_parse_tristate(
     641             :                 const char* unit,
     642             :                 const char *filename,
     643             :                 unsigned line,
     644             :                 const char *section,
     645             :                 unsigned section_line,
     646             :                 const char *lvalue,
     647             :                 int ltype,
     648             :                 const char *rvalue,
     649             :                 void *data,
     650             :                 void *userdata) {
     651             : 
     652           0 :         int k, *t = data;
     653             : 
     654           0 :         assert(filename);
     655           0 :         assert(lvalue);
     656           0 :         assert(rvalue);
     657           0 :         assert(data);
     658             : 
     659             :         /* A tristate is pretty much a boolean, except that it can
     660             :          * also take the special value -1, indicating "uninitialized",
     661             :          * much like NULL is for a pointer type. */
     662             : 
     663           0 :         k = parse_boolean(rvalue);
     664           0 :         if (k < 0) {
     665           0 :                 log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse boolean value, ignoring: %s", rvalue);
     666           0 :                 return 0;
     667             :         }
     668             : 
     669           0 :         *t = !!k;
     670           0 :         return 0;
     671             : }
     672             : 
     673         108 : int config_parse_string(
     674             :                 const char *unit,
     675             :                 const char *filename,
     676             :                 unsigned line,
     677             :                 const char *section,
     678             :                 unsigned section_line,
     679             :                 const char *lvalue,
     680             :                 int ltype,
     681             :                 const char *rvalue,
     682             :                 void *data,
     683             :                 void *userdata) {
     684             : 
     685         108 :         char **s = data;
     686             : 
     687         108 :         assert(filename);
     688         108 :         assert(lvalue);
     689         108 :         assert(rvalue);
     690         108 :         assert(data);
     691             : 
     692         108 :         if (free_and_strdup(s, empty_to_null(rvalue)) < 0)
     693           0 :                 return log_oom();
     694             : 
     695         108 :         return 0;
     696             : }
     697             : 
     698           7 : int config_parse_path(
     699             :                 const char *unit,
     700             :                 const char *filename,
     701             :                 unsigned line,
     702             :                 const char *section,
     703             :                 unsigned section_line,
     704             :                 const char *lvalue,
     705             :                 int ltype,
     706             :                 const char *rvalue,
     707             :                 void *data,
     708             :                 void *userdata) {
     709             : 
     710           7 :         _cleanup_free_ char *n = NULL;
     711           7 :         bool fatal = ltype;
     712           7 :         char **s = data;
     713             :         int r;
     714             : 
     715           7 :         assert(filename);
     716           7 :         assert(lvalue);
     717           7 :         assert(rvalue);
     718           7 :         assert(data);
     719             : 
     720           7 :         if (isempty(rvalue))
     721           0 :                 goto finalize;
     722             : 
     723           7 :         n = strdup(rvalue);
     724           7 :         if (!n)
     725           0 :                 return log_oom();
     726             : 
     727           7 :         r = path_simplify_and_warn(n, PATH_CHECK_ABSOLUTE | (fatal ? PATH_CHECK_FATAL : 0), unit, filename, line, lvalue);
     728           7 :         if (r < 0)
     729           2 :                 return fatal ? -ENOEXEC : 0;
     730             : 
     731           5 : finalize:
     732           5 :         return free_and_replace(*s, n);
     733             : }
     734             : 
     735         510 : int config_parse_strv(
     736             :                 const char *unit,
     737             :                 const char *filename,
     738             :                 unsigned line,
     739             :                 const char *section,
     740             :                 unsigned section_line,
     741             :                 const char *lvalue,
     742             :                 int ltype,
     743             :                 const char *rvalue,
     744             :                 void *data,
     745             :                 void *userdata) {
     746             : 
     747         510 :         char ***sv = data;
     748             :         int r;
     749             : 
     750         510 :         assert(filename);
     751         510 :         assert(lvalue);
     752         510 :         assert(rvalue);
     753         510 :         assert(data);
     754             : 
     755         510 :         if (isempty(rvalue)) {
     756           1 :                 *sv = strv_free(*sv);
     757           1 :                 return 0;
     758             :         }
     759             : 
     760         519 :         for (;;) {
     761        1028 :                 char *word = NULL;
     762             : 
     763        1028 :                 r = extract_first_word(&rvalue, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
     764        1028 :                 if (r == 0)
     765         509 :                         break;
     766         519 :                 if (r == -ENOMEM)
     767           0 :                         return log_oom();
     768         519 :                 if (r < 0) {
     769           0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
     770           0 :                         break;
     771             :                 }
     772             : 
     773         519 :                 r = strv_consume(sv, word);
     774         519 :                 if (r < 0)
     775           0 :                         return log_oom();
     776             :         }
     777             : 
     778         509 :         return 0;
     779             : }
     780             : 
     781           0 : int config_parse_warn_compat(
     782             :                 const char *unit,
     783             :                 const char *filename,
     784             :                 unsigned line,
     785             :                 const char *section,
     786             :                 unsigned section_line,
     787             :                 const char *lvalue,
     788             :                 int ltype,
     789             :                 const char *rvalue,
     790             :                 void *data,
     791             :                 void *userdata) {
     792             : 
     793           0 :         Disabled reason = ltype;
     794             : 
     795           0 :         switch(reason) {
     796             : 
     797           0 :         case DISABLED_CONFIGURATION:
     798           0 :                 log_syntax(unit, LOG_DEBUG, filename, line, 0,
     799             :                            "Support for option %s= has been disabled at compile time and it is ignored", lvalue);
     800           0 :                 break;
     801             : 
     802           0 :         case DISABLED_LEGACY:
     803           0 :                 log_syntax(unit, LOG_INFO, filename, line, 0,
     804             :                            "Support for option %s= has been removed and it is ignored", lvalue);
     805           0 :                 break;
     806             : 
     807           0 :         case DISABLED_EXPERIMENTAL:
     808           0 :                 log_syntax(unit, LOG_INFO, filename, line, 0,
     809             :                            "Support for option %s= has not yet been enabled and it is ignored", lvalue);
     810           0 :                 break;
     811             :         }
     812             : 
     813           0 :         return 0;
     814             : }
     815             : 
     816           3 : int config_parse_log_facility(
     817             :                 const char *unit,
     818             :                 const char *filename,
     819             :                 unsigned line,
     820             :                 const char *section,
     821             :                 unsigned section_line,
     822             :                 const char *lvalue,
     823             :                 int ltype,
     824             :                 const char *rvalue,
     825             :                 void *data,
     826             :                 void *userdata) {
     827             : 
     828           3 :         int *o = data, x;
     829             : 
     830           3 :         assert(filename);
     831           3 :         assert(lvalue);
     832           3 :         assert(rvalue);
     833           3 :         assert(data);
     834             : 
     835           3 :         x = log_facility_unshifted_from_string(rvalue);
     836           3 :         if (x < 0) {
     837           1 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse log facility, ignoring: %s", rvalue);
     838           1 :                 return 0;
     839             :         }
     840             : 
     841           2 :         *o = (x << 3) | LOG_PRI(*o);
     842             : 
     843           2 :         return 0;
     844             : }
     845             : 
     846           3 : int config_parse_log_level(
     847             :                 const char *unit,
     848             :                 const char *filename,
     849             :                 unsigned line,
     850             :                 const char *section,
     851             :                 unsigned section_line,
     852             :                 const char *lvalue,
     853             :                 int ltype,
     854             :                 const char *rvalue,
     855             :                 void *data,
     856             :                 void *userdata) {
     857             : 
     858           3 :         int *o = data, x;
     859             : 
     860           3 :         assert(filename);
     861           3 :         assert(lvalue);
     862           3 :         assert(rvalue);
     863           3 :         assert(data);
     864             : 
     865           3 :         x = log_level_from_string(rvalue);
     866           3 :         if (x < 0) {
     867           1 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse log level, ignoring: %s", rvalue);
     868           1 :                 return 0;
     869             :         }
     870             : 
     871           2 :         if (*o < 0) /* if it wasn't initialized so far, assume zero facility */
     872           0 :                 *o = x;
     873             :         else
     874           2 :                 *o = (*o & LOG_FACMASK) | x;
     875             : 
     876           2 :         return 0;
     877             : }
     878             : 
     879           0 : int config_parse_signal(
     880             :                 const char *unit,
     881             :                 const char *filename,
     882             :                 unsigned line,
     883             :                 const char *section,
     884             :                 unsigned section_line,
     885             :                 const char *lvalue,
     886             :                 int ltype,
     887             :                 const char *rvalue,
     888             :                 void *data,
     889             :                 void *userdata) {
     890             : 
     891           0 :         int *sig = data, r;
     892             : 
     893           0 :         assert(filename);
     894           0 :         assert(lvalue);
     895           0 :         assert(rvalue);
     896           0 :         assert(sig);
     897             : 
     898           0 :         r = signal_from_string(rvalue);
     899           0 :         if (r <= 0) {
     900           0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse signal name, ignoring: %s", rvalue);
     901           0 :                 return 0;
     902             :         }
     903             : 
     904           0 :         *sig = r;
     905           0 :         return 0;
     906             : }
     907             : 
     908           0 : int config_parse_personality(
     909             :                 const char *unit,
     910             :                 const char *filename,
     911             :                 unsigned line,
     912             :                 const char *section,
     913             :                 unsigned section_line,
     914             :                 const char *lvalue,
     915             :                 int ltype,
     916             :                 const char *rvalue,
     917             :                 void *data,
     918             :                 void *userdata) {
     919             : 
     920           0 :         unsigned long *personality = data, p;
     921             : 
     922           0 :         assert(filename);
     923           0 :         assert(lvalue);
     924           0 :         assert(rvalue);
     925           0 :         assert(personality);
     926             : 
     927           0 :         if (isempty(rvalue))
     928           0 :                 p = PERSONALITY_INVALID;
     929             :         else {
     930           0 :                 p = personality_from_string(rvalue);
     931           0 :                 if (p == PERSONALITY_INVALID) {
     932           0 :                         log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse personality, ignoring: %s", rvalue);
     933           0 :                         return 0;
     934             :                 }
     935             :         }
     936             : 
     937           0 :         *personality = p;
     938           0 :         return 0;
     939             : }
     940             : 
     941           0 : int config_parse_ifname(
     942             :                 const char *unit,
     943             :                 const char *filename,
     944             :                 unsigned line,
     945             :                 const char *section,
     946             :                 unsigned section_line,
     947             :                 const char *lvalue,
     948             :                 int ltype,
     949             :                 const char *rvalue,
     950             :                 void *data,
     951             :                 void *userdata) {
     952             : 
     953           0 :         char **s = data;
     954             :         int r;
     955             : 
     956           0 :         assert(filename);
     957           0 :         assert(lvalue);
     958           0 :         assert(rvalue);
     959           0 :         assert(data);
     960             : 
     961           0 :         if (isempty(rvalue)) {
     962           0 :                 *s = mfree(*s);
     963           0 :                 return 0;
     964             :         }
     965             : 
     966           0 :         if (!ifname_valid(rvalue)) {
     967           0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is not valid or too long, ignoring assignment: %s", rvalue);
     968           0 :                 return 0;
     969             :         }
     970             : 
     971           0 :         r = free_and_strdup(s, rvalue);
     972           0 :         if (r < 0)
     973           0 :                 return log_oom();
     974             : 
     975           0 :         return 0;
     976             : }
     977             : 
     978           0 : int config_parse_ip_port(
     979             :                 const char *unit,
     980             :                 const char *filename,
     981             :                 unsigned line,
     982             :                 const char *section,
     983             :                 unsigned section_line,
     984             :                 const char *lvalue,
     985             :                 int ltype,
     986             :                 const char *rvalue,
     987             :                 void *data,
     988             :                 void *userdata) {
     989             : 
     990           0 :         uint16_t *s = data;
     991             :         uint16_t port;
     992             :         int r;
     993             : 
     994           0 :         assert(filename);
     995           0 :         assert(lvalue);
     996           0 :         assert(rvalue);
     997           0 :         assert(data);
     998             : 
     999           0 :         if (isempty(rvalue)) {
    1000           0 :                 *s = 0;
    1001           0 :                 return 0;
    1002             :         }
    1003             : 
    1004           0 :         r = parse_ip_port(rvalue, &port);
    1005           0 :         if (r < 0) {
    1006           0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse port '%s'.", rvalue);
    1007           0 :                 return 0;
    1008             :         }
    1009             : 
    1010           0 :         *s = port;
    1011             : 
    1012           0 :         return 0;
    1013             : }
    1014             : 
    1015           0 : int config_parse_mtu(
    1016             :                 const char *unit,
    1017             :                 const char *filename,
    1018             :                 unsigned line,
    1019             :                 const char *section,
    1020             :                 unsigned section_line,
    1021             :                 const char *lvalue,
    1022             :                 int ltype,
    1023             :                 const char *rvalue,
    1024             :                 void *data,
    1025             :                 void *userdata) {
    1026             : 
    1027           0 :         uint32_t *mtu = data;
    1028             :         int r;
    1029             : 
    1030           0 :         assert(rvalue);
    1031           0 :         assert(mtu);
    1032             : 
    1033           0 :         r = parse_mtu(ltype, rvalue, mtu);
    1034           0 :         if (r == -ERANGE) {
    1035           0 :                 log_syntax(unit, LOG_ERR, filename, line, r,
    1036             :                            "Maximum transfer unit (MTU) value out of range. Permitted range is %" PRIu32 "…%" PRIu32 ", ignoring: %s",
    1037             :                            (uint32_t) (ltype == AF_INET6 ? IPV6_MIN_MTU : IPV4_MIN_MTU), (uint32_t) UINT32_MAX,
    1038             :                            rvalue);
    1039           0 :                 return 0;
    1040             :         }
    1041           0 :         if (r < 0) {
    1042           0 :                 log_syntax(unit, LOG_ERR, filename, line, r,
    1043             :                            "Failed to parse MTU value '%s', ignoring: %m", rvalue);
    1044           0 :                 return 0;
    1045             :         }
    1046             : 
    1047           0 :         return 0;
    1048             : }
    1049             : 
    1050          20 : int config_parse_rlimit(
    1051             :                 const char *unit,
    1052             :                 const char *filename,
    1053             :                 unsigned line,
    1054             :                 const char *section,
    1055             :                 unsigned section_line,
    1056             :                 const char *lvalue,
    1057             :                 int ltype,
    1058             :                 const char *rvalue,
    1059             :                 void *data,
    1060             :                 void *userdata) {
    1061             : 
    1062          20 :         struct rlimit **rl = data, d = {};
    1063             :         int r;
    1064             : 
    1065          20 :         assert(rvalue);
    1066          20 :         assert(rl);
    1067             : 
    1068          20 :         r = rlimit_parse(ltype, rvalue, &d);
    1069          20 :         if (r == -EILSEQ) {
    1070           1 :                 log_syntax(unit, LOG_WARNING, filename, line, r, "Soft resource limit chosen higher than hard limit, ignoring: %s", rvalue);
    1071           1 :                 return 0;
    1072             :         }
    1073          19 :         if (r < 0) {
    1074           3 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
    1075           3 :                 return 0;
    1076             :         }
    1077             : 
    1078          16 :         if (rl[ltype])
    1079          13 :                 *rl[ltype] = d;
    1080             :         else {
    1081           3 :                 rl[ltype] = newdup(struct rlimit, &d, 1);
    1082           3 :                 if (!rl[ltype])
    1083           0 :                         return log_oom();
    1084             :         }
    1085             : 
    1086          16 :         return 0;
    1087             : }
    1088             : 
    1089           0 : int config_parse_permille(const char* unit,
    1090             :                           const char *filename,
    1091             :                           unsigned line,
    1092             :                           const char *section,
    1093             :                           unsigned section_line,
    1094             :                           const char *lvalue,
    1095             :                           int ltype,
    1096             :                           const char *rvalue,
    1097             :                           void *data,
    1098             :                           void *userdata) {
    1099             : 
    1100           0 :         unsigned *permille = data;
    1101             :         int r;
    1102             : 
    1103           0 :         assert(filename);
    1104           0 :         assert(lvalue);
    1105           0 :         assert(rvalue);
    1106           0 :         assert(permille);
    1107             : 
    1108           0 :         r = parse_permille(rvalue);
    1109           0 :         if (r < 0) {
    1110           0 :                 log_syntax(unit, LOG_ERR, filename, line, r,
    1111             :                            "Failed to parse permille value, ignoring: %s", rvalue);
    1112           0 :                 return 0;
    1113             :         }
    1114             : 
    1115           0 :         *permille = (unsigned) r;
    1116             : 
    1117           0 :         return 0;
    1118             : }

Generated by: LCOV version 1.14