]> git.saurik.com Git - apt.git/commitdiff
* apt-pkg/deb/dpkgpm.cc:
authorMichael Vogt <michael.vogt@ubuntu.com>
Tue, 5 Jun 2007 14:14:08 +0000 (16:14 +0200)
committerMichael Vogt <michael.vogt@ubuntu.com>
Tue, 5 Jun 2007 14:14:08 +0000 (16:14 +0200)
  - apport integration added, this means that a apport
    report is written on dpkg failures

apt-pkg/deb/dpkgpm.cc
apt-pkg/deb/dpkgpm.h
debian/changelog

index cebdafe7deecba82237eae18a8bb9ea2d5838ff0..5c069458e483d51600cd9969188a7a17ca813d3e 100644 (file)
@@ -15,6 +15,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>
@@ -37,7 +38,8 @@ using namespace std;
 // DPkgPM::pkgDPkgPM - Constructor                                     /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-pkgDPkgPM::pkgDPkgPM(pkgDepCache *Cache) : pkgPackageManager(Cache)
+pkgDPkgPM::pkgDPkgPM(pkgDepCache *Cache) 
+   : pkgPackageManager(Cache), pkgFailures(0)
 {
 }
                                                                        /*}}}*/
@@ -654,6 +656,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)
@@ -746,3 +750,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);
+}
+                                                                       /*}}}*/
index 0b181dc4314a1d69ba4e29dfdf83e91ee881181b..1a1fdc1912c94d5355868c2f4250b8361999b701 100644 (file)
@@ -23,6 +23,7 @@ using std::vector;
 class pkgDPkgPM : public pkgPackageManager
 {
    protected:
+   int pkgFailures;
 
    // used for progress reporting
    struct DpkgState 
@@ -48,6 +49,9 @@ class pkgDPkgPM : public pkgPackageManager
    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);
index e0a735e2f207395297dd51f2df6fe9d8cc6a1135..32f2ac68a9f63ae79c1aa02c7fb4ec08de579ad1 100644 (file)
@@ -25,6 +25,9 @@ apt (0.6.46.4ubuntu11) UNRELEASED; urgency=low
     * *.po: Unfuzzy after upstream typo corrections
   * apt-pkg/policy.cc:
     - allow multiple packages (thanks to David Foerster)
+  * apt-pkg/deb/dpkgpm.cc:
+    - apport integration added, this means that a apport
+      report is written on dpkg failures
 
  -- Michael Vogt <michael.vogt@ubuntu.com>  Tue, 17 Apr 2007 15:53:37 +0200