// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
- // $Id: fileutl.cc,v 1.42 2002/09/14 05:29:22 jgg Exp $
/* ######################################################################
File Utilities
#include <apt-pkg/sptr.h>
#include <apt-pkg/aptconfiguration.h>
#include <apt-pkg/configuration.h>
-
+ #include <apt-pkg/macros.h>
+
+ #include <ctype.h>
+ #include <stdarg.h>
+ #include <stddef.h>
+ #include <sys/select.h>
+ #include <time.h>
+ #include <string>
+ #include <vector>
#include <cstdlib>
#include <cstring>
#include <cstdio>
-
#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
- #include <sys/types.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <dirent.h>
#ifdef HAVE_BZ2
#include <bzlib.h>
#endif
+ #ifdef HAVE_LZMA
+ #include <stdint.h>
+ #include <lzma.h>
+ #endif
#ifdef WORDS_BIGENDIAN
#include <inttypes.h>
using namespace std;
- class FileFdPrivate {
- public:
- #ifdef HAVE_ZLIB
- gzFile gz;
- #else
- void* gz;
- #endif
- #ifdef HAVE_BZ2
- BZFILE* bz2;
- #else
- void* bz2;
- #endif
- int compressed_fd;
- pid_t compressor_pid;
- bool pipe;
- APT::Configuration::Compressor compressor;
- unsigned int openmode;
- unsigned long long seekpos;
- FileFdPrivate() : gz(NULL), bz2(NULL),
- compressed_fd(-1), compressor_pid(-1), pipe(false),
- openmode(0), seekpos(0) {};
- bool CloseDown(std::string const &FileName)
- {
- bool Res = true;
- #ifdef HAVE_ZLIB
- if (gz != NULL) {
- int const e = gzclose(gz);
- gz = NULL;
- // gzdclose() on empty files always fails with "buffer error" here, ignore that
- if (e != 0 && e != Z_BUF_ERROR)
- Res &= _error->Errno("close",_("Problem closing the gzip file %s"), FileName.c_str());
- }
- #endif
- #ifdef HAVE_BZ2
- if (bz2 != NULL) {
- BZ2_bzclose(bz2);
- bz2 = NULL;
- }
- #endif
- if (compressor_pid > 0)
- ExecWait(compressor_pid, "FileFdCompressor", true);
- compressor_pid = -1;
-
- return Res;
- }
- ~FileFdPrivate() { CloseDown(""); }
- };
-
// RunScripts - Run a set of scripts from a configuration subtree /*{{{*/
// ---------------------------------------------------------------------
/* */
}
/*}}}*/
+ class FileFdPrivate { /*{{{*/
+ public:
+ #ifdef HAVE_ZLIB
+ gzFile gz;
+ #endif
+ #ifdef HAVE_BZ2
+ BZFILE* bz2;
+ #endif
+ #ifdef HAVE_LZMA
+ struct LZMAFILE {
+ FILE* file;
+ uint8_t buffer[4096];
+ lzma_stream stream;
+ lzma_ret err;
+ bool eof;
+ bool compressing;
+
+ LZMAFILE() : file(NULL), eof(false), compressing(false) {}
+ ~LZMAFILE() {
+ if (compressing == true)
+ {
+ for (;;) {
+ stream.avail_out = sizeof(buffer)/sizeof(buffer[0]);
+ stream.next_out = buffer;
+ err = lzma_code(&stream, LZMA_FINISH);
+ if (err != LZMA_OK && err != LZMA_STREAM_END)
+ {
+ _error->Error("~LZMAFILE: Compress finalisation failed");
+ break;
+ }
+ size_t const n = sizeof(buffer)/sizeof(buffer[0]) - stream.avail_out;
+ if (n && fwrite(buffer, 1, n, file) != n)
+ {
+ _error->Errno("~LZMAFILE",_("Write error"));
+ break;
+ }
+ if (err == LZMA_STREAM_END)
+ break;
+ }
+ }
+ lzma_end(&stream);
+ fclose(file);
+ }
+ };
+ LZMAFILE* lzma;
+ #endif
+ int compressed_fd;
+ pid_t compressor_pid;
+ bool pipe;
+ APT::Configuration::Compressor compressor;
+ unsigned int openmode;
+ unsigned long long seekpos;
+ FileFdPrivate() :
+ #ifdef HAVE_ZLIB
+ gz(NULL),
+ #endif
+ #ifdef HAVE_BZ2
+ bz2(NULL),
+ #endif
+ #ifdef HAVE_LZMA
+ lzma(NULL),
+ #endif
+ compressed_fd(-1), compressor_pid(-1), pipe(false),
+ openmode(0), seekpos(0) {};
+ bool InternalClose(std::string const &FileName)
+ {
+ if (false)
+ /* dummy so that the rest can be 'else if's */;
+ #ifdef HAVE_ZLIB
+ else if (gz != NULL) {
+ int const e = gzclose(gz);
+ gz = NULL;
+ // gzdclose() on empty files always fails with "buffer error" here, ignore that
+ if (e != 0 && e != Z_BUF_ERROR)
+ return _error->Errno("close",_("Problem closing the gzip file %s"), FileName.c_str());
+ }
+ #endif
+ #ifdef HAVE_BZ2
+ else if (bz2 != NULL) {
+ BZ2_bzclose(bz2);
+ bz2 = NULL;
+ }
+ #endif
+ #ifdef HAVE_LZMA
+ else if (lzma != NULL) {
+ delete lzma;
+ lzma = NULL;
+ }
+ #endif
+ return true;
+ }
+ bool CloseDown(std::string const &FileName)
+ {
+ bool const Res = InternalClose(FileName);
+
+ if (compressor_pid > 0)
+ ExecWait(compressor_pid, "FileFdCompressor", true);
+ compressor_pid = -1;
+
+ return Res;
+ }
+ bool InternalStream() const {
+ return false
+ #ifdef HAVE_BZ2
+ || bz2 != NULL
+ #endif
+ #ifdef HAVE_LZMA
+ || lzma != NULL
+ #endif
+ ;
+ }
+
+
+ ~FileFdPrivate() { CloseDown(""); }
+ };
+ /*}}}*/
// FileFd::Open - Open a file /*{{{*/
// ---------------------------------------------------------------------
/* The most commonly used open mode combinations are given with Mode */
{
for (; compressor != compressors.end(); ++compressor)
{
- std::string file = std::string(FileName).append(compressor->Extension);
+ std::string file = FileName + compressor->Extension;
if (FileExists(file) == false)
continue;
FileName = file;
{
Close();
Flags = (AutoClose) ? FileFd::AutoClose : 0;
- if (AutoClose == false && (
- #ifdef HAVE_ZLIB
- compressor.Name == "gzip" ||
- #endif
- #ifdef HAVE_BZ2
- compressor.Name == "bzip2" ||
- #endif
- false))
- {
- // Need to duplicate fd here or gzclose for cleanup will close the fd as well
- iFd = dup(Fd);
- }
- else
- iFd = Fd;
+ iFd = Fd;
this->FileName = "";
- if (Fd == -1 || OpenInternDescriptor(Mode, compressor) == false)
+ if (OpenInternDescriptor(Mode, compressor) == false)
{
if (iFd != -1 && (
- #ifdef HAVE_ZLIB
- compressor.Name == "gzip" ||
- #endif
- #ifdef HAVE_BZ2
- compressor.Name == "bzip2" ||
- #endif
+ (Flags & Compressed) == Compressed ||
AutoClose == true))
{
close (iFd);
}
bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::Compressor const &compressor)
{
+ if (iFd == -1)
+ return false;
if (compressor.Name == "." || compressor.Binary.empty() == true)
return true;
+ #if defined HAVE_ZLIB || defined HAVE_BZ2 || defined HAVE_LZMA
+ // the API to open files is similar, so setup to avoid code duplicates later
+ // and while at it ensure that we close before opening (if its a reopen)
+ void* (*compress_open)(int, const char *) = NULL;
+ if (false)
+ /* dummy so that the rest can be 'else if's */;
+ #define APT_COMPRESS_INIT(NAME,OPEN) \
+ else if (compressor.Name == NAME) \
+ { \
+ compress_open = (void*(*)(int, const char *)) OPEN; \
+ if (d != NULL) d->InternalClose(FileName); \
+ }
+ #ifdef HAVE_ZLIB
+ APT_COMPRESS_INIT("gzip", gzdopen)
+ #endif
+ #ifdef HAVE_BZ2
+ APT_COMPRESS_INIT("bzip2", BZ2_bzdopen)
+ #endif
+ #ifdef HAVE_LZMA
+ APT_COMPRESS_INIT("xz", fdopen)
+ APT_COMPRESS_INIT("lzma", fdopen)
+ #endif
+ #undef APT_COMPRESS_INIT
+ #endif
+
if (d == NULL)
{
d = new FileFdPrivate();
d->openmode = Mode;
d->compressor = compressor;
+ #if defined HAVE_ZLIB || defined HAVE_BZ2 || defined HAVE_LZMA
+ if (AutoClose == false && compress_open != NULL)
+ {
+ // Need to duplicate fd here or gz/bz2 close for cleanup will close the fd as well
+ int const internFd = dup(iFd);
+ if (internFd == -1)
+ return FileFdErrno("OpenInternDescriptor", _("Could not open file descriptor %d"), iFd);
+ iFd = internFd;
+ }
+ #endif
}
- #ifdef HAVE_ZLIB
- if (compressor.Name == "gzip")
+ #if defined HAVE_ZLIB || defined HAVE_BZ2 || defined HAVE_LZMA
+ if (compress_open != NULL)
{
- if (d->gz != NULL)
- {
- gzclose(d->gz);
- d->gz = NULL;
- }
+ void* compress_struct = NULL;
if ((Mode & ReadWrite) == ReadWrite)
- d->gz = gzdopen(iFd, "r+");
+ compress_struct = compress_open(iFd, "r+");
else if ((Mode & WriteOnly) == WriteOnly)
- d->gz = gzdopen(iFd, "w");
+ compress_struct = compress_open(iFd, "w");
else
- d->gz = gzdopen(iFd, "r");
- if (d->gz == NULL)
+ compress_struct = compress_open(iFd, "r");
+ if (compress_struct == NULL)
return false;
- Flags |= Compressed;
- return true;
- }
+
+ if (false)
+ /* dummy so that the rest can be 'else if's */;
+ #ifdef HAVE_ZLIB
+ else if (compressor.Name == "gzip")
+ d->gz = (gzFile) compress_struct;
#endif
#ifdef HAVE_BZ2
- if (compressor.Name == "bzip2")
- {
- if (d->bz2 != NULL)
+ else if (compressor.Name == "bzip2")
+ d->bz2 = (BZFILE*) compress_struct;
+ #endif
+ #ifdef HAVE_LZMA
+ else if (compressor.Name == "xz" || compressor.Name == "lzma")
{
- BZ2_bzclose(d->bz2);
- d->bz2 = NULL;
+ uint32_t const xzlevel = 6;
+ uint64_t const memlimit = UINT64_MAX;
+ if (d->lzma == NULL)
+ d->lzma = new FileFdPrivate::LZMAFILE;
+ d->lzma->file = (FILE*) compress_struct;
+ d->lzma->stream = LZMA_STREAM_INIT;
+
+ if ((Mode & ReadWrite) == ReadWrite)
+ return FileFdError("ReadWrite mode is not supported for file %s", FileName.c_str());
+
+ if ((Mode & WriteOnly) == WriteOnly)
+ {
+ if (compressor.Name == "xz")
+ {
+ if (lzma_easy_encoder(&d->lzma->stream, xzlevel, LZMA_CHECK_CRC32) != LZMA_OK)
+ return false;
+ }
+ else
+ {
+ lzma_options_lzma options;
+ lzma_lzma_preset(&options, xzlevel);
+ if (lzma_alone_encoder(&d->lzma->stream, &options) != LZMA_OK)
+ return false;
+ }
+ d->lzma->compressing = true;
+ }
+ else
+ {
+ if (compressor.Name == "xz")
+ {
+ if (lzma_auto_decoder(&d->lzma->stream, memlimit, 0) != LZMA_OK)
+ return false;
+ }
+ else
+ {
+ if (lzma_alone_decoder(&d->lzma->stream, memlimit) != LZMA_OK)
+ return false;
+ }
+ d->lzma->compressing = false;
+ }
}
- if ((Mode & ReadWrite) == ReadWrite)
- d->bz2 = BZ2_bzdopen(iFd, "r+");
- else if ((Mode & WriteOnly) == WriteOnly)
- d->bz2 = BZ2_bzdopen(iFd, "w");
- else
- d->bz2 = BZ2_bzdopen(iFd, "r");
- if (d->bz2 == NULL)
- return false;
+ #endif
Flags |= Compressed;
return true;
}
}
else
{
- if (FileName.empty() == true)
+ if (d->compressed_fd != -1)
dup2(d->compressed_fd,STDIN_FILENO);
dup2(Pipe[1],STDOUT_FILENO);
}
*((char *)To) = '\0';
do
{
+ if (false)
+ /* dummy so that the rest can be 'else if's */;
#ifdef HAVE_ZLIB
- if (d != NULL && d->gz != NULL)
+ else if (d != NULL && d->gz != NULL)
Res = gzread(d->gz,To,Size);
- else
#endif
#ifdef HAVE_BZ2
- if (d != NULL && d->bz2 != NULL)
+ else if (d != NULL && d->bz2 != NULL)
Res = BZ2_bzread(d->bz2,To,Size);
- else
#endif
+ #ifdef HAVE_LZMA
+ else if (d != NULL && d->lzma != NULL)
+ {
+ if (d->lzma->eof == true)
+ break;
+
+ d->lzma->stream.next_out = (uint8_t *) To;
+ d->lzma->stream.avail_out = Size;
+ if (d->lzma->stream.avail_in == 0)
+ {
+ d->lzma->stream.next_in = d->lzma->buffer;
+ d->lzma->stream.avail_in = fread(d->lzma->buffer, 1, sizeof(d->lzma->buffer)/sizeof(d->lzma->buffer[0]), d->lzma->file);
+ }
+ d->lzma->err = lzma_code(&d->lzma->stream, LZMA_RUN);
+ if (d->lzma->err == LZMA_STREAM_END)
+ {
+ d->lzma->eof = true;
+ Res = Size - d->lzma->stream.avail_out;
+ }
+ else if (d->lzma->err != LZMA_OK)
+ {
+ Res = -1;
+ errno = 0;
+ }
+ else
+ Res = Size - d->lzma->stream.avail_out;
+ }
+ #endif
+ else
Res = read(iFd,To,Size);
if (Res < 0)
{
if (errno == EINTR)
continue;
+ if (false)
+ /* dummy so that the rest can be 'else if's */;
#ifdef HAVE_ZLIB
- if (d != NULL && d->gz != NULL)
+ else if (d != NULL && d->gz != NULL)
{
int err;
char const * const errmsg = gzerror(d->gz, &err);
}
#endif
#ifdef HAVE_BZ2
- if (d != NULL && d->bz2 != NULL)
+ else if (d != NULL && d->bz2 != NULL)
{
int err;
char const * const errmsg = BZ2_bzerror(d->bz2, &err);
if (err != BZ_IO_ERROR)
return FileFdError("BZ2_bzread: %s (%d: %s)", _("Read error"), err, errmsg);
}
+ #endif
+ #ifdef HAVE_LZMA
+ else if (d != NULL && d->lzma != NULL)
+ return FileFdError("lzma_read: %s (%d)", _("Read error"), d->lzma->err);
#endif
return FileFdErrno("read",_("Read error"));
}
errno = 0;
do
{
+ if (false)
+ /* dummy so that the rest can be 'else if's */;
#ifdef HAVE_ZLIB
- if (d != NULL && d->gz != NULL)
- Res = gzwrite(d->gz,From,Size);
- else
+ else if (d != NULL && d->gz != NULL)
+ Res = gzwrite(d->gz,From,Size);
#endif
#ifdef HAVE_BZ2
- if (d != NULL && d->bz2 != NULL)
- Res = BZ2_bzwrite(d->bz2,(void*)From,Size);
- else
+ else if (d != NULL && d->bz2 != NULL)
+ Res = BZ2_bzwrite(d->bz2,(void*)From,Size);
+ #endif
+ #ifdef HAVE_LZMA
+ else if (d != NULL && d->lzma != NULL)
+ {
+ d->lzma->stream.next_in = (uint8_t *)From;
+ d->lzma->stream.avail_in = Size;
+ d->lzma->stream.next_out = d->lzma->buffer;
+ d->lzma->stream.avail_out = sizeof(d->lzma->buffer)/sizeof(d->lzma->buffer[0]);
+ d->lzma->err = lzma_code(&d->lzma->stream, LZMA_RUN);
+ if (d->lzma->err != LZMA_OK)
+ return false;
+ size_t const n = sizeof(d->lzma->buffer)/sizeof(d->lzma->buffer[0]) - d->lzma->stream.avail_out;
+ size_t const m = (n == 0) ? 0 : fwrite(d->lzma->buffer, 1, n, d->lzma->file);
+ if (m != n)
+ Res = -1;
+ else
+ Res = Size - d->lzma->stream.avail_in;
+ }
#endif
- Res = write(iFd,From,Size);
+ else
+ Res = write(iFd,From,Size);
+
if (Res < 0 && errno == EINTR)
continue;
if (Res < 0)
{
+ if (false)
+ /* dummy so that the rest can be 'else if's */;
#ifdef HAVE_ZLIB
- if (d != NULL && d->gz != NULL)
+ else if (d != NULL && d->gz != NULL)
{
int err;
char const * const errmsg = gzerror(d->gz, &err);
}
#endif
#ifdef HAVE_BZ2
- if (d != NULL && d->bz2 != NULL)
+ else if (d != NULL && d->bz2 != NULL)
{
int err;
char const * const errmsg = BZ2_bzerror(d->bz2, &err);
if (err != BZ_IO_ERROR)
return FileFdError("BZ2_bzwrite: %s (%d: %s)", _("Write error"), err, errmsg);
}
+ #endif
+ #ifdef HAVE_LZMA
+ else if (d != NULL && d->lzma != NULL)
+ return FileFdErrno("lzma_fwrite", _("Write error"));
#endif
return FileFdErrno("write",_("Write error"));
}
- From = (char *)From + Res;
+ From = (char const *)From + Res;
Size -= Res;
if (d != NULL)
d->seekpos += Res;
if (Res < 0)
return _error->Errno("write",_("Write error"));
- From = (char *)From + Res;
+ From = (char const *)From + Res;
Size -= Res;
}
while (Res > 0 && Size > 0);
/* */
bool FileFd::Seek(unsigned long long To)
{
- if (d != NULL && (d->pipe == true
- #ifdef HAVE_BZ2
- || d->bz2 != NULL
- #endif
- ))
+ if (d != NULL && (d->pipe == true || d->InternalStream() == true))
{
// Our poor man seeking in pipes is costly, so try to avoid it
unsigned long long seekpos = Tell();
if ((d->openmode & ReadOnly) != ReadOnly)
return FileFdError("Reopen is only implemented for read-only files!");
- #ifdef HAVE_BZ2
- if (d->bz2 != NULL)
- {
- BZ2_bzclose(d->bz2);
- d->bz2 = NULL;
- }
- #endif
+ d->InternalClose(FileName);
if (iFd != -1)
close(iFd);
iFd = -1;
/* */
bool FileFd::Skip(unsigned long long Over)
{
- if (d != NULL && (d->pipe == true
- #ifdef HAVE_BZ2
- || d->bz2 != NULL
- #endif
- ))
+ if (d != NULL && (d->pipe == true || d->InternalStream() == true))
{
d->seekpos += Over;
char buffer[1024];
// truncating /dev/null is always successful - as we get an error otherwise
if (To == 0 && FileName == "/dev/null")
return true;
- #if defined HAVE_ZLIB || defined HAVE_BZ2
- if (d != NULL && (d->gz != NULL || d->bz2 != NULL))
+ #if defined HAVE_ZLIB || defined HAVE_BZ2 || defined HAVE_LZMA
+ if (d != NULL && (d->InternalStream() == true
+ #ifdef HAVE_ZLIB
+ || d->gz != NULL
+ #endif
+ ))
return FileFdError("Truncating compressed files is not implemented (%s)", FileName.c_str());
#endif
if (ftruncate(iFd,To) != 0)
// seeking around, but not all users of FileFd use always Seek() and co
// so d->seekpos isn't always true and we can just use it as a hint if
// we have nothing else, but not always as an authority…
- if (d != NULL && (d->pipe == true
- #ifdef HAVE_BZ2
- || d->bz2 != NULL
- #endif
- ))
+ if (d != NULL && (d->pipe == true || d->InternalStream() == true))
return d->seekpos;
off_t Res;
// for compressor pipes st_size is undefined and at 'best' zero,
// so we 'read' the content and 'seek' back - see there
- if (d != NULL && (d->pipe == true
- #ifdef HAVE_BZ2
- || (d->bz2 && size > 0)
- #endif
- ))
+ if (d != NULL && (d->pipe == true || (d->InternalStream() == true && size > 0)))
{
unsigned long long const oldSeek = Tell();
char ignore[1000];
}
/*}}}*/
- gzFile FileFd::gzFd() { return (gzFile) d->gz; }
+ APT_DEPRECATED gzFile FileFd::gzFd() {
+ #ifdef HAVE_ZLIB
+ return d->gz;
+ #else
+ return NULL;
+ #endif
+ }
// Glob - wrapper around "glob()" /*{{{*/
return string(tmpdir);
}
+
+bool Rename(std::string From, std::string To)
+{
+ if (rename(From.c_str(),To.c_str()) != 0)
+ {
+ _error->Error(_("rename failed, %s (%s -> %s)."),strerror(errno),
+ From.c_str(),To.c_str());
+ return false;
+ }
+ return true;
+}
echo "${CDONE}DONE${CNORMAL}";
fi
}
-
+getaptconfig() {
+ if [ -f ./aptconfig.conf ]; then
+ echo "./aptconfig.conf"
+ elif [ -f ../aptconfig.conf ]; then
+ echo "../aptconfig.conf"
+ fi
+}
runapt() {
msgdebug "Executing: ${CCMD}$*${CDEBUG} "
local CMD="$1"
shift
- MALLOC_PERTURB_=21 MALLOC_CHECK_=2 APT_CONFIG="$(getaptconfig)" LD_LIBRARY_PATH=${BUILDDIRECTORY} ${BUILDDIRECTORY}/$CMD "$@"
+ case $CMD in
+ sh|aptitude|*/*) ;;
+ *) CMD="${BUILDDIRECTORY}/$CMD";;
+ esac
- if [ -f ./aptconfig.conf ]; then
- MALLOC_PERTURB_=21 MALLOC_CHECK_=2 APT_CONFIG=aptconfig.conf LD_LIBRARY_PATH=${LIBRARYPATH} $CMD "$@"
- elif [ -f ../aptconfig.conf ]; then
- MALLOC_PERTURB_=21 MALLOC_CHECK_=2 APT_CONFIG=../aptconfig.conf LD_LIBRARY_PATH=${LIBRARYPATH} $CMD "$@"
- else
- MALLOC_PERTURB_=21 MALLOC_CHECK_=2 LD_LIBRARY_PATH=${LIBRARYPATH} $CMD "$@"
- fi
++ MALLOC_PERTURB_=21 MALLOC_CHECK_=2 APT_CONFIG="$(getaptconfig)" LD_LIBRARY_PATH=${BUILDDIRECTORY} $CMD "$@"
}
aptconfig() { runapt apt-config "$@"; }
aptcache() { runapt apt-cache "$@"; }
aptkey() { runapt apt-key "$@"; }
aptmark() { runapt apt-mark "$@"; }
apt() { runapt apt "$@"; }
- apthelper() {
- APT_CONFIG="$(getaptconfig)" LD_LIBRARY_PATH=${APTHELPERBINDIR} ${APTHELPERBINDIR}/apt-helper "$@";
- }
- aptwebserver() {
- LD_LIBRARY_PATH=${APTWEBSERVERBINDIR} ${APTWEBSERVERBINDIR}/aptwebserver "$@";
- }
+ apthelper() { runapt "${APTHELPERBINDIR}/apt-helper" "$@"; }
+ aptwebserver() { runapt "${APTWEBSERVERBINDIR}/aptwebserver" "$@"; }
+ aptitude() { runapt aptitude "$@"; }
+
dpkg() {
command dpkg --root=${TMPWORKINGDIRECTORY}/rootdir --force-not-root --force-bad-path --log=${TMPWORKINGDIRECTORY}/rootdir/var/log/dpkg.log "$@"
}
- aptitude() {
- APT_CONFIG="$(getaptconfig)" LD_LIBRARY_PATH=${BUILDDIRECTORY} command aptitude "$@"
+ dpkgcheckbuilddeps() {
+ command dpkg-checkbuilddeps --admindir=${TMPWORKINGDIRECTORY}/rootdir/var/lib/dpkg "$@"
}
gdb() {
echo "gdb: run »$*«"
- APT_CONFIG="$(getaptconfig)" LD_LIBRARY_PATH=${BUILDDIRECTORY} command gdb ${BUILDDIRECTORY}/$1 --args "$@"
- }
- http() {
- LD_LIBRARY_PATH=${BUILDDIRECTORY} ${BUILDDIRECTORY}/methods/http
+ APT_CONFIG=aptconfig.conf LD_LIBRARY_PATH=${LIBRARYPATH} command gdb ${BUILDDIRECTORY}/$1 --args "$@"
}
gpg() {
# see apt-key for the whole trickery. Setup is done in setupenvironment
# allow overriding the default BUILDDIR location
BUILDDIRECTORY=${APT_INTEGRATION_TESTS_BUILD_DIR:-"${TESTDIRECTORY}/../../build/bin"}
+ LIBRARYPATH=${APT_INTEGRATION_TESTS_LIBRARY_PATH:-"${BUILDDIRECTORY}"}
METHODSDIR=${APT_INTEGRATION_TESTS_METHODS_DIR:-"${BUILDDIRECTORY}/methods"}
APTHELPERBINDIR=${APT_INTEGRATION_TESTS_LIBEXEC_DIR:-"${BUILDDIRECTORY}"}
APTWEBSERVERBINDIR=${APT_INTEGRATION_TESTS_WEBSERVER_BIN_DIR:-"${BUILDDIRECTORY}"}
mkdir rootdir aptarchive keys
cd rootdir
mkdir -p etc/apt/apt.conf.d etc/apt/sources.list.d etc/apt/trusted.gpg.d etc/apt/preferences.d
- mkdir -p var/cache var/lib var/log tmp
+ mkdir -p var/cache var/lib/apt var/log tmp
mkdir -p var/lib/dpkg/info var/lib/dpkg/updates var/lib/dpkg/triggers
touch var/lib/dpkg/available
mkdir -p usr/lib/apt
ln -s ${METHODSDIR} usr/lib/apt/methods
+ ln -s ${BUILDDIRECTORY}/../../debian/apt.conf.autoremove etc/apt/apt.conf.d/01autoremove
cd ..
local PACKAGESFILE=$(echo "$(basename $0)" | sed -e 's/^test-/Packages-/' -e 's/^skip-/Packages-/')
if [ -f "${TESTDIRECTORY}/${PACKAGESFILE}" ]; then
echo 'quiet::NoUpdate "true";' >> aptconfig.conf
echo "Acquire::https::CaInfo \"${TESTDIR}/apt.pem\";" > rootdir/etc/apt/apt.conf.d/99https
echo "Apt::Cmd::Disable-Script-Warning \"1\";" > rootdir/etc/apt/apt.conf.d/apt-binary
- export LC_ALL=C.UTF-8
- export PATH="${PATH}:/usr/local/sbin:/usr/sbin:/sbin"
configcompression '.' 'gz' #'bz2' 'lzma' 'xz'
# gpg needs a trustdb to function, but it can't be invalid (not even empty)
# newer gpg versions are fine without it, but play it safe for now
gpg --quiet --check-trustdb --secret-keyring $SECRETKEYRING --keyring $SECRETKEYRING >/dev/null 2>&1
+ # cleanup the environment a bit
+ export PATH="${PATH}:/usr/local/sbin:/usr/sbin:/sbin"
+ export LC_ALL=C.UTF-8
+ unset LANGUAGE APT_CONFIG
+ unset GREP_OPTIONS DEB_BUILD_PROFILES
+
msgdone "info"
}
echo "$(aptconfig dump | grep APT::Architecture | cut -d'"' -f 2 | sed '/^$/ d' | sort | uniq | tr '\n' ' ')"
}
+ getarchitecturesfromcommalist() {
+ echo "$1" | sed -e 's#,#\n#g' | sed -e "s/^native\$/$(getarchitecture 'native')/"
+ }
+
configarchitecture() {
{
echo "APT::Architecture \"$(getarchitecture $1)\";"
# fi
done
- for arch in $(echo "$ARCH" | sed -e 's#,#\n#g' | sed -e "s#^native\$#$(getarchitecture 'native')#"); do
+ for arch in $(getarchitecturesfromcommalist "$ARCH"); do
rm -rf ${BUILDDIR}/debian/tmp
mkdir -p ${BUILDDIR}/debian/tmp/DEBIAN ${BUILDDIR}/debian/tmp/usr/share/doc/${NAME} ${BUILDDIR}/debian/tmp/usr/bin
cp ${BUILDDIR}/debian/copyright ${BUILDDIR}/debian/changelog ${BUILDDIR}/FEATURES ${BUILDDIR}/debian/tmp/usr/share/doc/${NAME}
something went horribly wrong! They are autogenerated
und used only by testcases and surf no other propose…"}"
local ARCHS=""
- for arch in $(echo "$ARCH" | sed -e 's#,#\n#g' | sed -e "s#^native\$#$(getarchitecture 'native')#"); do
+ for arch in $(getarchitecturesfromcommalist "$ARCH"); do
if [ "$arch" = 'all' -o "$arch" = 'none' ]; then
ARCHS="$(getarchitectures)"
else
local FILE='rootdir/var/lib/dpkg/status'
local INFO='rootdir/var/lib/dpkg/info'
- for arch in $(echo "$ARCH" | sed -e 's#,#\n#g' | sed -e "s#^native\$#$(getarchitecture 'native')#"); do
+ for arch in $(getarchitecturesfromcommalist "$ARCH"); do
echo "Package: $NAME
Status: $STATUS
Priority: $PRIORITY
webserverconfig() {
msgtest "Set webserver config option '${1}' to" "$2"
- downloadfile "http://localhost:8080/_config/set/${1}/${2}" '/dev/null' >/dev/null
- local DOWNLOG='download-testfile.log'
- rm -f "$DOWNLOG"
- local STATUS="${TMPWORKINGDIRECTORY}/rootdir/tmp/webserverconfig.status"
- downloadfile "http://localhost:8080/_config/find/aptwebserver::last-status-code" "$STATUS" > "$DOWNLOG"
- if [ "$(cat "$STATUS")" = '200' ]; then
+ local DOWNLOG='rootdir/tmp/download-testfile.log'
+ local STATUS='rootdir/tmp/webserverconfig.status'
+ rm -f "$STATUS" "$DOWNLOG"
+ if downloadfile "http://localhost:8080/_config/set/${1}/${2}" "$STATUS" > "$DOWNLOG"; then
msgpass
else
- cat >&2 "$DOWNLOG"
- msgfail "Statuscode was $(cat "$STATUS")"
+ cat "$DOWNLOG" "$STATUS"
+ msgfail
fi
- rm "$STATUS"
+ testwebserverlaststatuscode '200'
}
rewritesourceslist() {
changetocdrom() {
mkdir -p rootdir/media/cdrom/.disk
local CD="$(readlink -f rootdir/media/cdrom)"
- echo "acquire::cdrom::mount \"${CD}\";" > rootdir/etc/apt/apt.conf.d/00cdrom
- echo 'acquire::cdrom::autodetect 0;' >> rootdir/etc/apt/apt.conf.d/00cdrom
+ echo "acquire::cdrom::mount \"${CD}\";
+ acquire::cdrom::${CD}/::mount \"mv ${CD}-unmounted ${CD}\";
+ acquire::cdrom::${CD}/::umount \"mv ${CD} ${CD}-unmounted\";
+ acquire::cdrom::autodetect 0;" > rootdir/etc/apt/apt.conf.d/00cdrom
echo -n "$1" > ${CD}/.disk/info
if [ ! -d aptarchive/dists ]; then
msgdie 'Flat file archive cdroms can not be created currently'
return 1
fi
- mv aptarchive/dists $CD
+ mv aptarchive/dists "$CD"
ln -s "$(readlink -f ./incoming)" $CD/pool
find rootdir/etc/apt/sources.list.d/ -name 'apt-test-*.list' -delete
+ # start with an unmounted disk
+ mv "${CD}" "${CD}-unmounted"
+ # we don't want the disk to be modifiable
+ addtrap 'prefix' "chmod -f -R +w $PWD/rootdir/media/cdrom/dists/ $PWD/rootdir/media/cdrom-unmounted/dists/ || true;"
+ chmod -R -w rootdir/media/cdrom-unmounted/dists
}
downloadfile() {
- PROTO="$(echo "$1" | cut -d':' -f 1)"
- apthelper -o Acquire::https::CaInfo=${TESTDIR}/apt.pem \
- -o Debug::Acquire::${PROTO}=1 \
- download-file "$1" "$2" 2>&1
+ local PROTO="$(echo "$1" | cut -d':' -f 1 )"
+ apthelper -o Debug::Acquire::${PROTO}=1 \
+ download-file "$1" "$2" 2>&1 || true
# only if the file exists the download was successful
if [ -e "$2" ]; then
return 0
checkdiff() {
local DIFFTEXT="$(command diff -u "$@" | sed -e '/^---/ d' -e '/^+++/ d' -e '/^@@/ d')"
if [ -n "$DIFFTEXT" ]; then
- echo
- echo "$DIFFTEXT"
+ echo >&2
+ echo >&2 "$DIFFTEXT"
return 1
else
return 0
shift 2
msgtest "Test for equality OR of" "$*"
$* >$COMPAREAGAINST 2>&1 || true
- (checkdiff $COMPAREFILE1 $COMPAREAGAINST 1> /dev/null ||
- checkdiff $COMPAREFILE2 $COMPAREAGAINST 1> /dev/null) && msgpass ||
- ( echo "\n${CINFO}Diff against OR 1${CNORMAL}" "$(checkdiff $COMPAREFILE1 $COMPAREAGAINST)" \
- "\n${CINFO}Diff against OR 2${CNORMAL}" "$(checkdiff $COMPAREFILE2 $COMPAREAGAINST)" &&
- msgfail )
+ if checkdiff $COMPAREFILE1 $COMPAREAGAINST >/dev/null 2>&1 || \
+ checkdiff $COMPAREFILE2 $COMPAREAGAINST >/dev/null 2>&1
+ then
+ msgpass
+ else
+ echo -n "\n${CINFO}Diff against OR 1${CNORMAL}"
+ checkdiff $COMPAREFILE1 $COMPAREAGAINST || true
+ echo -n "${CINFO}Diff against OR 2${CNORMAL}"
+ checkdiff $COMPAREFILE2 $COMPAREAGAINST || true
+ msgfail
+ fi
}
testshowvirtual() {
msgtest "Test for non-existent packages" "apt-cache show $*"
local SHOWPKG="$(aptcache show "$@" 2>&1 | grep '^Package: ')"
if [ -n "$SHOWPKG" ]; then
- echo
- echo "$SHOWPKG"
+ echo >&2
+ echo >&2 "$SHOWPKG"
msgfail
- return 1
+ else
+ msgpass
fi
- msgpass
}
testdpkginstalled() {
msgtest "Test for correctly installed package(s) with" "dpkg -l $*"
local PKGS="$(dpkg -l "$@" 2>/dev/null | grep '^i' | wc -l)"
if [ "$PKGS" != $# ]; then
- echo $PKGS
- dpkg -l "$@" | grep '^[a-z]'
+ echo >&2 $PKGS
+ dpkg -l "$@" | grep '^[a-z]' >&2
msgfail
- return 1
+ else
+ msgpass
fi
- msgpass
}
testdpkgnotinstalled() {
local PKGS="$(dpkg -l "$@" 2> /dev/null | grep '^i' | wc -l)"
if [ "$PKGS" != 0 ]; then
echo
- dpkg -l "$@" | grep '^[a-z]'
+ dpkg -l "$@" | grep '^[a-z]' >&2
msgfail
- return 1
+ else
+ msgpass
fi
- msgpass
}
testmarkedauto() {
if $@ >${OUTPUT} 2>&1; then
msgpass
else
- echo
- cat $OUTPUT
+ echo >&2
+ cat >&2 $OUTPUT
msgfail
fi
}
fi
local OUTPUT="${TMPWORKINGDIRECTORY}/rootdir/tmp/testfailure.output"
if $@ >${OUTPUT} 2>&1; then
- echo
- cat $OUTPUT
+ echo >&2
+ cat >&2 $OUTPUT
msgfail
else
msgpass
fi
}
+ testwebserverlaststatuscode() {
+ local DOWNLOG='rootdir/tmp/webserverstatus-testfile.log'
+ local STATUS='rootdir/tmp/webserverstatus-statusfile.log'
+ rm -f "$DOWNLOG" "$STATUS"
+ msgtest 'Test last status code from the webserver was' "$1"
+ downloadfile "http://localhost:8080/_config/find/aptwebserver::last-status-code" "$STATUS" > "$DOWNLOG"
+ if [ "$(cat "$STATUS")" = "$1" ]; then
+ msgpass
+ else
+ echo >&2
+ if [ -n "$2" ]; then
+ shift
+ echo >&2 '#### Additionally provided output files contain:'
+ cat >&2 "$@"
+ fi
+ echo >&2 '#### Download log of the status code:'
+ cat >&2 "$DOWNLOG"
+ msgfail "Status was $(cat "$STATUS")"
+ fi
+ }
+
pause() {
echo "STOPPED execution. Press enter to continue"
local IGNORE