diff options
author | Michael Vogt <mvo@debian.org> | 2014-02-27 22:52:34 +0100 |
---|---|---|
committer | Michael Vogt <mvo@debian.org> | 2014-02-27 22:52:34 +0100 |
commit | fce69e7a0f38299c57ef96ae1c1dd9a5379bfd5a (patch) | |
tree | be7d18baa836e9df166ec63f6c9fe6f94bb84b40 /cmdline | |
parent | a5e790985752c6820e08e7a7e650e1607fa826e4 (diff) | |
parent | fc104da6a583736223b2f941e43a05ea26b63a7d (diff) |
Merge branch 'debian/sid' into debian/experimental
Conflicts:
apt-private/private-list.cc
configure.ac
debian/apt.install.in
debian/changelog
Diffstat (limited to 'cmdline')
-rw-r--r-- | cmdline/apt-cdrom.cc | 76 | ||||
-rw-r--r-- | cmdline/apt-config.cc | 2 | ||||
-rw-r--r-- | cmdline/apt-extracttemplates.cc | 29 | ||||
-rw-r--r-- | cmdline/apt-get.cc | 383 | ||||
-rw-r--r-- | cmdline/apt-internal-solver.cc | 7 | ||||
-rw-r--r--[-rwxr-xr-x] | cmdline/apt-key.in (renamed from cmdline/apt-key) | 88 | ||||
-rw-r--r-- | cmdline/apt-mark.cc | 9 | ||||
-rw-r--r-- | cmdline/apt.cc | 63 | ||||
-rw-r--r-- | cmdline/makefile | 25 |
9 files changed, 412 insertions, 270 deletions
diff --git a/cmdline/apt-cdrom.cc b/cmdline/apt-cdrom.cc index 17a60ddcb..20c6e8892 100644 --- a/cmdline/apt-cdrom.cc +++ b/cmdline/apt-cdrom.cc @@ -111,10 +111,12 @@ OpProgress* pkgCdromTextStatus::GetOpProgress() }; /*}}}*/ // SetupAutoDetect /*{{{*/ -bool AutoDetectCdrom(pkgUdevCdromDevices &UdevCdroms, unsigned int &i) +bool AutoDetectCdrom(pkgUdevCdromDevices &UdevCdroms, unsigned int &i, bool &automounted) { bool Debug = _config->FindB("Debug::Acquire::cdrom", false); + automounted = false; + vector<struct CdromDevice> v = UdevCdroms.Scan(); if (i >= v.size()) return false; @@ -137,6 +139,8 @@ bool AutoDetectCdrom(pkgUdevCdromDevices &UdevCdroms, unsigned int &i) mkdir(AptMountPoint.c_str(), 0750); if(MountCdrom(AptMountPoint, v[i].DeviceName) == false) _error->Warning(_("Failed to mount '%s' to '%s'"), v[i].DeviceName.c_str(), AptMountPoint.c_str()); + else + automounted = true; _config->Set("Acquire::cdrom::mount", AptMountPoint); _config->Set("APT::CDROM::NoMount", true); } @@ -160,17 +164,35 @@ bool DoAdd(CommandLine &) bool AutoDetect = _config->FindB("Acquire::cdrom::AutoDetect", true); unsigned int count = 0; + string AptMountPoint = _config->FindDir("Dir::Media::MountPath"); + bool automounted = false; if (AutoDetect && UdevCdroms.Dlopen()) - while (AutoDetectCdrom(UdevCdroms, count)) - res &= cdrom.Add(&log); - if (count == 0) { - res = cdrom.Add(&log); - if (res == false) { - _error->Error("%s", _(W_NO_CDROM_FOUND)); + while (AutoDetectCdrom(UdevCdroms, count, automounted)) { + if (count == 1) { + // begin loop with res false to detect any success using OR + res = false; + } + + // dump any warnings/errors from autodetect + if (_error->empty() == false) + _error->DumpErrors(); + + res |= cdrom.Add(&log); + + if (automounted) + UnmountCdrom(AptMountPoint); + + // dump any warnings/errors from add/unmount + if (_error->empty() == false) + _error->DumpErrors(); } - } - if(res) + if (count == 0) + res = cdrom.Add(&log); + + if (res == false) + _error->Error("%s", _(W_NO_CDROM_FOUND)); + else cout << _("Repeat this process for the rest of the CDs in your set.") << endl; return res; @@ -187,18 +209,38 @@ bool DoIdent(CommandLine &) pkgCdrom cdrom; bool res = true; - bool AutoDetect = _config->FindB("Acquire::cdrom::AutoDetect"); + bool AutoDetect = _config->FindB("Acquire::cdrom::AutoDetect", true); unsigned int count = 0; + string AptMountPoint = _config->FindDir("Dir::Media::MountPath"); + bool automounted = false; if (AutoDetect && UdevCdroms.Dlopen()) - while (AutoDetectCdrom(UdevCdroms, count)) - res &= cdrom.Ident(ident, &log); - if (count == 0) { - res = cdrom.Ident(ident, &log); - if (res == false) { - _error->Error("%s", _(W_NO_CDROM_FOUND)); + while (AutoDetectCdrom(UdevCdroms, count, automounted)) { + if (count == 1) { + // begin loop with res false to detect any success using OR + res = false; + } + + // dump any warnings/errors from autodetect + if (_error->empty() == false) + _error->DumpErrors(); + + res |= cdrom.Ident(ident, &log); + + if (automounted) + UnmountCdrom(AptMountPoint); + + // dump any warnings/errors from add/unmount + if (_error->empty() == false) + _error->DumpErrors(); } - } + + if (count == 0) + res = cdrom.Ident(ident, &log); + + if (res == false) + _error->Error("%s", _(W_NO_CDROM_FOUND)); + return res; } /*}}}*/ diff --git a/cmdline/apt-config.cc b/cmdline/apt-config.cc index 3481eaf5f..30c2a22d5 100644 --- a/cmdline/apt-config.cc +++ b/cmdline/apt-config.cc @@ -8,7 +8,7 @@ This program will parse a config file and then do something with it. Commands: - shell - Shell mode. After this a series of word pairs should occure. + shell - Shell mode. After this a series of word pairs should occur. The first is the environment var to set and the second is the key to set it from. Use like: eval `apt-config shell QMode apt::QMode` diff --git a/cmdline/apt-extracttemplates.cc b/cmdline/apt-extracttemplates.cc index 8fe15fdf9..2408a7d9d 100644 --- a/cmdline/apt-extracttemplates.cc +++ b/cmdline/apt-extracttemplates.cc @@ -24,8 +24,7 @@ #include <apt-pkg/pkgcachegen.h> #include <apt-pkg/version.h> #include <apt-pkg/tagfile.h> -#include <apt-pkg/extracttar.h> -#include <apt-pkg/arfile.h> +#include <apt-pkg/debfile.h> #include <apt-pkg/deblistparser.h> #include <apt-pkg/error.h> #include <apt-pkg/strutl.h> @@ -47,8 +46,6 @@ using namespace std; -#define TMPDIR "/tmp" - pkgCache *DebFile::Cache = 0; // DebFile::DebFile - Construct the DebFile object /*{{{*/ @@ -93,18 +90,9 @@ string DebFile::GetInstalledVer(const string &package) /* */ bool DebFile::Go() { - ARArchive AR(File); - if (_error->PendingError() == true) - return false; - - const ARArchive::Member *Member = AR.FindMember("control.tar.gz"); - if (Member == 0) - return _error->Error(_("%s not a valid DEB package."),File.Name().c_str()); - - if (File.Seek(Member->Start) == false) - return false; - ExtractTar Tar(File, Member->Size,"gzip"); - return Tar.Go(*this); + debDebFile Deb(File); + + return Deb.ExtractTarMember(*this, "control.tar"); } /*}}}*/ // DebFile::DoItem examine element in package and mark /*{{{*/ @@ -253,14 +241,11 @@ string WriteFile(const char *package, const char *prefix, const char *data) { char fn[512]; static int i; - const char *tempdir = NULL; - - tempdir = getenv("TMPDIR"); - if (tempdir == NULL) - tempdir = TMPDIR; + std::string tempdir = GetTempDir(); snprintf(fn, sizeof(fn), "%s/%s.%s.%u%d", - _config->Find("APT::ExtractTemplates::TempDir", tempdir).c_str(), + _config->Find("APT::ExtractTemplates::TempDir", + tempdir.c_str()).c_str(), package, prefix, getpid(), i++); FileFd f; if (data == NULL) diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index cc8cc5aad..6e9d3bf68 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -15,7 +15,7 @@ upgrade - Smart-Download the newest versions of all packages dselect-upgrade - Follows dselect's changes to the Status: field and installes new and removes old packages - dist-upgrade - Powerfull upgrader designed to handle the issues with + 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 @@ -49,8 +49,11 @@ #include <apt-pkg/pkgsystem.h> #include <apt-pkg/pkgrecords.h> #include <apt-pkg/indexfile.h> +#include <apt-pkg/upgrade.h> +#include <apt-pkg/metaindex.h> +#include <apt-pkg/indexrecords.h> - +#include <apt-private/private-download.h> #include <apt-private/private-install.h> #include <apt-private/private-upgrade.h> #include <apt-private/private-output.h> @@ -58,13 +61,18 @@ #include <apt-private/private-update.h> #include <apt-private/private-cmndline.h> #include <apt-private/private-moo.h> +#include <apt-private/private-utils.h> + +#include <apt-pkg/debmetaindex.h> #include <apt-private/acqprogress.h> #include <set> +#include <fstream> +#include <sstream> + #include <locale.h> #include <langinfo.h> -#include <fstream> #include <termios.h> #include <sys/ioctl.h> #include <sys/stat.h> @@ -76,7 +84,6 @@ #include <errno.h> #include <regex.h> #include <sys/wait.h> -#include <sstream> #include <apt-private/private-output.h> #include <apt-private/private-main.h> @@ -84,11 +91,8 @@ #include <apti18n.h> /*}}}*/ - using namespace std; - - // TryToInstallBuildDep - Try to install a single package /*{{{*/ // --------------------------------------------------------------------- /* This used to be inlined in DoInstall, but with the advent of regex package @@ -130,24 +134,95 @@ bool TryToInstallBuildDep(pkgCache::PkgIterator Pkg,pkgCacheFile &Cache, return true; } /*}}}*/ + + +// helper that can go wit hthe next ABI break +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR < 13) +std::string MetaIndexFileNameOnDisk(metaIndex *metaindex) +{ + // FIXME: this cast is the horror, the horror + debReleaseIndex *r = (debReleaseIndex*)metaindex; + + // see if we have a InRelease file + std::string PathInRelease = r->MetaIndexFile("InRelease"); + if (FileExists(PathInRelease)) + return PathInRelease; + + // and if not return the normal one + if (FileExists(PathInRelease)) + return r->MetaIndexFile("Release"); + + return ""; +} +#endif + +// GetReleaseForSourceRecord - Return Suite for the given srcrecord /*{{{*/ +// --------------------------------------------------------------------- +/* */ +std::string GetReleaseForSourceRecord(pkgSourceList *SrcList, + pkgSrcRecords::Parser *Parse) +{ + // try to find release + const pkgIndexFile& CurrentIndexFile = Parse->Index(); + + for (pkgSourceList::const_iterator S = SrcList->begin(); + S != SrcList->end(); ++S) + { + vector<pkgIndexFile *> *Indexes = (*S)->GetIndexFiles(); + for (vector<pkgIndexFile *>::const_iterator IF = Indexes->begin(); + IF != Indexes->end(); ++IF) + { + if (&CurrentIndexFile == (*IF)) + { +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR < 13) + std::string path = MetaIndexFileNameOnDisk(*S); +#else + std::string path = (*S)->LocalFileName(); +#endif + if (path != "") + { + indexRecords records; + records.Load(path); + return records.GetSuite(); + } + } + } + } + return ""; +} + /*}}}*/ // FindSrc - Find a source record /*{{{*/ // --------------------------------------------------------------------- /* */ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, pkgSrcRecords &SrcRecs,string &Src, - pkgDepCache &Cache) + CacheFile &CacheFile) { - string VerTag; - string DefRel = _config->Find("APT::Default-Release"); + string VerTag, UserRequestedVerTag; + string ArchTag = ""; + string RelTag = _config->Find("APT::Default-Release"); string TmpSrc = Name; + pkgDepCache *Cache = CacheFile.GetDepCache(); - // extract the version/release from the pkgname - const size_t found = TmpSrc.find_last_of("/="); - if (found != string::npos) { - if (TmpSrc[found] == '/') - DefRel = TmpSrc.substr(found+1); - else - VerTag = TmpSrc.substr(found+1); + // extract release + size_t found = TmpSrc.find_last_of("/"); + if (found != string::npos) + { + RelTag = TmpSrc.substr(found+1); + TmpSrc = TmpSrc.substr(0,found); + } + // extract the version + found = TmpSrc.find_last_of("="); + if (found != string::npos) + { + VerTag = UserRequestedVerTag = TmpSrc.substr(found+1); + TmpSrc = TmpSrc.substr(0,found); + } + // extract arch + found = TmpSrc.find_last_of(":"); + if (found != string::npos) + { + ArchTag = TmpSrc.substr(found+1); TmpSrc = TmpSrc.substr(0,found); } @@ -155,10 +230,25 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, install a version and determine the source package name, then look in the archive for a source package of the same name. */ bool MatchSrcOnly = _config->FindB("APT::Get::Only-Source"); - const pkgCache::PkgIterator Pkg = Cache.FindPkg(TmpSrc); + pkgCache::PkgIterator Pkg; + if (ArchTag != "") + Pkg = Cache->FindPkg(TmpSrc, ArchTag); + else + Pkg = Cache->FindPkg(TmpSrc); + + // if we can't find a package but the user qualified with a arch, + // error out here + if (Pkg.end() && ArchTag != "") + { + Src = Name; + _error->Error(_("Can not find a package for architecture '%s'"), + ArchTag.c_str()); + return 0; + } + if (MatchSrcOnly == false && Pkg.end() == false) { - if(VerTag.empty() == false || DefRel.empty() == false) + if(VerTag != "" || RelTag != "" || ArchTag != "") { bool fuzzy = false; // we have a default release, try to locate the pkg. we do it like @@ -178,9 +268,20 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, if (Ver.end() == true) break; } + + // ignore arches that are not for us + if (ArchTag != "" && Ver.Arch() != ArchTag) + continue; + + // pick highest version for the arch unless the user wants + // something else + if (ArchTag != "" && VerTag == "" && RelTag == "") + if(Cache->VS().CmpVersion(VerTag, Ver.VerStr()) < 0) + VerTag = Ver.VerStr(); + // We match against a concrete version (or a part of this version) if (VerTag.empty() == false && - (fuzzy == true || Cache.VS().CmpVersion(VerTag, Ver.VerStr()) != 0) && // exact match + (fuzzy == true || Cache->VS().CmpVersion(VerTag, Ver.VerStr()) != 0) && // exact match (fuzzy == false || strncmp(VerTag.c_str(), Ver.VerStr(), VerTag.size()) != 0)) // fuzzy match continue; @@ -198,8 +299,8 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, // or we match against a release if(VerTag.empty() == false || - (VF.File().Archive() != 0 && VF.File().Archive() == DefRel) || - (VF.File().Codename() != 0 && VF.File().Codename() == DefRel)) + (VF.File().Archive() != 0 && VF.File().Archive() == RelTag) || + (VF.File().Codename() != 0 && VF.File().Codename() == RelTag)) { pkgRecords::Parser &Parse = Recs.Lookup(VF); Src = Parse.SourcePkg(); @@ -217,22 +318,28 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, if (Src.empty() == false) break; } - if (Src.empty() == true) - { - // Sources files have no codename information - if (VerTag.empty() == true && DefRel.empty() == false) - { - _error->Error(_("Ignore unavailable target release '%s' of package '%s'"), DefRel.c_str(), TmpSrc.c_str()); - return 0; - } - } } + + if (Src == "" && ArchTag != "") + { + if (VerTag != "") + _error->Error(_("Can not find a package '%s' with version '%s'"), + Pkg.FullName().c_str(), VerTag.c_str()); + if (RelTag != "") + _error->Error(_("Can not find a package '%s' with release '%s'"), + Pkg.FullName().c_str(), RelTag.c_str()); + Src = Name; + return 0; + } + + if (Src.empty() == true) { // if we don't have found a fitting package yet so we will // choose a good candidate and proceed with that. // Maybe we will find a source later on with the right VerTag - pkgCache::VerIterator Ver = Cache.GetCandidateVer(Pkg); + // or RelTag + pkgCache::VerIterator Ver = Cache->GetCandidateVer(Pkg); if (Ver.end() == false) { pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList()); @@ -244,7 +351,9 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, } if (Src.empty() == true) + { Src = TmpSrc; + } else { /* if we have a source pkg name, make sure to only search @@ -262,6 +371,7 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, pkgSrcRecords::Parser *Last = 0; unsigned long Offset = 0; string Version; + pkgSourceList *SrcList = CacheFile.GetSourceList(); /* Iterate over all of the hits, which includes the resulting binary packages in the search */ @@ -273,26 +383,43 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, { const string Ver = Parse->Version(); + // See if we need to look for a specific release tag + if (RelTag != "" && UserRequestedVerTag == "") + { + const string Rel = GetReleaseForSourceRecord(SrcList, Parse); + + if (Rel == RelTag) + { + Last = Parse; + Offset = Parse->Offset(); + Version = Ver; + } + } + // Ignore all versions which doesn't fit if (VerTag.empty() == false && - Cache.VS().CmpVersion(VerTag, Ver) != 0) // exact match + Cache->VS().CmpVersion(VerTag, Ver) != 0) // exact match continue; // Newer version or an exact match? Save the hit - if (Last == 0 || Cache.VS().CmpVersion(Version,Ver) < 0) { + if (Last == 0 || Cache->VS().CmpVersion(Version,Ver) < 0) { Last = Parse; Offset = Parse->Offset(); Version = Ver; } - // was the version check above an exact match? If so, we don't need to look further - if (VerTag.empty() == false && VerTag.size() == Ver.size()) + // was the version check above an exact match? + // If so, we don't need to look further + if (VerTag.empty() == false && (VerTag == Ver)) break; } + if (UserRequestedVerTag == "" && Version != "" && RelTag != "") + ioprintf(c1out, "Selected version '%s' (%s) for %s\n", + Version.c_str(), RelTag.c_str(), Src.c_str()); + if (Last != 0 || VerTag.empty() == true) break; - //if (VerTag.empty() == false && Last == 0) - _error->Error(_("Ignore unavailable version '%s' of package '%s'"), VerTag.c_str(), TmpSrc.c_str()); + _error->Error(_("Can not find version '%s' of package '%s'"), VerTag.c_str(), TmpSrc.c_str()); return 0; } @@ -345,31 +472,6 @@ bool DoMarkAuto(CommandLine &CmdL) return false; } /*}}}*/ -// DoDistUpgrade - Automatic smart upgrader /*{{{*/ -// --------------------------------------------------------------------- -/* Intelligent upgrader that will install and remove packages at will */ -bool DoDistUpgrade(CommandLine &CmdL) -{ - if (CmdL.FileSize() != 1) - return _error->Error(_("The dist-upgrade command takes no arguments")); - - CacheFile Cache; - if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false) - return false; - - c0out << _("Calculating upgrade... ") << flush; - if (pkgDistUpgrade(*Cache) == false) - { - c0out << _("Failed") << endl; - ShowBroken(c1out,Cache,false); - return false; - } - - c0out << _("Done") << endl; - - return InstallPackages(Cache,true); -} - /*}}}*/ // DoDSelectUpgrade - Do an upgrade by following dselects selections /*{{{*/ // --------------------------------------------------------------------- /* Follows dselect's selections */ @@ -411,7 +513,7 @@ bool DoDSelectUpgrade(CommandLine &CmdL) } /* Resolve any problems that dselect created, allupgrade cannot handle - such things. We do so quite agressively too.. */ + such things. We do so quite aggressively too.. */ if (Cache->BrokenCount() != 0) { pkgProblemResolver Fix(Cache); @@ -526,75 +628,68 @@ bool DoDownload(CommandLine &CmdL) CacheFile Cache; if (Cache.ReadOnlyOpen() == false) return false; - + APT::CacheSetHelper helper(c0out); - APT::VersionList verset = APT::VersionList::FromCommandLine(Cache, - CmdL.FileList + 1, APT::VersionList::CANDIDATE, helper); + APT::VersionSet verset = APT::VersionSet::FromCommandLine(Cache, + CmdL.FileList + 1, APT::VersionSet::CANDIDATE, helper); if (verset.empty() == true) return false; + AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet", 0)); pkgAcquire Fetcher; - AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet",0)); - if (_config->FindB("APT::Get::Print-URIs") == false) - Fetcher.Setup(&Stat); + if (Fetcher.Setup(&Stat) == false) + return false; pkgRecords Recs(Cache); pkgSourceList *SrcList = Cache.GetSourceList(); - bool gotAll = true; - for (APT::VersionList::const_iterator Ver = verset.begin(); - Ver != verset.end(); - ++Ver) + // reuse the usual acquire methods for deb files, but don't drop them into + // the usual directories - keep everything in the current directory + std::vector<std::string> storefile(verset.size()); + std::string const cwd = SafeGetCWD(); + _config->Set("Dir::Cache::Archives", cwd); + int i = 0; + for (APT::VersionSet::const_iterator Ver = verset.begin(); + Ver != verset.end(); ++Ver, ++i) { - string descr; - // get the right version - pkgCache::PkgIterator Pkg = Ver.ParentPkg(); - pkgRecords::Parser &rec=Recs.Lookup(Ver.FileList()); - pkgCache::VerFileIterator Vf = Ver.FileList(); - if (Vf.end() == true) - { - _error->Error("Can not find VerFile for %s in version %s", Pkg.FullName().c_str(), Ver.VerStr()); - gotAll = false; - continue; - } - pkgCache::PkgFileIterator F = Vf.File(); - pkgIndexFile *index; - if(SrcList->FindIndex(F, index) == false) - { - _error->Error(_("Can't find a source to download version '%s' of '%s'"), Ver.VerStr(), Pkg.FullName().c_str()); - gotAll = false; - continue; - } - string uri = index->ArchiveURI(rec.FileName()); - strprintf(descr, _("Downloading %s %s"), Pkg.Name(), Ver.VerStr()); - // get the most appropriate hash - HashString hash; - if (rec.SHA512Hash() != "") - hash = HashString("sha512", rec.SHA512Hash()); - else if (rec.SHA256Hash() != "") - hash = HashString("sha256", rec.SHA256Hash()); - else if (rec.SHA1Hash() != "") - hash = HashString("sha1", rec.SHA1Hash()); - else if (rec.MD5Hash() != "") - hash = HashString("md5", rec.MD5Hash()); - // get the file - new pkgAcqFile(&Fetcher, uri, hash.toStr(), (*Ver)->Size, descr, Pkg.Name(), "."); + pkgAcquire::Item *I = new pkgAcqArchive(&Fetcher, SrcList, &Recs, *Ver, storefile[i]); + std::string const filename = cwd + flNotDir(storefile[i]); + storefile[i].assign(filename); + I->DestFile.assign(filename); } - if (gotAll == false) - return false; // Just print out the uris and exit if the --print-uris flag was used if (_config->FindB("APT::Get::Print-URIs") == true) { pkgAcquire::UriIterator I = Fetcher.UriBegin(); for (; I != Fetcher.UriEnd(); ++I) - cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << + cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl; return true; } - return (Fetcher.Run() == pkgAcquire::Continue); + if (_error->PendingError() == true || CheckAuth(Fetcher, false) == false) + return false; + + bool Failed = false; + if (AcquireRun(Fetcher, 0, &Failed, NULL) == false) + return false; + + // copy files in local sources to the current directory + for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); ++I) + { + std::string const filename = cwd + flNotDir((*I)->DestFile); + if ((*I)->Local == true && + filename != (*I)->DestFile && + (*I)->Status == pkgAcquire::Item::StatDone) + { + std::ifstream src((*I)->DestFile.c_str(), std::ios::binary); + std::ofstream dst(filename.c_str(), std::ios::binary); + dst << src.rdbuf(); + } + } + return Failed == false; } /*}}}*/ // DoCheck - Perform the check operation /*{{{*/ @@ -663,7 +758,7 @@ bool DoSource(CommandLine &CmdL) for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++) { string Src; - pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,*Cache); + pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,Cache); if (Last == 0) { delete[] Dsc; @@ -811,27 +906,10 @@ bool DoSource(CommandLine &CmdL) delete[] Dsc; return true; } - - // Run it - if (Fetcher.Run() == pkgAcquire::Failed) - { - delete[] Dsc; - return false; - } - // Print error messages + // Run it bool Failed = false; - for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); ++I) - { - if ((*I)->Status == pkgAcquire::Item::StatDone && - (*I)->Complete == true) - continue; - - fprintf(stderr,_("Failed to fetch %s %s\n"),(*I)->DescURI().c_str(), - (*I)->ErrorText.c_str()); - Failed = true; - } - if (Failed == true) + if (AcquireRun(Fetcher, 0, &Failed, NULL) == false || Failed == true) { delete[] Dsc; return _error->Error(_("Failed to fetch some archives.")); @@ -974,7 +1052,7 @@ bool DoBuildDep(CommandLine &CmdL) for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++) { string Src; - pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,*Cache); + pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,Cache); if (Last == 0) return _error->Error(_("Unable to find a source package for %s"),Src.c_str()); @@ -1428,24 +1506,6 @@ bool DownloadChangelog(CacheFile &CacheFile, pkgAcquire &Fetcher, return _error->Error("changelog download failed"); } /*}}}*/ -// DisplayFileInPager - Display File with pager /*{{{*/ -void DisplayFileInPager(string filename) -{ - pid_t Process = ExecFork(); - if (Process == 0) - { - const char *Args[3]; - Args[0] = "/usr/bin/sensible-pager"; - Args[1] = filename.c_str(); - Args[2] = 0; - execvp(Args[0],(char **)Args); - exit(100); - } - - // Wait for the subprocess - ExecWait(Process, "sensible-pager", false); -} - /*}}}*/ // DoChangelog - Get changelog from the command line /*{{{*/ // --------------------------------------------------------------------- bool DoChangelog(CommandLine &CmdL) @@ -1476,14 +1536,12 @@ bool DoChangelog(CommandLine &CmdL) bool const downOnly = _config->FindB("APT::Get::Download-Only", false); char tmpname[100]; - char* tmpdir = NULL; + const char* tmpdir = NULL; if (downOnly == false) { - const char* const tmpDir = getenv("TMPDIR"); - if (tmpDir != NULL && *tmpDir != '\0') - snprintf(tmpname, sizeof(tmpname), "%s/apt-changelog-XXXXXX", tmpDir); - else - strncpy(tmpname, "/tmp/apt-changelog-XXXXXX", sizeof(tmpname)); + std::string systemTemp = GetTempDir(); + snprintf(tmpname, sizeof(tmpname), "%s/apt-changelog-XXXXXX", + systemTemp.c_str()); tmpdir = mkdtemp(tmpname); if (tmpdir == NULL) return _error->Errno("mkdtemp", "mkdtemp failed"); @@ -1621,15 +1679,6 @@ void SigWinch(int) #endif } /*}}}*/ - -bool DoUpgrade(CommandLine &CmdL) -{ - if (_config->FindB("APT::Get::UpgradeAllowNew", false) == true) - return DoUpgradeWithAllowNewPackages(CmdL); - else - return DoUpgradeNoNewPackages(CmdL); -} - int main(int argc,const char *argv[]) /*{{{*/ { CommandLine::Dispatch Cmds[] = {{"update",&DoUpdate}, @@ -1684,10 +1733,6 @@ int main(int argc,const char *argv[]) /*{{{*/ // see if we are in simulate mode CheckSimulateMode(CmdL); - // Deal with stdout not being a tty - if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1) - _config->Set("quiet","1"); - // Setup the output streams InitOutput(); diff --git a/cmdline/apt-internal-solver.cc b/cmdline/apt-internal-solver.cc index aef7636e9..bf5b8c1fe 100644 --- a/cmdline/apt-internal-solver.cc +++ b/cmdline/apt-internal-solver.cc @@ -19,6 +19,7 @@ #include <apt-pkg/algorithms.h> #include <apt-pkg/fileutl.h> #include <apt-pkg/pkgsystem.h> +#include <apt-pkg/upgrade.h> #include <unistd.h> #include <cstdio> @@ -159,16 +160,16 @@ int main(int argc,const char *argv[]) /*{{{*/ if (upgrade == true) { if (pkgAllUpgrade(CacheFile) == false) { - EDSP::WriteError("ERR_UNSOLVABLE_UPGRADE", "An upgrade error occured", output); + EDSP::WriteError("ERR_UNSOLVABLE_UPGRADE", "An upgrade error occurred", output); return 0; } } else if (distUpgrade == true) { if (pkgDistUpgrade(CacheFile) == false) { - EDSP::WriteError("ERR_UNSOLVABLE_DIST_UPGRADE", "An dist-upgrade error occured", output); + EDSP::WriteError("ERR_UNSOLVABLE_DIST_UPGRADE", "An dist-upgrade error occurred", output); return 0; } } else if (Fix.Resolve() == false) { - EDSP::WriteError("ERR_UNSOLVABLE", "An error occured", output); + EDSP::WriteError("ERR_UNSOLVABLE", "An error occurred", output); return 0; } diff --git a/cmdline/apt-key b/cmdline/apt-key.in index 713a41c07..0774cf4b7 100755..100644 --- a/cmdline/apt-key +++ b/cmdline/apt-key.in @@ -5,37 +5,39 @@ unset GREP_OPTIONS GPG_CMD="gpg --ignore-time-conflict --no-options --no-default-keyring" -# gpg needs a trustdb to function, but it can't be invalid (not even empty) -# so we create a temporary directory to store our fresh readable trustdb in -TRUSTDBDIR="$(mktemp -d)" -CURRENTTRAP="${CURRENTTRAP} rm -rf '${TRUSTDBDIR}';" +# gpg needs (in different versions more or less) files to function correctly, +# so we give it its own homedir and generate some valid content for it +GPGHOMEDIR="$(mktemp -d)" +CURRENTTRAP="${CURRENTTRAP} rm -rf '${GPGHOMEDIR}';" trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM -chmod 700 "$TRUSTDBDIR" -# We also don't use a secret keyring, of course, but gpg panics and +chmod 700 "$GPGHOMEDIR" +# We don't use a secret keyring, of course, but gpg panics and # implodes if there isn't one available - and writeable for imports -SECRETKEYRING="${TRUSTDBDIR}/secring.gpg" +SECRETKEYRING="${GPGHOMEDIR}/secring.gpg" touch $SECRETKEYRING -GPG_CMD="$GPG_CMD --secret-keyring $SECRETKEYRING" -GPG_CMD="$GPG_CMD --trustdb-name ${TRUSTDBDIR}/trustdb.gpg" - -# now create the trustdb with an (empty) dummy keyring -$GPG_CMD --quiet --check-trustdb --keyring $SECRETKEYRING -# and make sure that gpg isn't trying to update the file +GPG_CMD="$GPG_CMD --homedir $GPGHOMEDIR" +# create the trustdb with an (empty) dummy keyring +# older gpgs required it, newer gpgs even warn that it isn't needed, +# but require it nonetheless for some commands, so we just play safe +# here for the foreseeable future and create a dummy one +$GPG_CMD --quiet --check-trustdb --keyring $SECRETKEYRING >/dev/null 2>&1 +# tell gpg that it shouldn't try to maintain a trustdb file GPG_CMD="$GPG_CMD --no-auto-check-trustdb --trust-model always" GPG="$GPG_CMD" -MASTER_KEYRING="" -#MASTER_KEYRING=/usr/share/keyrings/debian-master-keyring.gpg -eval $(apt-config shell MASTER_KEYRING APT::Key::MasterKeyring) -ARCHIVE_KEYRING_URI="" -#ARCHIVE_KEYRING_URI=http://ftp.debian.org/debian/debian-archive-keyring.gpg -eval $(apt-config shell ARCHIVE_KEYRING_URI APT::Key::ArchiveKeyringURI) +APT_DIR="/" +eval $(apt-config shell APT_DIR Dir) -ARCHIVE_KEYRING=/usr/share/keyrings/debian-archive-keyring.gpg +MASTER_KEYRING='&keyring-master-filename;' +eval $(apt-config shell MASTER_KEYRING APT::Key::MasterKeyring) +ARCHIVE_KEYRING='&keyring-filename;' eval $(apt-config shell ARCHIVE_KEYRING APT::Key::ArchiveKeyring) -REMOVED_KEYS=/usr/share/keyrings/debian-archive-removed-keys.gpg +REMOVED_KEYS='&keyring-removed-filename;' eval $(apt-config shell REMOVED_KEYS APT::Key::RemovedKeys) +ARCHIVE_KEYRING_URI='&keyring-uri;' +eval $(apt-config shell ARCHIVE_KEYRING_URI APT::Key::ArchiveKeyringURI) +TMP_KEYRING=${APT_DIR}/var/lib/apt/keyrings/maybe-import-keyring.gpg requires_root() { if [ "$(id -u)" -ne 0 ]; then @@ -57,7 +59,7 @@ init_keyring() { add_keys_with_verify_against_master_keyring() { ADD_KEYRING=$1 MASTER=$2 - + if [ ! -f "$ADD_KEYRING" ]; then echo "ERROR: '$ADD_KEYRING' not found" return @@ -72,12 +74,28 @@ add_keys_with_verify_against_master_keyring() { # all keys that are exported must have a valid signature # from a key in the $distro-master-keyring add_keys=`$GPG_CMD --keyring $ADD_KEYRING --with-colons --list-keys | grep ^pub | cut -d: -f5` + all_add_keys=`$GPG_CMD --keyring $ADD_KEYRING --with-colons --list-keys | grep ^[ps]ub | cut -d: -f5` master_keys=`$GPG_CMD --keyring $MASTER --with-colons --list-keys | grep ^pub | cut -d: -f5` + + # ensure there are no colisions LP: #857472 + for all_add_key in $all_add_keys; do + for master_key in $master_keys; do + if [ "$all_add_key" = "$master_key" ]; then + echo >&2 "Keyid collision for '$all_add_key' detected, operation aborted" + return 1 + fi + done + done + for add_key in $add_keys; do - ADDED=0 + # export the add keyring one-by-one + rm -f $TMP_KEYRING + $GPG_CMD --keyring $ADD_KEYRING --output $TMP_KEYRING --export $add_key + # check if signed with the master key and only add in this case + ADDED=0 for master_key in $master_keys; do - if $GPG_CMD --keyring $ADD_KEYRING --list-sigs --with-colons $add_key | grep ^sig | cut -d: -f5 | grep -q $master_key; then - $GPG_CMD --quiet --batch --keyring $ADD_KEYRING --export $add_key | $GPG --import + if $GPG_CMD --keyring $MASTER --keyring $TMP_KEYRING --check-sigs --with-colons $add_key | grep '^sig:!:' | cut -d: -f5 | grep -q $master_key; then + $GPG --import $TMP_KEYRING ADDED=1 fi done @@ -85,12 +103,20 @@ add_keys_with_verify_against_master_keyring() { echo >&2 "Key '$add_key' not added. It is not signed with a master key" fi done + rm -f $TMP_KEYRING } # update the current archive signing keyring from a network URI # the archive-keyring keys needs to be signed with the master key # (otherwise it does not make sense from a security POV) net_update() { + # Disabled for now as code is insecure (LP: #1013639 (and 857472, 1013128)) + APT_KEY_NET_UPDATE_ENABLED="" + eval $(apt-config shell APT_KEY_NET_UPDATE_ENABLED APT::Key::Net-Update-Enabled) + if [ -z "$APT_KEY_NET_UPDATE_ENABLED" ]; then + exit 1 + fi + if [ -z "$ARCHIVE_KEYRING_URI" ]; then echo >&2 "ERROR: Your distribution is not supported in net-update as no uri for the archive-keyring is set" exit 1 @@ -102,15 +128,15 @@ net_update() { echo >&2 "ERROR: an installed wget is required for a network-based update" exit 1 fi - if [ ! -d /var/lib/apt/keyrings ]; then - mkdir -p /var/lib/apt/keyrings + if [ ! -d ${APT_DIR}/var/lib/apt/keyrings ]; then + mkdir -p ${APT_DIR}/var/lib/apt/keyrings fi - keyring=/var/lib/apt/keyrings/$(basename $ARCHIVE_KEYRING) + keyring=${APT_DIR}/var/lib/apt/keyrings/$(basename $ARCHIVE_KEYRING_URI) old_mtime=0 if [ -e $keyring ]; then old_mtime=$(stat -c %Y $keyring) fi - (cd /var/lib/apt/keyrings; wget -q -N $ARCHIVE_KEYRING_URI) + (cd ${APT_DIR}/var/lib/apt/keyrings; wget --timeout=90 -q -N $ARCHIVE_KEYRING_URI) if [ ! -e $keyring ]; then return fi @@ -124,7 +150,7 @@ net_update() { update() { if [ ! -f $ARCHIVE_KEYRING ]; then echo >&2 "ERROR: Can't find the archive-keyring" - echo >&2 "Is the debian-archive-keyring package installed?" + echo >&2 "Is the &keyring-package; package installed?" exit 1 fi requires_root @@ -161,7 +187,7 @@ remove_key_from_keyring() { echo >&2 "Key ${2} is in keyring ${1}, but can't be removed as it is read only." return fi - # check if it is the only key in the keyring and if so remove the keyring alltogether + # check if it is the only key in the keyring and if so remove the keyring altogether if [ '1' = "$($GPG --with-colons --list-keys | grep "^pub:[^:]*:[^:]*:[^:]*:[0-9A-F]\+:" | wc -l)" ]; then mv -f "$1" "${1}~" # behave like gpg return diff --git a/cmdline/apt-mark.cc b/cmdline/apt-mark.cc index eb3410be1..d3a3a780b 100644 --- a/cmdline/apt-mark.cc +++ b/cmdline/apt-mark.cc @@ -209,7 +209,7 @@ bool DoHold(CommandLine &CmdL) dup2(nullfd, STDIN_FILENO); dup2(nullfd, STDOUT_FILENO); dup2(nullfd, STDERR_FILENO); - if (chrootDir != "/" && chroot(chrootDir.c_str()) != 0) + if (chrootDir != "/" && chroot(chrootDir.c_str()) != 0 && chdir("/") != 0) _error->WarningE("getArchitecture", "Couldn't chroot into %s for dpkg --assert-multi-arch", chrootDir.c_str()); execvp(Args[0], (char**) &Args[0]); _error->WarningE("dpkgGo", "Can't detect if dpkg supports multi-arch!"); @@ -279,7 +279,7 @@ bool DoHold(CommandLine &CmdL) { close(external[1]); std::string const chrootDir = _config->FindDir("DPkg::Chroot-Directory"); - if (chrootDir != "/" && chroot(chrootDir.c_str()) != 0) + if (chrootDir != "/" && chroot(chrootDir.c_str()) != 0 && chdir("/") != 0) _error->WarningE("getArchitecture", "Couldn't chroot into %s for dpkg --set-selections", chrootDir.c_str()); int const nullfd = open("/dev/null", O_RDONLY); dup2(external[0], STDIN_FILENO); @@ -386,6 +386,11 @@ bool ShowHelp(CommandLine &CmdL) "Commands:\n" " auto - Mark the given packages as automatically installed\n" " manual - Mark the given packages as manually installed\n" + " hold - Mark a package as held back\n" + " unhold - Unset a package set as held back\n" + " showauto - Print the list of automatically installed packages\n" + " showmanual - Print the list of manually installed packages\n" + " showhold - Print the list of package on hold\n" "\n" "Options:\n" " -h This help text.\n" diff --git a/cmdline/apt.cc b/cmdline/apt.cc index e30967ec2..7ef9060aa 100644 --- a/cmdline/apt.cc +++ b/cmdline/apt.cc @@ -41,6 +41,7 @@ #include <apt-pkg/pkgsystem.h> #include <apt-pkg/indexfile.h> #include <apt-pkg/metaindex.h> +#include <apt-pkg/hashes.h> #include <apti18n.h> @@ -54,8 +55,12 @@ #include <apt-private/private-upgrade.h> #include <apt-private/private-show.h> #include <apt-private/private-main.h> +#include <apt-private/private-utils.h> +#include <apt-private/private-sources.h> /*}}}*/ + + bool ShowHelp(CommandLine &CmdL) { ioprintf(c1out,_("%s %s for %s compiled on %s %s\n"),PACKAGE,PACKAGE_VERSION, @@ -66,14 +71,20 @@ bool ShowHelp(CommandLine &CmdL) _("Usage: apt [options] command\n" "\n" "CLI for apt.\n" - "Commands: \n" + "Basic commands: \n" " list - list packages based on package names\n" " search - search in package descriptions\n" " show - show package details\n" "\n" " update - update list of available packages\n" + "\n" " install - install packages\n" - " upgrade - upgrade the systems packages\n" + " remove - remove packages\n" + "\n" + " upgrade - upgrade the system by installing/upgrading packages\n" + " full-upgrade - upgrade the system by removing/installing/upgrading packages\n" + "\n" + " edit-sources - edit the source information file\n" ); return true; @@ -81,14 +92,27 @@ bool ShowHelp(CommandLine &CmdL) int main(int argc, const char *argv[]) /*{{{*/ { - CommandLine::Dispatch Cmds[] = {{"list",&List}, + CommandLine::Dispatch Cmds[] = { + // query + {"list",&List}, {"search", &FullTextSearch}, {"show", &APT::Cmd::ShowPackage}, - // needs root + + // package stuff {"install",&DoInstall}, {"remove", &DoInstall}, + {"purge", &DoInstall}, + + // system wide stuff {"update",&DoUpdate}, - {"upgrade",&DoUpgradeWithAllowNewPackages}, + {"upgrade",&DoUpgrade}, + {"full-upgrade",&DoDistUpgrade}, + // for compat with muscle memory + {"dist-upgrade",&DoDistUpgrade}, + + // misc + {"edit-sources",&EditSources}, + // helper {"moo",&DoMoo}, {"help",&ShowHelp}, @@ -96,17 +120,6 @@ int main(int argc, const char *argv[]) /*{{{*/ std::vector<CommandLine::Args> Args = getCommandArgs("apt", CommandLine::GetCommand(Cmds, argc, argv)); - if(!isatty(1)) - { - std::cerr << std::endl - << "WARNING WARNING " - << argv[0] - << " is *NOT* intended for scripts " - << "use at your own peril^Wrisk" - << std::endl - << std::endl; - } - InitOutput(); // Set up gettext support @@ -119,9 +132,10 @@ int main(int argc, const char *argv[]) /*{{{*/ return 100; } - // FIXME: move into a new libprivate/private-install.cc:Install() - _config->Set("DPkgPM::Progress", "1"); - _config->Set("Apt::Color", "1"); + // some different defaults + _config->CndSet("DPkgPM::Progress", "1"); + _config->CndSet("Apt::Color", "1"); + _config->CndSet("APT::Get::Upgrade-Allow-New", true); // Parse the command line and initialize the package library CommandLine CmdL(Args.data(), _config); @@ -132,6 +146,17 @@ int main(int argc, const char *argv[]) /*{{{*/ return 100; } + if(!isatty(STDOUT_FILENO) && + _config->FindB("Apt::Cmd::Disable-Script-Warning", false) == false) + { + std::cerr << std::endl + << "WARNING: " << argv[0] << " " + << "does not have a stable CLI interface yet. " + << "Use with caution in scripts." + << std::endl + << std::endl; + } + // See if the help should be shown if (_config->FindB("help") == true || _config->FindB("version") == true || diff --git a/cmdline/makefile b/cmdline/makefile index e77ad5669..f89192e10 100644 --- a/cmdline/makefile +++ b/cmdline/makefile @@ -40,12 +40,6 @@ LIB_MAKES = apt-pkg/makefile SOURCE = apt-cdrom.cc include $(PROGRAM_H) -# The apt-key program -SOURCE=apt-key -TO=$(BIN) -TARGET=program -include $(COPY_H) - # The apt-mark program PROGRAM=apt-mark SLIBS = -lapt-pkg -lapt-private $(INTLLIBS) @@ -91,3 +85,22 @@ SLIBS = -lapt-pkg $(INTLLIBS) LIB_MAKES = apt-pkg/makefile SOURCE = apt-dump-solver.cc include $(PROGRAM_H) + +# The apt-key program +apt-key: apt-key.in + sed -e "s#&keyring-filename;#$(shell ../vendor/getinfo keyring-filename)#" \ + -e "s#&keyring-removed-filename;#$(shell ../vendor/getinfo keyring-removed-filename)#" \ + -e "s#&keyring-master-filename;#$(shell ../vendor/getinfo keyring-master-filename)#" \ + -e "s#&keyring-uri;#$(shell ../vendor/getinfo keyring-uri)#" \ + -e "s#&keyring-package;#$(shell ../vendor/getinfo keyring-package)#" $< > $@ + chmod 755 $@ + +SOURCE=apt-key +TO=$(BIN) +TARGET=program +include $(COPY_H) + +clean: clean/apt-key + +clean/apt-key: + rm -f apt-key |