Browse Source

allow Pre-Install-Pkgs hooks to get info over an FD != stdin

This adds ::InfoFD option alongside the ::Version one to request sending
the information to the specified FD, by default it is STDIN as it was
the case before.

The environment variable APT_HOOK_INFO_FD contains the FD the data is on as
a confirmation that the APT version used understood the request.

Allowing the hook to choose the FD is needed/helpful e.g. for shellscripts
which have a hard time accessing FDs above 9 (as >= 10 are usually used
 internally by them)

Closes: #671728
debian/1.8.y
David Kalnischkies 9 years ago
parent
commit
48498443e7
  1. 20
      apt-pkg/deb/dpkgpm.cc
  2. 13
      doc/apt.conf.5.xml
  3. 94
      test/integration/test-bug-712116-dpkg-pre-install-pkgs-hook-multiarch

20
apt-pkg/deb/dpkgpm.cc

@ -382,24 +382,32 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
OptSec = "DPkg::Tools::Options::" + string(Opts->Value.c_str(),Pos);
unsigned int Version = _config->FindI(OptSec+"::Version",1);
unsigned int InfoFD = _config->FindI(OptSec + "::InfoFD", STDIN_FILENO);
// Create the pipes
int Pipes[2];
if (pipe(Pipes) != 0)
return _error->Errno("pipe","Failed to create IPC pipe to subprocess");
SetCloseExec(Pipes[0],true);
if (InfoFD != (unsigned)Pipes[0])
SetCloseExec(Pipes[0],true);
else
_config->Set("APT::Keep-Fds::", Pipes[0]);
SetCloseExec(Pipes[1],true);
// Purified Fork for running the script
pid_t Process = ExecFork();
pid_t Process = ExecFork();
if (Process == 0)
{
// Setup the FDs
dup2(Pipes[0],STDIN_FILENO);
dup2(Pipes[0], InfoFD);
SetCloseExec(STDOUT_FILENO,false);
SetCloseExec(STDIN_FILENO,false);
SetCloseExec(STDIN_FILENO,false);
SetCloseExec(STDERR_FILENO,false);
string hookfd;
strprintf(hookfd, "%d", InfoFD);
setenv("APT_HOOK_INFO_FD", hookfd.c_str(), 1);
dpkgChrootDirectory();
const char *Args[4];
Args[0] = "/bin/sh";
@ -409,6 +417,8 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
execv(Args[0],(char **)Args);
_exit(100);
}
if (InfoFD == (unsigned)Pipes[0])
_config->Clear("APT::Keep-Fds", Pipes[0]);
close(Pipes[0]);
FILE *F = fdopen(Pipes[1],"w");
if (F == 0)

13
doc/apt.conf.5.xml

@ -688,7 +688,8 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
<literal>options</literal> this must be specified in list notation. The commands
are invoked in order using <filename>/bin/sh</filename>; should any fail APT
will abort. APT will pass the filenames of all .deb files it is going to
install to the commands, one per line on standard input.</para>
install to the commands, one per line on the requested file descriptor, defaulting
to standard input.</para>
<para>Version 2 of this protocol dumps more information, including the
protocol version, the APT configuration space and the packages, files
@ -700,7 +701,15 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
<literal>DPkg::Tools::options::<replaceable>cmd</replaceable>::Version</literal>
accordingly, the default being version 1. If APT isn't supporting the requested
version it will send the information in the highest version it has support for instead.
</para></listitem>
</para>
<para>The file descriptor to be used to send the information can be requested with
<literal>DPkg::Tools::options::<replaceable>cmd</replaceable>::InfoFD</literal>
which defaults to <literal>0</literal> for standard input and is available since
version 0.9.11. Support for the option can be detected by looking for the environment
variable <envar>APT_HOOK_INFO_FD</envar> which contains the number of the used
file descriptor as a confirmation.</para>
</listitem>
</varlistentry>
<varlistentry><term><option>Run-Directory</option></term>

94
test/integration/test-bug-712116-dpkg-pre-install-pkgs-hook-multiarch

