LCOV - code coverage report
Current view: top level - shared - dropin.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 18 112 16.1 %
Date: 2015-07-29 18:47:03 Functions: 2 6 33.3 %

          Line data    Source code
       1             : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
       2             : 
       3             : /***
       4             :   This file is part of systemd.
       5             : 
       6             :   Copyright 2014 Zbigniew Jędrzejewski-Szmek
       7             : 
       8             :   systemd is free software; you can redistribute it and/or modify it
       9             :   under the terms of the GNU Lesser General Public License as published by
      10             :   the Free Software Foundation; either version 2.1 of the License, or
      11             :   (at your option) any later version.
      12             : 
      13             :   systemd is distributed in the hope that it will be useful, but
      14             :   WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      16             :   Lesser General Public License for more details.
      17             : 
      18             :   You should have received a copy of the GNU Lesser General Public License
      19             :   along with systemd; If not, see <http://www.gnu.org/licenses/>.
      20             : ***/
      21             : 
      22             : #include "dropin.h"
      23             : #include "util.h"
      24             : #include "strv.h"
      25             : #include "mkdir.h"
      26             : #include "fileio-label.h"
      27             : #include "conf-files.h"
      28             : 
      29           0 : int drop_in_file(const char *dir, const char *unit, unsigned level,
      30             :                  const char *name, char **_p, char **_q) {
      31             : 
      32           0 :         _cleanup_free_ char *b = NULL;
      33             :         char *p, *q;
      34             : 
      35             :         char prefix[DECIMAL_STR_MAX(unsigned)];
      36             : 
      37           0 :         assert(unit);
      38           0 :         assert(name);
      39           0 :         assert(_p);
      40           0 :         assert(_q);
      41             : 
      42           0 :         sprintf(prefix, "%u", level);
      43             : 
      44           0 :         b = xescape(name, "/.");
      45           0 :         if (!b)
      46           0 :                 return -ENOMEM;
      47             : 
      48           0 :         if (!filename_is_valid(b))
      49           0 :                 return -EINVAL;
      50             : 
      51           0 :         p = strjoin(dir, "/", unit, ".d", NULL);
      52           0 :         if (!p)
      53           0 :                 return -ENOMEM;
      54             : 
      55           0 :         q = strjoin(p, "/", prefix, "-", b, ".conf", NULL);
      56           0 :         if (!q) {
      57           0 :                 free(p);
      58           0 :                 return -ENOMEM;
      59             :         }
      60             : 
      61           0 :         *_p = p;
      62           0 :         *_q = q;
      63           0 :         return 0;
      64             : }
      65             : 
      66           0 : int write_drop_in(const char *dir, const char *unit, unsigned level,
      67             :                   const char *name, const char *data) {
      68             : 
      69           0 :         _cleanup_free_ char *p = NULL, *q = NULL;
      70             :         int r;
      71             : 
      72           0 :         assert(dir);
      73           0 :         assert(unit);
      74           0 :         assert(name);
      75           0 :         assert(data);
      76             : 
      77           0 :         r = drop_in_file(dir, unit, level, name, &p, &q);
      78           0 :         if (r < 0)
      79           0 :                 return r;
      80             : 
      81           0 :         mkdir_p(p, 0755);
      82           0 :         return write_string_file_atomic_label(q, data);
      83             : }
      84             : 
      85           0 : int write_drop_in_format(const char *dir, const char *unit, unsigned level,
      86             :                          const char *name, const char *format, ...) {
      87           0 :         _cleanup_free_ char *p = NULL;
      88             :         va_list ap;
      89             :         int r;
      90             : 
      91           0 :         assert(dir);
      92           0 :         assert(unit);
      93           0 :         assert(name);
      94           0 :         assert(format);
      95             : 
      96           0 :         va_start(ap, format);
      97           0 :         r = vasprintf(&p, format, ap);
      98           0 :         va_end(ap);
      99             : 
     100           0 :         if (r < 0)
     101           0 :                 return -ENOMEM;
     102             : 
     103           0 :         return write_drop_in(dir, unit, level, name, p);
     104             : }
     105             : 
     106           0 : static int iterate_dir(
     107             :                 const char *path,
     108             :                 UnitDependency dependency,
     109             :                 dependency_consumer_t consumer,
     110             :                 void *arg,
     111             :                 char ***strv) {
     112             : 
     113           0 :         _cleanup_closedir_ DIR *d = NULL;
     114             :         int r;
     115             : 
     116           0 :         assert(path);
     117             : 
     118             :         /* The config directories are special, since the order of the
     119             :          * drop-ins matters */
     120           0 :         if (dependency < 0)  {
     121           0 :                 r = strv_extend(strv, path);
     122           0 :                 if (r < 0)
     123           0 :                         return log_oom();
     124             : 
     125           0 :                 return 0;
     126             :         }
     127             : 
     128           0 :         assert(consumer);
     129             : 
     130           0 :         d = opendir(path);
     131           0 :         if (!d) {
     132           0 :                 if (errno == ENOENT)
     133           0 :                         return 0;
     134             : 
     135           0 :                 log_error_errno(errno, "Failed to open directory %s: %m", path);
     136           0 :                 return -errno;
     137             :         }
     138             : 
     139             :         for (;;) {
     140             :                 struct dirent *de;
     141           0 :                 _cleanup_free_ char *f = NULL;
     142             : 
     143           0 :                 errno = 0;
     144           0 :                 de = readdir(d);
     145           0 :                 if (!de && errno != 0)
     146           0 :                         return log_error_errno(errno, "Failed to read directory %s: %m", path);
     147             : 
     148           0 :                 if (!de)
     149           0 :                         break;
     150             : 
     151           0 :                 if (hidden_file(de->d_name))
     152           0 :                         continue;
     153             : 
     154           0 :                 f = strjoin(path, "/", de->d_name, NULL);
     155           0 :                 if (!f)
     156           0 :                         return log_oom();
     157             : 
     158           0 :                 r = consumer(dependency, de->d_name, f, arg);
     159           0 :                 if (r < 0)
     160           0 :                         return r;
     161           0 :         }
     162             : 
     163           0 :         return 0;
     164             : }
     165             : 
     166        2539 : int unit_file_process_dir(
     167             :                 Set *unit_path_cache,
     168             :                 const char *unit_path,
     169             :                 const char *name,
     170             :                 const char *suffix,
     171             :                 UnitDependency dependency,
     172             :                 dependency_consumer_t consumer,
     173             :                 void *arg,
     174             :                 char ***strv) {
     175             : 
     176        5078 :         _cleanup_free_ char *path = NULL;
     177             :         int r;
     178             : 
     179        2539 :         assert(unit_path);
     180        2539 :         assert(name);
     181        2539 :         assert(suffix);
     182             : 
     183        2539 :         path = strjoin(unit_path, "/", name, suffix, NULL);
     184        2539 :         if (!path)
     185           0 :                 return log_oom();
     186             : 
     187        2539 :         if (!unit_path_cache || set_get(unit_path_cache, path))
     188           0 :                 (void) iterate_dir(path, dependency, consumer, arg, strv);
     189             : 
     190        2539 :         if (unit_name_is_valid(name, UNIT_NAME_INSTANCE)) {
     191           0 :                 _cleanup_free_ char *template = NULL, *p = NULL;
     192             :                 /* Also try the template dir */
     193             : 
     194           0 :                 r = unit_name_template(name, &template);
     195           0 :                 if (r < 0)
     196           0 :                         return log_error_errno(r, "Failed to generate template from unit name: %m");
     197             : 
     198           0 :                 p = strjoin(unit_path, "/", template, suffix, NULL);
     199           0 :                 if (!p)
     200           0 :                         return log_oom();
     201             : 
     202           0 :                 if (!unit_path_cache || set_get(unit_path_cache, p))
     203           0 :                         (void) iterate_dir(p, dependency, consumer, arg, strv);
     204             :         }
     205             : 
     206        2539 :         return 0;
     207             : }
     208             : 
     209        1057 : int unit_file_find_dropin_paths(
     210             :                 char **lookup_path,
     211             :                 Set *unit_path_cache,
     212             :                 Set *names,
     213             :                 char ***paths) {
     214             : 
     215        2114 :         _cleanup_strv_free_ char **strv = NULL, **ans = NULL;
     216             :         Iterator i;
     217             :         char *t;
     218             :         int r;
     219             : 
     220        1057 :         assert(paths);
     221             : 
     222        3177 :         SET_FOREACH(t, names, i) {
     223             :                 char **p;
     224             : 
     225        2126 :                 STRV_FOREACH(p, lookup_path)
     226        1063 :                         unit_file_process_dir(unit_path_cache, *p, t, ".d", _UNIT_DEPENDENCY_INVALID, NULL, NULL, &strv);
     227             :         }
     228             : 
     229        1057 :         if (strv_isempty(strv))
     230        1057 :                 return 0;
     231             : 
     232           0 :         r = conf_files_list_strv(&ans, ".conf", NULL, (const char**) strv);
     233           0 :         if (r < 0)
     234           0 :                 return log_warning_errno(r, "Failed to get list of configuration files: %m");
     235             : 
     236           0 :         *paths = ans;
     237           0 :         ans = NULL;
     238           0 :         return 1;
     239             : }

Generated by: LCOV version 1.11