From 5c0dd6fc637358094c9f0f9c98b9cd697090a529 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 13 Dec 2013 08:17:26 +0100 Subject: run autopkgtest against the installed apt --- debian/tests/run-tests | 17 ++++++++++++++--- test/integration/framework | 17 +++++++++++++---- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/debian/tests/run-tests b/debian/tests/run-tests index 6ea503568..233c5a386 100644 --- a/debian/tests/run-tests +++ b/debian/tests/run-tests @@ -2,6 +2,17 @@ set -e -make -make test -test/integration/run-tests +# auto-package-test is very unhappy if stuff it writen to stderr +exec 2> apt-stderr.log + +# we need the buildin webserver for the tests +if [ ! -e environment.mak ]; then + ./configure +fi +make -C test/interactive-helper/ + +# run against the installed apt +APT_INTEGRATION_TESTS_WEBSERVER_BIN_DIR=$(pwd)/build/bin \ +APT_INTEGRATION_TESTS_METHODS_DIR=/usr/lib/apt/methods \ +APT_INTEGRATION_TESTS_BUILD_DIR=/usr/bin \ +./test/integration/run-tests diff --git a/test/integration/framework b/test/integration/framework index 89b5bb0e4..c6422ca6f 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -102,6 +102,9 @@ aptget() { runapt apt-get $*; } aptftparchive() { runapt apt-ftparchive $*; } aptkey() { runapt apt-key $*; } aptmark() { runapt apt-mark $*; } +aptwebserver() { + LD_LIBRARY_PATH=${APTWEBSERVERBINDIR} ${APTWEBSERVERBINDIR}/aptwebserver $*; +} dpkg() { $(which dpkg) --root=${TMPWORKINGDIRECTORY}/rootdir --force-not-root --force-bad-path --log=${TMPWORKINGDIRECTORY}/rootdir/var/log/dpkg.log $* } @@ -154,8 +157,14 @@ setupenvironment() { TMPWORKINGDIRECTORY=$(mktemp -d) TESTDIRECTORY=$(readlink -f $(dirname $0)) msgninfo "Preparing environment for ${CCMD}$(basename $0)${CINFO} in ${TMPWORKINGDIRECTORY}… " - BUILDDIRECTORY="${TESTDIRECTORY}/../../build/bin" + + # allow overriding the default BUILDDIR location + BUILDDIRECTORY=${APT_INTEGRATION_TESTS_BUILD_DIR:-"${TESTDIRECTORY}/../../build/bin"} + METHODSDIR=${APT_INTEGRATION_TESTS_METHODS_DIR:-"${BUILDDIRECTORY}/methods"} + APTWEBSERVERBINDIR=${APT_INTEGRATION_TESTS_WEBSERVER_BIN_DIR:-BUILDDIRECTORY} test -x "${BUILDDIRECTORY}/apt-get" || msgdie "You need to build tree first" + # ----- + addtrap "cd /; rm -rf $TMPWORKINGDIRECTORY;" cd $TMPWORKINGDIRECTORY mkdir rootdir aptarchive keys @@ -181,7 +190,7 @@ setupenvironment() { echo "Dir::state::status \"${TMPWORKINGDIRECTORY}/rootdir/var/lib/dpkg/status\";" >> aptconfig.conf echo "Debug::NoLocking \"true\";" >> aptconfig.conf echo "APT::Get::Show-User-Simulation-Note \"false\";" >> aptconfig.conf - echo "Dir::Bin::Methods \"${BUILDDIRECTORY}/methods\";" >> aptconfig.conf + echo "Dir::Bin::Methods \"${METHODSDIR}\";" >> aptconfig.conf echo "Dir::Bin::dpkg \"fakeroot\";" >> aptconfig.conf echo "DPKG::options:: \"dpkg\";" >> aptconfig.conf echo "DPKG::options:: \"--root=${TMPWORKINGDIRECTORY}/rootdir\";" >> aptconfig.conf @@ -822,9 +831,9 @@ changetowebserver() { shift fi local LOG='/dev/null' - if test -x ${BUILDDIRECTORY}/aptwebserver; then + if test -x ${APTWEBSERVERBINDIR}/aptwebserver; then cd aptarchive - LD_LIBRARY_PATH=${BUILDDIRECTORY} ${BUILDDIRECTORY}/aptwebserver -o aptwebserver::fork=1 "$@" >$LOG 2>&1 + aptwebserver -o aptwebserver::fork=1 "$@" >$LOG 2>&1 local PID="$(cat aptwebserver.pid)" if [ -z "$PID" ]; then msgdie 'Could not fork aptwebserver successfully' -- cgit v1.2.3 From 5acf154d810a0225cc7d14637d101205e43ceba8 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 13 Dec 2013 14:37:14 +0100 Subject: make apt-key net-update actually testable --- cmdline/apt-key.in | 19 +++++++++++++------ test/integration/test-apt-key-net-update | 14 ++++++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in index 779872b4c..c7d3ce8b5 100644 --- a/cmdline/apt-key.in +++ b/cmdline/apt-key.in @@ -25,6 +25,9 @@ GPG_CMD="$GPG_CMD --no-auto-check-trustdb --trust-model always" GPG="$GPG_CMD" +APT_DIR="/" +eval $(apt-config shell APT_DIR Dir) + MASTER_KEYRING='&keyring-master-filename;' eval $(apt-config shell MASTER_KEYRING APT::Key::MasterKeyring) ARCHIVE_KEYRING='&keyring-filename;' @@ -33,7 +36,7 @@ REMOVED_KEYS='&keyring-removed-filename;' eval $(apt-config shell REMOVED_KEYS APT::Key::RemovedKeys) ARCHIVE_KEYRING_URI='&keyring-uri;' eval $(apt-config shell ARCHIVE_KEYRING_URI APT::Key::ArchiveKeyringURI) -TMP_KEYRING=/var/lib/apt/keyrings/maybe-import-keyring.gpg +TMP_KEYRING=${APT_DIR}/var/lib/apt/keyrings/maybe-import-keyring.gpg requires_root() { if [ "$(id -u)" -ne 0 ]; then @@ -107,7 +110,11 @@ add_keys_with_verify_against_master_keyring() { # (otherwise it does not make sense from a security POV) net_update() { # Disabled for now as code is insecure (LP: #1013639 (and 857472, 1013128)) - exit 1 + APT_KEY_NET_UPDATE_ENABLED="" + eval $(apt-config shell APT_KEY_NET_UPDATE_ENABLED APT::Key::Net-Update-Enabled) + if [ -z "$APT_KEY_NET_UPDATE_ENABLED" ]; then + exit 1 + fi if [ -z "$ARCHIVE_KEYRING_URI" ]; then echo >&2 "ERROR: Your distribution is not supported in net-update as no uri for the archive-keyring is set" @@ -120,15 +127,15 @@ net_update() { echo >&2 "ERROR: an installed wget is required for a network-based update" exit 1 fi - if [ ! -d /var/lib/apt/keyrings ]; then - mkdir -p /var/lib/apt/keyrings + if [ ! -d ${APT_DIR}/var/lib/apt/keyrings ]; then + mkdir -p ${APT_DIR}/var/lib/apt/keyrings fi - keyring=/var/lib/apt/keyrings/$(basename $ARCHIVE_KEYRING) + keyring=${APT_DIR}/var/lib/apt/keyrings/$(basename $ARCHIVE_KEYRING) old_mtime=0 if [ -e $keyring ]; then old_mtime=$(stat -c %Y $keyring) fi - (cd /var/lib/apt/keyrings; wget --timeout=90 -q -N $ARCHIVE_KEYRING_URI) + (cd ${APT_DIR}/var/lib/apt/keyrings; wget --timeout=90 -q -N $ARCHIVE_KEYRING_URI) if [ ! -e $keyring ]; then return fi diff --git a/test/integration/test-apt-key-net-update b/test/integration/test-apt-key-net-update index 73545aff7..e0869402e 100755 --- a/test/integration/test-apt-key-net-update +++ b/test/integration/test-apt-key-net-update @@ -6,6 +6,20 @@ TESTDIR=$(readlink -f $(dirname $0)) setupenvironment configarchitecture "i386" +changetowebserver + +# setup env +mkdir -p aptarchive/ubuntu/project var/lib/apt/keyrings +echo 'APT::Key::ArchiveKeyringURI "http://localhost:8080/ubuntu/project/ubuntu-archive-keyring.gpg";' >> ./aptconfig.conf +echo 'APT::Key::Net-Update-Enabled "1";' >> ./aptconfig.conf + +# signed thing +echo "meep" > aptarchive/ubuntu/project/ubuntu-archive-keyring.gpg + +# test against the "real" webserver +aptkey --fakeroot net-update + +exit 1 # mock requires_root() { -- cgit v1.2.3 From e5543ea5a236426dd33e74e427e8485a030a2540 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 19 Dec 2013 16:43:50 +0100 Subject: fix apt-key net-update test to use the buildin webserver --- cmdline/apt-key.in | 2 +- .../integration/exploid-keyring-with-dupe-keys.pub | Bin 3986 -> 0 bytes .../exploid-keyring-with-dupe-subkeys.pub | Bin 2016 -> 0 bytes test/integration/keyrings/test-archive-keyring.pub | Bin 0 -> 979 bytes test/integration/keyrings/test-archive-keyring.sec | Bin 0 -> 1355 bytes test/integration/keyrings/test-master-keyring.pub | Bin 0 -> 1199 bytes test/integration/keyrings/test-master-keyring.sec | Bin 0 -> 2501 bytes test/integration/test-apt-key-net-update | 133 ++++----------------- 8 files changed, 25 insertions(+), 110 deletions(-) delete mode 100644 test/integration/exploid-keyring-with-dupe-keys.pub delete mode 100644 test/integration/exploid-keyring-with-dupe-subkeys.pub create mode 100644 test/integration/keyrings/test-archive-keyring.pub create mode 100644 test/integration/keyrings/test-archive-keyring.sec create mode 100644 test/integration/keyrings/test-master-keyring.pub create mode 100644 test/integration/keyrings/test-master-keyring.sec diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in index c7d3ce8b5..463e4b4b4 100644 --- a/cmdline/apt-key.in +++ b/cmdline/apt-key.in @@ -130,7 +130,7 @@ net_update() { if [ ! -d ${APT_DIR}/var/lib/apt/keyrings ]; then mkdir -p ${APT_DIR}/var/lib/apt/keyrings fi - keyring=${APT_DIR}/var/lib/apt/keyrings/$(basename $ARCHIVE_KEYRING) + keyring=${APT_DIR}/var/lib/apt/keyrings/$(basename $ARCHIVE_KEYRING_URI) old_mtime=0 if [ -e $keyring ]; then old_mtime=$(stat -c %Y $keyring) diff --git a/test/integration/exploid-keyring-with-dupe-keys.pub b/test/integration/exploid-keyring-with-dupe-keys.pub deleted file mode 100644 index 642952a40..000000000 Binary files a/test/integration/exploid-keyring-with-dupe-keys.pub and /dev/null differ diff --git a/test/integration/exploid-keyring-with-dupe-subkeys.pub b/test/integration/exploid-keyring-with-dupe-subkeys.pub deleted file mode 100644 index 02d4e6ee8..000000000 Binary files a/test/integration/exploid-keyring-with-dupe-subkeys.pub and /dev/null differ diff --git a/test/integration/keyrings/test-archive-keyring.pub b/test/integration/keyrings/test-archive-keyring.pub new file mode 100644 index 000000000..d8d9d472b Binary files /dev/null and b/test/integration/keyrings/test-archive-keyring.pub differ diff --git a/test/integration/keyrings/test-archive-keyring.sec b/test/integration/keyrings/test-archive-keyring.sec new file mode 100644 index 000000000..aece750e8 Binary files /dev/null and b/test/integration/keyrings/test-archive-keyring.sec differ diff --git a/test/integration/keyrings/test-master-keyring.pub b/test/integration/keyrings/test-master-keyring.pub new file mode 100644 index 000000000..33aa16796 Binary files /dev/null and b/test/integration/keyrings/test-master-keyring.pub differ diff --git a/test/integration/keyrings/test-master-keyring.sec b/test/integration/keyrings/test-master-keyring.sec new file mode 100644 index 000000000..9cb33176c Binary files /dev/null and b/test/integration/keyrings/test-master-keyring.sec differ diff --git a/test/integration/test-apt-key-net-update b/test/integration/test-apt-key-net-update index e0869402e..4b38cd9b5 100755 --- a/test/integration/test-apt-key-net-update +++ b/test/integration/test-apt-key-net-update @@ -9,120 +9,35 @@ configarchitecture "i386" changetowebserver # setup env -mkdir -p aptarchive/ubuntu/project var/lib/apt/keyrings -echo 'APT::Key::ArchiveKeyringURI "http://localhost:8080/ubuntu/project/ubuntu-archive-keyring.gpg";' >> ./aptconfig.conf -echo 'APT::Key::Net-Update-Enabled "1";' >> ./aptconfig.conf - -# signed thing -echo "meep" > aptarchive/ubuntu/project/ubuntu-archive-keyring.gpg - -# test against the "real" webserver -aptkey --fakeroot net-update - -exit 1 - -# mock -requires_root() { - return 0 -} - -# extract net_update() and import it -func=$( sed -n -e '/^add_keys_with_verify_against_master_keyring/,/^}/p' ${BUILDDIRECTORY}/apt-key ) -eval "$func" - -mkdir -p ./etc/apt -TRUSTEDFILE=./etc/apt/trusted.gpg -mkdir -p ./var/lib/apt/keyrings -TMP_KEYRING=./var/lib/apt/keyrings/maybe-import-keyring.gpg -GPG_CMD="gpg --ignore-time-conflict --no-options --no-default-keyring" - -# FIXME: instead of copying this use apt-key and the buildin apt webserver -# to do a real test - -# COPYIED from apt-key.in -------------- - -# gpg needs a trustdb to function, but it can't be invalid (not even empty) -# so we create a temporary directory to store our fresh readable trustdb in -TRUSTDBDIR="$(mktemp -d)" -CURRENTTRAP="${CURRENTTRAP} rm -rf '${TRUSTDBDIR}';" -trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM -chmod 700 "$TRUSTDBDIR" -# We also don't use a secret keyring, of course, but gpg panics and -# implodes if there isn't one available - and writeable for imports -SECRETKEYRING="${TRUSTDBDIR}/secring.gpg" -touch $SECRETKEYRING -GPG_CMD="$GPG_CMD --secret-keyring $SECRETKEYRING" -GPG_CMD="$GPG_CMD --trustdb-name ${TRUSTDBDIR}/trustdb.gpg" -#----------------------------------------- END COPY +mkdir -p var/lib/apt/keyrings +mkdir -p usr/share/keyrings -GPG="$GPG_CMD --keyring $TRUSTEDFILE" -MASTER_KEYRING=/usr/share/keyrings/ubuntu-master-keyring.gpg - -msgtest "add_keys_with_verify_against_master_keyring" -if [ ! -e $MASTER_KEYRING ]; then - echo -n "No $MASTER_KEYRING found" - msgskip - exit 0 -fi - -# test bad keyring and ensure its not added (LP: #857472) -ADD_KEYRING=./keys/exploid-keyring-with-dupe-keys.pub -if add_keys_with_verify_against_master_keyring $ADD_KEYRING $MASTER_KEYRING; then - msgfail -else - msgpass -fi - -# ensure the keyring is still empty -gpg_out=$($GPG --list-keys) -msgtest "Test if keyring is empty" -if [ -n "" ]; then - msgfail -else - msgpass -fi - - -# test another possible attack vector using subkeys (LP: #1013128) -msgtest "add_keys_with_verify_against_master_keyring with subkey attack" -ADD_KEYRING=./keys/exploid-keyring-with-dupe-subkeys.pub -if add_keys_with_verify_against_master_keyring $ADD_KEYRING $MASTER_KEYRING; then - msgfail -else - msgpass -fi - -# ensure the keyring is still empty -gpg_out=$($GPG --list-keys) -msgtest "Test if keyring is empty" -if [ -n "" ]; then - msgfail -else - msgpass -fi +# install the fake master keyring +install -m0644 keys/test-master-keyring.pub usr/share/keyrings +echo "APT::Key::MasterKeyring \"${TMPWORKINGDIRECTORY}/usr/share/keyrings/test-master-keyring.pub\";" >> ./aptconfig.conf +# setup archive-keyring +mkdir -p aptarchive/ubuntu/project +install -m0644 keys/test-archive-keyring.pub aptarchive/ubuntu/project/ +echo 'APT::Key::ArchiveKeyringURI "http://localhost:8080/ubuntu/project/test-archive-keyring.pub";' >> ./aptconfig.conf +echo 'APT::Key::Net-Update-Enabled "1";' >> ./aptconfig.conf -# test good keyring and ensure we get no errors -ADD_KEYRING=/usr/share/keyrings/ubuntu-archive-keyring.gpg -if add_keys_with_verify_against_master_keyring $ADD_KEYRING $MASTER_KEYRING; then - msgpass -else - msgfail -fi +# test against the "real" webserver +testequal 'Checking for new archive signing keys now +gpg: key F68C85A3: public key "Test Automatic Archive Signing Key " imported +gpg: Total number processed: 1 +gpg: imported: 1 (RSA: 1)' aptkey --fakeroot net-update -testequal './etc/apt/trusted.gpg ---------------------- -pub 1024D/437D05B5 2004-09-12 -uid Ubuntu Archive Automatic Signing Key -sub 2048g/79164387 2004-09-12 -pub 1024D/FBB75451 2004-12-30 -uid Ubuntu CD Image Automatic Signing Key +# now try a different one +# setup archive-keyring +mkdir -p aptarchive/ubuntu/project +install -m0644 keys/marvinparanoid.pub aptarchive/ubuntu/project/ +echo 'APT::Key::ArchiveKeyringURI "http://localhost:8080/ubuntu/project/marvinparanoid.pub";' >> ./aptconfig.conf +echo 'APT::Key::Net-Update-Enabled "1";' >> ./aptconfig.conf -pub 4096R/C0B21F32 2012-05-11 -uid Ubuntu Archive Automatic Signing Key (2012) +# test against the "real" webserver +testequal "Checking for new archive signing keys now +Key 'E8525D47528144E2' not added. It is not signed with a master key" aptkey --fakeroot net-update -pub 4096R/EFE21092 2012-05-11 -uid Ubuntu CD Image Automatic Signing Key (2012) -' $GPG --list-keys -- cgit v1.2.3 From 75ab11ae3880530c5354cc90c8d1ff0998f8146b Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sat, 21 Dec 2013 18:50:03 +0100 Subject: make /etc/apt/preferences parser deal with comment only sections --- apt-pkg/policy.cc | 4 ++++ apt-pkg/tagfile.cc | 11 ++++++++-- test/integration/test-bug-732746-preferences | 32 ++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100755 test/integration/test-bug-732746-preferences diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc index 0a06cc6e3..d0f97441d 100644 --- a/apt-pkg/policy.cc +++ b/apt-pkg/policy.cc @@ -405,6 +405,10 @@ bool ReadPinFile(pkgPolicy &Plcy,string File) PreferenceSection Tags; while (TF.Step(Tags) == true) { + // can happen when there are only comments in a record + if (Tags.Count() == 0) + continue; + string Name = Tags.FindS("Package"); if (Name.empty() == true) return _error->Error(_("Invalid record in the preferences file %s, no Package header"), File.c_str()); diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index e0802e3d5..bef3c76ba 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -259,7 +259,12 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength) TagCount = 0; while (TagCount+1 < sizeof(Indexes)/sizeof(Indexes[0]) && Stop < End) { - TrimRecord(true,End); + TrimRecord(true,End); + + // this can happen when TrimRecord trims away the entire Record + // (e.g. because it just contains comments) + if(Stop == End) + return true; // Start a new index and add it to the hash if (isspace(Stop[0]) == 0) @@ -273,7 +278,9 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength) if (Stop == 0) return false; - for (; Stop+1 < End && Stop[1] == '\r'; Stop++); + for (; Stop+1 < End && Stop[1] == '\r'; Stop++) + /* nothing */ + ; // Double newline marks the end of the record if (Stop+1 < End && Stop[1] == '\n') diff --git a/test/integration/test-bug-732746-preferences b/test/integration/test-bug-732746-preferences new file mode 100755 index 000000000..b31f98aa0 --- /dev/null +++ b/test/integration/test-bug-732746-preferences @@ -0,0 +1,32 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'i386' + +insertinstalledpackage 'bar' 'i386' '1.0' + +cat > rootdir/etc/apt/preferences << EOF +# random test comment header + +# commented out by puppy^Wpuppet +#Package: foo +#Pin: origin "ftp.debian.org" +#Pin: 800 + +Package: bar +Pin: version 1.0 +Pin-Priority: 700 + +#Package: bar +#Pin: version 1.0 +#Pin: 800 +EOF + +testequal "Reading package lists... +Building dependency tree..." aptget check + +msgtest "Ensure policy is applied" +aptcache policy bar|grep -q "*** 1.0 700" && msgpass || msgfail -- cgit v1.2.3 From e5e51967a479552f6513d585a6eeefba05c7a12f Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sun, 22 Dec 2013 14:38:39 +0100 Subject: first proof-of-concept for a fix for #731738 --- apt-pkg/deb/dpkgpm.cc | 2 +- apt-pkg/install-progress.cc | 9 ++++++++- apt-pkg/install-progress.h | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index b4bfd1400..b9f839e82 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1182,7 +1182,7 @@ bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress) StartPtyMagic(); // Tell the progress that its starting and fork dpkg - d->progress->Start(); + d->progress->Start(d->master); // this loop is runs once per dpkg operation vector::const_iterator I = List.begin(); diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc index b82b7efde..2215fb1f5 100644 --- a/apt-pkg/install-progress.cc +++ b/apt-pkg/install-progress.cc @@ -273,11 +273,18 @@ void PackageManagerFancy::HandleSIGWINCH(int) SetupTerminalScrollArea(nr_terminal_rows); } -void PackageManagerFancy::Start() +void PackageManagerFancy::Start(int child_pty) { int nr_terminal_rows = GetNumberTerminalRows(); if (nr_terminal_rows > 0) + { SetupTerminalScrollArea(nr_terminal_rows); + // *cough* + struct winsize win; + ioctl(child_pty, TIOCGWINSZ, (char *)&win); + win.ws_row = nr_terminal_rows - 1; + ioctl(child_pty, TIOCSWINSZ, (char *)&win); + } } void PackageManagerFancy::Stop() diff --git a/apt-pkg/install-progress.h b/apt-pkg/install-progress.h index 4b7590983..010be82fd 100644 --- a/apt-pkg/install-progress.h +++ b/apt-pkg/install-progress.h @@ -28,7 +28,7 @@ namespace Progress { virtual ~PackageManager() {}; /* Global Start/Stop */ - virtual void Start() {}; + virtual void Start(int child_pty=-1) {}; virtual void Stop() {}; /* When dpkg is invoked (may happen multiple times for each @@ -125,7 +125,7 @@ namespace Progress { public: PackageManagerFancy(); ~PackageManagerFancy(); - virtual void Start(); + virtual void Start(int child_pty=-1); virtual void Stop(); virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, -- cgit v1.2.3 From 4754718a4461ebff89f5b49c385a007b4197bcff Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sun, 22 Dec 2013 14:38:39 +0100 Subject: first proof-of-concept for a fix for #731738 --- apt-pkg/deb/dpkgpm.cc | 2 +- apt-pkg/install-progress.cc | 9 ++++++++- apt-pkg/install-progress.h | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index b4bfd1400..b9f839e82 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1182,7 +1182,7 @@ bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress) StartPtyMagic(); // Tell the progress that its starting and fork dpkg - d->progress->Start(); + d->progress->Start(d->master); // this loop is runs once per dpkg operation vector::const_iterator I = List.begin(); diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc index b82b7efde..2215fb1f5 100644 --- a/apt-pkg/install-progress.cc +++ b/apt-pkg/install-progress.cc @@ -273,11 +273,18 @@ void PackageManagerFancy::HandleSIGWINCH(int) SetupTerminalScrollArea(nr_terminal_rows); } -void PackageManagerFancy::Start() +void PackageManagerFancy::Start(int child_pty) { int nr_terminal_rows = GetNumberTerminalRows(); if (nr_terminal_rows > 0) + { SetupTerminalScrollArea(nr_terminal_rows); + // *cough* + struct winsize win; + ioctl(child_pty, TIOCGWINSZ, (char *)&win); + win.ws_row = nr_terminal_rows - 1; + ioctl(child_pty, TIOCSWINSZ, (char *)&win); + } } void PackageManagerFancy::Stop() diff --git a/apt-pkg/install-progress.h b/apt-pkg/install-progress.h index 4b7590983..010be82fd 100644 --- a/apt-pkg/install-progress.h +++ b/apt-pkg/install-progress.h @@ -28,7 +28,7 @@ namespace Progress { virtual ~PackageManager() {}; /* Global Start/Stop */ - virtual void Start() {}; + virtual void Start(int child_pty=-1) {}; virtual void Stop() {}; /* When dpkg is invoked (may happen multiple times for each @@ -125,7 +125,7 @@ namespace Progress { public: PackageManagerFancy(); ~PackageManagerFancy(); - virtual void Start(); + virtual void Start(int child_pty=-1); virtual void Stop(); virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, -- cgit v1.2.3 From 68e0172140872d8044b3c768a6bea3ac58d426c4 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sun, 22 Dec 2013 22:15:52 +0100 Subject: factor GetTempDir out --- apt-pkg/contrib/fileutl.cc | 17 +++++++++++++++++ apt-pkg/contrib/fileutl.h | 2 ++ apt-pkg/contrib/gpgv.cc | 15 ++------------- cmdline/apt-extracttemplates.cc | 11 +++-------- cmdline/apt-get.cc | 10 ++++------ 5 files changed, 28 insertions(+), 27 deletions(-) diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 7fbe4d604..847d8b47f 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -1827,3 +1827,20 @@ std::vector Glob(std::string const &pattern, int flags) return result; } /*}}}*/ + +std::string GetTempDir() +{ + const char *tmpdir = getenv("TMPDIR"); + +#ifdef P_tmpdir + if (!tmpdir) + tmpdir = P_tmpdir; +#endif + + // check that tmpdir is set and exists + struct stat st; + if (!tmpdir || stat(tmpdir, &st) != 0) + tmpdir = "/tmp"; + + return string(tmpdir); +} diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index e9a9aab28..e752e9621 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -165,6 +165,8 @@ bool DirectoryExists(std::string const &Path) __attrib_const; bool CreateDirectory(std::string const &Parent, std::string const &Path); time_t GetModificationTime(std::string const &Path); +std::string GetTempDir(); + /** \brief Ensure the existence of the given Path * * \param Parent directory of the Path directory - a trailing diff --git a/apt-pkg/contrib/gpgv.cc b/apt-pkg/contrib/gpgv.cc index 8f619fee2..f57a72d86 100644 --- a/apt-pkg/contrib/gpgv.cc +++ b/apt-pkg/contrib/gpgv.cc @@ -22,20 +22,9 @@ /*}}}*/ static char * GenerateTemporaryFileTemplate(const char *basename) /*{{{*/ { - const char *tmpdir = getenv("TMPDIR"); - -#ifdef P_tmpdir - if (!tmpdir) - tmpdir = P_tmpdir; -#endif - - // check that tmpdir is set and exists - struct stat st; - if (!tmpdir || stat(tmpdir, &st) != 0) - tmpdir = "/tmp"; - std::string out; - strprintf(out, "%s/%s.XXXXXX", tmpdir, basename); + std::string tmpdir = GetTempDir(); + strprintf(out, "%s/%s.XXXXXX", tmpdir.c_str(), basename); return strdup(out.c_str()); } /*}}}*/ diff --git a/cmdline/apt-extracttemplates.cc b/cmdline/apt-extracttemplates.cc index 8fe15fdf9..8e1937113 100644 --- a/cmdline/apt-extracttemplates.cc +++ b/cmdline/apt-extracttemplates.cc @@ -47,8 +47,6 @@ using namespace std; -#define TMPDIR "/tmp" - pkgCache *DebFile::Cache = 0; // DebFile::DebFile - Construct the DebFile object /*{{{*/ @@ -253,14 +251,11 @@ string WriteFile(const char *package, const char *prefix, const char *data) { char fn[512]; static int i; - const char *tempdir = NULL; - - tempdir = getenv("TMPDIR"); - if (tempdir == NULL) - tempdir = TMPDIR; + std::string tempdir = GetTempDir(); snprintf(fn, sizeof(fn), "%s/%s.%s.%u%d", - _config->Find("APT::ExtractTemplates::TempDir", tempdir).c_str(), + _config->Find("APT::ExtractTemplates::TempDir", + tempdir.c_str()).c_str(), package, prefix, getpid(), i++); FileFd f; if (data == NULL) diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 730d3ea18..8a0772ce2 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -1536,14 +1536,12 @@ bool DoChangelog(CommandLine &CmdL) bool const downOnly = _config->FindB("APT::Get::Download-Only", false); char tmpname[100]; - char* tmpdir = NULL; + const char* tmpdir = NULL; if (downOnly == false) { - const char* const tmpDir = getenv("TMPDIR"); - if (tmpDir != NULL && *tmpDir != '\0') - snprintf(tmpname, sizeof(tmpname), "%s/apt-changelog-XXXXXX", tmpDir); - else - strncpy(tmpname, "/tmp/apt-changelog-XXXXXX", sizeof(tmpname)); + std::string systemTemp = GetTempDir(); + snprintf(tmpname, sizeof(tmpname), "%s/apt-changelog-XXXXXX", + systemTemp.c_str()); tmpdir = mkdtemp(tmpname); if (tmpdir == NULL) return _error->Errno("mkdtemp", "mkdtemp failed"); -- cgit v1.2.3 From a077861ad0f2e643307c2380a060a3b11914aa34 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 23 Dec 2013 13:35:08 +0100 Subject: add basic tests for GetTempDir() --- apt-pkg/contrib/fileutl.cc | 2 +- test/libapt/fileutl_test.cc | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 847d8b47f..efbf7aaf4 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -1839,7 +1839,7 @@ std::string GetTempDir() // check that tmpdir is set and exists struct stat st; - if (!tmpdir || stat(tmpdir, &st) != 0) + if (!tmpdir || strlen(tmpdir) == 0 || stat(tmpdir, &st) != 0) tmpdir = "/tmp"; return string(tmpdir); diff --git a/test/libapt/fileutl_test.cc b/test/libapt/fileutl_test.cc index b6b8ac579..462bdefd9 100644 --- a/test/libapt/fileutl_test.cc +++ b/test/libapt/fileutl_test.cc @@ -38,5 +38,18 @@ int main(int argc,char *argv[]) return 1; } + // GetTempDir() + unsetenv("TMPDIR"); + equals(GetTempDir(), "/tmp"); + + setenv("TMPDIR", "", 1); + equals(GetTempDir(), "/tmp"); + + setenv("TMPDIR", "/not-there-no-really-not", 1); + equals(GetTempDir(), "/tmp"); + + setenv("TMPDIR", "/usr", 1); + equals(GetTempDir(), "/usr"); + return 0; } -- cgit v1.2.3 From 6bbd65ee4fddb59d771d3cd1f7cf7433cbbd0097 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 24 Dec 2013 23:21:23 +0100 Subject: add integration test --- test/integration/test-bug-728500-tempdir | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100755 test/integration/test-bug-728500-tempdir diff --git a/test/integration/test-bug-728500-tempdir b/test/integration/test-bug-728500-tempdir new file mode 100755 index 000000000..0606538a1 --- /dev/null +++ b/test/integration/test-bug-728500-tempdir @@ -0,0 +1,18 @@ +#!/bin/sh + +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'i386' + +buildsimplenativepackage 'coolstuff' 'all' '1.0' 'unstable' + +setupaptarchive +changetowebserver + +msgtest 'Test with incorect TMPDIR' +export TMPDIR=/does-not-exists +aptget update && msgpass || msgfail +unset TMPDIR \ No newline at end of file -- cgit v1.2.3 From 8e2aa9904b1ef50e9480017feca7ef9d7391c078 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 27 Dec 2013 23:07:06 +0100 Subject: add make -C test/interactive-helper/ to .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2d9194c28..d89315be6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,4 +2,4 @@ language: cpp before_install: - sudo apt-get update -q - sudo apt-get install -q --no-install-recommends dpkg-dev debhelper libdb-dev gettext libcurl4-gnutls-dev zlib1g-dev libbz2-dev xsltproc docbook-xsl docbook-xml po4a autotools-dev autoconf automake doxygen debiandoc-sgml stunnel4 -script: make && make test && test/integration/run-tests +script: make && make -C test/interactive-helper/ && make test && test/integration/run-tests -- cgit v1.2.3 From c035b6552ba4bd1c6fba5fd8f8d829c2efbefe3c Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 27 Dec 2013 23:17:26 +0100 Subject: fix APTWEBSERVERBINDIR default --- .travis.yml | 2 +- test/integration/framework | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index d89315be6..2d9194c28 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,4 +2,4 @@ language: cpp before_install: - sudo apt-get update -q - sudo apt-get install -q --no-install-recommends dpkg-dev debhelper libdb-dev gettext libcurl4-gnutls-dev zlib1g-dev libbz2-dev xsltproc docbook-xsl docbook-xml po4a autotools-dev autoconf automake doxygen debiandoc-sgml stunnel4 -script: make && make -C test/interactive-helper/ && make test && test/integration/run-tests +script: make && make test && test/integration/run-tests diff --git a/test/integration/framework b/test/integration/framework index c6422ca6f..a28363768 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -161,7 +161,7 @@ setupenvironment() { # allow overriding the default BUILDDIR location BUILDDIRECTORY=${APT_INTEGRATION_TESTS_BUILD_DIR:-"${TESTDIRECTORY}/../../build/bin"} METHODSDIR=${APT_INTEGRATION_TESTS_METHODS_DIR:-"${BUILDDIRECTORY}/methods"} - APTWEBSERVERBINDIR=${APT_INTEGRATION_TESTS_WEBSERVER_BIN_DIR:-BUILDDIRECTORY} + APTWEBSERVERBINDIR=${APT_INTEGRATION_TESTS_WEBSERVER_BIN_DIR:-"${BUILDDIRECTORY}"} test -x "${BUILDDIRECTORY}/apt-get" || msgdie "You need to build tree first" # ----- -- cgit v1.2.3 From 5ed887855df9c39dcd22971073ed05b28a9ee95f Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sat, 28 Dec 2013 00:26:17 +0100 Subject: properly handle SIGWINCH in PackageManagerFancy again --- apt-pkg/install-progress.cc | 65 +++++++++++++++++++++++++++++---------------- apt-pkg/install-progress.h | 12 ++++++--- 2 files changed, 51 insertions(+), 26 deletions(-) diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc index 2215fb1f5..bfc00bd06 100644 --- a/apt-pkg/install-progress.cc +++ b/apt-pkg/install-progress.cc @@ -9,7 +9,7 @@ #include #include #include - +#include namespace APT { namespace Progress { @@ -222,17 +222,47 @@ bool PackageManagerProgressDeb822Fd::StatusChanged(std::string PackageName, return true; } + +PackageManagerFancy::PackageManagerFancy() + : child_pty(-1) +{ + // setup terminal size + old_SIGWINCH = signal(SIGWINCH, PackageManagerFancy::staticSIGWINCH); + instances.push_back(this); +} +std::vector PackageManagerFancy::instances; + +PackageManagerFancy::~PackageManagerFancy() +{ + instances.erase(find(instances.begin(), instances.end(), this)); + signal(SIGWINCH, old_SIGWINCH); +} + +void PackageManagerFancy::staticSIGWINCH(int signum) +{ + std::vector::const_iterator I; + for(I = instances.begin(); I != instances.end(); I++) + (*I)->HandleSIGWINCH(signum); +} + int PackageManagerFancy::GetNumberTerminalRows() { struct winsize win; + // FIXME: get from "child_pty" instead? if(ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win) != 0) return -1; + + if(_config->FindB("Debug::InstallProgress::Fancy", false) == true) + std::cerr << "GetNumberTerminalRows: " << win.ws_row << std::endl; return win.ws_row; } void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows) { + if(_config->FindB("Debug::InstallProgress::Fancy", false) == true) + std::cerr << "SetupTerminalScrollArea: " << nr_rows << std::endl; + // scroll down a bit to avoid visual glitch when the screen // area shrinks by one row std::cout << "\n"; @@ -241,30 +271,22 @@ void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows) std::cout << "\033[s"; // set scroll region (this will place the cursor in the top left) - std::cout << "\033[1;" << nr_rows - 1 << "r"; + std::cout << "\033[0;" << nr_rows - 1 << "r"; // restore cursor but ensure its inside the scrolling area std::cout << "\033[u"; static const char *move_cursor_up = "\033[1A"; std::cout << move_cursor_up; - // setup env for (hopefully!) ncurses - string s; - strprintf(s, "%i", nr_rows); - setenv("LINES", s.c_str(), 1); - + // ensure its flushed std::flush(std::cout); -} -PackageManagerFancy::PackageManagerFancy() -{ - // setup terminal size - old_SIGWINCH = signal(SIGWINCH, HandleSIGWINCH); -} - -PackageManagerFancy::~PackageManagerFancy() -{ - signal(SIGWINCH, old_SIGWINCH); + // setup tty size to ensure xterm/linux console are working properly too + // see bug #731738 + struct winsize win; + ioctl(child_pty, TIOCGWINSZ, (char *)&win); + win.ws_row = nr_rows - 1; + ioctl(child_pty, TIOCSWINSZ, (char *)&win); } void PackageManagerFancy::HandleSIGWINCH(int) @@ -273,17 +295,13 @@ void PackageManagerFancy::HandleSIGWINCH(int) SetupTerminalScrollArea(nr_terminal_rows); } -void PackageManagerFancy::Start(int child_pty) +void PackageManagerFancy::Start(int a_child_pty) { + child_pty = a_child_pty; int nr_terminal_rows = GetNumberTerminalRows(); if (nr_terminal_rows > 0) { SetupTerminalScrollArea(nr_terminal_rows); - // *cough* - struct winsize win; - ioctl(child_pty, TIOCGWINSZ, (char *)&win); - win.ws_row = nr_terminal_rows - 1; - ioctl(child_pty, TIOCSWINSZ, (char *)&win); } } @@ -298,6 +316,7 @@ void PackageManagerFancy::Stop() static const char* clear_screen_below_cursor = "\033[J"; std::cout << clear_screen_below_cursor; } + child_pty = -1; } bool PackageManagerFancy::StatusChanged(std::string PackageName, diff --git a/apt-pkg/install-progress.h b/apt-pkg/install-progress.h index 010be82fd..513de1c08 100644 --- a/apt-pkg/install-progress.h +++ b/apt-pkg/install-progress.h @@ -116,11 +116,17 @@ namespace Progress { class PackageManagerFancy : public PackageManager { + private: + static void staticSIGWINCH(int); + static std::vector instances; + protected: - static void SetupTerminalScrollArea(int nr_rows); - static int GetNumberTerminalRows(); - static void HandleSIGWINCH(int); + void SetupTerminalScrollArea(int nr_rows); + void HandleSIGWINCH(int); + + int GetNumberTerminalRows(); sighandler_t old_SIGWINCH; + int child_pty; public: PackageManagerFancy(); -- cgit v1.2.3 From 23bd09778261c945b460b46d855b1a6ef998cfd8 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sat, 28 Dec 2013 09:50:06 +0100 Subject: add missing vector include --- apt-pkg/install-progress.h | 1 + 1 file changed, 1 insertion(+) diff --git a/apt-pkg/install-progress.h b/apt-pkg/install-progress.h index 513de1c08..8a5b68a8f 100644 --- a/apt-pkg/install-progress.h +++ b/apt-pkg/install-progress.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace APT { namespace Progress { -- cgit v1.2.3