LCOV - code coverage report
Current view: top level - core - load-fragment.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 457 2387 19.1 %
Date: 2019-08-23 13:36:53 Functions: 22 111 19.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 350 2678 13.1 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : /***
       3                 :            :   Copyright © 2012 Holger Hans Peter Freyther
       4                 :            : ***/
       5                 :            : 
       6                 :            : #include <errno.h>
       7                 :            : #include <fcntl.h>
       8                 :            : #include <linux/fs.h>
       9                 :            : #include <linux/oom.h>
      10                 :            : #if HAVE_SECCOMP
      11                 :            : #include <seccomp.h>
      12                 :            : #endif
      13                 :            : #include <sched.h>
      14                 :            : #include <string.h>
      15                 :            : #include <sys/resource.h>
      16                 :            : #include <sys/stat.h>
      17                 :            : 
      18                 :            : #include "af-list.h"
      19                 :            : #include "alloc-util.h"
      20                 :            : #include "all-units.h"
      21                 :            : #include "bpf-firewall.h"
      22                 :            : #include "bus-error.h"
      23                 :            : #include "bus-internal.h"
      24                 :            : #include "bus-util.h"
      25                 :            : #include "cap-list.h"
      26                 :            : #include "capability-util.h"
      27                 :            : #include "cgroup.h"
      28                 :            : #include "conf-parser.h"
      29                 :            : #include "cpu-set-util.h"
      30                 :            : #include "env-util.h"
      31                 :            : #include "errno-list.h"
      32                 :            : #include "escape.h"
      33                 :            : #include "fd-util.h"
      34                 :            : #include "fs-util.h"
      35                 :            : #include "hexdecoct.h"
      36                 :            : #include "io-util.h"
      37                 :            : #include "ioprio.h"
      38                 :            : #include "ip-protocol-list.h"
      39                 :            : #include "journal-util.h"
      40                 :            : #include "limits-util.h"
      41                 :            : #include "load-fragment.h"
      42                 :            : #include "log.h"
      43                 :            : #include "missing.h"
      44                 :            : #include "mountpoint-util.h"
      45                 :            : #include "nulstr-util.h"
      46                 :            : #include "parse-util.h"
      47                 :            : #include "path-util.h"
      48                 :            : #include "process-util.h"
      49                 :            : #if HAVE_SECCOMP
      50                 :            : #include "seccomp-util.h"
      51                 :            : #endif
      52                 :            : #include "securebits-util.h"
      53                 :            : #include "signal-util.h"
      54                 :            : #include "stat-util.h"
      55                 :            : #include "string-util.h"
      56                 :            : #include "strv.h"
      57                 :            : #include "unit-name.h"
      58                 :            : #include "unit-printf.h"
      59                 :            : #include "user-util.h"
      60                 :            : #include "time-util.h"
      61                 :            : #include "web-util.h"
      62                 :            : 
      63                 :          0 : static int parse_socket_protocol(const char *s) {
      64                 :            :         int r;
      65                 :            : 
      66                 :          0 :         r = parse_ip_protocol(s);
      67         [ #  # ]:          0 :         if (r < 0)
      68                 :          0 :                 return r;
      69   [ #  #  #  # ]:          0 :         if (!IN_SET(r, IPPROTO_UDPLITE, IPPROTO_SCTP))
      70                 :          0 :                 return -EPROTONOSUPPORT;
      71                 :            : 
      72                 :          0 :         return r;
      73                 :            : }
      74                 :            : 
      75                 :          0 : int parse_crash_chvt(const char *value, int *data) {
      76                 :            :         int b;
      77                 :            : 
      78         [ #  # ]:          0 :         if (safe_atoi(value, data) >= 0)
      79                 :          0 :                 return 0;
      80                 :            : 
      81                 :          0 :         b = parse_boolean(value);
      82         [ #  # ]:          0 :         if (b < 0)
      83                 :          0 :                 return b;
      84                 :            : 
      85         [ #  # ]:          0 :         if (b > 0)
      86                 :          0 :                 *data = 0; /* switch to where kmsg goes */
      87                 :            :         else
      88                 :          0 :                 *data = -1; /* turn off switching */
      89                 :            : 
      90                 :          0 :         return 0;
      91                 :            : }
      92                 :            : 
      93                 :          0 : int parse_confirm_spawn(const char *value, char **console) {
      94                 :            :         char *s;
      95                 :            :         int r;
      96                 :            : 
      97         [ #  # ]:          0 :         r = value ? parse_boolean(value) : 1;
      98         [ #  # ]:          0 :         if (r == 0) {
      99                 :          0 :                 *console = NULL;
     100                 :          0 :                 return 0;
     101         [ #  # ]:          0 :         } else if (r > 0) /* on with default tty */
     102                 :          0 :                 s = strdup("/dev/console");
     103         [ #  # ]:          0 :         else if (is_path(value)) /* on with fully qualified path */
     104                 :          0 :                 s = strdup(value);
     105                 :            :         else /* on with only a tty file name, not a fully qualified path */
     106                 :          0 :                 s = path_join("/dev/", value);
     107         [ #  # ]:          0 :         if (!s)
     108                 :          0 :                 return -ENOMEM;
     109                 :            : 
     110                 :          0 :         *console = s;
     111                 :          0 :         return 0;
     112                 :            : }
     113                 :            : 
     114   [ #  #  #  #  :          0 : DEFINE_CONFIG_PARSE(config_parse_socket_protocol, parse_socket_protocol, "Failed to parse socket protocol");
          #  #  #  #  #  
                #  #  # ]
     115   [ #  #  #  #  :          0 : DEFINE_CONFIG_PARSE(config_parse_exec_secure_bits, secure_bits_from_string, "Failed to parse secure bits");
          #  #  #  #  #  
                #  #  # ]
     116   [ #  #  #  #  :          0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_collect_mode, collect_mode, CollectMode, "Failed to parse garbage collection mode");
          #  #  #  #  #  
                #  #  # ]
     117   [ #  #  #  #  :          0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGroupDevicePolicy, "Failed to parse device policy");
          #  #  #  #  #  
                #  #  # ]
     118   [ #  #  #  #  :          0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_keyring_mode, exec_keyring_mode, ExecKeyringMode, "Failed to parse keyring mode");
          #  #  #  #  #  
                #  #  # ]
     119   [ #  #  #  #  :          0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode, "Failed to parse utmp mode");
          #  #  #  #  #  
                #  #  # ]
     120   [ #  #  #  #  :          0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to parse job mode");
          #  #  #  #  #  
                #  #  # ]
     121   [ #  #  #  #  :          0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
          #  #  #  #  #  
                #  #  # ]
     122   [ #  #  #  #  :          0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
          #  #  #  #  #  
                #  #  # ]
     123   [ #  #  #  #  :          0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_home, protect_home, ProtectHome, "Failed to parse protect home value");
          #  #  #  #  #  
                #  #  # ]
     124   [ #  #  #  #  :          0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_system, protect_system, ProtectSystem, "Failed to parse protect system value");
          #  #  #  #  #  
                #  #  # ]
     125   [ #  #  #  #  :          0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_runtime_preserve_mode, exec_preserve_mode, ExecPreserveMode, "Failed to parse runtime directory preserve mode");
          #  #  #  #  #  
                #  #  # ]
     126   [ -  +  -  +  :         68 : DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type");
          -  +  -  +  -  
                +  #  # ]
     127   [ #  #  #  #  :          0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier");
          #  #  #  #  #  
                #  #  # ]
     128   [ #  #  #  #  :          0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_socket_bind, socket_address_bind_ipv6_only_or_bool, SocketAddressBindIPv6Only, "Failed to parse bind IPv6 only value");
          #  #  #  #  #  
                #  #  # ]
     129   [ #  #  #  #  :          0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_oom_policy, oom_policy, OOMPolicy, "Failed to parse OOM policy");
          #  #  #  #  #  
                #  #  # ]
     130   [ #  #  #  #  :          0 : DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_ip_tos, ip_tos, int, -1, "Failed to parse IP TOS value");
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     131   [ #  #  #  #  :          0 : DEFINE_CONFIG_PARSE_PTR(config_parse_blockio_weight, cg_blkio_weight_parse, uint64_t, "Invalid block IO weight");
          #  #  #  #  #  
                #  #  # ]
     132   [ -  +  -  +  :          8 : DEFINE_CONFIG_PARSE_PTR(config_parse_cg_weight, cg_weight_parse, uint64_t, "Invalid weight");
          -  +  -  +  -  
                +  #  # ]
     133   [ -  +  -  +  :          4 : DEFINE_CONFIG_PARSE_PTR(config_parse_cpu_shares, cg_cpu_shares_parse, uint64_t, "Invalid CPU shares");
          -  +  -  +  -  
                +  #  # ]
     134   [ #  #  #  #  :          0 : DEFINE_CONFIG_PARSE_PTR(config_parse_exec_mount_flags, mount_propagation_flags_from_string, unsigned long, "Failed to parse mount flag");
          #  #  #  #  #  
                #  #  # ]
     135   [ #  #  #  #  :          0 : DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_numa_policy, mpol, int, -1, "Invalid NUMA policy type");
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     136                 :            : 
     137                 :        396 : int config_parse_unit_deps(
     138                 :            :                 const char *unit,
     139                 :            :                 const char *filename,
     140                 :            :                 unsigned line,
     141                 :            :                 const char *section,
     142                 :            :                 unsigned section_line,
     143                 :            :                 const char *lvalue,
     144                 :            :                 int ltype,
     145                 :            :                 const char *rvalue,
     146                 :            :                 void *data,
     147                 :            :                 void *userdata) {
     148                 :            : 
     149                 :        396 :         UnitDependency d = ltype;
     150                 :        396 :         Unit *u = userdata;
     151                 :            :         const char *p;
     152                 :            : 
     153         [ -  + ]:        396 :         assert(filename);
     154         [ -  + ]:        396 :         assert(lvalue);
     155         [ -  + ]:        396 :         assert(rvalue);
     156                 :            : 
     157                 :        396 :         p = rvalue;
     158                 :        928 :         for (;;) {
     159   [ +  +  -  -  :       1720 :                 _cleanup_free_ char *word = NULL, *k = NULL;
             +  +  -  - ]
     160                 :            :                 int r;
     161                 :            : 
     162                 :       1324 :                 r = extract_first_word(&p, &word, NULL, EXTRACT_RETAIN_ESCAPE);
     163         [ +  + ]:       1324 :                 if (r == 0)
     164                 :        396 :                         break;
     165         [ -  + ]:        928 :                 if (r == -ENOMEM)
     166                 :          0 :                         return log_oom();
     167         [ -  + ]:        928 :                 if (r < 0) {
     168         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
     169                 :          0 :                         break;
     170                 :            :                 }
     171                 :            : 
     172                 :        928 :                 r = unit_name_printf(u, word, &k);
     173         [ -  + ]:        928 :                 if (r < 0) {
     174         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", word);
     175                 :          0 :                         continue;
     176                 :            :                 }
     177                 :            : 
     178                 :        928 :                 r = unit_add_dependency_by_name(u, d, k, true, UNIT_DEPENDENCY_FILE);
     179         [ -  + ]:        928 :                 if (r < 0)
     180         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k);
     181                 :            :         }
     182                 :            : 
     183                 :        396 :         return 0;
     184                 :            : }
     185                 :            : 
     186                 :          0 : int config_parse_obsolete_unit_deps(
     187                 :            :                 const char *unit,
     188                 :            :                 const char *filename,
     189                 :            :                 unsigned line,
     190                 :            :                 const char *section,
     191                 :            :                 unsigned section_line,
     192                 :            :                 const char *lvalue,
     193                 :            :                 int ltype,
     194                 :            :                 const char *rvalue,
     195                 :            :                 void *data,
     196                 :            :                 void *userdata) {
     197                 :            : 
     198         [ #  # ]:          0 :         log_syntax(unit, LOG_WARNING, filename, line, 0,
     199                 :            :                    "Unit dependency type %s= is obsolete, replacing by %s=, please update your unit file", lvalue, unit_dependency_to_string(ltype));
     200                 :            : 
     201                 :          0 :         return config_parse_unit_deps(unit, filename, line, section, section_line, lvalue, ltype, rvalue, data, userdata);
     202                 :            : }
     203                 :            : 
     204                 :        356 : int config_parse_unit_string_printf(
     205                 :            :                 const char *unit,
     206                 :            :                 const char *filename,
     207                 :            :                 unsigned line,
     208                 :            :                 const char *section,
     209                 :            :                 unsigned section_line,
     210                 :            :                 const char *lvalue,
     211                 :            :                 int ltype,
     212                 :            :                 const char *rvalue,
     213                 :            :                 void *data,
     214                 :            :                 void *userdata) {
     215                 :            : 
     216                 :        356 :         _cleanup_free_ char *k = NULL;
     217                 :        356 :         Unit *u = userdata;
     218                 :            :         int r;
     219                 :            : 
     220         [ -  + ]:        356 :         assert(filename);
     221         [ -  + ]:        356 :         assert(lvalue);
     222         [ -  + ]:        356 :         assert(rvalue);
     223         [ -  + ]:        356 :         assert(u);
     224                 :            : 
     225                 :        356 :         r = unit_full_printf(u, rvalue, &k);
     226         [ -  + ]:        356 :         if (r < 0) {
     227         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
     228                 :          0 :                 return 0;
     229                 :            :         }
     230                 :            : 
     231                 :        356 :         return config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata);
     232                 :            : }
     233                 :            : 
     234                 :        176 : int config_parse_unit_strv_printf(
     235                 :            :                 const char *unit,
     236                 :            :                 const char *filename,
     237                 :            :                 unsigned line,
     238                 :            :                 const char *section,
     239                 :            :                 unsigned section_line,
     240                 :            :                 const char *lvalue,
     241                 :            :                 int ltype,
     242                 :            :                 const char *rvalue,
     243                 :            :                 void *data,
     244                 :            :                 void *userdata) {
     245                 :            : 
     246                 :        176 :         Unit *u = userdata;
     247                 :        176 :         _cleanup_free_ char *k = NULL;
     248                 :            :         int r;
     249                 :            : 
     250         [ -  + ]:        176 :         assert(filename);
     251         [ -  + ]:        176 :         assert(lvalue);
     252         [ -  + ]:        176 :         assert(rvalue);
     253         [ -  + ]:        176 :         assert(u);
     254                 :            : 
     255                 :        176 :         r = unit_full_printf(u, rvalue, &k);
     256         [ -  + ]:        176 :         if (r < 0) {
     257         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
     258                 :          0 :                 return 0;
     259                 :            :         }
     260                 :            : 
     261                 :        176 :         return config_parse_strv(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata);
     262                 :            : }
     263                 :            : 
     264                 :          0 : int config_parse_unit_path_printf(
     265                 :            :                 const char *unit,
     266                 :            :                 const char *filename,
     267                 :            :                 unsigned line,
     268                 :            :                 const char *section,
     269                 :            :                 unsigned section_line,
     270                 :            :                 const char *lvalue,
     271                 :            :                 int ltype,
     272                 :            :                 const char *rvalue,
     273                 :            :                 void *data,
     274                 :            :                 void *userdata) {
     275                 :            : 
     276                 :          0 :         _cleanup_free_ char *k = NULL;
     277                 :          0 :         Unit *u = userdata;
     278                 :            :         int r;
     279                 :          0 :         bool fatal = ltype;
     280                 :            : 
     281         [ #  # ]:          0 :         assert(filename);
     282         [ #  # ]:          0 :         assert(lvalue);
     283         [ #  # ]:          0 :         assert(rvalue);
     284         [ #  # ]:          0 :         assert(u);
     285                 :            : 
     286                 :            :         /* Let's not bother with anything that is too long */
     287         [ #  # ]:          0 :         if (strlen(rvalue) >= PATH_MAX) {
     288   [ #  #  #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0,
     289                 :            :                            "%s value too long%s.",
     290                 :            :                            lvalue, fatal ? "" : ", ignoring");
     291         [ #  # ]:          0 :                 return fatal ? -ENAMETOOLONG : 0;
     292                 :            :         }
     293                 :            : 
     294                 :          0 :         r = unit_full_printf(u, rvalue, &k);
     295         [ #  # ]:          0 :         if (r < 0) {
     296   [ #  #  #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r,
     297                 :            :                            "Failed to resolve unit specifiers in '%s'%s: %m",
     298                 :            :                            rvalue, fatal ? "" : ", ignoring");
     299         [ #  # ]:          0 :                 return fatal ? -ENOEXEC : 0;
     300                 :            :         }
     301                 :            : 
     302                 :          0 :         return config_parse_path(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata);
     303                 :            : }
     304                 :            : 
     305                 :          0 : int config_parse_unit_path_strv_printf(
     306                 :            :                 const char *unit,
     307                 :            :                 const char *filename,
     308                 :            :                 unsigned line,
     309                 :            :                 const char *section,
     310                 :            :                 unsigned section_line,
     311                 :            :                 const char *lvalue,
     312                 :            :                 int ltype,
     313                 :            :                 const char *rvalue,
     314                 :            :                 void *data,
     315                 :            :                 void *userdata) {
     316                 :            : 
     317                 :          0 :         char ***x = data;
     318                 :          0 :         Unit *u = userdata;
     319                 :            :         int r;
     320                 :            :         const char *p;
     321                 :            : 
     322         [ #  # ]:          0 :         assert(filename);
     323         [ #  # ]:          0 :         assert(lvalue);
     324         [ #  # ]:          0 :         assert(rvalue);
     325         [ #  # ]:          0 :         assert(u);
     326                 :            : 
     327         [ #  # ]:          0 :         if (isempty(rvalue)) {
     328                 :          0 :                 *x = strv_free(*x);
     329                 :          0 :                 return 0;
     330                 :            :         }
     331                 :            : 
     332                 :          0 :         for (p = rvalue;;) {
     333   [ #  #  #  # ]:          0 :                 _cleanup_free_ char *word = NULL, *k = NULL;
     334                 :            : 
     335                 :          0 :                 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
     336         [ #  # ]:          0 :                 if (r == 0)
     337                 :          0 :                         return 0;
     338         [ #  # ]:          0 :                 if (r == -ENOMEM)
     339                 :          0 :                         return log_oom();
     340         [ #  # ]:          0 :                 if (r < 0) {
     341         [ #  # ]:          0 :                         log_syntax(unit, LOG_WARNING, filename, line, r,
     342                 :            :                                    "Invalid syntax, ignoring: %s", rvalue);
     343                 :          0 :                         return 0;
     344                 :            :                 }
     345                 :            : 
     346                 :          0 :                 r = unit_full_printf(u, word, &k);
     347         [ #  # ]:          0 :                 if (r < 0) {
     348         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
     349                 :            :                                    "Failed to resolve unit specifiers in '%s', ignoring: %m", word);
     350                 :          0 :                         return 0;
     351                 :            :                 }
     352                 :            : 
     353                 :          0 :                 r = path_simplify_and_warn(k, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
     354         [ #  # ]:          0 :                 if (r < 0)
     355                 :          0 :                         return 0;
     356                 :            : 
     357                 :          0 :                 r = strv_consume(x, TAKE_PTR(k));
     358         [ #  # ]:          0 :                 if (r < 0)
     359                 :          0 :                         return log_oom();
     360                 :            :         }
     361                 :            : }
     362                 :            : 
     363                 :          0 : static int patch_var_run(
     364                 :            :                 const char *unit,
     365                 :            :                 const char *filename,
     366                 :            :                 unsigned line,
     367                 :            :                 const char *lvalue,
     368                 :            :                 char **path) {
     369                 :            : 
     370                 :            :         const char *e;
     371                 :            :         char *z;
     372                 :            : 
     373                 :          0 :         e = path_startswith(*path, "/var/run/");
     374         [ #  # ]:          0 :         if (!e)
     375                 :          0 :                 return 0;
     376                 :            : 
     377                 :          0 :         z = path_join("/run/", e);
     378         [ #  # ]:          0 :         if (!z)
     379                 :          0 :                 return log_oom();
     380                 :            : 
     381         [ #  # ]:          0 :         log_syntax(unit, LOG_NOTICE, filename, line, 0,
     382                 :            :                    "%s= references a path below legacy directory /var/run/, updating %s → %s; "
     383                 :            :                    "please update the unit file accordingly.", lvalue, *path, z);
     384                 :            : 
     385                 :          0 :         free_and_replace(*path, z);
     386                 :            : 
     387                 :          0 :         return 1;
     388                 :            : }
     389                 :            : 
     390                 :          0 : int config_parse_socket_listen(
     391                 :            :                 const char *unit,
     392                 :            :                 const char *filename,
     393                 :            :                 unsigned line,
     394                 :            :                 const char *section,
     395                 :            :                 unsigned section_line,
     396                 :            :                 const char *lvalue,
     397                 :            :                 int ltype,
     398                 :            :                 const char *rvalue,
     399                 :            :                 void *data,
     400                 :            :                 void *userdata) {
     401                 :            : 
     402                 :          0 :         _cleanup_free_ SocketPort *p = NULL;
     403                 :            :         SocketPort *tail;
     404                 :            :         Socket *s;
     405                 :            :         int r;
     406                 :            : 
     407         [ #  # ]:          0 :         assert(filename);
     408         [ #  # ]:          0 :         assert(lvalue);
     409         [ #  # ]:          0 :         assert(rvalue);
     410         [ #  # ]:          0 :         assert(data);
     411                 :            : 
     412                 :          0 :         s = SOCKET(data);
     413                 :            : 
     414         [ #  # ]:          0 :         if (isempty(rvalue)) {
     415                 :            :                 /* An empty assignment removes all ports */
     416                 :          0 :                 socket_free_ports(s);
     417                 :          0 :                 return 0;
     418                 :            :         }
     419                 :            : 
     420                 :          0 :         p = new0(SocketPort, 1);
     421         [ #  # ]:          0 :         if (!p)
     422                 :          0 :                 return log_oom();
     423                 :            : 
     424         [ #  # ]:          0 :         if (ltype != SOCKET_SOCKET) {
     425         [ #  # ]:          0 :                 _cleanup_free_ char *k = NULL;
     426                 :            : 
     427         [ #  # ]:          0 :                 r = unit_full_printf(UNIT(s), rvalue, &k);
     428         [ #  # ]:          0 :                 if (r < 0) {
     429         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
     430                 :          0 :                         return 0;
     431                 :            :                 }
     432                 :            : 
     433                 :          0 :                 r = path_simplify_and_warn(k, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
     434         [ #  # ]:          0 :                 if (r < 0)
     435                 :          0 :                         return 0;
     436                 :            : 
     437         [ #  # ]:          0 :                 if (ltype == SOCKET_FIFO) {
     438                 :          0 :                         r = patch_var_run(unit, filename, line, lvalue, &k);
     439         [ #  # ]:          0 :                         if (r < 0)
     440                 :          0 :                                 return r;
     441                 :            :                 }
     442                 :            : 
     443                 :          0 :                 free_and_replace(p->path, k);
     444                 :          0 :                 p->type = ltype;
     445                 :            : 
     446         [ #  # ]:          0 :         } else if (streq(lvalue, "ListenNetlink")) {
     447         [ #  # ]:          0 :                 _cleanup_free_ char  *k = NULL;
     448                 :            : 
     449         [ #  # ]:          0 :                 r = unit_full_printf(UNIT(s), rvalue, &k);
     450         [ #  # ]:          0 :                 if (r < 0) {
     451         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
     452                 :          0 :                         return 0;
     453                 :            :                 }
     454                 :            : 
     455                 :          0 :                 r = socket_address_parse_netlink(&p->address, k);
     456         [ #  # ]:          0 :                 if (r < 0) {
     457         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address value in '%s', ignoring: %m", k);
     458                 :          0 :                         return 0;
     459                 :            :                 }
     460                 :            : 
     461                 :          0 :                 p->type = SOCKET_SOCKET;
     462                 :            : 
     463                 :            :         } else {
     464         [ #  # ]:          0 :                 _cleanup_free_ char *k = NULL;
     465                 :            : 
     466         [ #  # ]:          0 :                 r = unit_full_printf(UNIT(s), rvalue, &k);
     467         [ #  # ]:          0 :                 if (r < 0) {
     468         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
     469                 :          0 :                         return 0;
     470                 :            :                 }
     471                 :            : 
     472         [ #  # ]:          0 :                 if (k[0] == '/') { /* Only for AF_UNIX file system sockets… */
     473                 :          0 :                         r = patch_var_run(unit, filename, line, lvalue, &k);
     474         [ #  # ]:          0 :                         if (r < 0)
     475                 :          0 :                                 return r;
     476                 :            :                 }
     477                 :            : 
     478                 :          0 :                 r = socket_address_parse_and_warn(&p->address, k);
     479         [ #  # ]:          0 :                 if (r < 0) {
     480         [ #  # ]:          0 :                         if (r != -EAFNOSUPPORT)
     481         [ #  # ]:          0 :                                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address value in '%s', ignoring: %m", k);
     482                 :          0 :                         return 0;
     483                 :            :                 }
     484                 :            : 
     485         [ #  # ]:          0 :                 if (streq(lvalue, "ListenStream"))
     486                 :          0 :                         p->address.type = SOCK_STREAM;
     487         [ #  # ]:          0 :                 else if (streq(lvalue, "ListenDatagram"))
     488                 :          0 :                         p->address.type = SOCK_DGRAM;
     489                 :            :                 else {
     490         [ #  # ]:          0 :                         assert(streq(lvalue, "ListenSequentialPacket"));
     491                 :          0 :                         p->address.type = SOCK_SEQPACKET;
     492                 :            :                 }
     493                 :            : 
     494   [ #  #  #  # ]:          0 :                 if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) {
     495         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, 0, "Address family not supported, ignoring: %s", rvalue);
     496                 :          0 :                         return 0;
     497                 :            :                 }
     498                 :            : 
     499                 :          0 :                 p->type = SOCKET_SOCKET;
     500                 :            :         }
     501                 :            : 
     502                 :          0 :         p->fd = -1;
     503                 :          0 :         p->auxiliary_fds = NULL;
     504                 :          0 :         p->n_auxiliary_fds = 0;
     505                 :          0 :         p->socket = s;
     506                 :            : 
     507   [ #  #  #  # ]:          0 :         LIST_FIND_TAIL(port, s->ports, tail);
     508   [ #  #  #  #  :          0 :         LIST_INSERT_AFTER(port, s->ports, tail, p);
             #  #  #  # ]
     509                 :            : 
     510                 :          0 :         p = NULL;
     511                 :            : 
     512                 :          0 :         return 0;
     513                 :            : }
     514                 :            : 
     515                 :          0 : int config_parse_exec_nice(
     516                 :            :                 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                 :          0 :         ExecContext *c = data;
     528                 :            :         int priority, r;
     529                 :            : 
     530         [ #  # ]:          0 :         assert(filename);
     531         [ #  # ]:          0 :         assert(lvalue);
     532         [ #  # ]:          0 :         assert(rvalue);
     533         [ #  # ]:          0 :         assert(data);
     534                 :            : 
     535         [ #  # ]:          0 :         if (isempty(rvalue)) {
     536                 :          0 :                 c->nice_set = false;
     537                 :          0 :                 return 0;
     538                 :            :         }
     539                 :            : 
     540                 :          0 :         r = parse_nice(rvalue, &priority);
     541         [ #  # ]:          0 :         if (r < 0) {
     542         [ #  # ]:          0 :                 if (r == -ERANGE)
     543         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Nice priority out of range, ignoring: %s", rvalue);
     544                 :            :                 else
     545         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse nice priority '%s', ignoring: %m", rvalue);
     546                 :          0 :                 return 0;
     547                 :            :         }
     548                 :            : 
     549                 :          0 :         c->nice = priority;
     550                 :          0 :         c->nice_set = true;
     551                 :            : 
     552                 :          0 :         return 0;
     553                 :            : }
     554                 :            : 
     555                 :          0 : int config_parse_exec_oom_score_adjust(
     556                 :            :                 const char* unit,
     557                 :            :                 const char *filename,
     558                 :            :                 unsigned line,
     559                 :            :                 const char *section,
     560                 :            :                 unsigned section_line,
     561                 :            :                 const char *lvalue,
     562                 :            :                 int ltype,
     563                 :            :                 const char *rvalue,
     564                 :            :                 void *data,
     565                 :            :                 void *userdata) {
     566                 :            : 
     567                 :          0 :         ExecContext *c = data;
     568                 :            :         int oa, r;
     569                 :            : 
     570         [ #  # ]:          0 :         assert(filename);
     571         [ #  # ]:          0 :         assert(lvalue);
     572         [ #  # ]:          0 :         assert(rvalue);
     573         [ #  # ]:          0 :         assert(data);
     574                 :            : 
     575         [ #  # ]:          0 :         if (isempty(rvalue)) {
     576                 :          0 :                 c->oom_score_adjust_set = false;
     577                 :          0 :                 return 0;
     578                 :            :         }
     579                 :            : 
     580                 :          0 :         r = parse_oom_score_adjust(rvalue, &oa);
     581         [ #  # ]:          0 :         if (r < 0) {
     582         [ #  # ]:          0 :                 if (r == -ERANGE)
     583         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "OOM score adjust value out of range, ignoring: %s", rvalue);
     584                 :            :                 else
     585         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse the OOM score adjust value '%s', ignoring: %m", rvalue);
     586                 :          0 :                 return 0;
     587                 :            :         }
     588                 :            : 
     589                 :          0 :         c->oom_score_adjust = oa;
     590                 :          0 :         c->oom_score_adjust_set = true;
     591                 :            : 
     592                 :          0 :         return 0;
     593                 :            : }
     594                 :            : 
     595                 :        312 : int config_parse_exec(
     596                 :            :                 const char *unit,
     597                 :            :                 const char *filename,
     598                 :            :                 unsigned line,
     599                 :            :                 const char *section,
     600                 :            :                 unsigned section_line,
     601                 :            :                 const char *lvalue,
     602                 :            :                 int ltype,
     603                 :            :                 const char *rvalue,
     604                 :            :                 void *data,
     605                 :            :                 void *userdata) {
     606                 :            : 
     607                 :        312 :         ExecCommand **e = data;
     608                 :        312 :         Unit *u = userdata;
     609                 :            :         const char *p;
     610                 :            :         bool semicolon;
     611                 :            :         int r;
     612                 :            : 
     613         [ -  + ]:        312 :         assert(filename);
     614         [ -  + ]:        312 :         assert(lvalue);
     615         [ -  + ]:        312 :         assert(rvalue);
     616         [ -  + ]:        312 :         assert(e);
     617                 :            : 
     618                 :        312 :         e += ltype;
     619                 :        312 :         rvalue += strspn(rvalue, WHITESPACE);
     620                 :            : 
     621         [ +  + ]:        312 :         if (isempty(rvalue)) {
     622                 :            :                 /* An empty assignment resets the list */
     623                 :          8 :                 *e = exec_command_free_list(*e);
     624                 :          8 :                 return 0;
     625                 :            :         }
     626                 :            : 
     627                 :        304 :         p = rvalue;
     628                 :            :         do {
     629   [ +  +  +  + ]:        412 :                 _cleanup_free_ char *path = NULL, *firstword = NULL;
     630                 :        320 :                 ExecCommandFlags flags = 0;
     631                 :        320 :                 bool ignore = false, separate_argv0 = false;
     632         [ +  + ]:        320 :                 _cleanup_free_ ExecCommand *nce = NULL;
     633         [ +  + ]:        320 :                 _cleanup_strv_free_ char **n = NULL;
     634                 :        320 :                 size_t nlen = 0, nbufsize = 0;
     635                 :            :                 const char *f;
     636                 :            : 
     637                 :        320 :                 semicolon = false;
     638                 :            : 
     639                 :        320 :                 r = extract_first_word_and_warn(&p, &firstword, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE, unit, filename, line, rvalue);
     640         [ +  + ]:        320 :                 if (r <= 0)
     641                 :          8 :                         return 0;
     642                 :            : 
     643                 :        312 :                 f = firstword;
     644                 :            :                 for (;;) {
     645                 :            :                         /* We accept an absolute path as first argument.  If it's prefixed with - and the path doesn't
     646                 :            :                          * exist, we ignore it instead of erroring out; if it's prefixed with @, we allow overriding of
     647                 :            :                          * argv[0]; if it's prefixed with :, we will not do environment variable substitution;
     648                 :            :                          * if it's prefixed with +, it will be run with full privileges and no sandboxing; if
     649                 :            :                          * it's prefixed with '!' we apply sandboxing, but do not change user/group credentials; if
     650                 :            :                          * it's prefixed with '!!', then we apply user/group credentials if the kernel supports ambient
     651                 :            :                          * capabilities -- if it doesn't we don't apply the credentials themselves, but do apply most
     652                 :            :                          * other sandboxing, with some special exceptions for changing UID.
     653                 :            :                          *
     654                 :            :                          * The idea is that '!!' may be used to write services that can take benefit of systemd's
     655                 :            :                          * UID/GID dropping if the kernel supports ambient creds, but provide an automatic fallback to
     656                 :            :                          * privilege dropping within the daemon if the kernel does not offer that. */
     657                 :            : 
     658   [ +  +  +  + ]:        396 :                         if (*f == '-' && !(flags & EXEC_COMMAND_IGNORE_FAILURE)) {
     659                 :         44 :                                 flags |= EXEC_COMMAND_IGNORE_FAILURE;
     660                 :         44 :                                 ignore = true;
     661   [ +  +  +  - ]:        352 :                         } else if (*f == '@' && !separate_argv0)
     662                 :         40 :                                 separate_argv0 = true;
     663   [ -  +  #  # ]:        312 :                         else if (*f == ':' && !(flags & EXEC_COMMAND_NO_ENV_EXPAND))
     664                 :          0 :                                 flags |= EXEC_COMMAND_NO_ENV_EXPAND;
     665   [ -  +  #  # ]:        312 :                         else if (*f == '+' && !(flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID|EXEC_COMMAND_AMBIENT_MAGIC)))
     666                 :          0 :                                 flags |= EXEC_COMMAND_FULLY_PRIVILEGED;
     667   [ -  +  #  # ]:        312 :                         else if (*f == '!' && !(flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID|EXEC_COMMAND_AMBIENT_MAGIC)))
     668                 :          0 :                                 flags |= EXEC_COMMAND_NO_SETUID;
     669   [ -  +  #  # ]:        312 :                         else if (*f == '!' && !(flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_AMBIENT_MAGIC))) {
     670                 :          0 :                                 flags &= ~EXEC_COMMAND_NO_SETUID;
     671                 :          0 :                                 flags |= EXEC_COMMAND_AMBIENT_MAGIC;
     672                 :            :                         } else
     673                 :            :                                 break;
     674                 :         84 :                         f++;
     675                 :            :                 }
     676                 :            : 
     677                 :        312 :                 r = unit_full_printf(u, f, &path);
     678         [ -  + ]:        312 :                 if (r < 0) {
     679   [ #  #  #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
     680                 :            :                                    "Failed to resolve unit specifiers in '%s'%s: %m",
     681                 :            :                                    f, ignore ? ", ignoring" : "");
     682         [ #  # ]:          0 :                         return ignore ? 0 : -ENOEXEC;
     683                 :            :                 }
     684                 :            : 
     685         [ +  + ]:        312 :                 if (isempty(path)) {
     686                 :            :                         /* First word is either "-" or "@" with no command. */
     687   [ +  -  +  - ]:          8 :                         log_syntax(unit, LOG_ERR, filename, line, 0,
     688                 :            :                                    "Empty path in command line%s: '%s'",
     689                 :            :                                    ignore ? ", ignoring" : "", rvalue);
     690         [ +  - ]:          8 :                         return ignore ? 0 : -ENOEXEC;
     691                 :            :                 }
     692         [ +  + ]:        304 :                 if (!string_is_safe(path)) {
     693   [ +  -  -  + ]:         48 :                         log_syntax(unit, LOG_ERR, filename, line, 0,
     694                 :            :                                    "Executable name contains special characters%s: %s",
     695                 :            :                                    ignore ? ", ignoring" : "", path);
     696         [ -  + ]:         48 :                         return ignore ? 0 : -ENOEXEC;
     697                 :            :                 }
     698         [ +  + ]:        256 :                 if (endswith(path, "/")) {
     699   [ +  -  -  + ]:          4 :                         log_syntax(unit, LOG_ERR, filename, line, 0,
     700                 :            :                                    "Executable path specifies a directory%s: %s",
     701                 :            :                                    ignore ? ", ignoring" : "", path);
     702         [ -  + ]:          4 :                         return ignore ? 0 : -ENOEXEC;
     703                 :            :                 }
     704                 :            : 
     705         [ +  + ]:        252 :                 if (!path_is_absolute(path)) {
     706                 :            :                         const char *prefix;
     707                 :         12 :                         bool found = false;
     708                 :            : 
     709         [ +  + ]:         12 :                         if (!filename_is_valid(path)) {
     710   [ +  -  +  - ]:          8 :                                 log_syntax(unit, LOG_ERR, filename, line, 0,
     711                 :            :                                            "Neither a valid executable name nor an absolute path%s: %s",
     712                 :            :                                            ignore ? ", ignoring" : "", path);
     713         [ +  - ]:          8 :                                 return ignore ? 0 : -ENOEXEC;
     714                 :            :                         }
     715                 :            : 
     716                 :            :                         /* Resolve a single-component name to a full path */
     717   [ +  -  +  + ]:         20 :                         NULSTR_FOREACH(prefix, DEFAULT_PATH_NULSTR) {
     718      [ +  -  - ]:         16 :                                 _cleanup_free_ char *fullpath = NULL;
     719                 :            : 
     720                 :         16 :                                 fullpath = path_join(prefix, path);
     721         [ -  + ]:         16 :                                 if (!fullpath)
     722                 :          0 :                                         return log_oom();
     723                 :            : 
     724         [ -  + ]:         16 :                                 if (access(fullpath, F_OK) >= 0) {
     725                 :          0 :                                         free_and_replace(path, fullpath);
     726                 :          0 :                                         found = true;
     727                 :          0 :                                         break;
     728                 :            :                                 }
     729                 :            :                         }
     730                 :            : 
     731         [ +  - ]:          4 :                         if (!found) {
     732   [ +  -  -  + ]:          4 :                                 log_syntax(unit, LOG_ERR, filename, line, 0,
     733                 :            :                                            "Executable \"%s\" not found in path \"%s\"%s",
     734                 :            :                                            path, DEFAULT_PATH, ignore ? ", ignoring" : "");
     735         [ -  + ]:          4 :                                 return ignore ? 0 : -ENOEXEC;
     736                 :            :                         }
     737                 :            :                 }
     738                 :            : 
     739         [ +  + ]:        240 :                 if (!separate_argv0) {
     740                 :        204 :                         char *w = NULL;
     741                 :            : 
     742         [ -  + ]:        204 :                         if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
     743                 :          0 :                                 return log_oom();
     744                 :            : 
     745                 :        204 :                         w = strdup(path);
     746         [ -  + ]:        204 :                         if (!w)
     747                 :          0 :                                 return log_oom();
     748                 :        204 :                         n[nlen++] = w;
     749                 :        204 :                         n[nlen] = NULL;
     750                 :            :                 }
     751                 :            : 
     752                 :        240 :                 path_simplify(path, false);
     753                 :            : 
     754         [ +  + ]:        380 :                 while (!isempty(p)) {
     755   [ +  +  +  +  :        196 :                         _cleanup_free_ char *word = NULL, *resolved = NULL;
             +  +  +  + ]
     756                 :            : 
     757                 :            :                         /* Check explicitly for an unquoted semicolon as
     758                 :            :                          * command separator token.  */
     759   [ +  +  +  +  :        164 :                         if (p[0] == ';' && (!p[1] || strchr(WHITESPACE, p[1]))) {
                   +  - ]
     760                 :         16 :                                 p++;
     761                 :         16 :                                 p += strspn(p, WHITESPACE);
     762                 :         16 :                                 semicolon = true;
     763                 :         16 :                                 break;
     764                 :            :                         }
     765                 :            : 
     766                 :            :                         /* Check for \; explicitly, to not confuse it with \\; or "\;" or "\\;" etc.
     767                 :            :                          * extract_first_word() would return the same for all of those.  */
     768   [ +  +  +  +  :        148 :                         if (p[0] == '\\' && p[1] == ';' && (!p[2] || strchr(WHITESPACE, p[2]))) {
             +  +  +  + ]
     769                 :            :                                 char *w;
     770                 :            : 
     771                 :          8 :                                 p += 2;
     772                 :          8 :                                 p += strspn(p, WHITESPACE);
     773                 :            : 
     774         [ -  + ]:          8 :                                 if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
     775                 :          0 :                                         return log_oom();
     776                 :            : 
     777                 :          8 :                                 w = strdup(";");
     778         [ -  + ]:          8 :                                 if (!w)
     779                 :          0 :                                         return log_oom();
     780                 :          8 :                                 n[nlen++] = w;
     781                 :          8 :                                 n[nlen] = NULL;
     782                 :          8 :                                 continue;
     783                 :            :                         }
     784                 :            : 
     785                 :        140 :                         r = extract_first_word_and_warn(&p, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE, unit, filename, line, rvalue);
     786         [ -  + ]:        140 :                         if (r == 0)
     787                 :          0 :                                 break;
     788         [ +  + ]:        140 :                         if (r < 0)
     789         [ -  + ]:          8 :                                 return ignore ? 0 : -ENOEXEC;
     790                 :            : 
     791                 :        132 :                         r = unit_full_printf(u, word, &resolved);
     792         [ -  + ]:        132 :                         if (r < 0) {
     793   [ #  #  #  # ]:          0 :                                 log_syntax(unit, LOG_ERR, filename, line, r,
     794                 :            :                                            "Failed to resolve unit specifiers in %s%s: %m",
     795                 :            :                                            word, ignore ? ", ignoring" : "");
     796         [ #  # ]:          0 :                                 return ignore ? 0 : -ENOEXEC;
     797                 :            :                         }
     798                 :            : 
     799         [ -  + ]:        132 :                         if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
     800                 :          0 :                                 return log_oom();
     801                 :            : 
     802                 :        132 :                         n[nlen++] = TAKE_PTR(resolved);
     803                 :        132 :                         n[nlen] = NULL;
     804                 :            :                 }
     805                 :            : 
     806   [ +  +  -  + ]:        232 :                 if (!n || !n[0]) {
     807   [ +  -  -  + ]:          4 :                         log_syntax(unit, LOG_ERR, filename, line, 0,
     808                 :            :                                    "Empty executable name or zeroeth argument%s: %s",
     809                 :            :                                    ignore ? ", ignoring" : "", rvalue);
     810         [ -  + ]:          4 :                         return ignore ? 0 : -ENOEXEC;
     811                 :            :                 }
     812                 :            : 
     813                 :        228 :                 nce = new0(ExecCommand, 1);
     814         [ -  + ]:        228 :                 if (!nce)
     815                 :          0 :                         return log_oom();
     816                 :            : 
     817                 :        228 :                 nce->argv = TAKE_PTR(n);
     818                 :        228 :                 nce->path = TAKE_PTR(path);
     819                 :        228 :                 nce->flags = flags;
     820                 :            : 
     821                 :        228 :                 exec_command_append_list(e, nce);
     822                 :            : 
     823                 :            :                 /* Do not _cleanup_free_ these. */
     824                 :        228 :                 nce = NULL;
     825                 :            : 
     826                 :        228 :                 rvalue = p;
     827         [ +  + ]:        228 :         } while (semicolon);
     828                 :            : 
     829                 :        212 :         return 0;
     830                 :            : }
     831                 :            : 
     832                 :          0 : int config_parse_socket_bindtodevice(
     833                 :            :                 const char* unit,
     834                 :            :                 const char *filename,
     835                 :            :                 unsigned line,
     836                 :            :                 const char *section,
     837                 :            :                 unsigned section_line,
     838                 :            :                 const char *lvalue,
     839                 :            :                 int ltype,
     840                 :            :                 const char *rvalue,
     841                 :            :                 void *data,
     842                 :            :                 void *userdata) {
     843                 :            : 
     844                 :          0 :         Socket *s = data;
     845                 :            : 
     846         [ #  # ]:          0 :         assert(filename);
     847         [ #  # ]:          0 :         assert(lvalue);
     848         [ #  # ]:          0 :         assert(rvalue);
     849         [ #  # ]:          0 :         assert(data);
     850                 :            : 
     851   [ #  #  #  # ]:          0 :         if (isempty(rvalue) || streq(rvalue, "*")) {
     852                 :          0 :                 s->bind_to_device = mfree(s->bind_to_device);
     853                 :          0 :                 return 0;
     854                 :            :         }
     855                 :            : 
     856         [ #  # ]:          0 :         if (!ifname_valid(rvalue)) {
     857         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid interface name, ignoring: %s", rvalue);
     858                 :          0 :                 return 0;
     859                 :            :         }
     860                 :            : 
     861         [ #  # ]:          0 :         if (free_and_strdup(&s->bind_to_device, rvalue) < 0)
     862                 :          0 :                 return log_oom();
     863                 :            : 
     864                 :          0 :         return 0;
     865                 :            : }
     866                 :            : 
     867                 :          0 : int config_parse_exec_input(
     868                 :            :                 const char *unit,
     869                 :            :                 const char *filename,
     870                 :            :                 unsigned line,
     871                 :            :                 const char *section,
     872                 :            :                 unsigned section_line,
     873                 :            :                 const char *lvalue,
     874                 :            :                 int ltype,
     875                 :            :                 const char *rvalue,
     876                 :            :                 void *data,
     877                 :            :                 void *userdata) {
     878                 :            : 
     879                 :          0 :         ExecContext *c = data;
     880                 :          0 :         Unit *u = userdata;
     881                 :            :         const char *n;
     882                 :            :         ExecInput ei;
     883                 :            :         int r;
     884                 :            : 
     885         [ #  # ]:          0 :         assert(data);
     886         [ #  # ]:          0 :         assert(filename);
     887         [ #  # ]:          0 :         assert(line);
     888         [ #  # ]:          0 :         assert(rvalue);
     889                 :            : 
     890                 :          0 :         n = startswith(rvalue, "fd:");
     891         [ #  # ]:          0 :         if (n) {
     892         [ #  # ]:          0 :                 _cleanup_free_ char *resolved = NULL;
     893                 :            : 
     894                 :          0 :                 r = unit_full_printf(u, n, &resolved);
     895         [ #  # ]:          0 :                 if (r < 0)
     896         [ #  # ]:          0 :                         return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s': %m", n);
     897                 :            : 
     898         [ #  # ]:          0 :                 if (isempty(resolved))
     899                 :          0 :                         resolved = mfree(resolved);
     900         [ #  # ]:          0 :                 else if (!fdname_is_valid(resolved)) {
     901         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid file descriptor name: %s", resolved);
     902                 :          0 :                         return -ENOEXEC;
     903                 :            :                 }
     904                 :            : 
     905                 :          0 :                 free_and_replace(c->stdio_fdname[STDIN_FILENO], resolved);
     906                 :            : 
     907                 :          0 :                 ei = EXEC_INPUT_NAMED_FD;
     908                 :            : 
     909         [ #  # ]:          0 :         } else if ((n = startswith(rvalue, "file:"))) {
     910         [ #  # ]:          0 :                 _cleanup_free_ char *resolved = NULL;
     911                 :            : 
     912                 :          0 :                 r = unit_full_printf(u, n, &resolved);
     913         [ #  # ]:          0 :                 if (r < 0)
     914         [ #  # ]:          0 :                         return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s': %m", n);
     915                 :            : 
     916                 :          0 :                 r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE | PATH_CHECK_FATAL, unit, filename, line, lvalue);
     917         [ #  # ]:          0 :                 if (r < 0)
     918                 :          0 :                         return -ENOEXEC;
     919                 :            : 
     920                 :          0 :                 free_and_replace(c->stdio_file[STDIN_FILENO], resolved);
     921                 :            : 
     922                 :          0 :                 ei = EXEC_INPUT_FILE;
     923                 :            : 
     924                 :            :         } else {
     925                 :          0 :                 ei = exec_input_from_string(rvalue);
     926         [ #  # ]:          0 :                 if (ei < 0) {
     927         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse input specifier, ignoring: %s", rvalue);
     928                 :          0 :                         return 0;
     929                 :            :                 }
     930                 :            :         }
     931                 :            : 
     932                 :          0 :         c->std_input = ei;
     933                 :          0 :         return 0;
     934                 :            : }
     935                 :            : 
     936                 :          0 : int config_parse_exec_input_text(
     937                 :            :                 const char *unit,
     938                 :            :                 const char *filename,
     939                 :            :                 unsigned line,
     940                 :            :                 const char *section,
     941                 :            :                 unsigned section_line,
     942                 :            :                 const char *lvalue,
     943                 :            :                 int ltype,
     944                 :            :                 const char *rvalue,
     945                 :            :                 void *data,
     946                 :            :                 void *userdata) {
     947                 :            : 
     948                 :          0 :         _cleanup_free_ char *unescaped = NULL, *resolved = NULL;
     949                 :          0 :         ExecContext *c = data;
     950                 :          0 :         Unit *u = userdata;
     951                 :            :         size_t sz;
     952                 :            :         void *p;
     953                 :            :         int r;
     954                 :            : 
     955         [ #  # ]:          0 :         assert(data);
     956         [ #  # ]:          0 :         assert(filename);
     957         [ #  # ]:          0 :         assert(line);
     958         [ #  # ]:          0 :         assert(rvalue);
     959                 :            : 
     960         [ #  # ]:          0 :         if (isempty(rvalue)) {
     961                 :            :                 /* Reset if the empty string is assigned */
     962                 :          0 :                 c->stdin_data = mfree(c->stdin_data);
     963                 :          0 :                 c->stdin_data_size = 0;
     964                 :          0 :                 return 0;
     965                 :            :         }
     966                 :            : 
     967                 :          0 :         r = cunescape(rvalue, 0, &unescaped);
     968         [ #  # ]:          0 :         if (r < 0)
     969         [ #  # ]:          0 :                 return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to decode C escaped text '%s': %m", rvalue);
     970                 :            : 
     971                 :          0 :         r = unit_full_printf(u, unescaped, &resolved);
     972         [ #  # ]:          0 :         if (r < 0)
     973         [ #  # ]:          0 :                 return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s': %m", unescaped);
     974                 :            : 
     975                 :          0 :         sz = strlen(resolved);
     976         [ #  # ]:          0 :         if (c->stdin_data_size + sz + 1 < c->stdin_data_size || /* check for overflow */
     977         [ #  # ]:          0 :             c->stdin_data_size + sz + 1 > EXEC_STDIN_DATA_MAX) {
     978         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Standard input data too large (%zu), maximum of %zu permitted, ignoring.", c->stdin_data_size + sz, (size_t) EXEC_STDIN_DATA_MAX);
     979                 :          0 :                 return -E2BIG;
     980                 :            :         }
     981                 :            : 
     982                 :          0 :         p = realloc(c->stdin_data, c->stdin_data_size + sz + 1);
     983         [ #  # ]:          0 :         if (!p)
     984                 :          0 :                 return log_oom();
     985                 :            : 
     986                 :          0 :         *((char*) mempcpy((char*) p + c->stdin_data_size, resolved, sz)) = '\n';
     987                 :            : 
     988                 :          0 :         c->stdin_data = p;
     989                 :          0 :         c->stdin_data_size += sz + 1;
     990                 :            : 
     991                 :          0 :         return 0;
     992                 :            : }
     993                 :            : 
     994                 :          0 : int config_parse_exec_input_data(
     995                 :            :                 const char *unit,
     996                 :            :                 const char *filename,
     997                 :            :                 unsigned line,
     998                 :            :                 const char *section,
     999                 :            :                 unsigned section_line,
    1000                 :            :                 const char *lvalue,
    1001                 :            :                 int ltype,
    1002                 :            :                 const char *rvalue,
    1003                 :            :                 void *data,
    1004                 :            :                 void *userdata) {
    1005                 :            : 
    1006                 :          0 :         _cleanup_free_ void *p = NULL;
    1007                 :          0 :         ExecContext *c = data;
    1008                 :            :         size_t sz;
    1009                 :            :         void *q;
    1010                 :            :         int r;
    1011                 :            : 
    1012         [ #  # ]:          0 :         assert(data);
    1013         [ #  # ]:          0 :         assert(filename);
    1014         [ #  # ]:          0 :         assert(line);
    1015         [ #  # ]:          0 :         assert(rvalue);
    1016                 :            : 
    1017         [ #  # ]:          0 :         if (isempty(rvalue)) {
    1018                 :            :                 /* Reset if the empty string is assigned */
    1019                 :          0 :                 c->stdin_data = mfree(c->stdin_data);
    1020                 :          0 :                 c->stdin_data_size = 0;
    1021                 :          0 :                 return 0;
    1022                 :            :         }
    1023                 :            : 
    1024                 :          0 :         r = unbase64mem(rvalue, (size_t) -1, &p, &sz);
    1025         [ #  # ]:          0 :         if (r < 0)
    1026         [ #  # ]:          0 :                 return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to decode base64 data, ignoring: %s", rvalue);
    1027                 :            : 
    1028         [ #  # ]:          0 :         assert(sz > 0);
    1029                 :            : 
    1030         [ #  # ]:          0 :         if (c->stdin_data_size + sz < c->stdin_data_size || /* check for overflow */
    1031         [ #  # ]:          0 :             c->stdin_data_size + sz > EXEC_STDIN_DATA_MAX) {
    1032         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Standard input data too large (%zu), maximum of %zu permitted, ignoring.", c->stdin_data_size + sz, (size_t) EXEC_STDIN_DATA_MAX);
    1033                 :          0 :                 return -E2BIG;
    1034                 :            :         }
    1035                 :            : 
    1036                 :          0 :         q = realloc(c->stdin_data, c->stdin_data_size + sz);
    1037         [ #  # ]:          0 :         if (!q)
    1038                 :          0 :                 return log_oom();
    1039                 :            : 
    1040                 :          0 :         memcpy((uint8_t*) q + c->stdin_data_size, p, sz);
    1041                 :            : 
    1042                 :          0 :         c->stdin_data = q;
    1043                 :          0 :         c->stdin_data_size += sz;
    1044                 :            : 
    1045                 :          0 :         return 0;
    1046                 :            : }
    1047                 :            : 
    1048                 :          0 : int config_parse_exec_output(
    1049                 :            :                 const char *unit,
    1050                 :            :                 const char *filename,
    1051                 :            :                 unsigned line,
    1052                 :            :                 const char *section,
    1053                 :            :                 unsigned section_line,
    1054                 :            :                 const char *lvalue,
    1055                 :            :                 int ltype,
    1056                 :            :                 const char *rvalue,
    1057                 :            :                 void *data,
    1058                 :            :                 void *userdata) {
    1059                 :            : 
    1060                 :          0 :         _cleanup_free_ char *resolved = NULL;
    1061                 :            :         const char *n;
    1062                 :          0 :         ExecContext *c = data;
    1063                 :          0 :         Unit *u = userdata;
    1064                 :            :         ExecOutput eo;
    1065                 :            :         int r;
    1066                 :            : 
    1067         [ #  # ]:          0 :         assert(data);
    1068         [ #  # ]:          0 :         assert(filename);
    1069         [ #  # ]:          0 :         assert(line);
    1070         [ #  # ]:          0 :         assert(lvalue);
    1071         [ #  # ]:          0 :         assert(rvalue);
    1072                 :            : 
    1073                 :          0 :         n = startswith(rvalue, "fd:");
    1074         [ #  # ]:          0 :         if (n) {
    1075                 :          0 :                 r = unit_full_printf(u, n, &resolved);
    1076         [ #  # ]:          0 :                 if (r < 0)
    1077         [ #  # ]:          0 :                         return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", n);
    1078                 :            : 
    1079         [ #  # ]:          0 :                 if (isempty(resolved))
    1080                 :          0 :                         resolved = mfree(resolved);
    1081         [ #  # ]:          0 :                 else if (!fdname_is_valid(resolved)) {
    1082         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid file descriptor name: %s", resolved);
    1083                 :          0 :                         return -ENOEXEC;
    1084                 :            :                 }
    1085                 :            : 
    1086                 :          0 :                 eo = EXEC_OUTPUT_NAMED_FD;
    1087                 :            : 
    1088         [ #  # ]:          0 :         } else if ((n = startswith(rvalue, "file:"))) {
    1089                 :            : 
    1090                 :          0 :                 r = unit_full_printf(u, n, &resolved);
    1091         [ #  # ]:          0 :                 if (r < 0)
    1092         [ #  # ]:          0 :                         return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", n);
    1093                 :            : 
    1094                 :          0 :                 r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE | PATH_CHECK_FATAL, unit, filename, line, lvalue);
    1095         [ #  # ]:          0 :                 if (r < 0)
    1096                 :          0 :                         return -ENOEXEC;
    1097                 :            : 
    1098                 :          0 :                 eo = EXEC_OUTPUT_FILE;
    1099                 :            : 
    1100         [ #  # ]:          0 :         } else if ((n = startswith(rvalue, "append:"))) {
    1101                 :            : 
    1102                 :          0 :                 r = unit_full_printf(u, n, &resolved);
    1103         [ #  # ]:          0 :                 if (r < 0)
    1104         [ #  # ]:          0 :                         return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", n);
    1105                 :            : 
    1106                 :          0 :                 r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE | PATH_CHECK_FATAL, unit, filename, line, lvalue);
    1107         [ #  # ]:          0 :                 if (r < 0)
    1108                 :          0 :                         return -ENOEXEC;
    1109                 :            : 
    1110                 :          0 :                 eo = EXEC_OUTPUT_FILE_APPEND;
    1111                 :            :         } else {
    1112                 :          0 :                 eo = exec_output_from_string(rvalue);
    1113         [ #  # ]:          0 :                 if (eo < 0) {
    1114         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse output specifier, ignoring: %s", rvalue);
    1115                 :          0 :                         return 0;
    1116                 :            :                 }
    1117                 :            :         }
    1118                 :            : 
    1119         [ #  # ]:          0 :         if (streq(lvalue, "StandardOutput")) {
    1120         [ #  # ]:          0 :                 if (eo == EXEC_OUTPUT_NAMED_FD)
    1121                 :          0 :                         free_and_replace(c->stdio_fdname[STDOUT_FILENO], resolved);
    1122                 :            :                 else
    1123                 :          0 :                         free_and_replace(c->stdio_file[STDOUT_FILENO], resolved);
    1124                 :            : 
    1125                 :          0 :                 c->std_output = eo;
    1126                 :            : 
    1127                 :            :         } else {
    1128         [ #  # ]:          0 :                 assert(streq(lvalue, "StandardError"));
    1129                 :            : 
    1130         [ #  # ]:          0 :                 if (eo == EXEC_OUTPUT_NAMED_FD)
    1131                 :          0 :                         free_and_replace(c->stdio_fdname[STDERR_FILENO], resolved);
    1132                 :            :                 else
    1133                 :          0 :                         free_and_replace(c->stdio_file[STDERR_FILENO], resolved);
    1134                 :            : 
    1135                 :          0 :                 c->std_error = eo;
    1136                 :            :         }
    1137                 :            : 
    1138                 :          0 :         return 0;
    1139                 :            : }
    1140                 :            : 
    1141                 :          0 : int config_parse_exec_io_class(const char *unit,
    1142                 :            :                                const char *filename,
    1143                 :            :                                unsigned line,
    1144                 :            :                                const char *section,
    1145                 :            :                                unsigned section_line,
    1146                 :            :                                const char *lvalue,
    1147                 :            :                                int ltype,
    1148                 :            :                                const char *rvalue,
    1149                 :            :                                void *data,
    1150                 :            :                                void *userdata) {
    1151                 :            : 
    1152                 :          0 :         ExecContext *c = data;
    1153                 :            :         int x;
    1154                 :            : 
    1155         [ #  # ]:          0 :         assert(filename);
    1156         [ #  # ]:          0 :         assert(lvalue);
    1157         [ #  # ]:          0 :         assert(rvalue);
    1158         [ #  # ]:          0 :         assert(data);
    1159                 :            : 
    1160         [ #  # ]:          0 :         if (isempty(rvalue)) {
    1161                 :          0 :                 c->ioprio_set = false;
    1162                 :          0 :                 c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0);
    1163                 :          0 :                 return 0;
    1164                 :            :         }
    1165                 :            : 
    1166                 :          0 :         x = ioprio_class_from_string(rvalue);
    1167         [ #  # ]:          0 :         if (x < 0) {
    1168         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IO scheduling class, ignoring: %s", rvalue);
    1169                 :          0 :                 return 0;
    1170                 :            :         }
    1171                 :            : 
    1172                 :          0 :         c->ioprio = IOPRIO_PRIO_VALUE(x, IOPRIO_PRIO_DATA(c->ioprio));
    1173                 :          0 :         c->ioprio_set = true;
    1174                 :            : 
    1175                 :          0 :         return 0;
    1176                 :            : }
    1177                 :            : 
    1178                 :          0 : int config_parse_exec_io_priority(const char *unit,
    1179                 :            :                                   const char *filename,
    1180                 :            :                                   unsigned line,
    1181                 :            :                                   const char *section,
    1182                 :            :                                   unsigned section_line,
    1183                 :            :                                   const char *lvalue,
    1184                 :            :                                   int ltype,
    1185                 :            :                                   const char *rvalue,
    1186                 :            :                                   void *data,
    1187                 :            :                                   void *userdata) {
    1188                 :            : 
    1189                 :          0 :         ExecContext *c = data;
    1190                 :            :         int i, r;
    1191                 :            : 
    1192         [ #  # ]:          0 :         assert(filename);
    1193         [ #  # ]:          0 :         assert(lvalue);
    1194         [ #  # ]:          0 :         assert(rvalue);
    1195         [ #  # ]:          0 :         assert(data);
    1196                 :            : 
    1197         [ #  # ]:          0 :         if (isempty(rvalue)) {
    1198                 :          0 :                 c->ioprio_set = false;
    1199                 :          0 :                 c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0);
    1200                 :          0 :                 return 0;
    1201                 :            :         }
    1202                 :            : 
    1203                 :          0 :         r = ioprio_parse_priority(rvalue, &i);
    1204         [ #  # ]:          0 :         if (r < 0) {
    1205         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse IO priority, ignoring: %s", rvalue);
    1206                 :          0 :                 return 0;
    1207                 :            :         }
    1208                 :            : 
    1209                 :          0 :         c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), i);
    1210                 :          0 :         c->ioprio_set = true;
    1211                 :            : 
    1212                 :          0 :         return 0;
    1213                 :            : }
    1214                 :            : 
    1215                 :         12 : int config_parse_exec_cpu_sched_policy(const char *unit,
    1216                 :            :                                        const char *filename,
    1217                 :            :                                        unsigned line,
    1218                 :            :                                        const char *section,
    1219                 :            :                                        unsigned section_line,
    1220                 :            :                                        const char *lvalue,
    1221                 :            :                                        int ltype,
    1222                 :            :                                        const char *rvalue,
    1223                 :            :                                        void *data,
    1224                 :            :                                        void *userdata) {
    1225                 :            : 
    1226                 :         12 :         ExecContext *c = data;
    1227                 :            :         int x;
    1228                 :            : 
    1229         [ -  + ]:         12 :         assert(filename);
    1230         [ -  + ]:         12 :         assert(lvalue);
    1231         [ -  + ]:         12 :         assert(rvalue);
    1232         [ -  + ]:         12 :         assert(data);
    1233                 :            : 
    1234         [ -  + ]:         12 :         if (isempty(rvalue)) {
    1235                 :          0 :                 c->cpu_sched_set = false;
    1236                 :          0 :                 c->cpu_sched_policy = SCHED_OTHER;
    1237                 :          0 :                 c->cpu_sched_priority = 0;
    1238                 :          0 :                 return 0;
    1239                 :            :         }
    1240                 :            : 
    1241                 :         12 :         x = sched_policy_from_string(rvalue);
    1242         [ -  + ]:         12 :         if (x < 0) {
    1243         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
    1244                 :          0 :                 return 0;
    1245                 :            :         }
    1246                 :            : 
    1247                 :         12 :         c->cpu_sched_policy = x;
    1248                 :            :         /* Moving to or from real-time policy? We need to adjust the priority */
    1249         [ +  - ]:         12 :         c->cpu_sched_priority = CLAMP(c->cpu_sched_priority, sched_get_priority_min(x), sched_get_priority_max(x));
    1250                 :         12 :         c->cpu_sched_set = true;
    1251                 :            : 
    1252                 :         12 :         return 0;
    1253                 :            : }
    1254                 :            : 
    1255                 :          0 : int config_parse_numa_mask(const char *unit,
    1256                 :            :                            const char *filename,
    1257                 :            :                            unsigned line,
    1258                 :            :                            const char *section,
    1259                 :            :                            unsigned section_line,
    1260                 :            :                            const char *lvalue,
    1261                 :            :                            int ltype,
    1262                 :            :                            const char *rvalue,
    1263                 :            :                            void *data,
    1264                 :            :                            void *userdata) {
    1265                 :            :         int r;
    1266                 :          0 :         NUMAPolicy *p = data;
    1267                 :            : 
    1268         [ #  # ]:          0 :         assert(filename);
    1269         [ #  # ]:          0 :         assert(lvalue);
    1270         [ #  # ]:          0 :         assert(rvalue);
    1271         [ #  # ]:          0 :         assert(data);
    1272                 :            : 
    1273                 :          0 :         r = parse_cpu_set_extend(rvalue, &p->nodes, true, unit, filename, line, lvalue);
    1274         [ #  # ]:          0 :         if (r < 0) {
    1275         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse NUMA node mask, ignoring: %s", rvalue);
    1276                 :          0 :                 return 0;
    1277                 :            :         }
    1278                 :            : 
    1279                 :          0 :         return r;
    1280                 :            : }
    1281                 :            : 
    1282                 :         28 : int config_parse_exec_cpu_sched_prio(const char *unit,
    1283                 :            :                                      const char *filename,
    1284                 :            :                                      unsigned line,
    1285                 :            :                                      const char *section,
    1286                 :            :                                      unsigned section_line,
    1287                 :            :                                      const char *lvalue,
    1288                 :            :                                      int ltype,
    1289                 :            :                                      const char *rvalue,
    1290                 :            :                                      void *data,
    1291                 :            :                                      void *userdata) {
    1292                 :            : 
    1293                 :         28 :         ExecContext *c = data;
    1294                 :            :         int i, min, max, r;
    1295                 :            : 
    1296         [ -  + ]:         28 :         assert(filename);
    1297         [ -  + ]:         28 :         assert(lvalue);
    1298         [ -  + ]:         28 :         assert(rvalue);
    1299         [ -  + ]:         28 :         assert(data);
    1300                 :            : 
    1301                 :         28 :         r = safe_atoi(rvalue, &i);
    1302         [ -  + ]:         28 :         if (r < 0) {
    1303         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU scheduling priority, ignoring: %s", rvalue);
    1304                 :          0 :                 return 0;
    1305                 :            :         }
    1306                 :            : 
    1307                 :            :         /* On Linux RR/FIFO range from 1 to 99 and OTHER/BATCH may only be 0 */
    1308                 :         28 :         min = sched_get_priority_min(c->cpu_sched_policy);
    1309                 :         28 :         max = sched_get_priority_max(c->cpu_sched_policy);
    1310                 :            : 
    1311   [ +  +  +  + ]:         28 :         if (i < min || i > max) {
    1312         [ +  - ]:         12 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "CPU scheduling priority is out of range, ignoring: %s", rvalue);
    1313                 :         12 :                 return 0;
    1314                 :            :         }
    1315                 :            : 
    1316                 :         16 :         c->cpu_sched_priority = i;
    1317                 :         16 :         c->cpu_sched_set = true;
    1318                 :            : 
    1319                 :         16 :         return 0;
    1320                 :            : }
    1321                 :            : 
    1322                 :          0 : int config_parse_exec_cpu_affinity(const char *unit,
    1323                 :            :                                    const char *filename,
    1324                 :            :                                    unsigned line,
    1325                 :            :                                    const char *section,
    1326                 :            :                                    unsigned section_line,
    1327                 :            :                                    const char *lvalue,
    1328                 :            :                                    int ltype,
    1329                 :            :                                    const char *rvalue,
    1330                 :            :                                    void *data,
    1331                 :            :                                    void *userdata) {
    1332                 :            : 
    1333                 :          0 :         ExecContext *c = data;
    1334                 :            : 
    1335         [ #  # ]:          0 :         assert(filename);
    1336         [ #  # ]:          0 :         assert(lvalue);
    1337         [ #  # ]:          0 :         assert(rvalue);
    1338         [ #  # ]:          0 :         assert(data);
    1339                 :            : 
    1340                 :          0 :         return parse_cpu_set_extend(rvalue, &c->cpu_set, true, unit, filename, line, lvalue);
    1341                 :            : }
    1342                 :            : 
    1343                 :         24 : int config_parse_capability_set(
    1344                 :            :                 const char *unit,
    1345                 :            :                 const char *filename,
    1346                 :            :                 unsigned line,
    1347                 :            :                 const char *section,
    1348                 :            :                 unsigned section_line,
    1349                 :            :                 const char *lvalue,
    1350                 :            :                 int ltype,
    1351                 :            :                 const char *rvalue,
    1352                 :            :                 void *data,
    1353                 :            :                 void *userdata) {
    1354                 :            : 
    1355                 :         24 :         uint64_t *capability_set = data;
    1356                 :         24 :         uint64_t sum = 0, initial = 0;
    1357                 :         24 :         bool invert = false;
    1358                 :            :         int r;
    1359                 :            : 
    1360         [ -  + ]:         24 :         assert(filename);
    1361         [ -  + ]:         24 :         assert(lvalue);
    1362         [ -  + ]:         24 :         assert(rvalue);
    1363         [ -  + ]:         24 :         assert(data);
    1364                 :            : 
    1365         [ +  + ]:         24 :         if (rvalue[0] == '~') {
    1366                 :          8 :                 invert = true;
    1367                 :          8 :                 rvalue++;
    1368                 :            :         }
    1369                 :            : 
    1370         [ +  - ]:         24 :         if (streq(lvalue, "CapabilityBoundingSet"))
    1371                 :         24 :                 initial = CAP_ALL; /* initialized to all bits on */
    1372                 :            :         /* else "AmbientCapabilities" initialized to all bits off */
    1373                 :            : 
    1374                 :         24 :         r = capability_set_from_string(rvalue, &sum);
    1375         [ -  + ]:         24 :         if (r < 0) {
    1376         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s= specifier '%s', ignoring: %m", lvalue, rvalue);
    1377                 :          0 :                 return 0;
    1378                 :            :         }
    1379                 :            : 
    1380   [ +  +  -  + ]:         24 :         if (sum == 0 || *capability_set == initial)
    1381                 :            :                 /* "", "~" or uninitialized data -> replace */
    1382         [ +  + ]:          8 :                 *capability_set = invert ? ~sum : sum;
    1383                 :            :         else {
    1384                 :            :                 /* previous data -> merge */
    1385         [ +  + ]:         16 :                 if (invert)
    1386                 :          4 :                         *capability_set &= ~sum;
    1387                 :            :                 else
    1388                 :         12 :                         *capability_set |= sum;
    1389                 :            :         }
    1390                 :            : 
    1391                 :         24 :         return 0;
    1392                 :            : }
    1393                 :            : 
    1394                 :          0 : int config_parse_exec_selinux_context(
    1395                 :            :                 const char *unit,
    1396                 :            :                 const char *filename,
    1397                 :            :                 unsigned line,
    1398                 :            :                 const char *section,
    1399                 :            :                 unsigned section_line,
    1400                 :            :                 const char *lvalue,
    1401                 :            :                 int ltype,
    1402                 :            :                 const char *rvalue,
    1403                 :            :                 void *data,
    1404                 :            :                 void *userdata) {
    1405                 :            : 
    1406                 :          0 :         ExecContext *c = data;
    1407                 :          0 :         Unit *u = userdata;
    1408                 :            :         bool ignore;
    1409                 :            :         char *k;
    1410                 :            :         int r;
    1411                 :            : 
    1412         [ #  # ]:          0 :         assert(filename);
    1413         [ #  # ]:          0 :         assert(lvalue);
    1414         [ #  # ]:          0 :         assert(rvalue);
    1415         [ #  # ]:          0 :         assert(data);
    1416                 :            : 
    1417         [ #  # ]:          0 :         if (isempty(rvalue)) {
    1418                 :          0 :                 c->selinux_context = mfree(c->selinux_context);
    1419                 :          0 :                 c->selinux_context_ignore = false;
    1420                 :          0 :                 return 0;
    1421                 :            :         }
    1422                 :            : 
    1423         [ #  # ]:          0 :         if (rvalue[0] == '-') {
    1424                 :          0 :                 ignore = true;
    1425                 :          0 :                 rvalue++;
    1426                 :            :         } else
    1427                 :          0 :                 ignore = false;
    1428                 :            : 
    1429                 :          0 :         r = unit_full_printf(u, rvalue, &k);
    1430         [ #  # ]:          0 :         if (r < 0) {
    1431   [ #  #  #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r,
    1432                 :            :                            "Failed to resolve unit specifiers in '%s'%s: %m",
    1433                 :            :                            rvalue, ignore ? ", ignoring" : "");
    1434         [ #  # ]:          0 :                 return ignore ? 0 : -ENOEXEC;
    1435                 :            :         }
    1436                 :            : 
    1437                 :          0 :         free_and_replace(c->selinux_context, k);
    1438                 :          0 :         c->selinux_context_ignore = ignore;
    1439                 :            : 
    1440                 :          0 :         return 0;
    1441                 :            : }
    1442                 :            : 
    1443                 :          0 : int config_parse_exec_apparmor_profile(
    1444                 :            :                 const char *unit,
    1445                 :            :                 const char *filename,
    1446                 :            :                 unsigned line,
    1447                 :            :                 const char *section,
    1448                 :            :                 unsigned section_line,
    1449                 :            :                 const char *lvalue,
    1450                 :            :                 int ltype,
    1451                 :            :                 const char *rvalue,
    1452                 :            :                 void *data,
    1453                 :            :                 void *userdata) {
    1454                 :            : 
    1455                 :          0 :         ExecContext *c = data;
    1456                 :          0 :         Unit *u = userdata;
    1457                 :            :         bool ignore;
    1458                 :            :         char *k;
    1459                 :            :         int r;
    1460                 :            : 
    1461         [ #  # ]:          0 :         assert(filename);
    1462         [ #  # ]:          0 :         assert(lvalue);
    1463         [ #  # ]:          0 :         assert(rvalue);
    1464         [ #  # ]:          0 :         assert(data);
    1465                 :            : 
    1466         [ #  # ]:          0 :         if (isempty(rvalue)) {
    1467                 :          0 :                 c->apparmor_profile = mfree(c->apparmor_profile);
    1468                 :          0 :                 c->apparmor_profile_ignore = false;
    1469                 :          0 :                 return 0;
    1470                 :            :         }
    1471                 :            : 
    1472         [ #  # ]:          0 :         if (rvalue[0] == '-') {
    1473                 :          0 :                 ignore = true;
    1474                 :          0 :                 rvalue++;
    1475                 :            :         } else
    1476                 :          0 :                 ignore = false;
    1477                 :            : 
    1478                 :          0 :         r = unit_full_printf(u, rvalue, &k);
    1479         [ #  # ]:          0 :         if (r < 0) {
    1480   [ #  #  #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r,
    1481                 :            :                            "Failed to resolve unit specifiers in '%s'%s: %m",
    1482                 :            :                            rvalue, ignore ? ", ignoring" : "");
    1483         [ #  # ]:          0 :                 return ignore ? 0 : -ENOEXEC;
    1484                 :            :         }
    1485                 :            : 
    1486                 :          0 :         free_and_replace(c->apparmor_profile, k);
    1487                 :          0 :         c->apparmor_profile_ignore = ignore;
    1488                 :            : 
    1489                 :          0 :         return 0;
    1490                 :            : }
    1491                 :            : 
    1492                 :          0 : int config_parse_exec_smack_process_label(
    1493                 :            :                 const char *unit,
    1494                 :            :                 const char *filename,
    1495                 :            :                 unsigned line,
    1496                 :            :                 const char *section,
    1497                 :            :                 unsigned section_line,
    1498                 :            :                 const char *lvalue,
    1499                 :            :                 int ltype,
    1500                 :            :                 const char *rvalue,
    1501                 :            :                 void *data,
    1502                 :            :                 void *userdata) {
    1503                 :            : 
    1504                 :          0 :         ExecContext *c = data;
    1505                 :          0 :         Unit *u = userdata;
    1506                 :            :         bool ignore;
    1507                 :            :         char *k;
    1508                 :            :         int r;
    1509                 :            : 
    1510         [ #  # ]:          0 :         assert(filename);
    1511         [ #  # ]:          0 :         assert(lvalue);
    1512         [ #  # ]:          0 :         assert(rvalue);
    1513         [ #  # ]:          0 :         assert(data);
    1514                 :            : 
    1515         [ #  # ]:          0 :         if (isempty(rvalue)) {
    1516                 :          0 :                 c->smack_process_label = mfree(c->smack_process_label);
    1517                 :          0 :                 c->smack_process_label_ignore = false;
    1518                 :          0 :                 return 0;
    1519                 :            :         }
    1520                 :            : 
    1521         [ #  # ]:          0 :         if (rvalue[0] == '-') {
    1522                 :          0 :                 ignore = true;
    1523                 :          0 :                 rvalue++;
    1524                 :            :         } else
    1525                 :          0 :                 ignore = false;
    1526                 :            : 
    1527                 :          0 :         r = unit_full_printf(u, rvalue, &k);
    1528         [ #  # ]:          0 :         if (r < 0) {
    1529   [ #  #  #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r,
    1530                 :            :                            "Failed to resolve unit specifiers in '%s'%s: %m",
    1531                 :            :                            rvalue, ignore ? ", ignoring" : "");
    1532         [ #  # ]:          0 :                 return ignore ? 0 : -ENOEXEC;
    1533                 :            :         }
    1534                 :            : 
    1535                 :          0 :         free_and_replace(c->smack_process_label, k);
    1536                 :          0 :         c->smack_process_label_ignore = ignore;
    1537                 :            : 
    1538                 :          0 :         return 0;
    1539                 :            : }
    1540                 :            : 
    1541                 :          0 : int config_parse_timer(
    1542                 :            :                 const char *unit,
    1543                 :            :                 const char *filename,
    1544                 :            :                 unsigned line,
    1545                 :            :                 const char *section,
    1546                 :            :                 unsigned section_line,
    1547                 :            :                 const char *lvalue,
    1548                 :            :                 int ltype,
    1549                 :            :                 const char *rvalue,
    1550                 :            :                 void *data,
    1551                 :            :                 void *userdata) {
    1552                 :            : 
    1553                 :          0 :         _cleanup_(calendar_spec_freep) CalendarSpec *c = NULL;
    1554                 :          0 :         _cleanup_free_ char *k = NULL;
    1555                 :          0 :         Unit *u = userdata;
    1556                 :          0 :         Timer *t = data;
    1557                 :          0 :         usec_t usec = 0;
    1558                 :            :         TimerValue *v;
    1559                 :            :         int r;
    1560                 :            : 
    1561         [ #  # ]:          0 :         assert(filename);
    1562         [ #  # ]:          0 :         assert(lvalue);
    1563         [ #  # ]:          0 :         assert(rvalue);
    1564         [ #  # ]:          0 :         assert(data);
    1565                 :            : 
    1566         [ #  # ]:          0 :         if (isempty(rvalue)) {
    1567                 :            :                 /* Empty assignment resets list */
    1568                 :          0 :                 timer_free_values(t);
    1569                 :          0 :                 return 0;
    1570                 :            :         }
    1571                 :            : 
    1572                 :          0 :         r = unit_full_printf(u, rvalue, &k);
    1573         [ #  # ]:          0 :         if (r < 0) {
    1574         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
    1575                 :          0 :                 return 0;
    1576                 :            :         }
    1577                 :            : 
    1578         [ #  # ]:          0 :         if (ltype == TIMER_CALENDAR) {
    1579                 :          0 :                 r = calendar_spec_from_string(k, &c);
    1580         [ #  # ]:          0 :                 if (r < 0) {
    1581         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse calendar specification, ignoring: %s", k);
    1582                 :          0 :                         return 0;
    1583                 :            :                 }
    1584                 :            :         } else {
    1585                 :          0 :                 r = parse_sec(k, &usec);
    1586         [ #  # ]:          0 :                 if (r < 0) {
    1587         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse timer value, ignoring: %s", k);
    1588                 :          0 :                         return 0;
    1589                 :            :                 }
    1590                 :            :         }
    1591                 :            : 
    1592                 :          0 :         v = new(TimerValue, 1);
    1593         [ #  # ]:          0 :         if (!v)
    1594                 :          0 :                 return log_oom();
    1595                 :            : 
    1596                 :          0 :         *v = (TimerValue) {
    1597                 :            :                 .base = ltype,
    1598                 :            :                 .value = usec,
    1599                 :          0 :                 .calendar_spec = TAKE_PTR(c),
    1600                 :            :         };
    1601                 :            : 
    1602   [ #  #  #  # ]:          0 :         LIST_PREPEND(value, t->values, v);
    1603                 :            : 
    1604                 :          0 :         return 0;
    1605                 :            : }
    1606                 :            : 
    1607                 :          4 : int config_parse_trigger_unit(
    1608                 :            :                 const char *unit,
    1609                 :            :                 const char *filename,
    1610                 :            :                 unsigned line,
    1611                 :            :                 const char *section,
    1612                 :            :                 unsigned section_line,
    1613                 :            :                 const char *lvalue,
    1614                 :            :                 int ltype,
    1615                 :            :                 const char *rvalue,
    1616                 :            :                 void *data,
    1617                 :            :                 void *userdata) {
    1618                 :            : 
    1619                 :          4 :         _cleanup_free_ char *p = NULL;
    1620                 :          4 :         Unit *u = data;
    1621                 :            :         UnitType type;
    1622                 :            :         int r;
    1623                 :            : 
    1624         [ -  + ]:          4 :         assert(filename);
    1625         [ -  + ]:          4 :         assert(lvalue);
    1626         [ -  + ]:          4 :         assert(rvalue);
    1627         [ -  + ]:          4 :         assert(data);
    1628                 :            : 
    1629         [ -  + ]:          4 :         if (!hashmap_isempty(u->dependencies[UNIT_TRIGGERS])) {
    1630         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Multiple units to trigger specified, ignoring: %s", rvalue);
    1631                 :          0 :                 return 0;
    1632                 :            :         }
    1633                 :            : 
    1634                 :          4 :         r = unit_name_printf(u, rvalue, &p);
    1635         [ -  + ]:          4 :         if (r < 0) {
    1636         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
    1637                 :          0 :                 return 0;
    1638                 :            :         }
    1639                 :            : 
    1640                 :          4 :         type = unit_name_to_type(p);
    1641         [ -  + ]:          4 :         if (type < 0) {
    1642         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Unit type not valid, ignoring: %s", rvalue);
    1643                 :          0 :                 return 0;
    1644                 :            :         }
    1645         [ -  + ]:          4 :         if (unit_has_name(u, p)) {
    1646         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Units cannot trigger themselves, ignoring: %s", rvalue);
    1647                 :          0 :                 return 0;
    1648                 :            :         }
    1649                 :            : 
    1650                 :          4 :         r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_TRIGGERS, p, true, UNIT_DEPENDENCY_FILE);
    1651         [ -  + ]:          4 :         if (r < 0) {
    1652         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add trigger on %s, ignoring: %m", p);
    1653                 :          0 :                 return 0;
    1654                 :            :         }
    1655                 :            : 
    1656                 :          4 :         return 0;
    1657                 :            : }
    1658                 :            : 
    1659                 :         28 : int config_parse_path_spec(const char *unit,
    1660                 :            :                            const char *filename,
    1661                 :            :                            unsigned line,
    1662                 :            :                            const char *section,
    1663                 :            :                            unsigned section_line,
    1664                 :            :                            const char *lvalue,
    1665                 :            :                            int ltype,
    1666                 :            :                            const char *rvalue,
    1667                 :            :                            void *data,
    1668                 :            :                            void *userdata) {
    1669                 :            : 
    1670                 :         28 :         Path *p = data;
    1671                 :            :         PathSpec *s;
    1672                 :            :         PathType b;
    1673                 :         28 :         _cleanup_free_ char *k = NULL;
    1674                 :            :         int r;
    1675                 :            : 
    1676         [ -  + ]:         28 :         assert(filename);
    1677         [ -  + ]:         28 :         assert(lvalue);
    1678         [ -  + ]:         28 :         assert(rvalue);
    1679         [ -  + ]:         28 :         assert(data);
    1680                 :            : 
    1681         [ -  + ]:         28 :         if (isempty(rvalue)) {
    1682                 :            :                 /* Empty assignment clears list */
    1683                 :          0 :                 path_free_specs(p);
    1684                 :          0 :                 return 0;
    1685                 :            :         }
    1686                 :            : 
    1687                 :         28 :         b = path_type_from_string(lvalue);
    1688         [ -  + ]:         28 :         if (b < 0) {
    1689         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse path type, ignoring: %s", lvalue);
    1690                 :          0 :                 return 0;
    1691                 :            :         }
    1692                 :            : 
    1693         [ +  - ]:         28 :         r = unit_full_printf(UNIT(p), rvalue, &k);
    1694         [ -  + ]:         28 :         if (r < 0) {
    1695         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
    1696                 :          0 :                 return 0;
    1697                 :            :         }
    1698                 :            : 
    1699                 :         28 :         r = path_simplify_and_warn(k, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
    1700         [ -  + ]:         28 :         if (r < 0)
    1701                 :          0 :                 return 0;
    1702                 :            : 
    1703                 :         28 :         s = new0(PathSpec, 1);
    1704         [ -  + ]:         28 :         if (!s)
    1705                 :          0 :                 return log_oom();
    1706                 :            : 
    1707         [ +  - ]:         28 :         s->unit = UNIT(p);
    1708                 :         28 :         s->path = TAKE_PTR(k);
    1709                 :         28 :         s->type = b;
    1710                 :         28 :         s->inotify_fd = -1;
    1711                 :            : 
    1712   [ -  +  -  + ]:         28 :         LIST_PREPEND(spec, p->specs, s);
    1713                 :            : 
    1714                 :         28 :         return 0;
    1715                 :            : }
    1716                 :            : 
    1717                 :          0 : int config_parse_socket_service(
    1718                 :            :                 const char *unit,
    1719                 :            :                 const char *filename,
    1720                 :            :                 unsigned line,
    1721                 :            :                 const char *section,
    1722                 :            :                 unsigned section_line,
    1723                 :            :                 const char *lvalue,
    1724                 :            :                 int ltype,
    1725                 :            :                 const char *rvalue,
    1726                 :            :                 void *data,
    1727                 :            :                 void *userdata) {
    1728                 :            : 
    1729                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
    1730                 :          0 :         _cleanup_free_ char *p = NULL;
    1731                 :          0 :         Socket *s = data;
    1732                 :            :         Unit *x;
    1733                 :            :         int r;
    1734                 :            : 
    1735         [ #  # ]:          0 :         assert(filename);
    1736         [ #  # ]:          0 :         assert(lvalue);
    1737         [ #  # ]:          0 :         assert(rvalue);
    1738         [ #  # ]:          0 :         assert(data);
    1739                 :            : 
    1740         [ #  # ]:          0 :         r = unit_name_printf(UNIT(s), rvalue, &p);
    1741         [ #  # ]:          0 :         if (r < 0) {
    1742         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", rvalue);
    1743                 :          0 :                 return -ENOEXEC;
    1744                 :            :         }
    1745                 :            : 
    1746         [ #  # ]:          0 :         if (!endswith(p, ".service")) {
    1747         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Unit must be of type service: %s", rvalue);
    1748                 :          0 :                 return -ENOEXEC;
    1749                 :            :         }
    1750                 :            : 
    1751         [ #  # ]:          0 :         r = manager_load_unit(UNIT(s)->manager, p, NULL, &error, &x);
    1752         [ #  # ]:          0 :         if (r < 0) {
    1753         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s: %s", rvalue, bus_error_message(&error, r));
    1754                 :          0 :                 return -ENOEXEC;
    1755                 :            :         }
    1756                 :            : 
    1757         [ #  # ]:          0 :         unit_ref_set(&s->service, UNIT(s), x);
    1758                 :            : 
    1759                 :          0 :         return 0;
    1760                 :            : }
    1761                 :            : 
    1762                 :          0 : int config_parse_fdname(
    1763                 :            :                 const char *unit,
    1764                 :            :                 const char *filename,
    1765                 :            :                 unsigned line,
    1766                 :            :                 const char *section,
    1767                 :            :                 unsigned section_line,
    1768                 :            :                 const char *lvalue,
    1769                 :            :                 int ltype,
    1770                 :            :                 const char *rvalue,
    1771                 :            :                 void *data,
    1772                 :            :                 void *userdata) {
    1773                 :            : 
    1774                 :          0 :         _cleanup_free_ char *p = NULL;
    1775                 :          0 :         Socket *s = data;
    1776                 :            :         int r;
    1777                 :            : 
    1778         [ #  # ]:          0 :         assert(filename);
    1779         [ #  # ]:          0 :         assert(lvalue);
    1780         [ #  # ]:          0 :         assert(rvalue);
    1781         [ #  # ]:          0 :         assert(data);
    1782                 :            : 
    1783         [ #  # ]:          0 :         if (isempty(rvalue)) {
    1784                 :          0 :                 s->fdname = mfree(s->fdname);
    1785                 :          0 :                 return 0;
    1786                 :            :         }
    1787                 :            : 
    1788         [ #  # ]:          0 :         r = unit_full_printf(UNIT(s), rvalue, &p);
    1789         [ #  # ]:          0 :         if (r < 0) {
    1790         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
    1791                 :          0 :                 return 0;
    1792                 :            :         }
    1793                 :            : 
    1794         [ #  # ]:          0 :         if (!fdname_is_valid(p)) {
    1795         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid file descriptor name, ignoring: %s", p);
    1796                 :          0 :                 return 0;
    1797                 :            :         }
    1798                 :            : 
    1799                 :          0 :         return free_and_replace(s->fdname, p);
    1800                 :            : }
    1801                 :            : 
    1802                 :          0 : int config_parse_service_sockets(
    1803                 :            :                 const char *unit,
    1804                 :            :                 const char *filename,
    1805                 :            :                 unsigned line,
    1806                 :            :                 const char *section,
    1807                 :            :                 unsigned section_line,
    1808                 :            :                 const char *lvalue,
    1809                 :            :                 int ltype,
    1810                 :            :                 const char *rvalue,
    1811                 :            :                 void *data,
    1812                 :            :                 void *userdata) {
    1813                 :            : 
    1814                 :          0 :         Service *s = data;
    1815                 :            :         const char *p;
    1816                 :            :         int r;
    1817                 :            : 
    1818         [ #  # ]:          0 :         assert(filename);
    1819         [ #  # ]:          0 :         assert(lvalue);
    1820         [ #  # ]:          0 :         assert(rvalue);
    1821         [ #  # ]:          0 :         assert(data);
    1822                 :            : 
    1823                 :          0 :         p = rvalue;
    1824                 :          0 :         for (;;) {
    1825   [ #  #  #  #  :          0 :                 _cleanup_free_ char *word = NULL, *k = NULL;
             #  #  #  # ]
    1826                 :            : 
    1827                 :          0 :                 r = extract_first_word(&p, &word, NULL, 0);
    1828         [ #  # ]:          0 :                 if (r == 0)
    1829                 :          0 :                         break;
    1830         [ #  # ]:          0 :                 if (r == -ENOMEM)
    1831                 :          0 :                         return log_oom();
    1832         [ #  # ]:          0 :                 if (r < 0) {
    1833         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Trailing garbage in sockets, ignoring: %s", rvalue);
    1834                 :          0 :                         break;
    1835                 :            :                 }
    1836                 :            : 
    1837         [ #  # ]:          0 :                 r = unit_name_printf(UNIT(s), word, &k);
    1838         [ #  # ]:          0 :                 if (r < 0) {
    1839         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", word);
    1840                 :          0 :                         continue;
    1841                 :            :                 }
    1842                 :            : 
    1843         [ #  # ]:          0 :                 if (!endswith(k, ".socket")) {
    1844         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, 0, "Unit must be of type socket, ignoring: %s", k);
    1845                 :          0 :                         continue;
    1846                 :            :                 }
    1847                 :            : 
    1848         [ #  # ]:          0 :                 r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k, true, UNIT_DEPENDENCY_FILE);
    1849         [ #  # ]:          0 :                 if (r < 0)
    1850         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k);
    1851                 :            : 
    1852         [ #  # ]:          0 :                 r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k, true, UNIT_DEPENDENCY_FILE);
    1853         [ #  # ]:          0 :                 if (r < 0)
    1854         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k);
    1855                 :            :         }
    1856                 :            : 
    1857                 :          0 :         return 0;
    1858                 :            : }
    1859                 :            : 
    1860                 :          0 : int config_parse_bus_name(
    1861                 :            :                 const char *unit,
    1862                 :            :                 const char *filename,
    1863                 :            :                 unsigned line,
    1864                 :            :                 const char *section,
    1865                 :            :                 unsigned section_line,
    1866                 :            :                 const char *lvalue,
    1867                 :            :                 int ltype,
    1868                 :            :                 const char *rvalue,
    1869                 :            :                 void *data,
    1870                 :            :                 void *userdata) {
    1871                 :            : 
    1872                 :          0 :         _cleanup_free_ char *k = NULL;
    1873                 :          0 :         Unit *u = userdata;
    1874                 :            :         int r;
    1875                 :            : 
    1876         [ #  # ]:          0 :         assert(filename);
    1877         [ #  # ]:          0 :         assert(lvalue);
    1878         [ #  # ]:          0 :         assert(rvalue);
    1879         [ #  # ]:          0 :         assert(u);
    1880                 :            : 
    1881                 :          0 :         r = unit_full_printf(u, rvalue, &k);
    1882         [ #  # ]:          0 :         if (r < 0) {
    1883         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
    1884                 :          0 :                 return 0;
    1885                 :            :         }
    1886                 :            : 
    1887         [ #  # ]:          0 :         if (!service_name_is_valid(k)) {
    1888         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid bus name, ignoring: %s", k);
    1889                 :          0 :                 return 0;
    1890                 :            :         }
    1891                 :            : 
    1892                 :          0 :         return config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata);
    1893                 :            : }
    1894                 :            : 
    1895                 :          0 : int config_parse_service_timeout(
    1896                 :            :                 const char *unit,
    1897                 :            :                 const char *filename,
    1898                 :            :                 unsigned line,
    1899                 :            :                 const char *section,
    1900                 :            :                 unsigned section_line,
    1901                 :            :                 const char *lvalue,
    1902                 :            :                 int ltype,
    1903                 :            :                 const char *rvalue,
    1904                 :            :                 void *data,
    1905                 :            :                 void *userdata) {
    1906                 :            : 
    1907                 :          0 :         Service *s = userdata;
    1908                 :            :         usec_t usec;
    1909                 :            :         int r;
    1910                 :            : 
    1911         [ #  # ]:          0 :         assert(filename);
    1912         [ #  # ]:          0 :         assert(lvalue);
    1913         [ #  # ]:          0 :         assert(rvalue);
    1914         [ #  # ]:          0 :         assert(s);
    1915                 :            : 
    1916                 :            :         /* This is called for two cases: TimeoutSec= and TimeoutStartSec=. */
    1917                 :            : 
    1918                 :            :         /* Traditionally, these options accepted 0 to disable the timeouts. However, a timeout of 0 suggests it happens
    1919                 :            :          * immediately, hence fix this to become USEC_INFINITY instead. This is in-line with how we internally handle
    1920                 :            :          * all other timeouts. */
    1921                 :          0 :         r = parse_sec_fix_0(rvalue, &usec);
    1922         [ #  # ]:          0 :         if (r < 0) {
    1923         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s= parameter, ignoring: %s", lvalue, rvalue);
    1924                 :          0 :                 return 0;
    1925                 :            :         }
    1926                 :            : 
    1927                 :          0 :         s->start_timeout_defined = true;
    1928                 :          0 :         s->timeout_start_usec = usec;
    1929                 :            : 
    1930         [ #  # ]:          0 :         if (streq(lvalue, "TimeoutSec"))
    1931                 :          0 :                 s->timeout_stop_usec = usec;
    1932                 :            : 
    1933                 :          0 :         return 0;
    1934                 :            : }
    1935                 :            : 
    1936                 :          0 : int config_parse_service_timeout_abort(
    1937                 :            :                 const char *unit,
    1938                 :            :                 const char *filename,
    1939                 :            :                 unsigned line,
    1940                 :            :                 const char *section,
    1941                 :            :                 unsigned section_line,
    1942                 :            :                 const char *lvalue,
    1943                 :            :                 int ltype,
    1944                 :            :                 const char *rvalue,
    1945                 :            :                 void *data,
    1946                 :            :                 void *userdata) {
    1947                 :            : 
    1948                 :          0 :         Service *s = userdata;
    1949                 :            :         int r;
    1950                 :            : 
    1951         [ #  # ]:          0 :         assert(filename);
    1952         [ #  # ]:          0 :         assert(lvalue);
    1953         [ #  # ]:          0 :         assert(rvalue);
    1954         [ #  # ]:          0 :         assert(s);
    1955                 :            : 
    1956                 :          0 :         rvalue += strspn(rvalue, WHITESPACE);
    1957         [ #  # ]:          0 :         if (isempty(rvalue)) {
    1958                 :          0 :                 s->timeout_abort_set = false;
    1959                 :          0 :                 return 0;
    1960                 :            :         }
    1961                 :            : 
    1962                 :          0 :         r = parse_sec(rvalue, &s->timeout_abort_usec);
    1963         [ #  # ]:          0 :         if (r < 0) {
    1964         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse TimeoutAbortSec= setting, ignoring: %s", rvalue);
    1965                 :          0 :                 return 0;
    1966                 :            :         }
    1967                 :            : 
    1968                 :          0 :         s->timeout_abort_set = true;
    1969                 :          0 :         return 0;
    1970                 :            : }
    1971                 :            : 
    1972                 :          0 : int config_parse_sec_fix_0(
    1973                 :            :                 const char *unit,
    1974                 :            :                 const char *filename,
    1975                 :            :                 unsigned line,
    1976                 :            :                 const char *section,
    1977                 :            :                 unsigned section_line,
    1978                 :            :                 const char *lvalue,
    1979                 :            :                 int ltype,
    1980                 :            :                 const char *rvalue,
    1981                 :            :                 void *data,
    1982                 :            :                 void *userdata) {
    1983                 :            : 
    1984                 :          0 :         usec_t *usec = data;
    1985                 :            :         int r;
    1986                 :            : 
    1987         [ #  # ]:          0 :         assert(filename);
    1988         [ #  # ]:          0 :         assert(lvalue);
    1989         [ #  # ]:          0 :         assert(rvalue);
    1990         [ #  # ]:          0 :         assert(usec);
    1991                 :            : 
    1992                 :            :         /* This is pretty much like config_parse_sec(), except that this treats a time of 0 as infinity, for
    1993                 :            :          * compatibility with older versions of systemd where 0 instead of infinity was used as indicator to turn off a
    1994                 :            :          * timeout. */
    1995                 :            : 
    1996                 :          0 :         r = parse_sec_fix_0(rvalue, usec);
    1997         [ #  # ]:          0 :         if (r < 0) {
    1998         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s= parameter, ignoring: %s", lvalue, rvalue);
    1999                 :          0 :                 return 0;
    2000                 :            :         }
    2001                 :            : 
    2002                 :          0 :         return 0;
    2003                 :            : }
    2004                 :            : 
    2005                 :          0 : int config_parse_user_group(
    2006                 :            :                 const char *unit,
    2007                 :            :                 const char *filename,
    2008                 :            :                 unsigned line,
    2009                 :            :                 const char *section,
    2010                 :            :                 unsigned section_line,
    2011                 :            :                 const char *lvalue,
    2012                 :            :                 int ltype,
    2013                 :            :                 const char *rvalue,
    2014                 :            :                 void *data,
    2015                 :            :                 void *userdata) {
    2016                 :            : 
    2017                 :          0 :         _cleanup_free_ char *k = NULL;
    2018                 :          0 :         char **user = data;
    2019                 :          0 :         Unit *u = userdata;
    2020                 :            :         int r;
    2021                 :            : 
    2022         [ #  # ]:          0 :         assert(filename);
    2023         [ #  # ]:          0 :         assert(lvalue);
    2024         [ #  # ]:          0 :         assert(rvalue);
    2025         [ #  # ]:          0 :         assert(u);
    2026                 :            : 
    2027         [ #  # ]:          0 :         if (isempty(rvalue)) {
    2028                 :          0 :                 *user = mfree(*user);
    2029                 :          0 :                 return 0;
    2030                 :            :         }
    2031                 :            : 
    2032                 :          0 :         r = unit_full_printf(u, rvalue, &k);
    2033         [ #  # ]:          0 :         if (r < 0) {
    2034         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", rvalue);
    2035                 :          0 :                 return -ENOEXEC;
    2036                 :            :         }
    2037                 :            : 
    2038         [ #  # ]:          0 :         if (!valid_user_group_name_or_id(k)) {
    2039         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID: %s", k);
    2040                 :          0 :                 return -ENOEXEC;
    2041                 :            :         }
    2042                 :            : 
    2043                 :          0 :         return free_and_replace(*user, k);
    2044                 :            : }
    2045                 :            : 
    2046                 :          0 : int config_parse_user_group_strv(
    2047                 :            :                 const char *unit,
    2048                 :            :                 const char *filename,
    2049                 :            :                 unsigned line,
    2050                 :            :                 const char *section,
    2051                 :            :                 unsigned section_line,
    2052                 :            :                 const char *lvalue,
    2053                 :            :                 int ltype,
    2054                 :            :                 const char *rvalue,
    2055                 :            :                 void *data,
    2056                 :            :                 void *userdata) {
    2057                 :            : 
    2058                 :          0 :         char ***users = data;
    2059                 :          0 :         Unit *u = userdata;
    2060                 :          0 :         const char *p = rvalue;
    2061                 :            :         int r;
    2062                 :            : 
    2063         [ #  # ]:          0 :         assert(filename);
    2064         [ #  # ]:          0 :         assert(lvalue);
    2065         [ #  # ]:          0 :         assert(rvalue);
    2066         [ #  # ]:          0 :         assert(u);
    2067                 :            : 
    2068         [ #  # ]:          0 :         if (isempty(rvalue)) {
    2069                 :          0 :                 *users = strv_free(*users);
    2070                 :          0 :                 return 0;
    2071                 :            :         }
    2072                 :            : 
    2073                 :          0 :         for (;;) {
    2074   [ #  #  #  #  :          0 :                 _cleanup_free_ char *word = NULL, *k = NULL;
                   #  # ]
    2075                 :            : 
    2076                 :          0 :                 r = extract_first_word(&p, &word, NULL, 0);
    2077         [ #  # ]:          0 :                 if (r == 0)
    2078                 :          0 :                         break;
    2079         [ #  # ]:          0 :                 if (r == -ENOMEM)
    2080                 :          0 :                         return log_oom();
    2081         [ #  # ]:          0 :                 if (r < 0) {
    2082         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax: %s", rvalue);
    2083                 :          0 :                         return -ENOEXEC;
    2084                 :            :                 }
    2085                 :            : 
    2086                 :          0 :                 r = unit_full_printf(u, word, &k);
    2087         [ #  # ]:          0 :                 if (r < 0) {
    2088         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", word);
    2089                 :          0 :                         return -ENOEXEC;
    2090                 :            :                 }
    2091                 :            : 
    2092         [ #  # ]:          0 :                 if (!valid_user_group_name_or_id(k)) {
    2093         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID: %s", k);
    2094                 :          0 :                         return -ENOEXEC;
    2095                 :            :                 }
    2096                 :            : 
    2097                 :          0 :                 r = strv_push(users, k);
    2098         [ #  # ]:          0 :                 if (r < 0)
    2099                 :          0 :                         return log_oom();
    2100                 :            : 
    2101                 :          0 :                 k = NULL;
    2102                 :            :         }
    2103                 :            : 
    2104                 :          0 :         return 0;
    2105                 :            : }
    2106                 :            : 
    2107                 :          0 : int config_parse_working_directory(
    2108                 :            :                 const char *unit,
    2109                 :            :                 const char *filename,
    2110                 :            :                 unsigned line,
    2111                 :            :                 const char *section,
    2112                 :            :                 unsigned section_line,
    2113                 :            :                 const char *lvalue,
    2114                 :            :                 int ltype,
    2115                 :            :                 const char *rvalue,
    2116                 :            :                 void *data,
    2117                 :            :                 void *userdata) {
    2118                 :            : 
    2119                 :          0 :         ExecContext *c = data;
    2120                 :          0 :         Unit *u = userdata;
    2121                 :            :         bool missing_ok;
    2122                 :            :         int r;
    2123                 :            : 
    2124         [ #  # ]:          0 :         assert(filename);
    2125         [ #  # ]:          0 :         assert(lvalue);
    2126         [ #  # ]:          0 :         assert(rvalue);
    2127         [ #  # ]:          0 :         assert(c);
    2128         [ #  # ]:          0 :         assert(u);
    2129                 :            : 
    2130         [ #  # ]:          0 :         if (isempty(rvalue)) {
    2131                 :          0 :                 c->working_directory_home = false;
    2132                 :          0 :                 c->working_directory = mfree(c->working_directory);
    2133                 :          0 :                 return 0;
    2134                 :            :         }
    2135                 :            : 
    2136         [ #  # ]:          0 :         if (rvalue[0] == '-') {
    2137                 :          0 :                 missing_ok = true;
    2138                 :          0 :                 rvalue++;
    2139                 :            :         } else
    2140                 :          0 :                 missing_ok = false;
    2141                 :            : 
    2142         [ #  # ]:          0 :         if (streq(rvalue, "~")) {
    2143                 :          0 :                 c->working_directory_home = true;
    2144                 :          0 :                 c->working_directory = mfree(c->working_directory);
    2145                 :            :         } else {
    2146         [ #  # ]:          0 :                 _cleanup_free_ char *k = NULL;
    2147                 :            : 
    2148                 :          0 :                 r = unit_full_printf(u, rvalue, &k);
    2149         [ #  # ]:          0 :                 if (r < 0) {
    2150   [ #  #  #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
    2151                 :            :                                    "Failed to resolve unit specifiers in working directory path '%s'%s: %m",
    2152                 :            :                                    rvalue, missing_ok ? ", ignoring" : "");
    2153         [ #  # ]:          0 :                         return missing_ok ? 0 : -ENOEXEC;
    2154                 :            :                 }
    2155                 :            : 
    2156         [ #  # ]:          0 :                 r = path_simplify_and_warn(k, PATH_CHECK_ABSOLUTE | (missing_ok ? 0 : PATH_CHECK_FATAL), unit, filename, line, lvalue);
    2157         [ #  # ]:          0 :                 if (r < 0)
    2158         [ #  # ]:          0 :                         return missing_ok ? 0 : -ENOEXEC;
    2159                 :            : 
    2160                 :          0 :                 c->working_directory_home = false;
    2161                 :          0 :                 free_and_replace(c->working_directory, k);
    2162                 :            :         }
    2163                 :            : 
    2164                 :          0 :         c->working_directory_missing_ok = missing_ok;
    2165                 :          0 :         return 0;
    2166                 :            : }
    2167                 :            : 
    2168                 :          0 : int config_parse_unit_env_file(const char *unit,
    2169                 :            :                                const char *filename,
    2170                 :            :                                unsigned line,
    2171                 :            :                                const char *section,
    2172                 :            :                                unsigned section_line,
    2173                 :            :                                const char *lvalue,
    2174                 :            :                                int ltype,
    2175                 :            :                                const char *rvalue,
    2176                 :            :                                void *data,
    2177                 :            :                                void *userdata) {
    2178                 :            : 
    2179                 :          0 :         char ***env = data;
    2180                 :          0 :         Unit *u = userdata;
    2181                 :          0 :         _cleanup_free_ char *n = NULL;
    2182                 :            :         int r;
    2183                 :            : 
    2184         [ #  # ]:          0 :         assert(filename);
    2185         [ #  # ]:          0 :         assert(lvalue);
    2186         [ #  # ]:          0 :         assert(rvalue);
    2187         [ #  # ]:          0 :         assert(data);
    2188                 :            : 
    2189         [ #  # ]:          0 :         if (isempty(rvalue)) {
    2190                 :            :                 /* Empty assignment frees the list */
    2191                 :          0 :                 *env = strv_free(*env);
    2192                 :          0 :                 return 0;
    2193                 :            :         }
    2194                 :            : 
    2195                 :          0 :         r = unit_full_printf(u, rvalue, &n);
    2196         [ #  # ]:          0 :         if (r < 0) {
    2197         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
    2198                 :          0 :                 return 0;
    2199                 :            :         }
    2200                 :            : 
    2201         [ #  # ]:          0 :         r = path_simplify_and_warn(n[0] == '-' ? n + 1 : n, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
    2202         [ #  # ]:          0 :         if (r < 0)
    2203                 :          0 :                 return 0;
    2204                 :            : 
    2205                 :          0 :         r = strv_push(env, n);
    2206         [ #  # ]:          0 :         if (r < 0)
    2207                 :          0 :                 return log_oom();
    2208                 :            : 
    2209                 :          0 :         n = NULL;
    2210                 :            : 
    2211                 :          0 :         return 0;
    2212                 :            : }
    2213                 :            : 
    2214                 :          0 : int config_parse_environ(
    2215                 :            :                 const char *unit,
    2216                 :            :                 const char *filename,
    2217                 :            :                 unsigned line,
    2218                 :            :                 const char *section,
    2219                 :            :                 unsigned section_line,
    2220                 :            :                 const char *lvalue,
    2221                 :            :                 int ltype,
    2222                 :            :                 const char *rvalue,
    2223                 :            :                 void *data,
    2224                 :            :                 void *userdata) {
    2225                 :            : 
    2226                 :          0 :         Unit *u = userdata;
    2227                 :          0 :         char ***env = data;
    2228                 :            :         const char *p;
    2229                 :            :         int r;
    2230                 :            : 
    2231         [ #  # ]:          0 :         assert(filename);
    2232         [ #  # ]:          0 :         assert(lvalue);
    2233         [ #  # ]:          0 :         assert(rvalue);
    2234         [ #  # ]:          0 :         assert(data);
    2235                 :            : 
    2236         [ #  # ]:          0 :         if (isempty(rvalue)) {
    2237                 :            :                 /* Empty assignment resets the list */
    2238                 :          0 :                 *env = strv_free(*env);
    2239                 :          0 :                 return 0;
    2240                 :            :         }
    2241                 :            : 
    2242                 :          0 :         for (p = rvalue;; ) {
    2243   [ #  #  #  #  :          0 :                 _cleanup_free_ char *word = NULL, *k = NULL;
                   #  # ]
    2244                 :            : 
    2245                 :          0 :                 r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
    2246         [ #  # ]:          0 :                 if (r == 0)
    2247                 :          0 :                         return 0;
    2248         [ #  # ]:          0 :                 if (r == -ENOMEM)
    2249                 :          0 :                         return log_oom();
    2250         [ #  # ]:          0 :                 if (r < 0) {
    2251         [ #  # ]:          0 :                         log_syntax(unit, LOG_WARNING, filename, line, r,
    2252                 :            :                                    "Invalid syntax, ignoring: %s", rvalue);
    2253                 :          0 :                         return 0;
    2254                 :            :                 }
    2255                 :            : 
    2256         [ #  # ]:          0 :                 if (u) {
    2257                 :          0 :                         r = unit_full_printf(u, word, &k);
    2258         [ #  # ]:          0 :                         if (r < 0) {
    2259         [ #  # ]:          0 :                                 log_syntax(unit, LOG_ERR, filename, line, r,
    2260                 :            :                                            "Failed to resolve unit specifiers in %s, ignoring: %m", word);
    2261                 :          0 :                                 continue;
    2262                 :            :                         }
    2263                 :            :                 } else
    2264                 :          0 :                         k = TAKE_PTR(word);
    2265                 :            : 
    2266         [ #  # ]:          0 :                 if (!env_assignment_is_valid(k)) {
    2267         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, 0,
    2268                 :            :                                    "Invalid environment assignment, ignoring: %s", k);
    2269                 :          0 :                         continue;
    2270                 :            :                 }
    2271                 :            : 
    2272                 :          0 :                 r = strv_env_replace(env, k);
    2273         [ #  # ]:          0 :                 if (r < 0)
    2274                 :          0 :                         return log_oom();
    2275                 :            : 
    2276                 :          0 :                 k = NULL;
    2277                 :            :         }
    2278                 :            : }
    2279                 :            : 
    2280                 :         12 : int config_parse_pass_environ(
    2281                 :            :                 const char *unit,
    2282                 :            :                 const char *filename,
    2283                 :            :                 unsigned line,
    2284                 :            :                 const char *section,
    2285                 :            :                 unsigned section_line,
    2286                 :            :                 const char *lvalue,
    2287                 :            :                 int ltype,
    2288                 :            :                 const char *rvalue,
    2289                 :            :                 void *data,
    2290                 :            :                 void *userdata) {
    2291                 :            : 
    2292                 :         12 :         _cleanup_strv_free_ char **n = NULL;
    2293                 :         12 :         size_t nlen = 0, nbufsize = 0;
    2294                 :         12 :         char*** passenv = data;
    2295                 :         12 :         const char *p = rvalue;
    2296                 :         12 :         Unit *u = userdata;
    2297                 :            :         int r;
    2298                 :            : 
    2299         [ -  + ]:         12 :         assert(filename);
    2300         [ -  + ]:         12 :         assert(lvalue);
    2301         [ -  + ]:         12 :         assert(rvalue);
    2302         [ -  + ]:         12 :         assert(data);
    2303                 :            : 
    2304         [ +  + ]:         12 :         if (isempty(rvalue)) {
    2305                 :            :                 /* Empty assignment resets the list */
    2306                 :          4 :                 *passenv = strv_free(*passenv);
    2307                 :          4 :                 return 0;
    2308                 :            :         }
    2309                 :            : 
    2310                 :         20 :         for (;;) {
    2311   [ +  +  -  +  :         44 :                 _cleanup_free_ char *word = NULL, *k = NULL;
             +  +  -  + ]
    2312                 :            : 
    2313                 :         28 :                 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
    2314         [ +  + ]:         28 :                 if (r == 0)
    2315                 :          4 :                         break;
    2316         [ -  + ]:         24 :                 if (r == -ENOMEM)
    2317                 :          0 :                         return log_oom();
    2318         [ +  + ]:         24 :                 if (r < 0) {
    2319         [ +  - ]:          4 :                         log_syntax(unit, LOG_ERR, filename, line, r,
    2320                 :            :                                    "Trailing garbage in %s, ignoring: %s", lvalue, rvalue);
    2321                 :          4 :                         break;
    2322                 :            :                 }
    2323                 :            : 
    2324         [ -  + ]:         20 :                 if (u) {
    2325                 :          0 :                         r = unit_full_printf(u, word, &k);
    2326         [ #  # ]:          0 :                         if (r < 0) {
    2327         [ #  # ]:          0 :                                 log_syntax(unit, LOG_ERR, filename, line, r,
    2328                 :            :                                            "Failed to resolve specifiers in %s, ignoring: %m", word);
    2329                 :          0 :                                 continue;
    2330                 :            :                         }
    2331                 :            :                 } else
    2332                 :         20 :                         k = TAKE_PTR(word);
    2333                 :            : 
    2334         [ +  + ]:         20 :                 if (!env_name_is_valid(k)) {
    2335         [ +  - ]:          8 :                         log_syntax(unit, LOG_ERR, filename, line, 0,
    2336                 :            :                                    "Invalid environment name for %s, ignoring: %s", lvalue, k);
    2337                 :          8 :                         continue;
    2338                 :            :                 }
    2339                 :            : 
    2340         [ -  + ]:         12 :                 if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
    2341                 :          0 :                         return log_oom();
    2342                 :            : 
    2343                 :         12 :                 n[nlen++] = TAKE_PTR(k);
    2344                 :         12 :                 n[nlen] = NULL;
    2345                 :            :         }
    2346                 :            : 
    2347         [ +  - ]:          8 :         if (n) {
    2348                 :          8 :                 r = strv_extend_strv(passenv, n, true);
    2349         [ -  + ]:          8 :                 if (r < 0)
    2350                 :          0 :                         return r;
    2351                 :            :         }
    2352                 :            : 
    2353                 :          8 :         return 0;
    2354                 :            : }
    2355                 :            : 
    2356                 :          0 : int config_parse_unset_environ(
    2357                 :            :                 const char *unit,
    2358                 :            :                 const char *filename,
    2359                 :            :                 unsigned line,
    2360                 :            :                 const char *section,
    2361                 :            :                 unsigned section_line,
    2362                 :            :                 const char *lvalue,
    2363                 :            :                 int ltype,
    2364                 :            :                 const char *rvalue,
    2365                 :            :                 void *data,
    2366                 :            :                 void *userdata) {
    2367                 :            : 
    2368                 :          0 :         _cleanup_strv_free_ char **n = NULL;
    2369                 :          0 :         size_t nlen = 0, nbufsize = 0;
    2370                 :          0 :         char*** unsetenv = data;
    2371                 :          0 :         const char *p = rvalue;
    2372                 :          0 :         Unit *u = userdata;
    2373                 :            :         int r;
    2374                 :            : 
    2375         [ #  # ]:          0 :         assert(filename);
    2376         [ #  # ]:          0 :         assert(lvalue);
    2377         [ #  # ]:          0 :         assert(rvalue);
    2378         [ #  # ]:          0 :         assert(data);
    2379                 :            : 
    2380         [ #  # ]:          0 :         if (isempty(rvalue)) {
    2381                 :            :                 /* Empty assignment resets the list */
    2382                 :          0 :                 *unsetenv = strv_free(*unsetenv);
    2383                 :          0 :                 return 0;
    2384                 :            :         }
    2385                 :            : 
    2386                 :          0 :         for (;;) {
    2387   [ #  #  #  #  :          0 :                 _cleanup_free_ char *word = NULL, *k = NULL;
             #  #  #  # ]
    2388                 :            : 
    2389                 :          0 :                 r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
    2390         [ #  # ]:          0 :                 if (r == 0)
    2391                 :          0 :                         break;
    2392         [ #  # ]:          0 :                 if (r == -ENOMEM)
    2393                 :          0 :                         return log_oom();
    2394         [ #  # ]:          0 :                 if (r < 0) {
    2395         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
    2396                 :            :                                    "Trailing garbage in %s, ignoring: %s", lvalue, rvalue);
    2397                 :          0 :                         break;
    2398                 :            :                 }
    2399                 :            : 
    2400         [ #  # ]:          0 :                 if (u) {
    2401                 :          0 :                         r = unit_full_printf(u, word, &k);
    2402         [ #  # ]:          0 :                         if (r < 0) {
    2403         [ #  # ]:          0 :                                 log_syntax(unit, LOG_ERR, filename, line, r,
    2404                 :            :                                            "Failed to resolve unit specifiers in %s, ignoring: %m", word);
    2405                 :          0 :                                 continue;
    2406                 :            :                         }
    2407                 :            :                 } else
    2408                 :          0 :                         k = TAKE_PTR(word);
    2409                 :            : 
    2410   [ #  #  #  # ]:          0 :                 if (!env_assignment_is_valid(k) && !env_name_is_valid(k)) {
    2411         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, 0,
    2412                 :            :                                    "Invalid environment name or assignment %s, ignoring: %s", lvalue, k);
    2413                 :          0 :                         continue;
    2414                 :            :                 }
    2415                 :            : 
    2416         [ #  # ]:          0 :                 if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
    2417                 :          0 :                         return log_oom();
    2418                 :            : 
    2419                 :          0 :                 n[nlen++] = TAKE_PTR(k);
    2420                 :          0 :                 n[nlen] = NULL;
    2421                 :            :         }
    2422                 :            : 
    2423         [ #  # ]:          0 :         if (n) {
    2424                 :          0 :                 r = strv_extend_strv(unsetenv, n, true);
    2425         [ #  # ]:          0 :                 if (r < 0)
    2426                 :          0 :                         return r;
    2427                 :            :         }
    2428                 :            : 
    2429                 :          0 :         return 0;
    2430                 :            : }
    2431                 :            : 
    2432                 :         12 : int config_parse_log_extra_fields(
    2433                 :            :                 const char *unit,
    2434                 :            :                 const char *filename,
    2435                 :            :                 unsigned line,
    2436                 :            :                 const char *section,
    2437                 :            :                 unsigned section_line,
    2438                 :            :                 const char *lvalue,
    2439                 :            :                 int ltype,
    2440                 :            :                 const char *rvalue,
    2441                 :            :                 void *data,
    2442                 :            :                 void *userdata) {
    2443                 :            : 
    2444                 :         12 :         ExecContext *c = data;
    2445                 :         12 :         Unit *u = userdata;
    2446                 :         12 :         const char *p = rvalue;
    2447                 :            :         int r;
    2448                 :            : 
    2449         [ -  + ]:         12 :         assert(filename);
    2450         [ -  + ]:         12 :         assert(lvalue);
    2451         [ -  + ]:         12 :         assert(rvalue);
    2452         [ -  + ]:         12 :         assert(c);
    2453                 :            : 
    2454         [ +  + ]:         12 :         if (isempty(rvalue)) {
    2455                 :          4 :                 exec_context_free_log_extra_fields(c);
    2456                 :          4 :                 return 0;
    2457                 :            :         }
    2458                 :            : 
    2459                 :         20 :         for (;;) {
    2460   [ +  +  +  +  :         40 :                 _cleanup_free_ char *word = NULL, *k = NULL;
                   +  + ]
    2461                 :            :                 struct iovec *t;
    2462                 :            :                 const char *eq;
    2463                 :            : 
    2464                 :         28 :                 r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
    2465         [ +  + ]:         28 :                 if (r == 0)
    2466                 :          8 :                         return 0;
    2467         [ -  + ]:         20 :                 if (r == -ENOMEM)
    2468                 :          0 :                         return log_oom();
    2469         [ -  + ]:         20 :                 if (r < 0) {
    2470         [ #  # ]:          0 :                         log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
    2471                 :          0 :                         return 0;
    2472                 :            :                 }
    2473                 :            : 
    2474                 :         20 :                 r = unit_full_printf(u, word, &k);
    2475         [ -  + ]:         20 :                 if (r < 0) {
    2476         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", word);
    2477                 :          0 :                         continue;
    2478                 :            :                 }
    2479                 :            : 
    2480                 :         20 :                 eq = strchr(k, '=');
    2481         [ +  + ]:         20 :                 if (!eq) {
    2482         [ +  - ]:          4 :                         log_syntax(unit, LOG_ERR, filename, line, 0, "Log field lacks '=' character, ignoring: %s", k);
    2483                 :          4 :                         continue;
    2484                 :            :                 }
    2485                 :            : 
    2486         [ -  + ]:         16 :                 if (!journal_field_valid(k, eq-k, false)) {
    2487         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, 0, "Log field name is invalid, ignoring: %s", k);
    2488                 :          0 :                         continue;
    2489                 :            :                 }
    2490                 :            : 
    2491                 :         16 :                 t = reallocarray(c->log_extra_fields, c->n_log_extra_fields+1, sizeof(struct iovec));
    2492         [ -  + ]:         16 :                 if (!t)
    2493                 :          0 :                         return log_oom();
    2494                 :            : 
    2495                 :         16 :                 c->log_extra_fields = t;
    2496                 :         16 :                 c->log_extra_fields[c->n_log_extra_fields++] = IOVEC_MAKE_STRING(k);
    2497                 :            : 
    2498                 :         16 :                 k = NULL;
    2499                 :            :         }
    2500                 :            : }
    2501                 :            : 
    2502                 :          0 : int config_parse_unit_condition_path(
    2503                 :            :                 const char *unit,
    2504                 :            :                 const char *filename,
    2505                 :            :                 unsigned line,
    2506                 :            :                 const char *section,
    2507                 :            :                 unsigned section_line,
    2508                 :            :                 const char *lvalue,
    2509                 :            :                 int ltype,
    2510                 :            :                 const char *rvalue,
    2511                 :            :                 void *data,
    2512                 :            :                 void *userdata) {
    2513                 :            : 
    2514                 :          0 :         _cleanup_free_ char *p = NULL;
    2515                 :          0 :         Condition **list = data, *c;
    2516                 :          0 :         ConditionType t = ltype;
    2517                 :            :         bool trigger, negate;
    2518                 :          0 :         Unit *u = userdata;
    2519                 :            :         int r;
    2520                 :            : 
    2521         [ #  # ]:          0 :         assert(filename);
    2522         [ #  # ]:          0 :         assert(lvalue);
    2523         [ #  # ]:          0 :         assert(rvalue);
    2524         [ #  # ]:          0 :         assert(data);
    2525                 :            : 
    2526         [ #  # ]:          0 :         if (isempty(rvalue)) {
    2527                 :            :                 /* Empty assignment resets the list */
    2528                 :          0 :                 *list = condition_free_list(*list);
    2529                 :          0 :                 return 0;
    2530                 :            :         }
    2531                 :            : 
    2532                 :          0 :         trigger = rvalue[0] == '|';
    2533         [ #  # ]:          0 :         if (trigger)
    2534                 :          0 :                 rvalue++;
    2535                 :            : 
    2536                 :          0 :         negate = rvalue[0] == '!';
    2537         [ #  # ]:          0 :         if (negate)
    2538                 :          0 :                 rvalue++;
    2539                 :            : 
    2540                 :          0 :         r = unit_full_printf(u, rvalue, &p);
    2541         [ #  # ]:          0 :         if (r < 0) {
    2542         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
    2543                 :          0 :                 return 0;
    2544                 :            :         }
    2545                 :            : 
    2546                 :          0 :         r = path_simplify_and_warn(p, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
    2547         [ #  # ]:          0 :         if (r < 0)
    2548                 :          0 :                 return 0;
    2549                 :            : 
    2550                 :          0 :         c = condition_new(t, p, trigger, negate);
    2551         [ #  # ]:          0 :         if (!c)
    2552                 :          0 :                 return log_oom();
    2553                 :            : 
    2554   [ #  #  #  # ]:          0 :         LIST_PREPEND(conditions, *list, c);
    2555                 :          0 :         return 0;
    2556                 :            : }
    2557                 :            : 
    2558                 :          0 : int config_parse_unit_condition_string(
    2559                 :            :                 const char *unit,
    2560                 :            :                 const char *filename,
    2561                 :            :                 unsigned line,
    2562                 :            :                 const char *section,
    2563                 :            :                 unsigned section_line,
    2564                 :            :                 const char *lvalue,
    2565                 :            :                 int ltype,
    2566                 :            :                 const char *rvalue,
    2567                 :            :                 void *data,
    2568                 :            :                 void *userdata) {
    2569                 :            : 
    2570                 :          0 :         _cleanup_free_ char *s = NULL;
    2571                 :          0 :         Condition **list = data, *c;
    2572                 :          0 :         ConditionType t = ltype;
    2573                 :            :         bool trigger, negate;
    2574                 :          0 :         Unit *u = userdata;
    2575                 :            :         int r;
    2576                 :            : 
    2577         [ #  # ]:          0 :         assert(filename);
    2578         [ #  # ]:          0 :         assert(lvalue);
    2579         [ #  # ]:          0 :         assert(rvalue);
    2580         [ #  # ]:          0 :         assert(data);
    2581                 :            : 
    2582         [ #  # ]:          0 :         if (isempty(rvalue)) {
    2583                 :            :                 /* Empty assignment resets the list */
    2584                 :          0 :                 *list = condition_free_list(*list);
    2585                 :          0 :                 return 0;
    2586                 :            :         }
    2587                 :            : 
    2588                 :          0 :         trigger = *rvalue == '|';
    2589         [ #  # ]:          0 :         if (trigger)
    2590                 :          0 :                 rvalue += 1 + strspn(rvalue + 1, WHITESPACE);
    2591                 :            : 
    2592                 :          0 :         negate = *rvalue == '!';
    2593         [ #  # ]:          0 :         if (negate)
    2594                 :          0 :                 rvalue += 1 + strspn(rvalue + 1, WHITESPACE);
    2595                 :            : 
    2596                 :          0 :         r = unit_full_printf(u, rvalue, &s);
    2597         [ #  # ]:          0 :         if (r < 0) {
    2598         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r,
    2599                 :            :                            "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
    2600                 :          0 :                 return 0;
    2601                 :            :         }
    2602                 :            : 
    2603                 :          0 :         c = condition_new(t, s, trigger, negate);
    2604         [ #  # ]:          0 :         if (!c)
    2605                 :          0 :                 return log_oom();
    2606                 :            : 
    2607   [ #  #  #  # ]:          0 :         LIST_PREPEND(conditions, *list, c);
    2608                 :          0 :         return 0;
    2609                 :            : }
    2610                 :            : 
    2611                 :          0 : int config_parse_unit_condition_null(
    2612                 :            :                 const char *unit,
    2613                 :            :                 const char *filename,
    2614                 :            :                 unsigned line,
    2615                 :            :                 const char *section,
    2616                 :            :                 unsigned section_line,
    2617                 :            :                 const char *lvalue,
    2618                 :            :                 int ltype,
    2619                 :            :                 const char *rvalue,
    2620                 :            :                 void *data,
    2621                 :            :                 void *userdata) {
    2622                 :            : 
    2623                 :          0 :         Condition **list = data, *c;
    2624                 :            :         bool trigger, negate;
    2625                 :            :         int b;
    2626                 :            : 
    2627         [ #  # ]:          0 :         assert(filename);
    2628         [ #  # ]:          0 :         assert(lvalue);
    2629         [ #  # ]:          0 :         assert(rvalue);
    2630         [ #  # ]:          0 :         assert(data);
    2631                 :            : 
    2632         [ #  # ]:          0 :         log_syntax(unit, LOG_WARNING, filename, line, 0, "%s= is deprecated, please do not use.", lvalue);
    2633                 :            : 
    2634         [ #  # ]:          0 :         if (isempty(rvalue)) {
    2635                 :            :                 /* Empty assignment resets the list */
    2636                 :          0 :                 *list = condition_free_list(*list);
    2637                 :          0 :                 return 0;
    2638                 :            :         }
    2639                 :            : 
    2640                 :          0 :         trigger = rvalue[0] == '|';
    2641         [ #  # ]:          0 :         if (trigger)
    2642                 :          0 :                 rvalue++;
    2643                 :            : 
    2644                 :          0 :         negate = rvalue[0] == '!';
    2645         [ #  # ]:          0 :         if (negate)
    2646                 :          0 :                 rvalue++;
    2647                 :            : 
    2648                 :          0 :         b = parse_boolean(rvalue);
    2649         [ #  # ]:          0 :         if (b < 0) {
    2650         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, b, "Failed to parse boolean value in condition, ignoring: %s", rvalue);
    2651                 :          0 :                 return 0;
    2652                 :            :         }
    2653                 :            : 
    2654         [ #  # ]:          0 :         if (!b)
    2655                 :          0 :                 negate = !negate;
    2656                 :            : 
    2657                 :          0 :         c = condition_new(CONDITION_NULL, NULL, trigger, negate);
    2658         [ #  # ]:          0 :         if (!c)
    2659                 :          0 :                 return log_oom();
    2660                 :            : 
    2661   [ #  #  #  # ]:          0 :         LIST_PREPEND(conditions, *list, c);
    2662                 :          0 :         return 0;
    2663                 :            : }
    2664                 :            : 
    2665                 :         44 : int config_parse_unit_requires_mounts_for(
    2666                 :            :                 const char *unit,
    2667                 :            :                 const char *filename,
    2668                 :            :                 unsigned line,
    2669                 :            :                 const char *section,
    2670                 :            :                 unsigned section_line,
    2671                 :            :                 const char *lvalue,
    2672                 :            :                 int ltype,
    2673                 :            :                 const char *rvalue,
    2674                 :            :                 void *data,
    2675                 :            :                 void *userdata) {
    2676                 :            : 
    2677                 :         44 :         const char *p = rvalue;
    2678                 :         44 :         Unit *u = userdata;
    2679                 :            :         int r;
    2680                 :            : 
    2681         [ -  + ]:         44 :         assert(filename);
    2682         [ -  + ]:         44 :         assert(lvalue);
    2683         [ -  + ]:         44 :         assert(rvalue);
    2684         [ -  + ]:         44 :         assert(data);
    2685                 :            : 
    2686                 :         88 :         for (;;) {
    2687   [ +  +  -  +  :        176 :                 _cleanup_free_ char *word = NULL, *resolved = NULL;
                   +  - ]
    2688                 :            : 
    2689                 :        132 :                 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
    2690         [ +  + ]:        132 :                 if (r == 0)
    2691                 :         44 :                         return 0;
    2692         [ -  + ]:         88 :                 if (r == -ENOMEM)
    2693                 :          0 :                         return log_oom();
    2694         [ -  + ]:         88 :                 if (r < 0) {
    2695         [ #  # ]:          0 :                         log_syntax(unit, LOG_WARNING, filename, line, r,
    2696                 :            :                                    "Invalid syntax, ignoring: %s", rvalue);
    2697                 :          0 :                         return 0;
    2698                 :            :                 }
    2699                 :            : 
    2700                 :         88 :                 r = unit_full_printf(u, word, &resolved);
    2701         [ -  + ]:         88 :                 if (r < 0) {
    2702         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", word);
    2703                 :          0 :                         continue;
    2704                 :            :                 }
    2705                 :            : 
    2706                 :         88 :                 r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
    2707         [ -  + ]:         88 :                 if (r < 0)
    2708                 :          0 :                         continue;
    2709                 :            : 
    2710                 :         88 :                 r = unit_require_mounts_for(u, resolved, UNIT_DEPENDENCY_FILE);
    2711         [ -  + ]:         88 :                 if (r < 0) {
    2712         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add required mount '%s', ignoring: %m", resolved);
    2713                 :          0 :                         continue;
    2714                 :            :                 }
    2715                 :            :         }
    2716                 :            : }
    2717                 :            : 
    2718                 :        176 : int config_parse_documentation(const char *unit,
    2719                 :            :                                const char *filename,
    2720                 :            :                                unsigned line,
    2721                 :            :                                const char *section,
    2722                 :            :                                unsigned section_line,
    2723                 :            :                                const char *lvalue,
    2724                 :            :                                int ltype,
    2725                 :            :                                const char *rvalue,
    2726                 :            :                                void *data,
    2727                 :            :                                void *userdata) {
    2728                 :            : 
    2729                 :        176 :         Unit *u = userdata;
    2730                 :            :         int r;
    2731                 :            :         char **a, **b;
    2732                 :            : 
    2733         [ -  + ]:        176 :         assert(filename);
    2734         [ -  + ]:        176 :         assert(lvalue);
    2735         [ -  + ]:        176 :         assert(rvalue);
    2736         [ -  + ]:        176 :         assert(u);
    2737                 :            : 
    2738         [ -  + ]:        176 :         if (isempty(rvalue)) {
    2739                 :            :                 /* Empty assignment resets the list */
    2740                 :          0 :                 u->documentation = strv_free(u->documentation);
    2741                 :          0 :                 return 0;
    2742                 :            :         }
    2743                 :            : 
    2744                 :        176 :         r = config_parse_unit_strv_printf(unit, filename, line, section, section_line, lvalue, ltype,
    2745                 :            :                                           rvalue, data, userdata);
    2746         [ -  + ]:        176 :         if (r < 0)
    2747                 :          0 :                 return r;
    2748                 :            : 
    2749   [ +  -  +  + ]:        364 :         for (a = b = u->documentation; a && *a; a++) {
    2750                 :            : 
    2751         [ +  - ]:        188 :                 if (documentation_url_is_valid(*a))
    2752                 :        188 :                         *(b++) = *a;
    2753                 :            :                 else {
    2754         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid URL, ignoring: %s", *a);
    2755                 :          0 :                         free(*a);
    2756                 :            :                 }
    2757                 :            :         }
    2758         [ +  - ]:        176 :         if (b)
    2759                 :        176 :                 *b = NULL;
    2760                 :            : 
    2761                 :        176 :         return r;
    2762                 :            : }
    2763                 :            : 
    2764                 :            : #if HAVE_SECCOMP
    2765                 :          0 : int config_parse_syscall_filter(
    2766                 :            :                 const char *unit,
    2767                 :            :                 const char *filename,
    2768                 :            :                 unsigned line,
    2769                 :            :                 const char *section,
    2770                 :            :                 unsigned section_line,
    2771                 :            :                 const char *lvalue,
    2772                 :            :                 int ltype,
    2773                 :            :                 const char *rvalue,
    2774                 :            :                 void *data,
    2775                 :            :                 void *userdata) {
    2776                 :            : 
    2777                 :          0 :         ExecContext *c = data;
    2778                 :          0 :         Unit *u = userdata;
    2779                 :          0 :         bool invert = false;
    2780                 :            :         const char *p;
    2781                 :            :         int r;
    2782                 :            : 
    2783         [ #  # ]:          0 :         assert(filename);
    2784         [ #  # ]:          0 :         assert(lvalue);
    2785         [ #  # ]:          0 :         assert(rvalue);
    2786         [ #  # ]:          0 :         assert(u);
    2787                 :            : 
    2788         [ #  # ]:          0 :         if (isempty(rvalue)) {
    2789                 :            :                 /* Empty assignment resets the list */
    2790                 :          0 :                 c->syscall_filter = hashmap_free(c->syscall_filter);
    2791                 :          0 :                 c->syscall_whitelist = false;
    2792                 :          0 :                 return 0;
    2793                 :            :         }
    2794                 :            : 
    2795         [ #  # ]:          0 :         if (rvalue[0] == '~') {
    2796                 :          0 :                 invert = true;
    2797                 :          0 :                 rvalue++;
    2798                 :            :         }
    2799                 :            : 
    2800         [ #  # ]:          0 :         if (!c->syscall_filter) {
    2801                 :          0 :                 c->syscall_filter = hashmap_new(NULL);
    2802         [ #  # ]:          0 :                 if (!c->syscall_filter)
    2803                 :          0 :                         return log_oom();
    2804                 :            : 
    2805         [ #  # ]:          0 :                 if (invert)
    2806                 :            :                         /* Allow everything but the ones listed */
    2807                 :          0 :                         c->syscall_whitelist = false;
    2808                 :            :                 else {
    2809                 :            :                         /* Allow nothing but the ones listed */
    2810                 :          0 :                         c->syscall_whitelist = true;
    2811                 :            : 
    2812                 :            :                         /* Accept default syscalls if we are on a whitelist */
    2813                 :          0 :                         r = seccomp_parse_syscall_filter(
    2814                 :            :                                         "@default", -1, c->syscall_filter,
    2815                 :            :                                         SECCOMP_PARSE_PERMISSIVE|SECCOMP_PARSE_WHITELIST,
    2816                 :            :                                         unit,
    2817                 :            :                                         NULL, 0);
    2818         [ #  # ]:          0 :                         if (r < 0)
    2819                 :          0 :                                 return r;
    2820                 :            :                 }
    2821                 :            :         }
    2822                 :            : 
    2823                 :          0 :         p = rvalue;
    2824                 :          0 :         for (;;) {
    2825   [ #  #  #  #  :          0 :                 _cleanup_free_ char *word = NULL, *name = NULL;
                   #  # ]
    2826                 :            :                 int num;
    2827                 :            : 
    2828                 :          0 :                 r = extract_first_word(&p, &word, NULL, 0);
    2829         [ #  # ]:          0 :                 if (r == 0)
    2830                 :          0 :                         return 0;
    2831         [ #  # ]:          0 :                 if (r == -ENOMEM)
    2832                 :          0 :                         return log_oom();
    2833         [ #  # ]:          0 :                 if (r < 0) {
    2834         [ #  # ]:          0 :                         log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
    2835                 :          0 :                         return 0;
    2836                 :            :                 }
    2837                 :            : 
    2838                 :          0 :                 r = parse_syscall_and_errno(word, &name, &num);
    2839         [ #  # ]:          0 :                 if (r < 0) {
    2840         [ #  # ]:          0 :                         log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse syscall:errno, ignoring: %s", word);
    2841                 :          0 :                         continue;
    2842                 :            :                 }
    2843                 :            : 
    2844                 :          0 :                 r = seccomp_parse_syscall_filter(
    2845                 :            :                                 name, num, c->syscall_filter,
    2846         [ #  # ]:          0 :                                 SECCOMP_PARSE_LOG|SECCOMP_PARSE_PERMISSIVE|
    2847                 :          0 :                                 (invert ? SECCOMP_PARSE_INVERT : 0)|
    2848                 :          0 :                                 (c->syscall_whitelist ? SECCOMP_PARSE_WHITELIST : 0),
    2849                 :            :                                 unit, filename, line);
    2850         [ #  # ]:          0 :                 if (r < 0)
    2851                 :          0 :                         return r;
    2852                 :            :         }
    2853                 :            : }
    2854                 :            : 
    2855                 :          0 : int config_parse_syscall_archs(
    2856                 :            :                 const char *unit,
    2857                 :            :                 const char *filename,
    2858                 :            :                 unsigned line,
    2859                 :            :                 const char *section,
    2860                 :            :                 unsigned section_line,
    2861                 :            :                 const char *lvalue,
    2862                 :            :                 int ltype,
    2863                 :            :                 const char *rvalue,
    2864                 :            :                 void *data,
    2865                 :            :                 void *userdata) {
    2866                 :            : 
    2867                 :          0 :         const char *p = rvalue;
    2868                 :          0 :         Set **archs = data;
    2869                 :            :         int r;
    2870                 :            : 
    2871         [ #  # ]:          0 :         if (isempty(rvalue)) {
    2872                 :          0 :                 *archs = set_free(*archs);
    2873                 :          0 :                 return 0;
    2874                 :            :         }
    2875                 :            : 
    2876                 :          0 :         r = set_ensure_allocated(archs, NULL);
    2877         [ #  # ]:          0 :         if (r < 0)
    2878                 :          0 :                 return log_oom();
    2879                 :            : 
    2880                 :          0 :         for (;;) {
    2881      [ #  #  # ]:          0 :                 _cleanup_free_ char *word = NULL;
    2882                 :            :                 uint32_t a;
    2883                 :            : 
    2884                 :          0 :                 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
    2885         [ #  # ]:          0 :                 if (r == 0)
    2886                 :          0 :                         return 0;
    2887         [ #  # ]:          0 :                 if (r == -ENOMEM)
    2888                 :          0 :                         return log_oom();
    2889         [ #  # ]:          0 :                 if (r < 0) {
    2890         [ #  # ]:          0 :                         log_syntax(unit, LOG_WARNING, filename, line, r,
    2891                 :            :                                    "Invalid syntax, ignoring: %s", rvalue);
    2892                 :          0 :                         return 0;
    2893                 :            :                 }
    2894                 :            : 
    2895                 :          0 :                 r = seccomp_arch_from_string(word, &a);
    2896         [ #  # ]:          0 :                 if (r < 0) {
    2897         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
    2898                 :            :                                    "Failed to parse system call architecture \"%s\", ignoring: %m", word);
    2899                 :          0 :                         continue;
    2900                 :            :                 }
    2901                 :            : 
    2902                 :          0 :                 r = set_put(*archs, UINT32_TO_PTR(a + 1));
    2903         [ #  # ]:          0 :                 if (r < 0)
    2904                 :          0 :                         return log_oom();
    2905                 :            :         }
    2906                 :            : }
    2907                 :            : 
    2908                 :          0 : int config_parse_syscall_errno(
    2909                 :            :                 const char *unit,
    2910                 :            :                 const char *filename,
    2911                 :            :                 unsigned line,
    2912                 :            :                 const char *section,
    2913                 :            :                 unsigned section_line,
    2914                 :            :                 const char *lvalue,
    2915                 :            :                 int ltype,
    2916                 :            :                 const char *rvalue,
    2917                 :            :                 void *data,
    2918                 :            :                 void *userdata) {
    2919                 :            : 
    2920                 :          0 :         ExecContext *c = data;
    2921                 :            :         int e;
    2922                 :            : 
    2923         [ #  # ]:          0 :         assert(filename);
    2924         [ #  # ]:          0 :         assert(lvalue);
    2925         [ #  # ]:          0 :         assert(rvalue);
    2926                 :            : 
    2927         [ #  # ]:          0 :         if (isempty(rvalue)) {
    2928                 :            :                 /* Empty assignment resets to KILL */
    2929                 :          0 :                 c->syscall_errno = 0;
    2930                 :          0 :                 return 0;
    2931                 :            :         }
    2932                 :            : 
    2933                 :          0 :         e = parse_errno(rvalue);
    2934         [ #  # ]:          0 :         if (e <= 0) {
    2935         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse error number, ignoring: %s", rvalue);
    2936                 :          0 :                 return 0;
    2937                 :            :         }
    2938                 :            : 
    2939                 :          0 :         c->syscall_errno = e;
    2940                 :          0 :         return 0;
    2941                 :            : }
    2942                 :            : 
    2943                 :          0 : int config_parse_address_families(
    2944                 :            :                 const char *unit,
    2945                 :            :                 const char *filename,
    2946                 :            :                 unsigned line,
    2947                 :            :                 const char *section,
    2948                 :            :                 unsigned section_line,
    2949                 :            :                 const char *lvalue,
    2950                 :            :                 int ltype,
    2951                 :            :                 const char *rvalue,
    2952                 :            :                 void *data,
    2953                 :            :                 void *userdata) {
    2954                 :            : 
    2955                 :          0 :         ExecContext *c = data;
    2956                 :          0 :         bool invert = false;
    2957                 :            :         const char *p;
    2958                 :            :         int r;
    2959                 :            : 
    2960         [ #  # ]:          0 :         assert(filename);
    2961         [ #  # ]:          0 :         assert(lvalue);
    2962         [ #  # ]:          0 :         assert(rvalue);
    2963                 :            : 
    2964         [ #  # ]:          0 :         if (isempty(rvalue)) {
    2965                 :            :                 /* Empty assignment resets the list */
    2966                 :          0 :                 c->address_families = set_free(c->address_families);
    2967                 :          0 :                 c->address_families_whitelist = false;
    2968                 :          0 :                 return 0;
    2969                 :            :         }
    2970                 :            : 
    2971         [ #  # ]:          0 :         if (rvalue[0] == '~') {
    2972                 :          0 :                 invert = true;
    2973                 :          0 :                 rvalue++;
    2974                 :            :         }
    2975                 :            : 
    2976         [ #  # ]:          0 :         if (!c->address_families) {
    2977                 :          0 :                 c->address_families = set_new(NULL);
    2978         [ #  # ]:          0 :                 if (!c->address_families)
    2979                 :          0 :                         return log_oom();
    2980                 :            : 
    2981                 :          0 :                 c->address_families_whitelist = !invert;
    2982                 :            :         }
    2983                 :            : 
    2984                 :          0 :         for (p = rvalue;;) {
    2985      [ #  #  # ]:          0 :                 _cleanup_free_ char *word = NULL;
    2986                 :            :                 int af;
    2987                 :            : 
    2988                 :          0 :                 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
    2989         [ #  # ]:          0 :                 if (r == 0)
    2990                 :          0 :                         return 0;
    2991         [ #  # ]:          0 :                 if (r == -ENOMEM)
    2992                 :          0 :                         return log_oom();
    2993         [ #  # ]:          0 :                 if (r < 0) {
    2994         [ #  # ]:          0 :                         log_syntax(unit, LOG_WARNING, filename, line, r,
    2995                 :            :                                    "Invalid syntax, ignoring: %s", rvalue);
    2996                 :          0 :                         return 0;
    2997                 :            :                 }
    2998                 :            : 
    2999                 :          0 :                 af = af_from_name(word);
    3000         [ #  # ]:          0 :                 if (af < 0) {
    3001         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, af,
    3002                 :            :                                    "Failed to parse address family, ignoring: %s", word);
    3003                 :          0 :                         continue;
    3004                 :            :                 }
    3005                 :            : 
    3006                 :            :                 /* If we previously wanted to forbid an address family and now
    3007                 :            :                  * we want to allow it, then just remove it from the list.
    3008                 :            :                  */
    3009         [ #  # ]:          0 :                 if (!invert == c->address_families_whitelist)  {
    3010                 :          0 :                         r = set_put(c->address_families, INT_TO_PTR(af));
    3011         [ #  # ]:          0 :                         if (r < 0)
    3012                 :          0 :                                 return log_oom();
    3013                 :            :                 } else
    3014                 :          0 :                         set_remove(c->address_families, INT_TO_PTR(af));
    3015                 :            :         }
    3016                 :            : }
    3017                 :            : 
    3018                 :          0 : int config_parse_restrict_namespaces(
    3019                 :            :                 const char *unit,
    3020                 :            :                 const char *filename,
    3021                 :            :                 unsigned line,
    3022                 :            :                 const char *section,
    3023                 :            :                 unsigned section_line,
    3024                 :            :                 const char *lvalue,
    3025                 :            :                 int ltype,
    3026                 :            :                 const char *rvalue,
    3027                 :            :                 void *data,
    3028                 :            :                 void *userdata) {
    3029                 :            : 
    3030                 :          0 :         ExecContext *c = data;
    3031                 :            :         unsigned long flags;
    3032                 :          0 :         bool invert = false;
    3033                 :            :         int r;
    3034                 :            : 
    3035         [ #  # ]:          0 :         if (isempty(rvalue)) {
    3036                 :            :                 /* Reset to the default. */
    3037                 :          0 :                 c->restrict_namespaces = NAMESPACE_FLAGS_INITIAL;
    3038                 :          0 :                 return 0;
    3039                 :            :         }
    3040                 :            : 
    3041                 :            :         /* Boolean parameter ignores the previous settings */
    3042                 :          0 :         r = parse_boolean(rvalue);
    3043         [ #  # ]:          0 :         if (r > 0) {
    3044                 :          0 :                 c->restrict_namespaces = 0;
    3045                 :          0 :                 return 0;
    3046         [ #  # ]:          0 :         } else if (r == 0) {
    3047                 :          0 :                 c->restrict_namespaces = NAMESPACE_FLAGS_ALL;
    3048                 :          0 :                 return 0;
    3049                 :            :         }
    3050                 :            : 
    3051         [ #  # ]:          0 :         if (rvalue[0] == '~') {
    3052                 :          0 :                 invert = true;
    3053                 :          0 :                 rvalue++;
    3054                 :            :         }
    3055                 :            : 
    3056                 :            :         /* Not a boolean argument, in this case it's a list of namespace types. */
    3057                 :          0 :         r = namespace_flags_from_string(rvalue, &flags);
    3058         [ #  # ]:          0 :         if (r < 0) {
    3059         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse namespace type string, ignoring: %s", rvalue);
    3060                 :          0 :                 return 0;
    3061                 :            :         }
    3062                 :            : 
    3063         [ #  # ]:          0 :         if (c->restrict_namespaces == NAMESPACE_FLAGS_INITIAL)
    3064                 :            :                 /* Initial assignment. Just set the value. */
    3065         [ #  # ]:          0 :                 c->restrict_namespaces = invert ? (~flags) & NAMESPACE_FLAGS_ALL : flags;
    3066                 :            :         else
    3067                 :            :                 /* Merge the value with the previous one. */
    3068         [ #  # ]:          0 :                 SET_FLAG(c->restrict_namespaces, flags, !invert);
    3069                 :            : 
    3070                 :          0 :         return 0;
    3071                 :            : }
    3072                 :            : #endif
    3073                 :            : 
    3074                 :         40 : int config_parse_unit_slice(
    3075                 :            :                 const char *unit,
    3076                 :            :                 const char *filename,
    3077                 :            :                 unsigned line,
    3078                 :            :                 const char *section,
    3079                 :            :                 unsigned section_line,
    3080                 :            :                 const char *lvalue,
    3081                 :            :                 int ltype,
    3082                 :            :                 const char *rvalue,
    3083                 :            :                 void *data,
    3084                 :            :                 void *userdata) {
    3085                 :            : 
    3086                 :         40 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
    3087                 :         40 :         _cleanup_free_ char *k = NULL;
    3088                 :         40 :         Unit *u = userdata, *slice = NULL;
    3089                 :            :         int r;
    3090                 :            : 
    3091         [ -  + ]:         40 :         assert(filename);
    3092         [ -  + ]:         40 :         assert(lvalue);
    3093         [ -  + ]:         40 :         assert(rvalue);
    3094         [ -  + ]:         40 :         assert(u);
    3095                 :            : 
    3096                 :         40 :         r = unit_name_printf(u, rvalue, &k);
    3097         [ -  + ]:         40 :         if (r < 0) {
    3098         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
    3099                 :          0 :                 return 0;
    3100                 :            :         }
    3101                 :            : 
    3102                 :         40 :         r = manager_load_unit(u->manager, k, NULL, &error, &slice);
    3103         [ -  + ]:         40 :         if (r < 0) {
    3104         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load slice unit %s, ignoring: %s", k, bus_error_message(&error, r));
    3105                 :          0 :                 return 0;
    3106                 :            :         }
    3107                 :            : 
    3108                 :         40 :         r = unit_set_slice(u, slice);
    3109         [ -  + ]:         40 :         if (r < 0) {
    3110         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to assign slice %s to unit %s, ignoring: %m", slice->id, u->id);
    3111                 :          0 :                 return 0;
    3112                 :            :         }
    3113                 :            : 
    3114                 :         40 :         return 0;
    3115                 :            : }
    3116                 :            : 
    3117                 :          0 : int config_parse_cpu_quota(
    3118                 :            :                 const char *unit,
    3119                 :            :                 const char *filename,
    3120                 :            :                 unsigned line,
    3121                 :            :                 const char *section,
    3122                 :            :                 unsigned section_line,
    3123                 :            :                 const char *lvalue,
    3124                 :            :                 int ltype,
    3125                 :            :                 const char *rvalue,
    3126                 :            :                 void *data,
    3127                 :            :                 void *userdata) {
    3128                 :            : 
    3129                 :          0 :         CGroupContext *c = data;
    3130                 :            :         int r;
    3131                 :            : 
    3132         [ #  # ]:          0 :         assert(filename);
    3133         [ #  # ]:          0 :         assert(lvalue);
    3134         [ #  # ]:          0 :         assert(rvalue);
    3135                 :            : 
    3136         [ #  # ]:          0 :         if (isempty(rvalue)) {
    3137                 :          0 :                 c->cpu_quota_per_sec_usec = USEC_INFINITY;
    3138                 :          0 :                 return 0;
    3139                 :            :         }
    3140                 :            : 
    3141                 :          0 :         r = parse_permille_unbounded(rvalue);
    3142         [ #  # ]:          0 :         if (r <= 0) {
    3143         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Invalid CPU quota '%s', ignoring.", rvalue);
    3144                 :          0 :                 return 0;
    3145                 :            :         }
    3146                 :            : 
    3147                 :          0 :         c->cpu_quota_per_sec_usec = ((usec_t) r * USEC_PER_SEC) / 1000U;
    3148                 :          0 :         return 0;
    3149                 :            : }
    3150                 :            : 
    3151                 :         32 : int config_parse_memory_limit(
    3152                 :            :                 const char *unit,
    3153                 :            :                 const char *filename,
    3154                 :            :                 unsigned line,
    3155                 :            :                 const char *section,
    3156                 :            :                 unsigned section_line,
    3157                 :            :                 const char *lvalue,
    3158                 :            :                 int ltype,
    3159                 :            :                 const char *rvalue,
    3160                 :            :                 void *data,
    3161                 :            :                 void *userdata) {
    3162                 :            : 
    3163                 :         32 :         CGroupContext *c = data;
    3164                 :         32 :         uint64_t bytes = CGROUP_LIMIT_MAX;
    3165                 :            :         int r;
    3166                 :            : 
    3167   [ +  +  +  - ]:         32 :         if (!isempty(rvalue) && !streq(rvalue, "infinity")) {
    3168                 :            : 
    3169                 :         28 :                 r = parse_permille(rvalue);
    3170         [ +  - ]:         28 :                 if (r < 0) {
    3171                 :         28 :                         r = parse_size(rvalue, 1024, &bytes);
    3172         [ -  + ]:         28 :                         if (r < 0) {
    3173         [ #  # ]:          0 :                                 log_syntax(unit, LOG_ERR, filename, line, r, "Invalid memory limit '%s', ignoring: %m", rvalue);
    3174                 :          0 :                                 return 0;
    3175                 :            :                         }
    3176                 :            :                 } else
    3177                 :          0 :                         bytes = physical_memory_scale(r, 1000U);
    3178                 :            : 
    3179         [ +  - ]:         28 :                 if (bytes >= UINT64_MAX ||
    3180   [ +  +  -  + ]:         28 :                     (bytes <= 0 && !STR_IN_SET(lvalue, "MemorySwapMax", "MemoryLow", "MemoryMin", "DefaultMemoryLow", "DefaultMemoryMin"))) {
    3181         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, 0, "Memory limit '%s' out of range, ignoring.", rvalue);
    3182                 :          0 :                         return 0;
    3183                 :            :                 }
    3184                 :            :         }
    3185                 :            : 
    3186         [ +  + ]:         32 :         if (streq(lvalue, "DefaultMemoryLow")) {
    3187                 :         16 :                 c->default_memory_low_set = true;
    3188         [ +  + ]:         16 :                 if (isempty(rvalue))
    3189                 :          4 :                         c->default_memory_low = CGROUP_LIMIT_MIN;
    3190                 :            :                 else
    3191                 :         12 :                         c->default_memory_low = bytes;
    3192         [ -  + ]:         16 :         } else if (streq(lvalue, "DefaultMemoryMin")) {
    3193                 :          0 :                 c->default_memory_min_set = true;
    3194         [ #  # ]:          0 :                 if (isempty(rvalue))
    3195                 :          0 :                         c->default_memory_min = CGROUP_LIMIT_MIN;
    3196                 :            :                 else
    3197                 :          0 :                         c->default_memory_min = bytes;
    3198         [ -  + ]:         16 :         } else if (streq(lvalue, "MemoryMin")) {
    3199                 :          0 :                 c->memory_min = bytes;
    3200                 :          0 :                 c->memory_min_set = true;
    3201         [ +  + ]:         16 :         } else if (streq(lvalue, "MemoryLow")) {
    3202                 :         12 :                 c->memory_low = bytes;
    3203                 :         12 :                 c->memory_low_set = true;
    3204         [ -  + ]:          4 :         } else if (streq(lvalue, "MemoryHigh"))
    3205                 :          0 :                 c->memory_high = bytes;
    3206         [ -  + ]:          4 :         else if (streq(lvalue, "MemoryMax"))
    3207                 :          0 :                 c->memory_max = bytes;
    3208         [ -  + ]:          4 :         else if (streq(lvalue, "MemorySwapMax"))
    3209                 :          0 :                 c->memory_swap_max = bytes;
    3210         [ +  - ]:          4 :         else if (streq(lvalue, "MemoryLimit"))
    3211                 :          4 :                 c->memory_limit = bytes;
    3212                 :            :         else
    3213                 :          0 :                 return -EINVAL;
    3214                 :            : 
    3215                 :         32 :         return 0;
    3216                 :            : }
    3217                 :            : 
    3218                 :          0 : int config_parse_tasks_max(
    3219                 :            :                 const char *unit,
    3220                 :            :                 const char *filename,
    3221                 :            :                 unsigned line,
    3222                 :            :                 const char *section,
    3223                 :            :                 unsigned section_line,
    3224                 :            :                 const char *lvalue,
    3225                 :            :                 int ltype,
    3226                 :            :                 const char *rvalue,
    3227                 :            :                 void *data,
    3228                 :            :                 void *userdata) {
    3229                 :            : 
    3230                 :          0 :         uint64_t *tasks_max = data, v;
    3231                 :          0 :         Unit *u = userdata;
    3232                 :            :         int r;
    3233                 :            : 
    3234         [ #  # ]:          0 :         if (isempty(rvalue)) {
    3235         [ #  # ]:          0 :                 *tasks_max = u ? u->manager->default_tasks_max : UINT64_MAX;
    3236                 :          0 :                 return 0;
    3237                 :            :         }
    3238                 :            : 
    3239         [ #  # ]:          0 :         if (streq(rvalue, "infinity")) {
    3240                 :          0 :                 *tasks_max = CGROUP_LIMIT_MAX;
    3241                 :          0 :                 return 0;
    3242                 :            :         }
    3243                 :            : 
    3244                 :          0 :         r = parse_permille(rvalue);
    3245         [ #  # ]:          0 :         if (r < 0) {
    3246                 :          0 :                 r = safe_atou64(rvalue, &v);
    3247         [ #  # ]:          0 :                 if (r < 0) {
    3248         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Invalid maximum tasks value '%s', ignoring: %m", rvalue);
    3249                 :          0 :                         return 0;
    3250                 :            :                 }
    3251                 :            :         } else
    3252                 :          0 :                 v = system_tasks_max_scale(r, 1000U);
    3253                 :            : 
    3254   [ #  #  #  # ]:          0 :         if (v <= 0 || v >= UINT64_MAX) {
    3255         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Maximum tasks value '%s' out of range, ignoring.", rvalue);
    3256                 :          0 :                 return 0;
    3257                 :            :         }
    3258                 :            : 
    3259                 :          0 :         *tasks_max = v;
    3260                 :          0 :         return 0;
    3261                 :            : }
    3262                 :            : 
    3263                 :          0 : int config_parse_delegate(
    3264                 :            :                 const char *unit,
    3265                 :            :                 const char *filename,
    3266                 :            :                 unsigned line,
    3267                 :            :                 const char *section,
    3268                 :            :                 unsigned section_line,
    3269                 :            :                 const char *lvalue,
    3270                 :            :                 int ltype,
    3271                 :            :                 const char *rvalue,
    3272                 :            :                 void *data,
    3273                 :            :                 void *userdata) {
    3274                 :            : 
    3275                 :          0 :         CGroupContext *c = data;
    3276                 :            :         UnitType t;
    3277                 :            :         int r;
    3278                 :            : 
    3279                 :          0 :         t = unit_name_to_type(unit);
    3280         [ #  # ]:          0 :         assert(t != _UNIT_TYPE_INVALID);
    3281                 :            : 
    3282         [ #  # ]:          0 :         if (!unit_vtable[t]->can_delegate) {
    3283         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Delegate= setting not supported for this unit type, ignoring.");
    3284                 :          0 :                 return 0;
    3285                 :            :         }
    3286                 :            : 
    3287                 :            :         /* We either accept a boolean value, which may be used to turn on delegation for all controllers, or turn it
    3288                 :            :          * off for all. Or it takes a list of controller names, in which case we add the specified controllers to the
    3289                 :            :          * mask to delegate. */
    3290                 :            : 
    3291         [ #  # ]:          0 :         if (isempty(rvalue)) {
    3292                 :            :                 /* An empty string resets controllers and set Delegate=yes. */
    3293                 :          0 :                 c->delegate = true;
    3294                 :          0 :                 c->delegate_controllers = 0;
    3295                 :          0 :                 return 0;
    3296                 :            :         }
    3297                 :            : 
    3298                 :          0 :         r = parse_boolean(rvalue);
    3299         [ #  # ]:          0 :         if (r < 0) {
    3300                 :          0 :                 const char *p = rvalue;
    3301                 :          0 :                 CGroupMask mask = 0;
    3302                 :            : 
    3303                 :          0 :                 for (;;) {
    3304   [ #  #  #  # ]:          0 :                         _cleanup_free_ char *word = NULL;
    3305                 :            :                         CGroupController cc;
    3306                 :            : 
    3307                 :          0 :                         r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
    3308         [ #  # ]:          0 :                         if (r == 0)
    3309                 :          0 :                                 break;
    3310         [ #  # ]:          0 :                         if (r == -ENOMEM)
    3311                 :          0 :                                 return log_oom();
    3312         [ #  # ]:          0 :                         if (r < 0) {
    3313         [ #  # ]:          0 :                                 log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
    3314                 :          0 :                                 return 0;
    3315                 :            :                         }
    3316                 :            : 
    3317                 :          0 :                         cc = cgroup_controller_from_string(word);
    3318         [ #  # ]:          0 :                         if (cc < 0) {
    3319         [ #  # ]:          0 :                                 log_syntax(unit, LOG_ERR, filename, line, r, "Invalid controller name '%s', ignoring", word);
    3320                 :          0 :                                 continue;
    3321                 :            :                         }
    3322                 :            : 
    3323                 :          0 :                         mask |= CGROUP_CONTROLLER_TO_MASK(cc);
    3324                 :            :                 }
    3325                 :            : 
    3326                 :          0 :                 c->delegate = true;
    3327                 :          0 :                 c->delegate_controllers |= mask;
    3328                 :            : 
    3329         [ #  # ]:          0 :         } else if (r > 0) {
    3330                 :          0 :                 c->delegate = true;
    3331                 :          0 :                 c->delegate_controllers = _CGROUP_MASK_ALL;
    3332                 :            :         } else {
    3333                 :          0 :                 c->delegate = false;
    3334                 :          0 :                 c->delegate_controllers = 0;
    3335                 :            :         }
    3336                 :            : 
    3337                 :          0 :         return 0;
    3338                 :            : }
    3339                 :            : 
    3340                 :          0 : int config_parse_device_allow(
    3341                 :            :                 const char *unit,
    3342                 :            :                 const char *filename,
    3343                 :            :                 unsigned line,
    3344                 :            :                 const char *section,
    3345                 :            :                 unsigned section_line,
    3346                 :            :                 const char *lvalue,
    3347                 :            :                 int ltype,
    3348                 :            :                 const char *rvalue,
    3349                 :            :                 void *data,
    3350                 :            :                 void *userdata) {
    3351                 :            : 
    3352                 :          0 :         _cleanup_free_ char *path = NULL, *resolved = NULL;
    3353                 :          0 :         CGroupContext *c = data;
    3354                 :          0 :         const char *p = rvalue;
    3355                 :            :         int r;
    3356                 :            : 
    3357         [ #  # ]:          0 :         if (isempty(rvalue)) {
    3358         [ #  # ]:          0 :                 while (c->device_allow)
    3359                 :          0 :                         cgroup_context_free_device_allow(c, c->device_allow);
    3360                 :            : 
    3361                 :          0 :                 return 0;
    3362                 :            :         }
    3363                 :            : 
    3364                 :          0 :         r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE);
    3365         [ #  # ]:          0 :         if (r == -ENOMEM)
    3366                 :          0 :                 return log_oom();
    3367         [ #  # ]:          0 :         if (r < 0) {
    3368         [ #  # ]:          0 :                 log_syntax(unit, LOG_WARNING, filename, line, r,
    3369                 :            :                            "Invalid syntax, ignoring: %s", rvalue);
    3370                 :          0 :                 return 0;
    3371                 :            :         }
    3372         [ #  # ]:          0 :         if (r == 0) {
    3373         [ #  # ]:          0 :                 log_syntax(unit, LOG_WARNING, filename, line, 0,
    3374                 :            :                            "Failed to extract device path and rights from '%s', ignoring.", rvalue);
    3375                 :          0 :                 return 0;
    3376                 :            :         }
    3377                 :            : 
    3378                 :          0 :         r = unit_full_printf(userdata, path, &resolved);
    3379         [ #  # ]:          0 :         if (r < 0) {
    3380         [ #  # ]:          0 :                 log_syntax(unit, LOG_WARNING, filename, line, r,
    3381                 :            :                            "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
    3382                 :          0 :                 return 0;
    3383                 :            :         }
    3384                 :            : 
    3385   [ #  #  #  #  :          0 :         if (!STARTSWITH_SET(resolved, "block-", "char-")) {
             #  #  #  # ]
    3386                 :            : 
    3387                 :          0 :                 r = path_simplify_and_warn(resolved, 0, unit, filename, line, lvalue);
    3388         [ #  # ]:          0 :                 if (r < 0)
    3389                 :          0 :                         return 0;
    3390                 :            : 
    3391         [ #  # ]:          0 :                 if (!valid_device_node_path(resolved)) {
    3392         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s', ignoring.", resolved);
    3393                 :          0 :                         return 0;
    3394                 :            :                 }
    3395                 :            :         }
    3396                 :            : 
    3397   [ #  #  #  # ]:          0 :         if (!isempty(p) && !in_charset(p, "rwm")) {
    3398         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device rights '%s', ignoring.", p);
    3399                 :          0 :                 return 0;
    3400                 :            :         }
    3401                 :            : 
    3402                 :          0 :         return cgroup_add_device_allow(c, resolved, p);
    3403                 :            : }
    3404                 :            : 
    3405                 :          0 : int config_parse_io_device_weight(
    3406                 :            :                 const char *unit,
    3407                 :            :                 const char *filename,
    3408                 :            :                 unsigned line,
    3409                 :            :                 const char *section,
    3410                 :            :                 unsigned section_line,
    3411                 :            :                 const char *lvalue,
    3412                 :            :                 int ltype,
    3413                 :            :                 const char *rvalue,
    3414                 :            :                 void *data,
    3415                 :            :                 void *userdata) {
    3416                 :            : 
    3417                 :          0 :         _cleanup_free_ char *path = NULL, *resolved = NULL;
    3418                 :            :         CGroupIODeviceWeight *w;
    3419                 :          0 :         CGroupContext *c = data;
    3420                 :          0 :         const char *p = rvalue;
    3421                 :            :         uint64_t u;
    3422                 :            :         int r;
    3423                 :            : 
    3424         [ #  # ]:          0 :         assert(filename);
    3425         [ #  # ]:          0 :         assert(lvalue);
    3426         [ #  # ]:          0 :         assert(rvalue);
    3427                 :            : 
    3428         [ #  # ]:          0 :         if (isempty(rvalue)) {
    3429         [ #  # ]:          0 :                 while (c->io_device_weights)
    3430                 :          0 :                         cgroup_context_free_io_device_weight(c, c->io_device_weights);
    3431                 :            : 
    3432                 :          0 :                 return 0;
    3433                 :            :         }
    3434                 :            : 
    3435                 :          0 :         r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE);
    3436         [ #  # ]:          0 :         if (r == -ENOMEM)
    3437                 :          0 :                 return log_oom();
    3438         [ #  # ]:          0 :         if (r < 0) {
    3439         [ #  # ]:          0 :                 log_syntax(unit, LOG_WARNING, filename, line, r,
    3440                 :            :                            "Invalid syntax, ignoring: %s", rvalue);
    3441                 :          0 :                 return 0;
    3442                 :            :         }
    3443   [ #  #  #  # ]:          0 :         if (r == 0 || isempty(p)) {
    3444         [ #  # ]:          0 :                 log_syntax(unit, LOG_WARNING, filename, line, 0,
    3445                 :            :                            "Failed to extract device path and weight from '%s', ignoring.", rvalue);
    3446                 :          0 :                 return 0;
    3447                 :            :         }
    3448                 :            : 
    3449                 :          0 :         r = unit_full_printf(userdata, path, &resolved);
    3450         [ #  # ]:          0 :         if (r < 0) {
    3451         [ #  # ]:          0 :                 log_syntax(unit, LOG_WARNING, filename, line, r,
    3452                 :            :                            "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
    3453                 :          0 :                 return 0;
    3454                 :            :         }
    3455                 :            : 
    3456                 :          0 :         r = path_simplify_and_warn(resolved, 0, unit, filename, line, lvalue);
    3457         [ #  # ]:          0 :         if (r < 0)
    3458                 :          0 :                 return 0;
    3459                 :            : 
    3460                 :          0 :         r = cg_weight_parse(p, &u);
    3461         [ #  # ]:          0 :         if (r < 0) {
    3462         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "IO weight '%s' invalid, ignoring: %m", p);
    3463                 :          0 :                 return 0;
    3464                 :            :         }
    3465                 :            : 
    3466         [ #  # ]:          0 :         assert(u != CGROUP_WEIGHT_INVALID);
    3467                 :            : 
    3468                 :          0 :         w = new0(CGroupIODeviceWeight, 1);
    3469         [ #  # ]:          0 :         if (!w)
    3470                 :          0 :                 return log_oom();
    3471                 :            : 
    3472                 :          0 :         w->path = TAKE_PTR(resolved);
    3473                 :          0 :         w->weight = u;
    3474                 :            : 
    3475   [ #  #  #  # ]:          0 :         LIST_PREPEND(device_weights, c->io_device_weights, w);
    3476                 :          0 :         return 0;
    3477                 :            : }
    3478                 :            : 
    3479                 :          0 : int config_parse_io_device_latency(
    3480                 :            :                 const char *unit,
    3481                 :            :                 const char *filename,
    3482                 :            :                 unsigned line,
    3483                 :            :                 const char *section,
    3484                 :            :                 unsigned section_line,
    3485                 :            :                 const char *lvalue,
    3486                 :            :                 int ltype,
    3487                 :            :                 const char *rvalue,
    3488                 :            :                 void *data,
    3489                 :            :                 void *userdata) {
    3490                 :            : 
    3491                 :          0 :         _cleanup_free_ char *path = NULL, *resolved = NULL;
    3492                 :            :         CGroupIODeviceLatency *l;
    3493                 :          0 :         CGroupContext *c = data;
    3494                 :          0 :         const char *p = rvalue;
    3495                 :            :         usec_t usec;
    3496                 :            :         int r;
    3497                 :            : 
    3498         [ #  # ]:          0 :         assert(filename);
    3499         [ #  # ]:          0 :         assert(lvalue);
    3500         [ #  # ]:          0 :         assert(rvalue);
    3501                 :            : 
    3502         [ #  # ]:          0 :         if (isempty(rvalue)) {
    3503         [ #  # ]:          0 :                 while (c->io_device_latencies)
    3504                 :          0 :                         cgroup_context_free_io_device_latency(c, c->io_device_latencies);
    3505                 :            : 
    3506                 :          0 :                 return 0;
    3507                 :            :         }
    3508                 :            : 
    3509                 :          0 :         r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE);
    3510         [ #  # ]:          0 :         if (r == -ENOMEM)
    3511                 :          0 :                 return log_oom();
    3512         [ #  # ]:          0 :         if (r < 0) {
    3513         [ #  # ]:          0 :                 log_syntax(unit, LOG_WARNING, filename, line, r,
    3514                 :            :                            "Invalid syntax, ignoring: %s", rvalue);
    3515                 :          0 :                 return 0;
    3516                 :            :         }
    3517   [ #  #  #  # ]:          0 :         if (r == 0 || isempty(p)) {
    3518         [ #  # ]:          0 :                 log_syntax(unit, LOG_WARNING, filename, line, 0,
    3519                 :            :                            "Failed to extract device path and latency from '%s', ignoring.", rvalue);
    3520                 :          0 :                 return 0;
    3521                 :            :         }
    3522                 :            : 
    3523                 :          0 :         r = unit_full_printf(userdata, path, &resolved);
    3524         [ #  # ]:          0 :         if (r < 0) {
    3525         [ #  # ]:          0 :                 log_syntax(unit, LOG_WARNING, filename, line, r,
    3526                 :            :                            "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
    3527                 :          0 :                 return 0;
    3528                 :            :         }
    3529                 :            : 
    3530                 :          0 :         r = path_simplify_and_warn(resolved, 0, unit, filename, line, lvalue);
    3531         [ #  # ]:          0 :         if (r < 0)
    3532                 :          0 :                 return 0;
    3533                 :            : 
    3534         [ #  # ]:          0 :         if (parse_sec(p, &usec) < 0) {
    3535         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse timer value, ignoring: %s", p);
    3536                 :          0 :                 return 0;
    3537                 :            :         }
    3538                 :            : 
    3539                 :          0 :         l = new0(CGroupIODeviceLatency, 1);
    3540         [ #  # ]:          0 :         if (!l)
    3541                 :          0 :                 return log_oom();
    3542                 :            : 
    3543                 :          0 :         l->path = TAKE_PTR(resolved);
    3544                 :          0 :         l->target_usec = usec;
    3545                 :            : 
    3546   [ #  #  #  # ]:          0 :         LIST_PREPEND(device_latencies, c->io_device_latencies, l);
    3547                 :          0 :         return 0;
    3548                 :            : }
    3549                 :            : 
    3550                 :          0 : int config_parse_io_limit(
    3551                 :            :                 const char *unit,
    3552                 :            :                 const char *filename,
    3553                 :            :                 unsigned line,
    3554                 :            :                 const char *section,
    3555                 :            :                 unsigned section_line,
    3556                 :            :                 const char *lvalue,
    3557                 :            :                 int ltype,
    3558                 :            :                 const char *rvalue,
    3559                 :            :                 void *data,
    3560                 :            :                 void *userdata) {
    3561                 :            : 
    3562                 :          0 :         _cleanup_free_ char *path = NULL, *resolved = NULL;
    3563                 :          0 :         CGroupIODeviceLimit *l = NULL, *t;
    3564                 :          0 :         CGroupContext *c = data;
    3565                 :            :         CGroupIOLimitType type;
    3566                 :          0 :         const char *p = rvalue;
    3567                 :            :         uint64_t num;
    3568                 :            :         int r;
    3569                 :            : 
    3570         [ #  # ]:          0 :         assert(filename);
    3571         [ #  # ]:          0 :         assert(lvalue);
    3572         [ #  # ]:          0 :         assert(rvalue);
    3573                 :            : 
    3574                 :          0 :         type = cgroup_io_limit_type_from_string(lvalue);
    3575         [ #  # ]:          0 :         assert(type >= 0);
    3576                 :            : 
    3577         [ #  # ]:          0 :         if (isempty(rvalue)) {
    3578         [ #  # ]:          0 :                 LIST_FOREACH(device_limits, l, c->io_device_limits)
    3579                 :          0 :                         l->limits[type] = cgroup_io_limit_defaults[type];
    3580                 :          0 :                 return 0;
    3581                 :            :         }
    3582                 :            : 
    3583                 :          0 :         r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE);
    3584         [ #  # ]:          0 :         if (r == -ENOMEM)
    3585                 :          0 :                 return log_oom();
    3586         [ #  # ]:          0 :         if (r < 0) {
    3587         [ #  # ]:          0 :                 log_syntax(unit, LOG_WARNING, filename, line, r,
    3588                 :            :                            "Invalid syntax, ignoring: %s", rvalue);
    3589                 :          0 :                 return 0;
    3590                 :            :         }
    3591   [ #  #  #  # ]:          0 :         if (r == 0 || isempty(p)) {
    3592         [ #  # ]:          0 :                 log_syntax(unit, LOG_WARNING, filename, line, 0,
    3593                 :            :                            "Failed to extract device node and bandwidth from '%s', ignoring.", rvalue);
    3594                 :          0 :                 return 0;
    3595                 :            :         }
    3596                 :            : 
    3597                 :          0 :         r = unit_full_printf(userdata, path, &resolved);
    3598         [ #  # ]:          0 :         if (r < 0) {
    3599         [ #  # ]:          0 :                 log_syntax(unit, LOG_WARNING, filename, line, r,
    3600                 :            :                            "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
    3601                 :          0 :                 return 0;
    3602                 :            :         }
    3603                 :            : 
    3604                 :          0 :         r = path_simplify_and_warn(resolved, 0, unit, filename, line, lvalue);
    3605         [ #  # ]:          0 :         if (r < 0)
    3606                 :          0 :                 return 0;
    3607                 :            : 
    3608         [ #  # ]:          0 :         if (streq("infinity", p))
    3609                 :          0 :                 num = CGROUP_LIMIT_MAX;
    3610                 :            :         else {
    3611                 :          0 :                 r = parse_size(p, 1000, &num);
    3612   [ #  #  #  # ]:          0 :                 if (r < 0 || num <= 0) {
    3613         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid IO limit '%s', ignoring.", p);
    3614                 :          0 :                         return 0;
    3615                 :            :                 }
    3616                 :            :         }
    3617                 :            : 
    3618         [ #  # ]:          0 :         LIST_FOREACH(device_limits, t, c->io_device_limits) {
    3619         [ #  # ]:          0 :                 if (path_equal(resolved, t->path)) {
    3620                 :          0 :                         l = t;
    3621                 :          0 :                         break;
    3622                 :            :                 }
    3623                 :            :         }
    3624                 :            : 
    3625         [ #  # ]:          0 :         if (!l) {
    3626                 :            :                 CGroupIOLimitType ttype;
    3627                 :            : 
    3628                 :          0 :                 l = new0(CGroupIODeviceLimit, 1);
    3629         [ #  # ]:          0 :                 if (!l)
    3630                 :          0 :                         return log_oom();
    3631                 :            : 
    3632                 :          0 :                 l->path = TAKE_PTR(resolved);
    3633         [ #  # ]:          0 :                 for (ttype = 0; ttype < _CGROUP_IO_LIMIT_TYPE_MAX; ttype++)
    3634                 :          0 :                         l->limits[ttype] = cgroup_io_limit_defaults[ttype];
    3635                 :            : 
    3636   [ #  #  #  # ]:          0 :                 LIST_PREPEND(device_limits, c->io_device_limits, l);
    3637                 :            :         }
    3638                 :            : 
    3639                 :          0 :         l->limits[type] = num;
    3640                 :            : 
    3641                 :          0 :         return 0;
    3642                 :            : }
    3643                 :            : 
    3644                 :          0 : int config_parse_blockio_device_weight(
    3645                 :            :                 const char *unit,
    3646                 :            :                 const char *filename,
    3647                 :            :                 unsigned line,
    3648                 :            :                 const char *section,
    3649                 :            :                 unsigned section_line,
    3650                 :            :                 const char *lvalue,
    3651                 :            :                 int ltype,
    3652                 :            :                 const char *rvalue,
    3653                 :            :                 void *data,
    3654                 :            :                 void *userdata) {
    3655                 :            : 
    3656                 :          0 :         _cleanup_free_ char *path = NULL, *resolved = NULL;
    3657                 :            :         CGroupBlockIODeviceWeight *w;
    3658                 :          0 :         CGroupContext *c = data;
    3659                 :          0 :         const char *p = rvalue;
    3660                 :            :         uint64_t u;
    3661                 :            :         int r;
    3662                 :            : 
    3663         [ #  # ]:          0 :         assert(filename);
    3664         [ #  # ]:          0 :         assert(lvalue);
    3665         [ #  # ]:          0 :         assert(rvalue);
    3666                 :            : 
    3667         [ #  # ]:          0 :         if (isempty(rvalue)) {
    3668         [ #  # ]:          0 :                 while (c->blockio_device_weights)
    3669                 :          0 :                         cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
    3670                 :            : 
    3671                 :          0 :                 return 0;
    3672                 :            :         }
    3673                 :            : 
    3674                 :          0 :         r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE);
    3675         [ #  # ]:          0 :         if (r == -ENOMEM)
    3676                 :          0 :                 return log_oom();
    3677         [ #  # ]:          0 :         if (r < 0) {
    3678         [ #  # ]:          0 :                 log_syntax(unit, LOG_WARNING, filename, line, r,
    3679                 :            :                            "Invalid syntax, ignoring: %s", rvalue);
    3680                 :          0 :                 return 0;
    3681                 :            :         }
    3682   [ #  #  #  # ]:          0 :         if (r == 0 || isempty(p)) {
    3683         [ #  # ]:          0 :                 log_syntax(unit, LOG_WARNING, filename, line, 0,
    3684                 :            :                            "Failed to extract device node and weight from '%s', ignoring.", rvalue);
    3685                 :          0 :                 return 0;
    3686                 :            :         }
    3687                 :            : 
    3688                 :          0 :         r = unit_full_printf(userdata, path, &resolved);
    3689         [ #  # ]:          0 :         if (r < 0) {
    3690         [ #  # ]:          0 :                 log_syntax(unit, LOG_WARNING, filename, line, r,
    3691                 :            :                            "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
    3692                 :          0 :                 return 0;
    3693                 :            :         }
    3694                 :            : 
    3695                 :          0 :         r = path_simplify_and_warn(resolved, 0, unit, filename, line, lvalue);
    3696         [ #  # ]:          0 :         if (r < 0)
    3697                 :          0 :                 return 0;
    3698                 :            : 
    3699                 :          0 :         r = cg_blkio_weight_parse(p, &u);
    3700         [ #  # ]:          0 :         if (r < 0) {
    3701         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Invalid block IO weight '%s', ignoring: %m", p);
    3702                 :          0 :                 return 0;
    3703                 :            :         }
    3704                 :            : 
    3705         [ #  # ]:          0 :         assert(u != CGROUP_BLKIO_WEIGHT_INVALID);
    3706                 :            : 
    3707                 :          0 :         w = new0(CGroupBlockIODeviceWeight, 1);
    3708         [ #  # ]:          0 :         if (!w)
    3709                 :          0 :                 return log_oom();
    3710                 :            : 
    3711                 :          0 :         w->path = TAKE_PTR(resolved);
    3712                 :          0 :         w->weight = u;
    3713                 :            : 
    3714   [ #  #  #  # ]:          0 :         LIST_PREPEND(device_weights, c->blockio_device_weights, w);
    3715                 :          0 :         return 0;
    3716                 :            : }
    3717                 :            : 
    3718                 :          0 : int config_parse_blockio_bandwidth(
    3719                 :            :                 const char *unit,
    3720                 :            :                 const char *filename,
    3721                 :            :                 unsigned line,
    3722                 :            :                 const char *section,
    3723                 :            :                 unsigned section_line,
    3724                 :            :                 const char *lvalue,
    3725                 :            :                 int ltype,
    3726                 :            :                 const char *rvalue,
    3727                 :            :                 void *data,
    3728                 :            :                 void *userdata) {
    3729                 :            : 
    3730                 :          0 :         _cleanup_free_ char *path = NULL, *resolved = NULL;
    3731                 :          0 :         CGroupBlockIODeviceBandwidth *b = NULL, *t;
    3732                 :          0 :         CGroupContext *c = data;
    3733                 :          0 :         const char *p = rvalue;
    3734                 :            :         uint64_t bytes;
    3735                 :            :         bool read;
    3736                 :            :         int r;
    3737                 :            : 
    3738         [ #  # ]:          0 :         assert(filename);
    3739         [ #  # ]:          0 :         assert(lvalue);
    3740         [ #  # ]:          0 :         assert(rvalue);
    3741                 :            : 
    3742                 :          0 :         read = streq("BlockIOReadBandwidth", lvalue);
    3743                 :            : 
    3744         [ #  # ]:          0 :         if (isempty(rvalue)) {
    3745         [ #  # ]:          0 :                 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
    3746                 :          0 :                         b->rbps = CGROUP_LIMIT_MAX;
    3747                 :          0 :                         b->wbps = CGROUP_LIMIT_MAX;
    3748                 :            :                 }
    3749                 :          0 :                 return 0;
    3750                 :            :         }
    3751                 :            : 
    3752                 :          0 :         r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE);
    3753         [ #  # ]:          0 :         if (r == -ENOMEM)
    3754                 :          0 :                 return log_oom();
    3755         [ #  # ]:          0 :         if (r < 0) {
    3756         [ #  # ]:          0 :                 log_syntax(unit, LOG_WARNING, filename, line, r,
    3757                 :            :                            "Invalid syntax, ignoring: %s", rvalue);
    3758                 :          0 :                 return 0;
    3759                 :            :         }
    3760   [ #  #  #  # ]:          0 :         if (r == 0 || isempty(p)) {
    3761         [ #  # ]:          0 :                 log_syntax(unit, LOG_WARNING, filename, line, 0,
    3762                 :            :                            "Failed to extract device node and bandwidth from '%s', ignoring.", rvalue);
    3763                 :          0 :                 return 0;
    3764                 :            :         }
    3765                 :            : 
    3766                 :          0 :         r = unit_full_printf(userdata, path, &resolved);
    3767         [ #  # ]:          0 :         if (r < 0) {
    3768         [ #  # ]:          0 :                 log_syntax(unit, LOG_WARNING, filename, line, r,
    3769                 :            :                            "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
    3770                 :          0 :                 return 0;
    3771                 :            :         }
    3772                 :            : 
    3773                 :          0 :         r = path_simplify_and_warn(resolved, 0, unit, filename, line, lvalue);
    3774         [ #  # ]:          0 :         if (r < 0)
    3775                 :          0 :                 return 0;
    3776                 :            : 
    3777                 :          0 :         r = parse_size(p, 1000, &bytes);
    3778   [ #  #  #  # ]:          0 :         if (r < 0 || bytes <= 0) {
    3779         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Invalid Block IO Bandwidth '%s', ignoring.", p);
    3780                 :          0 :                 return 0;
    3781                 :            :         }
    3782                 :            : 
    3783         [ #  # ]:          0 :         LIST_FOREACH(device_bandwidths, t, c->blockio_device_bandwidths) {
    3784         [ #  # ]:          0 :                 if (path_equal(resolved, t->path)) {
    3785                 :          0 :                         b = t;
    3786                 :          0 :                         break;
    3787                 :            :                 }
    3788                 :            :         }
    3789                 :            : 
    3790         [ #  # ]:          0 :         if (!t) {
    3791                 :          0 :                 b = new0(CGroupBlockIODeviceBandwidth, 1);
    3792         [ #  # ]:          0 :                 if (!b)
    3793                 :          0 :                         return log_oom();
    3794                 :            : 
    3795                 :          0 :                 b->path = TAKE_PTR(resolved);
    3796                 :          0 :                 b->rbps = CGROUP_LIMIT_MAX;
    3797                 :          0 :                 b->wbps = CGROUP_LIMIT_MAX;
    3798                 :            : 
    3799   [ #  #  #  # ]:          0 :                 LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, b);
    3800                 :            :         }
    3801                 :            : 
    3802         [ #  # ]:          0 :         if (read)
    3803                 :          0 :                 b->rbps = bytes;
    3804                 :            :         else
    3805                 :          0 :                 b->wbps = bytes;
    3806                 :            : 
    3807                 :          0 :         return 0;
    3808                 :            : }
    3809                 :            : 
    3810                 :          0 : int config_parse_job_mode_isolate(
    3811                 :            :                 const char *unit,
    3812                 :            :                 const char *filename,
    3813                 :            :                 unsigned line,
    3814                 :            :                 const char *section,
    3815                 :            :                 unsigned section_line,
    3816                 :            :                 const char *lvalue,
    3817                 :            :                 int ltype,
    3818                 :            :                 const char *rvalue,
    3819                 :            :                 void *data,
    3820                 :            :                 void *userdata) {
    3821                 :            : 
    3822                 :          0 :         JobMode *m = data;
    3823                 :            :         int r;
    3824                 :            : 
    3825         [ #  # ]:          0 :         assert(filename);
    3826         [ #  # ]:          0 :         assert(lvalue);
    3827         [ #  # ]:          0 :         assert(rvalue);
    3828                 :            : 
    3829                 :          0 :         r = parse_boolean(rvalue);
    3830         [ #  # ]:          0 :         if (r < 0) {
    3831         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse boolean, ignoring: %s", rvalue);
    3832                 :          0 :                 return 0;
    3833                 :            :         }
    3834                 :            : 
    3835         [ #  # ]:          0 :         log_notice("%s is deprecated. Please use OnFailureJobMode= instead", lvalue);
    3836                 :            : 
    3837         [ #  # ]:          0 :         *m = r ? JOB_ISOLATE : JOB_REPLACE;
    3838                 :          0 :         return 0;
    3839                 :            : }
    3840                 :            : 
    3841                 :          0 : int config_parse_exec_directories(
    3842                 :            :                 const char *unit,
    3843                 :            :                 const char *filename,
    3844                 :            :                 unsigned line,
    3845                 :            :                 const char *section,
    3846                 :            :                 unsigned section_line,
    3847                 :            :                 const char *lvalue,
    3848                 :            :                 int ltype,
    3849                 :            :                 const char *rvalue,
    3850                 :            :                 void *data,
    3851                 :            :                 void *userdata) {
    3852                 :            : 
    3853                 :          0 :         char***rt = data;
    3854                 :          0 :         Unit *u = userdata;
    3855                 :            :         const char *p;
    3856                 :            :         int r;
    3857                 :            : 
    3858         [ #  # ]:          0 :         assert(filename);
    3859         [ #  # ]:          0 :         assert(lvalue);
    3860         [ #  # ]:          0 :         assert(rvalue);
    3861         [ #  # ]:          0 :         assert(data);
    3862                 :            : 
    3863         [ #  # ]:          0 :         if (isempty(rvalue)) {
    3864                 :            :                 /* Empty assignment resets the list */
    3865                 :          0 :                 *rt = strv_free(*rt);
    3866                 :          0 :                 return 0;
    3867                 :            :         }
    3868                 :            : 
    3869                 :          0 :         for (p = rvalue;;) {
    3870   [ #  #  #  #  :          0 :                 _cleanup_free_ char *word = NULL, *k = NULL;
                   #  # ]
    3871                 :            : 
    3872                 :          0 :                 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
    3873         [ #  # ]:          0 :                 if (r == -ENOMEM)
    3874                 :          0 :                         return log_oom();
    3875         [ #  # ]:          0 :                 if (r < 0) {
    3876         [ #  # ]:          0 :                         log_syntax(unit, LOG_WARNING, filename, line, r,
    3877                 :            :                                    "Invalid syntax, ignoring: %s", rvalue);
    3878                 :          0 :                         return 0;
    3879                 :            :                 }
    3880         [ #  # ]:          0 :                 if (r == 0)
    3881                 :          0 :                         return 0;
    3882                 :            : 
    3883                 :          0 :                 r = unit_full_printf(u, word, &k);
    3884         [ #  # ]:          0 :                 if (r < 0) {
    3885         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
    3886                 :            :                                    "Failed to resolve unit specifiers in \"%s\", ignoring: %m", word);
    3887                 :          0 :                         continue;
    3888                 :            :                 }
    3889                 :            : 
    3890                 :          0 :                 r = path_simplify_and_warn(k, PATH_CHECK_RELATIVE, unit, filename, line, lvalue);
    3891         [ #  # ]:          0 :                 if (r < 0)
    3892                 :          0 :                         continue;
    3893                 :            : 
    3894         [ #  # ]:          0 :                 if (path_startswith(k, "private")) {
    3895         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, 0,
    3896                 :            :                                    "%s= path can't be 'private', ignoring assignment: %s", lvalue, word);
    3897                 :          0 :                         continue;
    3898                 :            :                 }
    3899                 :            : 
    3900                 :          0 :                 r = strv_push(rt, k);
    3901         [ #  # ]:          0 :                 if (r < 0)
    3902                 :          0 :                         return log_oom();
    3903                 :          0 :                 k = NULL;
    3904                 :            :         }
    3905                 :            : }
    3906                 :            : 
    3907                 :          0 : int config_parse_set_status(
    3908                 :            :                 const char *unit,
    3909                 :            :                 const char *filename,
    3910                 :            :                 unsigned line,
    3911                 :            :                 const char *section,
    3912                 :            :                 unsigned section_line,
    3913                 :            :                 const char *lvalue,
    3914                 :            :                 int ltype,
    3915                 :            :                 const char *rvalue,
    3916                 :            :                 void *data,
    3917                 :            :                 void *userdata) {
    3918                 :            : 
    3919                 :            :         size_t l;
    3920                 :            :         const char *word, *state;
    3921                 :            :         int r;
    3922                 :          0 :         ExitStatusSet *status_set = data;
    3923                 :            : 
    3924         [ #  # ]:          0 :         assert(filename);
    3925         [ #  # ]:          0 :         assert(lvalue);
    3926         [ #  # ]:          0 :         assert(rvalue);
    3927         [ #  # ]:          0 :         assert(data);
    3928                 :            : 
    3929                 :            :         /* Empty assignment resets the list */
    3930         [ #  # ]:          0 :         if (isempty(rvalue)) {
    3931                 :          0 :                 exit_status_set_free(status_set);
    3932                 :          0 :                 return 0;
    3933                 :            :         }
    3934                 :            : 
    3935         [ #  # ]:          0 :         FOREACH_WORD(word, l, rvalue, state) {
    3936      [ #  #  # ]:          0 :                 _cleanup_free_ char *temp;
    3937                 :            :                 Bitmap *bitmap;
    3938                 :            : 
    3939                 :          0 :                 temp = strndup(word, l);
    3940         [ #  # ]:          0 :                 if (!temp)
    3941                 :          0 :                         return log_oom();
    3942                 :            : 
    3943                 :            :                 /* We need to call exit_status_from_string() first, because we want
    3944                 :            :                  * to parse numbers as exit statuses, not signals. */
    3945                 :            : 
    3946                 :          0 :                 r = exit_status_from_string(temp);
    3947         [ #  # ]:          0 :                 if (r >= 0) {
    3948   [ #  #  #  # ]:          0 :                         assert(r >= 0 && r < 256);
    3949                 :          0 :                         bitmap = &status_set->status;
    3950                 :            :                 } else {
    3951                 :          0 :                         r = signal_from_string(temp);
    3952                 :            : 
    3953         [ #  # ]:          0 :                         if (r <= 0) {
    3954         [ #  # ]:          0 :                                 log_syntax(unit, LOG_ERR, filename, line, 0,
    3955                 :            :                                            "Failed to parse value, ignoring: %s", word);
    3956                 :          0 :                                 continue;
    3957                 :            :                         }
    3958                 :          0 :                         bitmap = &status_set->signal;
    3959                 :            :                 }
    3960                 :            : 
    3961                 :          0 :                 r = bitmap_set(bitmap, r);
    3962         [ #  # ]:          0 :                 if (r < 0)
    3963         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to set signal or status %s: %m", word);
    3964                 :            :         }
    3965         [ #  # ]:          0 :         if (!isempty(state))
    3966         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
    3967                 :            : 
    3968                 :          0 :         return 0;
    3969                 :            : }
    3970                 :            : 
    3971                 :          0 : int config_parse_namespace_path_strv(
    3972                 :            :                 const char *unit,
    3973                 :            :                 const char *filename,
    3974                 :            :                 unsigned line,
    3975                 :            :                 const char *section,
    3976                 :            :                 unsigned section_line,
    3977                 :            :                 const char *lvalue,
    3978                 :            :                 int ltype,
    3979                 :            :                 const char *rvalue,
    3980                 :            :                 void *data,
    3981                 :            :                 void *userdata) {
    3982                 :            : 
    3983                 :          0 :         Unit *u = userdata;
    3984                 :          0 :         char*** sv = data;
    3985                 :          0 :         const char *p = rvalue;
    3986                 :            :         int r;
    3987                 :            : 
    3988         [ #  # ]:          0 :         assert(filename);
    3989         [ #  # ]:          0 :         assert(lvalue);
    3990         [ #  # ]:          0 :         assert(rvalue);
    3991         [ #  # ]:          0 :         assert(data);
    3992                 :            : 
    3993         [ #  # ]:          0 :         if (isempty(rvalue)) {
    3994                 :            :                 /* Empty assignment resets the list */
    3995                 :          0 :                 *sv = strv_free(*sv);
    3996                 :          0 :                 return 0;
    3997                 :            :         }
    3998                 :            : 
    3999                 :          0 :         for (;;) {
    4000   [ #  #  #  #  :          0 :                 _cleanup_free_ char *word = NULL, *resolved = NULL, *joined = NULL;
          #  #  #  #  #  
                #  #  # ]
    4001                 :            :                 const char *w;
    4002                 :          0 :                 bool ignore_enoent = false, shall_prefix = false;
    4003                 :            : 
    4004                 :          0 :                 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
    4005         [ #  # ]:          0 :                 if (r == 0)
    4006                 :          0 :                         break;
    4007         [ #  # ]:          0 :                 if (r == -ENOMEM)
    4008                 :          0 :                         return log_oom();
    4009         [ #  # ]:          0 :                 if (r < 0) {
    4010         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract first word, ignoring: %s", rvalue);
    4011                 :          0 :                         return 0;
    4012                 :            :                 }
    4013                 :            : 
    4014                 :          0 :                 w = word;
    4015         [ #  # ]:          0 :                 if (startswith(w, "-")) {
    4016                 :          0 :                         ignore_enoent = true;
    4017                 :          0 :                         w++;
    4018                 :            :                 }
    4019         [ #  # ]:          0 :                 if (startswith(w, "+")) {
    4020                 :          0 :                         shall_prefix = true;
    4021                 :          0 :                         w++;
    4022                 :            :                 }
    4023                 :            : 
    4024                 :          0 :                 r = unit_full_printf(u, w, &resolved);
    4025         [ #  # ]:          0 :                 if (r < 0) {
    4026         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", w);
    4027                 :          0 :                         continue;
    4028                 :            :                 }
    4029                 :            : 
    4030                 :          0 :                 r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
    4031         [ #  # ]:          0 :                 if (r < 0)
    4032                 :          0 :                         continue;
    4033                 :            : 
    4034   [ #  #  #  # ]:          0 :                 joined = strjoin(ignore_enoent ? "-" : "",
    4035                 :            :                                  shall_prefix ? "+" : "",
    4036                 :            :                                  resolved);
    4037                 :            : 
    4038                 :          0 :                 r = strv_push(sv, joined);
    4039         [ #  # ]:          0 :                 if (r < 0)
    4040                 :          0 :                         return log_oom();
    4041                 :            : 
    4042                 :          0 :                 joined = NULL;
    4043                 :            :         }
    4044                 :            : 
    4045                 :          0 :         return 0;
    4046                 :            : }
    4047                 :            : 
    4048                 :          0 : int config_parse_temporary_filesystems(
    4049                 :            :                 const char *unit,
    4050                 :            :                 const char *filename,
    4051                 :            :                 unsigned line,
    4052                 :            :                 const char *section,
    4053                 :            :                 unsigned section_line,
    4054                 :            :                 const char *lvalue,
    4055                 :            :                 int ltype,
    4056                 :            :                 const char *rvalue,
    4057                 :            :                 void *data,
    4058                 :            :                 void *userdata) {
    4059                 :            : 
    4060                 :          0 :         Unit *u = userdata;
    4061                 :          0 :         ExecContext *c = data;
    4062                 :          0 :         const char *p = rvalue;
    4063                 :            :         int r;
    4064                 :            : 
    4065         [ #  # ]:          0 :         assert(filename);
    4066         [ #  # ]:          0 :         assert(lvalue);
    4067         [ #  # ]:          0 :         assert(rvalue);
    4068         [ #  # ]:          0 :         assert(data);
    4069                 :            : 
    4070         [ #  # ]:          0 :         if (isempty(rvalue)) {
    4071                 :            :                 /* Empty assignment resets the list */
    4072                 :          0 :                 temporary_filesystem_free_many(c->temporary_filesystems, c->n_temporary_filesystems);
    4073                 :          0 :                 c->temporary_filesystems = NULL;
    4074                 :          0 :                 c->n_temporary_filesystems = 0;
    4075                 :          0 :                 return 0;
    4076                 :            :         }
    4077                 :            : 
    4078                 :          0 :         for (;;) {
    4079   [ #  #  #  #  :          0 :                 _cleanup_free_ char *word = NULL, *path = NULL, *resolved = NULL;
             #  #  #  #  
                      # ]
    4080                 :            :                 const char *w;
    4081                 :            : 
    4082                 :          0 :                 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
    4083         [ #  # ]:          0 :                 if (r == 0)
    4084                 :          0 :                         return 0;
    4085         [ #  # ]:          0 :                 if (r == -ENOMEM)
    4086                 :          0 :                         return log_oom();
    4087         [ #  # ]:          0 :                 if (r < 0) {
    4088         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract first word, ignoring: %s", rvalue);
    4089                 :          0 :                         return 0;
    4090                 :            :                 }
    4091                 :            : 
    4092                 :          0 :                 w = word;
    4093                 :          0 :                 r = extract_first_word(&w, &path, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
    4094         [ #  # ]:          0 :                 if (r == -ENOMEM)
    4095                 :          0 :                         return log_oom();
    4096         [ #  # ]:          0 :                 if (r < 0) {
    4097         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract first word, ignoring: %s", word);
    4098                 :          0 :                         continue;
    4099                 :            :                 }
    4100         [ #  # ]:          0 :                 if (r == 0) {
    4101         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid syntax, ignoring: %s", word);
    4102                 :          0 :                         continue;
    4103                 :            :                 }
    4104                 :            : 
    4105                 :          0 :                 r = unit_full_printf(u, path, &resolved);
    4106         [ #  # ]:          0 :                 if (r < 0) {
    4107         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", path);
    4108                 :          0 :                         continue;
    4109                 :            :                 }
    4110                 :            : 
    4111                 :          0 :                 r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
    4112         [ #  # ]:          0 :                 if (r < 0)
    4113                 :          0 :                         continue;
    4114                 :            : 
    4115                 :          0 :                 r = temporary_filesystem_add(&c->temporary_filesystems, &c->n_temporary_filesystems, resolved, w);
    4116         [ #  # ]:          0 :                 if (r < 0)
    4117                 :          0 :                         return log_oom();
    4118                 :            :         }
    4119                 :            : }
    4120                 :            : 
    4121                 :          0 : int config_parse_bind_paths(
    4122                 :            :                 const char *unit,
    4123                 :            :                 const char *filename,
    4124                 :            :                 unsigned line,
    4125                 :            :                 const char *section,
    4126                 :            :                 unsigned section_line,
    4127                 :            :                 const char *lvalue,
    4128                 :            :                 int ltype,
    4129                 :            :                 const char *rvalue,
    4130                 :            :                 void *data,
    4131                 :            :                 void *userdata) {
    4132                 :            : 
    4133                 :          0 :         ExecContext *c = data;
    4134                 :          0 :         Unit *u = userdata;
    4135                 :            :         const char *p;
    4136                 :            :         int r;
    4137                 :            : 
    4138         [ #  # ]:          0 :         assert(filename);
    4139         [ #  # ]:          0 :         assert(lvalue);
    4140         [ #  # ]:          0 :         assert(rvalue);
    4141         [ #  # ]:          0 :         assert(data);
    4142                 :            : 
    4143         [ #  # ]:          0 :         if (isempty(rvalue)) {
    4144                 :            :                 /* Empty assignment resets the list */
    4145                 :          0 :                 bind_mount_free_many(c->bind_mounts, c->n_bind_mounts);
    4146                 :          0 :                 c->bind_mounts = NULL;
    4147                 :          0 :                 c->n_bind_mounts = 0;
    4148                 :          0 :                 return 0;
    4149                 :            :         }
    4150                 :            : 
    4151                 :          0 :         p = rvalue;
    4152                 :          0 :         for (;;) {
    4153   [ #  #  #  #  :          0 :                 _cleanup_free_ char *source = NULL, *destination = NULL;
             #  #  #  # ]
    4154   [ #  #  #  #  :          0 :                 _cleanup_free_ char *sresolved = NULL, *dresolved = NULL;
             #  #  #  # ]
    4155                 :          0 :                 char *s = NULL, *d = NULL;
    4156                 :          0 :                 bool rbind = true, ignore_enoent = false;
    4157                 :            : 
    4158                 :          0 :                 r = extract_first_word(&p, &source, ":" WHITESPACE, EXTRACT_UNQUOTE|EXTRACT_DONT_COALESCE_SEPARATORS);
    4159         [ #  # ]:          0 :                 if (r == 0)
    4160                 :          0 :                         break;
    4161         [ #  # ]:          0 :                 if (r == -ENOMEM)
    4162                 :          0 :                         return log_oom();
    4163         [ #  # ]:          0 :                 if (r < 0) {
    4164         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s, ignoring: %s", lvalue, rvalue);
    4165                 :          0 :                         return 0;
    4166                 :            :                 }
    4167                 :            : 
    4168                 :          0 :                 r = unit_full_printf(u, source, &sresolved);
    4169         [ #  # ]:          0 :                 if (r < 0) {
    4170         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
    4171                 :            :                                    "Failed to resolved unit specifiers in \"%s\", ignoring: %m", source);
    4172                 :          0 :                         continue;
    4173                 :            :                 }
    4174                 :            : 
    4175                 :          0 :                 s = sresolved;
    4176         [ #  # ]:          0 :                 if (s[0] == '-') {
    4177                 :          0 :                         ignore_enoent = true;
    4178                 :          0 :                         s++;
    4179                 :            :                 }
    4180                 :            : 
    4181                 :          0 :                 r = path_simplify_and_warn(s, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
    4182         [ #  # ]:          0 :                 if (r < 0)
    4183                 :          0 :                         continue;
    4184                 :            : 
    4185                 :            :                 /* Optionally, the destination is specified. */
    4186   [ #  #  #  # ]:          0 :                 if (p && p[-1] == ':') {
    4187                 :          0 :                         r = extract_first_word(&p, &destination, ":" WHITESPACE, EXTRACT_UNQUOTE|EXTRACT_DONT_COALESCE_SEPARATORS);
    4188         [ #  # ]:          0 :                         if (r == -ENOMEM)
    4189                 :          0 :                                 return log_oom();
    4190         [ #  # ]:          0 :                         if (r < 0) {
    4191         [ #  # ]:          0 :                                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s, ignoring: %s", lvalue, rvalue);
    4192                 :          0 :                                 return 0;
    4193                 :            :                         }
    4194         [ #  # ]:          0 :                         if (r == 0) {
    4195         [ #  # ]:          0 :                                 log_syntax(unit, LOG_ERR, filename, line, 0, "Missing argument after ':', ignoring: %s", s);
    4196                 :          0 :                                 continue;
    4197                 :            :                         }
    4198                 :            : 
    4199                 :          0 :                         r = unit_full_printf(u, destination, &dresolved);
    4200         [ #  # ]:          0 :                         if (r < 0) {
    4201         [ #  # ]:          0 :                                 log_syntax(unit, LOG_ERR, filename, line, r,
    4202                 :            :                                            "Failed to resolved specifiers in \"%s\", ignoring: %m", destination);
    4203                 :          0 :                                 continue;
    4204                 :            :                         }
    4205                 :            : 
    4206                 :          0 :                         r = path_simplify_and_warn(dresolved, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
    4207         [ #  # ]:          0 :                         if (r < 0)
    4208                 :          0 :                                 continue;
    4209                 :            : 
    4210                 :          0 :                         d = dresolved;
    4211                 :            : 
    4212                 :            :                         /* Optionally, there's also a short option string specified */
    4213   [ #  #  #  # ]:          0 :                         if (p && p[-1] == ':') {
    4214      [ #  #  # ]:          0 :                                 _cleanup_free_ char *options = NULL;
    4215                 :            : 
    4216                 :          0 :                                 r = extract_first_word(&p, &options, NULL, EXTRACT_UNQUOTE);
    4217         [ #  # ]:          0 :                                 if (r == -ENOMEM)
    4218                 :          0 :                                         return log_oom();
    4219         [ #  # ]:          0 :                                 if (r < 0) {
    4220         [ #  # ]:          0 :                                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s: %s", lvalue, rvalue);
    4221                 :          0 :                                         return 0;
    4222                 :            :                                 }
    4223                 :            : 
    4224   [ #  #  #  # ]:          0 :                                 if (isempty(options) || streq(options, "rbind"))
    4225                 :          0 :                                         rbind = true;
    4226         [ #  # ]:          0 :                                 else if (streq(options, "norbind"))
    4227                 :          0 :                                         rbind = false;
    4228                 :            :                                 else {
    4229         [ #  # ]:          0 :                                         log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid option string, ignoring setting: %s", options);
    4230                 :          0 :                                         continue;
    4231                 :            :                                 }
    4232                 :            :                         }
    4233                 :            :                 } else
    4234                 :          0 :                         d = s;
    4235                 :            : 
    4236                 :          0 :                 r = bind_mount_add(&c->bind_mounts, &c->n_bind_mounts,
    4237                 :          0 :                                    &(BindMount) {
    4238                 :            :                                            .source = s,
    4239                 :            :                                            .destination = d,
    4240                 :          0 :                                            .read_only = !!strstr(lvalue, "ReadOnly"),
    4241                 :            :                                            .recursive = rbind,
    4242                 :            :                                            .ignore_enoent = ignore_enoent,
    4243                 :            :                                    });
    4244         [ #  # ]:          0 :                 if (r < 0)
    4245                 :          0 :                         return log_oom();
    4246                 :            :         }
    4247                 :            : 
    4248                 :          0 :         return 0;
    4249                 :            : }
    4250                 :            : 
    4251                 :          0 : int config_parse_job_timeout_sec(
    4252                 :            :                 const char* unit,
    4253                 :            :                 const char *filename,
    4254                 :            :                 unsigned line,
    4255                 :            :                 const char *section,
    4256                 :            :                 unsigned section_line,
    4257                 :            :                 const char *lvalue,
    4258                 :            :                 int ltype,
    4259                 :            :                 const char *rvalue,
    4260                 :            :                 void *data,
    4261                 :            :                 void *userdata) {
    4262                 :            : 
    4263                 :          0 :         Unit *u = data;
    4264                 :            :         usec_t usec;
    4265                 :            :         int r;
    4266                 :            : 
    4267         [ #  # ]:          0 :         assert(filename);
    4268         [ #  # ]:          0 :         assert(lvalue);
    4269         [ #  # ]:          0 :         assert(rvalue);
    4270         [ #  # ]:          0 :         assert(u);
    4271                 :            : 
    4272                 :          0 :         r = parse_sec_fix_0(rvalue, &usec);
    4273         [ #  # ]:          0 :         if (r < 0) {
    4274         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse JobTimeoutSec= parameter, ignoring: %s", rvalue);
    4275                 :          0 :                 return 0;
    4276                 :            :         }
    4277                 :            : 
    4278                 :            :         /* If the user explicitly changed JobTimeoutSec= also change JobRunningTimeoutSec=, for compatibility with old
    4279                 :            :          * versions. If JobRunningTimeoutSec= was explicitly set, avoid this however as whatever the user picked should
    4280                 :            :          * count. */
    4281                 :            : 
    4282         [ #  # ]:          0 :         if (!u->job_running_timeout_set)
    4283                 :          0 :                 u->job_running_timeout = usec;
    4284                 :            : 
    4285                 :          0 :         u->job_timeout = usec;
    4286                 :            : 
    4287                 :          0 :         return 0;
    4288                 :            : }
    4289                 :            : 
    4290                 :          0 : int config_parse_job_running_timeout_sec(
    4291                 :            :                 const char* unit,
    4292                 :            :                 const char *filename,
    4293                 :            :                 unsigned line,
    4294                 :            :                 const char *section,
    4295                 :            :                 unsigned section_line,
    4296                 :            :                 const char *lvalue,
    4297                 :            :                 int ltype,
    4298                 :            :                 const char *rvalue,
    4299                 :            :                 void *data,
    4300                 :            :                 void *userdata) {
    4301                 :            : 
    4302                 :          0 :         Unit *u = data;
    4303                 :            :         usec_t usec;
    4304                 :            :         int r;
    4305                 :            : 
    4306         [ #  # ]:          0 :         assert(filename);
    4307         [ #  # ]:          0 :         assert(lvalue);
    4308         [ #  # ]:          0 :         assert(rvalue);
    4309         [ #  # ]:          0 :         assert(u);
    4310                 :            : 
    4311                 :          0 :         r = parse_sec_fix_0(rvalue, &usec);
    4312         [ #  # ]:          0 :         if (r < 0) {
    4313         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse JobRunningTimeoutSec= parameter, ignoring: %s", rvalue);
    4314                 :          0 :                 return 0;
    4315                 :            :         }
    4316                 :            : 
    4317                 :          0 :         u->job_running_timeout = usec;
    4318                 :          0 :         u->job_running_timeout_set = true;
    4319                 :            : 
    4320                 :          0 :         return 0;
    4321                 :            : }
    4322                 :            : 
    4323                 :          0 : int config_parse_emergency_action(
    4324                 :            :                 const char* unit,
    4325                 :            :                 const char *filename,
    4326                 :            :                 unsigned line,
    4327                 :            :                 const char *section,
    4328                 :            :                 unsigned section_line,
    4329                 :            :                 const char *lvalue,
    4330                 :            :                 int ltype,
    4331                 :            :                 const char *rvalue,
    4332                 :            :                 void *data,
    4333                 :            :                 void *userdata) {
    4334                 :            : 
    4335                 :          0 :         Manager *m = NULL;
    4336                 :          0 :         EmergencyAction *x = data;
    4337                 :            :         int r;
    4338                 :            : 
    4339         [ #  # ]:          0 :         assert(filename);
    4340         [ #  # ]:          0 :         assert(lvalue);
    4341         [ #  # ]:          0 :         assert(rvalue);
    4342         [ #  # ]:          0 :         assert(data);
    4343                 :            : 
    4344         [ #  # ]:          0 :         if (unit)
    4345                 :          0 :                 m = ((Unit*) userdata)->manager;
    4346                 :            :         else
    4347                 :          0 :                 m = data;
    4348                 :            : 
    4349                 :          0 :         r = parse_emergency_action(rvalue, MANAGER_IS_SYSTEM(m), x);
    4350         [ #  # ]:          0 :         if (r < 0) {
    4351   [ #  #  #  # ]:          0 :                 if (r == -EOPNOTSUPP && MANAGER_IS_USER(m)) {
    4352                 :            :                         /* Compat mode: remove for systemd 241. */
    4353                 :            : 
    4354         [ #  # ]:          0 :                         log_syntax(unit, LOG_INFO, filename, line, r,
    4355                 :            :                                    "%s= in user mode specified as \"%s\", using \"exit-force\" instead.",
    4356                 :            :                                    lvalue, rvalue);
    4357                 :          0 :                         *x = EMERGENCY_ACTION_EXIT_FORCE;
    4358                 :          0 :                         return 0;
    4359                 :            :                 }
    4360                 :            : 
    4361         [ #  # ]:          0 :                 if (r == -EOPNOTSUPP)
    4362   [ #  #  #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
    4363                 :            :                                    "%s= specified as %s mode action, ignoring: %s",
    4364                 :            :                                    lvalue, MANAGER_IS_SYSTEM(m) ? "user" : "system", rvalue);
    4365                 :            :                 else
    4366         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
    4367                 :            :                                    "Failed to parse %s=, ignoring: %s", lvalue, rvalue);
    4368                 :          0 :                 return 0;
    4369                 :            :         }
    4370                 :            : 
    4371                 :          0 :         return 0;
    4372                 :            : }
    4373                 :            : 
    4374                 :          0 : int config_parse_pid_file(
    4375                 :            :                 const char *unit,
    4376                 :            :                 const char *filename,
    4377                 :            :                 unsigned line,
    4378                 :            :                 const char *section,
    4379                 :            :                 unsigned section_line,
    4380                 :            :                 const char *lvalue,
    4381                 :            :                 int ltype,
    4382                 :            :                 const char *rvalue,
    4383                 :            :                 void *data,
    4384                 :            :                 void *userdata) {
    4385                 :            : 
    4386                 :          0 :         _cleanup_free_ char *k = NULL, *n = NULL;
    4387                 :          0 :         Unit *u = userdata;
    4388                 :          0 :         char **s = data;
    4389                 :            :         int r;
    4390                 :            : 
    4391         [ #  # ]:          0 :         assert(filename);
    4392         [ #  # ]:          0 :         assert(lvalue);
    4393         [ #  # ]:          0 :         assert(rvalue);
    4394         [ #  # ]:          0 :         assert(u);
    4395                 :            : 
    4396         [ #  # ]:          0 :         if (isempty(rvalue)) {
    4397                 :            :                 /* An empty assignment removes already set value. */
    4398                 :          0 :                 *s = mfree(*s);
    4399                 :          0 :                 return 0;
    4400                 :            :         }
    4401                 :            : 
    4402                 :          0 :         r = unit_full_printf(u, rvalue, &k);
    4403         [ #  # ]:          0 :         if (r < 0) {
    4404         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
    4405                 :          0 :                 return 0;
    4406                 :            :         }
    4407                 :            : 
    4408                 :            :         /* If this is a relative path make it absolute by prefixing the /run */
    4409                 :          0 :         n = path_make_absolute(k, u->manager->prefix[EXEC_DIRECTORY_RUNTIME]);
    4410         [ #  # ]:          0 :         if (!n)
    4411                 :          0 :                 return log_oom();
    4412                 :            : 
    4413                 :            :         /* Check that the result is a sensible path */
    4414                 :          0 :         r = path_simplify_and_warn(n, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
    4415         [ #  # ]:          0 :         if (r < 0)
    4416                 :          0 :                 return r;
    4417                 :            : 
    4418                 :          0 :         r = patch_var_run(unit, filename, line, lvalue, &n);
    4419         [ #  # ]:          0 :         if (r < 0)
    4420                 :          0 :                 return r;
    4421                 :            : 
    4422                 :          0 :         free_and_replace(*s, n);
    4423                 :          0 :         return 0;
    4424                 :            : }
    4425                 :            : 
    4426                 :          0 : int config_parse_exit_status(
    4427                 :            :                 const char *unit,
    4428                 :            :                 const char *filename,
    4429                 :            :                 unsigned line,
    4430                 :            :                 const char *section,
    4431                 :            :                 unsigned section_line,
    4432                 :            :                 const char *lvalue,
    4433                 :            :                 int ltype,
    4434                 :            :                 const char *rvalue,
    4435                 :            :                 void *data,
    4436                 :            :                 void *userdata) {
    4437                 :            : 
    4438                 :          0 :         int *exit_status = data, r;
    4439                 :            :         uint8_t u;
    4440                 :            : 
    4441         [ #  # ]:          0 :         assert(filename);
    4442         [ #  # ]:          0 :         assert(lvalue);
    4443         [ #  # ]:          0 :         assert(rvalue);
    4444         [ #  # ]:          0 :         assert(exit_status);
    4445                 :            : 
    4446         [ #  # ]:          0 :         if (isempty(rvalue)) {
    4447                 :          0 :                 *exit_status = -1;
    4448                 :          0 :                 return 0;
    4449                 :            :         }
    4450                 :            : 
    4451                 :          0 :         r = safe_atou8(rvalue, &u);
    4452         [ #  # ]:          0 :         if (r < 0) {
    4453         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse exit status '%s', ignoring: %m", rvalue);
    4454                 :          0 :                 return 0;
    4455                 :            :         }
    4456                 :            : 
    4457                 :          0 :         *exit_status = u;
    4458                 :          0 :         return 0;
    4459                 :            : }
    4460                 :            : 
    4461                 :          4 : int config_parse_disable_controllers(
    4462                 :            :                 const char *unit,
    4463                 :            :                 const char *filename,
    4464                 :            :                 unsigned line,
    4465                 :            :                 const char *section,
    4466                 :            :                 unsigned section_line,
    4467                 :            :                 const char *lvalue,
    4468                 :            :                 int ltype,
    4469                 :            :                 const char *rvalue,
    4470                 :            :                 void *data,
    4471                 :            :                 void *userdata) {
    4472                 :            : 
    4473                 :            :         int r;
    4474                 :          4 :         CGroupContext *c = data;
    4475                 :            :         CGroupMask disabled_mask;
    4476                 :            : 
    4477                 :            :         /* 1. If empty, make all controllers eligible for use again.
    4478                 :            :          * 2. If non-empty, merge all listed controllers, space separated. */
    4479                 :            : 
    4480         [ -  + ]:          4 :         if (isempty(rvalue)) {
    4481                 :          0 :                 c->disable_controllers = 0;
    4482                 :          0 :                 return 0;
    4483                 :            :         }
    4484                 :            : 
    4485                 :          4 :         r = cg_mask_from_string(rvalue, &disabled_mask);
    4486   [ +  -  -  + ]:          4 :         if (r < 0 || disabled_mask <= 0) {
    4487         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Invalid cgroup string: %s, ignoring", rvalue);
    4488                 :          0 :                 return 0;
    4489                 :            :         }
    4490                 :            : 
    4491                 :          4 :         c->disable_controllers |= disabled_mask;
    4492                 :            : 
    4493                 :          4 :         return 0;
    4494                 :            : }
    4495                 :            : 
    4496                 :          0 : int config_parse_ip_filter_bpf_progs(
    4497                 :            :                 const char *unit,
    4498                 :            :                 const char *filename,
    4499                 :            :                 unsigned line,
    4500                 :            :                 const char *section,
    4501                 :            :                 unsigned section_line,
    4502                 :            :                 const char *lvalue,
    4503                 :            :                 int ltype,
    4504                 :            :                 const char *rvalue,
    4505                 :            :                 void *data,
    4506                 :            :                 void *userdata) {
    4507                 :            : 
    4508                 :          0 :         _cleanup_free_ char *resolved = NULL;
    4509                 :          0 :         Unit *u = userdata;
    4510                 :          0 :         char ***paths = data;
    4511                 :            :         int r;
    4512                 :            : 
    4513         [ #  # ]:          0 :         assert(filename);
    4514         [ #  # ]:          0 :         assert(lvalue);
    4515         [ #  # ]:          0 :         assert(rvalue);
    4516         [ #  # ]:          0 :         assert(paths);
    4517                 :            : 
    4518         [ #  # ]:          0 :         if (isempty(rvalue)) {
    4519                 :          0 :                 *paths = strv_free(*paths);
    4520                 :          0 :                 return 0;
    4521                 :            :         }
    4522                 :            : 
    4523                 :          0 :         r = unit_full_printf(u, rvalue, &resolved);
    4524         [ #  # ]:          0 :         if (r < 0) {
    4525         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
    4526                 :          0 :                 return 0;
    4527                 :            :         }
    4528                 :            : 
    4529                 :          0 :         r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
    4530         [ #  # ]:          0 :         if (r < 0)
    4531                 :          0 :                 return 0;
    4532                 :            : 
    4533         [ #  # ]:          0 :         if (strv_contains(*paths, resolved))
    4534                 :          0 :                 return 0;
    4535                 :            : 
    4536                 :          0 :         r = strv_extend(paths, resolved);
    4537         [ #  # ]:          0 :         if (r < 0)
    4538                 :          0 :                 return log_oom();
    4539                 :            : 
    4540                 :          0 :         r = bpf_firewall_supported();
    4541         [ #  # ]:          0 :         if (r < 0)
    4542                 :          0 :                 return r;
    4543         [ #  # ]:          0 :         if (r != BPF_FIREWALL_SUPPORTED_WITH_MULTI) {
    4544                 :            :                 static bool warned = false;
    4545                 :            : 
    4546   [ #  #  #  # ]:          0 :                 log_full(warned ? LOG_DEBUG : LOG_WARNING,
    4547                 :            :                          "File %s:%u configures an IP firewall with BPF programs (%s=%s), but the local system does not support BPF/cgroup based firewalling with multiple filters.\n"
    4548                 :            :                          "Starting this unit will fail! (This warning is only shown for the first loaded unit using IP firewalling.)", filename, line, lvalue, rvalue);
    4549                 :            : 
    4550                 :          0 :                 warned = true;
    4551                 :            :         }
    4552                 :            : 
    4553                 :          0 :         return 0;
    4554                 :            : }
    4555                 :            : 
    4556                 :       8664 : static int merge_by_names(Unit **u, Set *names, const char *id) {
    4557                 :            :         char *k;
    4558                 :            :         int r;
    4559                 :            : 
    4560         [ -  + ]:       8664 :         assert(u);
    4561         [ -  + ]:       8664 :         assert(*u);
    4562                 :            : 
    4563                 :            :         /* Let's try to add in all names that are aliases of this unit */
    4564         [ +  + ]:      17472 :         while ((k = set_steal_first(names))) {
    4565         [ +  - ]:       8808 :                 _cleanup_free_ _unused_ char *free_k = k;
    4566                 :            : 
    4567                 :            :                 /* First try to merge in the other name into our unit */
    4568                 :       8808 :                 r = unit_merge_by_name(*u, k);
    4569         [ -  + ]:       8808 :                 if (r < 0) {
    4570                 :            :                         Unit *other;
    4571                 :            : 
    4572                 :            :                         /* Hmm, we couldn't merge the other unit into ours? Then let's try it the other way
    4573                 :            :                          * round. */
    4574                 :            : 
    4575                 :          0 :                         other = manager_get_unit((*u)->manager, k);
    4576         [ #  # ]:          0 :                         if (!other)
    4577                 :          0 :                                 return r; /* return previous failure */
    4578                 :            : 
    4579                 :          0 :                         r = unit_merge(other, *u);
    4580         [ #  # ]:          0 :                         if (r < 0)
    4581                 :          0 :                                 return r;
    4582                 :            : 
    4583                 :          0 :                         *u = other;
    4584                 :          0 :                         return merge_by_names(u, names, NULL);
    4585                 :            :                 }
    4586                 :            : 
    4587         [ +  + ]:       8808 :                 if (streq_ptr(id, k))
    4588                 :       8664 :                         unit_choose_id(*u, id);
    4589                 :            :         }
    4590                 :            : 
    4591                 :       8664 :         return 0;
    4592                 :            : }
    4593                 :            : 
    4594                 :       8708 : int unit_load_fragment(Unit *u) {
    4595                 :            :         const char *fragment;
    4596                 :       8708 :         _cleanup_set_free_free_ Set *names = NULL;
    4597                 :            :         int r;
    4598                 :            : 
    4599         [ -  + ]:       8708 :         assert(u);
    4600         [ -  + ]:       8708 :         assert(u->load_state == UNIT_STUB);
    4601         [ -  + ]:       8708 :         assert(u->id);
    4602                 :            : 
    4603         [ +  + ]:       8708 :         if (u->transient) {
    4604                 :         44 :                 u->load_state = UNIT_LOADED;
    4605                 :         44 :                 return 0;
    4606                 :            :         }
    4607                 :            : 
    4608                 :            :         /* Possibly rebuild the fragment map to catch new units */
    4609                 :      34656 :         r = unit_file_build_name_map(&u->manager->lookup_paths,
    4610                 :       8664 :                                      &u->manager->unit_cache_mtime,
    4611                 :       8664 :                                      &u->manager->unit_id_map,
    4612                 :       8664 :                                      &u->manager->unit_name_map,
    4613                 :       8664 :                                      &u->manager->unit_path_cache);
    4614         [ -  + ]:       8664 :         if (r < 0)
    4615         [ #  # ]:          0 :                 log_error_errno(r, "Failed to rebuild name map: %m");
    4616                 :            : 
    4617                 :       8664 :         r = unit_file_find_fragment(u->manager->unit_id_map,
    4618                 :       8664 :                                     u->manager->unit_name_map,
    4619                 :       8664 :                                     u->id,
    4620                 :            :                                     &fragment,
    4621                 :            :                                     &names);
    4622   [ -  +  #  # ]:       8664 :         if (r < 0 && r != -ENOENT)
    4623                 :          0 :                 return r;
    4624                 :            : 
    4625         [ +  + ]:       8664 :         if (fragment) {
    4626                 :            :                 /* Open the file, check if this is a mask, otherwise read. */
    4627         [ +  - ]:        352 :                 _cleanup_fclose_ FILE *f = NULL;
    4628                 :            :                 struct stat st;
    4629                 :            : 
    4630                 :            :                 /* Try to open the file name. A symlink is OK, for example for linked files or masks. We
    4631                 :            :                  * expect that all symlinks within the lookup paths have been already resolved, but we don't
    4632                 :            :                  * verify this here. */
    4633                 :        352 :                 f = fopen(fragment, "re");
    4634         [ -  + ]:        352 :                 if (!f)
    4635         [ #  # ]:          0 :                         return log_unit_notice_errno(u, errno, "Failed to open %s: %m", fragment);
    4636                 :            : 
    4637         [ -  + ]:        352 :                 if (fstat(fileno(f), &st) < 0)
    4638                 :          0 :                         return -errno;
    4639                 :            : 
    4640                 :        352 :                 r = free_and_strdup(&u->fragment_path, fragment);
    4641         [ -  + ]:        352 :                 if (r < 0)
    4642                 :          0 :                         return r;
    4643                 :            : 
    4644         [ -  + ]:        352 :                 if (null_or_empty(&st)) {
    4645                 :          0 :                         u->load_state = UNIT_MASKED;
    4646                 :          0 :                         u->fragment_mtime = 0;
    4647                 :            :                 } else {
    4648                 :        352 :                         u->load_state = UNIT_LOADED;
    4649                 :        352 :                         u->fragment_mtime = timespec_load(&st.st_mtim);
    4650                 :            : 
    4651                 :            :                         /* Now, parse the file contents */
    4652                 :        352 :                         r = config_parse(u->id, fragment, f,
    4653                 :        352 :                                          UNIT_VTABLE(u)->sections,
    4654                 :            :                                          config_item_perf_lookup, load_fragment_gperf_lookup,
    4655                 :            :                                          CONFIG_PARSE_ALLOW_INCLUDE, u);
    4656         [ -  + ]:        352 :                         if (r == -ENOEXEC)
    4657         [ #  # ]:          0 :                                 log_unit_notice_errno(u, r, "Unit configuration has fatal error, unit will not be started.");
    4658         [ -  + ]:        352 :                         if (r < 0)
    4659                 :          0 :                                 return r;
    4660                 :            :                 }
    4661                 :            :         }
    4662                 :            : 
    4663                 :            :         /* We do the merge dance here because for some unit types, the unit might have aliases which are not
    4664                 :            :          * declared in the file system. In particular, this is true (and frequent) for device and swap units.
    4665                 :            :          */
    4666                 :            :         Unit *merged;
    4667                 :       8664 :         const char *id = u->id;
    4668                 :       8664 :         _cleanup_free_ char *free_id = NULL;
    4669                 :            : 
    4670         [ +  + ]:       8664 :         if (fragment) {
    4671                 :        352 :                 id = basename(fragment);
    4672         [ -  + ]:        352 :                 if (unit_name_is_valid(id, UNIT_NAME_TEMPLATE)) {
    4673         [ #  # ]:          0 :                         assert(u->instance); /* If we're not trying to use a template for non-instanced unit,
    4674                 :            :                                               * this must be set. */
    4675                 :            : 
    4676                 :          0 :                         r = unit_name_replace_instance(id, u->instance, &free_id);
    4677         [ #  # ]:          0 :                         if (r < 0)
    4678         [ #  # ]:          0 :                                 return log_debug_errno(r, "Failed to build id (%s + %s): %m", id, u->instance);
    4679                 :          0 :                         id = free_id;
    4680                 :            :                 }
    4681                 :            :         }
    4682                 :            : 
    4683                 :       8664 :         merged = u;
    4684                 :       8664 :         r = merge_by_names(&merged, names, id);
    4685         [ -  + ]:       8664 :         if (r < 0)
    4686                 :          0 :                 return r;
    4687                 :            : 
    4688         [ -  + ]:       8664 :         if (merged != u)
    4689                 :          0 :                 u->load_state = UNIT_MERGED;
    4690                 :            : 
    4691                 :       8664 :         return 0;
    4692                 :            : }
    4693                 :            : 
    4694                 :          4 : void unit_dump_config_items(FILE *f) {
    4695                 :            :         static const struct {
    4696                 :            :                 const ConfigParserCallback callback;
    4697                 :            :                 const char *rvalue;
    4698                 :            :         } table[] = {
    4699                 :            :                 { config_parse_warn_compat,           "NOTSUPPORTED" },
    4700                 :            :                 { config_parse_int,                   "INTEGER" },
    4701                 :            :                 { config_parse_unsigned,              "UNSIGNED" },
    4702                 :            :                 { config_parse_iec_size,              "SIZE" },
    4703                 :            :                 { config_parse_iec_uint64,            "SIZE" },
    4704                 :            :                 { config_parse_si_size,               "SIZE" },
    4705                 :            :                 { config_parse_bool,                  "BOOLEAN" },
    4706                 :            :                 { config_parse_string,                "STRING" },
    4707                 :            :                 { config_parse_path,                  "PATH" },
    4708                 :            :                 { config_parse_unit_path_printf,      "PATH" },
    4709                 :            :                 { config_parse_strv,                  "STRING [...]" },
    4710                 :            :                 { config_parse_exec_nice,             "NICE" },
    4711                 :            :                 { config_parse_exec_oom_score_adjust, "OOMSCOREADJUST" },
    4712                 :            :                 { config_parse_exec_io_class,         "IOCLASS" },
    4713                 :            :                 { config_parse_exec_io_priority,      "IOPRIORITY" },
    4714                 :            :                 { config_parse_exec_cpu_sched_policy, "CPUSCHEDPOLICY" },
    4715                 :            :                 { config_parse_exec_cpu_sched_prio,   "CPUSCHEDPRIO" },
    4716                 :            :                 { config_parse_exec_cpu_affinity,     "CPUAFFINITY" },
    4717                 :            :                 { config_parse_mode,                  "MODE" },
    4718                 :            :                 { config_parse_unit_env_file,         "FILE" },
    4719                 :            :                 { config_parse_exec_output,           "OUTPUT" },
    4720                 :            :                 { config_parse_exec_input,            "INPUT" },
    4721                 :            :                 { config_parse_log_facility,          "FACILITY" },
    4722                 :            :                 { config_parse_log_level,             "LEVEL" },
    4723                 :            :                 { config_parse_exec_secure_bits,      "SECUREBITS" },
    4724                 :            :                 { config_parse_capability_set,        "BOUNDINGSET" },
    4725                 :            :                 { config_parse_rlimit,                "LIMIT" },
    4726                 :            :                 { config_parse_unit_deps,             "UNIT [...]" },
    4727                 :            :                 { config_parse_exec,                  "PATH [ARGUMENT [...]]" },
    4728                 :            :                 { config_parse_service_type,          "SERVICETYPE" },
    4729                 :            :                 { config_parse_service_restart,       "SERVICERESTART" },
    4730                 :            :                 { config_parse_kill_mode,             "KILLMODE" },
    4731                 :            :                 { config_parse_signal,                "SIGNAL" },
    4732                 :            :                 { config_parse_socket_listen,         "SOCKET [...]" },
    4733                 :            :                 { config_parse_socket_bind,           "SOCKETBIND" },
    4734                 :            :                 { config_parse_socket_bindtodevice,   "NETWORKINTERFACE" },
    4735                 :            :                 { config_parse_sec,                   "SECONDS" },
    4736                 :            :                 { config_parse_nsec,                  "NANOSECONDS" },
    4737                 :            :                 { config_parse_namespace_path_strv,   "PATH [...]" },
    4738                 :            :                 { config_parse_bind_paths,            "PATH[:PATH[:OPTIONS]] [...]" },
    4739                 :            :                 { config_parse_unit_requires_mounts_for, "PATH [...]" },
    4740                 :            :                 { config_parse_exec_mount_flags,      "MOUNTFLAG [...]" },
    4741                 :            :                 { config_parse_unit_string_printf,    "STRING" },
    4742                 :            :                 { config_parse_trigger_unit,          "UNIT" },
    4743                 :            :                 { config_parse_timer,                 "TIMER" },
    4744                 :            :                 { config_parse_path_spec,             "PATH" },
    4745                 :            :                 { config_parse_notify_access,         "ACCESS" },
    4746                 :            :                 { config_parse_ip_tos,                "TOS" },
    4747                 :            :                 { config_parse_unit_condition_path,   "CONDITION" },
    4748                 :            :                 { config_parse_unit_condition_string, "CONDITION" },
    4749                 :            :                 { config_parse_unit_condition_null,   "CONDITION" },
    4750                 :            :                 { config_parse_unit_slice,            "SLICE" },
    4751                 :            :                 { config_parse_documentation,         "URL" },
    4752                 :            :                 { config_parse_service_timeout,       "SECONDS" },
    4753                 :            :                 { config_parse_emergency_action,      "ACTION" },
    4754                 :            :                 { config_parse_set_status,            "STATUS" },
    4755                 :            :                 { config_parse_service_sockets,       "SOCKETS" },
    4756                 :            :                 { config_parse_environ,               "ENVIRON" },
    4757                 :            : #if HAVE_SECCOMP
    4758                 :            :                 { config_parse_syscall_filter,        "SYSCALLS" },
    4759                 :            :                 { config_parse_syscall_archs,         "ARCHS" },
    4760                 :            :                 { config_parse_syscall_errno,         "ERRNO" },
    4761                 :            :                 { config_parse_address_families,      "FAMILIES" },
    4762                 :            :                 { config_parse_restrict_namespaces,   "NAMESPACES"  },
    4763                 :            : #endif
    4764                 :            :                 { config_parse_cpu_shares,            "SHARES" },
    4765                 :            :                 { config_parse_cg_weight,             "WEIGHT" },
    4766                 :            :                 { config_parse_memory_limit,          "LIMIT" },
    4767                 :            :                 { config_parse_device_allow,          "DEVICE" },
    4768                 :            :                 { config_parse_device_policy,         "POLICY" },
    4769                 :            :                 { config_parse_io_limit,              "LIMIT" },
    4770                 :            :                 { config_parse_io_device_weight,      "DEVICEWEIGHT" },
    4771                 :            :                 { config_parse_io_device_latency,     "DEVICELATENCY" },
    4772                 :            :                 { config_parse_blockio_bandwidth,     "BANDWIDTH" },
    4773                 :            :                 { config_parse_blockio_weight,        "WEIGHT" },
    4774                 :            :                 { config_parse_blockio_device_weight, "DEVICEWEIGHT" },
    4775                 :            :                 { config_parse_long,                  "LONG" },
    4776                 :            :                 { config_parse_socket_service,        "SERVICE" },
    4777                 :            : #if HAVE_SELINUX
    4778                 :            :                 { config_parse_exec_selinux_context,  "LABEL" },
    4779                 :            : #endif
    4780                 :            :                 { config_parse_job_mode,              "MODE" },
    4781                 :            :                 { config_parse_job_mode_isolate,      "BOOLEAN" },
    4782                 :            :                 { config_parse_personality,           "PERSONALITY" },
    4783                 :            :         };
    4784                 :            : 
    4785                 :          4 :         const char *prev = NULL;
    4786                 :            :         const char *i;
    4787                 :            : 
    4788         [ -  + ]:          4 :         assert(f);
    4789                 :            : 
    4790   [ +  -  +  + ]:       3928 :         NULSTR_FOREACH(i, load_fragment_gperf_nulstr) {
    4791                 :       3924 :                 const char *rvalue = "OTHER", *lvalue;
    4792                 :            :                 const ConfigPerfItem *p;
    4793                 :            :                 size_t prefix_len;
    4794                 :            :                 const char *dot;
    4795                 :            :                 unsigned j;
    4796                 :            : 
    4797         [ -  + ]:       3924 :                 assert_se(p = load_fragment_gperf_lookup(i, strlen(i)));
    4798                 :            : 
    4799                 :            :                 /* Hide legacy settings */
    4800         [ +  + ]:       3924 :                 if (p->parse == config_parse_warn_compat &&
    4801         [ +  + ]:         68 :                     p->ltype == DISABLED_LEGACY)
    4802                 :         52 :                         continue;
    4803                 :            : 
    4804         [ +  + ]:     166220 :                 for (j = 0; j < ELEMENTSOF(table); j++)
    4805         [ +  + ]:     165532 :                         if (p->parse == table[j].callback) {
    4806                 :       3184 :                                 rvalue = table[j].rvalue;
    4807                 :       3184 :                                 break;
    4808                 :            :                         }
    4809                 :            : 
    4810                 :       3872 :                 dot = strchr(i, '.');
    4811         [ +  - ]:       3872 :                 lvalue = dot ? dot + 1 : i;
    4812                 :       3872 :                 prefix_len = dot-i;
    4813                 :            : 
    4814         [ +  - ]:       3872 :                 if (dot)
    4815   [ +  +  +  + ]:       3872 :                         if (!prev || !strneq(prev, i, prefix_len+1)) {
    4816         [ +  + ]:         44 :                                 if (prev)
    4817                 :         40 :                                         fputc('\n', f);
    4818                 :            : 
    4819                 :         44 :                                 fprintf(f, "[%.*s]\n", (int) prefix_len, i);
    4820                 :            :                         }
    4821                 :            : 
    4822                 :       3872 :                 fprintf(f, "%s=%s\n", lvalue, rvalue);
    4823                 :       3872 :                 prev = i;
    4824                 :            :         }
    4825                 :          4 : }
    4826                 :            : 
    4827                 :          0 : int config_parse_cpu_affinity2(
    4828                 :            :                 const char *unit,
    4829                 :            :                 const char *filename,
    4830                 :            :                 unsigned line,
    4831                 :            :                 const char *section,
    4832                 :            :                 unsigned section_line,
    4833                 :            :                 const char *lvalue,
    4834                 :            :                 int ltype,
    4835                 :            :                 const char *rvalue,
    4836                 :            :                 void *data,
    4837                 :            :                 void *userdata) {
    4838                 :            : 
    4839                 :          0 :         CPUSet *affinity = data;
    4840                 :            : 
    4841         [ #  # ]:          0 :         assert(affinity);
    4842                 :            : 
    4843                 :          0 :         (void) parse_cpu_set_extend(rvalue, affinity, true, unit, filename, line, lvalue);
    4844                 :            : 
    4845                 :          0 :         return 0;
    4846                 :            : }
    4847                 :            : 
    4848                 :          0 : int config_parse_show_status(
    4849                 :            :                 const char* unit,
    4850                 :            :                 const char *filename,
    4851                 :            :                 unsigned line,
    4852                 :            :                 const char *section,
    4853                 :            :                 unsigned section_line,
    4854                 :            :                 const char *lvalue,
    4855                 :            :                 int ltype,
    4856                 :            :                 const char *rvalue,
    4857                 :            :                 void *data,
    4858                 :            :                 void *userdata) {
    4859                 :            : 
    4860                 :            :         int k;
    4861                 :          0 :         ShowStatus *b = data;
    4862                 :            : 
    4863         [ #  # ]:          0 :         assert(filename);
    4864         [ #  # ]:          0 :         assert(lvalue);
    4865         [ #  # ]:          0 :         assert(rvalue);
    4866         [ #  # ]:          0 :         assert(data);
    4867                 :            : 
    4868                 :          0 :         k = parse_show_status(rvalue, b);
    4869         [ #  # ]:          0 :         if (k < 0) {
    4870         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse show status setting, ignoring: %s", rvalue);
    4871                 :          0 :                 return 0;
    4872                 :            :         }
    4873                 :            : 
    4874                 :          0 :         return 0;
    4875                 :            : }
    4876                 :            : 
    4877                 :          0 : int config_parse_output_restricted(
    4878                 :            :                 const char* unit,
    4879                 :            :                 const char *filename,
    4880                 :            :                 unsigned line,
    4881                 :            :                 const char *section,
    4882                 :            :                 unsigned section_line,
    4883                 :            :                 const char *lvalue,
    4884                 :            :                 int ltype,
    4885                 :            :                 const char *rvalue,
    4886                 :            :                 void *data,
    4887                 :            :                 void *userdata) {
    4888                 :            : 
    4889                 :          0 :         ExecOutput t, *eo = data;
    4890                 :            : 
    4891         [ #  # ]:          0 :         assert(filename);
    4892         [ #  # ]:          0 :         assert(lvalue);
    4893         [ #  # ]:          0 :         assert(rvalue);
    4894         [ #  # ]:          0 :         assert(data);
    4895                 :            : 
    4896                 :          0 :         t = exec_output_from_string(rvalue);
    4897         [ #  # ]:          0 :         if (t < 0) {
    4898         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse output type, ignoring: %s", rvalue);
    4899                 :          0 :                 return 0;
    4900                 :            :         }
    4901                 :            : 
    4902   [ #  #  #  # ]:          0 :         if (IN_SET(t, EXEC_OUTPUT_SOCKET, EXEC_OUTPUT_NAMED_FD, EXEC_OUTPUT_FILE, EXEC_OUTPUT_FILE_APPEND)) {
    4903         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Standard output types socket, fd:, file:, append: are not supported as defaults, ignoring: %s", rvalue);
    4904                 :          0 :                 return 0;
    4905                 :            :         }
    4906                 :            : 
    4907                 :          0 :         *eo = t;
    4908                 :          0 :         return 0;
    4909                 :            : }
    4910                 :            : 
    4911                 :          0 : int config_parse_crash_chvt(
    4912                 :            :                 const char* unit,
    4913                 :            :                 const char *filename,
    4914                 :            :                 unsigned line,
    4915                 :            :                 const char *section,
    4916                 :            :                 unsigned section_line,
    4917                 :            :                 const char *lvalue,
    4918                 :            :                 int ltype,
    4919                 :            :                 const char *rvalue,
    4920                 :            :                 void *data,
    4921                 :            :                 void *userdata) {
    4922                 :            : 
    4923                 :            :         int r;
    4924                 :            : 
    4925         [ #  # ]:          0 :         assert(filename);
    4926         [ #  # ]:          0 :         assert(lvalue);
    4927         [ #  # ]:          0 :         assert(rvalue);
    4928         [ #  # ]:          0 :         assert(data);
    4929                 :            : 
    4930                 :          0 :         r = parse_crash_chvt(rvalue, data);
    4931         [ #  # ]:          0 :         if (r < 0) {
    4932         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CrashChangeVT= setting, ignoring: %s", rvalue);
    4933                 :          0 :                 return 0;
    4934                 :            :         }
    4935                 :            : 
    4936                 :          0 :         return 0;
    4937                 :            : }
    4938                 :            : 
    4939                 :          0 : int config_parse_timeout_abort(
    4940                 :            :                 const char* unit,
    4941                 :            :                 const char *filename,
    4942                 :            :                 unsigned line,
    4943                 :            :                 const char *section,
    4944                 :            :                 unsigned section_line,
    4945                 :            :                 const char *lvalue,
    4946                 :            :                 int ltype,
    4947                 :            :                 const char *rvalue,
    4948                 :            :                 void *data,
    4949                 :            :                 void *userdata) {
    4950                 :            : 
    4951                 :          0 :         usec_t *timeout_usec = data;
    4952                 :            :         int r;
    4953                 :            : 
    4954         [ #  # ]:          0 :         assert(filename);
    4955         [ #  # ]:          0 :         assert(lvalue);
    4956         [ #  # ]:          0 :         assert(rvalue);
    4957         [ #  # ]:          0 :         assert(timeout_usec);
    4958                 :            : 
    4959                 :          0 :         rvalue += strspn(rvalue, WHITESPACE);
    4960         [ #  # ]:          0 :         if (isempty(rvalue)) {
    4961                 :          0 :                 *timeout_usec = false;
    4962                 :          0 :                 return 0;
    4963                 :            :         }
    4964                 :            : 
    4965                 :          0 :         r = parse_sec(rvalue, timeout_usec);
    4966         [ #  # ]:          0 :         if (r < 0) {
    4967         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse DefaultTimeoutAbortSec= setting, ignoring: %s", rvalue);
    4968                 :          0 :                 return 0;
    4969                 :            :         }
    4970                 :            : 
    4971                 :          0 :         *timeout_usec = true;
    4972                 :          0 :         return 0;
    4973                 :            : }

Generated by: LCOV version 1.14