diff options
Diffstat (limited to 'cmdline/apt-get.cc')
-rw-r--r-- | cmdline/apt-get.cc | 452 |
1 files changed, 452 insertions, 0 deletions
diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc new file mode 100644 index 0000000..2828ad6 --- /dev/null +++ b/cmdline/apt-get.cc @@ -0,0 +1,452 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + + apt-get - Cover for dpkg + + This is an allout cover for dpkg implementing a safer front end. It is + based largely on libapt-pkg. + + The syntax is different, + apt-get [opt] command [things] + Where command is: + update - Resyncronize the package files from their sources + upgrade - Smart-Download the newest versions of all packages + dselect-upgrade - Follows dselect's changes to the Status: field + and installs new and removes old packages + dist-upgrade - Powerful upgrader designed to handle the issues with + a new distribution. + install - Download and install a given package (by name, not by .deb) + check - Update the package cache and check for broken packages + clean - Erase the .debs downloaded to /var/cache/apt/archives and + the partial dir too + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include <config.h> + +#include <apt-pkg/acquire-item.h> +#include <apt-pkg/acquire.h> +#include <apt-pkg/algorithms.h> +#include <apt-pkg/aptconfiguration.h> +#include <apt-pkg/cachefile.h> +#include <apt-pkg/cacheset.h> +#include <apt-pkg/clean.h> +#include <apt-pkg/cmndline.h> +#include <apt-pkg/configuration.h> +#include <apt-pkg/debmetaindex.h> +#include <apt-pkg/depcache.h> +#include <apt-pkg/error.h> +#include <apt-pkg/fileutl.h> +#include <apt-pkg/indexfile.h> +#include <apt-pkg/init.h> +#include <apt-pkg/macros.h> +#include <apt-pkg/metaindex.h> +#include <apt-pkg/pkgcache.h> +#include <apt-pkg/pkgrecords.h> +#include <apt-pkg/pkgsystem.h> +#include <apt-pkg/progress.h> +#include <apt-pkg/sourcelist.h> +#include <apt-pkg/srcrecords.h> +#include <apt-pkg/strutl.h> +#include <apt-pkg/upgrade.h> +#include <apt-pkg/version.h> + +#include <apt-private/acqprogress.h> +#include <apt-private/private-cachefile.h> +#include <apt-private/private-cacheset.h> +#include <apt-private/private-cmndline.h> +#include <apt-private/private-download.h> +#include <apt-private/private-install.h> +#include <apt-private/private-main.h> +#include <apt-private/private-moo.h> +#include <apt-private/private-output.h> +#include <apt-private/private-source.h> +#include <apt-private/private-update.h> +#include <apt-private/private-upgrade.h> +#include <apt-private/private-utils.h> + +#include <cerrno> +#include <csignal> +#include <cstddef> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <grp.h> +#include <pwd.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <unistd.h> + +#include <algorithm> +#include <fstream> +#include <iostream> +#include <set> +#include <sstream> +#include <string> +#include <vector> + +#include <apti18n.h> + /*}}}*/ + +using namespace std; + +/* mark packages as automatically/manually installed. {{{*/ +static bool DoMarkAuto(CommandLine &CmdL) +{ + bool Action = true; + int AutoMarkChanged = 0; + OpTextProgress progress; + CacheFile Cache; + if (Cache.Open() == false) + return false; + + if (strcasecmp(CmdL.FileList[0],"markauto") == 0) + Action = true; + else if (strcasecmp(CmdL.FileList[0],"unmarkauto") == 0) + Action = false; + + for (const char **I = CmdL.FileList + 1; *I != 0; I++) + { + const char *S = *I; + // Locate the package + pkgCache::PkgIterator Pkg = Cache->FindPkg(S); + if (Pkg.end() == true) { + return _error->Error(_("Couldn't find package %s"),S); + } + else + { + if (!Action) + ioprintf(c1out,_("%s set to manually installed.\n"), Pkg.Name()); + else + ioprintf(c1out,_("%s set to automatically installed.\n"), + Pkg.Name()); + + Cache->MarkAuto(Pkg,Action); + AutoMarkChanged++; + } + } + + _error->Notice(_("This command is deprecated. Please use 'apt-mark auto' and 'apt-mark manual' instead.")); + + if (AutoMarkChanged && ! _config->FindB("APT::Get::Simulate",false)) + return Cache->writeStateFile(NULL); + return false; +} + /*}}}*/ +// DoDSelectUpgrade - Do an upgrade by following dselects selections /*{{{*/ +// --------------------------------------------------------------------- +/* Follows dselect's selections */ +static bool DoDSelectUpgrade(CommandLine &) +{ + CacheFile Cache; + if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false) + return false; + + pkgDepCache::ActionGroup group(Cache); + + // Install everything with the install flag set + for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() != true; ++I) + { + /* Install the package only if it is a new install, the autoupgrader + will deal with the rest */ + if (I->SelectedState == pkgCache::State::Install) + Cache->MarkInstall(I,false); + } + + /* Now install their deps too, if we do this above then order of + the status file is significant for | groups */ + for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() != true; ++I) + { + /* Install the package only if it is a new install, the autoupgrader + will deal with the rest */ + if (I->SelectedState == pkgCache::State::Install) + Cache->MarkInstall(I,true); + } + + // Apply erasures now, they override everything else. + for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() != true; ++I) + { + // Remove packages + if (I->SelectedState == pkgCache::State::DeInstall || + I->SelectedState == pkgCache::State::Purge) + Cache->MarkDelete(I,I->SelectedState == pkgCache::State::Purge); + } + + /* Resolve any problems that dselect created, allupgrade cannot handle + such things. We do so quite aggressively too.. */ + if (Cache->BrokenCount() != 0) + { + pkgProblemResolver Fix(Cache); + + // Hold back held packages. + if (_config->FindB("APT::Ignore-Hold",false) == false) + { + for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() == false; ++I) + { + if (I->SelectedState == pkgCache::State::Hold) + { + Fix.Protect(I); + Cache->MarkKeep(I); + } + } + } + + if (Fix.Resolve() == false) + { + ShowBroken(c1out,Cache,false); + return _error->Error(_("Internal error, problem resolver broke stuff")); + } + } + + // Now upgrade everything + if (APT::Upgrade::Upgrade(Cache, APT::Upgrade::FORBID_REMOVE_PACKAGES | APT::Upgrade::FORBID_INSTALL_NEW_PACKAGES) == false) + { + ShowBroken(c1out,Cache,false); + return _error->Error(_("Internal error, problem resolver broke stuff")); + } + + APT::PackageVector HeldBackPackages; + for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); not Pkg.end(); ++Pkg) + if (Pkg->CurrentVer != 0 && Cache[Pkg].Upgradable() && not Cache[Pkg].Upgrade() && not Cache[Pkg].Delete()) + HeldBackPackages.push_back(Pkg); + + return InstallPackages(Cache, HeldBackPackages, false); +} + /*}}}*/ +// DoCheck - Perform the check operation /*{{{*/ +// --------------------------------------------------------------------- +/* Opening automatically checks the system, this command is mostly used + for debugging */ +static bool DoCheck(CommandLine &) +{ + CacheFile Cache; + Cache.Open(); + Cache.CheckDeps(); + + return true; +} + /*}}}*/ +// DoIndexTargets - Lists all IndexTargets /*{{{*/ +static std::string format_key(std::string key) +{ + // deb822 is case-insensitive, but the human eye prefers candy + std::transform(key.begin(), key.end(), key.begin(), ::tolower); + key[0] = ::toupper(key[0]); + size_t found = key.find("_uri"); + if (found != std::string::npos) + key.replace(found, 4, "-URI"); + while ((found = key.find('_')) != std::string::npos) + { + key[found] = '-'; + key[found + 1] = ::toupper(key[found + 1]); + } + return key; +} +static bool DoIndexTargets(CommandLine &CmdL) +{ + pkgCacheFile CacheFile; + pkgSourceList *SrcList = CacheFile.GetSourceList(); + pkgCache *Cache = CacheFile.GetPkgCache(); + + if (SrcList == nullptr || Cache == nullptr) + return false; + + std::string const Format = _config->Find("APT::Get::IndexTargets::Format"); + bool const ReleaseInfo = _config->FindB("APT::Get::IndexTargets::ReleaseInfo", true); + bool Filtered = CmdL.FileSize() > 1; + for (pkgSourceList::const_iterator S = SrcList->begin(); S != SrcList->end(); ++S) + { + std::vector<IndexTarget> const targets = (*S)->GetIndexTargets(); + std::map<std::string, string> AddOptions; + if (ReleaseInfo) + { + AddOptions.insert(std::make_pair("TRUSTED", ((*S)->IsTrusted() ? "yes" : "no"))); + pkgCache::RlsFileIterator const RlsFile = (*S)->FindInCache(*Cache, false); + if (RlsFile.end()) + continue; +#define APT_RELEASE(X,Y) if (RlsFile.Y() != NULL) AddOptions.insert(std::make_pair(X, RlsFile.Y())) + APT_RELEASE("CODENAME", Codename); + APT_RELEASE("SUITE", Archive); + APT_RELEASE("VERSION", Version); + APT_RELEASE("ORIGIN", Origin); + APT_RELEASE("LABEL", Label); +#undef APT_RELEASE + } + + for (std::vector<IndexTarget>::const_iterator T = targets.begin(); T != targets.end(); ++T) + { + std::string filename = T->Option(ReleaseInfo ? IndexTarget::EXISTING_FILENAME : IndexTarget::FILENAME); + if (filename.empty()) + continue; + + std::ostringstream stanza; + if (Filtered || Format.empty()) + { + stanza << "MetaKey: " << T->MetaKey << "\n" + << "ShortDesc: " << T->ShortDesc << "\n" + << "Description: " << T->Description << "\n" + << "URI: " << T->URI << "\n" + << "Filename: " << filename << "\n" + << "Optional: " << (T->IsOptional ? "yes" : "no") << "\n" + << "KeepCompressed: " << (T->KeepCompressed ? "yes" : "no") << "\n"; + for (std::map<std::string,std::string>::const_iterator O = AddOptions.begin(); O != AddOptions.end(); ++O) + stanza << format_key(O->first) << ": " << O->second << "\n"; + for (std::map<std::string,std::string>::const_iterator O = T->Options.begin(); O != T->Options.end(); ++O) + { + if (O->first == "PDIFFS") + stanza << "PDiffs: " << O->second << "\n"; + else if (O->first == "COMPRESSIONTYPES") + stanza << "CompressionTypes: " << O->second << "\n"; + else if (O->first == "KEEPCOMPRESSEDAS") + stanza << "KeepCompressedAs: " << O->second << "\n"; + else if (O->first == "DEFAULTENABLED") + stanza << "DefaultEnabled: " << O->second << "\n"; + else + stanza << format_key(O->first) << ": " << O->second << "\n"; + } + stanza << "\n"; + + if (Filtered) + { + // that is a bit crude, but good enough for now + bool found = true; + std::string haystack = std::string("\n") + stanza.str() + "\n"; + std::transform(haystack.begin(), haystack.end(), haystack.begin(), ::tolower); + size_t const filesize = CmdL.FileSize() - 1; + for (size_t i = 0; i != filesize; ++i) + { + std::string needle = std::string("\n") + CmdL.FileList[i + 1] + "\n"; + std::transform(needle.begin(), needle.end(), needle.begin(), ::tolower); + if (haystack.find(needle) != std::string::npos) + continue; + found = false; + break; + } + if (found == false) + continue; + } + } + + if (Format.empty()) + cout << stanza.str(); + else + { + std::string out = SubstVar(Format, "$(FILENAME)", filename); + out = T->Format(out); + for (std::map<std::string,std::string>::const_iterator O = AddOptions.begin(); O != AddOptions.end(); ++O) + out = SubstVar(out, std::string("$(") + O->first + ")", O->second); + cout << out << std::endl; + } + } + } + + return true; +} + /*}}}*/ +static bool ShowHelp(CommandLine &) /*{{{*/ +{ + if (_config->FindB("version") == true) + { + cout << _("Supported modules:") << endl; + + for (unsigned I = 0; I != pkgVersioningSystem::GlobalListLen; I++) + { + pkgVersioningSystem *VS = pkgVersioningSystem::GlobalList[I]; + if (_system != 0 && _system->VS == VS) + cout << '*'; + else + cout << ' '; + cout << "Ver: " << VS->Label << endl; + + /* Print out all the packaging systems that will work with + this VS */ + for (unsigned J = 0; J != pkgSystem::GlobalListLen; J++) + { + pkgSystem *Sys = pkgSystem::GlobalList[J]; + if (_system == Sys) + cout << '*'; + else + cout << ' '; + if (Sys->VS->TestCompatibility(*VS) == true) + cout << "Pkg: " << Sys->Label << " (Priority " << Sys->Score(*_config) << ")" << endl; + } + } + + for (unsigned I = 0; I != pkgSourceList::Type::GlobalListLen; I++) + { + pkgSourceList::Type *Type = pkgSourceList::Type::GlobalList[I]; + cout << " S.L: '" << Type->Name << "' " << Type->Label << endl; + } + + for (unsigned I = 0; I != pkgIndexFile::Type::GlobalListLen; I++) + { + pkgIndexFile::Type *Type = pkgIndexFile::Type::GlobalList[I]; + cout << " Idx: " << Type->Label << endl; + } + + return true; + } + + std::cout << + _("Usage: apt-get [options] command\n" + " apt-get [options] install|remove pkg1 [pkg2 ...]\n" + " apt-get [options] source pkg1 [pkg2 ...]\n" + "\n" + "apt-get is a command line interface for retrieval of packages\n" + "and information about them from authenticated sources and\n" + "for installation, upgrade and removal of packages together\n" + "with their dependencies.\n"); + return true; +} + /*}}}*/ +static std::vector<aptDispatchWithHelp> GetCommands() /*{{{*/ +{ + // advanced commands are left undocumented on purpose + return { + {"update", &DoUpdate, _("Retrieve new lists of packages")}, + {"upgrade", &DoUpgrade, _("Perform an upgrade")}, + {"install", &DoInstall, _("Install new packages (pkg is libc6 not libc6.deb)")}, + {"reinstall", &DoInstall, _("Reinstall packages (pkg is libc6 not libc6.deb)")}, + {"remove", &DoInstall, _("Remove packages")}, + {"purge", &DoInstall, _("Remove packages and config files")}, + {"autoremove", &DoInstall, _("Remove automatically all unused packages")}, + {"auto-remove", &DoInstall, nullptr}, + {"autopurge",&DoInstall, nullptr}, + {"markauto", &DoMarkAuto, nullptr}, + {"unmarkauto", &DoMarkAuto, nullptr}, + {"dist-upgrade", &DoDistUpgrade, _("Distribution upgrade, see apt-get(8)")}, + {"full-upgrade", &DoDistUpgrade, nullptr}, + {"dselect-upgrade", &DoDSelectUpgrade, _("Follow dselect selections")}, + {"build-dep", &DoBuildDep, _("Configure build-dependencies for source packages")}, + {"satisfy", &DoBuildDep, _("Satisfy dependency strings")}, + {"clean", &DoClean, _("Erase downloaded archive files")}, + {"autoclean", &DoAutoClean, _("Erase old downloaded archive files")}, + {"auto-clean", &DoAutoClean, nullptr}, + {"distclean", &DoDistClean, nullptr}, + {"dist-clean", &DoDistClean, nullptr}, + {"check", &DoCheck, _("Verify that there are no broken dependencies")}, + {"source", &DoSource, _("Download source archives")}, + {"download", &DoDownload, _("Download the binary package into the current directory")}, + {"changelog", &DoChangelog, _("Download and display the changelog for the given package")}, + {"indextargets", &DoIndexTargets, nullptr}, + {"moo", &DoMoo, nullptr}, + {nullptr, nullptr, nullptr} + }; +} + /*}}}*/ +int main(int argc,const char *argv[]) /*{{{*/ +{ + // Parse the command line and initialize the package library + CommandLine CmdL; + auto const Cmds = ParseCommandLine(CmdL, APT_CMD::APT_GET, &_config, &_system, argc, argv, &ShowHelp, &GetCommands); + + InitSignals(); + InitOutput(); + + CheckIfSimulateMode(CmdL); + + return DispatchCommandLine(CmdL, Cmds); +} + /*}}}*/ |