chiark / gitweb /
tmpfiles: add new "C" line for copying files or directories
[elogind.git] / src / shared / install.c
index 9ce94035b92096e316a051e5c66dae32827427cd..487d0f660d40b6f13d3be1435e9d4a65a6dd187c 100644 (file)
@@ -47,7 +47,9 @@ typedef struct {
 
 #define _cleanup_install_context_done_ _cleanup_(install_context_done)
 
-static int lookup_paths_init_from_scope(LookupPaths *paths, UnitFileScope scope) {
+static int lookup_paths_init_from_scope(LookupPaths *paths,
+                                        UnitFileScope scope,
+                                        const char *root_dir) {
         assert(paths);
         assert(scope >= 0);
         assert(scope < _UNIT_FILE_SCOPE_MAX);
@@ -57,6 +59,7 @@ static int lookup_paths_init_from_scope(LookupPaths *paths, UnitFileScope scope)
         return lookup_paths_init(paths,
                                  scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
                                  scope == UNIT_FILE_USER,
+                                 root_dir,
                                  NULL, NULL, NULL);
 }
 
@@ -701,7 +704,7 @@ int unit_file_link(
         assert(scope >= 0);
         assert(scope < _UNIT_FILE_SCOPE_MAX);
 
-        r = lookup_paths_init_from_scope(&paths, scope);
+        r = lookup_paths_init_from_scope(&paths, scope, root_dir);
         if (r < 0)
                 return r;
 
@@ -1037,67 +1040,64 @@ static int unit_file_search(
         assert(info);
         assert(paths);
 
-        if (info->path)
-                return unit_file_load(c, info, info->path, allow_symlink);
+        if (info->path) {
+                char *full_path = NULL;
+
+                if (!isempty(root_dir))
+                        full_path = strappenda(root_dir, info->path);
+
+                return unit_file_load(c, info, full_path ?: info->path, allow_symlink);
+        }
 
         assert(info->name);
 
         STRV_FOREACH(p, paths->unit_path) {
-                char *path = NULL;
-
-                if (isempty(root_dir))
-                        asprintf(&path, "%s/%s", *p, info->name);
-                else
-                        asprintf(&path, "%s/%s/%s", root_dir, *p, info->name);
+                _cleanup_free_ char *path = NULL, *full_path = NULL;
 
+                path = strjoin(*p, "/", info->name, NULL);
                 if (!path)
                         return -ENOMEM;
 
-                r = unit_file_load(c, info, path, allow_symlink);
+                if (!isempty(root_dir)) {
+                        full_path = strappend(root_dir, path);
+                        if (!full_path)
+                                return -ENOMEM;
+                }
 
-                if (r >= 0)
+                r = unit_file_load(c, info, full_path ?: path, allow_symlink);
+                if (r >= 0) {
                         info->path = path;
-                else {
-                        if (r == -ENOENT && unit_name_is_instance(info->name)) {
-                                /* Unit file doesn't exist, however instance enablement was requested.
-                                 * We will check if it is possible to load template unit file. */
-                                char *template = NULL,
-                                     *template_path = NULL,
-                                     *template_dir = NULL;
-
-                                template = unit_name_template(info->name);
-                                if (!template) {
-                                        free(path);
-                                        return -ENOMEM;
-                                }
+                        path = NULL;
+                } else if (r == -ENOENT && unit_name_is_instance(info->name)) {
+                        /* Unit file doesn't exist, however instance enablement was requested.
+                         * We will check if it is possible to load template unit file. */
+                        _cleanup_free_ char *template = NULL, *template_dir = NULL;
+
+                        template = unit_name_template(info->name);
+                        if (!template)
+                                return -ENOMEM;
 
-                                /* We will reuse path variable since we don't need it anymore. */
-                                template_dir = path;
-                                *(strrchr(path, '/') + 1) = '\0';
+                        /* We will reuse path variable since we don't need it anymore. */
+                        template_dir = path;
+                        *(strrchr(template_dir, '/') + 1) = '\0';
 
-                                template_path = strjoin(template_dir, template, NULL);
-                                if (!template_path) {
-                                        free(path);
-                                        free(template);
-                                        return -ENOMEM;
-                                }
+                        path = strappend(template_dir, template);
+                        if (!path)
+                                return -ENOMEM;
 
-                                /* Let's try to load template unit. */
-                                r = unit_file_load(c, info, template_path, allow_symlink);
-                                if (r >= 0) {
-                                        info->path = strdup(template_path);
-                                        if (!info->path) {
-                                                free(path);
-                                                free(template);
-                                                free(template_path);
-                                                return -ENOMEM;
-                                        }
-                                }
+                        if (!isempty(root_dir)) {
+                                free(full_path);
+                                full_path = strappend(root_dir, path);
+                                if (!full_path)
+                                        return -ENOMEM;
+                        }
 
-                                free(template);
-                                free(template_path);
+                        /* Let's try to load template unit. */
+                        r = unit_file_load(c, info, full_path ?: path, allow_symlink);
+                        if (r >= 0) {
+                                info->path = path;
+                                path = NULL;
                         }
-                        free(path);
                 }
 
                 if (r != -ENOENT && r != -ELOOP)
@@ -1476,7 +1476,7 @@ int unit_file_enable(
         assert(scope >= 0);
         assert(scope < _UNIT_FILE_SCOPE_MAX);
 
-        r = lookup_paths_init_from_scope(&paths, scope);
+        r = lookup_paths_init_from_scope(&paths, scope, root_dir);
         if (r < 0)
                 return r;
 
@@ -1516,7 +1516,7 @@ int unit_file_disable(
         assert(scope >= 0);
         assert(scope < _UNIT_FILE_SCOPE_MAX);
 
-        r = lookup_paths_init_from_scope(&paths, scope);
+        r = lookup_paths_init_from_scope(&paths, scope, root_dir);
         if (r < 0)
                 return r;
 
@@ -1580,7 +1580,7 @@ int unit_file_set_default(
         if (unit_name_to_type(file) != UNIT_TARGET)
                 return -EINVAL;
 
-        r = lookup_paths_init_from_scope(&paths, scope);
+        r = lookup_paths_init_from_scope(&paths, scope, root_dir);
         if (r < 0)
                 return r;
 
@@ -1620,7 +1620,7 @@ int unit_file_get_default(
         assert(scope < _UNIT_FILE_SCOPE_MAX);
         assert(name);
 
-        r = lookup_paths_init_from_scope(&paths, scope);
+        r = lookup_paths_init_from_scope(&paths, scope, root_dir);
         if (r < 0)
                 return r;
 
@@ -1678,12 +1678,13 @@ UnitFileState unit_file_get_state(
         if (!unit_name_is_valid(name, TEMPLATE_VALID))
                 return -EINVAL;
 
-        r = lookup_paths_init_from_scope(&paths, scope);
+        r = lookup_paths_init_from_scope(&paths, scope, root_dir);
         if (r < 0)
                 return r;
 
         STRV_FOREACH(i, paths.unit_path) {
                 struct stat st;
+                char *partial;
 
                 free(path);
                 path = NULL;
@@ -1692,10 +1693,14 @@ UnitFileState unit_file_get_state(
                         asprintf(&path, "%s/%s/%s", root_dir, *i, name);
                 else
                         asprintf(&path, "%s/%s", *i, name);
-
                 if (!path)
                         return -ENOMEM;
 
+                if (root_dir)
+                        partial = path + strlen(root_dir) + 1;
+                else
+                        partial = path;
+
                 /*
                  * Search for a unit file in our default paths, to
                  * be sure, that there are no broken symlinks.
@@ -1727,7 +1732,7 @@ UnitFileState unit_file_get_state(
                 else if (r > 0)
                         return state;
 
-                r = unit_file_can_install(&paths, root_dir, path, true);
+                r = unit_file_can_install(&paths, root_dir, partial, true);
                 if (r < 0 && errno != ENOENT)
                         return r;
                 else if (r > 0)
@@ -1835,7 +1840,7 @@ int unit_file_preset(
         assert(scope >= 0);
         assert(scope < _UNIT_FILE_SCOPE_MAX);
 
-        r = lookup_paths_init_from_scope(&paths, scope);
+        r = lookup_paths_init_from_scope(&paths, scope, root_dir);
         if (r < 0)
                 return r;
 
@@ -1905,7 +1910,7 @@ int unit_file_get_list(
         if (root_dir && scope != UNIT_FILE_SYSTEM)
                 return -EINVAL;
 
-        r = lookup_paths_init_from_scope(&paths, scope);
+        r = lookup_paths_init_from_scope(&paths, scope, root_dir);
         if (r < 0)
                 return r;