LCOV - code coverage report
Current view: top level - core - unit-printf.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 65 106 61.3 %
Date: 2019-08-22 15:41:25 Functions: 10 14 71.4 %

          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           3 : static int specifier_prefix_and_instance(char specifier, const void *data, const void *userdata, char **ret) {
      16           3 :         const Unit *u = userdata;
      17             : 
      18           3 :         assert(u);
      19             : 
      20           3 :         return unit_name_to_prefix_and_instance(u->id, ret);
      21             : }
      22             : 
      23           3 : static int specifier_prefix(char specifier, const void *data, const void *userdata, char **ret) {
      24           3 :         const Unit *u = userdata;
      25             : 
      26           3 :         assert(u);
      27             : 
      28           3 :         return unit_name_to_prefix(u->id, ret);
      29             : }
      30             : 
      31           3 : static int specifier_prefix_unescaped(char specifier, const void *data, const void *userdata, char **ret) {
      32           3 :         _cleanup_free_ char *p = NULL;
      33           3 :         const Unit *u = userdata;
      34             :         int r;
      35             : 
      36           3 :         assert(u);
      37             : 
      38           3 :         r = unit_name_to_prefix(u->id, &p);
      39           3 :         if (r < 0)
      40           0 :                 return r;
      41             : 
      42           3 :         return unit_name_unescape(p, ret);
      43             : }
      44             : 
      45           3 : static int specifier_instance_unescaped(char specifier, const void *data, const void *userdata, char **ret) {
      46           3 :         const Unit *u = userdata;
      47             : 
      48           3 :         assert(u);
      49             : 
      50           3 :         return unit_name_unescape(strempty(u->instance), ret);
      51             : }
      52             : 
      53           6 : static int specifier_last_component(char specifier, const void *data, const void *userdata, char **ret) {
      54           6 :         const Unit *u = userdata;
      55           6 :         _cleanup_free_ char *prefix = NULL;
      56             :         char *dash;
      57             :         int r;
      58             : 
      59           6 :         assert(u);
      60             : 
      61           6 :         r = unit_name_to_prefix(u->id, &prefix);
      62           6 :         if (r < 0)
      63           0 :                 return r;
      64             : 
      65           6 :         dash = strrchr(prefix, '-');
      66           6 :         if (dash)
      67           2 :                 return specifier_string(specifier, dash + 1, userdata, ret);
      68             : 
      69           4 :         *ret = TAKE_PTR(prefix);
      70           4 :         return 0;
      71             : }
      72             : 
      73           3 : static int specifier_last_component_unescaped(char specifier, const void *data, const void *userdata, char **ret) {
      74           3 :         _cleanup_free_ char *p = NULL;
      75             :         int r;
      76             : 
      77           3 :         r = specifier_last_component(specifier, data, userdata, &p);
      78           3 :         if (r < 0)
      79           0 :                 return r;
      80             : 
      81           3 :         return unit_name_unescape(p, ret);
      82             : }
      83             : 
      84           3 : static int specifier_filename(char specifier, const void *data, const void *userdata, char **ret) {
      85           3 :         const Unit *u = userdata;
      86             : 
      87           3 :         assert(u);
      88             : 
      89           3 :         if (u->instance)
      90           1 :                 return unit_name_path_unescape(u->instance, ret);
      91             :         else
      92           2 :                 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           2 : static int specifier_special_directory(char specifier, const void *data, const void *userdata, char **ret) {
     161           2 :         const Unit *u = userdata;
     162           2 :         char *n = NULL;
     163             : 
     164           2 :         assert(u);
     165             : 
     166           2 :         n = strdup(u->manager->prefix[PTR_TO_UINT(data)]);
     167           2 :         if (!n)
     168           0 :                 return -ENOMEM;
     169             : 
     170           2 :         *ret = n;
     171           2 :         return 0;
     172             : }
     173             : 
     174         243 : 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         729 :         const Specifier table[] = {
     194         243 :                 { 'n', specifier_string,              u->id },
     195             :                 { 'N', specifier_prefix_and_instance, NULL },
     196             :                 { 'p', specifier_prefix,              NULL },
     197         243 :                 { '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         243 :         assert(u);
     212         243 :         assert(format);
     213         243 :         assert(ret);
     214             : 
     215         243 :         return specifier_printf(format, table, u, ret);
     216             : }
     217             : 
     218         327 : 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         327 :         assert(u);
     248         327 :         assert(format);
     249         327 :         assert(ret);
     250             : 
     251         981 :         const Specifier table[] = {
     252         327 :                 { 'n', specifier_string,                   u->id },
     253             :                 { 'N', specifier_prefix_and_instance,      NULL },
     254             :                 { 'p', specifier_prefix,                   NULL },
     255             :                 { 'P', specifier_prefix_unescaped,         NULL },
     256         327 :                 { '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         327 :         return specifier_printf(format, table, u, ret);
     289             : }

Generated by: LCOV version 1.14