[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: dpkg-reconfigure does not set DPKG_MAINTSCRIPT_PACKAGE (et al)



Hi Joey,

On Fri, 05 Aug 2011, Joey Hess wrote:
> I keep seeing people complain that this bug is not fixed, but every
> time I look at it, I find myself unable to fix it, and with issues like
> these:

Thanks for looking into it!

> * Where are these variables documented?
>   (Appears that they're basically not, which makes it sorta hard to
>   know that they are being set, or used, as intended.)

man dpkg

ENVIRONMENT
[...]
       DPKG_MAINTSCRIPT_PACKAGE
              Defined  by  dpkg on the maintainer script environment to the package
              name being handled.

       DPKG_MAINTSCRIPT_ARCH
              Defined by dpkg on the maintainer script environment to the architec-
              ture the package got built for.

       DPKG_MAINTSCRIPT_NAME
              Defined  by  dpkg on the maintainer script environment to the name of
              the script running (preinst, postinst, prerm, postrm).

> * How is debconf supposed to set DPKG_MAINTSCRIPT_ARCH? If it has to call
>   dpkg --print-architecture every time, that just makes every run slower,
>   which would seem to be the opposite of the point of having such a
>   variable in the first place. But it cannot be that simple anyway, with
>   multiarch. What uses DPKG_MAINTSCRIPT_ARCH anyway?

Nothing uses DPKG_MAINTSCRIPT_ARCH yet, to the best of my knowledge. It has been
introduced for completeness in the multiarch world because DPKG_MAINTSCRIPT_PACKAGE
might not be enough to precisely identify the package in the case of Multi-Arch:
same packages.

The goal of this variable was definitely not to be a cache for "dpkg
--print-architecture". It should be set to the architecture of the package
(i.e. it can be "all" too).

So really the value you want is:
"dpkg -s <package-typed-by-user> | awk '/^Architecture: / { print $2 }'"
(you're already querying dpkg -s so it's fine to extract it too)

BTW, for multiarch compliance you should use "dpkg-query --control-path
<package-typed-by-user> postinst" to find out the path of the postinst script
(and similar for the config script).

I have attached 3 patches, you should consider at least the first two.
(Not tested though)

> * What should DPKG_MAINTSCRIPT_NAME be set to when the config script
>   is being run?

"config" should be fine.

> * How is it appropriate for dpkg-maintscript-helper etc to be already using
>   these variables when debconf is not yet setting them? Would it make
>   more sense for dpkg-reconfigure to not set them, and
>   dpkg-maintscript-helper etc to be a no-op when a package is being
>   reconfigured?

I'm not sure we can answer this in the same way for all dpkg-maintscript-helper
sub-commands (existing and to come). Thus I prefer the statu quo over
arbitrarily deciding that being a no-op is ok when its action might be required
by something that happened earlier in the postinst.

> * Nobody has ever addressed my concern that, if dpkg-reconfigure runs
>   dpkg --configure --pending, this will result in it confusingly doing
>   other things than configuring the specified package.

I believe this should simply be documented. I rarely run dpkg-reconfigure
on a system that's not "clean" from an installation point of view.

But if you really want to try to limit the side effects then you can compare
the status of all packages before and after having run the scripts and decide
whether or not you have to run it. You could also try to configure only the
affected packages but since triggers processing can activate other triggers,
you might have to fallback to --configure --pending anyway if it turns out
it was not enough.

Cheers,
-- 
Raphaël Hertzog ◈ Debian Developer

Follow my Debian News ▶ http://RaphaelHertzog.com (English)
                      ▶ http://RaphaelHertzog.fr (Français)
>From 2d46466417d9f98012abd5ee126b48d54290776f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rapha=C3=ABl=20Hertzog?= <hertzog@debian.org>
Date: Fri, 5 Aug 2011 21:21:13 +0200
Subject: [PATCH 1/3] Set environment variables expected by maintainer scripts

Closes: #560317
---
 dpkg-reconfigure |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/dpkg-reconfigure b/dpkg-reconfigure
index e38df69..b433bb0 100755
--- a/dpkg-reconfigure
+++ b/dpkg-reconfigure
@@ -170,6 +170,8 @@ foreach my $pkg (@packages) {
 	$_=`dpkg --status $pkg`;
 	my ($version)=m/Version: (.*)\n/;
 	my ($status)=m/Status: (.*)\n/;
+	my ($package)=m/Package: (.*)\n/;
+	my ($arch)=m/Architecture: (.*)\n/;
 	if (! $force) {
 		if (! defined $status || $status =~ m/not-installed$/) {
 			print STDERR "$0: ".sprintf(gettext("%s is not installed"), $pkg)."\n";
@@ -200,6 +202,11 @@ foreach my $pkg (@packages) {
 
 		my $is_confmodule='';
 
+		# Set environment variables expected by maintainer scripts
+		$ENV{DPKG_MAINTSCRIPT_PACKAGE}=$package;
+		$ENV{DPKG_MAINTSCRIPT_ARCH}=$arch;
+		$ENV{DPKG_MAINTSCRIPT_NAME}=$script;
+
 		if ($script ne 'config') {
 			# Test to see if the script uses debconf.
 			open (IN, "<$infodir/$pkg.$script");
-- 
1.7.5.4

>From 0eecb009633c5210edda3d52438649599bc43218 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rapha=C3=ABl=20Hertzog?= <hertzog@debian.org>
Date: Fri, 5 Aug 2011 21:27:06 +0200
Subject: [PATCH 2/3] Do not hardcode the path of maintainer scripts

Multi-arch changes the layout for Multi-Arch: same package
and it's thus important to use the official dpkg interface
to retrieve the path.
---
 dpkg-reconfigure |   21 ++++++++++++---------
 1 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/dpkg-reconfigure b/dpkg-reconfigure
index b433bb0..9bb49eb 100755
--- a/dpkg-reconfigure
+++ b/dpkg-reconfigure
@@ -85,8 +85,6 @@ if (exists $ENV{DEBCONF_USE_CDEBCONF} and $ENV{DEBCONF_USE_CDEBCONF} ne '') {
     exec "/usr/lib/cdebconf/dpkg-reconfigure", @ARGV;
 }
 
-my $infodir="/var/lib/dpkg/info";
-
 use strict;
 use Debconf::Db;
 use Debconf::Gettext;
@@ -185,8 +183,11 @@ foreach my $pkg (@packages) {
 	
 	if ($reload) {
 		# Load up templates just in case they aren't already.
-		Debconf::Template->load("$infodir/$pkg.templates", $pkg)
-			if -e "$infodir/$pkg.templates";
+		my $templates=`dpkg-query --control-path $pkg $templates`;
+		chomp($templates);
+		if ($templates and -e $templates) {
+			Debconf::Template->load($templates, $pkg);
+		}
 	}
 
 	# Simulation of reinstalling a package, without bothering with
@@ -198,7 +199,10 @@ foreach my $pkg (@packages) {
 		          ['config',   'reconfigure', $version],
 			  ['postinst', 'configure',   $version]) {
 		my $script=shift @$info;
-		next unless -x "$infodir/$pkg.$script";
+		my $path_script=`dpkg-query --control-path $pkg $script`;
+		chomp($path);
+
+		next unless $path_script and -x $path_script;
 
 		my $is_confmodule='';
 
@@ -209,7 +213,7 @@ foreach my $pkg (@packages) {
 
 		if ($script ne 'config') {
 			# Test to see if the script uses debconf.
-			open (IN, "<$infodir/$pkg.$script");
+			open (IN, "<$path_script");
 			while (<IN>) {
 				if (/confmodule/i) {
 					$is_confmodule=1;
@@ -221,8 +225,7 @@ foreach my $pkg (@packages) {
 		
 		if ($script eq 'config' || $is_confmodule) {
 			# Start up the confmodule.
-			my $confmodule=make_confmodule(
-				"$infodir/$pkg.$script", @$info);
+			my $confmodule=make_confmodule($path_script, @$info);
 	
 			# Make sure any questions the confmodule registers
 			# are owned by this package.
@@ -241,7 +244,7 @@ foreach my $pkg (@packages) {
 			Debconf::Db->save;
 			
 			delete $ENV{DEBIAN_HAS_FRONTEND};
-			my $ret=system("$infodir/$pkg.$script", @$info);
+			my $ret=system($path_script, @$info);
 			if (int($ret / 256) != 0) {
 				exit int($ret / 256);
 			}
-- 
1.7.5.4

>From 9299de20a295635c8e0be9c927130f5d0f9fc7f6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rapha=C3=ABl=20Hertzog?= <hertzog@debian.org>
Date: Fri, 5 Aug 2011 21:28:49 +0200
Subject: [PATCH 3/3] Properly differentiate Multi-Arch: same packages when
 looping over all packages

While this change is the right to do in theory (because each package in a
"Multi-Arch: same" set could have different templates, config scripts,
postinst behavior), in practice it's highly unlikely that they will
diverge across architectures.
---
 dpkg-reconfigure |   15 +++++++++++++--
 1 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/dpkg-reconfigure b/dpkg-reconfigure
index 9bb49eb..cd97bde 100755
--- a/dpkg-reconfigure
+++ b/dpkg-reconfigure
@@ -264,11 +264,22 @@ sub allpackages {
 	my @ret;
 	local $/="\n\n";
 	
+	my $ret=system("dpkg --assert-multi-arch 2>/dev/null");
+	my $has_multiarch=($ret == 0);
+
 	open (STATUS, "</var/lib/dpkg/status")
 		|| die sprintf(gettext("Cannot read status file: %s"), $!);
 	while (<STATUS>) {
-		push @ret, $1
-			if m/Status:\s*.*\sinstalled\n/ && m/Package:\s*(.*)\n/;
+		next unless m/Status:\s*.*\sinstalled\n/;
+		my ($package)=m/Package:\s*(.*)\n/;
+		my ($multiarch)=m/Multi-Arch:\s*(.*)\n/;
+		my ($arch)=m/Architecture:\s*(.*)\n/;
+		if ($has_multiarch && defined($multiarch) &&
+		    $multiarch eq "same") {
+		    push @ret, "$package:$arch";
+		} else {
+		    push @ret, $package;
+		}
 	}
 	close STATUS;
 
-- 
1.7.5.4


Reply to: