shared/install: always overwrite symlinks in .wants and .requires

Before:
$ systemctl preset getty@.service
Failed to preset unit, file /etc/systemd/system/getty.target.wants/getty@tty1.service
already exists and is a symlink to ../../../../usr/lib/systemd/system/getty@.service.

After:
$ systemctl preset getty@.service
Created symlink /etc/systemd/system/getty.target.wants/getty@tty1.service,
pointing to /usr/lib/systemd/system/getty@.service.

We don't really care where the symlink points to. For example, it might point
to /usr/lib or /etc, and systemd will always load the unit from /etc in
preference to /usr/lib. In fact, if we make a symlink like
/etc/systemd/system/multi-user.target.wants/b.service -> ../a.service, pid1
will still start b.service. The name of the symlink is the only thing that
matters, as far as systemd is concerned. For humans it's confusing when the
symlinks points to anything else than the actual unit file. At the very least,
the symlink is supposed to point to a file with the same name in some other
directory. Since we don't care where the symlink points, we can always replace
an existing symlink.

Another option I considered would be to simply leave an existing symlink in
place. That would work too, but replacing the symlink with the expected value
seems more intuitive.

Of course those considerations only apply to .wants and .requires. Symlinks
created with "link" and "alias" are a separate matter.

Fixes #3056.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2016-04-21 21:11:15 -04:00
parent 39207373dd
commit 29380daff5

View file

@ -1390,7 +1390,6 @@ static int install_info_symlink_wants(
const char *config_path,
char **list,
const char *suffix,
bool force,
UnitFileChange **changes,
unsigned *n_changes) {
@ -1438,7 +1437,7 @@ static int install_info_symlink_wants(
rp = skip_root(paths, i->path);
q = create_symlink(rp ?: i->path, path, force, changes, n_changes);
q = create_symlink(rp ?: i->path, path, true, changes, n_changes);
if (r == 0)
r = q;
}
@ -1497,11 +1496,11 @@ static int install_info_apply(
r = install_info_symlink_alias(i, paths, config_path, force, changes, n_changes);
q = install_info_symlink_wants(i, paths, config_path, i->wanted_by, ".wants/", force, changes, n_changes);
q = install_info_symlink_wants(i, paths, config_path, i->wanted_by, ".wants/", changes, n_changes);
if (r == 0)
r = q;
q = install_info_symlink_wants(i, paths, config_path, i->required_by, ".requires/", force, changes, n_changes);
q = install_info_symlink_wants(i, paths, config_path, i->required_by, ".requires/", changes, n_changes);
if (r == 0)
r = q;