summaryrefslogtreecommitdiffstats
path: root/cmdline/apt-get.cc
diff options
context:
space:
mode:
Diffstat (limited to 'cmdline/apt-get.cc')
-rw-r--r--cmdline/apt-get.cc450
1 files changed, 450 insertions, 0 deletions
diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc
new file mode 100644
index 0000000..95c4a85
--- /dev/null
+++ b/cmdline/apt-get.cc
@@ -0,0 +1,450 @@
+// -*- 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 <errno.h>
+#include <grp.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.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},
+ {"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);
+}
+ /*}}}*/