LCOV - code coverage report
Current view: top level - core - unit-printf.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 65 106 61.3 %
Date: 2019-08-23 13:36:53 Functions: 10 14 71.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 21 58 36.2 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include "alloc-util.h"
       4                 :            : #include "cgroup-util.h"
       5                 :            : #include "format-util.h"
       6                 :            : #include "macro.h"
       7                 :            : #include "specifier.h"
       8                 :            : #include "string-util.h"
       9                 :            : #include "strv.h"
      10                 :            : #include "unit-name.h"
      11                 :            : #include "unit-printf.h"
      12                 :            : #include "unit.h"
      13                 :            : #include "user-util.h"
      14                 :            : 
      15                 :         12 : static int specifier_prefix_and_instance(char specifier, const void *data, const void *userdata, char **ret) {
      16                 :         12 :         const Unit *u = userdata;
      17                 :            : 
      18         [ -  + ]:         12 :         assert(u);
      19                 :            : 
      20                 :         12 :         return unit_name_to_prefix_and_instance(u->id, ret);
      21                 :            : }
      22                 :            : 
      23                 :         12 : static int specifier_prefix(char specifier, const void *data, const void *userdata, char **ret) {
      24                 :         12 :         const Unit *u = userdata;
      25                 :            : 
      26         [ -  + ]:         12 :         assert(u);
      27                 :            : 
      28                 :         12 :         return unit_name_to_prefix(u->id, ret);
      29                 :            : }
      30                 :            : 
      31                 :         12 : static int specifier_prefix_unescaped(char specifier, const void *data, const void *userdata, char **ret) {
      32                 :         12 :         _cleanup_free_ char *p = NULL;
      33                 :         12 :         const Unit *u = userdata;
      34                 :            :         int r;
      35                 :            : 
      36         [ -  + ]:         12 :         assert(u);
      37                 :            : 
      38                 :         12 :         r = unit_name_to_prefix(u->id, &p);
      39         [ -  + ]:         12 :         if (r < 0)
      40                 :          0 :                 return r;
      41                 :            : 
      42                 :         12 :         return unit_name_unescape(p, ret);
      43                 :            : }
      44                 :            : 
      45                 :         12 : static int specifier_instance_unescaped(char specifier, const void *data, const void *userdata, char **ret) {
      46                 :         12 :         const Unit *u = userdata;
      47                 :            : 
      48         [ -  + ]:         12 :         assert(u);
      49                 :            : 
      50                 :         12 :         return unit_name_unescape(strempty(u->instance), ret);
      51                 :            : }
      52                 :            : 
      53                 :         24 : static int specifier_last_component(char specifier, const void *data, const void *userdata, char **ret) {
      54                 :         24 :         const Unit *u = userdata;
      55                 :         24 :         _cleanup_free_ char *prefix = NULL;
      56                 :            :         char *dash;
      57                 :            :         int r;
      58                 :            : 
      59         [ -  + ]:         24 :         assert(u);
      60                 :            : 
      61                 :         24 :         r = unit_name_to_prefix(u->id, &prefix);
      62         [ -  + ]:         24 :         if (r < 0)
      63                 :          0 :                 return r;
      64                 :            : 
      65                 :         24 :         dash = strrchr(prefix, '-');
      66         [ +  + ]:         24 :         if (dash)
      67                 :          8 :                 return specifier_string(specifier, dash + 1, userdata, ret);
      68                 :            : 
      69                 :         16 :         *ret = TAKE_PTR(prefix);
      70                 :         16 :         return 0;
      71                 :            : }
      72                 :            : 
      73                 :         12 : static int specifier_last_component_unescaped(char specifier, const void *data, const void *userdata, char **ret) {
      74                 :         12 :         _cleanup_free_ char *p = NULL;
      75                 :            :         int r;
      76                 :            : 
      77                 :         12 :         r = specifier_last_component(specifier, data, userdata, &p);
      78         [ -  + ]:         12 :         if (r < 0)
      79                 :          0 :                 return r;
      80                 :            : 
      81                 :         12 :         return unit_name_unescape(p, ret);
      82                 :            : }
      83                 :            : 
      84                 :         12 : static int specifier_filename(char specifier, const void *data, const void *userdata, char **ret) {
      85                 :         12 :         const Unit *u = userdata;
      86                 :            : 
      87         [ -  + ]:         12 :         assert(u);
      88                 :            : 
      89         [ +  + ]:         12 :         if (u->instance)
      90                 :          4 :                 return unit_name_path_unescape(u->instance, ret);
      91                 :            :         else
      92                 :          8 :                 return unit_name_to_path(u->id, ret);
      93                 :            : }
      94                 :            : 
      95                 :          0 : static void bad_specifier(const Unit *u, char specifier) {
      96         [ #  # ]:          0 :         log_unit_warning(u, "Specifier '%%%c' used in unit configuration, which is deprecated. Please update your unit file, as it does not work as intended.", specifier);
      97                 :          0 : }
      98                 :            : 
      99                 :          0 : static int specifier_cgroup(char specifier, const void *data, const void *userdata, char **ret) {
     100                 :          0 :         const Unit *u = userdata;
     101                 :            :         char *n;
     102                 :            : 
     103         [ #  # ]:          0 :         assert(u);
     104                 :            : 
     105                 :          0 :         bad_specifier(u, specifier);
     106                 :            : 
     107         [ #  # ]:          0 :         if (u->cgroup_path)
     108                 :          0 :                 n = strdup(u->cgroup_path);
     109                 :            :         else
     110                 :          0 :                 n = unit_default_cgroup_path(u);
     111         [ #  # ]:          0 :         if (!n)
     112                 :          0 :                 return -ENOMEM;
     113                 :            : 
     114                 :          0 :         *ret = n;
     115                 :          0 :         return 0;
     116                 :            : }
     117                 :            : 
     118                 :          0 : static int specifier_cgroup_root(char specifier, const void *data, const void *userdata, char **ret) {
     119                 :          0 :         const Unit *u = userdata;
     120                 :            :         char *n;
     121                 :            : 
     122         [ #  # ]:          0 :         assert(u);
     123                 :            : 
     124                 :          0 :         bad_specifier(u, specifier);
     125                 :            : 
     126                 :          0 :         n = strdup(u->manager->cgroup_root);
     127         [ #  # ]:          0 :         if (!n)
     128                 :          0 :                 return -ENOMEM;
     129                 :            : 
     130                 :          0 :         *ret = n;
     131                 :          0 :         return 0;
     132                 :            : }
     133                 :            : 
     134                 :          0 : static int specifier_cgroup_slice(char specifier, const void *data, const void *userdata, char **ret) {
     135                 :          0 :         const Unit *u = userdata;
     136                 :            :         char *n;
     137                 :            : 
     138         [ #  # ]:          0 :         assert(u);
     139                 :            : 
     140                 :          0 :         bad_specifier(u, specifier);
     141                 :            : 
     142         [ #  # ]:          0 :         if (UNIT_ISSET(u->slice)) {
     143                 :            :                 const Unit *slice;
     144                 :            : 
     145                 :          0 :                 slice = UNIT_DEREF(u->slice);
     146                 :            : 
     147         [ #  # ]:          0 :                 if (slice->cgroup_path)
     148                 :          0 :                         n = strdup(slice->cgroup_path);
     149                 :            :                 else
     150                 :          0 :                         n = unit_default_cgroup_path(slice);
     151                 :            :         } else
     152                 :          0 :                 n = strdup(u->manager->cgroup_root);
     153         [ #  # ]:          0 :         if (!n)
     154                 :          0 :                 return -ENOMEM;
     155                 :            : 
     156                 :          0 :         *ret = n;
     157                 :          0 :         return 0;
     158                 :            : }
     159                 :            : 
     160                 :          8 : static int specifier_special_directory(char specifier, const void *data, const void *userdata, char **ret) {
     161                 :          8 :         const Unit *u = userdata;
     162                 :          8 :         char *n = NULL;
     163                 :            : 
     164         [ -  + ]:          8 :         assert(u);
     165                 :            : 
     166                 :          8 :         n = strdup(u->manager->prefix[PTR_TO_UINT(data)]);
     167         [ -  + ]:          8 :         if (!n)
     168                 :          0 :                 return -ENOMEM;
     169                 :            : 
     170                 :          8 :         *ret = n;
     171                 :          8 :         return 0;
     172                 :            : }
     173                 :            : 
     174                 :        972 : int unit_name_printf(Unit *u, const char* format, char **ret) {
     175                 :            : 
     176                 :            :         /*
     177                 :            :          * This will use the passed string as format string and replace the following specifiers (which should all be
     178                 :            :          * safe for inclusion in unit names):
     179                 :            :          *
     180                 :            :          * %n: the full id of the unit                 (foo@bar.waldo)
     181                 :            :          * %N: the id of the unit without the suffix   (foo@bar)
     182                 :            :          * %p: the prefix                              (foo)
     183                 :            :          * %i: the instance                            (bar)
     184                 :            :          *
     185                 :            :          * %U: the UID of the running user
     186                 :            :          * %u: the username of the running user
     187                 :            :          *
     188                 :            :          * %m: the machine ID of the running system
     189                 :            :          * %H: the host name of the running system
     190                 :            :          * %b: the boot ID of the running system
     191                 :            :          */
     192                 :            : 
     193                 :       2916 :         const Specifier table[] = {
     194                 :        972 :                 { 'n', specifier_string,              u->id },
     195                 :            :                 { 'N', specifier_prefix_and_instance, NULL },
     196                 :            :                 { 'p', specifier_prefix,              NULL },
     197                 :        972 :                 { 'i', specifier_string,              u->instance },
     198                 :            :                 { 'j', specifier_last_component,      NULL },
     199                 :            : 
     200                 :            :                 { 'g', specifier_group_name,          NULL },
     201                 :            :                 { 'G', specifier_group_id,            NULL },
     202                 :            :                 { 'U', specifier_user_id,             NULL },
     203                 :            :                 { 'u', specifier_user_name,           NULL },
     204                 :            : 
     205                 :            :                 { 'm', specifier_machine_id,          NULL },
     206                 :            :                 { 'H', specifier_host_name,           NULL },
     207                 :            :                 { 'b', specifier_boot_id,             NULL },
     208                 :            :                 {}
     209                 :            :         };
     210                 :            : 
     211         [ -  + ]:        972 :         assert(u);
     212         [ -  + ]:        972 :         assert(format);
     213         [ -  + ]:        972 :         assert(ret);
     214                 :            : 
     215                 :        972 :         return specifier_printf(format, table, u, ret);
     216                 :            : }
     217                 :            : 
     218                 :       1308 : int unit_full_printf(Unit *u, const char *format, char **ret) {
     219                 :            : 
     220                 :            :         /* This is similar to unit_name_printf() but also supports unescaping. Also, adds a couple of additional codes
     221                 :            :          * (which are likely not suitable for unescaped inclusion in unit names):
     222                 :            :          *
     223                 :            :          * %f: the unescaped instance if set, otherwise the id unescaped as path
     224                 :            :          *
     225                 :            :          * %c: cgroup path of unit (deprecated)
     226                 :            :          * %r: where units in this slice are placed in the cgroup tree (deprecated)
     227                 :            :          * %R: the root of this systemd's instance tree (deprecated)
     228                 :            :          *
     229                 :            :          * %t: the runtime directory root (e.g. /run or $XDG_RUNTIME_DIR)
     230                 :            :          * %S: the state directory root (e.g. /var/lib or $XDG_CONFIG_HOME)
     231                 :            :          * %C: the cache directory root (e.g. /var/cache or $XDG_CACHE_HOME)
     232                 :            :          * %L: the log directory root (e.g. /var/log or $XDG_CONFIG_HOME/log)
     233                 :            :          * %E: the configuration directory root (e.g. /etc or $XDG_CONFIG_HOME)
     234                 :            :          * %T: the temporary directory (e.g. /tmp, or $TMPDIR, $TEMP, $TMP)
     235                 :            :          * %V: the temporary directory for large, persistent stuff (e.g. /var/tmp, or $TMPDIR, $TEMP, $TMP)
     236                 :            :          *
     237                 :            :          * %h: the homedir of the running user
     238                 :            :          * %s: the shell of the running user
     239                 :            :          *
     240                 :            :          * %v: `uname -r` of the running system
     241                 :            :          *
     242                 :            :          * NOTICE: When you add new entries here, please be careful: specifiers which depend on settings of the unit
     243                 :            :          * file itself are broken by design, as they would resolve differently depending on whether they are used
     244                 :            :          * before or after the relevant configuration setting. Hence: don't add them.
     245                 :            :          */
     246                 :            : 
     247         [ -  + ]:       1308 :         assert(u);
     248         [ -  + ]:       1308 :         assert(format);
     249         [ -  + ]:       1308 :         assert(ret);
     250                 :            : 
     251                 :       3924 :         const Specifier table[] = {
     252                 :       1308 :                 { 'n', specifier_string,                   u->id },
     253                 :            :                 { 'N', specifier_prefix_and_instance,      NULL },
     254                 :            :                 { 'p', specifier_prefix,                   NULL },
     255                 :            :                 { 'P', specifier_prefix_unescaped,         NULL },
     256                 :       1308 :                 { 'i', specifier_string,                   u->instance },
     257                 :            :                 { 'I', specifier_instance_unescaped,       NULL },
     258                 :            :                 { 'j', specifier_last_component,           NULL },
     259                 :            :                 { 'J', specifier_last_component_unescaped, NULL },
     260                 :            : 
     261                 :            :                 { 'f', specifier_filename,                 NULL },
     262                 :            :                 { 'c', specifier_cgroup,                   NULL },
     263                 :            :                 { 'r', specifier_cgroup_slice,             NULL },
     264                 :            :                 { 'R', specifier_cgroup_root,              NULL },
     265                 :            : 
     266                 :            :                 { 't', specifier_special_directory,        UINT_TO_PTR(EXEC_DIRECTORY_RUNTIME) },
     267                 :            :                 { 'S', specifier_special_directory,        UINT_TO_PTR(EXEC_DIRECTORY_STATE) },
     268                 :            :                 { 'C', specifier_special_directory,        UINT_TO_PTR(EXEC_DIRECTORY_CACHE) },
     269                 :            :                 { 'L', specifier_special_directory,        UINT_TO_PTR(EXEC_DIRECTORY_LOGS) },
     270                 :            :                 { 'E', specifier_special_directory,        UINT_TO_PTR(EXEC_DIRECTORY_CONFIGURATION) },
     271                 :            :                 { 'T', specifier_tmp_dir,                  NULL },
     272                 :            :                 { 'V', specifier_var_tmp_dir,              NULL },
     273                 :            : 
     274                 :            :                 { 'g', specifier_group_name,               NULL },
     275                 :            :                 { 'G', specifier_group_id,                 NULL },
     276                 :            :                 { 'U', specifier_user_id,                  NULL },
     277                 :            :                 { 'u', specifier_user_name,                NULL },
     278                 :            :                 { 'h', specifier_user_home,                NULL },
     279                 :            :                 { 's', specifier_user_shell,               NULL },
     280                 :            : 
     281                 :            :                 { 'm', specifier_machine_id,               NULL },
     282                 :            :                 { 'H', specifier_host_name,                NULL },
     283                 :            :                 { 'b', specifier_boot_id,                  NULL },
     284                 :            :                 { 'v', specifier_kernel_release,           NULL },
     285                 :            :                 {}
     286                 :            :         };
     287                 :            : 
     288                 :       1308 :         return specifier_printf(format, table, u, ret);
     289                 :            : }

Generated by: LCOV version 1.14