LCOV - code coverage report
Current view: top level - shared - conf-parser.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 264 328 80.5 %
Date: 2015-07-29 18:47:03 Functions: 20 23 87.0 %

          Line data    Source code
       1             : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
       2             : 
       3             : /***
       4             :   This file is part of systemd.
       5             : 
       6             :   Copyright 2010 Lennart Poettering
       7             : 
       8             :   systemd is free software; you can redistribute it and/or modify it
       9             :   under the terms of the GNU Lesser General Public License as published by
      10             :   the Free Software Foundation; either version 2.1 of the License, or
      11             :   (at your option) any later version.
      12             : 
      13             :   systemd is distributed in the hope that it will be useful, but
      14             :   WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      16             :   Lesser General Public License for more details.
      17             : 
      18             :   You should have received a copy of the GNU Lesser General Public License
      19             :   along with systemd; If not, see <http://www.gnu.org/licenses/>.
      20             : ***/
      21             : 
      22             : #include <string.h>
      23             : #include <stdio.h>
      24             : #include <errno.h>
      25             : #include <stdlib.h>
      26             : 
      27             : #include "conf-parser.h"
      28             : #include "conf-files.h"
      29             : #include "util.h"
      30             : #include "macro.h"
      31             : #include "strv.h"
      32             : #include "log.h"
      33             : #include "utf8.h"
      34             : #include "path-util.h"
      35             : #include "sd-messages.h"
      36             : 
      37        2117 : int config_item_table_lookup(
      38             :                 const void *table,
      39             :                 const char *section,
      40             :                 const char *lvalue,
      41             :                 ConfigParserCallback *func,
      42             :                 int *ltype,
      43             :                 void **data,
      44             :                 void *userdata) {
      45             : 
      46             :         const ConfigTableItem *t;
      47             : 
      48        2117 :         assert(table);
      49        2117 :         assert(lvalue);
      50        2117 :         assert(func);
      51        2117 :         assert(ltype);
      52        2117 :         assert(data);
      53             : 
      54       14278 :         for (t = table; t->lvalue; t++) {
      55             : 
      56       12276 :                 if (!streq(lvalue, t->lvalue))
      57       12150 :                         continue;
      58             : 
      59         126 :                 if (!streq_ptr(section, t->section))
      60          11 :                         continue;
      61             : 
      62         115 :                 *func = t->parse;
      63         115 :                 *ltype = t->ltype;
      64         115 :                 *data = t->data;
      65         115 :                 return 1;
      66             :         }
      67             : 
      68        2002 :         return 0;
      69             : }
      70             : 
      71         352 : int config_item_perf_lookup(
      72             :                 const void *table,
      73             :                 const char *section,
      74             :                 const char *lvalue,
      75             :                 ConfigParserCallback *func,
      76             :                 int *ltype,
      77             :                 void **data,
      78             :                 void *userdata) {
      79             : 
      80         352 :         ConfigPerfItemLookup lookup = (ConfigPerfItemLookup) table;
      81             :         const ConfigPerfItem *p;
      82             : 
      83         352 :         assert(table);
      84         352 :         assert(lvalue);
      85         352 :         assert(func);
      86         352 :         assert(ltype);
      87         352 :         assert(data);
      88             : 
      89         352 :         if (!section)
      90           0 :                 p = lookup(lvalue, strlen(lvalue));
      91             :         else {
      92             :                 char *key;
      93             : 
      94         352 :                 key = strjoin(section, ".", lvalue, NULL);
      95         352 :                 if (!key)
      96           0 :                         return -ENOMEM;
      97             : 
      98         352 :                 p = lookup(key, strlen(key));
      99         352 :                 free(key);
     100             :         }
     101             : 
     102         352 :         if (!p)
     103           0 :                 return 0;
     104             : 
     105         352 :         *func = p->parse;
     106         352 :         *ltype = p->ltype;
     107         352 :         *data = (uint8_t*) userdata + p->offset;
     108         352 :         return 1;
     109             : }
     110             : 
     111             : /* Run the user supplied parser for an assignment */
     112        2469 : static int next_assignment(const char *unit,
     113             :                            const char *filename,
     114             :                            unsigned line,
     115             :                            ConfigItemLookup lookup,
     116             :                            const void *table,
     117             :                            const char *section,
     118             :                            unsigned section_line,
     119             :                            const char *lvalue,
     120             :                            const char *rvalue,
     121             :                            bool relaxed,
     122             :                            void *userdata) {
     123             : 
     124        2469 :         ConfigParserCallback func = NULL;
     125        2469 :         int ltype = 0;
     126        2469 :         void *data = NULL;
     127             :         int r;
     128             : 
     129        2469 :         assert(filename);
     130        2469 :         assert(line > 0);
     131        2469 :         assert(lookup);
     132        2469 :         assert(lvalue);
     133        2469 :         assert(rvalue);
     134             : 
     135        2469 :         r = lookup(table, section, lvalue, &func, &ltype, &data, userdata);
     136        2469 :         if (r < 0)
     137           0 :                 return r;
     138             : 
     139        2469 :         if (r > 0) {
     140         467 :                 if (func)
     141         460 :                         return func(unit, filename, line, section, section_line,
     142             :                                     lvalue, ltype, rvalue, data, userdata);
     143             : 
     144           7 :                 return 0;
     145             :         }
     146             : 
     147             :         /* Warn about unknown non-extension fields. */
     148        2002 :         if (!relaxed && !startswith(lvalue, "X-"))
     149           0 :                 log_syntax(unit, LOG_WARNING, filename, line, EINVAL,
     150             :                            "Unknown lvalue '%s' in section '%s'", lvalue, section);
     151             : 
     152        2002 :         return 0;
     153             : }
     154             : 
     155             : /* Parse a variable assignment line */
     156        5512 : static int parse_line(const char* unit,
     157             :                       const char *filename,
     158             :                       unsigned line,
     159             :                       const char *sections,
     160             :                       ConfigItemLookup lookup,
     161             :                       const void *table,
     162             :                       bool relaxed,
     163             :                       bool allow_include,
     164             :                       char **section,
     165             :                       unsigned *section_line,
     166             :                       bool *section_ignored,
     167             :                       char *l,
     168             :                       void *userdata) {
     169             : 
     170             :         char *e;
     171             : 
     172        5512 :         assert(filename);
     173        5512 :         assert(line > 0);
     174        5512 :         assert(lookup);
     175        5512 :         assert(l);
     176             : 
     177        5512 :         l = strstrip(l);
     178             : 
     179        5512 :         if (!*l)
     180         672 :                 return 0;
     181             : 
     182        4840 :         if (strchr(COMMENTS "\n", *l))
     183        1643 :                 return 0;
     184             : 
     185        3197 :         if (startswith(l, ".include ")) {
     186           0 :                 _cleanup_free_ char *fn = NULL;
     187             : 
     188             :                 /* .includes are a bad idea, we only support them here
     189             :                  * for historical reasons. They create cyclic include
     190             :                  * problems and make it difficult to detect
     191             :                  * configuration file changes with an easy
     192             :                  * stat(). Better approaches, such as .d/ drop-in
     193             :                  * snippets exist.
     194             :                  *
     195             :                  * Support for them should be eventually removed. */
     196             : 
     197           0 :                 if (!allow_include) {
     198           0 :                         log_syntax(unit, LOG_ERR, filename, line, EBADMSG,
     199             :                                    ".include not allowed here. Ignoring.");
     200           0 :                         return 0;
     201             :                 }
     202             : 
     203           0 :                 fn = file_in_same_dir(filename, strstrip(l+9));
     204           0 :                 if (!fn)
     205           0 :                         return -ENOMEM;
     206             : 
     207           0 :                 return config_parse(unit, fn, NULL, sections, lookup, table, relaxed, false, false, userdata);
     208             :         }
     209             : 
     210        3197 :         if (*l == '[') {
     211             :                 size_t k;
     212             :                 char *n;
     213             : 
     214         728 :                 k = strlen(l);
     215         728 :                 assert(k > 0);
     216             : 
     217         728 :                 if (l[k-1] != ']') {
     218           0 :                         log_syntax(unit, LOG_ERR, filename, line, EBADMSG,
     219             :                                    "Invalid section header '%s'", l);
     220           0 :                         return -EBADMSG;
     221             :                 }
     222             : 
     223         728 :                 n = strndup(l+1, k-2);
     224         728 :                 if (!n)
     225           0 :                         return -ENOMEM;
     226             : 
     227         728 :                 if (sections && !nulstr_contains(sections, n)) {
     228             : 
     229           0 :                         if (!relaxed && !startswith(n, "X-"))
     230           0 :                                 log_syntax(unit, LOG_WARNING, filename, line, EINVAL,
     231             :                                            "Unknown section '%s'. Ignoring.", n);
     232             : 
     233           0 :                         free(n);
     234           0 :                         free(*section);
     235           0 :                         *section = NULL;
     236           0 :                         *section_line = 0;
     237           0 :                         *section_ignored = true;
     238             :                 } else {
     239         728 :                         free(*section);
     240         728 :                         *section = n;
     241         728 :                         *section_line = line;
     242         728 :                         *section_ignored = false;
     243             :                 }
     244             : 
     245         728 :                 return 0;
     246             :         }
     247             : 
     248        2469 :         if (sections && !*section) {
     249             : 
     250           0 :                 if (!relaxed && !*section_ignored)
     251           0 :                         log_syntax(unit, LOG_WARNING, filename, line, EINVAL,
     252             :                                    "Assignment outside of section. Ignoring.");
     253             : 
     254           0 :                 return 0;
     255             :         }
     256             : 
     257        2469 :         e = strchr(l, '=');
     258        2469 :         if (!e) {
     259           0 :                 log_syntax(unit, LOG_WARNING, filename, line, EINVAL, "Missing '='.");
     260           0 :                 return -EBADMSG;
     261             :         }
     262             : 
     263        2469 :         *e = 0;
     264        2469 :         e++;
     265             : 
     266        4938 :         return next_assignment(unit,
     267             :                                filename,
     268             :                                line,
     269             :                                lookup,
     270             :                                table,
     271             :                                *section,
     272             :                                *section_line,
     273        2469 :                                strstrip(l),
     274        2469 :                                strstrip(e),
     275             :                                relaxed,
     276             :                                userdata);
     277             : }
     278             : 
     279             : /* Go through the file and parse each line */
     280         373 : int config_parse(const char *unit,
     281             :                  const char *filename,
     282             :                  FILE *f,
     283             :                  const char *sections,
     284             :                  ConfigItemLookup lookup,
     285             :                  const void *table,
     286             :                  bool relaxed,
     287             :                  bool allow_include,
     288             :                  bool warn,
     289             :                  void *userdata) {
     290             : 
     291         746 :         _cleanup_free_ char *section = NULL, *continuation = NULL;
     292         746 :         _cleanup_fclose_ FILE *ours = NULL;
     293         373 :         unsigned line = 0, section_line = 0;
     294         373 :         bool section_ignored = false;
     295             :         int r;
     296             : 
     297         373 :         assert(filename);
     298         373 :         assert(lookup);
     299             : 
     300         373 :         if (!f) {
     301           3 :                 f = ours = fopen(filename, "re");
     302           3 :                 if (!f) {
     303             :                         /* Only log on request, except for ENOENT,
     304             :                          * since we return 0 to the caller. */
     305           3 :                         if (warn || errno == ENOENT)
     306           3 :                                 log_full(errno == ENOENT ? LOG_DEBUG : LOG_ERR,
     307             :                                          "Failed to open configuration file '%s': %m", filename);
     308           3 :                         return errno == ENOENT ? 0 : -errno;
     309             :                 }
     310             :         }
     311             : 
     312         370 :         fd_warn_permissions(filename, fileno(f));
     313             : 
     314         370 :         while (!feof(f)) {
     315        5885 :                 char l[LINE_MAX], *p, *c = NULL, *e;
     316        5885 :                 bool escaped = false;
     317             : 
     318        5885 :                 if (!fgets(l, sizeof(l), f)) {
     319         370 :                         if (feof(f))
     320         370 :                                 break;
     321             : 
     322           0 :                         log_error_errno(errno, "Failed to read configuration file '%s': %m", filename);
     323           0 :                         return -errno;
     324             :                 }
     325             : 
     326        5515 :                 truncate_nl(l);
     327             : 
     328        5515 :                 if (continuation) {
     329           3 :                         c = strappend(continuation, l);
     330           3 :                         if (!c) {
     331           0 :                                 if (warn)
     332           0 :                                         log_oom();
     333           0 :                                 return -ENOMEM;
     334             :                         }
     335             : 
     336           3 :                         free(continuation);
     337           3 :                         continuation = NULL;
     338           3 :                         p = c;
     339             :                 } else
     340        5512 :                         p = l;
     341             : 
     342      168870 :                 for (e = p; *e; e++) {
     343      163355 :                         if (escaped)
     344           4 :                                 escaped = false;
     345      163351 :                         else if (*e == '\\')
     346           7 :                                 escaped = true;
     347             :                 }
     348             : 
     349        5515 :                 if (escaped) {
     350           3 :                         *(e-1) = ' ';
     351             : 
     352           3 :                         if (c)
     353           1 :                                 continuation = c;
     354             :                         else {
     355           2 :                                 continuation = strdup(l);
     356           2 :                                 if (!continuation) {
     357           0 :                                         if (warn)
     358           0 :                                                 log_oom();
     359           0 :                                         return -ENOMEM;
     360             :                                 }
     361             :                         }
     362             : 
     363           3 :                         continue;
     364             :                 }
     365             : 
     366        5512 :                 r = parse_line(unit,
     367             :                                filename,
     368             :                                ++line,
     369             :                                sections,
     370             :                                lookup,
     371             :                                table,
     372             :                                relaxed,
     373             :                                allow_include,
     374             :                                &section,
     375             :                                &section_line,
     376             :                                &section_ignored,
     377             :                                p,
     378             :                                userdata);
     379        5512 :                 free(c);
     380             : 
     381        5512 :                 if (r < 0) {
     382           0 :                         if (warn)
     383           0 :                                 log_warning_errno(r, "Failed to parse file '%s': %m",
     384             :                                                   filename);
     385           0 :                         return r;
     386             :                 }
     387             :         }
     388             : 
     389         370 :         return 0;
     390             : }
     391             : 
     392             : /* Parse each config file in the specified directories. */
     393           3 : int config_parse_many(const char *conf_file,
     394             :                       const char *conf_file_dirs,
     395             :                       const char *sections,
     396             :                       ConfigItemLookup lookup,
     397             :                       const void *table,
     398             :                       bool relaxed,
     399             :                       void *userdata) {
     400           6 :         _cleanup_strv_free_ char **files = NULL;
     401             :         char **fn;
     402             :         int r;
     403             : 
     404           3 :         r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
     405           3 :         if (r < 0)
     406           0 :                 return r;
     407             : 
     408           3 :         if (conf_file) {
     409           3 :                 r = config_parse(NULL, conf_file, NULL, sections, lookup, table, relaxed, false, true, userdata);
     410           3 :                 if (r < 0)
     411           0 :                         return r;
     412             :         }
     413             : 
     414           3 :         STRV_FOREACH(fn, files) {
     415           0 :                 r = config_parse(NULL, *fn, NULL, sections, lookup, table, relaxed, false, true, userdata);
     416           0 :                 if (r < 0)
     417           0 :                         return r;
     418             :         }
     419             : 
     420           3 :         return 0;
     421             : }
     422             : 
     423             : #define DEFINE_PARSER(type, vartype, conv_func)                         \
     424             :         int config_parse_##type(const char *unit,                       \
     425             :                                 const char *filename,                   \
     426             :                                 unsigned line,                          \
     427             :                                 const char *section,                    \
     428             :                                 unsigned section_line,                  \
     429             :                                 const char *lvalue,                     \
     430             :                                 int ltype,                              \
     431             :                                 const char *rvalue,                     \
     432             :                                 void *data,                             \
     433             :                                 void *userdata) {                       \
     434             :                                                                         \
     435             :                 vartype *i = data;                                      \
     436             :                 int r;                                                  \
     437             :                                                                         \
     438             :                 assert(filename);                                       \
     439             :                 assert(lvalue);                                         \
     440             :                 assert(rvalue);                                         \
     441             :                 assert(data);                                           \
     442             :                                                                         \
     443             :                 r = conv_func(rvalue, i);                               \
     444             :                 if (r < 0)                                              \
     445             :                         log_syntax(unit, LOG_ERR, filename, line, -r,   \
     446             :                                    "Failed to parse %s value, ignoring: %s", \
     447             :                                    #type, rvalue);                      \
     448             :                                                                         \
     449             :                 return 0;                                               \
     450             :         }
     451             : 
     452           7 : DEFINE_PARSER(int, int, safe_atoi)
     453           0 : DEFINE_PARSER(long, long, safe_atoli)
     454           0 : DEFINE_PARSER(uint64, uint64_t, safe_atou64)
     455           7 : DEFINE_PARSER(unsigned, unsigned, safe_atou)
     456           0 : DEFINE_PARSER(double, double, safe_atod)
     457           7 : DEFINE_PARSER(nsec, nsec_t, parse_nsec)
     458           7 : DEFINE_PARSER(sec, usec_t, parse_sec)
     459             : 
     460           9 : int config_parse_iec_size(const char* unit,
     461             :                             const char *filename,
     462             :                             unsigned line,
     463             :                             const char *section,
     464             :                             unsigned section_line,
     465             :                             const char *lvalue,
     466             :                             int ltype,
     467             :                             const char *rvalue,
     468             :                             void *data,
     469             :                             void *userdata) {
     470             : 
     471           9 :         size_t *sz = data;
     472             :         off_t o;
     473             :         int r;
     474             : 
     475           9 :         assert(filename);
     476           9 :         assert(lvalue);
     477           9 :         assert(rvalue);
     478           9 :         assert(data);
     479             : 
     480           9 :         r = parse_size(rvalue, 1024, &o);
     481           9 :         if (r < 0 || (off_t) (size_t) o != o) {
     482           3 :                 log_syntax(unit, LOG_ERR, filename, line, r < 0 ? -r : ERANGE, "Failed to parse size value, ignoring: %s", rvalue);
     483           3 :                 return 0;
     484             :         }
     485             : 
     486           6 :         *sz = (size_t) o;
     487           6 :         return 0;
     488             : }
     489             : 
     490           9 : int config_parse_si_size(const char* unit,
     491             :                             const char *filename,
     492             :                             unsigned line,
     493             :                             const char *section,
     494             :                             unsigned section_line,
     495             :                             const char *lvalue,
     496             :                             int ltype,
     497             :                             const char *rvalue,
     498             :                             void *data,
     499             :                             void *userdata) {
     500             : 
     501           9 :         size_t *sz = data;
     502             :         off_t o;
     503             :         int r;
     504             : 
     505           9 :         assert(filename);
     506           9 :         assert(lvalue);
     507           9 :         assert(rvalue);
     508           9 :         assert(data);
     509             : 
     510           9 :         r = parse_size(rvalue, 1000, &o);
     511           9 :         if (r < 0 || (off_t) (size_t) o != o) {
     512           3 :                 log_syntax(unit, LOG_ERR, filename, line, r < 0 ? -r : ERANGE, "Failed to parse size value, ignoring: %s", rvalue);
     513           3 :                 return 0;
     514             :         }
     515             : 
     516           6 :         *sz = (size_t) o;
     517           6 :         return 0;
     518             : }
     519             : 
     520           2 : int config_parse_iec_off(const char* unit,
     521             :                            const char *filename,
     522             :                            unsigned line,
     523             :                            const char *section,
     524             :                            unsigned section_line,
     525             :                            const char *lvalue,
     526             :                            int ltype,
     527             :                            const char *rvalue,
     528             :                            void *data,
     529             :                            void *userdata) {
     530             : 
     531           2 :         off_t *bytes = data;
     532             :         int r;
     533             : 
     534           2 :         assert(filename);
     535           2 :         assert(lvalue);
     536           2 :         assert(rvalue);
     537           2 :         assert(data);
     538             : 
     539             :         assert_cc(sizeof(off_t) == sizeof(uint64_t));
     540             : 
     541           2 :         r = parse_size(rvalue, 1024, bytes);
     542           2 :         if (r < 0)
     543           0 :                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to parse size value, ignoring: %s", rvalue);
     544             : 
     545           2 :         return 0;
     546             : }
     547             : 
     548          33 : int config_parse_bool(const char* unit,
     549             :                       const char *filename,
     550             :                       unsigned line,
     551             :                       const char *section,
     552             :                       unsigned section_line,
     553             :                       const char *lvalue,
     554             :                       int ltype,
     555             :                       const char *rvalue,
     556             :                       void *data,
     557             :                       void *userdata) {
     558             : 
     559             :         int k;
     560          33 :         bool *b = data;
     561             : 
     562          33 :         assert(filename);
     563          33 :         assert(lvalue);
     564          33 :         assert(rvalue);
     565          33 :         assert(data);
     566             : 
     567          33 :         k = parse_boolean(rvalue);
     568          33 :         if (k < 0) {
     569           0 :                 log_syntax(unit, LOG_ERR, filename, line, -k,
     570             :                            "Failed to parse boolean value, ignoring: %s", rvalue);
     571           0 :                 return 0;
     572             :         }
     573             : 
     574          33 :         *b = !!k;
     575          33 :         return 0;
     576             : }
     577             : 
     578          92 : int config_parse_string(
     579             :                 const char *unit,
     580             :                 const char *filename,
     581             :                 unsigned line,
     582             :                 const char *section,
     583             :                 unsigned section_line,
     584             :                 const char *lvalue,
     585             :                 int ltype,
     586             :                 const char *rvalue,
     587             :                 void *data,
     588             :                 void *userdata) {
     589             : 
     590          92 :         char **s = data, *n;
     591             : 
     592          92 :         assert(filename);
     593          92 :         assert(lvalue);
     594          92 :         assert(rvalue);
     595          92 :         assert(data);
     596             : 
     597          92 :         if (!utf8_is_valid(rvalue)) {
     598           0 :                 log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
     599           0 :                 return 0;
     600             :         }
     601             : 
     602          92 :         if (isempty(rvalue))
     603           0 :                 n = NULL;
     604             :         else {
     605          92 :                 n = strdup(rvalue);
     606          92 :                 if (!n)
     607           0 :                         return log_oom();
     608             :         }
     609             : 
     610          92 :         free(*s);
     611          92 :         *s = n;
     612             : 
     613          92 :         return 0;
     614             : }
     615             : 
     616           4 : int config_parse_path(
     617             :                 const char *unit,
     618             :                 const char *filename,
     619             :                 unsigned line,
     620             :                 const char *section,
     621             :                 unsigned section_line,
     622             :                 const char *lvalue,
     623             :                 int ltype,
     624             :                 const char *rvalue,
     625             :                 void *data,
     626             :                 void *userdata) {
     627             : 
     628           4 :         char **s = data, *n;
     629             : 
     630           4 :         assert(filename);
     631           4 :         assert(lvalue);
     632           4 :         assert(rvalue);
     633           4 :         assert(data);
     634             : 
     635           4 :         if (!utf8_is_valid(rvalue)) {
     636           0 :                 log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
     637           0 :                 return 0;
     638             :         }
     639             : 
     640           4 :         if (!path_is_absolute(rvalue)) {
     641           1 :                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Not an absolute path, ignoring: %s", rvalue);
     642           1 :                 return 0;
     643             :         }
     644             : 
     645           3 :         n = strdup(rvalue);
     646           3 :         if (!n)
     647           0 :                 return log_oom();
     648             : 
     649           3 :         path_kill_slashes(n);
     650             : 
     651           3 :         free(*s);
     652           3 :         *s = n;
     653             : 
     654           3 :         return 0;
     655             : }
     656             : 
     657         163 : int config_parse_strv(const char *unit,
     658             :                       const char *filename,
     659             :                       unsigned line,
     660             :                       const char *section,
     661             :                       unsigned section_line,
     662             :                       const char *lvalue,
     663             :                       int ltype,
     664             :                       const char *rvalue,
     665             :                       void *data,
     666             :                       void *userdata) {
     667             : 
     668         163 :         char ***sv = data;
     669             :         const char *word, *state;
     670             :         size_t l;
     671             :         int r;
     672             : 
     673         163 :         assert(filename);
     674         163 :         assert(lvalue);
     675         163 :         assert(rvalue);
     676         163 :         assert(data);
     677             : 
     678         163 :         if (isempty(rvalue)) {
     679             :                 char **empty;
     680             : 
     681             :                 /* Empty assignment resets the list. As a special rule
     682             :                  * we actually fill in a real empty array here rather
     683             :                  * than NULL, since some code wants to know if
     684             :                  * something was set at all... */
     685           1 :                 empty = strv_new(NULL, NULL);
     686           1 :                 if (!empty)
     687           0 :                         return log_oom();
     688             : 
     689           1 :                 strv_free(*sv);
     690           1 :                 *sv = empty;
     691           1 :                 return 0;
     692             :         }
     693             : 
     694         329 :         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
     695             :                 char *n;
     696             : 
     697         167 :                 n = strndup(word, l);
     698         167 :                 if (!n)
     699           0 :                         return log_oom();
     700             : 
     701         167 :                 if (!utf8_is_valid(n)) {
     702           0 :                         log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
     703           0 :                         free(n);
     704           0 :                         continue;
     705             :                 }
     706             : 
     707         167 :                 r = strv_consume(sv, n);
     708         167 :                 if (r < 0)
     709           0 :                         return log_oom();
     710             :         }
     711         162 :         if (!isempty(state))
     712           0 :                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
     713             :                            "Trailing garbage, ignoring.");
     714             : 
     715         162 :         return 0;
     716             : }
     717             : 
     718           8 : int config_parse_mode(
     719             :                 const char *unit,
     720             :                 const char *filename,
     721             :                 unsigned line,
     722             :                 const char *section,
     723             :                       unsigned section_line,
     724             :                 const char *lvalue,
     725             :                 int ltype,
     726             :                 const char *rvalue,
     727             :                 void *data,
     728             :                 void *userdata) {
     729             : 
     730           8 :         mode_t *m = data;
     731             : 
     732           8 :         assert(filename);
     733           8 :         assert(lvalue);
     734           8 :         assert(rvalue);
     735           8 :         assert(data);
     736             : 
     737           8 :         if (parse_mode(rvalue, m) < 0) {
     738           5 :                 log_syntax(unit, LOG_ERR, filename, line, errno, "Failed to parse mode value, ignoring: %s", rvalue);
     739           5 :                 return 0;
     740             :         }
     741             : 
     742           3 :         return 0;
     743             : }
     744             : 
     745           3 : int config_parse_log_facility(
     746             :                 const char *unit,
     747             :                 const char *filename,
     748             :                 unsigned line,
     749             :                 const char *section,
     750             :                 unsigned section_line,
     751             :                 const char *lvalue,
     752             :                 int ltype,
     753             :                 const char *rvalue,
     754             :                 void *data,
     755             :                 void *userdata) {
     756             : 
     757             : 
     758           3 :         int *o = data, x;
     759             : 
     760           3 :         assert(filename);
     761           3 :         assert(lvalue);
     762           3 :         assert(rvalue);
     763           3 :         assert(data);
     764             : 
     765           3 :         x = log_facility_unshifted_from_string(rvalue);
     766           3 :         if (x < 0) {
     767           1 :                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse log facility, ignoring: %s", rvalue);
     768           1 :                 return 0;
     769             :         }
     770             : 
     771           2 :         *o = (x << 3) | LOG_PRI(*o);
     772             : 
     773           2 :         return 0;
     774             : }
     775             : 
     776           3 : int config_parse_log_level(
     777             :                 const char *unit,
     778             :                 const char *filename,
     779             :                 unsigned line,
     780             :                 const char *section,
     781             :                 unsigned section_line,
     782             :                 const char *lvalue,
     783             :                 int ltype,
     784             :                 const char *rvalue,
     785             :                 void *data,
     786             :                 void *userdata) {
     787             : 
     788             : 
     789           3 :         int *o = data, x;
     790             : 
     791           3 :         assert(filename);
     792           3 :         assert(lvalue);
     793           3 :         assert(rvalue);
     794           3 :         assert(data);
     795             : 
     796           3 :         x = log_level_from_string(rvalue);
     797           3 :         if (x < 0) {
     798           1 :                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse log level, ignoring: %s", rvalue);
     799           1 :                 return 0;
     800             :         }
     801             : 
     802           2 :         *o = (*o & LOG_FACMASK) | x;
     803           2 :         return 0;
     804             : }

Generated by: LCOV version 1.11