summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/acquire-item.cc138
-rw-r--r--apt-pkg/acquire-item.h16
-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/cdrom.cc3
-rw-r--r--apt-pkg/contrib/strutl.cc21
-rw-r--r--apt-pkg/contrib/strutl.h1
-rw-r--r--apt-pkg/deb/debsystem.cc3
-rw-r--r--apt-pkg/deb/debversion.cc18
-rw-r--r--apt-pkg/deb/dpkgpm.cc251
-rw-r--r--apt-pkg/deb/dpkgpm.h9
-rw-r--r--apt-pkg/indexfile.cc3
-rw-r--r--apt-pkg/init.cc1
-rw-r--r--apt-pkg/packagemanager.h6
-rw-r--r--apt-pkg/pkgrecords.cc4
-rw-r--r--apt-pkg/tagfile.cc2
17 files changed, 413 insertions, 102 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc
index d2aca597e..a959253bc 100644
--- a/apt-pkg/acquire-item.cc
+++ b/apt-pkg/acquire-item.cc
@@ -64,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
@@ -76,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 /*{{{*/
@@ -101,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)
@@ -110,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);
@@ -132,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
@@ -616,7 +666,6 @@ 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);
}
/*}}}*/
@@ -684,6 +733,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
@@ -874,8 +924,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);
}
/*}}}*/
@@ -888,7 +939,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
@@ -963,6 +1014,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
{
@@ -1014,22 +1074,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) /*{{{*/
@@ -1059,7 +1112,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);
@@ -1100,7 +1152,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
@@ -1203,30 +1255,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 3f073de5b..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.
*
@@ -545,7 +557,8 @@ class pkgAcqIndex : public pkgAcquire::Item
* 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 {{{
@@ -608,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/cdrom.cc b/apt-pkg/cdrom.cc
index 96d4e9c91..783ffc430 100644
--- a/apt-pkg/cdrom.cc
+++ b/apt-pkg/cdrom.cc
@@ -289,7 +289,8 @@ bool pkgCdrom::DropRepeats(vector<string> &List,const char *Name)
List[J] = string();
}
}
-
+ delete[] Inodes;
+
// Wipe erased entries
for (unsigned int I = 0; I < List.size();)
{
diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc
index 8e8820949..b54758632 100644
--- a/apt-pkg/contrib/strutl.cc
+++ b/apt-pkg/contrib/strutl.cc
@@ -198,7 +198,8 @@ bool ParseQuoteWord(const char *&String,string &Res)
char *I;
for (I = Buffer; I < Buffer + sizeof(Buffer) && Start != C; I++)
{
- if (*Start == '%' && Start + 2 < C)
+ if (*Start == '%' && Start + 2 < C &&
+ isxdigit(Start[1]) && isxdigit(Start[2]))
{
Tmp[0] = Start[1];
Tmp[1] = Start[2];
@@ -273,7 +274,8 @@ string QuoteString(const string &Str, const char *Bad)
for (string::const_iterator I = Str.begin(); I != Str.end(); I++)
{
if (strchr(Bad,*I) != 0 || isprint(*I) == 0 ||
- *I <= 0x20 || *I >= 0x7F)
+ *I == 0x25 || // percent '%' char
+ *I <= 0x20 || *I >= 0x7F) // control chars
{
char Buf[10];
sprintf(Buf,"%%%02x",(int)*I);
@@ -290,10 +292,16 @@ string QuoteString(const string &Str, const char *Bad)
/* This undoes QuoteString */
string DeQuoteString(const string &Str)
{
+ return DeQuoteString(Str.begin(),Str.end());
+}
+string DeQuoteString(string::const_iterator const &begin,
+ string::const_iterator const &end)
+{
string Res;
- for (string::const_iterator I = Str.begin(); I != Str.end(); I++)
+ for (string::const_iterator I = begin; I != end; I++)
{
- if (*I == '%' && I + 2 < Str.end())
+ if (*I == '%' && I + 2 < end &&
+ isxdigit(I[1]) && isxdigit(I[2]))
{
char Tmp[3];
Tmp[0] = I[1];
@@ -1217,9 +1225,10 @@ void URI::CopyFrom(const string &U)
else
{
Host.assign(At+1,SingleSlash);
- User.assign(FirstColon,SecondColon);
+ // username and password must be encoded (RFC 3986)
+ User.assign(DeQuoteString(FirstColon,SecondColon));
if (SecondColon < At)
- Password.assign(SecondColon+1,At);
+ Password.assign(DeQuoteString(SecondColon+1,At));
}
// Now we parse the RFC 2732 [] hostnames.
diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h
index a1e7f3934..a92c0a78f 100644
--- a/apt-pkg/contrib/strutl.h
+++ b/apt-pkg/contrib/strutl.h
@@ -45,6 +45,7 @@ bool ParseQuoteWord(const char *&String,string &Res);
bool ParseCWord(const char *&String,string &Res);
string QuoteString(const string &Str,const char *Bad);
string DeQuoteString(const string &Str);
+string DeQuoteString(string::const_iterator const &begin, string::const_iterator const &end);
string SizeToStr(double Bytes);
string TimeToStr(unsigned long Sec);
string Base64Encode(const string &Str);
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/debversion.cc b/apt-pkg/deb/debversion.cc
index ad45e9a44..755ffbe96 100644
--- a/apt-pkg/deb/debversion.cc
+++ b/apt-pkg/deb/debversion.cc
@@ -190,8 +190,22 @@ int debVersioningSystem::DoCmpVersion(const char *A,const char *AEnd,
dlhs++;
if (drhs != rhs)
drhs++;
-
- return CmpFragment(dlhs,AEnd,drhs,BEnd);
+
+ // no debian revision need to be treated like -0
+ if (*(dlhs-1) == '-' && *(drhs-1) == '-')
+ return CmpFragment(dlhs,AEnd,drhs,BEnd);
+ else if (*(dlhs-1) == '-')
+ {
+ const char* null = "0";
+ return CmpFragment(dlhs,AEnd,null, null+1);
+ }
+ else if (*(drhs-1) == '-')
+ {
+ const char* null = "0";
+ return CmpFragment(null, null+1, drhs, BEnd);
+ }
+ else
+ return 0;
}
/*}}}*/
// debVS::CheckDep - Check a single dependency /*{{{*/
diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index 8abe3f5c6..18c731788 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>
@@ -105,7 +107,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)
{
}
/*}}}*/
@@ -341,7 +343,6 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
return true;
}
-
/*}}}*/
// DPkgPM::DoStdin - Read stdin and pass to slave pty /*{{{*/
// ---------------------------------------------------------------------
@@ -411,7 +412,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
'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
@@ -459,6 +460,14 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
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]
@@ -467,6 +476,8 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
write(OutStatusFd, status.str().c_str(), status.str().size());
if (Debug == true)
std::clog << "send: '" << status.str() << "'" << endl;
+ pkgFailures++;
+ WriteApportReport(list[1], list[3]);
return;
}
else if(strncmp(action,"conffile",strlen("conffile")) == 0)
@@ -551,7 +562,7 @@ void pkgDPkgPM::DoDpkgStatusFd(int statusfd, int OutStatusFd)
}
/*}}}*/
// DPkgPM::WriteHistoryTag /*{{{*/
-void pkgDPkgPM::WriteHistoryTag(string tag, string value)
+void pkgDPkgPM::WriteHistoryTag(FILE *history_out, string tag, string value)
{
if (value.size() > 0)
{
@@ -564,35 +575,37 @@ void pkgDPkgPM::WriteHistoryTag(string tag, string value)
// DPkgPM::OpenLog /*{{{*/
bool pkgDPkgPM::OpenLog()
{
- string logdir = _config->FindDir("Dir::Log");
+ string const logdir = _config->FindDir("Dir::Log");
if(not FileExists(logdir))
return _error->Error(_("Directory '%s' missing"), logdir.c_str());
// get current time
char timestr[200];
- time_t t = time(NULL);
- struct tm *tmp = localtime(&t);
+ time_t const t = time(NULL);
+ struct tm const * const tmp = localtime(&t);
strftime(timestr, sizeof(timestr), "%F %T", tmp);
// open terminal log
- string logfile_name = flCombine(logdir,
+ string const logfile_name = flCombine(logdir,
_config->Find("Dir::Log::Terminal"));
if (!logfile_name.empty())
{
term_out = fopen(logfile_name.c_str(),"a");
if (term_out == NULL)
- return _error->WarningE(_("Could not open file '%s'"), logfile_name.c_str());
+ return _error->WarningE("OpenLog", _("Could not open file '%s'"), logfile_name.c_str());
chmod(logfile_name.c_str(), 0600);
fprintf(term_out, "\nLog started: %s\n", timestr);
}
- // write
- string history_name = flCombine(logdir,
+ // write your history
+ string const history_name = flCombine(logdir,
_config->Find("Dir::Log::History"));
if (!history_name.empty())
{
- history_out = fopen(history_name.c_str(),"a");
+ FILE *history_out = fopen(history_name.c_str(),"a");
+ if (history_out == NULL)
+ return _error->WarningE("OpenLog", _("Could not open file '%s'"), history_name.c_str());
chmod(history_name.c_str(), 0644);
fprintf(history_out, "\nStart-Date: %s\n", timestr);
string remove, purge, install, upgrade, downgrade;
@@ -612,12 +625,12 @@ bool pkgDPkgPM::OpenLog()
remove += I.Name() + string(" (") + Cache[I].CurVersion + string("), ");
}
}
- WriteHistoryTag("Install", install);
- WriteHistoryTag("Upgrade", upgrade);
- WriteHistoryTag("Downgrade",downgrade);
- WriteHistoryTag("Remove",remove);
- WriteHistoryTag("Purge",purge);
- fflush(history_out);
+ WriteHistoryTag(history_out, "Install", install);
+ WriteHistoryTag(history_out, "Upgrade", upgrade);
+ WriteHistoryTag(history_out, "Downgrade",downgrade);
+ WriteHistoryTag(history_out, "Remove",remove);
+ WriteHistoryTag(history_out, "Purge",purge);
+ fclose(history_out);
}
return true;
@@ -640,10 +653,11 @@ bool pkgDPkgPM::CloseLog()
}
term_out = NULL;
- if(history_out)
+ string history_name = flCombine(_config->FindDir("Dir::Log"),
+ _config->Find("Dir::Log::History"));
+ if (!history_name.empty())
{
- if (dpkg_error.size() > 0)
- fprintf(history_out, "Error: %s\n", dpkg_error.c_str());
+ FILE *history_out = fopen(history_name.c_str(),"a");
fprintf(history_out, "End-Date: %s\n", timestr);
fclose(history_out);
}
@@ -1061,7 +1075,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)
@@ -1117,6 +1130,7 @@ bool pkgDPkgPM::Go(int OutStatusFd)
if(stopOnError)
RunScripts("DPkg::Post-Invoke");
+ string dpkg_error;
if (WIFSIGNALED(Status) != 0 && WTERMSIG(Status) == SIGSEGV)
strprintf(dpkg_error, "Sub-process %s received a segmentation fault.",Args[0]);
else if (WIFEXITED(Status) != 0)
@@ -1125,7 +1139,17 @@ bool pkgDPkgPM::Go(int OutStatusFd)
strprintf(dpkg_error, "Sub-process %s exited unexpectedly",Args[0]);
if(dpkg_error.size() > 0)
+ {
_error->Error(dpkg_error.c_str());
+ string history_name = flCombine(_config->FindDir("Dir::Log"),
+ _config->Find("Dir::Log::History"));
+ if (!history_name.empty())
+ {
+ FILE *history_out = fopen(history_name.c_str(),"a");
+ fprintf(history_out, "Error: %s\n", dpkg_error.c_str());
+ fclose(history_out);
+ }
+ }
if(stopOnError)
{
@@ -1151,3 +1175,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 330c788a2..160486bf9 100644
--- a/apt-pkg/deb/dpkgpm.h
+++ b/apt-pkg/deb/dpkgpm.h
@@ -29,10 +29,9 @@ class pkgDPkgPM : public pkgPackageManager
char dpkgbuf[1024];
int dpkgbuf_pos;
FILE *term_out;
- FILE *history_out;
- string dpkg_error;
protected:
+ int pkgFailures;
// progress reporting
struct DpkgState
@@ -49,6 +48,7 @@ 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;
@@ -68,7 +68,10 @@ class pkgDPkgPM : public pkgPackageManager
// Helpers
bool RunScriptsWithPkgs(const char *Cnf);
bool SendV2Pkgs(FILE *F);
- void WriteHistoryTag(string tag, string value);
+ void WriteHistoryTag(FILE* history_out, string tag, string value);
+
+ // apport integration
+ void WriteApportReport(const char *pkgpath, const char *errormsg);
// dpkg log
bool OpenLog();
diff --git a/apt-pkg/indexfile.cc b/apt-pkg/indexfile.cc
index 34fd71b20..9b85a8cf8 100644
--- a/apt-pkg/indexfile.cc
+++ b/apt-pkg/indexfile.cc
@@ -115,8 +115,7 @@ string pkgIndexFile::LanguageCode()
// we have a mapping of the language codes that contains all the language
// codes that need the country code as well
// (like pt_BR, pt_PT, sv_SE, zh_*, en_*)
- const char *need_full_langcode[] = { "cs_",
- "en_",
+ const char *need_full_langcode[] = { "en_",
"pt_",
"sv_",
"zh_",
diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc
index 6310aff11..e2f847ed2 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/");
diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h
index af1476b7a..44f5d5ef7 100644
--- a/apt-pkg/packagemanager.h
+++ b/apt-pkg/packagemanager.h
@@ -49,7 +49,11 @@ class pkgPackageManager : protected pkgCache::Namespace
bool Debug;
bool DepAdd(pkgOrderList &Order,PkgIterator P,int Depth = 0);
- void ImmediateAdd(PkgIterator P, bool UseInstallVer, unsigned const int &Depth = 0);
+ // binary-compat change, fix on next abi break
+ void ImmediateAdd(PkgIterator P, bool UseInstallVer) {
+ ImmediateAdd(P, UseInstallVer, 0);
+ }
+ void ImmediateAdd(PkgIterator P, bool UseInstallVer, unsigned const int &Depth);
virtual OrderResult OrderInstall();
bool CheckRConflicts(PkgIterator Pkg,DepIterator Dep,const char *Ver);
bool CreateOrderList();
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",