1 #!/bin/sh -- # no runable script, just for vi 
   6         if [ "$1" = "-q" ]; then 
   8         elif [ "$1" = "-v" ]; then 
  10         elif [ "$1" = '--color=no' ]; then 
  12         elif [ "$1" = '--color=yes' ]; then 
  14         elif [ "$1" = '--color' ]; then 
  15                 export MSGCOLOR
="$(echo "$2" | tr 'a-z' 'A-Z')" 
  17         elif [ "$1" = '--level' ]; then 
  21                 echo >&2 "WARNING: Unknown parameter »$1« will be ignored" 
  25 export MSGLEVEL
="${MSGLEVEL:-3}" 
  27 # we all like colorful messages 
  28 if [ "${MSGCOLOR:-YES}" = 'YES' ]; then 
  29         if [ ! -t 1 ]; then # but check that we output to a terminal 
  35 if [ "$MSGCOLOR" != 'NO' ]; then 
  36         CERROR
="\033[1;31m" # red 
  37         CWARNING
="\033[1;33m" # yellow 
  38         CMSG
="\033[1;32m" # green 
  39         CINFO
="\033[1;96m" # light blue 
  40         CDEBUG
="\033[1;94m" # blue 
  41         CNORMAL
="\033[0;39m" # default system console color 
  42         CDONE
="\033[1;32m" # green 
  43         CPASS
="\033[1;32m" # green 
  44         CFAIL
="\033[1;31m" # red 
  45         CCMD
="\033[1;35m" # pink 
  57                         printf "$MIDDLE " "$(echo "$1" | sed -e 's#^apt\([cfghs]\)#apt-\1#')" 
  63 msgdie
() { msgprintf 
"${CERROR}E: %s" '%s' "${CNORMAL}\n" "$@" >&2; exit 1; } 
  64 msgwarn
() { msgprintf 
"${CWARNING}W: %s" '%s' "${CNORMAL}\n" "$@" >&2; } 
  65 msgmsg
() { msgprintf 
"${CMSG}%s" '%s' "${CNORMAL}\n" "$@"; } 
  66 msginfo
() { msgprintf 
"${CINFO}I: %s" '%s' "${CNORMAL}\n" "$@"; } 
  67 msgdebug
() { msgprintf 
"${CDEBUG}D: %s" '%s' "${CNORMAL}\n" "$@"; } 
  68 msgdone
() { msgprintf 
"${CDONE}DONE" '%s' "${CNORMAL}\n" "$@"; } 
  69 msgnwarn
() { msgprintf 
"${CWARNING}W: %s" '%s' "${CNORMAL}" "$@" >&2; } 
  70 msgnmsg
() { msgprintf 
"${CMSG}%s" '%s' "${CNORMAL}" "$@"; } 
  71 msgninfo
() { msgprintf 
"${CINFO}I: %s" '%s' "${CNORMAL}" "$@"; } 
  72 msgndebug
() { msgprintf 
"${CDEBUG}D: %s" '%s' "${CNORMAL}" "$@"; } 
  73 msgtest
() { msgprintf 
"${CINFO}%s" "${CCMD}%s${CINFO}" "…${CNORMAL} " "$@"; } 
  74 msgpass
() { printf "${CPASS}PASS${CNORMAL}\n"; } 
  76         if [ -n "$MSGTEST_MSG" ]; then 
  77                 test "$1" != 'msgfailoutput' || echo 
  78                 if [ -n "$MSGTEST_MSGMSG" ]; then 
  79                         echo "$MSGTEST_MSGMSG" 
  81                 if [ -n "$MSGTEST_GRP" ] && [ "$MSGTEST_GRP" != 'NEXT' ] && [ "$MSGTEST_GRP" != "$MSGTEST_MSG" ]; then 
  82                         echo "${CFAIL}Part of the test group: $MSGTEST_GRP" 
  84                 echo -n "$MSGTEST_MSG" 
  89         msgreportheader 
