diff options
author | Djalal Harouni <tixxdz@opendz.org> | 2014-04-17 01:47:11 +0100 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2014-04-16 23:13:22 -0400 |
commit | af7fce1cdb6c0d6ce56bcddccbc31dd3d64a8cd8 (patch) | |
tree | 9159e713c9dba978bd8535356f6805958af7f9f4 /src/shared/install.c | |
parent | a1484a216e79da1fa7e2323095fb1b7203fb7a17 (diff) |
install: create_symlink() check unlink() return value
create_symlink() do not check the return value of unlink(), this may
confuse the user.
Before the unlink() call we check the 'force' argument. If it is not set
we fail with -EEXIST, otherwise we unlink() the file, therefore the next
symlink() should not fail with -EEXIST (do not count races...).
However since callers may not have appropriate privileges to unlink()
the file we lose the -EPERM or any other errno code of unlink(), and
return the -EEXIST of the next symlink(). Fix this by checking unlink()
results.
Before:
$ systemctl --force --root=~/container-03 set-default multi-user.target
Failed to set default target: File exists
After:
$ systemctl --force --root=~/container-03 set-default multi-user.target
Failed to set default target: Permission denied
Diffstat (limited to 'src/shared/install.c')
-rw-r--r-- | src/shared/install.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/src/shared/install.c b/src/shared/install.c index 74090463d9..6334833812 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -1170,7 +1170,9 @@ static int create_symlink( if (!force) return -EEXIST; - unlink(new_path); + r = unlink(new_path); + if (r < 0 && errno != ENOENT) + return -errno; if (symlink(old_path, new_path) >= 0) { add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL); |