From 2f958de6e883ba7b0c9895750d4dde35047f1e82 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 25 Jan 2014 01:00:23 +0100 Subject: use svg in doxygen and ensure dot is around for it --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'debian/control') diff --git a/debian/control b/debian/control index c70d0e9ea..f3303e891 100644 --- a/debian/control +++ b/debian/control @@ -9,7 +9,7 @@ Build-Depends: dpkg-dev (>= 1.15.8), debhelper (>= 8.1.3~), libdb-dev, gettext (>= 0.12), libcurl4-gnutls-dev (>= 7.19.4~), zlib1g-dev, libbz2-dev, xsltproc, docbook-xsl, docbook-xml, po4a (>= 0.34-2), autotools-dev, autoconf, automake -Build-Depends-Indep: doxygen, debiandoc-sgml +Build-Depends-Indep: doxygen, debiandoc-sgml, graphviz Build-Conflicts: autoconf2.13, automake1.4 Vcs-Git: git://anonscm.debian.org/apt/apt.git Vcs-Browser: http://anonscm.debian.org/gitweb/?p=apt/apt.git -- cgit v1.2.3-70-g09d2 From a5c657563746d2576b662f1711723312fcb1c186 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 6 Feb 2014 22:01:45 +0100 Subject: bump Standards-Version to 3.9.5 (no changes needed) --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'debian/control') diff --git a/debian/control b/debian/control index f3303e891..0c1341bb9 100644 --- a/debian/control +++ b/debian/control @@ -4,7 +4,7 @@ Priority: important Maintainer: APT Development Team Uploaders: Michael Vogt , Christian Perrier , Julian Andres Klode -Standards-Version: 3.9.4 +Standards-Version: 3.9.5 Build-Depends: dpkg-dev (>= 1.15.8), debhelper (>= 8.1.3~), libdb-dev, gettext (>= 0.12), libcurl4-gnutls-dev (>= 7.19.4~), zlib1g-dev, libbz2-dev, xsltproc, docbook-xsl, docbook-xml, -- cgit v1.2.3-70-g09d2 From 93bd01f7e0606b3f778401fb772fb3cb56cb3697 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 12 Mar 2014 20:46:36 +0100 Subject: Promote xz-utils from apt Suggests to libapt-pkg Depends libapt-pkg depends on the other compressors, and now that xz is the default in many cases, it should depend on that one as well. --- debian/control | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'debian/control') diff --git a/debian/control b/debian/control index 0c1341bb9..2d58d0711 100644 --- a/debian/control +++ b/debian/control @@ -21,7 +21,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${apt:keyring}, gnupg Replaces: manpages-pl (<< 20060617-3~), manpages-it (<< 2.80-4~) Breaks: manpages-pl (<< 20060617-3~), manpages-it (<< 2.80-4~) Conflicts: python-apt (<< 0.7.93.2~) -Suggests: aptitude | synaptic | wajig, dpkg-dev, apt-doc, xz-utils, python-apt +Suggests: aptitude | synaptic | wajig, dpkg-dev, apt-doc, python-apt Description: commandline package manager This package provides commandline tools for searching and managing as well as querying information about packages @@ -41,7 +41,7 @@ Package: libapt-pkg4.12 Architecture: any Multi-Arch: same Pre-Depends: ${misc:Pre-Depends} -Depends: ${shlibs:Depends}, ${misc:Depends} +Depends: ${shlibs:Depends}, ${misc:Depends}, xz-utils Breaks: apt (<< 0.9.4~), libapt-inst1.5 (<< 0.9.9~) Section: libs Description: package management runtime library -- cgit v1.2.3-70-g09d2 From ce7f128c020e1347f91c6074238fc5da58c5df71 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 25 Feb 2014 14:26:18 +0100 Subject: support DEB_BUILD_PROFILES and -P for build profiles Inspired by the rest of the patch in 661537, but abstract the parsing of various ways of setting the build profiles more so it can potentially be reused and all apt parts have the same behaviour. Especially config options, cmdline options and environment will not be combined as proposed as this isn't APTs usual behaviour and dpkg doesn't do it either, so one overrides the other as it normally does. --- apt-pkg/aptconfiguration.cc | 26 +++- apt-pkg/aptconfiguration.h | 5 + apt-pkg/deb/deblistparser.cc | 2 +- apt-private/private-cmndline.cc | 2 + cmdline/apt-config.cc | 5 + cmdline/apt-get.cc | 6 + debian/control | 2 +- doc/apt-get.8.xml | 13 +- doc/apt.conf.5.xml | 9 ++ test/integration/framework | 6 + .../test-bug-661537-build-profiles-support | 147 +++++++++++++++++++++ 11 files changed, 219 insertions(+), 4 deletions(-) create mode 100755 test/integration/test-bug-661537-build-profiles-support (limited to 'debian/control') diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc index f5c758e14..3948854c6 100644 --- a/apt-pkg/aptconfiguration.cc +++ b/apt-pkg/aptconfiguration.cc @@ -426,7 +426,7 @@ void Configuration::setDefaultConfigurationForCompressors() { } } /*}}}*/ -// getCompressors - Return Vector of usbale compressors /*{{{*/ +// getCompressors - Return Vector of usealbe compressors /*{{{*/ // --------------------------------------------------------------------- /* return a vector of compressors used by apt-ftparchive in the multicompress functionality or to detect data.tar files */ @@ -508,4 +508,28 @@ Configuration::Compressor::Compressor(char const *name, char const *extension, UncompressArgs.push_back(uncompressArg); } /*}}}*/ +// getBuildProfiles - return a vector of enabled build profiles /*{{{*/ +std::vector const Configuration::getBuildProfiles() { + // order is: override value (~= commandline), environment variable, list (~= config file) + std::string profiles_env = getenv("DEB_BUILD_PROFILES") == 0 ? "" : getenv("DEB_BUILD_PROFILES"); + if (profiles_env.empty() == false) { + profiles_env = SubstVar(profiles_env, " ", ","); + std::string const bp = _config->Find("APT::Build-Profiles"); + _config->Clear("APT::Build-Profiles"); + if (bp.empty() == false) + _config->Set("APT::Build-Profiles", bp); + } + return _config->FindVector("APT::Build-Profiles", profiles_env); +} +std::string const Configuration::getBuildProfilesString() { + std::vector profiles = getBuildProfiles(); + if (profiles.empty() == true) + return ""; + std::vector::const_iterator p = profiles.begin(); + std::string list = *p; + for (; p != profiles.end(); ++p) + list.append(",").append(*p); + return list; +} + /*}}}*/ } diff --git a/apt-pkg/aptconfiguration.h b/apt-pkg/aptconfiguration.h index bf7deae85..026493c6d 100644 --- a/apt-pkg/aptconfiguration.h +++ b/apt-pkg/aptconfiguration.h @@ -117,6 +117,11 @@ public: /*{{{*/ /** \brief Return a vector of extensions supported for data.tar's */ std::vector static const getCompressorExtensions(); + + /** \return Return a vector of enabled build profile specifications */ + std::vector static const getBuildProfiles(); + /** \return Return a comma-separated list of enabled build profile specifications */ + std::string static const getBuildProfilesString(); /*}}}*/ private: /*{{{*/ void static setDefaultConfigurationForCompressors(); diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index a4795f15d..89f3514c9 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -625,7 +625,7 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop, if (unlikely(I == Stop)) return 0; - std::vector const profiles = _config->FindVector("APT::Build-Profiles"); + std::vector const profiles = APT::Configuration::getBuildProfiles(); const char *End = I; bool Found = false; diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc index ef7d65f3c..b99443210 100644 --- a/apt-private/private-cmndline.cc +++ b/apt-private/private-cmndline.cc @@ -141,6 +141,7 @@ bool addArgumentsAPTGet(std::vector &Args, char const * const { addArg('b', "compile", "APT::Get::Compile", 0); addArg('b', "build", "APT::Get::Compile", 0); + addArg('P', "build-profiles", "APT::Build-Profiles", CommandLine::HasArg); addArg(0, "diff-only", "APT::Get::Diff-Only", 0); addArg(0, "debian-only", "APT::Get::Diff-Only", 0); addArg(0, "tar-only", "APT::Get::Tar-Only", 0); @@ -149,6 +150,7 @@ bool addArgumentsAPTGet(std::vector &Args, char const * const else if (CmdMatches("build-dep")) { addArg('a', "host-architecture", "APT::Get::Host-Architecture", CommandLine::HasArg); + addArg('P', "build-profiles", "APT::Build-Profiles", CommandLine::HasArg); addArg(0, "purge", "APT::Get::Purge", 0); addArg(0, "solver", "APT::Solver", CommandLine::HasArg); // this has no effect *but* sbuild is using it (see LP: #1255806) diff --git a/cmdline/apt-config.cc b/cmdline/apt-config.cc index 30c2a22d5..9f20b3c1b 100644 --- a/cmdline/apt-config.cc +++ b/cmdline/apt-config.cc @@ -155,6 +155,11 @@ int main(int argc,const char *argv[]) /*{{{*/ _config->Set(comp + "UncompressArg::", *a); } + std::vector const profiles = APT::Configuration::getBuildProfiles(); + _config->Clear("APT::Build-Profiles"); + for (std::vector::const_iterator p = profiles.begin(); p != profiles.end(); ++p) + _config->Set("APT::Build-Profiles::", *p); + // Match the operation CmdL.DispatchArg(Cmds); diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 12e385b69..f8de80a91 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -970,6 +970,12 @@ bool DoSource(CommandLine &CmdL) string buildopts = _config->Find("APT::Get::Host-Architecture"); if (buildopts.empty() == false) buildopts = "-a" + buildopts + " "; + + // get all active build profiles + std::string const profiles = APT::Configuration::getBuildProfilesString(); + if (profiles.empty() == false) + buildopts.append(" -P").append(profiles).append(" "); + buildopts.append(_config->Find("DPkg::Build-Options","-b -uc")); // Call dpkg-buildpackage diff --git a/debian/control b/debian/control index 2d58d0711..5ce68414e 100644 --- a/debian/control +++ b/debian/control @@ -21,7 +21,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${apt:keyring}, gnupg Replaces: manpages-pl (<< 20060617-3~), manpages-it (<< 2.80-4~) Breaks: manpages-pl (<< 20060617-3~), manpages-it (<< 2.80-4~) Conflicts: python-apt (<< 0.7.93.2~) -Suggests: aptitude | synaptic | wajig, dpkg-dev, apt-doc, python-apt +Suggests: aptitude | synaptic | wajig, dpkg-dev (>= 1.17.2), apt-doc, python-apt Description: commandline package manager This package provides commandline tools for searching and managing as well as querying information about packages diff --git a/doc/apt-get.8.xml b/doc/apt-get.8.xml index 595ea875d..1ed08904e 100644 --- a/doc/apt-get.8.xml +++ b/doc/apt-get.8.xml @@ -371,7 +371,18 @@ by apt-get source --compile and how cross-builddependencies are satisfied. By default is it not set which means that the host architecture is the same as the build architecture (which is defined by APT::Architecture). - Configuration Item: APT::Get::Host-Architecture + Configuration Item: APT::Get::Host-Architecture. + + + + + + This option controls the activated build profiles for which + a source package is built by apt-get source --compile and + how build dependencies are satisfied. By default no build profile is active. + More than one build profile can be activated at a time by concatenating them + with a comma. + Configuration Item: APT::Build-Profiles. diff --git a/doc/apt.conf.5.xml b/doc/apt.conf.5.xml index bfc43ba29..78f6a27a2 100644 --- a/doc/apt.conf.5.xml +++ b/doc/apt.conf.5.xml @@ -177,6 +177,15 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";}; + + + List of all build profiles enabled for build-dependency resolution, + without the "profile." namespace prefix. + By default this list is empty. The DEB_BUILD_PROFILES + as used by &dpkg-buildpackage; overrides the list notation. + + + Default release to install packages from if more than one version is available. Contains release name, codename or release version. Examples: 'stable', 'testing', diff --git a/test/integration/framework b/test/integration/framework index 911a4d742..9c4ac87d3 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -120,6 +120,9 @@ aptwebserver() { dpkg() { command dpkg --root=${TMPWORKINGDIRECTORY}/rootdir --force-not-root --force-bad-path --log=${TMPWORKINGDIRECTORY}/rootdir/var/log/dpkg.log "$@" } +dpkgcheckbuilddeps() { + command dpkg-checkbuilddeps --admindir=${TMPWORKINGDIRECTORY}/rootdir/var/lib/dpkg "$@" +} aptitude() { if [ -f ./aptconfig.conf ]; then APT_CONFIG=aptconfig.conf LD_LIBRARY_PATH=${BUILDDIRECTORY} command aptitude "$@" @@ -240,6 +243,9 @@ setupenvironment() { # 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 + unset GREP_OPTIONS DEB_BUILD_PROFILES + msgdone "info" } diff --git a/test/integration/test-bug-661537-build-profiles-support b/test/integration/test-bug-661537-build-profiles-support new file mode 100755 index 000000000..ae1403f71 --- /dev/null +++ b/test/integration/test-bug-661537-build-profiles-support @@ -0,0 +1,147 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'amd64' 'i386' 'armel' + +insertinstalledpackage 'build-essential' 'all' '0' 'Multi-Arch: foreign' + +insertpackage 'unstable' 'foo' 'all' '1.0' +insertpackage 'unstable' 'bar' 'all' '1.0' + +insertsource 'unstable' 'buildprofiles' 'any' '1' 'Build-Depends: foo (>= 1.0) [i386 arm] , bar' + +# table from https://wiki.debian.org/BuildProfileSpec +insertsource 'unstable' 'spec-1' 'any' '1' 'Build-Depends: foo ' +insertsource 'unstable' 'spec-2' 'any' '1' 'Build-Depends: foo ' +insertsource 'unstable' 'spec-3' 'any' '1' 'Build-Depends: foo ' +insertsource 'unstable' 'spec-4' 'any' '1' 'Build-Depends: foo ' +insertsource 'unstable' 'spec-5' 'any' '1' 'Build-Depends: foo ' +insertsource 'unstable' 'spec-6' 'any' '1' 'Build-Depends: foo ' +# multiple stanzas not supported: error out +insertsource 'unstable' 'spec-7' 'any' '1' 'Build-Depends: foo ' +insertsource 'unstable' 'spec-8' 'any' '1' 'Build-Depends: foo ' + +setupaptarchive + +testequal 'Reading package lists... +Building dependency tree... +The following NEW packages will be installed: + bar +0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. +Inst bar (1.0 unstable [all]) +Conf bar (1.0 unstable [all])' aptget build-dep buildprofiles -s + +testequal 'Reading package lists... +Building dependency tree... +The following NEW packages will be installed: + bar foo +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst bar (1.0 unstable [all]) +Inst foo (1.0 unstable [all]) +Conf bar (1.0 unstable [all]) +Conf foo (1.0 unstable [all])' aptget build-dep buildprofiles -s -o APT::Architecture=i386 + +testequal 'Reading package lists... +Building dependency tree... +The following NEW packages will be installed: + bar +0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. +Inst bar (1.0 unstable [all]) +Conf bar (1.0 unstable [all])' aptget build-dep buildprofiles -s -o APT::Architecture=armel + +testequal 'Reading package lists... +Building dependency tree... +The following NEW packages will be installed: + bar +0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. +Inst bar (1.0 unstable [all]) +Conf bar (1.0 unstable [all])' aptget build-dep buildprofiles -s -o APT::Architecture=i386 -P stage1 + +KEEP='Reading package lists... +Building dependency tree... +The following NEW packages will be installed: + foo +0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. +Inst foo (1.0 unstable [all]) +Conf foo (1.0 unstable [all])' +DROP='Reading package lists... +Building dependency tree... +0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.' + +msgtest 'Check if version of installed dpkg is high enough for' 'build profiles support' +if dpkg --compare-versions "$(command dpkg-query --showformat='${Version}' --show dpkg)" 'ge' '1.17.2'; then + msgpass + testwithdpkg() { + msgtest "Test with" "dpkg-checkbuilddeps -d '$1' -P '$2'" + local OUTPUT="${TMPWORKINGDIRECTORY}/rootdir/tmp/testwithdpkg.output" + if dpkgcheckbuilddeps -d "$1" -P "$2" /dev/null >$OUTPUT 2>&1; then + if [ "$3" = "$DROP" ]; then + msgpass + else + cat $OUTPUT + msgfail + fi + else + if [ "$3" = "$KEEP" ]; then + msgpass + else + cat $OUTPUT + msgfail + fi + fi + } +else + msgskip + testwithdpkg() { + msgtest "Test with" "dpkg-checkbuilddeps -d '$1' -P '$2'" + msgskip + } +fi + +testprofile() { + if [ -n "$3" ]; then + testequal "$4" aptget build-dep "$1" -s -P "$3" + export DEB_BUILD_PROFILES="$(echo "$3" | tr ',' ' ')" + testequal "$4" aptget build-dep "$1" -s -o with::environment=1 + unset DEB_BUILD_PROFILES + else + testequal "$4" aptget build-dep "$1" -s + fi + testwithdpkg "$2" "$3" "$4" +} + +testprofile 'spec-1' 'foo ' '' "$KEEP" +testprofile 'spec-1' 'foo ' 'stage1' "$DROP" +testprofile 'spec-1' 'foo ' 'notest' "$KEEP" +testprofile 'spec-1' 'foo ' 'stage1,notest' "$DROP" + +testprofile 'spec-2' 'foo ' '' "$DROP" +testprofile 'spec-2' 'foo ' 'stage1' "$KEEP" +testprofile 'spec-2' 'foo ' 'notest' "$DROP" +testprofile 'spec-2' 'foo ' 'stage1,notest' "$KEEP" + +testprofile 'spec-3' 'foo ' '' "$KEEP" +testprofile 'spec-3' 'foo ' 'stage1' "$DROP" +testprofile 'spec-3' 'foo ' 'notest' "$DROP" +testprofile 'spec-3' 'foo ' 'stage1,notest' "$DROP" + +testprofile 'spec-4' 'foo ' '' "$DROP" +testprofile 'spec-4' 'foo ' 'stage1' "$KEEP" +testprofile 'spec-4' 'foo ' 'notest' "$KEEP" +testprofile 'spec-4' 'foo ' 'stage1,notest' "$KEEP" + +testprofile 'spec-5' 'foo ' '' "$KEEP" +testprofile 'spec-5' 'foo ' 'stage1' "$DROP" +testprofile 'spec-5' 'foo ' 'notest' "$KEEP" +testprofile 'spec-5' 'foo ' 'stage1,notest' "$DROP" + +testprofile 'spec-6' 'foo ' '' "$KEEP" +testprofile 'spec-6' 'foo ' 'stage1' "$KEEP" +testprofile 'spec-6' 'foo ' 'notest' "$DROP" +testprofile 'spec-6' 'foo ' 'stage1,notest' "$KEEP" + +testfailure aptget build-dep spec-7 -s +testfailure aptget build-dep spec-8 -s -- cgit v1.2.3-70-g09d2 From 7f350a377e0c65a656b9b5437e27d037fd742901 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 12 Mar 2014 14:39:18 +0100 Subject: use liblzma-dev to provide xz/lzma support We have xz/lzma support for a while, but only via an external binary provided by xz-utils. Now that the Debian archive provides xz by default and dpkg pre-depends on the library provided by liblzma-dev we can switch now to use this library as well to avoid requiring an external binary. For now the binary is in a prio:required package, but this might change in the future. API wise it is quiet similar to bz2 code expect that it doesn't provide file I/O methods, so we piece this together on our own. --- apt-pkg/aptconfiguration.cc | 8 ++ apt-pkg/contrib/fileutl.cc | 280 ++++++++++++++++++++++++++++++++++++++------ apt-pkg/makefile | 3 + buildlib/config.h.in | 3 + buildlib/environment.mak.in | 1 + configure.ac | 7 ++ debian/control | 8 +- 7 files changed, 271 insertions(+), 39 deletions(-) (limited to 'debian/control') diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc index 941a9c334..6ba047560 100644 --- a/apt-pkg/aptconfiguration.cc +++ b/apt-pkg/aptconfiguration.cc @@ -462,8 +462,16 @@ const Configuration::getCompressors(bool const Cached) { #endif if (_config->Exists("Dir::Bin::xz") == false || FileExists(_config->FindFile("Dir::Bin::xz")) == true) compressors.push_back(Compressor("xz",".xz","xz","-6","-d",4)); +#ifdef HAVE_LZMA + else + compressors.push_back(Compressor("xz",".xz","false", NULL, NULL, 4)); +#endif if (_config->Exists("Dir::Bin::lzma") == false || FileExists(_config->FindFile("Dir::Bin::lzma")) == true) compressors.push_back(Compressor("lzma",".lzma","lzma","-9","-d",5)); +#ifdef HAVE_LZMA + else + compressors.push_back(Compressor("lzma",".lzma","false", NULL, NULL, 5)); +#endif std::vector const comp = _config->FindVector("APT::Compressor"); for (std::vector::const_iterator c = comp.begin(); diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 057cb6a94..22730ec04 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -58,6 +58,9 @@ #ifdef HAVE_BZ2 #include #endif +#ifdef HAVE_LZMA + #include +#endif #ifdef WORDS_BIGENDIAN #include @@ -72,13 +75,47 @@ class FileFdPrivate { public: #ifdef HAVE_ZLIB gzFile gz; -#else - void* gz; #endif #ifdef HAVE_BZ2 BZFILE* bz2; -#else - void* 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; @@ -86,7 +123,16 @@ class FileFdPrivate { APT::Configuration::Compressor compressor; unsigned int openmode; unsigned long long seekpos; - FileFdPrivate() : gz(NULL), bz2(NULL), + 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 CloseDown(std::string const &FileName) @@ -106,6 +152,12 @@ class FileFdPrivate { BZ2_bzclose(bz2); bz2 = NULL; } +#endif +#ifdef HAVE_LZMA + if (lzma != NULL) { + delete lzma; + lzma = NULL; + } #endif if (compressor_pid > 0) ExecWait(compressor_pid, "FileFdCompressor", true); @@ -1089,12 +1141,14 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C if (compressor.Name == "." || compressor.Binary.empty() == true) return true; -#if defined HAVE_ZLIB || defined HAVE_BZ2 +#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,CLOSE,STRUCT) \ - if (compressor.Name == NAME) \ + else if (compressor.Name == NAME) \ { \ compress_open = (void*(*)(int, const char *)) OPEN; \ if (d != NULL && STRUCT != NULL) { CLOSE(STRUCT); STRUCT = NULL; } \ @@ -1105,6 +1159,17 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C #ifdef HAVE_BZ2 APT_COMPRESS_INIT("bzip2", BZ2_bzdopen, BZ2_bzclose, d->bz2) #endif +#ifdef HAVE_LZMA + else if (compressor.Name == "xz" || compressor.Name == "lzma") + { + compress_open = (void*(*)(int, const char*)) fdopen; + if (d != NULL && d->lzma != NULL) + { + delete d->lzma; + d->lzma = NULL; + } + } +#endif #undef APT_COMPRESS_INIT #endif @@ -1113,7 +1178,7 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C d = new FileFdPrivate(); d->openmode = Mode; d->compressor = compressor; -#if defined HAVE_ZLIB || defined HAVE_BZ2 +#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 @@ -1125,7 +1190,7 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C #endif } -#if defined HAVE_ZLIB || defined HAVE_BZ2 +#if defined HAVE_ZLIB || defined HAVE_BZ2 || defined HAVE_LZMA if (compress_open != NULL) { void* compress_struct = NULL; @@ -1138,13 +1203,60 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C if (compress_struct == NULL) return false; + if (false) + /* dummy so that the rest can be 'else if's */; #ifdef HAVE_ZLIB - if (compressor.Name == "gzip") + else if (compressor.Name == "gzip") d->gz = (gzFile) compress_struct; #endif #ifdef HAVE_BZ2 - if (compressor.Name == "bzip2") + else if (compressor.Name == "bzip2") d->bz2 = (BZFILE*) compress_struct; +#endif +#ifdef HAVE_LZMA + else if (compressor.Name == "xz" || compressor.Name == "lzma") + { + 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; + } + } #endif Flags |= Compressed; return true; @@ -1202,7 +1314,7 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C } else { - if (FileName.empty() == true) + if (d->compressed_fd != -1) dup2(d->compressed_fd,STDIN_FILENO); dup2(Pipe[1],STDOUT_FILENO); } @@ -1271,24 +1383,55 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual) *((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); @@ -1297,13 +1440,17 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual) } #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")); } @@ -1368,23 +1515,45 @@ bool FileFd::Write(const void *From,unsigned long long Size) 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 - Res = write(iFd,From,Size); +#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 + 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); @@ -1393,13 +1562,17 @@ bool FileFd::Write(const void *From,unsigned long long Size) } #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")); } @@ -1447,6 +1620,9 @@ bool FileFd::Seek(unsigned long long To) if (d != NULL && (d->pipe == true #ifdef HAVE_BZ2 || d->bz2 != NULL +#endif +#ifdef HAVE_LZMA + || d->lzma != NULL #endif )) { @@ -1459,12 +1635,21 @@ bool FileFd::Seek(unsigned long long To) if ((d->openmode & ReadOnly) != ReadOnly) return FileFdError("Reopen is only implemented for read-only files!"); + if (false) + /* dummy so that the rest can be 'else if's */; #ifdef HAVE_BZ2 - if (d->bz2 != NULL) - { - BZ2_bzclose(d->bz2); - d->bz2 = NULL; - } + else if (d->bz2 != NULL) + { + BZ2_bzclose(d->bz2); + d->bz2 = NULL; + } +#endif +#ifdef HAVE_LZMA + else if (d->lzma != NULL) + { + delete d->lzma; + d->lzma = NULL; + } #endif if (iFd != -1) close(iFd); @@ -1514,6 +1699,9 @@ bool FileFd::Skip(unsigned long long Over) if (d != NULL && (d->pipe == true #ifdef HAVE_BZ2 || d->bz2 != NULL +#endif +#ifdef HAVE_LZMA + || d->lzma != NULL #endif )) { @@ -1552,8 +1740,18 @@ bool FileFd::Truncate(unsigned long long To) // 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 && ( +#ifdef HAVE_ZLIB + d->gz != NULL || +#endif +#ifdef HAVE_BZ2 + d->bz2 != NULL || +#endif +#ifdef HAVE_LZMA + d->lzma != NULL || +#endif + false)) return FileFdError("Truncating compressed files is not implemented (%s)", FileName.c_str()); #endif if (ftruncate(iFd,To) != 0) @@ -1574,6 +1772,9 @@ unsigned long long FileFd::Tell() if (d != NULL && (d->pipe == true #ifdef HAVE_BZ2 || d->bz2 != NULL +#endif +#ifdef HAVE_LZMA + || d->lzma != NULL #endif )) return d->seekpos; @@ -1653,6 +1854,9 @@ unsigned long long FileFd::Size() if (d != NULL && (d->pipe == true #ifdef HAVE_BZ2 || (d->bz2 && size > 0) +#endif +#ifdef HAVE_LZMA + || (d->lzma && size > 0) #endif )) { @@ -1797,7 +2001,13 @@ bool FileFd::FileFdError(const char *Description,...) { } /*}}}*/ -gzFile FileFd::gzFd() { return d->gz; } +APT_DEPRECATED gzFile FileFd::gzFd() { +#ifdef HAVE_ZLIB + return d->gz; +#else + return NULL; +#endif +} // Glob - wrapper around "glob()" /*{{{*/ diff --git a/apt-pkg/makefile b/apt-pkg/makefile index a90131f80..1d456873b 100644 --- a/apt-pkg/makefile +++ b/apt-pkg/makefile @@ -21,6 +21,9 @@ endif ifeq ($(HAVE_BZ2),yes) SLIBS+= -lbz2 endif +ifeq ($(HAVE_LZMA),yes) +SLIBS+= -llzma +endif APT_DOMAIN:=libapt-pkg$(LIBAPTPKG_MAJOR) # Source code for the contributed non-core things diff --git a/buildlib/config.h.in b/buildlib/config.h.in index 6779e07bc..6b72fb393 100644 --- a/buildlib/config.h.in +++ b/buildlib/config.h.in @@ -11,6 +11,9 @@ /* Define if we have the bz2 library for bzip2 */ #undef HAVE_BZ2 +/* Define if we have the lzma library for lzma/xz */ +#undef HAVE_LZMA + /* These two are used by the statvfs shim for glibc2.0 and bsd */ /* Define if we have sys/vfs.h */ #undef HAVE_VFS_H diff --git a/buildlib/environment.mak.in b/buildlib/environment.mak.in index 9cc449573..c1bf29672 100644 --- a/buildlib/environment.mak.in +++ b/buildlib/environment.mak.in @@ -61,6 +61,7 @@ INTLLIBS = @INTLLIBS@ HAVE_STATVFS = @HAVE_STATVFS@ HAVE_ZLIB = @HAVE_ZLIB@ HAVE_BZ2 = @HAVE_BZ2@ +HAVE_LZMA = @HAVE_LZMA@ NEED_SOCKLEN_T_DEFINE = @NEED_SOCKLEN_T_DEFINE@ # Shared library things diff --git a/configure.ac b/configure.ac index 40556ee54..4f782f873 100644 --- a/configure.ac +++ b/configure.ac @@ -107,6 +107,13 @@ if test "x$HAVE_BZ2" = "xyes"; then AC_DEFINE(HAVE_BZ2) fi +HAVE_LZMA=no +AC_CHECK_LIB(lzma, lzma_easy_encoder,[AC_CHECK_HEADER(lzma.h, [HAVE_LZMA=yes], [])], []) +AC_SUBST(HAVE_LZMA) +if test "x$HAVE_LZMA" = "xyes"; then + AC_DEFINE(HAVE_LZMA) +fi + dnl Converts the ARCH to be something singular for this general CPU family dnl This is often the dpkg architecture string. dnl First check against the full canonical canoncial-system-type in $target diff --git a/debian/control b/debian/control index 5ce68414e..cb6f9b995 100644 --- a/debian/control +++ b/debian/control @@ -7,8 +7,9 @@ Uploaders: Michael Vogt , Christian Perrier Standards-Version: 3.9.5 Build-Depends: dpkg-dev (>= 1.15.8), debhelper (>= 8.1.3~), libdb-dev, gettext (>= 0.12), libcurl4-gnutls-dev (>= 7.19.4~), - zlib1g-dev, libbz2-dev, xsltproc, docbook-xsl, docbook-xml, - po4a (>= 0.34-2), autotools-dev, autoconf, automake + zlib1g-dev, libbz2-dev, liblzma-dev, + xsltproc, docbook-xsl, docbook-xml, po4a (>= 0.34-2), + autotools-dev, autoconf, automake Build-Depends-Indep: doxygen, debiandoc-sgml, graphviz Build-Conflicts: autoconf2.13, automake1.4 Vcs-Git: git://anonscm.debian.org/apt/apt.git @@ -41,7 +42,7 @@ Package: libapt-pkg4.12 Architecture: any Multi-Arch: same Pre-Depends: ${misc:Pre-Depends} -Depends: ${shlibs:Depends}, ${misc:Depends}, xz-utils +Depends: ${shlibs:Depends}, ${misc:Depends} Breaks: apt (<< 0.9.4~), libapt-inst1.5 (<< 0.9.9~) Section: libs Description: package management runtime library @@ -107,7 +108,6 @@ Description: documentation for APT development Package: apt-utils Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} -Suggests: xz-utils Description: package management related utility programs This package contains some less used commandline utilities related to package management with APT. -- cgit v1.2.3-70-g09d2