'msgskip' 
  90         if [ $# -gt 0 ]; then printf "${CWARNING}SKIP: $*${CNORMAL}\n" >&2; 
  91         else printf "${CWARNING}SKIP${CNORMAL}\n" >&2; fi 
  94         msgreportheader 
'msgfail' 
  95         if [ $# -gt 0 ] && [ -n "$1" ]; then printf "${CFAIL}FAIL: $*${CNORMAL}\n" >&2; 
  96         else printf "${CFAIL}FAIL${CNORMAL}\n" >&2; fi 
  97         if [ -n "$APT_DEBUG_TESTS" ]; then 
 100         EXIT_CODE
=$((EXIT_CODE+1)); 
 105                 if [ $MSGGROUP_LEVEL = 0 ]; then 
 108                 MSGGROUP_LEVEL
=$((MSGGROUP_LEVEL+1)); 
 110                 MSGGROUP_LEVEL
=$((MSGGROUP_LEVEL-1)); 
 111                 if [ $MSGGROUP_LEVEL = 0 ]; then 
 117 # enable / disable Debugging 
 118 if [ $MSGLEVEL -le 0 ]; then 
 121 if [ $MSGLEVEL -le 1 ]; then 
 125 if [ $MSGLEVEL -le 2 ]; then 
 127                 MSGTEST_MSGMSG
="$(msgprintf "${CMSG}%s" '%s' "${CNORMAL}" "$@")" 
 131                 MSGTEST_MSG
="$(msgprintf "${CINFO}%s" "${CCMD}%s${CINFO}" "…${CNORMAL} " "$@")" 
 132                 if [ "$MSGTEST_GRP" = 'NEXT' ]; then 
 133                         MSGTEST_GRP
="$MSGTEST_MSG" 
 136         msgpass
() { printf " ${CPASS}P${CNORMAL}"; } 
 138 if [ $MSGLEVEL -le 3 ]; then 
 142 if [ $MSGLEVEL -le 4 ]; then 
 144         msgndebug
() { true
; } 
 147         if [ "$1" = "debug" -a $MSGLEVEL -le 4 ] || 
 148            [ "$1" = "info" -a $MSGLEVEL -le 3 ] || 
 149            [ "$1" = "msg" -a $MSGLEVEL -le 2 ] || 
 150            [ "$1" = "warn" -a $MSGLEVEL -le 1 ] || 
 151            [ "$1" = "die" -a $MSGLEVEL -le 0 ]; then 
 154                 printf "${CDONE}DONE${CNORMAL}\n"; 
 158         if [ -f .
/aptconfig.conf 
]; then 
 159                 echo "$(readlink -f ./aptconfig.conf)" 
 160         elif [ -f ..
/aptconfig.conf 
]; then 
 161                 echo "$(readlink -f ../aptconfig.conf)" 
 162         elif [ -f ..
/..
/aptconfig.conf 
]; then 
 163                 echo "$(readlink -f ../../aptconfig.conf)" 
 164         elif [ -f "${TMPWORKINGDIRECTORY}/aptconfig.conf" ]; then 
 165                 echo "$(readlink -f "${TMPWORKINGDIRECTORY}/aptconfig.conf")" 
 169         msgdebug 
"Executing: ${CCMD}$*${CDEBUG} " 
 173         sh
|aptitude
|*/*|command) ;; 
 174         *) CMD
="${BUILDDIRECTORY}/$CMD";; 
 176         MALLOC_PERTURB_
=21 MALLOC_CHECK_
=2 APT_CONFIG
="$(getaptconfig)" LD_LIBRARY_PATH
=${LIBRARYPATH} $CMD "$@" 
 178 aptconfig
() { runapt apt
-config "$@"; } 
 179 aptcache
() { runapt apt
-cache "$@"; } 
 180 aptcdrom
() { runapt apt
-cdrom "$@"; } 
 181 aptget
() { runapt apt
-get "$@"; } 
 182 aptftparchive
() { runapt apt
-ftparchive "$@"; } 
 183 aptkey
() { runapt apt
-key "$@"; } 
 184 aptmark
() { runapt apt
-mark "$@"; } 
 185 aptsortpkgs
() { runapt apt
-sortpkgs "$@"; } 
 186 apt
() { runapt apt 
"$@"; } 
 187 apthelper
() { runapt 
"${APTHELPERBINDIR}/apt-helper" "$@"; } 
 188 aptwebserver
() { runapt 
"${APTWEBSERVERBINDIR}/aptwebserver" "$@"; } 
 189 aptitude
() { runapt aptitude 
"$@"; } 
 190 aptextracttemplates
() { runapt apt
-extracttemplates "$@"; } 
 191 aptinternalsolver
() { runapt 
"${APTINTERNALSOLVER}" "$@"; } 
 192 aptdumpsolver
() { runapt 
"${APTDUMPSOLVER}" "$@"; } 
 195         "${TMPWORKINGDIRECTORY}/rootdir/usr/bin/dpkg" "$@" 
 197 dpkgcheckbuilddeps
() { 
 198         command dpkg
-checkbuilddeps --admindir="${TMPWORKINGDIRECTORY}/rootdir/var/lib/dpkg" "$@" 
 203         aptget
) CMD
="apt-get";; 
 204         aptcache
) CMD
="apt-cache";; 
 205         aptcdrom
) CMD
="apt-cdrom";; 
 206         aptconfig
) CMD
="apt-config";; 
 207         aptmark
) CMD
="apt-mark";; 
 208         apthelper
) CMD
="apt-helper";; 
 209         aptftparchive
) CMD
="apt-ftparchive";; 
 210         dpkg
) shift; runapt 
"${TMPWORKINGDIRECTORY}/rootdir/usr/bin/gdb-dpkg" "$@"; return;; 
 214         if [ "${CMD##*/}" = "$CMD" ]; then 
 215                 CMD
="${BUILDDIRECTORY}/${CMD}" 
 217         runapt 
command gdb 
--quiet -ex run 
"$CMD" --args "$CMD" "$@" 
 221         # error if we about to overflow, but ... 
 222         #   "255 failures ought to be enough for everybody" 
 223         if [ $EXIT_CODE -gt 255 ]; then 
 224             msgdie 
"Total failure count $EXIT_CODE too big" 
 226         exit $((EXIT_CODE <= 255 ? EXIT_CODE : 255)); 
 229 shellsetedetector
() { 
 231         if [ "$exit_status" != '0' ]; then 
 232                 printf >&2 "${CERROR}E: Looks like the testcases ended prematurely with exitcode: ${exit_status}${CNORMAL}\n" 
 233                 if [ "$EXIT_CODE" = '0' ]; then 
 234                         EXIT_CODE
="$exit_status" 
 240         if [ "$1" = 'prefix' ]; then 
 241                 CURRENTTRAP
="$2 $CURRENTTRAP" 
 243                 CURRENTTRAP
="$CURRENTTRAP $1" 
 245         trap "shellsetedetector; $CURRENTTRAP exitwithstatus;" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM
 
 249         # privilege dropping and testing doesn't work if /tmp isn't world-writeable (as e.g. with libpam-tmpdir) 
 250         if [ -n "$TMPDIR" ] && [ "$(id -u)" = '0' ] && [ "$(stat --format '%a' "$TMPDIR")" != '1777' ]; then 
 253         TMPWORKINGDIRECTORY
="$(mktemp -d)" 
 254         addtrap 
"cd /; rm -rf \"$TMPWORKINGDIRECTORY\";" 
 255         msgninfo 
"Preparing environment for ${0##*/} in ${TMPWORKINGDIRECTORY}…" 
 257         mkdir -m 700 "${TMPWORKINGDIRECTORY}/downloaded" 
 258         if [ "$(id -u)" = '0' ]; then 
 259                 # relax permissions so that running as root with user switching works 
 261                 chmod 711 "$TMPWORKINGDIRECTORY" 
 262                 chown _apt
:root 
"${TMPWORKINGDIRECTORY}/downloaded" 
 265         TESTDIRECTORY
="$(readlink -f "$(dirname $0)")" 
 266         # allow overriding the default BUILDDIR location 
 267         SOURCEDIRECTORY="${APT_INTEGRATION_TESTS_SOURCE_DIR:-"${TESTDIRECTORY}/../../"}" 
 268         BUILDDIRECTORY="${APT_INTEGRATION_TESTS_BUILD_DIR:-"${TESTDIRECTORY}/../../build/bin"}" 
 269         LIBRARYPATH="${APT_INTEGRATION_TESTS_LIBRARY_PATH:-"${BUILDDIRECTORY}"}" 
 270         METHODSDIR="${APT_INTEGRATION_TESTS_METHODS_DIR:-"${BUILDDIRECTORY}/methods"}" 
 271         APTHELPERBINDIR="${APT_INTEGRATION_TESTS_LIBEXEC_DIR:-"${BUILDDIRECTORY}"}" 
 272         APTWEBSERVERBINDIR="${APT_INTEGRATION_TESTS_WEBSERVER_BIN_DIR:-"${BUILDDIRECTORY}"}" 
 273         APTINTERNALSOLVER="${APT_INTEGRATION_TESTS_INTERNAL_SOLVER:-"${BUILDDIRECTORY}/apt-internal-solver"}" 
 274         APTDUMPSOLVER="${APT_INTEGRATION_TESTS_DUMP_SOLVER:-"${BUILDDIRECTORY}/apt-dump-solver"}" 
 275         test -x "${BUILDDIRECTORY}/apt
-get" || msgdie "You need to build tree first
" 
 278         cd "$TMPWORKINGDIRECTORY" 
 279         mkdir rootdir aptarchive keys 
 281         mkdir -p etc/apt/apt.conf.d etc/apt/sources.list.d etc/apt/trusted.gpg.d etc/apt/preferences.d 
 282         mkdir -p usr/bin var/cache var/lib var/log tmp 
 283         mkdir -p var/lib/dpkg/info var/lib/dpkg/updates var/lib/dpkg/triggers 
 284         touch var/lib/dpkg/available 
 286         ln -s "${METHODSDIR}" usr/lib/apt/methods 
 287         if [ "$BUILDDIRECTORY" = "$LIBRARYPATH" ]; then 
 288                 mkdir -p usr/lib/apt/solvers 
 289                 ln -s "${BUILDDIRECTORY}/apt
-dump-solver" usr/lib/apt/solvers/dump 
 290                 ln -s "${BUILDDIRECTORY}/apt
-internal-solver" usr/lib/apt/solvers/apt 
 291                 echo "Dir
::Bin
::Solvers 
\"${TMPWORKINGDIRECTORY}/rootdir
/usr
/lib
/apt
/solvers
\";" > etc/apt/apt.conf.d/externalsolver.conf 
 293         # use the autoremove from the BUILDDIRECTORY if its there, otherwise 
 295         if [ -e "${BUILDDIRECTORY}/..
/..
/debian
/apt.conf.autoremove
" ]; then 
 296             ln -s "${BUILDDIRECTORY}/..
/..
/debian
/apt.conf.autoremove
" etc/apt/apt.conf.d/01autoremove 
 298             ln -s /etc/apt/apt.conf.d/01autoremove etc/apt/apt.conf.d/01autoremove 
 301         local BASENAME="${0##*/}" 
 302         local PACKAGESFILE="Packages
-${BASENAME#*-}" 
 303         if [ -f "${TESTDIRECTORY}/${PACKAGESFILE}" ]; then 
 304                 cp "${TESTDIRECTORY}/${PACKAGESFILE}" aptarchive/Packages 
 306         local SOURCESSFILE="Sources
-${BASENAME#*-}" 
 307         if [ -f "${TESTDIRECTORY}/${SOURCESSFILE}" ]; then 
 308                 cp "${TESTDIRECTORY}/${SOURCESSFILE}" aptarchive/Sources 
 310         for key in $(find "$TESTDIRECTORY" -name '*.pub' -o -name '*.sec'); do 
 314         ln -s "${TMPWORKINGDIRECTORY}/keys
/joesixpack.pub
" rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg 
 316         echo "Dir 
\"${TMPWORKINGDIRECTORY}/rootdir
\";" > aptconfig.conf 
 317         echo "Dir
::state
::status 
\"${TMPWORKINGDIRECTORY}/rootdir
/var
/lib
/dpkg
/status
\";" >> aptconfig.conf 
 318         echo "APT
::Get
::Show
-User-Simulation-Note \"false
\";" >> aptconfig.conf 
 319         echo "Dir
::Bin
::Methods 
\"${TMPWORKINGDIRECTORY}/rootdir
/usr
/lib
/apt
/methods
\";" >> aptconfig.conf 
 320         # either store apt-key were we can access it, even if we run it as a different user 
 321         #cp "${BUILDDIRECTORY}/apt
-key" "${TMPWORKINGDIRECTORY}/rootdir
/usr
/bin
/" 
 322         #chmod o+rx "${TMPWORKINGDIRECTORY}/rootdir
/usr
/bin
/apt
-key" 
 323         #echo "Dir
::Bin
::apt
-key \"${TMPWORKINGDIRECTORY}/rootdir
/usr
/bin
/apt
-key\";" >> aptconfig.conf 
 324         # destroys coverage reporting though, so we disable changing user for the calling gpgv 
 325         echo "Dir
::Bin
::apt
-key \"${BUILDDIRECTORY}/apt
-key\";" >> aptconfig.conf 
 326         if [ "$(id -u)" = '0' ]; then 
 327                 echo 'Binary::gpgv::Debug::NoDropPrivs "true
";' >>aptconfig.conf 
 330         cat > "${TMPWORKINGDIRECTORY}/rootdir
/usr
/bin
/dpkg
" <<EOF 
 333 if [ -r "${TMPWORKINGDIRECTORY}/noopchroot.so
" ]; then 
 334         if [ -n "\
$LD_LIBRARY_PATH" ]; then 
 335                 export LD_LIBRARY_PATH="${TMPWORKINGDIRECTORY}:${LD_LIBRARY_PATH}" 
 337                 export LD_LIBRARY_PATH="${TMPWORKINGDIRECTORY}" 
 339         if [ -n "\
$LD_PRELOAD" ]; then 
 340                 export LD_PRELOAD="noopchroot.so \
${LD_PRELOAD}" 
 342                 export LD_PRELOAD="noopchroot.so
" 
 346         cp "${TMPWORKINGDIRECTORY}/rootdir
/usr
/bin
/dpkg
" "${TMPWORKINGDIRECTORY}/rootdir
/usr
/bin
/gdb
-dpkg" 
 347         cat >> "${TMPWORKINGDIRECTORY}/rootdir
/usr
/bin
/dpkg
" <<EOF 
 348 exec fakeroot "${DPKG:-dpkg}" --root="${TMPWORKINGDIRECTORY}/rootdir
" \\ 
 349         --log="${TMPWORKINGDIRECTORY}/rootdir
/var
/log
/dpkg.log
" \\ 
 350         --force-not-root --force-bad-path "\$@
" 
 352         cat >> "${TMPWORKINGDIRECTORY}/rootdir
/usr
/bin
/gdb
-dpkg" <<EOF 
 353 exec fakeroot gdb --quiet -ex run "${DPKG:-dpkg}" --args "${DPKG:-dpkg}" --root="${TMPWORKINGDIRECTORY}/rootdir
" \\ 
 354         --log="${TMPWORKINGDIRECTORY}/rootdir
/var
/log
/dpkg.log
" \\ 
 355         --force-not-root --force-bad-path "\$@
" 
 357         chmod +x "${TMPWORKINGDIRECTORY}/rootdir
/usr
/bin
/dpkg
" "${TMPWORKINGDIRECTORY}/rootdir
/usr
/bin
/gdb
-dpkg" 
 358         echo "Dir
::Bin
::dpkg 
\"${TMPWORKINGDIRECTORY}/rootdir
/usr
/bin
/dpkg
\";" > rootdir/etc/apt/apt.conf.d/99dpkg 
 361                 if ! command dpkg --assert-multi-arch >/dev/null 2>&1; then 
 362                         echo "DPKG
::options
:: \"--force-architecture\";" # Added to test multiarch before dpkg is ready for it… 
 365                 echo 'quiet::NoUpdate "true
";' 
 366                 echo 'quiet::NoStatistic "true
";' 
 367                 # too distracting for users, but helpful to detect changes 
 368                 echo 'Acquire::Progress::Ignore::ShowErrorText "true
";' 
 369                 echo 'Acquire::Progress::Diffpercent "true
";' 
 370                 # in testcases, it can appear as if localhost has a rotation setup, 
 371                 # hide this as we can't really deal with it properly 
 372                 echo 'Acquire::Failure::ShowIP "false
";' 
 375         cp "${TESTDIRECTORY}/apt.pem
" "${TMPWORKINGDIRECTORY}/rootdir
/etc
/webserver.pem
" 
 376         if [ "$(id -u)" = '0' ]; then 
 377                 chown _apt:root "${TMPWORKINGDIRECTORY}/rootdir
/etc
/webserver.pem
" 
 379         echo "Acquire
::https
::CaInfo 
\"${TMPWORKINGDIRECTORY}/rootdir
/etc
/webserver.pem
\";" > rootdir/etc/apt/apt.conf.d/99https 
 380         echo "Apt
::Cmd
::Disable
-Script-Warning \"1\";" > rootdir/etc/apt/apt.conf.d/apt-binary 
 381         echo 'Acquire::Connect::AddrConfig "false
";' > rootdir/etc/apt/apt.conf.d/connect-addrconfig 
 382         configcompression '.' 'gz' #'bz2' 'lzma' 'xz' 
 383         confighashes 'SHA1' # these are tests, not security best-practices 
 385         # create some files in /tmp and look at user/group to get what this means 
 386         TEST_DEFAULT_USER="$USER" 
 387         if [ "$(uname)" = 'GNU/kFreeBSD' ]; then 
 388                 TEST_DEFAULT_GROUP='root' 
 390                 TEST_DEFAULT_GROUP="$USER" 
 393         # cleanup the environment a bit 
 394         # prefer our apt binaries over the system apt binaries 
 395         export PATH="${BUILDDIRECTORY}:${PATH}:/usr
/local
/sbin
:/usr
/sbin
:/sbin
" 
 396         export LC_ALL=C.UTF-8 
 397         unset LANGUAGE APT_CONFIG 
 398         unset GREP_OPTIONS DEB_BUILD_PROFILES 
 403         if [ "$1" = "native
" -o -z "$1" ]; then 
 404                 eval `aptconfig shell ARCH APT::Architecture` 
 405                 if [ -n "$ARCH" ]; then 
 408                         dpkg --print-architecture 
 416         aptconfig dump --no-empty --format '%v%n' APT::Architecture APT::Architectures | sort -u | tr '\n' ' ' 
 419 getarchitecturesfromcommalist() { 
 420         echo "$1" | sed -e 's#,#\n#g' | sed -e "s
/^native\$
/$(getarchitecture 'native')/" 
 423 configarchitecture() { 
 425                 echo "APT
::Architecture 
\"$(getarchitecture $1)\";" 
 426                 while [ -n "$1" ]; do 
 427                         echo "APT
::Architectures
:: \"$(getarchitecture $1)\";" 
 430         } >rootdir/etc/apt/apt.conf.d/01multiarch.conf 
 435         if [ ! -e rootdir/var/lib/dpkg/status ]; then 
 436                 local BASENAME="${0##*/}" 
 437                 local STATUSFILE="status
-${BASENAME#*-}" 
 438                 if [ -f "${TESTDIRECTORY}/${STATUSFILE}" ]; then 
 439                         cp "${TESTDIRECTORY}/${STATUSFILE}" rootdir/var/lib/dpkg/status 
 441                         echo -n > rootdir/var/lib/dpkg/status 
 444         rm -f rootdir/etc/apt/apt.conf.d/00foreigndpkg 
 445         if command dpkg --assert-multi-arch >/dev/null 2>&1 ; then 
 446                 local ARCHS="$(getarchitectures)" 
 447                 if echo "$ARCHS" | grep -E -q '[^ ]+ [^ ]+'; then 
 448                         DPKGARCH="$(dpkg --print-architecture)" 
 449                         for ARCH in ${ARCHS}; do 
 450                                 if [ "${ARCH}" != "${DPKGARCH}" ]; then 
 451                                         if ! dpkg --add-architecture ${ARCH} >/dev/null 2>&1; then 
 452                                                 # old-style used e.g. in Ubuntu-P – and as it seems travis 
 453                                                 echo "DPKG
::options
:: \"--foreign-architecture\";" >> rootdir/etc/apt/apt.conf.d/00foreigndpkg 
 454                                                 echo "DPKG
::options
:: \"${ARCH}\";"  >> rootdir/etc/apt/apt.conf.d/00foreigndpkg 
 458                         if [ "0" = "$(dpkg -l dpkg 2> /dev/null | grep '^i' | wc -l)" ]; then 
 459                                 # dpkg doesn't really check the version as long as it is fully installed, 
 460                                 # but just to be sure we choose one above the required version 
 461                                 insertinstalledpackage 'dpkg' "all
" '1.16.2+fake' 
 467 configdpkgnoopchroot() { 
 468         # create a library to noop chroot() and rewrite maintainer script executions 
 469         # via execvp() as used by dpkg as we don't want our rootdir to be a fullblown 
 470         # chroot directory dpkg could chroot into to execute the maintainer scripts 
 471         msgtest 'Building library to preload to make maintainerscript work in' 'dpkg' 
 472         cat > noopchroot.c << EOF 
 479 static char * chrootdir = NULL; 
 481 int chroot(const char *path) { 
 482         printf("WARNING
: CHROOTing to 
%s was ignored
!\n", path); 
 484         chrootdir = strdup(path); 
 487 int execvp(const char *file, char *const argv[]) { 
 488         static int (*func_execvp) (const char *, char * const []) = NULL; 
 489         if (func_execvp == NULL) 
 490                 func_execvp = (int (*) (const char *, char * const [])) dlsym(RTLD_NEXT, "execvp
"); 
 491         if (chrootdir == NULL || strncmp(file, "/var
/lib
/dpkg
/", strlen("/var
/lib
/dpkg
/")) != 0) 
 492                 return func_execvp(file, argv); 
 493         printf("REWRITE execvp call 
%s into 
%s
\n", file, chrootdir); 
 494         char newfile[strlen(chrootdir) + strlen(file)]; 
 495         strcpy(newfile, chrootdir); 
 496         strcat(newfile, file); 
 497         char const * const baseadmindir = "/var
/lib
/dpkg
"; 
 498         char admindir[strlen(chrootdir) + strlen(baseadmindir)]; 
 499         strcpy(admindir, chrootdir); 
 500         strcat(admindir, baseadmindir); 
 501         setenv("DPKG_ADMINDIR
", admindir, 1); 
 502         return func_execvp(newfile, argv); 
 505         testsuccess --nomsg gcc -fPIC -shared -o noopchroot.so noopchroot.c -ldl 
 507 configcompression() { 
 508         while [ -n "$1" ]; do 
 510                 '.') printf ".
\t.
\tcat
\n";; 
 511                 'gz') printf "gzip\tgz
\tgzip
\n";; 
 512                 'bz2') printf "bzip2\tbz
2\tbzip
2\n";; 
 513                 'lzma') printf "lzma
\tlzma
\txz 
--format=lzma
\n";; 
 514                 'xz') printf "xz
\txz
\txz
\n";; 
 515                 *) printf "$1\t$1\t$1\n";; 
 518         done > "${TMPWORKINGDIRECTORY}/rootdir
/etc
/testcase
-compressor.conf
" 
 522                 echo 'APT::FTPArchive {' 
 524                         while [ -n "$1" ]; do 
 525                                 printf "$1" | tr 'a-z' 'A-Z' 
 526                                 printf "\t\"true
\";\n" 
 529                         for h in 'MD5' 'SHA1' 'SHA256' 'SHA512'; do 
 530                                 printf "$h\t\"false
\";\n" 
 534         } >> "${TMPWORKINGDIRECTORY}/rootdir
/etc
/apt
/apt.conf.d
/ftparchive
-hashes.conf
" 
 540         gzip) COMPRESS='gz';; 
 541         bzip2) COMPRESS='bz2';; 
 542         lzma) COMPRESS='lzma';; 
 544         *) msgdie "Compressor 
$COMPRESSOR is unknown to framework
, so can
't be forced by forcecompressor!";; 
 546         local CONFFILE="${TMPWORKINGDIRECTORY}/rootdir/etc/apt/apt.conf.d/00force-compressor" 
 547         echo "Acquire::CompressionTypes::Order { \"${COMPRESS}\"; }; 
 548 Dir::Bin::uncompressed \"/does/not/exist\"; 
 549 Dir::Bin::gzip \"/does/not/exist\"; 
 550 Dir::Bin::bzip2 \"/does/not/exist\"; 
 551 Dir::Bin::lzma \"/does/not/exist\"; 
 552 Dir::Bin::xz \"/does/not/exist\";" > "$CONFFILE" 
 553         if [ -e "/bin/${COMPRESSOR}" ]; then 
 554                 echo "Dir::Bin::${COMPRESSOR} \"/bin/${COMPRESSOR}\";" >> "$CONFFILE" 
 555         elif [ -e "/usr/bin/${COMPRESSOR}" ]; then 
 556                 echo "Dir::Bin::${COMPRESSOR} \"/usr/bin/${COMPRESSOR}\";" >> "$CONFFILE" 
 557         elif [ "${COMPRESSOR}" = 'lzma
' ]; then 
 558                 echo 'Dir
::Bin
::xz 
"/usr/bin/xz";' >> "$CONFFILE" 
 559                 COMPRESSOR_CMD='xz 
--format=lzma
' 
 561                 msgtest 'Test 
for availability of compressor
' "${COMPRESSOR}" 
 562                 msgfail "${COMPRESSOR} not available" 
 566 setupsimplenativepackage() { 
 570         local RELEASE="${4:-unstable}" 
 571         local DEPENDENCIES="$5" 
 572         local DESCRIPTION="${6:-"an autogenerated dummy ${NAME}=${VERSION}/${RELEASE} 
 573  If you find such a package installed on your system, 
 574  something went horribly wrong! They are autogenerated 
 575  und used only by testcases and surf no other propose…"}" 
 577         local SECTION="${7:-others}" 
 579         if [ "$SECTION" = "${SECTION#*/}" ]; then 
 582                 DISTSECTION="${SECTION%/*}" 
 584         local BUILDDIR=incoming/${NAME}-${VERSION} 
 585         mkdir -p ${BUILDDIR}/debian/source 
 587         echo "* most suckless software product ever" > FEATURES 
 588         test -e debian/copyright || echo "Copyleft by Joe Sixpack $(date +%Y)" > debian/copyright 
 589         test -e debian/changelog || echo "$NAME ($VERSION) $RELEASE; urgency=low 
 593  -- Joe Sixpack <joe@example.org>  $(date -R)" > debian/changelog 
 594         test -e debian/control || echo "Source: $NAME 
 597 Maintainer: Joe Sixpack <joe@example.org> 
 598 Build-Depends: debhelper (>= 7) 
 599 Standards-Version: 3.9.1 
 601 Package: $NAME" > debian/control 
 602         if [ "$ARCH" = 'all
' ]; then 
 603                 echo "Architecture: all" >> debian/control 
 605                 echo "Architecture: any" >> debian/control 
 607         test -z "$DEPENDENCIES" || echo "$DEPENDENCIES" >> debian/control 
 608         echo "Description: $DESCRIPTION" >> debian/control 
 610         test -e debian/compat || echo "7" > debian/compat 
 611         test -e debian/source/format || echo "3.0 (native)" > debian/source/format 
 612         test -e debian/rules || cp /usr/share/doc/debhelper/examples/rules.tiny debian/rules 
 616 buildsimplenativepackage() { 
 619         if [ "$(echo "$NAME" | cut -c 1-3)" = 'lib
' ]; then 
 620                 NM="$(echo "$NAME" | cut -c 1-4)" 
 622                 NM="$(echo "$NAME" | cut -c 1)" 
 626         local RELEASE="${4:-unstable}" 
 627         local DEPENDENCIES="$5" 
 628         local DESCRIPTION="${6:-"an autogenerated dummy ${NAME}=${VERSION}/${RELEASE} 
 629  If you find such a package installed on your system, 
 630  something went horribly wrong! They are autogenerated 
 631  und used only by testcases and surf no other propose…"}" 
 633         local SECTION="${7:-others}" 
 634         local PRIORITY="${8:-optional}" 
 636         local COMPRESS_TYPE="${10:-gzip}" 
 638         if [ "$SECTION" = "${SECTION#*/}" ]; then 
 641                 DISTSECTION="${SECTION%/*}" 
 643         local BUILDDIR="${TMPWORKINGDIRECTORY}/incoming/${NAME}-${VERSION}" 
 645         msgtest "Build source package in version ${VERSION} for ${RELEASE} in ${DISTSECTION}" "$NAME" 
 646         mkdir -p "$BUILDDIR/debian/source" 
 647         echo "* most suckless software product ever" > "${BUILDDIR}/FEATURES" 
 649 echo '$NAME says 
\"Hello
!\"'" > "${BUILDDIR}/${NAME}" 
 651         echo "Copyleft by Joe Sixpack $(date +%Y)" > "${BUILDDIR}/debian/copyright" 
 652         echo "$NAME ($VERSION) $RELEASE; urgency=low 
 656  -- Joe Sixpack <joe@example.org>  $(date -R)" > "${BUILDDIR}/debian/changelog" 
 660 Maintainer: Joe Sixpack <joe@example.org> 
 661 Standards-Version: 3.9.3" 
 662                 if [ "$SECTION" != '<none
>' ]; then 
 663                         echo "Section: $SECTION" 
 665                 local BUILDDEPS="$(echo "$DEPENDENCIES" | grep '^Build-')" 
 666                 test -z "$BUILDDEPS" || echo "$BUILDDEPS" 
 670                 if [ "$ARCH" = 'all
' ]; then 
 671                         echo "Architecture: all" 
 673                         echo "Architecture: any" 
 675                 local DEPS="$(echo "$DEPENDENCIES" | grep -v '^Build-')" 
 676                 test -z "$DEPS" || echo "$DEPS" 
 677                 echo "Description: $DESCRIPTION" 
 678         } > "${BUILDDIR}/debian/control" 
 680         echo '3.0 (native
)' > "${BUILDDIR}/debian/source/format" 
 682         testsuccess --nomsg dpkg-source -b ${NAME}-${VERSION} 
 684         sed -n 's
#^dpkg-source: info: building [^ ]\+ in ##p' "${TMPWORKINGDIRECTORY}/rootdir/tmp/testsuccess.output" \ 
 686                 echo "pool/${SRC}" >> "${BUILDDIR}/../${RELEASE}.${DISTSECTION}.srclist" 
 687 #               if expr match "${SRC}" '.*\.dsc' >/dev/null 2>&1; then 
 688 #                       aptkey --keyring ./keys/joesixpack.pub --secret-keyring ./keys/joesixpack.sec --quiet --readonly \ 
 689 #                               adv --yes --default-key 'Joe Sixpack' \ 
 690 #                               --clearsign -o "${BUILDDIR}/../${SRC}.sign" "${BUILDDIR}/../$SRC" 
 691 #                       mv "${BUILDDIR}/../${SRC}.sign" "${BUILDDIR}/../$SRC" 
 695         for arch 
in $(getarchitecturesfromcommalist "$ARCH"); do 
 696                 msgtest 
"Build binary package for ${RELEASE} in ${SECTION}" "$NAME" 
 697                 rm -rf "${BUILDDIR}/debian/tmp" 
 698                 mkdir -p "${BUILDDIR}/debian/tmp/DEBIAN" "${BUILDDIR}/debian/tmp/usr/share/doc/${NAME}" "${BUILDDIR}/debian/tmp/usr/bin" 
 699                 cp "${BUILDDIR}/debian/copyright" "${BUILDDIR}/debian/changelog" "${BUILDDIR}/FEATURES" "${BUILDDIR}/debian/tmp/usr/share/doc/${NAME}" 
 700                 cp "${BUILDDIR}/${NAME}" "${BUILDDIR}/debian/tmp/usr/bin/${NAME}-${arch}" 
 701                 if [ -n "$FILE_TREE" ]; then 
 702                     cp -ar "$FILE_TREE" "${BUILDDIR}/debian/tmp" 
 705                 (cd "${BUILDDIR}"; dpkg
-gencontrol -DArchitecture=$arch) 
 706                 (cd "${BUILDDIR}/debian/tmp"; md5sum $(find usr/ -type f) > DEBIAN
/md5sums
) 
 707                 local LOG
="${BUILDDIR}/../${NAME}_${VERSION}_${arch}.dpkg-deb.log" 
 708                 # ensure the right permissions as dpkg-deb insists 
 709                 chmod 755 "${BUILDDIR}/debian/tmp/DEBIAN" 
 710                 testsuccess 
--nomsg dpkg
-deb -Z${COMPRESS_TYPE} --build "${BUILDDIR}/debian/tmp" "${BUILDDIR}/.." 
 711                 echo "pool/${NAME}_${VERSION}_${arch}.deb" >> "${BUILDDIR}/../${RELEASE}.${DISTSECTION}.pkglist" 
 714         local CHANGEPATH
="${BUILDDIR}/../${DISTSECTION}/${NM}/${NAME}/${NAME}_${VERSION}" 
 715         mkdir -p "$CHANGEPATH" 
 716         cp "${BUILDDIR}/debian/changelog" "$CHANGEPATH" 
 725         local ARCH
=$(getarchitecture $4) 
 726         local PKGNAME
="$(echo "$BUILDDIR" | grep -o '[^/]*$')" 
 727         local BUILDLOG
="$(readlink -f "${BUILDDIR}/../${PKGNAME}_${RELEASE}_${SECTION}.dpkg-bp.log")" 
 728         msgtest 
"Build package for ${RELEASE} in ${SECTION}" "$PKGNAME" 
 730         if [ "$ARCH" = "all" ]; then 
 731                 ARCH
="$(dpkg-architecture -qDEB_HOST_ARCH 2> /dev/null)" 
 733         testsuccess 
--nomsg dpkg
-buildpackage -uc -us -a$ARCH 
 734         cp "${TMPWORKINGDIRECTORY}/rootdir/tmp/testsuccess.output" "$BUILDLOG" 
 735         local PKGS
="$(grep '^dpkg-deb: building package' "$BUILDLOG" | cut -d'/' -f 2 | sed -e "s#'\.##")" 
 736         local SRCS
="$(grep '^dpkg-source: info: building' "$BUILDLOG" | grep -o '[a-z0-9._+~-]*$')" 
 739                 echo "pool/${PKG}" >> "${TMPWORKINGDIRECTORY}/incoming/${RELEASE}.${SECTION}.pkglist" 
 742                 echo "pool/${SRC}" >> "${TMPWORKINGDIRECTORY}/incoming/${RELEASE}.${SECTION}.srclist" 
 747         if [ -d incoming 
]; then 
 748                 buildaptarchivefromincoming 
"$@" 
 750                 buildaptarchivefromfiles 
"$@" 
 754 createaptftparchiveconfig
() { 
 755         local COMPRESSORS
="$(cut -d'    ' -f 1 "${TMPWORKINGDIRECTORY}/rootdir/etc/testcase-compressor.conf" | tr '\n' ' ')" 
 756         local COMPRESSORS
="${COMPRESSORS%* }" 
 757         local ARCHS
="$(getarchitectures)" 
 758         cat > ftparchive.conf 
<<EOF 
 760         ArchiveDir "$(readlink -f .)"; 
 761         CacheDir "$(readlink -f ..)"; 
 762         FileListDir "$(readlink -f pool/)"; 
 765         Packages::Compress "$COMPRESSORS"; 
 766         Sources::Compress "$COMPRESSORS"; 
 767         Contents::Compress "$COMPRESSORS"; 
 768         Translation::Compress "$COMPRESSORS"; 
 769         LongDescription "false"; 
 773         SrcDirectory "pool/"; 
 776         for DIST 
in $(find ./pool/ -maxdepth 1 -name '*.pkglist' -type f | cut -d'/' -f 3 | cut -d'.' -f 1 | sort | uniq); do 
 779         Architectures "$ARCHS all source"; 
 780         FileList "${DIST}.\$(SECTION).pkglist"; 
 781         SourceFileList "${DIST}.\$(SECTION).srclist"; 
 782         Sections "$(find ./pool/ -maxdepth 1 -name "${DIST}.*.pkglist" -type f | cut -d'/' -f 3 | cut -d'.' -f 2 | sort | uniq | tr '\n' ' ')"; 
 785         done >> ftparchive.conf
 
 788 buildaptftparchivedirectorystructure
() { 
 789         local DISTS
="$(grep -i '^tree ' ftparchive.conf | cut -d'/' -f 2 | sed -e 's#".*##')" 
 790         for DIST 
in $DISTS; do 
 791                 local SECTIONS
="$(grep -i -A 5 "dists/$DIST" ftparchive.conf | grep -i 'Sections' | cut -d'"' -f 2)" 
 792                 for SECTION 
in $SECTIONS; do 
 793                         local ARCHS
="$(grep -A 5 "dists/$DIST" ftparchive.conf | grep Architectures | cut -d'"' -f 2 | sed -e 's#source##')" 
 794                         for ARCH 
in $ARCHS; do 
 795                                 mkdir -p "dists/${DIST}/${SECTION}/binary-${ARCH}" 
 797                         mkdir -p "dists/${DIST}/${SECTION}/source" 
 798                         mkdir -p "dists/${DIST}/${SECTION}/i18n" 
 808         local DEPENDENCIES
="$5" 
 809         local PRIORITY
="${6:-optional}" 
 810         local DESCRIPTION
="${7:-"an autogenerated dummy ${NAME}=${VERSION}/${RELEASES} 
 811  If you find such a package installed on your system, 
 812  something went horribly wrong! They are autogenerated 
 813  und used only by testcases and surf no other propose…"}" 
 815         for RELEASE in $(printf '%s' "$RELEASES" | tr ',' '\n'); do 
 816                 if [ "$RELEASE" = 'installed' ]; then 
 817                         insertinstalledpackage "$2" "$3" "$4" "$5" "$6" "$7" 
 820                 for arch in $(getarchitecturesfromcommalist "$ARCH"); do 
 821                         if [ "$arch" = 'none' ]; then 
 822                                 ARCHS="$(getarchitectures)" 
 826                         for BUILDARCH in $ARCHS; do 
 827                                 local PPATH="aptarchive
/dists
/${RELEASE}/main
/binary
-${BUILDARCH}" 
 834 Maintainer
: Joe Sixpack 
<joe@example.org
>" 
 835                                         test "$arch" = 'none' || echo "Architecture
: $arch" 
 836                                         echo "Version
: $VERSION 
 837 Filename
: pool
/main
/${NAME}/${NAME}_
${VERSION}_
${arch}.deb
" 
 838                                         test -z "$DEPENDENCIES" || echo "$DEPENDENCIES" 
 839                                         echo "Description
: $(printf '%s' "$DESCRIPTION" | head -n 1)" 
 840                                         echo "Description
-md5: $(printf '%s' "$DESCRIPTION" | md5sum | cut -d' ' -f 1)" 
 842                                 } >> "${PPATH}/Packages
" 
 845                 mkdir -p "aptarchive
/dists
/${RELEASE}/main
/source" "aptarchive
/dists
/${RELEASE}/main
/i18n
" 
 846                 touch "aptarchive
/dists
/${RELEASE}/main
/source
/Sources
" 
 848 Description
-md5: $(printf '%s' "$DESCRIPTION" | md5sum | cut -d' ' -f 1) 
 849 Description
-en: $DESCRIPTION 
 850 " >> "aptarchive
/dists
/${RELEASE}/main
/i
18n
/Translation
-en" 
 859         local DEPENDENCIES="$5" 
 860         local BINARY="${6:-$NAME}" 
 862         local SPATH="aptarchive
/dists
/${RELEASE}/main
/source" 
 864         local FILE="${SPATH}/Sources
" 
 865         local DSCFILE="${NAME}_
${VERSION}.dsc
" 
 866         local TARFILE="${NAME}_
${VERSION}.
tar.gz
" 
 870 Maintainer
: Joe Sixpack 
<joe@example.org
> 
 871 Architecture
: $ARCH" >> $FILE 
 872         test -z "$DEPENDENCIES" || echo "$DEPENDENCIES" >> "$FILE" 
 874  $(echo -n "$DSCFILE" | md5sum | cut -d' ' -f 1) $(echo -n "$DSCFILE" | wc -c) "$DSCFILE" 
 875  $(echo -n "$TARFILE" | md5sum | cut -d' ' -f 1) $(echo -n "$TARFILE" | wc -c) "$TARFILE" 
 877  $(echo -n "$DSCFILE" | sha256sum | cut -d' ' -f 1) $(echo -n "$DSCFILE" | wc -c) "$DSCFILE" 
 878  $(echo -n "$TARFILE" | sha256sum | cut -d' ' -f 1) $(echo -n "$TARFILE" | wc -c) "$TARFILE" 
 882 insertinstalledpackage() { 
 886         local DEPENDENCIES="$4" 
 887         local PRIORITY="${5:-optional}" 
 888         local STATUS="${6:-install ok installed}" 
 889         local DESCRIPTION="${7:-"an autogenerated dummy ${NAME}=${VERSION}/installed
 
 890  If you 
find such a package installed on your system
, 
 891  something went horribly wrong
! They are autogenerated
 
 892  und used only by testcases and surf no other propose…
"}" 
 894         local FILE
='rootdir/var/lib/dpkg/status' 
 895         local INFO
='rootdir/var/lib/dpkg/info' 
 896         for arch 
in $(getarchitecturesfromcommalist "$ARCH"); do 
 902 Maintainer: Joe Sixpack <joe@example.org> 
 903 Version: $VERSION" >> "$FILE" 
 904                 test "$arch" = 'none' || echo "Architecture: $arch" >> "$FILE" 
 905                 test -z "$DEPENDENCIES" || echo "$DEPENDENCIES" >> "$FILE" 
 906                 echo "Description: $DESCRIPTION" >> "$FILE" 
 908                 if [ "$(dpkg-query -W --showformat='${Multi-Arch}')" = 'same' ]; then 
 909                         echo -n > "${INFO}/${NAME}:${arch}.list" 
 911                         echo -n > "${INFO}/${NAME}.list" 
 917 buildaptarchivefromincoming
() { 
 918         msginfo 
"Build APT archive for ${CCMD}${0##*/}${CINFO} based on incoming packages…" 
 920         [ -e pool 
] || ln -s ..
/incoming pool
 
 921         [ -e ftparchive.conf 
] || createaptftparchiveconfig
 
 922         [ -e dists 
] || buildaptftparchivedirectorystructure
 
 923         msgninfo 
"\tGenerate Packages, Sources and Contents files… " 
 924         testsuccess aptftparchive generate ftparchive.conf
 
 927         generatereleasefiles 
"$@" 
 930 buildaptarchivefromfiles
() { 
 931         msginfo 
"Build APT archive for ${CCMD}${0##*/}${CINFO} based on prebuild files…" 
 932         local DIR
='aptarchive' 
 933         if [ -d "${DIR}/dists" ]; then DIR
="${DIR}/dists"; fi 
 934         find "$DIR" -name 'Packages' -o -name 'Sources' -o -name 'Translation-*' | while read line
; do 
 935                 msgninfo 
"\t${line} file… " 
 936                 compressfile 
"$line" "$1" 
 939         generatereleasefiles 
"$@" 
 943         cat "${TMPWORKINGDIRECTORY}/rootdir/etc/testcase-compressor.conf" | while read compressor extension 
command; do 
 944                 if [ "$compressor" = '.' ]; then 
 950                 cat "$1" | $command > "${1}.${extension}" 
 952                         touch -d "$2" "${1}.${extension}" 
 957 # can be overridden by testcases for their pleasure 
 958 getcodenamefromsuite
() { 
 960         unstable
) echo 'sid';; 
 964 getreleaseversionfromsuite
() { true
; } 
 965 getlabelfromsuite
() { true
; } 
 966 getoriginfromsuite
() { true
; } 
 967 getarchitecturesfromreleasefile
() { echo "all $(getarchitectures)"; } 
 969 aptftparchiverelease
() { 
 970         aptftparchive 
-qq release 
"$@" | sed -e '/0 Release$/ d' # remove the self reference 
 972 generatereleasefiles
() { 
 973         # $1 is the Date header and $2 is the ValidUntil header to be set 
 974         # both should be given in notation date/touch can understand 
 976         local VALIDUNTIL
="$2" 
 977         if [ -e aptarchive
/dists 
]; then 
 978                 msgninfo 
"\tGenerate Release files for dists… " 
 979                 for dir 
in $(find ./aptarchive/dists -mindepth 1 -maxdepth 1 -type d); do 
 980                         local ARCHITECTURES
="$(getarchitecturesfromreleasefile "$dir")" 
 981                         local SUITE
="$(echo "$dir" | cut -d'/' -f 4)" 
 982                         local CODENAME
="$(getcodenamefromsuite $SUITE)" 
 983                         local VERSION
="$(getreleaseversionfromsuite $SUITE)" 
 984                         local LABEL
="$(getlabelfromsuite $SUITE)" 
 985                         local ORIGIN
="$(getoriginfromsuite $SUITE)" 
 986                         aptftparchiverelease 
"$dir" \
 
 987                                 -o APT
::FTPArchive
::Release
::Suite
="${SUITE}" \
 
 988                                 -o APT
::FTPArchive
::Release
::Codename
="${CODENAME}" \
 
 989                                 -o APT
::FTPArchive
::Release
::Architectures
="${ARCHITECTURES}" \
 
 990                                 -o APT
::FTPArchive
::Release
::Label
="${LABEL}" \
 
 991                                 -o APT
::FTPArchive
::Release
::Origin
="${ORIGIN}" \
 
 992                                 -o APT
::FTPArchive
::Release
::Version
="${VERSION}" \
 
 994                         if [ "$SUITE" = "experimental" -o "$SUITE" = "experimental2" ]; then 
 996 NotAutomatic: yes' "$dir/Release" 
1000                 msgninfo 
"\tGenerate Release files for flat… " 
1001                 aptftparchiverelease .
/aptarchive 
> aptarchive
/Release
 
1003         if [ -n "$DATE" -a "$DATE" != "now" ]; then 
1004                 for release 
in $(find ./aptarchive -name 'Release'); do 
1005                         sed -i "s/^Date: .*$/Date: $(date -d "$DATE" '+%a, %d %b %Y %H:%M:%S %Z')/" "$release" 
1006                         touch -d "$DATE" "$release" 
1009         if [ -n "$VALIDUNTIL" ]; then 
1010                 sed -i "/^Date: / a\ 
1011 Valid-Until: $(date -d "$VALIDUNTIL" '+%a, %d %b %Y %H:%M:%S %Z')" $(find ./aptarchive -name 'Release') 
1016 setupdistsaptarchive
() { 
1017         local APTARCHIVE
="$(readlink -f ./aptarchive | sed 's# #%20#g')" 
1018         rm -f root
/etc
/apt
/sources.list.d
/apt
-test-*-deb.list
 
1019         rm -f root
/etc
/apt
/sources.list.d
/apt
-test-*-deb-src.list
 
1020         for DISTS 
in $(find ./aptarchive/dists/ -mindepth 1 -maxdepth 1 -type d | cut -d'/' -f 4); do 
1021                 SECTIONS
=$(find "./aptarchive/dists/${DISTS}/" -mindepth 1 -maxdepth 1 -type d | cut -d'/' -f 5 | tr '\n' ' ') 
1022                 msgninfo 
"\tadd deb and deb-src sources.list lines for ${CCMD}${DISTS} ${SECTIONS}${CINFO}… " 
1023                 echo "deb file://$APTARCHIVE $DISTS $SECTIONS" > "rootdir/etc/apt/sources.list.d/apt-test-${DISTS}-deb.list" 
1024                 echo "deb-src file://$APTARCHIVE $DISTS $SECTIONS" > "rootdir/etc/apt/sources.list.d/apt-test-${DISTS}-deb-src.list" 
1029 setupflataptarchive
() { 
1030         local APTARCHIVE
="$(readlink -f ./aptarchive)" 
1031         local APTARCHIVEURI
="$(readlink -f ./aptarchive | sed 's# #%20#g')" 
1032         if [ -f "${APTARCHIVE}/Packages" ]; then 
1033                 msgninfo 
"\tadd deb sources.list line… " 
1034                 echo "deb file://$APTARCHIVEURI /" > 'rootdir/etc/apt/sources.list.d/apt-test-archive-deb.list' 
1037                 rm -f 'rootdir/etc/apt/sources.list.d/apt-test-archive-deb.list' 
1039         if [ -f "${APTARCHIVE}/Sources" ]; then 
1040                 msgninfo 
"\tadd deb-src sources.list line… " 
1041                 echo "deb-src file://$APTARCHIVEURI /" > 'rootdir/etc/apt/sources.list.d/apt-test-archive-deb-src.list' 
1044                 rm -f 'rootdir/etc/apt/sources.list.d/apt-test-archive-deb-src.list' 
1050         if [ "$1" = '--no-update' ]; then 
1054         buildaptarchive 
"$@" 
1055         if [ -e aptarchive
/dists 
]; then 
1056                 setupdistsaptarchive
 
1060         signreleasefiles 
'Joe Sixpack' 
1061         if [ "1" != "$NOUPDATE" ]; then 
1062                 testsuccess aptget update 
-o Debug
::pkgAcquire
::Worker
=true 
-o Debug
::Acquire
::gpgv
=true
 
1066 signreleasefiles
() { 
1067         local SIGNER
="${1:-Joe Sixpack}" 
1068         local REPODIR
="${2:-aptarchive}" 
1069         local KEY
="keys/$(echo "$SIGNER" | tr 'A-Z' 'a-z' | sed 's# ##g')" 
1070         local GPG
="aptkey --quiet --keyring ${KEY}.pub --secret-keyring ${KEY}.sec --readonly adv --batch --yes" 
1071         msgninfo 
"\tSign archive with $SIGNER key $KEY… " 
1072         local REXKEY
='keys/rexexpired' 
1073         local SECEXPIREBAK
="${REXKEY}.sec.bak" 
1074         local PUBEXPIREBAK
="${REXKEY}.pub.bak" 
1075         if [ "${SIGNER}" = 'Rex Expired' ]; then 
1076                 # the key is expired, so gpg doesn't allow to sign with and the --faked-system-time 
1077                 # option doesn't exist anymore (and using faketime would add a new obscure dependency) 
1078                 # therefore we 'temporary' make the key not expired and restore a backup after signing 
1079                 cp "${REXKEY}.sec" "$SECEXPIREBAK" 
1080                 cp "${REXKEY}.pub" "$PUBEXPIREBAK" 
1081                 local SECUNEXPIRED
="${REXKEY}.sec.unexpired" 
1082                 local PUBUNEXPIRED
="${REXKEY}.pub.unexpired" 
1083                 if [ -f "$SECUNEXPIRED" ] && [ -f "$PUBUNEXPIRED" ]; then 
1084                         cp "$SECUNEXPIRED" "${REXKEY}.sec" 
1085                         cp "$PUBUNEXPIRED" "${REXKEY}.pub" 
1087                         if ! printf "expire\n1w\nsave\n" | $GPG --default-key "$SIGNER" --command-fd 0 --edit-key "${SIGNER}" >setexpire.gpg 
2>&1; then 
1091                         cp "${REXKEY}.sec" "$SECUNEXPIRED" 
1092                         cp "${REXKEY}.pub" "$PUBUNEXPIRED" 
1095         for RELEASE 
in $(find "${REPODIR}/" -name Release); do 
1096                 $GPG --default-key "$SIGNER" --armor --detach-sign --sign --output "${RELEASE}.gpg" "${RELEASE}" 
1097                 local INRELEASE
="$(echo "${RELEASE}" | sed 's#/Release$#/InRelease#')" 
1098                 $GPG --default-key "$SIGNER" --clearsign --output "$INRELEASE" "$RELEASE" 
1099                 # we might have set a specific date for the Release file, so copy it 
1100                 touch -d "$(stat --format "%y" ${RELEASE})" "${RELEASE}.gpg" "${INRELEASE}" 
1102         if [ -f "$SECEXPIREBAK" ] && [ -f "$PUBEXPIREBAK" ]; then 
1103                 mv -f "$SECEXPIREBAK" "${REXKEY}.sec" 
1104                 mv -f "$PUBEXPIREBAK" "${REXKEY}.pub" 
1109 redatereleasefiles
() { 
1110         local DATE
="$(date -d "$1" '+%a, %d %b %Y %H:%M:%S %Z')" 
1111         for release 
in $(find aptarchive/ -name 'Release'); do 
1112                 sed -i "s/^Date: .*$/Date: ${DATE}/" "$release" 
1113                 touch -d "$DATE" "$release" 
1115         signreleasefiles 
"${2:-Joe Sixpack}" 
1119         local WEBSERVER
="${3:-http://localhost:${APTHTTPPORT}}" 
1121         if [ "$1" = '--no-check' ]; then 
1125         local DOWNLOG
='rootdir/tmp/download-testfile.log' 
1126         local STATUS
='downloaded/webserverconfig.status' 
1127         rm -f "$STATUS" "$DOWNLOG" 
1128         # very very basic URI encoding 
1130         if [ -n "$2" ]; then 
1131                 msgtest 
"Set webserver config option '${1}' to" "$2" 
1132                 URI
="${WEBSERVER}/_config/set/$(echo "${1}" | sed -e 's/\//%2f/g')/$(echo "${2}" | sed -e 's/\//%2f/g')" 
1134                 msgtest 
'Clear webserver config option' "${1}" 
1135                 URI
="${WEBSERVER}/_config/clear/$(echo "${1}" | sed -e 's/\//%2f/g')" 
1137         if downloadfile 
"$URI" "$STATUS" > "$DOWNLOG"; then 
1140                 local OUTPUT
="${TMPWORKINGDIRECTORY}/rootdir/tmp/webserverconfig.output" 
1141                 cat "$DOWNLOG" "$STATUS" >"$OUTPUT" 2>&1 || true
 
1142                 msgfailoutput 
'' "$OUTPUT" 
1144         $NOCHECK || testwebserverlaststatuscode 
'200' 
1147 rewritesourceslist
() { 
1148         local APTARCHIVE
="file://$(readlink -f "${TMPWORKINGDIRECTORY}/aptarchive" | sed 's# #%20#g')" 
1149         local APTARCHIVE2
="copy://$(readlink -f "${TMPWORKINGDIRECTORY}/aptarchive" | sed 's# #%20#g')" 
1150         for LIST 
in $(find rootdir/etc/apt/sources.list.d/ -name 'apt-test-*.list'); do 
1151                 sed -i $LIST -e "s#$APTARCHIVE#${1}#" -e "s#$APTARCHIVE2#${1}#" \
 
1152                         -e "s#http://localhost:${APTHTTPPORT}/#${1}#" \
 
1153                         -e "s#https://localhost:${APTHTTPSPORT}/#${1}#" 
1157 # wait for up to 10s for a pid file to appear to avoid possible race 
1158 # when a helper is started and dosn't write the PID quick enough 
1161         for i 
in $(seq 10); do 
1162                 if test -s "$PIDFILE"; then 
1167         msgdie 
"waiting for $PIDFILE failed" 
1171 changetowebserver
() { 
1173         if [ "$1" != '--no-rewrite' ]; then 
1178         if test -x "${APTWEBSERVERBINDIR}/aptwebserver"; then 
1180                 local LOG
="webserver.log" 
1181                 if ! aptwebserver 
--port 0 -o aptwebserver
::fork
=1 -o aptwebserver
::portfile
='aptwebserver.port' "$@" >$LOG 2>&1 ; then 
1185                 waitforpidfile aptwebserver.pid
 
1186                 local PID
="$(cat aptwebserver.pid)" 
1187                 if [ -z "$PID" ]; then 
1188                         msgdie 
'Could not fork aptwebserver successfully' 
1190                 addtrap 
"kill $PID;" 
1191                 waitforpidfile aptwebserver.port
 
1192                 APTHTTPPORT
="$(cat aptwebserver.port)" 
1193                 if [ -z "$APTHTTPPORT" ]; then 
1194                         msgdie 
'Could not get port for aptwebserver successfully' 
1198                 msgdie 
'You have to build aptwerbserver or install a webserver' 
1200         if [ "$REWRTE" != 'yes' ]; then 
1201                 rewritesourceslist 
"http://localhost:${APTHTTPPORT}/" 
1205 changetohttpswebserver
() { 
1206         if ! which stunnel4 
>/dev
/null
; then 
1207                 msgdie 
'You need to install stunnel4 for https testcases' 
1209         if [ ! -e "${TMPWORKINGDIRECTORY}/aptarchive/aptwebserver.pid" ]; then 
1210                 changetowebserver 
--no-rewrite "$@" 
1212         echo "pid = ${TMPWORKINGDIRECTORY}/aptarchive/stunnel.pid 
1213 cert = ${TMPWORKINGDIRECTORY}/rootdir/etc/webserver.pem 
1218 connect = $APTHTTPPORT 
1219 " > "${TMPWORKINGDIRECTORY}/stunnel.conf" 
1220         stunnel4 
"${TMPWORKINGDIRECTORY}/stunnel.conf" 
1221         waitforpidfile 
"${TMPWORKINGDIRECTORY}/aptarchive/stunnel.pid" 
1222         local PID
="$(cat "${TMPWORKINGDIRECTORY}/aptarchive/stunnel.pid")" 
1223         if [ -z "$PID" ]; then 
1224                 msgdie 
'Could not fork stunnel4 successfully' 
1226         addtrap 
'prefix' "kill ${PID};" 
1227         APTHTTPSPORT
="$(lsof -i | awk "/^stunnel4 / && \$2 == \"${PID}\" {print \$9; exit; }" | cut -d':' -f 2)" 
1228         webserverconfig 
'aptwebserver::port::https' "$APTHTTPSPORT" "https://localhost:${APTHTTPSPORT}" 
1229         rewritesourceslist 
"https://localhost:${APTHTTPSPORT}/" 
1233         mkdir -p rootdir
/media
/cdrom
/.disk
 
1234         local CD
="$(readlink -f rootdir/media/cdrom)" 
1235         cat > rootdir
/etc
/apt
/apt.conf.d
/00cdrom 
<<EOF 
1236 acquire::cdrom::mount "${CD}"; 
1237 acquire::cdrom::"${CD}/"::mount "mv ${CD}-unmounted ${CD}"; 
1238 acquire::cdrom::"${CD}/"::umount "mv ${CD} ${CD}-unmounted"; 
1239 acquire::cdrom::autodetect 0; 
1241         echo -n "$1" > "${CD}/.disk/info" 
1242         if [ ! -d aptarchive
/dists 
]; then 
1243                 msgdie 
'Flat file archive cdroms can not be created currently' 
1246         mv aptarchive
/dists 
"$CD" 
1247         ln -s "$(readlink -f ./incoming)" "$CD/pool" 
1248         find rootdir
/etc
/apt
/sources.list.d
/ -name 'apt-test-*.list' -delete 
1249         # start with an unmounted disk 
1250         mv "${CD}" "${CD}-unmounted" 
1251         # we don't want the disk to be modifiable 
1252         addtrap 
'prefix' "chmod -f -R +w \"$PWD/rootdir/media/cdrom/dists/\" \"$PWD/rootdir/media/cdrom-unmounted/dists/\" || true;" 
1253         chmod -R 555 rootdir
/media
/cdrom
-unmounted/dists
 
1257         local PROTO
="${1%%:*}" 
1258         if ! apthelper 
-o Debug
::Acquire
::${PROTO}=1 -o Debug
::pkgAcquire
::Worker
=1 \
 
1259                 download
-file "$1" "$2" "$3" 2>&1 ; then 
1262         # only if the file exists the download was successful 
1263         if [ -r "$2" ]; then 
1271         local DIFFTEXT
="$(command diff -u "$@" 2>&1 | sed -e '/^---/ d' -e '/^+++/ d' -e '/^@@/ d')" 
1272         if [ -n "$DIFFTEXT" ]; then 
1274                 echo >&2 "$DIFFTEXT" 
1282         local OUTPUT
="${TMPWORKINGDIRECTORY}/rootdir/tmp/testoutputequal.output" 
1283         local COMPAREFILE
="$1" 
1285         if "$@" 2>&1 | checkdiff 
"$COMPAREFILE" - >"$OUTPUT" 2>&1; then 
1288                 echo "=== content of file we compared with (${COMPAREFILE}) ===" >>"${OUTPUT}" 
1289                 cat "$COMPAREFILE" >>"${OUTPUT}" 
1290                 msgfailoutput 
'' "$OUTPUT" "$@" 
1295         msggroup 
'testfileequal' 
1296         local MSG
='Test for correctness of file' 
1297         if [ "$1" = '--nomsg' ]; then 
1303         if [ -n "$MSG" ]; then 
1304                 msgtest 
"$MSG" "$FILE" 
1306         local OUTPUT
="${TMPWORKINGDIRECTORY}/rootdir/tmp/testfileequal.output" 
1307         if [ -z "$*" ]; then 
1308                 testoutputequal 
"$FILE" echo -n '' 
1310                 testoutputequal 
"$FILE" echo "$*" 
1316         msggroup 
'testempty' 
1317         msgtest 
"Test for no output of" "$*" 
1318         local COMPAREFILE
="${TMPWORKINGDIRECTORY}/rootdir/tmp/testempty.comparefile" 
1319         if ("$@" >"$COMPAREFILE" 2>&1 || true
) && test ! -s "$COMPAREFILE"; then 
1322                 msgfailoutput 
'' "$COMPAREFILE" "$@" 
1324         aptautotest 
'testempty' "$@" 
1328         msggroup 
'testnotempty' 
1329         msgtest 
"Test for some output of" "$*" 
1330         local COMPAREFILE
="${TMPWORKINGDIRECTORY}/rootdir/tmp/testnotempty.comparefile" 
1331         if ("$@" >"$COMPAREFILE" 2>&1 || true
) && test -s "$COMPAREFILE"; then 
1334                 msgfailoutput 
'' "$COMPAREFILE" "$@" 
1336         aptautotest 
'testnotempty' "$@" 
1341         msggroup 
'testequal' 
1342         local MSG
='Test of equality of' 
1343         if [ "$1" = '--nomsg' ]; then 
1348         local COMPAREFILE
="${TMPWORKINGDIRECTORY}/rootdir/tmp/testequal.comparefile" 
1349         echo "$1" > "$COMPAREFILE" 
1352         if [ -n "$MSG" ]; then 
1355         testoutputequal 
"$COMPAREFILE" "$@" 
1356         aptautotest 
'testequal' "$@" 
1361         msggroup 
'testequalor2' 
1362         local COMPAREFILE1
="${TMPWORKINGDIRECTORY}/rootdir/tmp/testequalor2.comparefile1" 
1363         local COMPAREFILE2
="${TMPWORKINGDIRECTORY}/rootdir/tmp/testequalor2.comparefile2" 
1364         local COMPAREAGAINST
="${TMPWORKINGDIRECTORY}/rootdir/tmp/testequalor2.compareagainst" 
1365         echo "$1" > "$COMPAREFILE1" 
1366         echo "$2" > "$COMPAREFILE2" 
1368         msgtest 
"Test for equality OR of" "$*" 
1369         "$@" >"$COMPAREAGAINST" 2>&1 || true
 
1370         if checkdiff 
"$COMPAREFILE1" "$COMPAREAGAINST" >/dev
/null 
2>&1 || \
 
1371                 checkdiff 
"$COMPAREFILE2" "$COMPAREAGAINST" >/dev
/null 
2>&1 
1375                 local OUTPUT
="${TMPWORKINGDIRECTORY}/rootdir/tmp/testequal.output" 
1376                 echo -n "\n${CINFO}Diff against OR 1${CNORMAL}" >"$OUTPUT" 2>&1 
1377                 checkdiff 
"$COMPAREFILE1" "$COMPAREAGAINST" >"$OUTPUT" 2>&1 || true
 
1378                 echo -n "${CINFO}Diff against OR 2${CNORMAL}" >"$OUTPUT" 2>&1 
1379                 checkdiff 
"$COMPAREFILE2" "$COMPAREAGAINST" >"$OUTPUT" 2>&1 || true
 
1380                 msgfailoutput 
'' "$OUTPUT" 
1382         aptautotest 
'testequalor2' "$@" 
1387         msggroup 
'testshowvirtual' 
1388         local VIRTUAL
="N: Can't select versions from package '$1' as it is purely virtual" 
1391         while [ -n "$1" ]; do 
1393 N: Can't select versions from package '$1' as it is purely virtual" 
1394                 PACKAGE
="${PACKAGE} $1" 
1397         msgtest 
"Test for virtual packages" "apt-cache show $PACKAGE" 
1399 N: No packages found" 
1400         local COMPAREFILE
="${TMPWORKINGDIRECTORY}/rootdir/tmp/testshowvirtual.comparefile" 
1401         local ARCH
="$(getarchitecture 'native')" 
1402         echo "$VIRTUAL" | sed -e "s/:$ARCH//" -e 's/:all//' >"$COMPAREFILE" 
1403         local OUTPUT
="${TMPWORKINGDIRECTORY}/rootdir/tmp/testshowvirtual.output" 
1404         testoutputequal 
"$COMPAREFILE" aptcache show 
"$PACKAGE" 
1409         msggroup 
'testnopackage' 
1410         msgtest 
"Test for non-existent packages" "apt-cache show $*" 
1411         local SHOWPKG
="$(aptcache show "$@" 2>&1 | grep '^Package: ')" 
1412         if [ -n "$SHOWPKG" ]; then 
1413                 local OUTPUT
="${TMPWORKINGDIRECTORY}/rootdir/tmp/testnopackage.output" 
1414                 echo "$SHOWPKG" >"$OUTPUT" 
1415                 msgfailoutput 
'' "$OUTPUT" 
1423         msggroup 
'testdpkgstatus' 
1427         msgtest 
"Test that $NR package(s) are in state $STATE with" "dpkg -l $*" 
1428         local PKGS
="$(dpkg -l "$@" 2>/dev/null | grep "^${STATE}" | wc -l)" 
1429         if [ "$PKGS" != $NR ]; then 
1430                 local OUTPUT
="${TMPWORKINGDIRECTORY}/rootdir/tmp/testnopackage.output" 
1431                 echo "$PKGS" >"$OUTPUT" 
1432                 dpkg 
-l "$@" | grep '^[a-z]' >"$OUTPUT" >&2 || true
 
1433                 msgfailoutput 
'' "$OUTPUT" 
1440 testdpkginstalled
() { 
1441         msggroup 
'testdpkginstalled' 
1442         testdpkgstatus 
'ii' "$#" "$@" 
1446 testdpkgnotinstalled
() { 
1447         msggroup 
'testdpkgnotinstalled' 
1448         testdpkgstatus 
'ii' '0' "$@" 
1453         msggroup 
'testmarkedauto' 
1454         local COMPAREFILE
="${TMPWORKINGDIRECTORY}/rootdir/tmp/testmarkedauto.comparefile" 
1455         if [ -n "$1" ]; then 
1456                 msgtest 
'Test for correctly marked as auto-installed' "$*" 
1457                 while [ -n "$1" ]; do echo "$1"; shift; done | sort > "$COMPAREFILE" 
1459                 msgtest 
'Test for correctly marked as auto-installed' 'no package' 
1460                 echo -n > "$COMPAREFILE" 
1462         testoutputequal 
"$COMPAREFILE" aptmark showauto
 
1465 testmarkedmanual
() { 
1466         msggroup 
'testmarkedmanual' 
1467         local COMPAREFILE
="${TMPWORKINGDIRECTORY}/rootdir/tmp/testmarkedmanual.comparefile" 
1468         if [ -n "$1" ]; then 
1469                 msgtest 
'Test for correctly marked as manually installed' "$*" 
1470                 while [ -n "$1" ]; do echo "$1"; shift; done | sort > "$COMPAREFILE" 
1472                 msgtest 
'Test for correctly marked as manually installed' 'no package' 
1473                 echo -n > "$COMPAREFILE" 
1475         testoutputequal 
"$COMPAREFILE" aptmark showmanual
 
1480         msgreportheader 
'msgfailoutput' 
1484         if [ "$1" = 'grep' ]; then 
1486                 while [ -n "$2" ]; do shift; done 
1487                 echo "#### Complete file: $1 ####" 
1488                 cat >&2 "$1" || true
 
1489                 echo '#### grep output ####' 
1490         elif [ "$1" = 'test' ]; then 
1492                 # doesn't support ! or non-file flags 
1493                 msgfailoutputstatfile
() { 
1494                         local FILEFLAGS
='^-[bcdefgGhkLOprsStuwx]$' 
1495                         if expr match 
"$1" "$FILEFLAGS" >/dev
/null
; then 
1496                                 echo "#### stat(2) of file: $2 ####" 
1498                                 if test -e "$2"; then 
1499                                         echo "#### Complete file: $2 ####" 
1500                                         cat >&2 "$2" || true
 
1504                 msgfailoutputstatfile 
"$2" "$3" 
1505                 while [ -n "$5" ] && [ "$4" = '-o' -o "$4" = '-a' ]; do 
1507                         msgfailoutputstatfile 
"$2" "$3" 
1509                 echo '#### test output ####' 
1515 testsuccesswithglobalerror
() { 
1520         if [ "$1" = '--nomsg' ]; then 
1523                 msgtest 
'Test for successful execution of' "$*" 
1525         local OUTPUT
="${TMPWORKINGDIRECTORY}/rootdir/tmp/${TYPE}.output" 
1526         if "$@" >"${OUTPUT}" 2>&1; then 
1527                 if expr match 
"$1" '^apt.*' >/dev
/null
; then 
1528                         if grep -q -E ' runtime error: ' "$OUTPUT"; then 
1529                                 msgfailoutput 
'compiler detected undefined behavior' "$OUTPUT" "$@" 
1530                         elif grep -E "^[${ERRORS}]: " "$OUTPUT" > "${TMPWORKINGDIRECTORY}/rootdir/tmp/checkforwarnings.output" 2>&1; then 
1531                                 if [ "$IGNORE_PTY_NOT_MOUNTED" = '1' ]; then 
1532                                         if echo 'E: Can not write log (Is /dev/pts mounted?) - posix_openpt (2: No such file or directory)' \
 
1533                                                 | cmp - "${TMPWORKINGDIRECTORY}/rootdir/tmp/checkforwarnings.output" >/dev
/null 
2>&1; then 
1536                                                 msgfailoutput 
'successful run, but output contains warnings/errors' "$OUTPUT" "$@" 
1539                                         msgfailoutput 
'successful run, but output contains warnings/errors' "$OUTPUT" "$@" 
1541                         elif [ "$TYPE" = 'testsuccesswithnotice' ]; then 
1542                                 if grep -q -E "^N: " "$OUTPUT"; then 
1545                                         msgfailoutput 
'successful run, but output had no notices' "$OUTPUT" "$@" 
1555                 msgfailoutput 
"exitcode $EXITCODE" "$OUTPUT" "$@" 
1557         aptautotest 
"$TYPE" "$@" 
1560 testsuccesswithnotice
() { 
1561         testsuccesswithglobalerror 
'testsuccesswithnotice' 'WE' "$@" 
1564         testsuccesswithglobalerror 
'testsuccess' 'NWE' "$@" 
1567         msggroup 
'testwarning' 
1568         if [ "$1" = '--nomsg' ]; then 
1571                 msgtest 
'Test for successful execution with warnings of' "$*" 
1573         local OUTPUT
="${TMPWORKINGDIRECTORY}/rootdir/tmp/testwarning.output" 
1574         if "$@" >"${OUTPUT}" 2>&1; then 
1575                 if expr match 
"$1" '^apt.*' >/dev
/null
; then 
1576                         if grep -q -E ' runtime error: ' "$OUTPUT"; then 
1577                                 msgfailoutput 
'compiler detected undefined behavior' "$OUTPUT" "$@" 
1578                         elif grep -q -E '^E: ' "$OUTPUT"; then 
1579                                 msgfailoutput 
'successful run, but output contains errors' "$OUTPUT" "$@" 
1580                         elif ! grep -q -E '^W: ' "$OUTPUT"; then 
1581                                 msgfailoutput 
'successful run, but output contains no warnings' "$OUTPUT" "$@" 
1590                 msgfailoutput 
"exitcode $EXITCODE" "$OUTPUT" "$@" 
1592         aptautotest 
'testwarning' "$@" 
1596         msggroup 
'testfailure' 
1597         if [ "$1" = '--nomsg' ]; then 
1600                 msgtest 
'Test for failure in execution of' "$*" 
1602         local OUTPUT
="${TMPWORKINGDIRECTORY}/rootdir/tmp/testfailure.output" 
1603         if "$@" >"${OUTPUT}" 2>&1; then 
1605                 msgfailoutput 
"exitcode $EXITCODE" "$OUTPUT" "$@" 
1608                 if expr match 
"$1" '^apt.*' >/dev
/null
; then 
1609                         if [ "$1" = 'aptkey' ]; then 
1610                                 if grep -q -E " Can't check signature: " "$OUTPUT" || \
 
1611                                         grep -q -E " BAD signature from " "$OUTPUT"; then 
1614                                         msgfailoutput 
"run failed with exitcode ${EXITCODE}, but no signature error" "$OUTPUT" "$@" 
1617                                 if grep -q -E ' runtime error: ' "$OUTPUT"; then 
1618                                         msgfailoutput 
'compiler detected undefined behavior' "$OUTPUT" "$@" 
1619                                 elif grep -q -E '==ERROR' "$OUTPUT"; then 
1620                                         msgfailoutput 
'compiler sanitizers reported errors' "$OUTPUT" "$@" 
1621                                 elif ! grep -q -E '^E: ' "$OUTPUT"; then 
1622                                         msgfailoutput 
"run failed with exitcode ${EXITCODE}, but with no errors" "$OUTPUT" "$@" 
1631         aptautotest 
'testfailure' "$@" 
1635 testreturnstateequal
() { 
1637         if [ "$STATE" = 'testsuccesswithglobalerror' ]; then 
1641                 msggroup 
"${STATE}equal" 
1642                 if [ "$1" != '--nomsg' ]; then 
1645                         testsuccesswithglobalerror 
"$STATE" "$TYPE" "$@" 
1646                         testfileequal 
"${TMPWORKINGDIRECTORY}/rootdir/tmp/${STATE}.output" "$CMP" 
1650                         testsuccesswithglobalerror 
"$STATE" "$TYPE" "$@" 
1651                         testfileequal 
"${TMPWORKINGDIRECTORY}/rootdir/tmp/${STATE}.output" "$CMP" 
1654                 msggroup 
"${STATE}equal" 
1655                 if [ "$2" != '--nomsg' ]; then 
1659                         testfileequal 
"${TMPWORKINGDIRECTORY}/rootdir/tmp/${STATE}.output" "$CMP" 
1663                         "$STATE" --nomsg "$@" 
1664                         testfileequal 
"${TMPWORKINGDIRECTORY}/rootdir/tmp/${STATE}.output" "$CMP" 
1669 testsuccessequal
() { 
1670         # we compare output, so we know perfectly well about N: 
1671         testreturnstateequal 
'testsuccesswithglobalerror' 'testsuccess' 'WE' "$@" 
1673 testwarningequal
() { 
1674         testreturnstateequal 
'testwarning' "$@" 
1676 testfailureequal
() { 
1677         testreturnstateequal 
'testfailure' "$@" 
1681         msggroup 
'testfailuremsg' 
1685         msgtest 
'Check that the output of the previous failed command has expected' 'failures and warnings' 
1686         local COMPAREFILE
="${TMPWORKINGDIRECTORY}/rootdir/tmp/testfailuremsg.comparefile" 
1687         grep '^\(W\|E\|N\):' "${TMPWORKINGDIRECTORY}/rootdir/tmp/testfailure.output" > "$COMPAREFILE" 2>&1 || true
 
1688         testoutputequal 
"$COMPAREFILE" echo "$CMP" 
1692         msggroup 
'testwarningmsg' 
1696         msgtest 
'Check that the output of the previous warned command has expected' 'warnings' 
1697         local COMPAREFILE
="${TMPWORKINGDIRECTORY}/rootdir/tmp/testwarningmsg.comparefile" 
1698         grep '^\(W\|E\|N\):' "${TMPWORKINGDIRECTORY}/rootdir/tmp/testwarning.output" > "$COMPAREFILE" 2>&1 || true
 
1699         testoutputequal 
"$COMPAREFILE" echo "$CMP" 
1704         msggroup 
'testfilestats' 
1705         msgtest 
"Test that file $1 has $2 $3" "$4" 
1706         if [ "$4" "$3" "$(stat --format "$2" "$1")" ]; then 
1709                 local OUTPUT
="${TMPWORKINGDIRECTORY}/rootdir/tmp/testfilestats.output" 
1712                         echo -n "stat(1) reports for $2: " 
1713                         stat 
--format "$2" "$1" || true
 
1715                 msgfailoutput 
'' "$OUTPUT" 
1719 testaccessrights
() { 
1720         msggroup 
'testaccessrights' 
1721         testfilestats 
"$1" '%a' '=' "$2" 
1725 testwebserverlaststatuscode
() { 
1726         msggroup 
'testwebserverlaststatuscode' 
1727         local DOWNLOG
='rootdir/tmp/webserverstatus-testfile.log' 
1728         local STATUS
='downloaded/webserverstatus-statusfile.log' 
1729         rm -f "$DOWNLOG" "$STATUS" 
1730         msgtest 
'Test last status code from the webserver was' "$1" 
1731         if downloadfile 
"http://localhost:${APTHTTPPORT}/_config/find/aptwebserver::last-status-code" "$STATUS" > "$DOWNLOG" && [ "$(cat "$STATUS")" = "$1" ]; then 
1734                 local OUTPUT
="${TMPWORKINGDIRECTORY}/rootdir/tmp/testwebserverlaststatuscode.output" 
1736                         if [ -n "$2" ]; then 
1738                                 echo >&2 '#### Additionally provided output files contain:' 
1741                         echo >&2 '#### Download log of the status code:' 
1744                 msgfailoutput 
"Status was $(cat "$STATUS")" "$OUTPUT" 
1750         echo "STOPPED execution. Press enter to continue" 
1755 listcurrentlistsdirectory
() { 
1757                 find rootdir
/var
/lib
/apt
/lists 
-maxdepth 1 -type d 
| while read line
; do 
1758                         stat 
--format '%U:%G:%a:%n' "$line" 
1760                 find rootdir
/var
/lib
/apt
/lists 
-maxdepth 1 \
! -type d 
| while read line
; do 
1761                         stat 
--format '%U:%G:%a:%s:%y:%n' "$line" 
1766 ### convenience hacks ### 
1768         # creating some directories by hand is a tedious task, so make it look simple 
1770         if [ "$PARAMS" != "${PARAMS#*rootdir/var/lib/apt/lists}" ]; then 
1771                 # only the last directory created by mkdir is effected by the -m ! 
1772                 command mkdir -m 755 -p "${TMPWORKINGDIRECTORY}/rootdir/var/lib/apt" 
1773                 command mkdir -m 755 -p "${TMPWORKINGDIRECTORY}/rootdir/var/lib/apt/lists" 
1774                 command mkdir -m 700 -p "${TMPWORKINGDIRECTORY}/rootdir/var/lib/apt/lists/partial" 
1775                 touch "${TMPWORKINGDIRECTORY}/rootdir/var/lib/apt/lists/lock" 
1776                 if [ "$(id -u)" = '0' ]; then 
1777                         chown _apt
:root 
"${TMPWORKINGDIRECTORY}/rootdir/var/lib/apt/lists/partial" 
1784 ### The following tests are run by most test methods automatically to check 
1785 ### general things about commands executed without writing the test every time. 
1791         local AUTOTEST
="aptautotest_$(echo "${CMD##*/}_${FIRSTOPT}" | tr -d '-')" 
1792         if command -v $AUTOTEST >/dev
/null
; then 
1794                 # save and restore the *.output files from other tests 
1795                 # as we might otherwise override them in these automatic tests 
1796                 rm -rf "${TMPWORKINGDIRECTORY}/rootdir/tmp-before" 
1797                 mv "${TMPWORKINGDIRECTORY}/rootdir/tmp" "${TMPWORKINGDIRECTORY}/rootdir/tmp-before" 
1798                 mkdir "${TMPWORKINGDIRECTORY}/rootdir/tmp" 
1799                 $AUTOTEST "$TESTCALL" "$@" 
1800                 rm -rf "${TMPWORKINGDIRECTORY}/rootdir/tmp-aptautotest" 
1801                 mv "${TMPWORKINGDIRECTORY}/rootdir/tmp" "${TMPWORKINGDIRECTORY}/rootdir/tmp-aptautotest" 
1802                 mv "${TMPWORKINGDIRECTORY}/rootdir/tmp-before" "${TMPWORKINGDIRECTORY}/rootdir/tmp" 
1806 aptautotest_aptget_update
() { 
1808         while [ -n "$2" ]; do 
1809                 if [ "$2" = '--print-uris' ]; then return; fi # simulation mode 
1812         if ! test -d "${TMPWORKINGDIRECTORY}/rootdir/var/lib/apt/lists"; then return; fi 
1813         testfilestats 
"${TMPWORKINGDIRECTORY}/rootdir/var/lib/apt" '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:755" 
1814         testfilestats 
"${TMPWORKINGDIRECTORY}/rootdir/var/lib/apt/lists" '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:755" 
1815         # all copied files are properly chmodded 
1816         local backupIFS
="$IFS" 
1817         IFS
="$(printf "\n\b")" 
1818         for file in $(find "${TMPWORKINGDIRECTORY}/rootdir/var/lib/apt/lists" -type f ! -name 'lock'); do 
1819                 testfilestats 
"$file" '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644" 
1822         if [ "$TESTCALL" = 'testsuccess' ]; then 
1823                 # failure cases can retain partial files and such 
1824                 testempty 
find "${TMPWORKINGDIRECTORY}/rootdir/var/lib/apt/lists/partial" -mindepth 1 ! \
( -name 'lock' -o -name '*.FAILED' \
) 
1827 aptautotest_apt_update
() { aptautotest_aptget_update 
"$@"; } 
1828 aptautotest_aptcdrom_add
() { aptautotest_aptget_update 
"$@"; } 
1830 testaptautotestnodpkgwarning
() { 
1832         while [ -n "$2" ]; do 
1833                 if expr match 
"$2" '^-[a-z]*s' >/dev
/null 
2>&1; then return; fi # simulation mode 
1834                 if expr match 
"$2" '^-dy\?' >/dev
/null 
2>&1; then return; fi # download-only mode 
1837         testfailure 
grep '^dpkg: warning:.*ignor.*' "${TMPWORKINGDIRECTORY}/rootdir/tmp-before/${TESTCALL}.output" 
1840 aptautotest_aptget_install
() { testaptautotestnodpkgwarning 
"$@"; } 
1841 aptautotest_aptget_remove
() { testaptautotestnodpkgwarning 
"$@"; } 
1842 aptautotest_aptget_purge
() { testaptautotestnodpkgwarning 
"$@"; } 
1843 aptautotest_apt_install
() { testaptautotestnodpkgwarning 
"$@"; } 
1844 aptautotest_apt_remove
() { testaptautotestnodpkgwarning 
"$@"; } 
1845 aptautotest_apt_purge
() { testaptautotestnodpkgwarning 
"$@"; }