mirror of
https://github.com/systemd/systemd.git
synced 2026-08-09 17:38:42 +00:00
tmpfiles: check relative L? targets beside the link
Relative symlink targets are resolved from the directory containing the
link. Make the L? existence check use the same rule.
Reproducer:
tmp=$(mktemp -d /tmp/tmpfiles-link.XXXXXX)
conf=$(mktemp /tmp/tmpfiles-conf.XXXXXX)
printf data >"$tmp/target"
printf 'L? %s/link - - - - target\n' "$tmp" >"$conf"
systemd-tmpfiles --create --dry-run "$conf"
Before:
The target was checked root-relative, not beside the link.
Follow-up for b5dc805583.
This commit is contained in:
@@ -2680,16 +2680,30 @@ static int create_symlink(Context *c, Item *i) {
|
||||
assert(i);
|
||||
|
||||
if (i->ignore_if_target_missing) {
|
||||
r = chase(i->argument, arg_root, CHASE_SAFE|CHASE_PREFIX_ROOT|CHASE_NOFOLLOW, /* ret_path= */ NULL, /* ret_fd= */ NULL);
|
||||
_cleanup_free_ char *target = NULL;
|
||||
ChaseFlags chase_flags = CHASE_SAFE|CHASE_NOFOLLOW;
|
||||
|
||||
if (!path_is_absolute(i->argument)) {
|
||||
_cleanup_free_ char *dn = NULL;
|
||||
|
||||
r = path_extract_directory(i->path, &dn);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to extract directory from path '%s': %m", i->path);
|
||||
|
||||
target = path_join(dn, i->argument);
|
||||
if (!target)
|
||||
return log_oom();
|
||||
} else
|
||||
chase_flags |= CHASE_PREFIX_ROOT;
|
||||
|
||||
r = chase(target ?: i->argument, arg_root, chase_flags, /* ret_path= */ NULL, /* ret_fd= */ NULL);
|
||||
if (r == -ENOENT) {
|
||||
/* Silently skip over lines where the source file is missing. */
|
||||
log_debug_errno(r, "Symlink source path '%s/%s' does not exist, skipping line.",
|
||||
strempty(arg_root), skip_leading_slash(i->argument));
|
||||
log_debug_errno(r, "Symlink source path '%s' does not exist, skipping line.", i->argument);
|
||||
return 0;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to check if symlink source path '%s/%s' exists: %m",
|
||||
strempty(arg_root), skip_leading_slash(i->argument));
|
||||
return log_error_errno(r, "Failed to check if symlink source path '%s' exists: %m", i->argument);
|
||||
}
|
||||
|
||||
r = path_extract_filename(i->path, &bn);
|
||||
|
||||
@@ -54,3 +54,36 @@ EOF
|
||||
)"
|
||||
[[ "$output" == *"Would create directory $root/run/test"* ]]
|
||||
[[ "$output" != *"$root$root"* ]]
|
||||
|
||||
# Check that L? resolves relative targets from the symlink's parent directory.
|
||||
root='/tmp/L/4'
|
||||
rm -rf "$root"
|
||||
mkdir -p "$root"
|
||||
touch "$root/target"
|
||||
|
||||
systemd-tmpfiles --create - <<EOF
|
||||
L? $root/link - - - - target
|
||||
EOF
|
||||
test "$(readlink "$root/link")" = "target"
|
||||
|
||||
rm -f "$root/link" "$root/target"
|
||||
systemd-tmpfiles --create - <<EOF
|
||||
L? $root/link - - - - target
|
||||
EOF
|
||||
test ! -e "$root/link"
|
||||
|
||||
# Check the same relative target lookup with --root=.
|
||||
rm -rf "$root"
|
||||
mkdir -p "$root/dir"
|
||||
touch "$root/dir/target"
|
||||
|
||||
systemd-tmpfiles --create --root="$root" - <<EOF
|
||||
L? /dir/link - - - - target
|
||||
EOF
|
||||
test "$(readlink "$root/dir/link")" = "target"
|
||||
|
||||
rm -f "$root/dir/link" "$root/dir/target"
|
||||
systemd-tmpfiles --create --root="$root" - <<EOF
|
||||
L? /dir/link - - - - target
|
||||
EOF
|
||||
test ! -e "$root/dir/link"
|
||||
|
||||
Reference in New Issue
Block a user