diff options
author | Daniel Hartwig <mandyke@gmail.com> | 2012-07-10 17:01:43 +0800 |
---|---|---|
committer | Daniel Hartwig <mandyke@gmail.com> | 2012-07-10 17:01:43 +0800 |
commit | 4412e28ca51a23d559631108119a51ba129ddbf2 (patch) | |
tree | 895ce878041044bee53c14b19946b1a11e7dd5f3 | |
parent | a6b2e20396aa754c0d2445312c744e82510b7f84 (diff) | |
download | aptitude-4412e28ca51a23d559631108119a51ba129ddbf2.tar.gz |
Add helpers for interfacing with dpkg
These should rather be in libapt-pkg but too late for Wheezy.
* generic/apt/dpkg.{cc,h}:
- dpkg_base_args: base arguments for dpkg from APT conf
- dpkg_mult_arch: true if dpkg is multi-arch aware
- dpkg_package_name: returns the name that dpkg uses for
a package
-rw-r--r-- | src/generic/apt/Makefile.am | 2 | ||||
-rw-r--r-- | src/generic/apt/dpkg.cc | 150 | ||||
-rw-r--r-- | src/generic/apt/dpkg.h | 53 |
3 files changed, 205 insertions, 0 deletions
diff --git a/src/generic/apt/Makefile.am b/src/generic/apt/Makefile.am index 29488f4f..4df2cfe7 100644 --- a/src/generic/apt/Makefile.am +++ b/src/generic/apt/Makefile.am @@ -47,6 +47,8 @@ libgeneric_apt_a_SOURCES = \ download_update_manager.h \ download_signal_log.cc \ download_signal_log.h \ + dpkg.cc \ + dpkg.h \ dump_packages.cc \ dump_packages.h \ globals.cc \ diff --git a/src/generic/apt/dpkg.cc b/src/generic/apt/dpkg.cc new file mode 100644 index 00000000..a777acec --- /dev/null +++ b/src/generic/apt/dpkg.cc @@ -0,0 +1,150 @@ +// dpkg.cc +// +// Copyright 2012 Daniel Hartwig +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; see the file COPYING. If not, write to +// the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. + +#include "dpkg.h" + +#include <aptitude.h> + +#include <apt-pkg/configuration.h> +#include <apt-pkg/error.h> +#include <apt-pkg/fileutl.h> +#include <apt-pkg/pkgcache.h> + +#include <boost/optional.hpp> + +#include <cerrno> +#include <string> +#include <vector> + +#include <sys/types.h> +#include <sys/wait.h> +#include <fcntl.h> + +using namespace std; + +namespace aptitude { +namespace apt { + +std::vector<const char *> dpkg_base_args(const bool cached) +{ + static std::vector<const char *> Args; + + if (cached == true && Args.empty() == false) + return Args; + + // Generate the base argument list for dpkg + Args.clear(); + string Tmp = _config->Find("Dir::Bin::dpkg","dpkg"); + { + string const dpkgChrootDir = _config->FindDir("DPkg::Chroot-Directory", "/"); + size_t dpkgChrootLen = dpkgChrootDir.length(); + if (dpkgChrootDir != "/" && Tmp.find(dpkgChrootDir) == 0) + { + if (dpkgChrootDir[dpkgChrootLen - 1] == '/') + --dpkgChrootLen; + Tmp = Tmp.substr(dpkgChrootLen); + } + } + Args.push_back(Tmp.c_str()); + + // Stick in any custom dpkg options + Configuration::Item const *Opts = _config->Tree("DPkg::Options"); + if (Opts != 0) + { + Opts = Opts->Child; + for (; Opts != 0; Opts = Opts->Next) + { + if (Opts->Value.empty() == true) + continue; + Args.push_back(Opts->Value.c_str()); + } + } + + return Args; +} + +bool dpkg_multi_arch(const bool cached) +{ + static boost::optional<bool> dpkgMultiArch; + + if (cached == true && dpkgMultiArch) + return *dpkgMultiArch; + + std::vector<const char *> Args(dpkg_base_args(cached)); + + // we need to detect if we can qualify packages with the architecture or not + Args.push_back("--assert-multi-arch"); + Args.push_back(NULL); + + + pid_t dpkgAssertMultiArch = ExecFork(); + if (dpkgAssertMultiArch == 0) + { + std::string const chrootDir = _config->FindDir("DPkg::Chroot-Directory"); + if (chrootDir != "/" && chroot(chrootDir.c_str()) != 0) + _error->WarningE("dpkg_multi_arch", + _("Couldn't chroot into %s for %s"), + chrootDir.c_str(), + "dpkg --assert-multi-arch"); + // redirect everything to the ultimate sink as we only need the exit-status + int const nullfd = open("/dev/null", O_RDONLY); + dup2(nullfd, STDIN_FILENO); + dup2(nullfd, STDOUT_FILENO); + dup2(nullfd, STDERR_FILENO); + execvp(Args[0], (char**) &Args[0]); + _error->WarningE("dpkg_multi_arch", "Can't detect if dpkg supports multi-arch!"); + _exit(2); + } + + dpkgMultiArch.reset(false); + if (dpkgAssertMultiArch > 0) + { + int Status = 0; + while (waitpid(dpkgAssertMultiArch, &Status, 0) != dpkgAssertMultiArch) + { + if (errno == EINTR) + continue; + _error->WarningE("dpkg_multi_arch", + _("Waited for %s but it wasn't there"), + "dpkg --assert-multi-arch"); + break; + } + if (WIFEXITED(Status) == true && WEXITSTATUS(Status) == 0) + dpkgMultiArch.reset(true); + } + + return *dpkgMultiArch; +} + +std::string dpkg_package_name(const pkgCache::PkgIterator &pkg) +{ + if(dpkg_multi_arch() == false) + return pkg.FullName(true); + else + { + if(pkg->CurrentVer != 0) + return string(pkg.Name()).append(":").append(pkg.CurrentVer().Arch()); + else if(pkg.VersionList().end() == false) + return string(pkg.Name()).append(":").append(pkg.VersionList().Arch()); + else + return pkg.FullName(false); + } +} + +}} // namespace aptitude { namespace apt { diff --git a/src/generic/apt/dpkg.h b/src/generic/apt/dpkg.h new file mode 100644 index 00000000..53a2d9bc --- /dev/null +++ b/src/generic/apt/dpkg.h @@ -0,0 +1,53 @@ +// dpkg.h -*-c++-*- +// +// Copyright 2012 Daniel Hartwig +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; see the file COPYING. If not, write to +// the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// Helpers for interfacing with dpkg. +// Based on APT: dpkgpm.cc, apt-mark.cc + +// FIXME: These should really go in libapt-pkg. + +#ifndef APTITUDE_GENERIC_APT_DPKG_H +#define APTITUDE_GENERIC_APT_DPKG_H + +#include <apt-pkg/pkgcache.h> + +#include <string> +#include <vector> + +namespace aptitude { +namespace apt { + +/** \brief Base arguments that should be passed to dpkg. Append + * additional arguments, followed by NULL, then pass to + * execvp(3). + */ +std::vector<const char *> dpkg_base_args(const bool cached = true); + +/** \brief Returns \b true if dpkg is multi-arch aware. + */ +bool dpkg_multi_arch(const bool cached = true); + +/** \brief Returns the name by which dpkg knows /b pkg. Note that + * this is different to PkgIterator::FullName. + */ +std::string dpkg_package_name(const pkgCache::PkgIterator &pkg); + +}} // namespace aptitude { namespace apt { + +#endif // APTITUDE_GENERIC_APT_DPKG_H |