chiark / gitweb /
Properly check for overflow in offsets
[elogind.git] / src / shared / install.c
index b22019d7b5ddcb24ca9a7967c9280de2d9fa2444..d2dd27680309b424f3d89588597f8d8c6beab9c4 100644 (file)
@@ -1015,7 +1015,7 @@ static int unit_file_load(
         }
 
         r = config_parse(NULL, path, f, NULL,
-                         config_item_table_lookup, (void*) items, true, info);
+                         config_item_table_lookup, (void*) items, true, true, info);
         if (r < 0)
                 return r;
 
@@ -1413,7 +1413,9 @@ static int install_context_mark_for_removal(
                 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
 
                 q = unit_file_search(c, i, paths, root_dir, false);
-                if (q < 0) {
+                if (q == -ENOENT) {
+                        /* do nothing */
+                } else if (q < 0) {
                         if (r >= 0)
                                 r = q;
 
@@ -1570,6 +1572,92 @@ int unit_file_reenable(
         return r;
 }
 
+int unit_file_set_default(
+                UnitFileScope scope,
+                const char *root_dir,
+                char *file,
+                UnitFileChange **changes,
+                unsigned *n_changes) {
+
+        _cleanup_lookup_paths_free_ LookupPaths paths = {};
+        _cleanup_install_context_done_ InstallContext c = {};
+        _cleanup_free_ char *config_path = NULL;
+        char *path;
+        int r;
+        InstallInfo *i = NULL;
+
+        assert(scope >= 0);
+        assert(scope < _UNIT_FILE_SCOPE_MAX);
+
+        if (unit_name_to_type(file) != UNIT_TARGET)
+                return -EINVAL;
+
+        r = lookup_paths_init_from_scope(&paths, scope);
+        if (r < 0)
+                return r;
+
+        r = get_config_path(scope, false, root_dir, &config_path);
+        if (r < 0)
+                return r;
+
+        r = install_info_add_auto(&c, file);
+        if (r < 0)
+                return r;
+
+        i = (InstallInfo*)hashmap_first(c.will_install);
+
+        r = unit_file_search(&c, i, &paths, root_dir, false);
+        if (r < 0)
+                return r;
+
+        path = strappenda(config_path, "/default.target");
+        r = create_symlink(i->path, path, true, changes, n_changes);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
+int unit_file_get_default(
+                UnitFileScope scope,
+                const char *root_dir,
+                char **name) {
+
+        _cleanup_lookup_paths_free_ LookupPaths paths = {};
+        char **p;
+        int r;
+
+        r = lookup_paths_init_from_scope(&paths, scope);
+        if (r < 0)
+                return r;
+
+        STRV_FOREACH(p, paths.unit_path) {
+                _cleanup_free_ char *path = NULL, *tmp = NULL;
+
+                if (isempty(root_dir))
+                        path = strappend(*p, "/default.target");
+                else
+                        path = strjoin(root_dir, "/", *p, "/default.target", NULL);
+
+                if (!path)
+                        return -ENOMEM;
+
+                r = readlink_malloc(path, &tmp);
+                if (r == -ENOENT)
+                        continue;
+                else if (r < 0)
+                        return r;
+
+                *name = strdup(path_get_file_name(tmp));
+                if (!*name)
+                        return -ENOMEM;
+
+                return 0;
+        }
+
+        return -ENOENT;
+}
+
 UnitFileState unit_file_get_state(
                 UnitFileScope scope,
                 const char *root_dir,
@@ -1609,24 +1697,29 @@ UnitFileState unit_file_get_state(
                 if (!path)
                         return -ENOMEM;
 
+                /*
+                 * Search for a unit file in our default paths, to
+                 * be sure, that there are no broken symlinks.
+                 */
                 if (lstat(path, &st) < 0) {
                         r = -errno;
-                        if (errno == ENOENT)
-                                continue;
-
-                        return -errno;
-                }
+                        if (errno != ENOENT)
+                                return r;
 
-                if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
-                        return -ENOENT;
+                        if (!unit_name_is_instance(name))
+                                continue;
+                } else {
+                        if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
+                                return -ENOENT;
 
-                r = null_or_empty_path(path);
-                if (r < 0 && r != -ENOENT)
-                        return r;
-                else if (r > 0) {
-                        state = path_startswith(*i, "/run") ?
-                                UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
-                        return state;
+                        r = null_or_empty_path(path);
+                        if (r < 0 && r != -ENOENT)
+                                return r;
+                        else if (r > 0) {
+                                state = path_startswith(*i, "/run") ?
+                                        UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
+                                return state;
+                        }
                 }
 
                 r = find_symlinks_in_scope(scope, root_dir, name, &state);