summaryrefslogtreecommitdiff
path: root/apt-pkg/deb
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg/deb')
-rw-r--r--apt-pkg/deb/debindexfile.cc176
-rw-r--r--apt-pkg/deb/debindexfile.h30
-rw-r--r--apt-pkg/deb/deblistparser.cc46
-rw-r--r--apt-pkg/deb/deblistparser.h4
-rw-r--r--apt-pkg/deb/debmetaindex.cc17
-rw-r--r--apt-pkg/deb/debrecords.cc25
-rw-r--r--apt-pkg/deb/debrecords.h2
-rw-r--r--apt-pkg/deb/debsrcrecords.cc28
-rw-r--r--apt-pkg/deb/debsrcrecords.h10
-rw-r--r--apt-pkg/deb/dpkgpm.cc143
-rw-r--r--apt-pkg/deb/dpkgpm.h6
11 files changed, 442 insertions, 45 deletions
diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc
index 2d52f7c45..ed7633803 100644
--- a/apt-pkg/deb/debindexfile.cc
+++ b/apt-pkg/deb/debindexfile.cc
@@ -301,7 +301,7 @@ pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const
pkgCache::PkgFileIterator File = Cache.FileBegin();
for (; File.end() == false; File++)
{
- if (FileName != File.FileName())
+ if (File.FileName() == NULL || FileName != File.FileName())
continue;
struct stat St;
@@ -316,6 +316,170 @@ pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const
}
/*}}}*/
+// TranslationsIndex::debTranslationsIndex - Contructor /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+debTranslationsIndex::debTranslationsIndex(string URI,string Dist,string Section) :
+ pkgIndexFile(true), URI(URI), Dist(Dist), Section(Section)
+{
+}
+ /*}}}*/
+// TranslationIndex::Trans* - Return the URI to the translation files /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+inline string debTranslationsIndex::IndexFile(const char *Type) const
+{
+ return _config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type));
+}
+string debTranslationsIndex::IndexURI(const char *Type) const
+{
+ string Res;
+ if (Dist[Dist.size() - 1] == '/')
+ {
+ if (Dist != "/")
+ Res = URI + Dist;
+ else
+ Res = URI;
+ }
+ else
+ Res = URI + "dists/" + Dist + '/' + Section +
+ "/i18n/Translation-";
+
+ Res += Type;
+ return Res;
+}
+ /*}}}*/
+// TranslationsIndex::GetIndexes - Fetch the index files /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool debTranslationsIndex::GetIndexes(pkgAcquire *Owner) const
+{
+ if (TranslationsAvailable()) {
+ string TranslationFile = "Translation-" + LanguageCode();
+ new pkgAcqIndexTrans(Owner, IndexURI(LanguageCode().c_str()),
+ Info(TranslationFile.c_str()),
+ TranslationFile);
+ }
+
+ return true;
+}
+ /*}}}*/
+// TranslationsIndex::Describe - Give a descriptive path to the index /*{{{*/
+// ---------------------------------------------------------------------
+/* This should help the user find the index in the sources.list and
+ in the filesystem for problem solving */
+string debTranslationsIndex::Describe(bool Short) const
+{
+ char S[300];
+ if (Short == true)
+ snprintf(S,sizeof(S),"%s",Info(TranslationFile().c_str()).c_str());
+ else
+ snprintf(S,sizeof(S),"%s (%s)",Info(TranslationFile().c_str()).c_str(),
+ IndexFile(LanguageCode().c_str()).c_str());
+ return S;
+}
+ /*}}}*/
+// TranslationsIndex::Info - One liner describing the index URI /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+string debTranslationsIndex::Info(const char *Type) const
+{
+ string Info = ::URI::SiteOnly(URI) + ' ';
+ if (Dist[Dist.size() - 1] == '/')
+ {
+ if (Dist != "/")
+ Info += Dist;
+ }
+ else
+ Info += Dist + '/' + Section;
+ Info += " ";
+ Info += Type;
+ return Info;
+}
+ /*}}}*/
+bool debTranslationsIndex::HasPackages() const
+{
+ if(!TranslationsAvailable())
+ return false;
+
+ return FileExists(IndexFile(LanguageCode().c_str()));
+}
+
+// TranslationsIndex::Exists - Check if the index is available /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool debTranslationsIndex::Exists() const
+{
+ return FileExists(IndexFile(LanguageCode().c_str()));
+}
+ /*}}}*/
+// TranslationsIndex::Size - Return the size of the index /*{{{*/
+// ---------------------------------------------------------------------
+/* This is really only used for progress reporting. */
+unsigned long debTranslationsIndex::Size() const
+{
+ struct stat S;
+ if (stat(IndexFile(LanguageCode().c_str()).c_str(),&S) != 0)
+ return 0;
+ return S.st_size;
+}
+ /*}}}*/
+// TranslationsIndex::Merge - Load the index file into a cache /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
+{
+ // Check the translation file, if in use
+ string TranslationFile = IndexFile(LanguageCode().c_str());
+ if (TranslationsAvailable() && FileExists(TranslationFile))
+ {
+ FileFd Trans(TranslationFile,FileFd::ReadOnly);
+ debListParser TransParser(&Trans);
+ if (_error->PendingError() == true)
+ return false;
+
+ Prog.SubProgress(0, Info(TranslationFile.c_str()));
+ if (Gen.SelectFile(TranslationFile,string(),*this) == false)
+ return _error->Error("Problem with SelectFile %s",TranslationFile.c_str());
+
+ // Store the IMS information
+ pkgCache::PkgFileIterator TransFile = Gen.GetCurFile();
+ struct stat TransSt;
+ if (fstat(Trans.Fd(),&TransSt) != 0)
+ return _error->Errno("fstat","Failed to stat");
+ TransFile->Size = TransSt.st_size;
+ TransFile->mtime = TransSt.st_mtime;
+
+ if (Gen.MergeList(TransParser) == false)
+ return _error->Error("Problem with MergeList %s",TranslationFile.c_str());
+ }
+
+ return true;
+}
+ /*}}}*/
+// TranslationsIndex::FindInCache - Find this index /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) const
+{
+ string FileName = IndexFile(LanguageCode().c_str());
+
+ pkgCache::PkgFileIterator File = Cache.FileBegin();
+ for (; File.end() == false; File++)
+ {
+ if (FileName != File.FileName())
+ continue;
+
+ struct stat St;
+ if (stat(File.FileName(),&St) != 0)
+ return pkgCache::PkgFileIterator(Cache);
+ if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
+ return pkgCache::PkgFileIterator(Cache);
+ return File;
+ }
+ return File;
+}
+ /*}}}*/
// StatusIndex::debStatusIndex - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* */
@@ -412,6 +576,11 @@ class debIFTypePkg : public pkgIndexFile::Type
};
debIFTypePkg() {Label = "Debian Package Index";};
};
+class debIFTypeTrans : public debIFTypePkg
+{
+ public:
+ debIFTypeTrans() {Label = "Debian Translation Index";};
+};
class debIFTypeStatus : public pkgIndexFile::Type
{
public:
@@ -424,6 +593,7 @@ class debIFTypeStatus : public pkgIndexFile::Type
};
static debIFTypeSrc _apt_Src;
static debIFTypePkg _apt_Pkg;
+static debIFTypeTrans _apt_Trans;
static debIFTypeStatus _apt_Status;
const pkgIndexFile::Type *debSourcesIndex::GetType() const
@@ -434,6 +604,10 @@ const pkgIndexFile::Type *debPackagesIndex::GetType() const
{
return &_apt_Pkg;
}
+const pkgIndexFile::Type *debTranslationsIndex::GetType() const
+{
+ return &_apt_Trans;
+}
const pkgIndexFile::Type *debStatusIndex::GetType() const
{
return &_apt_Status;
diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h
index 2bc963567..b0012c96b 100644
--- a/apt-pkg/deb/debindexfile.h
+++ b/apt-pkg/deb/debindexfile.h
@@ -72,6 +72,36 @@ class debPackagesIndex : public pkgIndexFile
debPackagesIndex(string URI,string Dist,string Section,bool Trusted);
};
+class debTranslationsIndex : public pkgIndexFile
+{
+ string URI;
+ string Dist;
+ string Section;
+
+ string Info(const char *Type) const;
+ string IndexFile(const char *Type) const;
+ string IndexURI(const char *Type) const;
+
+ inline string TranslationFile() const {return "Translation-" + LanguageCode();};
+
+ public:
+
+ virtual const Type *GetType() const;
+
+ // Interface for acquire
+ virtual string Describe(bool Short) const;
+ virtual bool GetIndexes(pkgAcquire *Owner) const;
+
+ // Interface for the Cache Generator
+ virtual bool Exists() const;
+ virtual bool HasPackages() const;
+ virtual unsigned long Size() const;
+ virtual bool Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const;
+ virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
+
+ debTranslationsIndex(string URI,string Dist,string Section);
+};
+
class debSourcesIndex : public pkgIndexFile
{
string URI;
diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc
index d0dc7a260..074abea6d 100644
--- a/apt-pkg/deb/deblistparser.cc
+++ b/apt-pkg/deb/deblistparser.cc
@@ -15,6 +15,7 @@
#include <apt-pkg/configuration.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/crc-16.h>
+#include <apt-pkg/md5.h>
#include <ctype.h>
@@ -104,6 +105,8 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver)
return false;
if (ParseDepends(Ver,"Conflicts",pkgCache::Dep::Conflicts) == false)
return false;
+ if (ParseDepends(Ver,"Breaks",pkgCache::Dep::DpkgBreaks) == false)
+ return false;
if (ParseDepends(Ver,"Replaces",pkgCache::Dep::Replaces) == false)
return false;
@@ -117,6 +120,48 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver)
return true;
}
/*}}}*/
+// ListParser::Description - Return the description string /*{{{*/
+// ---------------------------------------------------------------------
+/* This is to return the string describing the package in debian
+ form. If this returns the blank string then the entry is assumed to
+ only describe package properties */
+string debListParser::Description()
+{
+ if (DescriptionLanguage().empty())
+ return Section.FindS("Description");
+ else
+ return Section.FindS(("Description-" + pkgIndexFile::LanguageCode()).c_str());
+}
+ /*}}}*/
+// ListParser::DescriptionLanguage - Return the description lang string /*{{{*/
+// ---------------------------------------------------------------------
+/* This is to return the string describing the language of
+ description. If this returns the blank string then the entry is
+ assumed to describe original description. */
+string debListParser::DescriptionLanguage()
+{
+ return Section.FindS("Description").empty() ? pkgIndexFile::LanguageCode() : "";
+}
+ /*}}}*/
+// ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
+// ---------------------------------------------------------------------
+/* This is to return the md5 string to allow the check if it is the right
+ description. If no Description-md5 is found in the section it will be
+ calculated.
+ */
+MD5SumValue debListParser::Description_md5()
+{
+ string value = Section.FindS("Description-md5");
+
+ if (value.empty())
+ {
+ MD5Summation md5;
+ md5.Add((Description() + "\n").c_str());
+ return md5.Result();
+ } else
+ return MD5SumValue(value);
+}
+ /*}}}*/
// ListParser::UsePackage - Update a package structure /*{{{*/
// ---------------------------------------------------------------------
/* This is called to update the package with any new information
@@ -150,6 +195,7 @@ unsigned short debListParser::VersionHash()
// "Suggests",
// "Recommends",
"Conflicts",
+ "Breaks",
"Replaces",0};
unsigned long Result = INIT_FCS;
char S[1024];
diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h
index 3a0e0421b..34bb29c72 100644
--- a/apt-pkg/deb/deblistparser.h
+++ b/apt-pkg/deb/deblistparser.h
@@ -12,6 +12,7 @@
#define PKGLIB_DEBLISTPARSER_H
#include <apt-pkg/pkgcachegen.h>
+#include <apt-pkg/indexfile.h>
#include <apt-pkg/tagfile.h>
class debListParser : public pkgCacheGenerator::ListParser
@@ -47,6 +48,9 @@ class debListParser : public pkgCacheGenerator::ListParser
virtual string Package();
virtual string Version();
virtual bool NewVersion(pkgCache::VerIterator Ver);
+ virtual string Description();
+ virtual string DescriptionLanguage();
+ virtual MD5SumValue Description_md5();
virtual unsigned short VersionHash();
virtual bool UsePackage(pkgCache::PkgIterator Pkg,
pkgCache::VerIterator Ver);
diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc
index 6830f9e83..73b2dda49 100644
--- a/apt-pkg/deb/debmetaindex.cc
+++ b/apt-pkg/deb/debmetaindex.cc
@@ -153,6 +153,16 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool GetAll) const
ComputeIndexTargets(),
new indexRecords (Dist));
+ // Queue the translations
+ for (vector<const debSectionEntry *>::const_iterator I = SectionEntries.begin();
+ I != SectionEntries.end(); I++) {
+
+ if((*I)->IsSrc)
+ continue;
+ debTranslationsIndex i = debTranslationsIndex(URI,Dist,(*I)->Section);
+ i.GetIndexes(Owner);
+ }
+
return true;
}
@@ -177,11 +187,16 @@ vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles()
Indexes = new vector <pkgIndexFile*>;
for (vector<const debSectionEntry *>::const_iterator I = SectionEntries.begin();
- I != SectionEntries.end(); I++)
+ I != SectionEntries.end(); I++) {
if ((*I)->IsSrc)
Indexes->push_back(new debSourcesIndex (URI, Dist, (*I)->Section, IsTrusted()));
else
+ {
Indexes->push_back(new debPackagesIndex (URI, Dist, (*I)->Section, IsTrusted()));
+ Indexes->push_back(new debTranslationsIndex(URI, Dist, (*I)->Section));
+ }
+ }
+
return Indexes;
}
diff --git a/apt-pkg/deb/debrecords.cc b/apt-pkg/deb/debrecords.cc
index 6ecbd15d6..5421b3db7 100644
--- a/apt-pkg/deb/debrecords.cc
+++ b/apt-pkg/deb/debrecords.cc
@@ -9,7 +9,9 @@
/*}}}*/
// Include Files /*{{{*/
#include <apt-pkg/debrecords.h>
+#include <apt-pkg/strutl.h>
#include <apt-pkg/error.h>
+#include <langinfo.h>
/*}}}*/
// RecordParser::debRecordParser - Constructor /*{{{*/
@@ -28,6 +30,10 @@ bool debRecordParser::Jump(pkgCache::VerFileIterator const &Ver)
{
return Tags.Jump(Section,Ver->Offset);
}
+bool debRecordParser::Jump(pkgCache::DescFileIterator const &Desc)
+{
+ return Tags.Jump(Section,Desc->Offset);
+}
/*}}}*/
// RecordParser::FileName - Return the archive filename on the site /*{{{*/
// ---------------------------------------------------------------------
@@ -58,7 +64,7 @@ string debRecordParser::MD5Hash()
/* */
string debRecordParser::SHA1Hash()
{
- return Section.FindS("SHA1Sum");
+ return Section.FindS("SHA1");
}
/*}}}*/
// RecordParser::Maintainer - Return the maintainer email /*{{{*/
@@ -74,7 +80,7 @@ string debRecordParser::Maintainer()
/* */
string debRecordParser::ShortDesc()
{
- string Res = Section.FindS("Description");
+ string Res = LongDesc();
string::size_type Pos = Res.find('\n');
if (Pos == string::npos)
return Res;
@@ -86,7 +92,20 @@ string debRecordParser::ShortDesc()
/* */
string debRecordParser::LongDesc()
{
- return Section.FindS("Description");
+ string orig, dest;
+ char *codeset = nl_langinfo(CODESET);
+
+ if (!Section.FindS("Description").empty())
+ orig = Section.FindS("Description").c_str();
+ else
+ orig = Section.FindS(("Description-" + pkgIndexFile::LanguageCode()).c_str()).c_str();
+
+ if (strcmp(codeset,"UTF-8") != 0) {
+ UTF8ToCodeset(codeset, orig, &dest);
+ orig = dest;
+ }
+
+ return orig;
}
/*}}}*/
// RecordParser::SourcePkg - Return the source package name if any /*{{{*/
diff --git a/apt-pkg/deb/debrecords.h b/apt-pkg/deb/debrecords.h
index 3f1956164..fdf8d762b 100644
--- a/apt-pkg/deb/debrecords.h
+++ b/apt-pkg/deb/debrecords.h
@@ -15,6 +15,7 @@
#define PKGLIB_DEBRECORDS_H
#include <apt-pkg/pkgrecords.h>
+#include <apt-pkg/indexfile.h>
#include <apt-pkg/tagfile.h>
class debRecordParser : public pkgRecords::Parser
@@ -26,6 +27,7 @@ class debRecordParser : public pkgRecords::Parser
protected:
virtual bool Jump(pkgCache::VerFileIterator const &Ver);
+ virtual bool Jump(pkgCache::DescFileIterator const &Desc);
public:
diff --git a/apt-pkg/deb/debsrcrecords.cc b/apt-pkg/deb/debsrcrecords.cc
index 21d7392a0..7338de15d 100644
--- a/apt-pkg/deb/debsrcrecords.cc
+++ b/apt-pkg/deb/debsrcrecords.cc
@@ -14,6 +14,8 @@
#include <apt-pkg/error.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/configuration.h>
+
+using std::max;
/*}}}*/
// SrcRecordParser::Binaries - Return the binaries field /*{{{*/
@@ -30,31 +32,19 @@ const char **debSrcRecordParser::Binaries()
if (Bins.empty() == true || Bins.length() >= 102400)
return 0;
- // Workaround for #236688. Only allocate a new buffer if the field
- // is large, to avoid a performance penalty
- char *BigBuf = NULL;
- char *Buf;
- if (Bins.length() > sizeof(Buffer))
- {
- BigBuf = new char[Bins.length()];
- Buf = BigBuf;
- }
- else
+ if (Bins.length() >= BufSize)
{
- Buf = Buffer;
+ delete [] Buffer;
+ // allocate new size based on buffer (but never smaller than 4000)
+ BufSize = max((unsigned long)4000, max((unsigned long)Bins.length()+1,2*BufSize));
+ Buffer = new char[BufSize];
}
- strcpy(Buf,Bins.c_str());
- if (TokSplitString(',',Buf,StaticBinList,
+ strcpy(Buffer,Bins.c_str());
+ if (TokSplitString(',',Buffer,StaticBinList,
sizeof(StaticBinList)/sizeof(StaticBinList[0])) == false)
- {
- if (BigBuf != NULL)
- delete BigBuf;
return 0;
- }
- if (BigBuf != NULL)
- delete BigBuf;
return (const char **)StaticBinList;
}
/*}}}*/
diff --git a/apt-pkg/deb/debsrcrecords.h b/apt-pkg/deb/debsrcrecords.h
index 51e063812..55fdcb667 100644
--- a/apt-pkg/deb/debsrcrecords.h
+++ b/apt-pkg/deb/debsrcrecords.h
@@ -21,9 +21,10 @@ class debSrcRecordParser : public pkgSrcRecords::Parser
FileFd Fd;
pkgTagFile Tags;
pkgTagSection Sect;
- char Buffer[10000];
char *StaticBinList[400];
unsigned long iOffset;
+ char *Buffer;
+ unsigned long BufSize;
public:
@@ -46,10 +47,9 @@ class debSrcRecordParser : public pkgSrcRecords::Parser
};
virtual bool Files(vector<pkgSrcRecords::File> &F);
- debSrcRecordParser(string File,pkgIndexFile const *Index) :
- Parser(Index),
- Fd(File,FileFd::ReadOnly),
- Tags(&Fd,102400) {};
+ debSrcRecordParser(string File,pkgIndexFile const *Index)
+ : Parser(Index), Fd(File,FileFd::ReadOnly), Tags(&Fd,102400),
+ Buffer(0), BufSize(0) {}
};
#endif
diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index 905ac93c4..4b4bba696 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 <unistd.h>
@@ -34,7 +35,8 @@ using namespace std;
// DPkgPM::pkgDPkgPM - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* */
-pkgDPkgPM::pkgDPkgPM(pkgDepCache *Cache) : pkgPackageManager(Cache)
+pkgDPkgPM::pkgDPkgPM(pkgDepCache *Cache)
+ : pkgPackageManager(Cache), pkgFailures(0)
{
}
/*}}}*/
@@ -471,6 +473,8 @@ bool pkgDPkgPM::Go(int OutStatusFd)
case Item::Install:
Args[n++] = "--unpack";
Size += strlen(Args[n-1]);
+ Args[n++] = "--auto-deconfigure";
+ Size += strlen(Args[n-1]);
break;
}
@@ -621,15 +625,22 @@ bool pkgDPkgPM::Go(int OutStatusFd)
*/
char* list[5];
- if(!TokSplitString(':', line, list, sizeof(list)/sizeof(list[0])))
- // FIXME: 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
- // statusfd or by rewriting the code here to deal with
- // it. for now we just ignore it and not crash
- continue;
+ // 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
+ // statusfd or by rewriting the code here to deal with
+ // it. for now we just ignore it and not crash
+ TokSplitString(':', line, list, sizeof(list)/sizeof(list[0]));
char *pkg = list[1];
char *action = _strstrip(list[2]);
+ if( pkg == NULL || action == NULL)
+ {
+ if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+ std::clog << "ignoring line: not enough ':'" << std::endl;
+ // reset the line buffer
+ line[0]=0;
+ continue;
+ }
if(strncmp(action,"error",strlen("error")) == 0)
{
@@ -642,6 +653,8 @@ bool pkgDPkgPM::Go(int OutStatusFd)
line[0]=0;
if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
std::clog << "send: '" << status.str() << "'" << endl;
+ pkgFailures++;
+ WriteApportReport(list[1], list[3]);
continue;
}
if(strncmp(action,"conffile",strlen("conffile")) == 0)
@@ -701,14 +714,23 @@ bool pkgDPkgPM::Go(int OutStatusFd)
// Check for an error code.
if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
{
- RunScripts("DPkg::Post-Invoke");
- if (WIFSIGNALED(Status) != 0 && WTERMSIG(Status) == SIGSEGV)
- return _error->Error("Sub-process %s received a segmentation fault.",Args[0]);
-
- if (WIFEXITED(Status) != 0)
- return _error->Error("Sub-process %s returned an error code (%u)",Args[0],WEXITSTATUS(Status));
+ // 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);
- return _error->Error("Sub-process %s exited unexpectedly",Args[0]);
+ if(stopOnError)
+ RunScripts("DPkg::Post-Invoke");
+
+ if (WIFSIGNALED(Status) != 0 && WTERMSIG(Status) == SIGSEGV)
+ _error->Error("Sub-process %s received a segmentation fault.",Args[0]);
+ else if (WIFEXITED(Status) != 0)
+ _error->Error("Sub-process %s returned an error code (%u)",Args[0],WEXITSTATUS(Status));
+ else
+ _error->Error("Sub-process %s exited unexpectedly",Args[0]);
+
+ if(stopOnError)
+ return false;
}
}
@@ -725,3 +747,94 @@ 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)
+ return;
+
+ // only report the first error if we are in StopOnError=false mode
+ // to prevent bogus reports
+ if((_config->FindB("Dpkg::StopOnError",true) == false) && pkgFailures > 1)
+ return;
+
+ // get the pkgname and reportfile
+ pkgname = flNotDir(pkgpath);
+ pos = pkgname.rfind('_');
+ if(pos != string::npos)
+ pkgname = string(pkgname, 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);
+ pkgver = Ver.VerStr();
+ if (Ver.end() == true)
+ return;
+ 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);
+ fclose(report);
+}
+ /*}}}*/
diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h
index 45eb6b15b..a413f3a90 100644
--- a/apt-pkg/deb/dpkgpm.h
+++ b/apt-pkg/deb/dpkgpm.h
@@ -19,6 +19,7 @@ using std::vector;
class pkgDPkgPM : public pkgPackageManager
{
protected:
+ int pkgFailures;
// used for progress reporting
struct DpkgState
@@ -43,7 +44,10 @@ class pkgDPkgPM : public pkgPackageManager
bool RunScripts(const char *Cnf);
bool RunScriptsWithPkgs(const char *Cnf);
bool SendV2Pkgs(FILE *F);
-
+
+ // apport integration
+ void WriteApportReport(const char *pkgpath, const char *errormsg);
+
// The Actuall installation implementation
virtual bool Install(PkgIterator Pkg,string File);
virtual bool Configure(PkgIterator Pkg);