diff --git a/src/core/manager.c b/src/core/manager.c index 21358a0469..f3275a4070 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -4511,16 +4511,14 @@ void manager_status_printf(Manager *m, StatusType type, const char *status, cons va_end(ap); } -Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path) { - char p[strlen(path)+1]; - +Set* manager_get_units_requiring_mounts_for(Manager *m, const char *path) { assert(m); assert(path); - strcpy(p, path); - path_simplify(p); + if (path_equal(path, "/")) + path = ""; - return hashmap_get(m->units_requiring_mounts_for, streq(p, "/") ? "" : p); + return hashmap_get(m->units_requiring_mounts_for, path); } int manager_update_failed_units(Manager *m, Unit *u, bool failed) { diff --git a/src/core/unit.c b/src/core/unit.c index 0cfb2aa281..3792cee711 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -4562,45 +4562,43 @@ int unit_kill_context( } int unit_require_mounts_for(Unit *u, const char *path, UnitDependencyMask mask) { - _cleanup_free_ char *p = NULL; - UnitDependencyInfo di; int r; assert(u); assert(path); - /* Registers a unit for requiring a certain path and all its prefixes. We keep a hashtable of these paths in - * the unit (from the path to the UnitDependencyInfo structure indicating how to the dependency came to - * be). However, we build a prefix table for all possible prefixes so that new appearing mount units can easily - * determine which units to make themselves a dependency of. */ + /* Registers a unit for requiring a certain path and all its prefixes. We keep a hashtable of these + * paths in the unit (from the path to the UnitDependencyInfo structure indicating how to the + * dependency came to be). However, we build a prefix table for all possible prefixes so that new + * appearing mount units can easily determine which units to make themselves a dependency of. */ if (!path_is_absolute(path)) return -EINVAL; - r = hashmap_ensure_allocated(&u->requires_mounts_for, &path_hash_ops); - if (r < 0) - return r; + if (hashmap_contains(u->requires_mounts_for, path)) /* Exit quickly if the path is already covered. */ + return 0; - p = strdup(path); + _cleanup_free_ char *p = strdup(path); if (!p) return -ENOMEM; + /* Use the canonical form of the path as the stored key. We call path_is_normalized() + * only after simplification, since path_is_normalized() rejects paths with '.'. + * path_is_normalized() also verifies that the path fits in PATH_MAX. */ path = path_simplify(p); if (!path_is_normalized(path)) return -EPERM; - if (hashmap_contains(u->requires_mounts_for, path)) - return 0; - - di = (UnitDependencyInfo) { + UnitDependencyInfo di = { .origin_mask = mask }; - r = hashmap_put(u->requires_mounts_for, path, di.data); + r = hashmap_ensure_put(&u->requires_mounts_for, &path_hash_ops, p, di.data); if (r < 0) return r; - p = NULL; + assert(r > 0); + TAKE_PTR(p); /* path remains a valid pointer to the string stored in the hashmap */ char prefix[strlen(path) + 1]; PATH_FOREACH_PREFIX_MORE(prefix, path) {