const char *path,
const char *root_dir,
SearchFlags flags) {
-
- _cleanup_free_ char *target = NULL;
+ struct stat st;
int r;
r = unit_file_load(c, info, path, root_dir, flags);
if (r != -ELOOP || (flags & SEARCH_DROPIN))
return r;
- /* This is a symlink, let's read it. */
-
- r = readlink_malloc(path, &target);
- if (r < 0)
- return r;
-
- if (path_equal(target, "/dev/null"))
+ r = chase_symlinks_and_stat(path, root_dir, CHASE_WARN, NULL, &st, NULL);
+ if (r > 0 && null_or_empty(&st))
info->type = UNIT_FILE_TYPE_MASKED;
else {
+ _cleanup_free_ char *target = NULL;
const char *bn;
UnitType a, b;
+ /* This is a symlink, let's read it. */
+
+ r = readlink_malloc(path, &target);
+ if (r < 0)
+ return r;
+
bn = basename(target);
if (unit_name_is_valid(info->name, UNIT_NAME_PLAIN)) {
#include "alloc-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "install.h"
#include "mkdir.h"
#include "rm-rf.h"
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) == -ENOENT);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) == -ENOENT);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "e.service", NULL) == -ENOENT);
p = strjoina(root, "/usr/lib/systemd/system/a.service");
assert_se(write_string_file(p,
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ALIAS);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ALIAS);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ALIAS);
+
+ /* Test masking with relative symlinks */
+
+ p = strjoina(root, "/usr/lib/systemd/system/e.service");
+ assert_se(symlink("../../../../../../dev/null", p) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "e.service", NULL) >= 0);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "e.service", &state) >= 0 && state == UNIT_FILE_MASKED);
+
+ assert_se(unlink(p) == 0);
+ assert_se(symlink("/usr/../dev/null", p) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "e.service", NULL) >= 0);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "e.service", &state) >= 0 && state == UNIT_FILE_MASKED);
+
+ assert_se(unlink(p) == 0);
}
static void test_linked_units(const char *root) {
p = strjoina(root, "/usr/lib/systemd/system-preset/");
assert_se(mkdir_p(p, 0755) >= 0);
+ p = strjoina(root, "/dev/");
+ assert_se(mkdir_p(p, 0755) >= 0);
+
+ p = strjoina(root, "/dev/null");
+ assert_se(touch(p) >= 0);
+
test_basic_mask_and_enable(root);
test_linked_units(root);
test_default(root);