summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/acquire-item.cc203
-rw-r--r--apt-pkg/acquire-item.h26
-rw-r--r--apt-pkg/acquire-method.cc21
-rw-r--r--apt-pkg/acquire-method.h15
-rw-r--r--apt-pkg/algorithms.cc3
-rw-r--r--apt-pkg/aptconfiguration.cc90
-rw-r--r--apt-pkg/aptconfiguration.h46
-rw-r--r--apt-pkg/contrib/configuration.cc27
-rw-r--r--apt-pkg/contrib/configuration.h3
-rw-r--r--apt-pkg/contrib/fileutl.cc2
-rw-r--r--apt-pkg/contrib/strutl.cc19
-rw-r--r--apt-pkg/deb/debsystem.cc3
-rw-r--r--apt-pkg/deb/dpkgpm.cc341
-rw-r--r--apt-pkg/deb/dpkgpm.h7
-rw-r--r--apt-pkg/depcache.cc4
-rw-r--r--apt-pkg/indexcopy.cc3
-rw-r--r--apt-pkg/init.cc5
-rw-r--r--apt-pkg/init.h2
-rw-r--r--apt-pkg/makefile7
-rw-r--r--apt-pkg/orderlist.cc63
-rw-r--r--apt-pkg/packagemanager.cc40
-rw-r--r--apt-pkg/pkgrecords.cc4
-rw-r--r--apt-pkg/tagfile.cc2
23 files changed, 736 insertions, 200 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc
index 39ae327cb..171dafa24 100644
--- a/apt-pkg/acquire-item.cc
+++ b/apt-pkg/acquire-item.cc
@@ -15,6 +15,7 @@
// Include Files /*{{{*/
#include <apt-pkg/acquire-item.h>
#include <apt-pkg/configuration.h>
+#include <apt-pkg/aptconfiguration.h>
#include <apt-pkg/sourcelist.h>
#include <apt-pkg/vendorlist.h>
#include <apt-pkg/error.h>
@@ -63,6 +64,7 @@ void pkgAcquire::Item::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
{
Status = StatIdle;
ErrorText = LookupTag(Message,"Message");
+ UsedMirror = LookupTag(Message,"UsedMirror");
if (QueueCounter <= 1)
{
/* This indicates that the file is not available right now but might
@@ -75,10 +77,17 @@ void pkgAcquire::Item::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
Dequeue();
return;
}
-
+
Status = StatError;
Dequeue();
}
+
+ // report mirror failure back to LP if we actually use a mirror
+ string FailReason = LookupTag(Message, "FailReason");
+ if(FailReason.size() != 0)
+ ReportMirrorFailure(FailReason);
+ else
+ ReportMirrorFailure(ErrorText);
}
/*}}}*/
// Acquire::Item::Start - Item has begun to download /*{{{*/
@@ -100,7 +109,7 @@ void pkgAcquire::Item::Done(string Message,unsigned long Size,string Hash,
{
// We just downloaded something..
string FileName = LookupTag(Message,"Filename");
- // we only inform the Log class if it was actually not a local thing
+ UsedMirror = LookupTag(Message,"UsedMirror");
if (Complete == false && !Local && FileName == DestFile)
{
if (Owner->Log != 0)
@@ -109,7 +118,6 @@ void pkgAcquire::Item::Done(string Message,unsigned long Size,string Hash,
if (FileSize == 0)
FileSize= Size;
-
Status = StatDone;
ErrorText = string();
Owner->Dequeue(this);
@@ -131,6 +139,49 @@ void pkgAcquire::Item::Rename(string From,string To)
}
}
/*}}}*/
+
+void pkgAcquire::Item::ReportMirrorFailure(string FailCode)
+{
+ // we only act if a mirror was used at all
+ if(UsedMirror.empty())
+ return;
+#if 0
+ std::cerr << "\nReportMirrorFailure: "
+ << UsedMirror
+ << " Uri: " << DescURI()
+ << " FailCode: "
+ << FailCode << std::endl;
+#endif
+ const char *Args[40];
+ unsigned int i = 0;
+ string report = _config->Find("Methods::Mirror::ProblemReporting",
+ "/usr/lib/apt/apt-report-mirror-failure");
+ if(!FileExists(report))
+ return;
+ Args[i++] = report.c_str();
+ Args[i++] = UsedMirror.c_str();
+ Args[i++] = DescURI().c_str();
+ Args[i++] = FailCode.c_str();
+ Args[i++] = NULL;
+ pid_t pid = ExecFork();
+ if(pid < 0)
+ {
+ _error->Error("ReportMirrorFailure Fork failed");
+ return;
+ }
+ else if(pid == 0)
+ {
+ execvp(Args[0], (char**)Args);
+ std::cerr << "Could not exec " << Args[0] << std::endl;
+ _exit(100);
+ }
+ if(!ExecWait(pid, "report-mirror-failure"))
+ {
+ _error->Warning("Couldn't report problem to '%s'",
+ _config->Find("Methods::Mirror::ProblemReporting").c_str());
+ }
+}
+
// AcqDiffIndex::AcqDiffIndex - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* Get the DiffIndex file first and see if there are patches availabe
@@ -551,13 +602,14 @@ pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,
if(comprExt.empty())
{
// autoselect the compression method
- if(FileExists("/bin/bzip2"))
- CompressionExtension = ".bz2";
- else
- CompressionExtension = ".gz";
- } else {
- CompressionExtension = (comprExt == "plain" ? "" : comprExt);
+ std::vector<std::string> types = APT::Configuration::getCompressionTypes();
+ if (types.empty() == true)
+ comprExt = "plain";
+ else
+ comprExt = "." + types[0];
}
+ CompressionExtension = ((comprExt == "plain" || comprExt == ".") ? "" : comprExt);
+
Desc.URI = URI + CompressionExtension;
Desc.Description = URIDesc;
@@ -578,30 +630,32 @@ string pkgAcqIndex::Custom600Headers()
struct stat Buf;
if (stat(Final.c_str(),&Buf) != 0)
return "\nIndex-File: true";
-
return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
}
/*}}}*/
void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*{{{*/
{
- bool descChanged = false;
- // no .bz2 found, retry with .gz
- if(Desc.URI.substr(Desc.URI.size()-3) == "bz2") {
- Desc.URI = Desc.URI.substr(0,Desc.URI.size()-3) + "gz";
-
- new pkgAcqIndex(Owner, RealURI, Desc.Description,Desc.ShortDesc,
- ExpectedHash, string(".gz"));
- descChanged = true;
- }
- // no .gz found, retry with uncompressed
- else if(Desc.URI.substr(Desc.URI.size()-2) == "gz") {
- Desc.URI = Desc.URI.substr(0,Desc.URI.size()-2);
+ std::vector<std::string> types = APT::Configuration::getCompressionTypes();
- new pkgAcqIndex(Owner, RealURI, Desc.Description,Desc.ShortDesc,
- ExpectedHash, string("plain"));
- descChanged = true;
- }
- if (descChanged) {
+ for (std::vector<std::string>::const_iterator t = types.begin();
+ t != types.end(); t++)
+ {
+ // jump over all already tried compression types
+ const unsigned int nameLen = Desc.URI.size() - (*t).size();
+ if(Desc.URI.substr(nameLen) != *t)
+ continue;
+
+ // we want to try it with the next extension (and make sure to
+ // not skip over the end)
+ t++;
+ if (t == types.end())
+ break;
+
+ // queue new download
+ Desc.URI = Desc.URI.substr(0, nameLen) + *t;
+ new pkgAcqIndex(Owner, RealURI, Desc.Description, Desc.ShortDesc,
+ ExpectedHash, string(".").append(*t));
+
Status = StatDone;
Complete = false;
Dequeue();
@@ -643,6 +697,7 @@ void pkgAcqIndex::Done(string Message,unsigned long Size,string Hash,
Status = StatAuthError;
ErrorText = _("Hash Sum mismatch");
Rename(DestFile,DestFile + ".FAILED");
+ ReportMirrorFailure("HashChecksumFailure");
return;
}
// Done, move it into position
@@ -698,11 +753,11 @@ void pkgAcqIndex::Done(string Message,unsigned long Size,string Hash,
Local = true;
string compExt = flExtension(flNotDir(URI(Desc.URI).Path));
- const char *decompProg;
- if(compExt == "bz2")
- decompProg = "bzip2";
- else if(compExt == "gz")
- decompProg = "gzip";
+ string decompProg;
+
+ // get the binary name for your used compression type
+ decompProg = _config->Find(string("Acquire::CompressionTypes::").append(compExt),"");
+ if(decompProg.empty() == false);
// flExtensions returns the full name if no extension is found
// this is why we have this complicated compare operation here
// FIMXE: add a new flJustExtension() that return "" if no
@@ -717,9 +772,9 @@ void pkgAcqIndex::Done(string Message,unsigned long Size,string Hash,
Decompression = true;
DestFile += ".decomp";
- Desc.URI = string(decompProg) + ":" + FileName;
+ Desc.URI = decompProg + ":" + FileName;
QueueURI(Desc);
- Mode = decompProg;
+ Mode = decompProg.c_str();
}
/*}}}*/
// AcqIndexTrans::pkgAcqIndexTrans - Constructor /*{{{*/
@@ -833,8 +888,9 @@ void pkgAcqMetaSig::Done(string Message,unsigned long Size,string MD5,
Rename(LastGoodSig, DestFile);
// queue a pkgAcqMetaIndex to be verified against the sig we just retrieved
- new pkgAcqMetaIndex(Owner, MetaIndexURI, MetaIndexURIDesc, MetaIndexShortDesc,
- DestFile, IndexTargets, MetaIndexParser);
+ new pkgAcqMetaIndex(Owner, MetaIndexURI, MetaIndexURIDesc,
+ MetaIndexShortDesc, DestFile, IndexTargets,
+ MetaIndexParser);
}
/*}}}*/
@@ -847,7 +903,7 @@ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/
{
Item::Failed(Message,Cnf);
// move the sigfile back on transient network failures
- if(FileExists(DestFile))
+ if(FileExists(LastGoodSig))
Rename(LastGoodSig,Final);
// set the status back to , Item::Failed likes to reset it
@@ -922,6 +978,15 @@ void pkgAcqMetaIndex::Done(string Message,unsigned long Size,string Hash, /*{{{*
if (AuthPass == true)
{
AuthDone(Message);
+
+ // all cool, move Release file into place
+ Complete = true;
+
+ string FinalFile = _config->FindDir("Dir::State::lists");
+ FinalFile += URItoFileName(RealURI);
+ Rename(DestFile,FinalFile);
+ chmod(FinalFile.c_str(),0644);
+ DestFile = FinalFile;
}
else
{
@@ -973,22 +1038,15 @@ void pkgAcqMetaIndex::RetrievalDone(string Message) /*{{{*/
return;
}
- // see if the download was a IMSHit
+ // make sure to verify against the right file on I-M-S hit
IMSHit = StringToBool(LookupTag(Message,"IMS-Hit"),false);
+ if(IMSHit)
+ {
+ string FinalFile = _config->FindDir("Dir::State::lists");
+ FinalFile += URItoFileName(RealURI);
+ DestFile = FinalFile;
+ }
Complete = true;
-
- string FinalFile = _config->FindDir("Dir::State::lists");
- FinalFile += URItoFileName(RealURI);
-
- // If we get a IMS hit we can remove the empty file in partial
- // othersie we move the file in place
- if (IMSHit)
- unlink(DestFile.c_str());
- else
- Rename(DestFile,FinalFile);
-
- chmod(FinalFile.c_str(),0644);
- DestFile = FinalFile;
}
/*}}}*/
void pkgAcqMetaIndex::AuthDone(string Message) /*{{{*/
@@ -1018,7 +1076,6 @@ void pkgAcqMetaIndex::AuthDone(string Message) /*{{{*/
QueueIndexes(true);
// Done, move signature file into position
-
string VerifiedSigFile = _config->FindDir("Dir::State::lists") +
URItoFileName(RealURI) + ".gpg";
Rename(SigFile,VerifiedSigFile);
@@ -1059,7 +1116,7 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify) /*{{{*/
// Queue Packages file (either diff or full packages files, depending
// on the users option)
- if(_config->FindB("Acquire::PDiffs",true) == true)
+ if(_config->FindB("Acquire::PDiffs",false) == true)
new pkgAcqDiffIndex(Owner, (*Target)->URI, (*Target)->Description,
(*Target)->ShortDesc, ExpectedIndexHash);
else
@@ -1162,30 +1219,30 @@ void pkgAcqMetaIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
{
if (AuthPass == true)
{
- // if we fail the authentication but got the file via a IMS-Hit
- // this means that the file wasn't downloaded and that it might be
- // just stale (server problem, proxy etc). we delete what we have
- // queue it again without i-m-s
- // alternatively we could just unlink the file and let the user try again
- if (IMSHit)
+ // gpgv method failed, if we have a good signature
+ string LastGoodSigFile = _config->FindDir("Dir::State::lists") +
+ "partial/" + URItoFileName(RealURI) + ".gpg.reverify";
+ if(FileExists(LastGoodSigFile))
{
- Complete = false;
- Local = false;
- AuthPass = false;
- unlink(DestFile.c_str());
-
- DestFile = _config->FindDir("Dir::State::lists") + "partial/";
- DestFile += URItoFileName(RealURI);
- Desc.URI = RealURI;
- QueueURI(Desc);
+ string VerifiedSigFile = _config->FindDir("Dir::State::lists") +
+ URItoFileName(RealURI) + ".gpg";
+ Rename(LastGoodSigFile,VerifiedSigFile);
+ Status = StatTransientNetworkError;
+ _error->Warning(_("A error occurred during the signature "
+ "verification. The repository is not updated "
+ "and the previous index files will be used."
+ "GPG error: %s: %s\n"),
+ Desc.Description.c_str(),
+ LookupTag(Message,"Message").c_str());
+ RunScripts("APT::Update::Auth-Failure");
return;
+ } else {
+ _error->Warning(_("GPG error: %s: %s"),
+ Desc.Description.c_str(),
+ LookupTag(Message,"Message").c_str());
}
-
// gpgv method failed
- _error->Warning("GPG error: %s: %s",
- Desc.Description.c_str(),
- LookupTag(Message,"Message").c_str());
-
+ ReportMirrorFailure("GPGFailure");
}
// No Release file was present, or verification failed, so fall
diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h
index 36a926a0f..06fcffc73 100644
--- a/apt-pkg/acquire-item.h
+++ b/apt-pkg/acquire-item.h
@@ -142,6 +142,7 @@ class pkgAcquire::Item
* download progress indicator's overall statistics.
*/
bool Local;
+ string UsedMirror;
/** \brief The number of fetch queues into which this item has been
* inserted.
@@ -242,6 +243,17 @@ class pkgAcquire::Item
/** \return \b true if this object is being fetched from a trusted source. */
virtual bool IsTrusted() {return false;};
+
+ // report mirror problems
+ /** \brief Report mirror problem
+ *
+ * This allows reporting mirror failures back to a centralized
+ * server. The apt-report-mirror-failure script is called for this
+ *
+ * \param FailCode A short failure string that is send
+ */
+ void ReportMirrorFailure(string FailCode);
+
/** \brief Initialize an item.
*
@@ -540,10 +552,13 @@ class pkgAcqIndex : public pkgAcquire::Item
*
* \param compressExt The compression-related extension with which
* this index file should be downloaded, or "" to autodetect
- * (".bz2" is used if bzip2 is installed, ".gz" otherwise).
+ * Compression types can be set with config Acquire::CompressionTypes,
+ * default is ".lzma" or ".bz2" (if the needed binaries are present)
+ * fallback is ".gz" or none.
*/
pkgAcqIndex(pkgAcquire *Owner,string URI,string URIDesc,
- string ShortDesc, HashString ExpectedHash, string compressExt="");
+ string ShortDesc, HashString ExpectedHash,
+ string compressExt="");
};
/*}}}*/
/** \brief An acquire item that is responsible for fetching a {{{
@@ -569,12 +584,6 @@ class pkgAcqIndexTrans : public pkgAcqIndex
* \param URIDesc A "URI-style" description of this index file.
*
* \param ShortDesc A brief description of this index file.
- *
- * \param ExpectedHash The expected hashsum of this index file.
- *
- * \param compressExt The compression-related extension with which
- * this index file should be downloaded, or "" to autodetect
- * (".bz2" is used if bzip2 is installed, ".gz" otherwise).
*/
pkgAcqIndexTrans(pkgAcquire *Owner,string URI,string URIDesc,
string ShortDesc);
@@ -612,7 +621,6 @@ class pkgAcqMetaSig : public pkgAcquire::Item
/** \brief The last good signature file */
string LastGoodSig;
-
/** \brief The fetch request that is currently being processed. */
pkgAcquire::ItemDesc Desc;
diff --git a/apt-pkg/acquire-method.cc b/apt-pkg/acquire-method.cc
index fe066741c..3008c8d1a 100644
--- a/apt-pkg/acquire-method.cc
+++ b/apt-pkg/acquire-method.cc
@@ -96,12 +96,11 @@ void pkgAcqMethod::Fail(string Err,bool Transient)
}
char S[1024];
+ char *End = S;
if (Queue != 0)
{
- snprintf(S,sizeof(S)-50,"400 URI Failure\nURI: %s\n"
- "Message: %s %s\n",Queue->Uri.c_str(),Err.c_str(),
- FailExtra.c_str());
-
+ End += snprintf(S,sizeof(S)-50,"400 URI Failure\nURI: %s\n"
+ "Message: %s %s\n",Queue->Uri.c_str(), Err.c_str(), IP.c_str());
// Dequeue
FetchItem *Tmp = Queue;
Queue = Queue->Next;
@@ -110,10 +109,14 @@ void pkgAcqMethod::Fail(string Err,bool Transient)
QueueBack = Queue;
}
else
- snprintf(S,sizeof(S)-50,"400 URI Failure\nURI: <UNKNOWN>\n"
- "Message: %s %s\n",Err.c_str(),
- FailExtra.c_str());
-
+ {
+ End += snprintf(S,sizeof(S)-50,"400 URI Failure\nURI: <UNKNOWN>\n"
+ "Message: %s\n",Err.c_str());
+ }
+ if(FailReason.empty() == false)
+ End += snprintf(End,sizeof(S)-50 - (End - S),"FailReason: %s\n",FailReason.c_str());
+ if (UsedMirror.empty() == false)
+ End += snprintf(End,sizeof(S)-50 - (End - S),"UsedMirror: %s\n",UsedMirror.c_str());
// Set the transient flag
if (Transient == true)
strcat(S,"Transient-Failure: true\n\n");
@@ -184,6 +187,8 @@ void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt)
End += snprintf(End,sizeof(S)-50 - (End - S),"SHA1-Hash: %s\n",Res.SHA1Sum.c_str());
if (Res.SHA256Sum.empty() == false)
End += snprintf(End,sizeof(S)-50 - (End - S),"SHA256-Hash: %s\n",Res.SHA256Sum.c_str());
+ if (UsedMirror.empty() == false)
+ End += snprintf(End,sizeof(S)-50 - (End - S),"UsedMirror: %s\n",UsedMirror.c_str());
if (Res.GPGVOutput.size() > 0)
End += snprintf(End,sizeof(S)-50 - (End - S),"GPGVOutput:\n");
for (vector<string>::iterator I = Res.GPGVOutput.begin();
diff --git a/apt-pkg/acquire-method.h b/apt-pkg/acquire-method.h
index fab77e664..99a4605b1 100644
--- a/apt-pkg/acquire-method.h
+++ b/apt-pkg/acquire-method.h
@@ -59,7 +59,9 @@ class pkgAcqMethod
vector<string> Messages;
FetchItem *Queue;
FetchItem *QueueBack;
- string FailExtra;
+ string FailReason;
+ string UsedMirror;
+ string IP;
// Handlers for messages
virtual bool Configuration(string Message);
@@ -68,14 +70,14 @@ class pkgAcqMethod
// Outgoing messages
void Fail(bool Transient = false);
inline void Fail(const char *Why, bool Transient = false) {Fail(string(Why),Transient);};
- void Fail(string Why, bool Transient = false);
- void URIStart(FetchResult &Res);
- void URIDone(FetchResult &Res,FetchResult *Alt = 0);
+ virtual void Fail(string Why, bool Transient = false);
+ virtual void URIStart(FetchResult &Res);
+ virtual void URIDone(FetchResult &Res,FetchResult *Alt = 0);
+
bool MediaFail(string Required,string Drive);
virtual void Exit() {};
public:
-
enum CnfFlags {SingleInstance = (1<<0),
Pipeline = (1<<1), SendConfig = (1<<2),
LocalOnly = (1<<3), NeedsCleanup = (1<<4),
@@ -87,7 +89,8 @@ class pkgAcqMethod
void Redirect(const string &NewURI);
int Run(bool Single = false);
- inline void SetFailExtraMsg(string Msg) {FailExtra = Msg;};
+ inline void SetFailReason(string Msg) {FailReason = Msg;};
+ inline void SetIP(string aIP) {IP = aIP;};
pkgAcqMethod(const char *Ver,unsigned long Flags = 0);
virtual ~pkgAcqMethod() {};
diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc
index 34da745de..a3963d546 100644
--- a/apt-pkg/algorithms.cc
+++ b/apt-pkg/algorithms.cc
@@ -1140,8 +1140,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
return _error->Error(_("Unable to correct problems, you have held broken packages."));
}
- // set the auto-flags (mvo: I'm not sure if we _really_ need this, but
- // I didn't managed
+ // set the auto-flags (mvo: I'm not sure if we _really_ need this)
pkgCache::PkgIterator I = Cache.PkgBegin();
for (;I.end() != true; I++) {
if (Cache[I].NewInstall() && !(Flags[I->ID] & PreInstalled)) {
diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc
new file mode 100644
index 000000000..45ae9bed5
--- /dev/null
+++ b/apt-pkg/aptconfiguration.cc
@@ -0,0 +1,90 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+/* ######################################################################
+
+ Provide access methods to various configuration settings,
+ setup defaults and returns validate settings.
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include <apt-pkg/fileutl.h>
+#include <apt-pkg/aptconfiguration.h>
+#include <apt-pkg/configuration.h>
+
+#include <vector>
+#include <string>
+#include <algorithm>
+ /*}}}*/
+namespace APT {
+// getCompressionTypes - Return Vector of usbale compressiontypes /*{{{*/
+// ---------------------------------------------------------------------
+/* return a vector of compression types in the prefered order. */
+std::vector<std::string>
+const Configuration::getCompressionTypes(bool const &Cached) {
+ static std::vector<std::string> types;
+ if (types.empty() == false) {
+ if (Cached == true)
+ return types;
+ else
+ types.clear();
+ }
+
+ // setup the defaults for the compressiontypes => method mapping
+ _config->CndSet("Acquire::CompressionTypes::bz2","bzip2");
+ _config->CndSet("Acquire::CompressionTypes::lzma","lzma");
+ _config->CndSet("Acquire::CompressionTypes::gz","gzip");
+
+ // Set default application paths to check for optional compression types
+ _config->CndSet("Dir::Bin::lzma", "/usr/bin/lzma");
+ _config->CndSet("Dir::Bin::bzip2", "/bin/bzip2");
+
+ // accept non-list order as override setting for config settings on commandline
+ std::string const overrideOrder = _config->Find("Acquire::CompressionTypes::Order","");
+ if (overrideOrder.empty() == false)
+ types.push_back(overrideOrder);
+
+ // load the order setting into our vector
+ std::vector<std::string> const order = _config->FindVector("Acquire::CompressionTypes::Order");
+ for (std::vector<std::string>::const_iterator o = order.begin();
+ o != order.end(); o++) {
+ if ((*o).empty() == true)
+ continue;
+ // ignore types we have no method ready to use
+ if (_config->Exists(string("Acquire::CompressionTypes::").append(*o)) == false)
+ continue;
+ // ignore types we have no app ready to use
+ string const appsetting = string("Dir::Bin::").append(*o);
+ if (_config->Exists(appsetting) == true) {
+ std::string const app = _config->FindFile(appsetting.c_str(), "");
+ if (app.empty() == false && FileExists(app) == false)
+ continue;
+ }
+ types.push_back(*o);
+ }
+
+ // move again over the option tree to add all missing compression types
+ ::Configuration::Item const *Types = _config->Tree("Acquire::CompressionTypes");
+ if (Types != 0)
+ Types = Types->Child;
+
+ for (; Types != 0; Types = Types->Next) {
+ if (Types->Tag == "Order" || Types->Tag.empty() == true)
+ continue;
+ // ignore types we already have in the vector
+ if (std::find(types.begin(),types.end(),Types->Tag) != types.end())
+ continue;
+ // ignore types we have no app ready to use
+ string const appsetting = string("Dir::Bin::").append(Types->Value);
+ if (appsetting.empty() == false && _config->Exists(appsetting) == true) {
+ std::string const app = _config->FindFile(appsetting.c_str(), "");
+ if (app.empty() == false && FileExists(app) == false)
+ continue;
+ }
+ types.push_back(Types->Tag);
+ }
+
+ return types;
+}
+ /*}}}*/
+}
diff --git a/apt-pkg/aptconfiguration.h b/apt-pkg/aptconfiguration.h
new file mode 100644
index 000000000..6a123adce
--- /dev/null
+++ b/apt-pkg/aptconfiguration.h
@@ -0,0 +1,46 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+/** \class APT::Configuration
+ * \brief Provide access methods to various configuration settings
+ *
+ * This class and their methods providing a layer around the usual access
+ * methods with _config to ensure that settings are correct and to be able
+ * to set defaults without the need to recheck it in every method again.
+ */
+ /*}}}*/
+#ifndef APT_CONFIGURATION_H
+#define APT_CONFIGURATION_H
+// Include Files /*{{{*/
+#include <string>
+#include <vector>
+ /*}}}*/
+namespace APT {
+class Configuration { /*{{{*/
+public: /*{{{*/
+ /** \brief Returns a vector of usable Compression Types
+ *
+ * Files can be compressed in various ways to decrease the size of the
+ * download. Therefore the Acquiremethods support a few compression types
+ * and some archives provide also a few different types. This option
+ * group exists to give the user the choice to prefer one type over the
+ * other (some compression types are very resource intensive - great if you
+ * have a limited download, bad if you have a really lowpowered hardware.)
+ *
+ * This method ensures that the defaults are set and checks at runtime
+ * if the type can be used. E.g. the current default is to prefer bzip2
+ * over lzma and gz - if the bzip2 binary is not available it has not much
+ * sense in downloading the bz2 file, therefore we will not return bz2 as
+ * a usable compression type. The availability is checked with the settings
+ * in the Dir::Bin group.
+ *
+ * \param Cached saves the result so we need to calculated it only once
+ * this parameter should ony be used for testing purposes.
+ *
+ * \return a vector of (all) Language Codes in the prefered usage order
+ */
+ std::vector<std::string> static const getCompressionTypes(bool const &Cached = true);
+ /*}}}*/
+};
+ /*}}}*/
+}
+#endif
diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc
index 48a5f0bff..4e8586e83 100644
--- a/apt-pkg/contrib/configuration.cc
+++ b/apt-pkg/contrib/configuration.cc
@@ -223,6 +223,25 @@ string Configuration::FindDir(const char *Name,const char *Default) const
return Res;
}
/*}}}*/
+// Configuration::FindVector - Find a vector of values /*{{{*/
+// ---------------------------------------------------------------------
+/* Returns a vector of config values under the given item */
+vector<string> Configuration::FindVector(const char *Name) const
+{
+ vector<string> Vec;
+ const Item *Top = Lookup(Name);
+ if (Top == NULL)
+ return Vec;
+
+ Item *I = Top->Child;
+ while(I != NULL)
+ {
+ Vec.push_back(I->Value);
+ I = I->Next;
+ }
+ return Vec;
+}
+ /*}}}*/
// Configuration::FindI - Find an integer value /*{{{*/
// ---------------------------------------------------------------------
/* */
@@ -582,9 +601,11 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool AsSectional,
InQuote = !InQuote;
if (InQuote == true)
continue;
-
- if ((*I == '/' && I + 1 != End && I[1] == '/') || *I == '#')
- {
+
+ if ((*I == '/' && I + 1 != End && I[1] == '/') ||
+ (*I == '#' && strcmp(string(I,I+6).c_str(),"#clear") != 0 &&
+ strcmp(string(I,I+8).c_str(),"#include") != 0))
+ {
End = I;
break;
}
diff --git a/apt-pkg/contrib/configuration.h b/apt-pkg/contrib/configuration.h
index 2534692a3..e2da83f5b 100644
--- a/apt-pkg/contrib/configuration.h
+++ b/apt-pkg/contrib/configuration.h
@@ -31,6 +31,7 @@
#include <string>
+#include <vector>
#include <iostream>
using std::string;
@@ -70,6 +71,8 @@ class Configuration
string Find(const string Name,const char *Default = 0) const {return Find(Name.c_str(),Default);};
string FindFile(const char *Name,const char *Default = 0) const;
string FindDir(const char *Name,const char *Default = 0) const;
+ std::vector<string> FindVector(const string &Name) const;
+ std::vector<string> FindVector(const char *Name) const;
int FindI(const char *Name,int Default = 0) const;
int FindI(const string Name,int Default = 0) const {return FindI(Name.c_str(),Default);};
bool FindB(const char *Name,bool Default = false) const;
diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc
index a7de09c44..4240d9f49 100644
--- a/apt-pkg/contrib/fileutl.cc
+++ b/apt-pkg/contrib/fileutl.cc
@@ -451,10 +451,12 @@ bool ExecWait(pid_t Pid,const char *Name,bool Reap)
if (Reap == true)
return false;
if (WIFSIGNALED(Status) != 0)
+ {
if( WTERMSIG(Status) == SIGSEGV)
return _error->Error(_("Sub-process %s received a segmentation fault."),Name);
else
return _error->Error(_("Sub-process %s received signal %u."),Name, WTERMSIG(Status));
+ }
if (WIFEXITED(Status) != 0)
return _error->Error(_("Sub-process %s returned an error code (%u)"),Name,WEXITSTATUS(Status));
diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc
index a991b8988..4c05f2df8 100644
--- a/apt-pkg/contrib/strutl.cc
+++ b/apt-pkg/contrib/strutl.cc
@@ -67,9 +67,20 @@ bool UTF8ToCodeset(const char *codeset, const string &orig, string *dest)
outbuf = new char[insize+1];
outptr = outbuf;
- iconv(cd, &inptr, &insize, &outptr, &outsize);
- *outptr = '\0';
+ while (insize != 0)
+ {
+ size_t const err = iconv(cd, &inptr, &insize, &outptr, &outsize);
+ if (err == (size_t)(-1))
+ {
+ insize--;
+ outsize++;
+ inptr++;
+ *outptr = '?';
+ outptr++;
+ }
+ }
+ *outptr = '\0';
*dest = outbuf;
delete[] outbuf;
@@ -304,13 +315,13 @@ string SizeToStr(double Size)
{
if (ASize < 100 && I != 0)
{
- sprintf(S,"%.1f%c",ASize,Ext[I]);
+ sprintf(S,"%'.1f%c",ASize,Ext[I]);
break;
}
if (ASize < 10000)
{
- sprintf(S,"%.0f%c",ASize,Ext[I]);
+ sprintf(S,"%'.0f%c",ASize,Ext[I]);
break;
}
ASize /= 1000.0;
diff --git a/apt-pkg/deb/debsystem.cc b/apt-pkg/deb/debsystem.cc
index 59f826d96..089a465c1 100644
--- a/apt-pkg/deb/debsystem.cc
+++ b/apt-pkg/deb/debsystem.cc
@@ -18,7 +18,6 @@
#include <apt-pkg/error.h>
#include <apt-pkg/fileutl.h>
#include <apti18n.h>
-
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>
@@ -80,7 +79,7 @@ bool debSystem::Lock()
close(LockFD);
LockFD = -1;
return _error->Error(_("dpkg was interrupted, you must manually "
- "run 'dpkg --configure -a' to correct the problem. "));
+ "run 'sudo dpkg --configure -a' to correct the problem. "));
}
LockCount++;
diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index ab71d4e96..332b3cf0b 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -12,6 +12,7 @@
#include <apt-pkg/error.h>
#include <apt-pkg/configuration.h>
#include <apt-pkg/depcache.h>
+#include <apt-pkg/pkgrecords.h>
#include <apt-pkg/strutl.h>
#include <apti18n.h>
#include <apt-pkg/fileutl.h>
@@ -24,6 +25,7 @@
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>
+#include <string.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
@@ -104,7 +106,7 @@ ionice(int PID)
/* */
pkgDPkgPM::pkgDPkgPM(pkgDepCache *Cache)
: pkgPackageManager(Cache), dpkgbuf_pos(0),
- term_out(NULL), PackagesDone(0), PackagesTotal(0)
+ term_out(NULL), PackagesDone(0), PackagesTotal(0), pkgFailures(0)
{
}
/*}}}*/
@@ -134,8 +136,14 @@ bool pkgDPkgPM::Configure(PkgIterator Pkg)
{
if (Pkg.end() == true)
return false;
-
- List.push_back(Item(Item::Configure,Pkg));
+
+ List.push_back(Item(Item::Configure, Pkg));
+
+ // Use triggers for config calls if we configure "smart"
+ // as otherwise Pre-Depends will not be satisfied, see #526774
+ if (_config->FindB("DPkg::TriggersPending", false) == true)
+ List.push_back(Item(Item::TriggersPending, PkgIterator()));
+
return true;
}
/*}}}*/
@@ -190,6 +198,9 @@ bool pkgDPkgPM::SendV2Pkgs(FILE *F)
// Write out the package actions in order.
for (vector<Item>::iterator I = List.begin(); I != List.end(); I++)
{
+ if(I->Pkg.end() == true)
+ continue;
+
pkgDepCache::StateCache &S = Cache[I->Pkg];
fprintf(F,"%s ",I->Pkg.Name());
@@ -331,7 +342,6 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
return true;
}
-
/*}}}*/
// DPkgPM::DoStdin - Read stdin and pass to slave pty /*{{{*/
// ---------------------------------------------------------------------
@@ -378,10 +388,11 @@ void pkgDPkgPM::DoTerminalPty(int master)
*/
void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
{
+ bool const Debug = _config->FindB("Debug::pkgDPkgProgressReporting",false);
// the status we output
ostringstream status;
- if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+ if (Debug == true)
std::clog << "got from dpkg '" << line << "'" << std::endl;
@@ -396,10 +407,11 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
'processing: install: pkg'
'processing: configure: pkg'
'processing: remove: pkg'
+ 'processing: purge: pkg' - but for apt is it a ignored "unknown" action
'processing: trigproc: trigger'
*/
- char* list[5];
+ char* list[6];
// dpkg sends multiline error messages sometimes (see
// #374195 for a example. we should support this by
// either patching dpkg to not send multiline over the
@@ -408,28 +420,28 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
TokSplitString(':', line, list, sizeof(list)/sizeof(list[0]));
if( list[0] == NULL || list[1] == NULL || list[2] == NULL)
{
- if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+ if (Debug == true)
std::clog << "ignoring line: not enough ':'" << std::endl;
return;
}
- char *pkg = list[1];
- char *action = _strstrip(list[2]);
+ const char* const pkg = list[1];
+ const char* action = _strstrip(list[2]);
// 'processing' from dpkg looks like
// 'processing: action: pkg'
if(strncmp(list[0], "processing", strlen("processing")) == 0)
{
char s[200];
- char *pkg_or_trigger = _strstrip(list[2]);
- action =_strstrip( list[1]);
+ const char* const pkg_or_trigger = _strstrip(list[2]);
+ action = _strstrip( list[1]);
const std::pair<const char *, const char *> * const iter =
std::find_if(PackageProcessingOpsBegin,
PackageProcessingOpsEnd,
MatchProcessingOp(action));
if(iter == PackageProcessingOpsEnd)
{
- if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
- std::clog << "ignoring unknwon action: " << action << std::endl;
+ if (Debug == true)
+ std::clog << "ignoring unknown action: " << action << std::endl;
return;
}
snprintf(s, sizeof(s), _(iter->second), pkg_or_trigger);
@@ -440,24 +452,34 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
<< endl;
if(OutStatusFd > 0)
write(OutStatusFd, status.str().c_str(), status.str().size());
- if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+ if (Debug == true)
std::clog << "send: '" << status.str() << "'" << endl;
return;
}
if(strncmp(action,"error",strlen("error")) == 0)
{
+ // urgs, sometime has ":" in its error string so that we
+ // end up with the error message split between list[3]
+ // and list[4], e.g. the message:
+ // "failed in buffer_write(fd) (10, ret=-1): backend dpkg-deb ..."
+ // concat them again
+ if( list[4] != NULL )
+ list[3][strlen(list[3])] = ':';
+
status << "pmerror:" << list[1]
<< ":" << (PackagesDone/float(PackagesTotal)*100.0)
<< ":" << list[3]
<< endl;
if(OutStatusFd > 0)
write(OutStatusFd, status.str().c_str(), status.str().size());
- if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+ if (Debug == true)
std::clog << "send: '" << status.str() << "'" << endl;
+ pkgFailures++;
+ WriteApportReport(list[1], list[3]);
return;
}
- if(strncmp(action,"conffile",strlen("conffile")) == 0)
+ else if(strncmp(action,"conffile",strlen("conffile")) == 0)
{
status << "pmconffile:" << list[1]
<< ":" << (PackagesDone/float(PackagesTotal)*100.0)
@@ -465,12 +487,12 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
<< endl;
if(OutStatusFd > 0)
write(OutStatusFd, status.str().c_str(), status.str().size());
- if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+ if (Debug == true)
std::clog << "send: '" << status.str() << "'" << endl;
return;
}
- vector<struct DpkgState> &states = PackageOps[pkg];
+ vector<struct DpkgState> const &states = PackageOps[pkg];
const char *next_action = NULL;
if(PackageOpsDone[pkg] < states.size())
next_action = states[PackageOpsDone[pkg]].state;
@@ -493,15 +515,15 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
<< endl;
if(OutStatusFd > 0)
write(OutStatusFd, status.str().c_str(), status.str().size());
- if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+ if (Debug == true)
std::clog << "send: '" << status.str() << "'" << endl;
}
- if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+ if (Debug == true)
std::clog << "(parsed from dpkg) pkg: " << pkg
<< " action: " << action << endl;
}
-
-// DPkgPM::DoDpkgStatusFd /*{{{*/
+ /*}}}*/
+// DPkgPM::DoDpkgStatusFd /*{{{*/
// ---------------------------------------------------------------------
/*
*/
@@ -538,7 +560,7 @@ void pkgDPkgPM::DoDpkgStatusFd(int statusfd, int OutStatusFd)
dpkgbuf_pos = dpkgbuf+dpkgbuf_pos-p;
}
/*}}}*/
-
+// DPkgPM::OpenLog /*{{{*/
bool pkgDPkgPM::OpenLog()
{
string logdir = _config->FindDir("Dir::Log");
@@ -561,7 +583,8 @@ bool pkgDPkgPM::OpenLog()
}
return true;
}
-
+ /*}}}*/
+// DPkg::CloseLog /*{{{*/
bool pkgDPkgPM::CloseLog()
{
if(term_out)
@@ -578,7 +601,7 @@ bool pkgDPkgPM::CloseLog()
term_out = NULL;
return true;
}
-
+ /*}}}*/
/*{{{*/
// This implements a racy version of pselect for those architectures
// that don't have a working implementation.
@@ -600,7 +623,6 @@ static int racy_pselect(int nfds, fd_set *readfds, fd_set *writefds,
return retval;
}
/*}}}*/
-
// DPkgPM::Go - Run the sequence /*{{{*/
// ---------------------------------------------------------------------
/* This globs the operations and calls dpkg
@@ -617,9 +639,9 @@ bool pkgDPkgPM::Go(int OutStatusFd)
sigset_t sigmask;
sigset_t original_sigmask;
- unsigned int MaxArgs = _config->FindI("Dpkg::MaxArgs",8*1024);
- unsigned int MaxArgBytes = _config->FindI("Dpkg::MaxArgBytes",32*1024);
- bool NoTriggers = _config->FindB("DPkg::NoTriggers",false);
+ unsigned int const MaxArgs = _config->FindI("Dpkg::MaxArgs",8*1024);
+ unsigned int const MaxArgBytes = _config->FindI("Dpkg::MaxArgBytes",32*1024);
+ bool const NoTriggers = _config->FindB("DPkg::NoTriggers", false);
if (RunScripts("DPkg::Pre-Invoke") == false)
return false;
@@ -627,6 +649,13 @@ bool pkgDPkgPM::Go(int OutStatusFd)
if (RunScriptsWithPkgs("DPkg::Pre-Install-Pkgs") == false)
return false;
+ // support subpressing of triggers processing for special
+ // cases like d-i that runs the triggers handling manually
+ bool const SmartConf = (_config->Find("PackageManager::Configure", "all") != "all");
+ bool const TriggersPending = _config->FindB("DPkg::TriggersPending", false);
+ if (_config->FindB("DPkg::ConfigurePending", SmartConf) == true)
+ List.push_back(Item(Item::ConfigurePending, PkgIterator()));
+
// map the dpkg states to the operations that are performed
// (this is sorted in the same way as Item::Ops)
static const struct DpkgState DpkgStatesOpMap[][7] = {
@@ -662,16 +691,19 @@ bool pkgDPkgPM::Go(int OutStatusFd)
// that will be [installed|configured|removed|purged] and add
// them to the PackageOps map (the dpkg states it goes through)
// and the PackageOpsTranslations (human readable strings)
- for (vector<Item>::iterator I = List.begin(); I != List.end();I++)
+ for (vector<Item>::const_iterator I = List.begin(); I != List.end();I++)
{
- string name = (*I).Pkg.Name();
+ if((*I).Pkg.end() == true)
+ continue;
+
+ string const name = (*I).Pkg.Name();
PackageOpsDone[name] = 0;
for(int i=0; (DpkgStatesOpMap[(*I).Op][i]).state != NULL; i++)
{
PackageOps[name].push_back(DpkgStatesOpMap[(*I).Op][i]);
PackagesTotal++;
}
- }
+ }
stdin_is_dev_null = false;
@@ -679,11 +711,25 @@ bool pkgDPkgPM::Go(int OutStatusFd)
OpenLog();
// this loop is runs once per operation
- for (vector<Item>::iterator I = List.begin(); I != List.end();)
+ for (vector<Item>::const_iterator I = List.begin(); I != List.end();)
{
- vector<Item>::iterator J = I;
- for (; J != List.end() && J->Op == I->Op; J++)
- /* nothing */;
+ // Do all actions with the same Op in one run
+ vector<Item>::const_iterator J = I;
+ if (TriggersPending == true)
+ for (; J != List.end(); J++)
+ {
+ if (J->Op == I->Op)
+ continue;
+ if (J->Op != Item::TriggersPending)
+ break;
+ vector<Item>::const_iterator T = J + 1;
+ if (T != List.end() && T->Op == I->Op)
+ continue;
+ break;
+ }
+ else
+ for (; J != List.end() && J->Op == I->Op; J++)
+ /* nothing */;
// Generate the argument list
const char *Args[MaxArgs + 50];
@@ -700,7 +746,7 @@ bool pkgDPkgPM::Go(int OutStatusFd)
unsigned int n = 0;
unsigned long Size = 0;
- string Tmp = _config->Find("Dir::Bin::dpkg","dpkg");
+ string const Tmp = _config->Find("Dir::Bin::dpkg","dpkg");
Args[n++] = Tmp.c_str();
Size += strlen(Args[n-1]);
@@ -750,11 +796,23 @@ bool pkgDPkgPM::Go(int OutStatusFd)
case Item::Configure:
Args[n++] = "--configure";
- if (NoTriggers)
- Args[n++] = "--no-triggers";
Size += strlen(Args[n-1]);
break;
-
+
+ case Item::ConfigurePending:
+ Args[n++] = "--configure";
+ Size += strlen(Args[n-1]);
+ Args[n++] = "--pending";
+ Size += strlen(Args[n-1]);
+ break;
+
+ case Item::TriggersPending:
+ Args[n++] = "--triggers-only";
+ Size += strlen(Args[n-1]);
+ Args[n++] = "--pending";
+ Size += strlen(Args[n-1]);
+ break;
+
case Item::Install:
Args[n++] = "--unpack";
Size += strlen(Args[n-1]);
@@ -762,7 +820,14 @@ bool pkgDPkgPM::Go(int OutStatusFd)
Size += strlen(Args[n-1]);
break;
}
-
+
+ if (NoTriggers == true && I->Op != Item::TriggersPending &&
+ I->Op != Item::ConfigurePending)
+ {
+ Args[n++] = "--no-triggers";
+ Size += strlen(Args[n-1]);
+ }
+
// Write in the file or package names
if (I->Op == Item::Install)
{
@@ -778,6 +843,8 @@ bool pkgDPkgPM::Go(int OutStatusFd)
{
for (;I != J && Size < MaxArgBytes; I++)
{
+ if((*I).Pkg.end() == true)
+ continue;
Args[n++] = I->Pkg.Name();
Size += strlen(Args[n-1]);
}
@@ -916,11 +983,9 @@ bool pkgDPkgPM::Go(int OutStatusFd)
int Status = 0;
// we read from dpkg here
- int _dpkgin = fd[0];
+ int const _dpkgin = fd[0];
close(fd[1]); // close the write end of the pipe
- // the result of the waitpid call
- int res;
if(slave > 0)
close(slave);
@@ -928,6 +993,8 @@ bool pkgDPkgPM::Go(int OutStatusFd)
sigemptyset(&sigmask);
sigprocmask(SIG_BLOCK,&sigmask,&original_sigmask);
+ // the result of the waitpid call
+ int res;
int select_ret;
while ((res=waitpid(Child,&Status, WNOHANG)) != Child) {
if(res < 0) {
@@ -943,7 +1010,6 @@ bool pkgDPkgPM::Go(int OutStatusFd)
signal(SIGHUP,old_SIGHUP);
return _error->Errno("waitpid","Couldn't wait for subprocess");
}
-
// wait for input or output here
FD_ZERO(&rfds);
if (!stdin_is_dev_null)
@@ -994,7 +1060,7 @@ bool pkgDPkgPM::Go(int OutStatusFd)
// if it was set to "keep-dpkg-runing" then we won't return
// here but keep the loop going and just report it as a error
// for later
- bool stopOnError = _config->FindB("Dpkg::StopOnError",true);
+ bool const stopOnError = _config->FindB("Dpkg::StopOnError",true);
if(stopOnError)
RunScripts("DPkg::Post-Invoke");
@@ -1030,3 +1096,186 @@ void pkgDPkgPM::Reset()
List.erase(List.begin(),List.end());
}
/*}}}*/
+// pkgDpkgPM::WriteApportReport - write out error report pkg failure /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg)
+{
+ string pkgname, reportfile, srcpkgname, pkgver, arch;
+ string::size_type pos;
+ FILE *report;
+
+ if (_config->FindB("Dpkg::ApportFailureReport",true) == false)
+ {
+ std::clog << "configured to not write apport reports" << std::endl;
+ return;
+ }
+
+ // only report the first errors
+ if(pkgFailures > _config->FindI("APT::Apport::MaxReports", 3))
+ {
+ std::clog << _("No apport report written because MaxReports is reached already") << std::endl;
+ return;
+ }
+
+ // check if its not a follow up error
+ const char *needle = dgettext("dpkg", "dependency problems - leaving unconfigured");
+ if(strstr(errormsg, needle) != NULL) {
+ std::clog << _("No apport report written because the error message indicates its a followup error from a previous failure.") << std::endl;
+ return;
+ }
+
+ // do not report disk-full failures
+ if(strstr(errormsg, strerror(ENOSPC)) != NULL) {
+ std::clog << _("No apport report written because the error message indicates a disk full error") << std::endl;
+ return;
+ }
+
+ // do not report out-of-memory failures
+ if(strstr(errormsg, strerror(ENOMEM)) != NULL) {
+ std::clog << _("No apport report written because the error message indicates a out of memory error") << std::endl;
+ return;
+ }
+
+ // do not report dpkg I/O errors
+ // XXX - this message is localized, but this only matches the English version. This is better than nothing.
+ if(strstr(errormsg, "short read in buffer_copy (")) {
+ std::clog << _("No apport report written because the error message indicates a dpkg I/O error") << std::endl;
+ return;
+ }
+
+ // get the pkgname and reportfile
+ pkgname = flNotDir(pkgpath);
+ pos = pkgname.find('_');
+ if(pos != string::npos)
+ pkgname = pkgname.substr(0, pos);
+
+ // find the package versin and source package name
+ pkgCache::PkgIterator Pkg = Cache.FindPkg(pkgname);
+ if (Pkg.end() == true)
+ return;
+ pkgCache::VerIterator Ver = Cache.GetCandidateVer(Pkg);
+ if (Ver.end() == true)
+ return;
+ pkgver = Ver.VerStr() == NULL ? "unknown" : Ver.VerStr();
+ pkgRecords Recs(Cache);
+ pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
+ srcpkgname = Parse.SourcePkg();
+ if(srcpkgname.empty())
+ srcpkgname = pkgname;
+
+ // if the file exists already, we check:
+ // - if it was reported already (touched by apport).
+ // If not, we do nothing, otherwise
+ // we overwrite it. This is the same behaviour as apport
+ // - if we have a report with the same pkgversion already
+ // then we skip it
+ reportfile = flCombine("/var/crash",pkgname+".0.crash");
+ if(FileExists(reportfile))
+ {
+ struct stat buf;
+ char strbuf[255];
+
+ // check atime/mtime
+ stat(reportfile.c_str(), &buf);
+ if(buf.st_mtime > buf.st_atime)
+ return;
+
+ // check if the existing report is the same version
+ report = fopen(reportfile.c_str(),"r");
+ while(fgets(strbuf, sizeof(strbuf), report) != NULL)
+ {
+ if(strstr(strbuf,"Package:") == strbuf)
+ {
+ char pkgname[255], version[255];
+ if(sscanf(strbuf, "Package: %s %s", pkgname, version) == 2)
+ if(strcmp(pkgver.c_str(), version) == 0)
+ {
+ fclose(report);
+ return;
+ }
+ }
+ }
+ fclose(report);
+ }
+
+ // now write the report
+ arch = _config->Find("APT::Architecture");
+ report = fopen(reportfile.c_str(),"w");
+ if(report == NULL)
+ return;
+ if(_config->FindB("DPkgPM::InitialReportOnly",false) == true)
+ chmod(reportfile.c_str(), 0);
+ else
+ chmod(reportfile.c_str(), 0600);
+ fprintf(report, "ProblemType: Package\n");
+ fprintf(report, "Architecture: %s\n", arch.c_str());
+ time_t now = time(NULL);
+ fprintf(report, "Date: %s" , ctime(&now));
+ fprintf(report, "Package: %s %s\n", pkgname.c_str(), pkgver.c_str());
+ fprintf(report, "SourcePackage: %s\n", srcpkgname.c_str());
+ fprintf(report, "ErrorMessage:\n %s\n", errormsg);
+
+ // ensure that the log is flushed
+ if(term_out)
+ fflush(term_out);
+
+ // attach terminal log it if we have it
+ string logfile_name = _config->FindFile("Dir::Log::Terminal");
+ if (!logfile_name.empty())
+ {
+ FILE *log = NULL;
+ char buf[1024];
+
+ fprintf(report, "DpkgTerminalLog:\n");
+ log = fopen(logfile_name.c_str(),"r");
+ if(log != NULL)
+ {
+ while( fgets(buf, sizeof(buf), log) != NULL)
+ fprintf(report, " %s", buf);
+ fclose(log);
+ }
+ }
+
+ // log the ordering
+ const char *ops_str[] = {"Install", "Configure","Remove","Purge"};
+ fprintf(report, "AptOrdering:\n");
+ for (vector<Item>::iterator I = List.begin(); I != List.end(); I++)
+ fprintf(report, " %s: %s\n", (*I).Pkg.Name(), ops_str[(*I).Op]);
+
+ // attach dmesg log (to learn about segfaults)
+ if (FileExists("/bin/dmesg"))
+ {
+ FILE *log = NULL;
+ char buf[1024];
+
+ fprintf(report, "Dmesg:\n");
+ log = popen("/bin/dmesg","r");
+ if(log != NULL)
+ {
+ while( fgets(buf, sizeof(buf), log) != NULL)
+ fprintf(report, " %s", buf);
+ fclose(log);
+ }
+ }
+
+ // attach df -l log (to learn about filesystem status)
+ if (FileExists("/bin/df"))
+ {
+ FILE *log = NULL;
+ char buf[1024];
+
+ fprintf(report, "Df:\n");
+ log = popen("/bin/df -l","r");
+ if(log != NULL)
+ {
+ while( fgets(buf, sizeof(buf), log) != NULL)
+ fprintf(report, " %s", buf);
+ fclose(log);
+ }
+ }
+
+ fclose(report);
+
+}
+ /*}}}*/
diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h
index ebc7e32bf..90e5b95e6 100644
--- a/apt-pkg/deb/dpkgpm.h
+++ b/apt-pkg/deb/dpkgpm.h
@@ -31,6 +31,7 @@ class pkgDPkgPM : public pkgPackageManager
FILE *term_out;
protected:
+ int pkgFailures;
// progress reporting
struct DpkgState
@@ -47,13 +48,14 @@ class pkgDPkgPM : public pkgPackageManager
// the int is the state that is already done (e.g. a package that is
// going to be install is already in state "half-installed")
map<string,unsigned int> PackageOpsDone;
+
// progress reporting
unsigned int PackagesDone;
unsigned int PackagesTotal;
struct Item
{
- enum Ops {Install, Configure, Remove, Purge} Op;
+ enum Ops {Install, Configure, Remove, Purge, ConfigurePending, TriggersPending} Op;
string File;
PkgIterator Pkg;
Item(Ops Op,PkgIterator Pkg,string File = "") : Op(Op),
@@ -67,6 +69,9 @@ class pkgDPkgPM : public pkgPackageManager
bool RunScriptsWithPkgs(const char *Cnf);
bool SendV2Pkgs(FILE *F);
+ // apport integration
+ void WriteApportReport(const char *pkgpath, const char *errormsg);
+
// dpkg log
bool OpenLog();
bool CloseLog();
diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc
index 45e427d81..ec7a5de64 100644
--- a/apt-pkg/depcache.cc
+++ b/apt-pkg/depcache.cc
@@ -823,7 +823,7 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge,
bool pkgDepCache::IsDeleteOk(PkgIterator const &Pkg,bool rPurge,
unsigned long Depth, bool FromUser)
{
- if (FromUser == false && Pkg->SelectedState == pkgCache::State::Hold)
+ if (FromUser == false && Pkg->SelectedState == pkgCache::State::Hold && _config->FindB("APT::Ignore-Hold",false) == false)
{
if (DebugMarker == true)
std::clog << OutputInDepth(Depth) << "Hold prevents MarkDelete of " << Pkg << " FU=" << FromUser << std::endl;
@@ -1085,7 +1085,7 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
bool pkgDepCache::IsInstallOk(PkgIterator const &Pkg,bool AutoInst,
unsigned long Depth, bool FromUser)
{
- if (FromUser == false && Pkg->SelectedState == pkgCache::State::Hold)
+ if (FromUser == false && Pkg->SelectedState == pkgCache::State::Hold && _config->FindB("APT::Ignore-Hold",false) == false)
{
if (DebugMarker == true)
std::clog << OutputInDepth(Depth) << "Hold prevents MarkInstall of " << Pkg << " FU=" << FromUser << std::endl;
diff --git a/apt-pkg/indexcopy.cc b/apt-pkg/indexcopy.cc
index e7bf046a4..57c9f95ca 100644
--- a/apt-pkg/indexcopy.cc
+++ b/apt-pkg/indexcopy.cc
@@ -592,7 +592,10 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList,
// a Release.gpg without a Release should never happen
if(!FileExists(*I+"Release"))
+ {
+ delete MetaIndex;
continue;
+ }
// verify the gpg signature of "Release"
diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc
index 2a3dfae74..6f02203cd 100644
--- a/apt-pkg/init.cc
+++ b/apt-pkg/init.cc
@@ -51,6 +51,7 @@ bool pkgInitConfig(Configuration &Cnf)
Cnf.Set("Dir::State::lists","lists/");
Cnf.Set("Dir::State::cdroms","cdroms.list");
+ Cnf.Set("Dir::State::mirrors","mirrors/");
// Cache
Cnf.Set("Dir::Cache","var/cache/apt/");
@@ -74,7 +75,7 @@ bool pkgInitConfig(Configuration &Cnf)
// State
Cnf.Set("Dir::Log","var/log/apt");
Cnf.Set("Dir::Log::Terminal","term.log");
-
+
// Translation
Cnf.Set("APT::Acquire::Translation", "environment");
@@ -104,7 +105,7 @@ bool pkgInitConfig(Configuration &Cnf)
if (Res == false)
return false;
-
+
if (Cnf.FindB("Debug::pkgInitConfig",false) == true)
Cnf.Dump();
diff --git a/apt-pkg/init.h b/apt-pkg/init.h
index 165299253..44d1d107c 100644
--- a/apt-pkg/init.h
+++ b/apt-pkg/init.h
@@ -19,7 +19,7 @@
// See the makefile
#define APT_PKG_MAJOR 4
#define APT_PKG_MINOR 8
-#define APT_PKG_RELEASE 0
+#define APT_PKG_RELEASE 1
extern const char *pkgVersion;
extern const char *pkgLibVersion;
diff --git a/apt-pkg/makefile b/apt-pkg/makefile
index 26fc9fac5..f2a8460a9 100644
--- a/apt-pkg/makefile
+++ b/apt-pkg/makefile
@@ -14,7 +14,7 @@ include ../buildlib/defaults.mak
LIBRARY=apt-pkg
LIBEXT=$(GLIBC_VER)$(LIBSTDCPP_VER)
MAJOR=4.8
-MINOR=0
+MINOR=1
SLIBS=$(PTHREADLIB) $(INTLLIBS) -lutil -ldl
APT_DOMAIN:=libapt-pkg$(MAJOR)
@@ -34,14 +34,15 @@ SOURCE+= pkgcache.cc version.cc depcache.cc \
acquire-worker.cc acquire-method.cc init.cc clean.cc \
srcrecords.cc cachefile.cc versionmatch.cc policy.cc \
pkgsystem.cc indexfile.cc pkgcachegen.cc acquire-item.cc \
- indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.cc
+ indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.cc \
+ aptconfiguration.cc
HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \
orderlist.h sourcelist.h packagemanager.h tagfile.h \
init.h pkgcache.h version.h progress.h pkgrecords.h \
acquire.h acquire-worker.h acquire-item.h acquire-method.h \
clean.h srcrecords.h cachefile.h versionmatch.h policy.h \
pkgsystem.h indexfile.h metaindex.h indexrecords.h vendor.h \
- vendorlist.h cdrom.h indexcopy.h
+ vendorlist.h cdrom.h indexcopy.h aptconfiguration.h
# Source code for the debian specific components
# In theory the deb headers do not need to be exported..
diff --git a/apt-pkg/orderlist.cc b/apt-pkg/orderlist.cc
index 01b150722..0ee2e2bc8 100644
--- a/apt-pkg/orderlist.cc
+++ b/apt-pkg/orderlist.cc
@@ -174,22 +174,35 @@ bool pkgOrderList::DoRun()
bool pkgOrderList::OrderCritical()
{
FileList = 0;
-
- Primary = &pkgOrderList::DepUnPackPre;
+
+ Primary = &pkgOrderList::DepUnPackPreD;
Secondary = 0;
RevDepends = 0;
Remove = 0;
LoopCount = 0;
-
+
// Sort
Me = this;
- qsort(List,End - List,sizeof(*List),&OrderCompareB);
-
+ qsort(List,End - List,sizeof(*List),&OrderCompareB);
+
if (DoRun() == false)
return false;
-
+
if (LoopCount != 0)
return _error->Error("Fatal, predepends looping detected");
+
+ if (Debug == true)
+ {
+ clog << "** Critical Unpack ordering done" << endl;
+
+ for (iterator I = List; I != End; I++)
+ {
+ PkgIterator P(Cache,*I);
+ if (IsNow(P) == true)
+ clog << " " << P.Name() << ' ' << IsMissing(P) << ',' << IsFlag(P,After) << endl;
+ }
+ }
+
return true;
}
/*}}}*/
@@ -205,7 +218,7 @@ bool pkgOrderList::OrderUnpack(string *FileList)
if (FileList != 0)
{
WipeFlags(After);
-
+
// Set the inlist flag
for (iterator I = List; I != End; I++)
{
@@ -214,7 +227,7 @@ bool pkgOrderList::OrderUnpack(string *FileList)
Flag(*I,After);
}
}
-
+
Primary = &pkgOrderList::DepUnPackCrit;
Secondary = &pkgOrderList::DepConfigure;
RevDepends = &pkgOrderList::DepUnPackDep;
@@ -229,7 +242,7 @@ bool pkgOrderList::OrderUnpack(string *FileList)
clog << "** Pass A" << endl;
if (DoRun() == false)
return false;
-
+
if (Debug == true)
clog << "** Pass B" << endl;
Secondary = 0;
@@ -243,7 +256,7 @@ bool pkgOrderList::OrderUnpack(string *FileList)
Remove = 0; // Otherwise the libreadline remove problem occures
if (DoRun() == false)
return false;
-
+
if (Debug == true)
clog << "** Pass D" << endl;
LoopCount = 0;
@@ -259,9 +272,9 @@ bool pkgOrderList::OrderUnpack(string *FileList)
{
PkgIterator P(Cache,*I);
if (IsNow(P) == true)
- clog << P.Name() << ' ' << IsMissing(P) << ',' << IsFlag(P,After) << endl;
+ clog << " " << P.Name() << ' ' << IsMissing(P) << ',' << IsFlag(P,After) << endl;
}
- }
+ }
return true;
}
@@ -286,29 +299,35 @@ bool pkgOrderList::OrderConfigure()
/* Higher scores order earlier */
int pkgOrderList::Score(PkgIterator Pkg)
{
+ static int const ScoreDelete = _config->FindI("OrderList::Score::Delete", 500);
+
// Removal is always done first
if (Cache[Pkg].Delete() == true)
- return 200;
-
+ return ScoreDelete;
+
// This should never happen..
if (Cache[Pkg].InstVerIter(Cache).end() == true)
return -1;
-
+
+ static int const ScoreEssential = _config->FindI("OrderList::Score::Essential", 200);
+ static int const ScoreImmediate = _config->FindI("OrderList::Score::Immediate", 10);
+ static int const ScorePreDepends = _config->FindI("OrderList::Score::PreDepends", 50);
+
int Score = 0;
if ((Pkg->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
- Score += 100;
+ Score += ScoreEssential;
if (IsFlag(Pkg,Immediate) == true)
- Score += 10;
-
- for (DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList();
+ Score += ScoreImmediate;
+
+ for (DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList();
D.end() == false; D++)
if (D->Type == pkgCache::Dep::PreDepends)
{
- Score += 50;
+ Score += ScorePreDepends;
break;
}
-
+
// Important Required Standard Optional Extra
signed short PrioMap[] = {0,5,4,3,1,0};
if (Cache[Pkg].InstVerIter(Cache)->Priority <= 5)
@@ -386,6 +405,7 @@ int pkgOrderList::OrderCompareA(const void *a, const void *b)
int ScoreA = Me->Score(A);
int ScoreB = Me->Score(B);
+
if (ScoreA > ScoreB)
return -1;
@@ -422,6 +442,7 @@ int pkgOrderList::OrderCompareB(const void *a, const void *b)
int ScoreA = Me->Score(A);
int ScoreB = Me->Score(B);
+
if (ScoreA > ScoreB)
return -1;
diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc
index 019a1db1f..c6812ed11 100644
--- a/apt-pkg/packagemanager.cc
+++ b/apt-pkg/packagemanager.cc
@@ -57,7 +57,10 @@ bool pkgPackageManager::GetArchives(pkgAcquire *Owner,pkgSourceList *Sources,
if (CreateOrderList() == false)
return false;
- if (List->OrderUnpack() == false)
+ bool const ordering =
+ _config->FindB("PackageManager::UnpackAll",true) ?
+ List->OrderUnpack() : List->OrderCritical();
+ if (ordering == false)
return _error->Error("Internal ordering error");
for (pkgOrderList::iterator I = List->begin(); I != List->end(); I++)
@@ -163,7 +166,7 @@ bool pkgPackageManager::CreateOrderList()
delete List;
List = new pkgOrderList(&Cache);
- bool NoImmConfigure = !_config->FindB("APT::Immediate-Configure",true);
+ static bool const NoImmConfigure = !_config->FindB("APT::Immediate-Configure",true);
// Generate the list of affected packages and sort it
for (PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
@@ -266,13 +269,16 @@ bool pkgPackageManager::ConfigureAll()
if (OList.OrderConfigure() == false)
return false;
-
+
+ std::string const conf = _config->Find("PackageManager::Configure","all");
+ bool const ConfigurePkgs = (conf == "all");
+
// Perform the configuring
for (pkgOrderList::iterator I = OList.begin(); I != OList.end(); I++)
{
PkgIterator Pkg(Cache,*I);
- if (Configure(Pkg) == false)
+ if (ConfigurePkgs == true && Configure(Pkg) == false)
return false;
List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States);
@@ -294,19 +300,20 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg)
if (DepAdd(OList,Pkg) == false)
return false;
-
- if (OList.OrderConfigure() == false)
- return false;
-
+
+ static std::string const conf = _config->Find("PackageManager::Configure","all");
+ static bool const ConfigurePkgs = (conf == "all" || conf == "smart");
+
+ if (ConfigurePkgs == true)
+ if (OList.OrderConfigure() == false)
+ return false;
+
// Perform the configuring
for (pkgOrderList::iterator I = OList.begin(); I != OList.end(); I++)
{
PkgIterator Pkg(Cache,*I);
- if (Debug == true)
- clog << " SmartConfigure on" << Pkg.Name() << endl;
-
- if (Configure(Pkg) == false)
+ if (ConfigurePkgs == true && Configure(Pkg) == false)
return false;
List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States);
@@ -590,9 +597,12 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall()
Reset();
if (Debug == true)
- clog << "Begining to order" << endl;
+ clog << "Beginning to order" << endl;
- if (List->OrderUnpack(FileNames) == false)
+ bool const ordering =
+ _config->FindB("PackageManager::UnpackAll",true) ?
+ List->OrderUnpack(FileNames) : List->OrderCritical();
+ if (ordering == false)
{
_error->Error("Internal ordering error");
return Failed;
@@ -645,7 +655,7 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall()
return Failed;
DoneSomething = true;
}
-
+
// Final run through the configure phase
if (ConfigureAll() == false)
return Failed;
diff --git a/apt-pkg/pkgrecords.cc b/apt-pkg/pkgrecords.cc
index e506de73a..a5dab22ff 100644
--- a/apt-pkg/pkgrecords.cc
+++ b/apt-pkg/pkgrecords.cc
@@ -23,8 +23,8 @@
pkgRecords::pkgRecords(pkgCache &Cache) : Cache(Cache),
Files(Cache.HeaderP->PackageFileCount)
{
- for (pkgCache::PkgFileIterator I = Cache.FileBegin();
- I.end() == false; I++)
+ for (pkgCache::PkgFileIterator I = Cache.FileBegin();
+ I.end() == false; I++)
{
const pkgIndexFile::Type *Type = pkgIndexFile::Type::GetType(I.IndexType());
if (Type == 0)
diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc
index 7c5d15a58..1c41f1265 100644
--- a/apt-pkg/tagfile.cc
+++ b/apt-pkg/tagfile.cc
@@ -418,6 +418,7 @@ static const char *iTFRewritePackageOrder[] = {
"Section",
"Installed-Size",
"Maintainer",
+ "Original-Maintainer",
"Architecture",
"Source",
"Version",
@@ -447,6 +448,7 @@ static const char *iTFRewriteSourceOrder[] = {"Package",
"Priority",
"Section",
"Maintainer",
+ "Original-Maintainer",
"Build-Depends",
"Build-Depends-Indep",
"Build-Conflicts",