This is an automated email from the git hooks/post-receive script. guillem pushed a commit to branch main in repository dpkg.
View the commit online: https://git.dpkg.org/cgit/dpkg/dpkg.git/commit/?id=3c23f8f541c1e0a8434fea4163565be2fdc385da commit 3c23f8f541c1e0a8434fea4163565be2fdc385da Author: Guillem Jover <guil...@debian.org> AuthorDate: Sun Jun 20 15:30:15 2021 +0200 u-a: Fix admindir setting When specifying the --root option, or one of DPKG_ROOT or DPKG_ADMINDIR environment variables, we need to take into account the installation directory as the prefix for the administrative directory, instead of using it also as the actual administrative directory. Prompted-by: Johannes Schauer Marin Rodrigues <jo...@debian.org> Stable-Candidate: 1.20.x --- utils/Makefile.am | 7 +- utils/t/update_alternatives.t | 153 ++++++++++++++++++++++++++++++++++++++++-- utils/update-alternatives.c | 16 ++--- 3 files changed, 163 insertions(+), 13 deletions(-) diff --git a/utils/Makefile.am b/utils/Makefile.am index 53dcdd7f1..0bfb2e9f9 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -79,7 +79,12 @@ endif uninstall-local: rm -f $(DESTDIR)$(sysconfdir)/alternatives/README -TEST_ENV_VARS = DPKG_DATADIR=$(top_srcdir)/data +TEST_ENV_VARS = \ + DPKG_DATADIR=$(top_srcdir)/data \ + UA_ROOTDIR_ENVVAR=DPKG_ROOT \ + UA_ADMINDIR_ENVVAR=DPKG_ADMINDIR \ + UA_ADMINDIR_DEFAULT=$(admindir) \ + # EOL test_tmpdir = t.tmp test_scripts = \ diff --git a/utils/t/update_alternatives.t b/utils/t/update_alternatives.t index 3f4ac44c1..a4885dda9 100644 --- a/utils/t/update_alternatives.t +++ b/utils/t/update_alternatives.t @@ -32,8 +32,11 @@ my $bindir = File::Spec->rel2abs("$tmpdir/bin"); my @ua = ("$ENV{builddir}/update-alternatives", '--log', '/dev/null', '--quiet', '--admindir', "$admindir", '--altdir', "$altdir"); -delete $ENV{DPKG_ROOT}; -delete $ENV{DPKG_ADMINDIR}; +my $rootdir_envvar = $ENV{UA_ROOTDIR_ENVVAR} // 'DPKG_ROOT'; +my $admindir_envvar = $ENV{UA_ADMINDIR_ENVVAR} // 'DPKG_ADMINDIR'; + +delete $ENV{$rootdir_envvar}; +delete $ENV{$admindir_envvar}; my %paths = ( true => find_command('true'), @@ -97,6 +100,7 @@ my @choices = ( ); my $nb_slaves = 4; plan tests => (4 * ($nb_slaves + 1) + 2) * 26 # number of check_choices + + 30 # number of directory checks + 110; # rest sub cleanup { @@ -106,8 +110,18 @@ sub cleanup { sub call_ua { my ($params, %opts) = @_; - spawn(exec => [ @ua, @$params ], nocheck => 1, - wait_child => 1, env => { LC_ALL => 'C' }, %opts); + + my %env; + %env = %{delete $opts{env}} if exists $opts{env}; + my @cmd; + if (exists $opts{cmd}) { + @cmd = @{delete $opts{cmd}}; + } else { + @cmd = @ua; + } + + spawn(exec => [ @cmd, @{$params} ], nocheck => 1, + wait_child => 1, env => { LC_ALL => 'C', %env }, %opts); my $test_id = ''; $test_id = "$opts{test_id}: " if defined $opts{test_id}; if ($opts{expect_failure}) { @@ -119,6 +133,29 @@ sub call_ua { } } +sub call_ua_dirs { + my (%opts) = @_; + + $opts{cmd} = [ "$ENV{builddir}/update-alternatives" ]; + + my @params; + @params = @{delete $opts{params}} if exists $opts{params}; + push @params, qw(--debug); + push @params, qw(--log /dev/null); + push @params, qw(--get-selections); + + die unless exists $opts{expected}; + + my $stderr; + my $expected = delete $opts{expected}; + $opts{to_file} = '/dev/null'; + $opts{error_to_string} = \$stderr; + + call_ua(\@params, %opts); + + ok($stderr =~ $expected, "output '$stderr' does not match expected '$expected'"); +} + sub install_choice { my ($id, %opts) = @_; my $alt = $choices[$id]; @@ -251,6 +288,114 @@ sub check_choice { } ### START OF TESTS +cleanup(); + +# check directory overrides + +my $DEFAULT_ROOTDIR = ''; +my $DEFAULT_ADMINDIR = $ENV{UA_ADMINDIR_DEFAULT} // '/var/lib/dpkg/alternatives'; + +# ENV_ADMINDIR + defaults +call_ua_dirs( + env => { + $admindir_envvar => '/admindir_env', + }, + expected => "root=$DEFAULT_ROOTDIR admdir=/admindir_env", +); + +# ENV_ROOT + defaults +call_ua_dirs( + env => { $rootdir_envvar => '/rootdir_env' }, + expected => "root=/rootdir_env admdir=/rootdir_env$DEFAULT_ADMINDIR", +); + +# ENV_ROOT + ENV_ADMINDIR +call_ua_dirs( + env => { + $rootdir_envvar => '/rootdir_env', + $admindir_envvar => '/admindir_env', + }, + expected => 'root=/rootdir_env admdir=/admindir_env', +); + +# ENV_ADMINDIR + options +call_ua_dirs( + env => { $admindir_envvar => '/admindir_env' }, + params => [ qw(--root /rootdir_opt) ], + expected => "root=/rootdir_opt admdir=/rootdir_opt$DEFAULT_ADMINDIR", +); +call_ua_dirs( + env => { $admindir_envvar => '/admindir_env' }, + params => [ qw(--admindir /admindir_opt) ], + expected => "root=$DEFAULT_ROOTDIR admdir=/admindir_opt", +); +call_ua_dirs( + env => { $admindir_envvar => '/admindir_env' }, + params => [ qw(--root /rootdir_opt --admindir /admindir_opt) ], + expected => 'root=/rootdir_opt admdir=/admindir_opt', +); +call_ua_dirs( + env => { $admindir_envvar => '/admindir_env' }, + params => [ qw(--admindir /admindir_opt --root /rootdir_opt) ], + expected => "root=/rootdir_opt admdir=/rootdir_opt$DEFAULT_ADMINDIR", +); + +# DPKG_ROOT + options +call_ua_dirs( + env => { $rootdir_envvar => '/rootdir_env' }, + params => [ qw(--root /rootdir_opt) ], + expected => "root=/rootdir_opt admdir=/rootdir_opt$DEFAULT_ADMINDIR", +); +call_ua_dirs( + env => { $rootdir_envvar => '/rootdir_env' }, + params => [ qw(--admindir /admindir_opt) ], + expected => 'root=/rootdir_env admdir=/admindir_opt', +); +call_ua_dirs( + env => { $rootdir_envvar => '/rootdir_env' }, + params => [ qw(--root /rootdir_opt --admindir /admindir_opt) ], + expected => 'root=/rootdir_opt admdir=/admindir_opt', +); +call_ua_dirs( + env => { $rootdir_envvar => '/rootdir_env' }, + params => [ qw(--admindir /admindir_opt --root /rootdir_opt) ], + expected => "root=/rootdir_opt admdir=/rootdir_opt$DEFAULT_ADMINDIR", +); + +# ENV_ROOT + ENV_ADMINDIR + options +call_ua_dirs( + env => { + $rootdir_envvar => '/rootdir_env', + $admindir_envvar => '/admindir_env', + }, + params => [ qw(--root /rootdir_opt) ], + expected => "root=/rootdir_opt admdir=/rootdir_opt$DEFAULT_ADMINDIR", +); +call_ua_dirs( + env => { + $rootdir_envvar => '/rootdir_env', + $admindir_envvar => '/admindir_env', + }, + params => [ qw(--admindir /admindir_opt) ], + expected => 'root=/rootdir_env admdir=/admindir_opt', +); +call_ua_dirs( + env => { + $rootdir_envvar => '/rootdir_env', + $admindir_envvar => '/admindir_env', + }, + params => [ qw(--root /rootdir_opt --admindir /admindir_opt) ], + expected => 'root=/rootdir_opt admdir=/admindir_opt', +); +call_ua_dirs( + env => { + $rootdir_envvar => '/rootdir_env', + $admindir_envvar => '/admindir_env', + }, + params => [ qw(--admindir /admindir_opt --root /rootdir_opt) ], + expected => "root=/rootdir_opt admdir=/rootdir_opt$DEFAULT_ADMINDIR", +); + cleanup(); # removal when not installed should not fail remove_choice(0); diff --git a/utils/update-alternatives.c b/utils/update-alternatives.c index 4e1d3c500..d3db37c9c 100644 --- a/utils/update-alternatives.c +++ b/utils/update-alternatives.c @@ -563,9 +563,9 @@ fsys_set_dir(const char *dir) } static char * -fsys_gen_admindir(const char *basedir) +fsys_gen_admindir(void) { - return xasprintf("%s%s/%s", instdir, basedir, "alternatives"); + return fsys_get_path(ADMINDIR "/alternatives"); } static bool @@ -2813,7 +2813,7 @@ set_rootdir(const char *dir) log_file = fsys_get_path(LOGDIR "/alternatives.log"); altdir = SYSCONFDIR "/alternatives"; free(admdir); - admdir = fsys_gen_admindir(dir); + admdir = fsys_gen_admindir(); return instdir; } @@ -2821,17 +2821,15 @@ set_rootdir(const char *dir) static char * admindir_init(void) { - const char *basedir, *basedir_env; + const char *basedir_env; /* Try to get the admindir from an environment variable, usually set * by the system package manager. */ basedir_env = getenv(ADMINDIR_ENVVAR); if (basedir_env) - basedir = basedir_env; + return strdup(basedir_env); else - basedir = ADMINDIR; - - return fsys_gen_admindir(basedir); + return fsys_gen_admindir(); } #define MISSING_ARGS(nb) (argc < i + nb + 1) @@ -3038,6 +3036,8 @@ main(int argc, char **argv) "config", "set", "set-selections", "install", "remove", "all", "remove-all", "auto"); + debug("root=%s admdir=%s altdir=%s", instdir, admdir, altdir); + /* The following actions might modify the current alternative. */ if (action == ACTION_SET || action == ACTION_AUTO || -- Dpkg.Org's dpkg