chiark / gitweb /
manager: rework generator logic
[elogind.git] / src / shared / install.c
index a982c54142184b77d32be90bd323bf75feba8922..7e4f666952a9debc438c36e02eed1ac4b09be35c 100644 (file)
 #include "mkdir.h"
 #include "hashmap.h"
 #include "set.h"
+#include "path-util.h"
 #include "path-lookup.h"
 #include "strv.h"
 #include "unit-name.h"
 #include "install.h"
 #include "conf-parser.h"
+#include "conf-files.h"
 
 typedef struct {
         char *name;
@@ -41,6 +43,7 @@ typedef struct {
 
         char **aliases;
         char **wanted_by;
+        char **required_by;
 } InstallInfo;
 
 typedef struct {
@@ -57,7 +60,8 @@ static int lookup_paths_init_from_scope(LookupPaths *paths, UnitFileScope scope)
 
         return lookup_paths_init(paths,
                                  scope == UNIT_FILE_SYSTEM ? MANAGER_SYSTEM : MANAGER_USER,
-                                 scope == UNIT_FILE_USER);
+                                 scope == UNIT_FILE_USER,
+                                 NULL, NULL, NULL);
 }
 
 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
@@ -282,7 +286,7 @@ static int remove_marked_symlinks_fd(
 
                         found =
                                 set_get(remove_symlinks_to, dest) ||
-                                set_get(remove_symlinks_to, file_name_from_path(dest));
+                                set_get(remove_symlinks_to, path_get_file_name(dest));
 
                         if (found) {
 
@@ -467,7 +471,7 @@ static int find_symlinks_fd(
                         if (path_is_absolute(name))
                                 found_dest = path_equal(dest, name);
                         else
-                                found_dest = streq(file_name_from_path(dest), name);
+                                found_dest = streq(path_get_file_name(dest), name);
 
                         free(dest);
 
@@ -753,7 +757,7 @@ int unit_file_link(
                 char *path, *fn;
                 struct stat st;
 
-                fn = file_name_from_path(*i);
+                fn = path_get_file_name(*i);
 
                 if (!path_is_absolute(*i) ||
                     !unit_name_is_valid_no_type(fn, true)) {
@@ -881,6 +885,7 @@ static void install_info_free(InstallInfo *i) {
         free(i->path);
         strv_free(i->aliases);
         strv_free(i->wanted_by);
+        strv_free(i->required_by);
         free(i);
 }
 
@@ -916,7 +921,7 @@ static int install_info_add(
         assert(name || path);
 
         if (!name)
-                name = file_name_from_path(path);
+                name = path_get_file_name(path);
 
         if (!unit_name_is_valid_no_type(name, true))
                 return -EINVAL;
@@ -1019,9 +1024,10 @@ static int unit_file_load(
                 bool allow_symlink) {
 
         const ConfigTableItem items[] = {
-                { "Install", "Alias",    config_parse_strv, 0, &info->aliases   },
-                { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
-                { "Install", "Also",     config_parse_also, 0, c                },
+                { "Install", "Alias",      config_parse_strv, 0, &info->aliases     },
+                { "Install", "WantedBy",   config_parse_strv, 0, &info->wanted_by   },
+                { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
+                { "Install", "Also",       config_parse_also, 0, c                  },
                 { NULL, NULL, NULL, 0, NULL }
         };
 
@@ -1048,7 +1054,10 @@ static int unit_file_load(
         if (r < 0)
                 return r;
 
-        return strv_length(info->aliases) + strv_length(info->wanted_by);
+        return
+                strv_length(info->aliases) +
+                strv_length(info->wanted_by) +
+                strv_length(info->required_by);
 }
 
 static int unit_file_search(
@@ -1119,7 +1128,10 @@ static int unit_file_can_install(
         r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
 
         if (r >= 0)
-                r = strv_length(i->aliases) + strv_length(i->wanted_by);
+                r =
+                        strv_length(i->aliases) +
+                        strv_length(i->wanted_by) +
+                        strv_length(i->required_by);
 
         install_context_done(&c);
 
@@ -1160,7 +1172,7 @@ static int create_symlink(
 
         free(dest);
 
-        if (force)
+        if (!force)
                 return -EEXIST;
 
         unlink(new_path);
@@ -1239,6 +1251,40 @@ static int install_info_symlink_wants(
         return r;
 }
 
+static int install_info_symlink_requires(
+                InstallInfo *i,
+                const char *config_path,
+                bool force,
+                UnitFileChange **changes,
+                unsigned *n_changes) {
+
+        char **s;
+        int r = 0, q;
+
+        assert(i);
+        assert(config_path);
+
+        STRV_FOREACH(s, i->required_by) {
+                char *path;
+
+                if (!unit_name_is_valid_no_type(*s, true)) {
+                        r = -EINVAL;
+                        continue;
+                }
+
+                if (asprintf(&path, "%s/%s.requires/%s", config_path, *s, i->name) < 0)
+                        return -ENOMEM;
+
+                q = create_symlink(i->path, path, force, changes, n_changes);
+                free(path);
+
+                if (r == 0)
+                        r = q;
+        }
+
+        return r;
+}
+
 static int install_info_symlink_link(
                 InstallInfo *i,
                 LookupPaths *paths,
@@ -1288,6 +1334,10 @@ static int install_info_apply(
         if (r == 0)
                 r = q;
 
+        q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
+        if (r == 0)
+                r = q;
+
         q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
         if (r == 0)
                 r = q;
@@ -1914,7 +1964,7 @@ int unit_file_get_list(
                         continue;
 
                 found:
-                        r = hashmap_put(h, file_name_from_path(f->path), f);
+                        r = hashmap_put(h, path_get_file_name(f->path), f);
                         if (r < 0) {
                                 free(f->path);
                                 free(f);