tag 633627 + patch thanks On Fri, 15 Jul 2011, Raphael Hertzog wrote: > In the mean time, I will look into fixing this regression.
Here's a patch, can you tell me if it works for you? Cheers, -- Raphaël Hertzog ◈ Debian Developer Follow my Debian News ▶ http://RaphaelHertzog.com (English) ▶ http://RaphaelHertzog.fr (Français)
commit c34fe91e6679c2a41944e30df83e6a9684f4da81 Author: Raphaël Hertzog <[email protected]> Date: Fri Jul 15 22:06:38 2011 +0200 update-alternatives: fix regression when dropping slave alternatives When the alternative is changed, it might have to drop a slave alternative that's no longer provide by the new choice. This must only remove the slave link if it's actually a link. If it's a file, it must be kept except if --force is given. Reported-by: Andreas Beckmann <[email protected]> diff --git a/debian/changelog b/debian/changelog index 20b149a..ac9d3fb 100644 --- a/debian/changelog +++ b/debian/changelog @@ -74,6 +74,9 @@ dpkg (1.16.1) UNRELEASED; urgency=low * dpkg-mergechangelogs now checks the return value of the close() call. Thanks to Niels Thykier <[email protected]> for the patch. Closes: #633539 * Similar changes to dpkg-shlibdeps and dpkg-gencontrol, also by Niels. + * Fix update-alternatives to not remove a real file when dropping a + symlink for a slave that's not provided by the new current choice. + Closes: #633627 [ Guillem Jover ] * Install deb-src-control(5) man pages in dpkg-dev. Closes: #620520 diff --git a/utils/update-alternatives.c b/utils/update-alternatives.c index 0ad55a6..f35f5db 100644 --- a/utils/update-alternatives.c +++ b/utils/update-alternatives.c @@ -1623,13 +1623,29 @@ alternative_commit(struct alternative *a) alternative_commit_operations_free(a); } +static bool +alternative_can_replace_link(const char *linkname) +{ + struct stat st; + bool replace_link; + + errno = 0; + if (lstat(linkname, &st) == -1) { + if (errno != ENOENT) + syserr(_("cannot stat file '%s'"), linkname); + replace_link = true; + } else { + replace_link = S_ISLNK(st.st_mode); + } + + return (replace_link || opt_force); +} + static void alternative_prepare_install_single(struct alternative *a, const char *name, const char *linkname, const char *file) { char *fntmp, *fn; - struct stat st; - bool create_link; /* Create link in /etc/alternatives. */ xasprintf(&fntmp, "%s/%s" DPKG_TMP_EXT, altdir, name); @@ -1639,15 +1655,7 @@ alternative_prepare_install_single(struct alternative *a, const char *name, alternative_add_commit_op(a, opcode_mv, fntmp, fn); free(fntmp); - errno = 0; - if (lstat(linkname, &st) == -1) { - if (errno != ENOENT) - syserr(_("cannot stat file '%s'"), linkname); - create_link = true; - } else { - create_link = S_ISLNK(st.st_mode); - } - if (create_link || opt_force) { + if (alternative_can_replace_link(linkname)) { /* Create alternative link. */ xasprintf(&fntmp, "%s" DPKG_TMP_EXT, linkname); checked_rm(fntmp); @@ -1693,7 +1701,11 @@ alternative_prepare_install(struct alternative *a, const char *choice) /* Drop unused slave. */ xasprintf(&fn, "%s/%s", altdir, sl->name); - alternative_add_commit_op(a, opcode_rm, sl->link, NULL); + if (alternative_can_replace_link(sl->link)) + alternative_add_commit_op(a, opcode_rm, sl->link, NULL); + else + warning(_("not removing %s since it's not a symlink."), + sl->link); alternative_add_commit_op(a, opcode_rm, fn, NULL); free(fn); }

