On Sep 20, Vincent Danjean <[email protected]> wrote:

> Now that you point out this, it recalls me that years ago,
> I moved /lib/systemd/system/ to /etc/conffiles-out-etc/lib/systemd/system
> (so that the systemd configuration files are correctly tracked by etckeeper)
> and I put a /lib/systemd/system -> /etc/conffiles-out-etc/lib/systemd/system
> symlink.
> 
> So, I'm downgrading the severity. But as it is allowed
> to create symlinks to other part of the disk for directory,
> usrmerge should handle this case (or, at least, give a
> preeminent message about a strange situation)
Indeed, this should be handled. Let's have a look at the code:

    # both source and dest are directories
    if (-d $n and -d "/usr$n") {
        # so they have to be merged recursively
        my $rule = File::Find::Rule->mindepth(1)->maxdepth(1)->start($n);
        while (defined (my $name = $rule->match)) {
            convert_file($name, $later);
        }
        return;
    }

    # both source and dest are links
    if (-l $n and -l "/usr$n") {
...
    }

    # the source is a link
    if (-l $n) {
        my $l = readlink($n);
        return if $l eq "/usr$n";           # and it points to dest
        fatal("Both $n and /usr$n exist");
    }

    # the destination is a link
    if (-l "/usr$n") {
...
    }

But -d is true also for a symlink which points to a directory, so the 
latter blocks are never reached!

And running File::Find::Rule this way on a symlink without a trailing 
/ returns no matches:

my $rule = File::Find::Rule->mindepth(1)->maxdepth(1)->start('/var/lock');
while (defined (my $name = $rule->match)) {
    say $name;
}

So the content of the link target was not moved to /usr, and then
the link (/lib/systemd/system/) was just deleted during the final 
cleanup because at that point only valid links to their counterparts
in /usr are supposed to be left in the source directories.

In your case the expected outcome should have been a failure instead, 
because /lib/systemd/system/ was a link which did not point to 
/usr/lib/systemd/system/ :

        fatal("Both $n and /usr$n exist");

(Also see the "CONFLICTS RESOLUTION MATRIX" section in the man page.)

While this bug is annoying and needs to be fixed, we had not noticed it 
in many years so apparently it is an highly unusual case.
And thankfully no files are lost and they can just be moved manually to 
the new directory.

Now I just need to figure out if the safest solution would be to move 
the "both source and dest are directories" block at the end or leave it 
there and make it ignore directories which are links.

-- 
ciao,
Marco

Attachment: signature.asc
Description: PGP signature

Reply via email to