@ -26,95 +26,111 @@ hook='pre-install-pkgs'
enablehookversion() {
echo "#!/bin/sh
while read line; do
FD=0
echo -n > ${hook}-v${1}.list
if [ -n \"${2}\" ]; then
FD=\$APT_HOOK_INFO_FD
if [ "\$FD" != \"${2}\" ]; then echo \"ERROR: Information is not on requested FD: \$FD != ${2}\" >> ${hook}-v${1}.list; fi
fi
while read </proc/\$\$/fd/\$FD line; do
if echo \"\$line\" | grep -Fq '**'; then
echo \"\$line\"
fi
done > ${hook}-v${1}.list" > ${hook}-v${1}.sh
done >> ${hook}-v${1}.list" > ${hook}-v${1}.sh
chmod +x ${hook}-v${1}.sh
echo "dpkg::${hook}:: \"./${hook}-v${1}.sh --foo -bar\";
DPkg::Tools::options::\"./${hook}-v${1}.sh\"::Version \"$1\";" > rootdir/etc/apt/apt.conf.d/hook-v$1
if [ -n "$2" ]; then
echo "DPkg::Tools::options::\"./${hook}-v${1}.sh\"::InfoFD \"${2}\";" >> rootdir/etc/apt/apt.conf.d/hook-v$1
fi
}
enablehookversion 2
enablehookversion 3
observehook() {
rm -f ${hook}-v2.list ${hook}-v3.list
msgtest 'Observe hooks while' "$*"
testsuccess --nomsg aptget "$@" -y --force-yes
}
observehook install stuff -t stable
testfileequal "${hook}-v2.list" 'libsame - < 1 **CONFIGURE**
testrun() {
observehook install stuff -t stable
testfileequal "${hook}-v2.list" 'libsame - < 1 **CONFIGURE**
toolkit - < 1 **CONFIGURE**
stuff - < 1 **CONFIGURE**'
testfileequal "${hook}-v3.list" 'libsame - - none < 1 amd64 same **CONFIGURE**
testfileequal "${hook}-v3.list" 'libsame - - none < 1 amd64 same **CONFIGURE**
toolkit - - none < 1 all foreign **CONFIGURE**
stuff - - none < 1 amd64 none **CONFIGURE**'
observehook install stuff -t unstable
testfileequal "${hook}-v2.list" 'libsame 1 < 2 **CONFIGURE**
observehook install stuff -t unstable
testfileequal "${hook}-v2.list" 'libsame 1 < 2 **CONFIGURE**
toolkit 1 < 2 **CONFIGURE**
stuff 1 < 2 **CONFIGURE**'
testfileequal "${hook}-v3.list" 'libsame 1 amd64 same < 2 amd64 same **CONFIGURE**
testfileequal "${hook}-v3.list" 'libsame 1 amd64 same < 2 amd64 same **CONFIGURE**
toolkit 1 all foreign < 2 amd64 foreign **CONFIGURE**
stuff 1 amd64 none < 2 amd64 none **CONFIGURE**'
observehook install stuff:i386 -t unstable
testfileequal "${hook}-v2.list" 'stuff 2 > - **REMOVE**
observehook install stuff:i386 -t unstable
testfileequal "${hook}-v2.list" 'stuff 2 > - **REMOVE**
libsame - < 2 **CONFIGURE**
stuff - < 2 **CONFIGURE**'
testfileequal "${hook}-v3.list" 'stuff 2 amd64 none > - - none **REMOVE**
testfileequal "${hook}-v3.list" 'stuff 2 amd64 none > - - none **REMOVE**
libsame - - none < 2 i386 same **CONFIGURE**
stuff - - none < 2 i386 none **CONFIGURE**'
observehook remove libsame
testfileequal "${hook}-v2.list" 'libsame 2 > - **REMOVE**'
testfileequal "${hook}-v3.list" 'libsame 2 amd64 same > - - none **REMOVE**'
observehook remove libsame
testfileequal "${hook}-v2.list" 'libsame 2 > - **REMOVE**'
testfileequal "${hook}-v3.list" 'libsame 2 amd64 same > - - none **REMOVE**'
observehook install stuff:i386/stable libsame:i386/stable toolkit/stable
testfileequal "${hook}-v2.list" 'libsame 2 > 1 **CONFIGURE**
observehook install stuff:i386/stable libsame:i386/stable toolkit/stable
testfileequal "${hook}-v2.list" 'libsame 2 > 1 **CONFIGURE**
toolkit 2 > 1 **CONFIGURE**
stuff 2 > 1 **CONFIGURE**'
testfileequal "${hook}-v3.list" 'libsame 2 i386 same > 1 i386 same **CONFIGURE**
testfileequal "${hook}-v3.list" 'libsame 2 i386 same > 1 i386 same **CONFIGURE**
toolkit 2 amd64 foreign > 1 all foreign **CONFIGURE**
stuff 2 i386 none > 1 i386 none **CONFIGURE**'
observehook install 'libsame:*'
testfileequal "${hook}-v2.list" 'libsame 1 < 2 **CONFIGURE**
observehook install 'libsame:*'
testfileequal "${hook}-v2.list" 'libsame 1 < 2 **CONFIGURE**
libsame - < 2 **CONFIGURE**
toolkit 1 < 2 **CONFIGURE**
stuff 1 < 2 **CONFIGURE**'
testfileequal "${hook}-v3.list" 'libsame 1 i386 same < 2 i386 same **CONFIGURE**
testfileequal "${hook}-v3.list" 'libsame 1 i386 same < 2 i386 same **CONFIGURE**
libsame - - none < 2 amd64 same **CONFIGURE**
toolkit 1 all foreign < 2 amd64 foreign **CONFIGURE**
stuff 1 i386 none < 2 i386 none **CONFIGURE**'
observehook purge stuff:i386 'libsame:*' toolkit
testfileequal "${hook}-v2.list" 'libsame 2 > - **REMOVE**
observehook purge stuff:i386 'libsame:*' toolkit
testfileequal "${hook}-v2.list" 'libsame 2 > - **REMOVE**
stuff 2 > - **REMOVE**
libsame 2 > - **REMOVE**
toolkit 2 > - **REMOVE**'
testfileequal "${hook}-v3.list" 'libsame 2 amd64 same > - - none **REMOVE**
testfileequal "${hook}-v3.list" 'libsame 2 amd64 same > - - none **REMOVE**
stuff 2 i386 none > - - none **REMOVE**
libsame 2 i386 same > - - none **REMOVE**
toolkit 2 amd64 foreign > - - none **REMOVE**'
observehook install confpkg
testfileequal "${hook}-v2.list" 'confpkg - < 1 **CONFIGURE**'
testfileequal "${hook}-v3.list" 'confpkg - - none < 1 amd64 none **CONFIGURE**'
observehook install confpkg
testfileequal "${hook}-v2.list" 'confpkg - < 1 **CONFIGURE**'
testfileequal "${hook}-v3.list" 'confpkg - - none < 1 amd64 none **CONFIGURE**'
observehook remove confpkg
testfileequal "${hook}-v2.list" 'confpkg 1 > - **REMOVE**'
testfileequal "${hook}-v3.list" 'confpkg 1 amd64 none > - - none **REMOVE**'
observehook remove confpkg
testfileequal "${hook}-v2.list" 'confpkg 1 > - **REMOVE**'
testfileequal "${hook}-v3.list" 'confpkg 1 amd64 none > - - none **REMOVE**'
msgtest 'Conffiles of package remained after remove' 'confpkg'
dpkg -l confpkg | grep -q '^rc' && msgpass || msgfail
msgtest 'Conffiles of package remained after remove' 'confpkg'
dpkg -l confpkg | grep -q '^rc' && msgpass || msgfail
observehook purge confpkg
testfileequal "${hook}-v2.list" 'confpkg 1 > - **REMOVE**'
testfileequal "${hook}-v3.list" 'confpkg 1 amd64 none > - - none **REMOVE**'
observehook purge confpkg
testfileequal "${hook}-v2.list" 'confpkg 1 > - **REMOVE**'
testfileequal "${hook}-v3.list" 'confpkg 1 amd64 none > - - none **REMOVE**'
msgtest 'Conffiles are gone after purge' 'confpkg'
dpkg -l confpkg 2>/dev/null | grep -q '^rc' && msgfail || msgpass
}
enablehookversion 2
enablehookversion 3
testrun
msgtest 'Conffiles are gone after purge' 'confpkg'
dpkg -l confpkg 2>/dev/null | grep -q '^rc' && msgfail || msgpass
enablehookversion 2 13
enablehookversion 3 13
testrun

Loading…
Cancel
Save