Skip to content

Commit

Permalink
alternatives: --keep-foreign incorrectly handles non-existent files
Browse files Browse the repository at this point in the history
Normally alternatives will only refuse to create a link to /etc/alternatives/*
if the file already exists and is not a symlink. But alternatives never
checked if existing symlink goes to /etc/alternatives/.

This is a weird behavior, but we did not want to change the default
behavior so we added --keep-foreign option that is more strict and
checks that the target if the symlink is in /etc/alternatives/.

But we missed the corner-case where there is no file at all and
incorrectly reported on error.

Fixes fedora-sysv#102
  • Loading branch information
lnykryn committed Apr 9, 2023
1 parent c143b0e commit 8ad0619
Showing 1 changed file with 18 additions and 6 deletions.
24 changes: 18 additions & 6 deletions alternatives.c
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,12 @@ static int isLink(char *path) {
return !!S_ISLNK(sbuf.st_mode);
}

static int fileExists(char *path) {
struct stat sbuf;

return !stat(path, &sbuf);
}

static int facilityBelongsToUs(char *facility, const char *altDir) {
char buf[PATH_MAX];
if (readlink(facility, buf, sizeof(buf)) <= 0)
Expand Down Expand Up @@ -534,7 +540,17 @@ static int makeLinks(struct linkSet *l, const char *altDir, int flags) {
sl = alloca(strlen(altDir) + strlen(l->title) + 2);
sprintf(sl, "%s/%s", altDir, l->title);

if (isLink(l->facility) && (!FL_KEEP_FOREIGN(flags) || facilityBelongsToUs(l->facility, altDir)) ) {
if (fileExists(l->facility) && !isLink(l->facility)) {
fprintf(
stderr,
_("failed to link %s -> %s: %s exists and it is not a symlink\n"),
l->facility, sl, l->facility);
} else if (FL_KEEP_FOREIGN(flags) && isLink(l->facility) && !facilityBelongsToUs(l->facility, altDir)) {
fprintf(
stderr,
_("failed to link %s -> %s: --keep-foreign was set and link %s points outside %s\n"),
l->facility, sl, l->facility, altDir);
} else {
if (FL_TEST(flags)) {
printf(_("would link %s -> %s\n"), l->facility, sl);
} else {
Expand All @@ -551,11 +567,7 @@ static int makeLinks(struct linkSet *l, const char *altDir, int flags) {
}
}
}
} else
fprintf(
stderr,
_("failed to link %s -> %s: %s exists and it is either not a symlink or --keep-foreign was set and link points outside %s\n"),
l->facility, sl, l->facility, altDir);
}

if (FL_TEST(flags)) {
printf(_("would link %s -> %s\n"), sl, l->target);
Expand Down

0 comments on commit 8ad0619

Please sign in to comment.