Previously, an update-alternatives run in a maintscript when installing
with `dpkg --root` would have worked on /etc/alternatives rather than
/install-dir/etc/alternatives.

This patch is not complete yet because an unmodified version of altdir
would actually be required for symlink targets. (Right now, this creates
a $DPKG_ROOT/usr/bin/awk -> $DPKG_ROOT/etc/alternatives/awk rather than
-> /etc/alternatives/awk; that still needs to be resolved.)

Closes: https://bugs.debian.org/871808
---
 utils/update-alternatives.c | 59 +++++++++++++++++++++++++++++++++------------
 1 file changed, 44 insertions(+), 15 deletions(-)

diff --git a/utils/update-alternatives.c b/utils/update-alternatives.c
index 9a9d10c62..8a3bff1dd 100644
--- a/utils/update-alternatives.c
+++ b/utils/update-alternatives.c
@@ -50,7 +50,8 @@
 
 #define PROGNAME "update-alternatives"
 
-static const char *altdir = SYSCONFDIR "/alternatives";
+static const char *altdir ;
+static const char *dpkg_root;
 static const char *admdir;
 
 static const char *prog_path = "update-alternatives";
@@ -378,6 +379,24 @@ admindir_init(void)
        return xasprintf("%s/%s", basedir, "alternatives");
 }
 
+static const char *
+dpkg_root_init(void)
+{
+       const char *env_root;
+
+       env_root = getenv("DPKG_ROOT");
+       if (env_root != NULL)
+               return env_root;
+
+       return "";
+}
+
+static const char *
+altdir_init(void)
+{
+       return xasprintf("%s%s/%s", dpkg_root, SYSCONFDIR, "alternatives");
+}
+
 static FILE *fh_log = NULL;
 
 static void DPKG_ATTR_PRINTF(1)
@@ -1741,7 +1760,7 @@ static void
 alternative_prepare_install_single(struct alternative *a, const char *name,
                                    const char *linkname, const char *file)
 {
-       char *fntmp, *fn;
+       char *fntmp, *linktmp, *fn;
 
        /* Create link in /etc/alternatives. */
        fntmp = xasprintf("%s/%s" ALT_TMP_EXT, altdir, name);
@@ -1751,14 +1770,16 @@ alternative_prepare_install_single(struct alternative 
*a, const char *name,
        alternative_add_commit_op(a, OPCODE_MV, fntmp, fn);
        free(fntmp);
 
-       if (alternative_path_needs_update(linkname, fn)) {
+       linktmp = xasprintf("%s%s", dpkg_root, linkname);
+       if (alternative_path_needs_update(linktmp, fn)) {
                /* Create alternative link. */
-               fntmp = xasprintf("%s" ALT_TMP_EXT, linkname);
+               fntmp = xasprintf("%s" ALT_TMP_EXT, linktmp);
                checked_rm(fntmp);
                checked_symlink(fn, fntmp);
-               alternative_add_commit_op(a, OPCODE_MV, fntmp, linkname);
+               alternative_add_commit_op(a, OPCODE_MV, fntmp, linktmp);
                free(fntmp);
        }
+       free(linktmp);
        free(fn);
 }
 
@@ -1778,7 +1799,7 @@ alternative_prepare_install(struct alternative *a, const 
char *choice)
 
        /* Take care of slaves alternatives */
        for (sl = a->slaves; sl; sl = sl->next) {
-               char *fn;
+               char *fn, *sltmp;
 
                if (fileset_can_install_slave(fs, sl->name)) {
                        alternative_prepare_install_single(a, sl->name,
@@ -1795,11 +1816,12 @@ alternative_prepare_install(struct alternative *a, 
const char *choice)
 
                /* Drop unused slave. */
                fn = xasprintf("%s/%s", altdir, sl->name);
-               if (alternative_path_can_remove(sl->link))
-                       alternative_add_commit_op(a, OPCODE_RM, sl->link, NULL);
+               sltmp = xasprintf("%s%s", dpkg_root, sl->link);
+               if (alternative_path_can_remove(sltmp))
+                       alternative_add_commit_op(a, OPCODE_RM, sltmp, NULL);
                else
                        warning(_("not removing %s since it's not a symlink"),
-                               sl->link);
+                               sltmp);
                alternative_add_commit_op(a, OPCODE_RM, fn, NULL);
                free(fn);
        }
@@ -1810,17 +1832,22 @@ alternative_remove_files(struct alternative *a)
 {
        struct slave_link *sl;
 
-       checked_rm_args("%s" ALT_TMP_EXT, a->master_link);
-       if (alternative_path_can_remove(a->master_link))
-               checked_rm(a->master_link);
+       const char *mltmp, *sltmp;
+
+       mltmp = xasprintf("%s%s", dpkg_root, a->master_link);
+
+       checked_rm_args("%s" ALT_TMP_EXT, mltmp);
+       if (alternative_path_can_remove(mltmp))
+               checked_rm(mltmp);
 
        checked_rm_args("%s/%s" ALT_TMP_EXT, altdir, a->master_name);
        checked_rm_args("%s/%s", altdir, a->master_name);
 
        for (sl = a->slaves; sl; sl = sl->next) {
-               checked_rm_args("%s" ALT_TMP_EXT, sl->link);
-               if (alternative_path_can_remove(sl->link))
-                       checked_rm(sl->link);
+               sltmp = xasprintf("%s%s", dpkg_root, sl->link);
+               checked_rm_args("%s" ALT_TMP_EXT, sltmp);
+               if (alternative_path_can_remove(sltmp))
+                       checked_rm(sltmp);
 
                checked_rm_args("%s/%s" ALT_TMP_EXT, altdir, sl->name);
                checked_rm_args("%s/%s", altdir, sl->name);
@@ -2564,6 +2591,8 @@ main(int argc, char **argv)
        textdomain(PACKAGE);
 
        admdir = admindir_init();
+       dpkg_root = dpkg_root_init();
+       altdir = altdir_init();
 
        if (setvbuf(stdout, NULL, _IONBF, 0))
                syserr("setvbuf failed");
-- 
2.13.3

Attachment: signature.asc
Description: PGP signature

Reply via email to