Bläddra i källkod

Merge remote-tracking branch 'donkult/debian/experimental' into debian/experimental

Michael Vogt 11 år sedan
förälder
incheckning
245dde9619
100 ändrade filer med 5962 tillägg och 4412 borttagningar
  1. 5 0
      apt-inst/contrib/arfile.h
  2. 5 0
      apt-inst/contrib/extracttar.cc
  3. 10 1
      apt-inst/contrib/extracttar.h
  4. 8 0
      apt-inst/deb/debfile.cc
  5. 10 2
      apt-inst/deb/debfile.h
  6. 11 1
      apt-inst/dirstream.h
  7. 2174 1672
      apt-pkg/acquire-item.cc
  8. 442 426
      apt-pkg/acquire-item.h
  9. 15 10
      apt-pkg/acquire-method.cc
  10. 11 3
      apt-pkg/acquire-method.h
  11. 224 148
      apt-pkg/acquire-worker.cc
  12. 3 1
      apt-pkg/acquire-worker.h
  13. 139 24
      apt-pkg/acquire.cc
  14. 38 17
      apt-pkg/acquire.h
  15. 13 1
      apt-pkg/algorithms.cc
  16. 13 3
      apt-pkg/algorithms.h
  17. 10 11
      apt-pkg/aptconfiguration.h
  18. 0 1
      apt-pkg/cachefile.h
  19. 48 10
      apt-pkg/cacheiterators.h
  20. 26 39
      apt-pkg/cacheset.cc
  21. 45 99
      apt-pkg/cacheset.h
  22. 20 16
      apt-pkg/cdrom.cc
  23. 9 2
      apt-pkg/cdrom.h
  24. 2 1
      apt-pkg/clean.cc
  25. 2 0
      apt-pkg/clean.h
  26. 16 15
      apt-pkg/contrib/cdromutl.cc
  27. 3 0
      apt-pkg/contrib/cmndline.cc
  28. 1 0
      apt-pkg/contrib/cmndline.h
  29. 13 7
      apt-pkg/contrib/configuration.cc
  30. 3 2
      apt-pkg/contrib/configuration.h
  31. 21 1
      apt-pkg/contrib/fileutl.cc
  32. 12 1
      apt-pkg/contrib/fileutl.h
  33. 86 46
      apt-pkg/contrib/hashes.cc
  34. 37 11
      apt-pkg/contrib/hashes.h
  35. 18 1
      apt-pkg/contrib/macros.h
  36. 9 0
      apt-pkg/contrib/sha2_internal.cc
  37. 74 79
      apt-pkg/contrib/strutl.cc
  38. 2 1
      apt-pkg/contrib/strutl.h
  39. 98 427
      apt-pkg/deb/debindexfile.cc
  40. 28 75
      apt-pkg/deb/debindexfile.h
  41. 10 39
      apt-pkg/deb/deblistparser.cc
  42. 13 13
      apt-pkg/deb/deblistparser.h
  43. 333 269
      apt-pkg/deb/debmetaindex.cc
  44. 17 14
      apt-pkg/deb/debmetaindex.h
  45. 60 55
      apt-pkg/deb/debrecords.cc
  46. 33 17
      apt-pkg/deb/debrecords.h
  47. 36 22
      apt-pkg/deb/debsrcrecords.cc
  48. 4 5
      apt-pkg/deb/debsrcrecords.h
  49. 1 1
      apt-pkg/deb/debsystem.cc
  50. 0 1
      apt-pkg/deb/debversion.h
  51. 103 67
      apt-pkg/deb/dpkgpm.cc
  52. 37 40
      apt-pkg/depcache.cc
  53. 6 4
      apt-pkg/depcache.h
  54. 70 62
      apt-pkg/edsp.cc
  55. 13 29
      apt-pkg/edsp.h
  56. 6 5
      apt-pkg/edsp/edspindexfile.cc
  57. 2 1
      apt-pkg/edsp/edspindexfile.h
  58. 4 2
      apt-pkg/edsp/edsplistparser.cc
  59. 5 3
      apt-pkg/edsp/edsplistparser.h
  60. 2 2
      apt-pkg/edsp/edspsystem.cc
  61. 2 4
      apt-pkg/edsp/edspsystem.h
  62. 63 77
      apt-pkg/indexcopy.cc
  63. 23 7
      apt-pkg/indexcopy.h
  64. 126 6
      apt-pkg/indexfile.cc
  65. 73 7
      apt-pkg/indexfile.h
  66. 32 24
      apt-pkg/indexrecords.cc
  67. 9 12
      apt-pkg/indexrecords.h
  68. 24 2
      apt-pkg/init.cc
  69. 6 0
      apt-pkg/install-progress.cc
  70. 10 1
      apt-pkg/install-progress.h
  71. 57 0
      apt-pkg/metaindex.cc
  72. 14 20
      apt-pkg/metaindex.h
  73. 2 2
      apt-pkg/orderlist.h
  74. 39 13
      apt-pkg/packagemanager.cc
  75. 6 8
      apt-pkg/packagemanager.h
  76. 81 57
      apt-pkg/pkgcache.cc
  77. 151 26
      apt-pkg/pkgcache.h
  78. 200 66
      apt-pkg/pkgcachegen.cc
  79. 20 17
      apt-pkg/pkgcachegen.h
  80. 3 0
      apt-pkg/pkgrecords.cc
  81. 12 3
      apt-pkg/pkgrecords.h
  82. 2 0
      apt-pkg/pkgsystem.cc
  83. 3 2
      apt-pkg/pkgsystem.h
  84. 29 54
      apt-pkg/policy.cc
  85. 3 2
      apt-pkg/policy.h
  86. 1 1
      apt-pkg/sourcelist.cc
  87. 12 16
      apt-pkg/sourcelist.h
  88. 30 1
      apt-pkg/srcrecords.cc
  89. 9 11
      apt-pkg/srcrecords.h
  90. 109 0
      apt-pkg/tagfile-order.c
  91. 237 95
      apt-pkg/tagfile.cc
  92. 56 27
      apt-pkg/tagfile.h
  93. 18 10
      apt-pkg/upgrade.cc
  94. 9 4
      apt-pkg/upgrade.h
  95. 3 7
      apt-pkg/vendorlist.cc
  96. 3 0
      apt-pkg/version.cc
  97. 1 1
      apt-pkg/version.h
  98. 23 22
      apt-pkg/versionmatch.cc
  99. 2 2
      apt-pkg/versionmatch.h
  100. 0 0
      apt-private/acqprogress.cc

+ 5 - 0
apt-inst/contrib/arfile.h

@@ -17,6 +17,7 @@
 
 
 #include <string>
+#include <apt-pkg/macros.h>
 #ifndef APT_8_CLEANER_HEADERS
 #include <apt-pkg/fileutl.h>
 #endif
@@ -61,7 +62,11 @@ struct ARArchive::Member
    unsigned long long Size;
    
    // Location of the data.
+#if APT_PKG_ABI >= 413
    unsigned long long Start;
+#else
+   unsigned long Start;
+#endif
    Member *Next;
    
    Member() : Start(0), Next(0) {};

+ 5 - 0
apt-inst/contrib/extracttar.cc

@@ -60,8 +60,13 @@ struct ExtractTar::TarHeader
 // ExtractTar::ExtractTar - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 /* */
+#if APT_PKG_ABI >= 413
 ExtractTar::ExtractTar(FileFd &Fd,unsigned long long Max,string DecompressionProgram)
 	: File(Fd), MaxInSize(Max), DecompressProg(DecompressionProgram)
+#else
+ExtractTar::ExtractTar(FileFd &Fd,unsigned long Max,string DecompressionProgram)
+	: File(Fd), MaxInSize(Max), DecompressProg(DecompressionProgram)
+#endif
 {
    GZPid = -1;
    Eof = false;

+ 10 - 1
apt-inst/contrib/extracttar.h

@@ -15,6 +15,7 @@
 #define PKGLIB_EXTRACTTAR_H
 
 #include <apt-pkg/fileutl.h>
+#include <apt-pkg/macros.h>
 
 #include <string>
 
@@ -39,7 +40,11 @@ class ExtractTar
                   GNU_LongLink = 'K',GNU_LongName = 'L'};
 
    FileFd &File;
+#if APT_PKG_ABI >= 413
    unsigned long long MaxInSize;
+#else
+   unsigned long MaxInSize;
+#endif
    int GZPid;
    FileFd InFd;
    bool Eof;
@@ -52,8 +57,12 @@ class ExtractTar
    public:
 
    bool Go(pkgDirStream &Stream);
-   
+
+#if APT_PKG_ABI >= 413
    ExtractTar(FileFd &Fd,unsigned long long Max,std::string DecompressionProgram);
+#else
+   ExtractTar(FileFd &Fd,unsigned long Max,std::string DecompressionProgram);
+#endif
    virtual ~ExtractTar();
 };
 

+ 8 - 0
apt-inst/deb/debfile.cc

@@ -203,7 +203,11 @@ bool debDebFile::MemControlExtract::DoItem(Item &Itm,int &Fd)
 /* Just memcopy the block from the tar extractor and put it in the right
    place in the pre-allocated memory block. */
 bool debDebFile::MemControlExtract::Process(Item &/*Itm*/,const unsigned char *Data,
+#if APT_PKG_ABI >= 413
 			     unsigned long long Size,unsigned long long Pos)
+#else
+			     unsigned long Size,unsigned long Pos)
+#endif
 {
    memcpy(Control + Pos, Data,Size);
    return true;
@@ -232,7 +236,11 @@ bool debDebFile::MemControlExtract::Read(debDebFile &Deb)
 // ---------------------------------------------------------------------
 /* The given memory block is loaded into the parser and parsed as a control
    record. */
+#if APT_PKG_ABI >= 413
 bool debDebFile::MemControlExtract::TakeControl(const void *Data,unsigned long long Size)
+#else
+bool debDebFile::MemControlExtract::TakeControl(const void *Data,unsigned long Size)
+#endif
 {
    delete [] Control;
    Control = new char[Size+2];

+ 10 - 2
apt-inst/deb/debfile.h

@@ -27,6 +27,7 @@
 #include <apt-pkg/arfile.h>
 #include <apt-pkg/dirstream.h>
 #include <apt-pkg/tagfile.h>
+#include <apt-pkg/macros.h>
 
 #include <string>
 
@@ -81,13 +82,20 @@ class debDebFile::MemControlExtract : public pkgDirStream
    // Members from DirStream
    virtual bool DoItem(Item &Itm,int &Fd);
    virtual bool Process(Item &Itm,const unsigned char *Data,
+#if APT_PKG_ABI >= 413
 			unsigned long long Size,unsigned long long Pos);
-   
+#else
+			unsigned long Size,unsigned long Pos);
+#endif
 
    // Helpers
    bool Read(debDebFile &Deb);
+#if APT_PKG_ABI >= 413
    bool TakeControl(const void *Data,unsigned long long Size);
-      
+#else
+   bool TakeControl(const void *Data,unsigned long Size);
+#endif
+
    MemControlExtract() : IsControl(false), Control(0), Length(0), Member("control") {};
    MemControlExtract(std::string Member) : IsControl(false), Control(0), Length(0), Member(Member) {};
    ~MemControlExtract() {delete [] Control;};   

+ 11 - 1
apt-inst/dirstream.h

@@ -25,6 +25,7 @@
 #ifndef PKGLIB_DIRSTREAM_H
 #define PKGLIB_DIRSTREAM_H
 
+#include <apt-pkg/macros.h>
 
 class pkgDirStream
 { 
@@ -37,10 +38,15 @@ class pkgDirStream
 	           Directory, FIFO} Type;
       char *Name;
       char *LinkTarget;
+#if APT_PKG_ABI >= 413
       unsigned long long Size;
+#endif
       unsigned long Mode;
       unsigned long UID;
       unsigned long GID;
+#if APT_PKG_ABI < 413
+      unsigned long Size;
+#endif
       unsigned long MTime;
       unsigned long Major;
       unsigned long Minor;
@@ -49,9 +55,13 @@ class pkgDirStream
    virtual bool DoItem(Item &Itm,int &Fd);
    virtual bool Fail(Item &Itm,int Fd);
    virtual bool FinishedFile(Item &Itm,int Fd);
+#if APT_PKG_ABI >= 413
    virtual bool Process(Item &/*Itm*/,const unsigned char * /*Data*/,
 			unsigned long long /*Size*/,unsigned long long /*Pos*/) {return true;};
-      
+#else
+   virtual bool Process(Item &/*Itm*/,const unsigned char * /*Data*/,
+			unsigned long /*Size*/,unsigned long /*Pos*/) {return true;};
+#endif
    virtual ~pkgDirStream() {};   
 };
 

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 2174 - 1672
apt-pkg/acquire-item.cc


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 442 - 426
apt-pkg/acquire-item.h


+ 15 - 10
apt-pkg/acquire-method.cc

@@ -376,7 +376,10 @@ int pkgAcqMethod::Run(bool Single)
 		  Tmp->ExpectedHashes.push_back(HashString(*t, hash));
 	    }
             char *End;
-            Tmp->MaximumSize = strtoll(LookupTag(Message, "Maximum-Size", "0").c_str(), &End, 10);
+	    if (Tmp->ExpectedHashes.FileSize() > 0)
+	       Tmp->MaximumSize = Tmp->ExpectedHashes.FileSize();
+	    else
+	       Tmp->MaximumSize = strtoll(LookupTag(Message, "Maximum-Size", "0").c_str(), &End, 10);
 	    Tmp->Next = 0;
 	    
 	    // Append it to the list
@@ -385,14 +388,14 @@ int pkgAcqMethod::Run(bool Single)
 	    *I = Tmp;
 	    if (QueueBack == 0)
 	       QueueBack = Tmp;
-	    
+
 	    // Notify that this item is to be fetched.
-	    if (Fetch(Tmp) == false)
+	    if (URIAcquire(Message, Tmp) == false)
 	       Fail();
-	    
-	    break;					     
-	 }   
-      }      
+
+	    break;
+	 }
+      }
    }
 
    Exit();
@@ -400,8 +403,6 @@ int pkgAcqMethod::Run(bool Single)
 }
 									/*}}}*/
 // AcqMethod::PrintStatus - privately really send a log/status message	/*{{{*/
-// ---------------------------------------------------------------------
-/* */
 void pkgAcqMethod::PrintStatus(char const * const header, const char* Format,
 			       va_list &args) const
 {
@@ -477,5 +478,9 @@ void pkgAcqMethod::Dequeue() {						/*{{{*/
    delete Tmp;
 }
 									/*}}}*/
-
 pkgAcqMethod::~pkgAcqMethod() {}
+
+pkgAcqMethod::FetchItem::FetchItem() {}
+pkgAcqMethod::FetchItem::~FetchItem() {}
+
+pkgAcqMethod::FetchResult::~FetchResult() {}

+ 11 - 3
apt-pkg/acquire-method.h

@@ -1,6 +1,5 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: acquire-method.h,v 1.15.2.1 2003/12/24 23:09:17 mdz Exp $
 /* ######################################################################
 
    Acquire Method - Method helper class + functions
@@ -53,6 +52,11 @@ class pkgAcqMethod
       // for when we know it or a arbitrary limit when we don't know the
       // filesize (like a InRelease file)
       unsigned long long MaximumSize;
+
+      FetchItem();
+      virtual ~FetchItem();
+      private:
+      void *d;
    };
    
    struct FetchResult
@@ -67,6 +71,9 @@ class pkgAcqMethod
       
       void TakeHashes(class Hashes &Hash);
       FetchResult();
+      virtual ~FetchResult();
+      private:
+      void *d;
    };
 
    // State
@@ -76,11 +83,12 @@ class pkgAcqMethod
    std::string FailReason;
    std::string UsedMirror;
    std::string IP;
-   
+
    // Handlers for messages
    virtual bool Configuration(std::string Message);
    virtual bool Fetch(FetchItem * /*Item*/) {return true;};
-   
+   virtual bool URIAcquire(std::string const &/*Message*/, FetchItem *Itm) { return Fetch(Itm); };
+
    // Outgoing messages
    void Fail(bool Transient = false);
    inline void Fail(const char *Why, bool Transient = false) {Fail(std::string(Why),Transient);};

+ 224 - 148
apt-pkg/acquire-worker.cc

@@ -43,20 +43,6 @@
 
 using namespace std;
 
-static void ChangeOwnerAndPermissionOfFile(char const * const requester, char const * const file, char const * const user, char const * const group, mode_t const mode) /*{{{*/
-{
-   if (getuid() == 0 && strlen(user) != 0 && strlen(group) != 0) // if we aren't root, we can't chown, so don't try it
-   {
-      // ensure the file is owned by root and has good permissions
-      struct passwd const * const pw = getpwnam(user);
-      struct group const * const gr = getgrnam(group);
-      if (pw != NULL && gr != NULL && chown(file, pw->pw_uid, gr->gr_gid) != 0)
-	 _error->WarningE(requester, "chown to %s:%s of file %s failed", user, group, file);
-   }
-   if (chmod(file, mode) != 0)
-      _error->WarningE(requester, "chmod 0%o of file %s failed", mode, file);
-}
-									/*}}}*/
 // Worker::Worker - Constructor for Queue startup			/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -69,8 +55,8 @@ pkgAcquire::Worker::Worker(Queue *Q,MethodConfig *Cnf,
    CurrentItem = 0;
    TotalSize = 0;
    CurrentSize = 0;
-   
-   Construct();   
+
+   Construct();
 }
 									/*}}}*/
 // Worker::Worker - Constructor for method config startup		/*{{{*/
@@ -84,8 +70,8 @@ pkgAcquire::Worker::Worker(MethodConfig *Cnf)
    CurrentItem = 0;
    TotalSize = 0;
    CurrentSize = 0;
-   
-   Construct();   
+
+   Construct();
 }
 									/*}}}*/
 // Worker::Construct - Constructor helper				/*{{{*/
@@ -150,7 +136,7 @@ bool pkgAcquire::Worker::Start()
    }
    for (int I = 0; I != 4; I++)
       SetCloseExec(Pipes[I],true);
-   
+
    // Fork off the process
    Process = ExecFork();
    if (Process == 0)
@@ -159,9 +145,9 @@ bool pkgAcquire::Worker::Start()
       dup2(Pipes[1],STDOUT_FILENO);
       dup2(Pipes[2],STDIN_FILENO);
       SetCloseExec(STDOUT_FILENO,false);
-      SetCloseExec(STDIN_FILENO,false);      
+      SetCloseExec(STDIN_FILENO,false);
       SetCloseExec(STDERR_FILENO,false);
-      
+
       const char *Args[2];
       Args[0] = Method.c_str();
       Args[1] = 0;
@@ -179,7 +165,7 @@ bool pkgAcquire::Worker::Start()
    close(Pipes[2]);
    OutReady = false;
    InReady = true;
-   
+
    // Read the configuration data
    if (WaitFd(InFd) == false ||
        ReadMessages() == false)
@@ -188,7 +174,7 @@ bool pkgAcquire::Worker::Start()
    RunMessages();
    if (OwnerQ != 0)
       SendConfiguration();
-   
+
    return true;
 }
 									/*}}}*/
@@ -215,7 +201,7 @@ bool pkgAcquire::Worker::RunMessages()
 
       if (Debug == true)
 	 clog << " <- " << Access << ':' << QuoteString(Message,"\n") << endl;
-      
+
       // Fetch the message number
       char *End;
       int Number = strtol(Message.c_str(),&End,10);
@@ -229,15 +215,15 @@ bool pkgAcquire::Worker::RunMessages()
 
       // update used mirror
       string UsedMirror = LookupTag(Message,"UsedMirror", "");
-      if (!UsedMirror.empty() && 
+      if (!UsedMirror.empty() &&
           Itm && 
-          Itm->Description.find(" ") != string::npos) 
+          Itm->Description.find(" ") != string::npos)
       {
          Itm->Description.replace(0, Itm->Description.find(" "), UsedMirror);
          // FIXME: will we need this as well?
          //Itm->ShortDesc = UsedMirror;
       }
-      
+
       // Determine the message number and dispatch
       switch (Number)
       {
@@ -246,18 +232,18 @@ bool pkgAcquire::Worker::RunMessages()
 	 if (Capabilities(Message) == false)
 	    return _error->Error("Unable to process Capabilities message from %s",Access.c_str());
 	 break;
-	 
+
 	 // 101 Log
 	 case 101:
 	 if (Debug == true)
 	    clog << " <- (log) " << LookupTag(Message,"Message") << endl;
 	 break;
-	 
+
 	 // 102 Status
 	 case 102:
 	 Status = LookupTag(Message,"Message");
 	 break;
-	    
+
          // 103 Redirect
          case 103:
          {
@@ -266,27 +252,36 @@ bool pkgAcquire::Worker::RunMessages()
                _error->Error("Method gave invalid 103 Redirect message");
                break;
             }
- 
+
             string NewURI = LookupTag(Message,"New-URI",URI.c_str());
             Itm->URI = NewURI;
 
 	    ItemDone();
 
-	    pkgAcquire::Item *Owner = Itm->Owner;
-	    pkgAcquire::ItemDesc Desc = *Itm;
-
 	    // Change the status so that it can be dequeued
-	    Owner->Status = pkgAcquire::Item::StatIdle;
+	    for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O)
+	    {
+	       pkgAcquire::Item *Owner = *O;
+	       Owner->Status = pkgAcquire::Item::StatIdle;
+	    }
 	    // Mark the item as done (taking care of all queues)
 	    // and then put it in the main queue again
+	    std::vector<Item*> const ItmOwners = Itm->Owners;
 	    OwnerQ->ItemDone(Itm);
-	    OwnerQ->Owner->Enqueue(Desc);
+	    Itm = NULL;
+	    for (pkgAcquire::Queue::QItem::owner_iterator O = ItmOwners.begin(); O != ItmOwners.end(); ++O)
+	    {
+	       pkgAcquire::Item *Owner = *O;
+	       pkgAcquire::ItemDesc desc = Owner->GetItemDesc();
+	       desc.URI = NewURI;
+	       OwnerQ->Owner->Enqueue(desc);
 
-	    if (Log != 0)
-	       Log->Done(Desc);
+	       if (Log != 0)
+		  Log->Done(Owner->GetItemDesc());
+	    }
             break;
          }
-   
+
 	 // 200 URI Start
 	 case 200:
 	 {
@@ -295,23 +290,27 @@ bool pkgAcquire::Worker::RunMessages()
 	       _error->Error("Method gave invalid 200 URI Start message");
 	       break;
 	    }
-	    
+
 	    CurrentItem = Itm;
 	    CurrentSize = 0;
 	    TotalSize = strtoull(LookupTag(Message,"Size","0").c_str(), NULL, 10);
 	    ResumePoint = strtoull(LookupTag(Message,"Resume-Point","0").c_str(), NULL, 10);
-	    Itm->Owner->Start(Message,strtoull(LookupTag(Message,"Size","0").c_str(), NULL, 10));
+	    for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O)
+	    {
+	       (*O)->Start(Message, TotalSize);
 
-	    // Display update before completion
-	    if (Log != 0 && Log->MorePulses == true)
-	       Log->Pulse(Itm->Owner->GetOwner());
-	    
-	    if (Log != 0)
-	       Log->Fetch(*Itm);
+	       // Display update before completion
+	       if (Log != 0)
+	       {
+		  if (Log->MorePulses == true)
+		     Log->Pulse((*O)->GetOwner());
+		  Log->Fetch((*O)->GetItemDesc());
+	       }
+	    }
 
 	    break;
 	 }
-	 
+
 	 // 201 URI Done
 	 case 201:
 	 {
@@ -320,72 +319,113 @@ bool pkgAcquire::Worker::RunMessages()
 	       _error->Error("Method gave invalid 201 URI Done message");
 	       break;
 	    }
-	    
-	    pkgAcquire::Item *Owner = Itm->Owner;
-	    pkgAcquire::ItemDesc Desc = *Itm;
 
-	    if (RealFileExists(Owner->DestFile))
-	       ChangeOwnerAndPermissionOfFile("201::URIDone", Owner->DestFile.c_str(), "root", "root", 0644);
+	    PrepareFiles("201::URIDone", Itm);
 
 	    // Display update before completion
 	    if (Log != 0 && Log->MorePulses == true)
-	       Log->Pulse(Owner->GetOwner());
-	    
-	    OwnerQ->ItemDone(Itm);
-	    unsigned long long const ServerSize = strtoull(LookupTag(Message,"Size","0").c_str(), NULL, 10);
-            bool isHit = StringToBool(LookupTag(Message,"IMS-Hit"),false) ||
-                         StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false);
-            // Using the https method the server might return 200, but the
-            // If-Modified-Since condition is not satsified, libcurl will
-            // discard the download. In this case, however, TotalSize will be
-            // set to the actual size of the file, while ServerSize will be set
-            // to 0. Therefore, if the item is marked as a hit and the
-            // downloaded size (ServerSize) is 0, we ignore TotalSize.
-	    if (TotalSize != 0 && (!isHit || ServerSize != 0) && ServerSize != TotalSize)
-	       _error->Warning("Size of file %s is not what the server reported %s %llu",
-			       Owner->DestFile.c_str(), LookupTag(Message,"Size","0").c_str(),TotalSize);
-
-	    // see if there is a hash to verify
-	    HashStringList RecivedHashes;
-	    HashStringList expectedHashes = Owner->HashSums();
-	    for (HashStringList::const_iterator hs = expectedHashes.begin(); hs != expectedHashes.end(); ++hs)
-	    {
-	       std::string const tagname = hs->HashType() + "-Hash";
-	       std::string const hashsum = LookupTag(Message, tagname.c_str());
-	       if (hashsum.empty() == false)
-		  RecivedHashes.push_back(HashString(hs->HashType(), hashsum));
-	    }
+	       for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O)
+		  Log->Pulse((*O)->GetOwner());
 
-	    if(_config->FindB("Debug::pkgAcquire::Auth", false) == true)
+	    std::string const filename = LookupTag(Message, "Filename", Itm->Owner->DestFile.c_str());
+	    HashStringList ReceivedHashes;
 	    {
-	       std::clog << "201 URI Done: " << Owner->DescURI() << endl
-		  << "RecivedHash:" << endl;
-	       for (HashStringList::const_iterator hs = RecivedHashes.begin(); hs != RecivedHashes.end(); ++hs)
-		  std::clog <<  "\t- " << hs->toStr() << std::endl;
-	       std::clog << "ExpectedHash:" << endl;
-	       for (HashStringList::const_iterator hs = expectedHashes.begin(); hs != expectedHashes.end(); ++hs)
-		  std::clog <<  "\t- " << hs->toStr() << std::endl;
-	       std::clog << endl;
+	       // see if we got hashes to verify
+	       for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type)
+	       {
+		  std::string const tagname = std::string(*type) + "-Hash";
+		  std::string const hashsum = LookupTag(Message, tagname.c_str());
+		  if (hashsum.empty() == false)
+		     ReceivedHashes.push_back(HashString(*type, hashsum));
+	       }
+	       // not all methods always sent Hashes our way
+	       if (ReceivedHashes.usable() == false)
+	       {
+		  HashStringList const ExpectedHashes = Itm->GetExpectedHashes();
+		  if (ExpectedHashes.usable() == true && RealFileExists(filename))
+		  {
+		     Hashes calc(ExpectedHashes);
+		     FileFd file(filename, FileFd::ReadOnly, FileFd::None);
+		     calc.AddFD(file);
+		     ReceivedHashes = calc.GetHashStringList();
+		  }
+	       }
 	    }
-	    Owner->Done(Message, ServerSize, RecivedHashes, Config);
-	    ItemDone();
 
-	    // Log that we are done
-	    if (Log != 0)
+	    // only local files can refer other filenames and counting them as fetched would be unfair
+	    if (Log !=  NULL && filename != Itm->Owner->DestFile)
+	       Log->Fetched(ReceivedHashes.FileSize(),atoi(LookupTag(Message,"Resume-Point","0").c_str()));
+
+	    std::vector<Item*> const ItmOwners = Itm->Owners;
+	    OwnerQ->ItemDone(Itm);
+	    Itm = NULL;
+
+	    bool const isIMSHit = StringToBool(LookupTag(Message,"IMS-Hit"),false) ||
+	       StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false);
+	    for (pkgAcquire::Queue::QItem::owner_iterator O = ItmOwners.begin(); O != ItmOwners.end(); ++O)
 	    {
-	       if (isHit)
+	       pkgAcquire::Item * const Owner = *O;
+	       HashStringList const ExpectedHashes = Owner->GetExpectedHashes();
+	       if(_config->FindB("Debug::pkgAcquire::Auth", false) == true)
+	       {
+		  std::clog << "201 URI Done: " << Owner->DescURI() << endl
+		     << "ReceivedHash:" << endl;
+		  for (HashStringList::const_iterator hs = ReceivedHashes.begin(); hs != ReceivedHashes.end(); ++hs)
+		     std::clog <<  "\t- " << hs->toStr() << std::endl;
+		  std::clog << "ExpectedHash:" << endl;
+		  for (HashStringList::const_iterator hs = ExpectedHashes.begin(); hs != ExpectedHashes.end(); ++hs)
+		     std::clog <<  "\t- " << hs->toStr() << std::endl;
+		  std::clog << endl;
+	       }
+
+	       // decide if what we got is what we expected
+	       bool consideredOkay = false;
+	       if (ExpectedHashes.usable())
+	       {
+		  if (ReceivedHashes.usable() == false)
+		  {
+		     /* IMS-Hits can't be checked here as we will have uncompressed file,
+			but the hashes for the compressed file. What we have was good through
+			so all we have to ensure later is that we are not stalled. */
+		     consideredOkay = isIMSHit;
+		  }
+		  else if (ReceivedHashes == ExpectedHashes)
+		     consideredOkay = true;
+		  else
+		     consideredOkay = false;
+
+	       }
+	       else if (Owner->HashesRequired() == true)
+		  consideredOkay = false;
+	       else
+		  consideredOkay = true;
+
+	       if (consideredOkay == true)
 	       {
-		  /* Hide 'hits' for local only sources - we also manage to
-		     hide gets */
-		  if (Config->LocalOnly == false)
-		     Log->IMSHit(Desc);
-	       }	       
+		  Owner->Done(Message, ReceivedHashes, Config);
+
+		  // Log that we are done
+		  if (Log != 0)
+		  {
+		     if (isIMSHit)
+			Log->IMSHit(Owner->GetItemDesc());
+		     else
+			Log->Done(Owner->GetItemDesc());
+		  }
+	       }
 	       else
-		  Log->Done(Desc);
+	       {
+		  Owner->Status = pkgAcquire::Item::StatAuthError;
+		  Owner->Failed(Message,Config);
+
+		  if (Log != 0)
+		     Log->Fail(Owner->GetItemDesc());
+	       }
 	    }
+	    ItemDone();
 	    break;
-	 }	 
-	 
+	 }
+
 	 // 400 URI Failure
 	 case 400:
 	 {
@@ -396,44 +436,46 @@ bool pkgAcquire::Worker::RunMessages()
 	       break;
 	    }
 
+	    PrepareFiles("400::URIFailure", Itm);
+
 	    // Display update before completion
 	    if (Log != 0 && Log->MorePulses == true)
-	       Log->Pulse(Itm->Owner->GetOwner());
-
-	    pkgAcquire::Item *Owner = Itm->Owner;
-	    pkgAcquire::ItemDesc Desc = *Itm;
-
-	    if (RealFileExists(Owner->DestFile))
-	       ChangeOwnerAndPermissionOfFile("400::URIFailure", Owner->DestFile.c_str(), "root", "root", 0644);
+	       for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O)
+		  Log->Pulse((*O)->GetOwner());
 
+	    std::vector<Item*> const ItmOwners = Itm->Owners;
 	    OwnerQ->ItemDone(Itm);
+	    Itm = NULL;
+
+	    for (pkgAcquire::Queue::QItem::owner_iterator O = ItmOwners.begin(); O != ItmOwners.end(); ++O)
+	    {
+	       // set some status
+	       if(LookupTag(Message,"FailReason") == "Timeout" ||
+		     LookupTag(Message,"FailReason") == "TmpResolveFailure" ||
+		     LookupTag(Message,"FailReason") == "ResolveFailure" ||
+		     LookupTag(Message,"FailReason") == "ConnectionRefused")
+		  (*O)->Status = pkgAcquire::Item::StatTransientNetworkError;
 
-	    // set some status
-	    if(LookupTag(Message,"FailReason") == "Timeout" || 
-	       LookupTag(Message,"FailReason") == "TmpResolveFailure" ||
-	       LookupTag(Message,"FailReason") == "ResolveFailure" ||
-	       LookupTag(Message,"FailReason") == "ConnectionRefused") 
-	       Owner->Status = pkgAcquire::Item::StatTransientNetworkError;
+	       (*O)->Failed(Message,Config);
 
-	    Owner->Failed(Message,Config);
+	       if (Log != 0)
+		  Log->Fail((*O)->GetItemDesc());
+	    }
 	    ItemDone();
 
-	    if (Log != 0)
-	       Log->Fail(Desc);
-
 	    break;
-	 }	 
-	 
+	 }
+
 	 // 401 General Failure
 	 case 401:
 	 _error->Error("Method %s General failure: %s",Access.c_str(),LookupTag(Message,"Message").c_str());
 	 break;
-	 
+
 	 // 403 Media Change
 	 case 403:
-	 MediaChange(Message); 
+	 MediaChange(Message);
 	 break;
-      }      
+      }
    }
    return true;
 }
@@ -446,7 +488,7 @@ bool pkgAcquire::Worker::Capabilities(string Message)
 {
    if (Config == 0)
       return true;
-   
+
    Config->Version = LookupTag(Message,"Version");
    Config->SingleInstance = StringToBool(LookupTag(Message,"Single-Instance"),false);
    Config->Pipeline = StringToBool(LookupTag(Message,"Pipeline"),false);
@@ -461,13 +503,13 @@ bool pkgAcquire::Worker::Capabilities(string Message)
       clog << "Configured access method " << Config->Access << endl;
       clog << "Version:" << Config->Version <<
 	      " SingleInstance:" << Config->SingleInstance <<
-	      " Pipeline:" << Config->Pipeline << 
-	      " SendConfig:" << Config->SendConfig << 
-	      " LocalOnly: " << Config->LocalOnly << 
-	      " NeedsCleanup: " << Config->NeedsCleanup << 
+	      " Pipeline:" << Config->Pipeline <<
+	      " SendConfig:" << Config->SendConfig <<
+	      " LocalOnly: " << Config->LocalOnly <<
+	      " NeedsCleanup: " << Config->NeedsCleanup <<
 	      " Removable: " << Config->Removable << endl;
    }
-   
+
    return true;
 }
 									/*}}}*/
@@ -477,10 +519,10 @@ bool pkgAcquire::Worker::Capabilities(string Message)
 bool pkgAcquire::Worker::MediaChange(string Message)
 {
    int status_fd = _config->FindI("APT::Status-Fd",-1);
-   if(status_fd > 0) 
+   if(status_fd > 0)
    {
       string Media = LookupTag(Message,"Media");
-      string Drive = LookupTag(Message,"Drive"); 
+      string Drive = LookupTag(Message,"Drive");
       ostringstream msg,status;
       ioprintf(msg,_("Please insert the disc labeled: "
 		     "'%s' "
@@ -550,21 +592,29 @@ bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item)
 {
    if (OutFd == -1)
       return false;
-   
+
    string Message = "600 URI Acquire\n";
    Message.reserve(300);
    Message += "URI: " + Item->URI;
    Message += "\nFilename: " + Item->Owner->DestFile;
-   HashStringList const hsl = Item->Owner->HashSums();
+
+   HashStringList const hsl = Item->GetExpectedHashes();
    for (HashStringList::const_iterator hs = hsl.begin(); hs != hsl.end(); ++hs)
       Message += "\nExpected-" + hs->HashType() + ": " + hs->HashValue();
-   if(Item->Owner->FileSize > 0)
+
+   if (hsl.FileSize() == 0)
    {
-      string MaximumSize;
-      strprintf(MaximumSize, "%llu", Item->Owner->FileSize);
-      Message += "\nMaximum-Size: " + MaximumSize;
+      unsigned long long FileSize = Item->GetMaximumSize();
+      if(FileSize > 0)
+      {
+	 string MaximumSize;
+	 strprintf(MaximumSize, "%llu", FileSize);
+	 Message += "\nMaximum-Size: " + MaximumSize;
+      }
    }
-   Message += Item->Owner->Custom600Headers();
+
+   Item->SyncDestinationFiles();
+   Message += Item->Custom600Headers();
    Message += "\n\n";
 
    if (RealFileExists(Item->Owner->DestFile))
@@ -578,7 +628,7 @@ bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item)
       clog << " -> " << Access << ':' << QuoteString(Message,"\n") << endl;
    OutQueue += Message;
    OutReady = true;
-   
+
    return true;
 }
 									/*}}}*/
@@ -600,7 +650,7 @@ bool pkgAcquire::Worker::OutFdReady()
    OutQueue.erase(0,Res);
    if (OutQueue.empty() == true)
       OutReady = false;
-   
+
    return true;
 }
 									/*}}}*/
@@ -622,7 +672,7 @@ bool pkgAcquire::Worker::InFdReady()
 bool pkgAcquire::Worker::MethodFailure()
 {
    _error->Error("Method %s has died unexpectedly!",Access.c_str());
-   
+
    // do not reap the child here to show meaningfull error to the user
    ExecWait(Process,Access.c_str(),false);
    Process = -1;
@@ -634,26 +684,22 @@ bool pkgAcquire::Worker::MethodFailure()
    InReady = false;
    OutQueue = string();
    MessageQueue.erase(MessageQueue.begin(),MessageQueue.end());
-   
+
    return false;
 }
 									/*}}}*/
-// Worker::Pulse - Called periodically 					/*{{{*/
+// Worker::Pulse - Called periodically					/*{{{*/
 // ---------------------------------------------------------------------
 /* */
 void pkgAcquire::Worker::Pulse()
 {
    if (CurrentItem == 0)
       return;
- 
+
    struct stat Buf;
    if (stat(CurrentItem->Owner->DestFile.c_str(),&Buf) != 0)
       return;
    CurrentSize = Buf.st_size;
-   
-   // Hmm? Should not happen...
-   if (CurrentSize > TotalSize && TotalSize != 0)
-      TotalSize = CurrentSize;
 }
 									/*}}}*/
 // Worker::ItemDone - Called when the current item is finished		/*{{{*/
@@ -667,3 +713,33 @@ void pkgAcquire::Worker::ItemDone()
    Status = string();
 }
 									/*}}}*/
+void pkgAcquire::Worker::PrepareFiles(char const * const caller, pkgAcquire::Queue::QItem const * const Itm)/*{{{*/
+{
+   if (RealFileExists(Itm->Owner->DestFile))
+   {
+      ChangeOwnerAndPermissionOfFile(caller, Itm->Owner->DestFile.c_str(), "root", "root", 0644);
+      std::string const filename = Itm->Owner->DestFile;
+      for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O)
+      {
+	 pkgAcquire::Item const * const Owner = *O;
+	 if (Owner->DestFile == filename)
+	    continue;
+	 unlink(Owner->DestFile.c_str());
+	 if (link(filename.c_str(), Owner->DestFile.c_str()) != 0)
+	 {
+	    // diferent mounts can't happen for us as we download to lists/ by default,
+	    // but if the system is reused by others the locations can potentially be on
+	    // different disks, so use symlink as poor-men replacement.
+	    // FIXME: Real copying as last fallback, but that is costly, so offload to a method preferable
+	    if (symlink(filename.c_str(), Owner->DestFile.c_str()) != 0)
+	       _error->Error("Can't create (sym)link of file %s to %s", filename.c_str(), Owner->DestFile.c_str());
+	 }
+      }
+   }
+   else
+   {
+      for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O)
+	 unlink((*O)->DestFile.c_str());
+   }
+}
+									/*}}}*/

+ 3 - 1
apt-pkg/acquire-worker.h

@@ -1,6 +1,5 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: acquire-worker.h,v 1.12 2001/02/20 07:03:17 jgg Exp $
 /* ######################################################################
 
    Acquire Worker - Worker process manager
@@ -326,6 +325,9 @@ class pkgAcquire::Worker : public WeakPointable
     *  \b false, also rudely interrupts the worker with a SIGINT.
     */
    virtual ~Worker();
+
+private:
+   APT_HIDDEN void PrepareFiles(char const * const caller, pkgAcquire::Queue::QItem const * const Itm);
 };
 
 /** @} */

+ 139 - 24
apt-pkg/acquire.cc

@@ -23,6 +23,7 @@
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/fileutl.h>
 
+#include <algorithm>
 #include <string>
 #include <vector>
 #include <iostream>
@@ -92,8 +93,11 @@ void pkgAcquire::Initialize()
 static bool SetupAPTPartialDirectory(std::string const &grand, std::string const &parent)
 {
    std::string const partial = parent + "partial";
-   if (CreateAPTDirectoryIfNeeded(grand, partial) == false &&
-	 CreateAPTDirectoryIfNeeded(parent, partial) == false)
+   mode_t const mode = umask(S_IWGRP | S_IWOTH);
+   bool const creation_fail = (CreateAPTDirectoryIfNeeded(grand, partial) == false &&
+	 CreateAPTDirectoryIfNeeded(parent, partial) == false);
+   umask(mode);
+   if (creation_fail == true)
       return false;
 
    std::string const SandboxUser = _config->Find("APT::Sandbox::User");
@@ -152,6 +156,8 @@ bool pkgAcquire::GetLock(std::string const &Lock)
       return true;
 
    // Lock the directory this acquire object will work in
+   if (LockFD != -1)
+      close(LockFD);
    LockFD = ::GetLock(flCombine(Lock, "lock"));
    if (LockFD == -1)
       return _error->Error(_("Unable to lock directory %s"), Lock.c_str());
@@ -674,10 +680,14 @@ bool pkgAcquire::Queue::Enqueue(ItemDesc &Item)
 {
    QItem **I = &Items;
    // move to the end of the queue and check for duplicates here
+   HashStringList const hsl = Item.Owner->GetExpectedHashes();
    for (; *I != 0; I = &(*I)->Next)
-      if (Item.URI == (*I)->URI) 
+      if (Item.URI == (*I)->URI || hsl == (*I)->Owner->GetExpectedHashes())
       {
-	 Item.Owner->Status = Item::StatDone;
+	 if (_config->FindB("Debug::pkgAcquire::Worker",false) == true)
+	    std::cerr << " @ Queue: Action combined for " << Item.URI << " and " << (*I)->URI << std::endl;
+	 (*I)->Owners.push_back(Item.Owner);
+	 Item.Owner->Status = (*I)->Owner->Status;
 	 return false;
       }
 
@@ -700,13 +710,13 @@ bool pkgAcquire::Queue::Dequeue(Item *Owner)
 {
    if (Owner->Status == pkgAcquire::Item::StatFetching)
       return _error->Error("Tried to dequeue a fetching object");
-       
+
    bool Res = false;
-   
+
    QItem **I = &Items;
    for (; *I != 0;)
    {
-      if ((*I)->Owner == Owner)
+      if (Owner == (*I)->Owner)
       {
 	 QItem *Jnk= *I;
 	 *I = (*I)->Next;
@@ -717,7 +727,7 @@ bool pkgAcquire::Queue::Dequeue(Item *Owner)
       else
 	 I = &(*I)->Next;
    }
-   
+
    return Res;
 }
 									/*}}}*/
@@ -794,9 +804,12 @@ pkgAcquire::Queue::QItem *pkgAcquire::Queue::FindItem(string URI,pkgAcquire::Wor
 bool pkgAcquire::Queue::ItemDone(QItem *Itm)
 {
    PipeDepth--;
-   if (Itm->Owner->Status == pkgAcquire::Item::StatFetching)
-      Itm->Owner->Status = pkgAcquire::Item::StatDone;
-   
+   for (QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O)
+   {
+      if ((*O)->Status == pkgAcquire::Item::StatFetching)
+	 (*O)->Status = pkgAcquire::Item::StatDone;
+   }
+
    if (Itm->Owner->QueueCounter <= 1)
       Owner->Dequeue(Itm->Owner);
    else
@@ -804,7 +817,7 @@ bool pkgAcquire::Queue::ItemDone(QItem *Itm)
       Dequeue(Itm->Owner);
       Owner->Bump();
    }
-   
+
    return Cycle();
 }
 									/*}}}*/
@@ -819,7 +832,7 @@ bool pkgAcquire::Queue::Cycle()
 
    if (PipeDepth < 0)
       return _error->Error("Pipedepth failure");
-			   
+
    // Look for a queable item
    QItem *I = Items;
    while (PipeDepth < (signed)MaxPipeDepth)
@@ -827,18 +840,19 @@ bool pkgAcquire::Queue::Cycle()
       for (; I != 0; I = I->Next)
 	 if (I->Owner->Status == pkgAcquire::Item::StatIdle)
 	    break;
-      
+
       // Nothing to do, queue is idle.
       if (I == 0)
 	 return true;
-      
+
       I->Worker = Workers;
-      I->Owner->Status = pkgAcquire::Item::StatFetching;
+      for (QItem::owner_iterator O = I->Owners.begin(); O != I->Owners.end(); ++O)
+	 (*O)->Status = pkgAcquire::Item::StatFetching;
       PipeDepth++;
       if (Workers->QueueItem(I) == false)
 	 return false;
    }
-   
+
    return true;
 }
 									/*}}}*/
@@ -850,10 +864,98 @@ void pkgAcquire::Queue::Bump()
    Cycle();
 }
 									/*}}}*/
+HashStringList pkgAcquire::Queue::QItem::GetExpectedHashes() const	/*{{{*/
+{
+   /* each Item can have multiple owners and each owner might have different
+      hashes, even if that is unlikely in practice and if so at least some
+      owners will later fail. There is one situation through which is not a
+      failure and still needs this handling: Two owners who expect the same
+      file, but one owner only knows the SHA1 while the other only knows SHA256. */
+   HashStringList superhsl;
+   for (pkgAcquire::Queue::QItem::owner_iterator O = Owners.begin(); O != Owners.end(); ++O)
+   {
+      HashStringList const hsl = (*O)->GetExpectedHashes();
+      if (hsl.usable() == false)
+	 continue;
+      if (superhsl.usable() == false)
+	 superhsl = hsl;
+      else
+      {
+	 // we merge both lists - if we find disagreement send no hashes
+	 HashStringList::const_iterator hs = hsl.begin();
+	 for (; hs != hsl.end(); ++hs)
+	    if (superhsl.push_back(*hs) == false)
+	       break;
+	 if (hs != hsl.end())
+	 {
+	    superhsl.clear();
+	    break;
+	 }
+      }
+   }
+   return superhsl;
+}
+									/*}}}*/
+APT_PURE unsigned long long pkgAcquire::Queue::QItem::GetMaximumSize() const	/*{{{*/
+{
+   unsigned long long Maximum = std::numeric_limits<unsigned long long>::max();
+   for (pkgAcquire::Queue::QItem::owner_iterator O = Owners.begin(); O != Owners.end(); ++O)
+   {
+      if ((*O)->FileSize == 0)
+	 continue;
+      Maximum = std::min(Maximum, (*O)->FileSize);
+   }
+   if (Maximum == std::numeric_limits<unsigned long long>::max())
+      return 0;
+   return Maximum;
+}
+									/*}}}*/
+void pkgAcquire::Queue::QItem::SyncDestinationFiles() const		/*{{{*/
+{
+   /* ensure that the first owner has the best partial file of all and
+      the rest have (potentially dangling) symlinks to it so that
+      everything (like progress reporting) finds it easily */
+   std::string superfile = Owner->DestFile;
+   off_t supersize = 0;
+   for (pkgAcquire::Queue::QItem::owner_iterator O = Owners.begin(); O != Owners.end(); ++O)
+   {
+      if ((*O)->DestFile == superfile)
+	 continue;
+      struct stat file;
+      if (lstat((*O)->DestFile.c_str(),&file) == 0)
+      {
+	 if ((file.st_mode & S_IFREG) == 0)
+	    unlink((*O)->DestFile.c_str());
+	 else if (supersize < file.st_size)
+	 {
+	    supersize = file.st_size;
+	    unlink(superfile.c_str());
+	    rename((*O)->DestFile.c_str(), superfile.c_str());
+	 }
+	 else
+	    unlink((*O)->DestFile.c_str());
+	 if (symlink(superfile.c_str(), (*O)->DestFile.c_str()) != 0)
+	 {
+	    ; // not a problem per-se and no real alternative
+	 }
+      }
+   }
+}
+									/*}}}*/
+std::string pkgAcquire::Queue::QItem::Custom600Headers() const		/*{{{*/
+{
+   /* The others are relatively easy to merge, but this one?
+      Lets not merge and see how far we can run with it…
+      Likely, nobody will ever notice as all the items will
+      be of the same class and hence generate the same headers. */
+   return Owner->Custom600Headers();
+}
+									/*}}}*/
+
 // AcquireStatus::pkgAcquireStatus - Constructor			/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-pkgAcquireStatus::pkgAcquireStatus() : d(NULL), Percent(0), Update(true), MorePulses(false)
+pkgAcquireStatus::pkgAcquireStatus() : d(NULL), Percent(-1), Update(true), MorePulses(false)
 {
    Start();
 }
@@ -909,9 +1011,9 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner)
       {
 	 CurrentBytes += I->CurrentSize;
 	 ResumeSize += I->ResumePoint;
-	 
+
 	 // Files with unknown size always have 100% completion
-	 if (I->CurrentItem->Owner->FileSize == 0 && 
+	 if (I->CurrentItem->Owner->FileSize == 0 &&
 	     I->CurrentItem->Owner->Complete == false)
 	    TotalBytes += I->CurrentSize;
       }
@@ -952,13 +1054,17 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner)
       Time = NewTime;
    }
 
+   double const OldPercent = Percent;
    // calculate the percentage, if we have too little data assume 1%
    if (TotalBytes > 0 && UnfetchedReleaseFiles)
       Percent = 0;
-   else 
+   else
       // use both files and bytes because bytes can be unreliable
-      Percent = (0.8 * (CurrentBytes/float(TotalBytes)*100.0) + 
+      Percent = (0.8 * (CurrentBytes/float(TotalBytes)*100.0) +
                  0.2 * (CurrentItems/float(TotalItems)*100.0));
+   double const DiffPercent = Percent - OldPercent;
+   if (DiffPercent < 0.001 && _config->FindB("Acquire::Progress::Diffpercent", false) == true)
+      return true;
 
    int fd = _config->FindI("APT::Status-Fd",-1);
    if(fd > 0) 
@@ -976,11 +1082,11 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner)
 	 snprintf(msg,sizeof(msg), _("Retrieving file %li of %li (%s remaining)"), i, TotalItems, TimeToStr(ETA).c_str());
       else
 	 snprintf(msg,sizeof(msg), _("Retrieving file %li of %li"), i, TotalItems);
-	 
+
       // build the status str
       status << "dlstatus:" << i
              << ":"  << std::setprecision(3) << Percent
-             << ":" << msg 
+             << ":" << msg
              << endl;
 
       std::string const dlstatus = status.str();
@@ -1037,6 +1143,15 @@ void pkgAcquireStatus::Fetched(unsigned long long Size,unsigned long long Resume
 }
 									/*}}}*/
 
+pkgAcquire::UriIterator::UriIterator(pkgAcquire::Queue *Q) : d(NULL), CurQ(Q), CurItem(0)
+{
+   while (CurItem == 0 && CurQ != 0)
+   {
+      CurItem = CurQ->Items;
+      CurQ = CurQ->Next;
+   }
+}
+
 APT_CONST pkgAcquire::UriIterator::~UriIterator() {}
 APT_CONST pkgAcquire::MethodConfig::~MethodConfig() {}
 APT_CONST pkgAcquireStatus::~pkgAcquireStatus() {}

+ 38 - 17
apt-pkg/acquire.h

@@ -1,6 +1,5 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: acquire.h,v 1.29.2.1 2003/12/24 23:09:17 mdz Exp $
 /* ######################################################################
 
    Acquire - File Acquiration
@@ -68,9 +67,10 @@
 
 #include <apt-pkg/macros.h>
 #include <apt-pkg/weakptr.h>
+#include <apt-pkg/hashes.h>
 
-#include <vector>
 #include <string>
+#include <vector>
 
 #include <stddef.h>
 #include <sys/time.h>
@@ -111,6 +111,7 @@ class pkgAcquire
    struct MethodConfig;
    struct ItemDesc;
    friend class Item;
+   friend class pkgAcqMetaBase;
    friend class Queue;
 
    typedef std::vector<Item *>::iterator ItemIterator;
@@ -389,13 +390,13 @@ class pkgAcquire
  */
 struct pkgAcquire::ItemDesc : public WeakPointable
 {
-   /** \brief The URI from which to download this item. */
+   /** \brief URI from which to download this item. */
    std::string URI;
-   /** brief A description of this item. */
+   /** \brief description of this item. */
    std::string Description;
-   /** brief A shorter description of this item. */
+   /** \brief shorter description of this item. */
    std::string ShortDesc;
-   /** brief The underlying item which is to be downloaded. */
+   /** \brief underlying item which is to be downloaded. */
    Item *Owner;
 };
 									/*}}}*/
@@ -418,13 +419,26 @@ class pkgAcquire::Queue
    protected:
 
    /** \brief A single item placed in this queue. */
-   struct QItem : pkgAcquire::ItemDesc
+   struct QItem : public WeakPointable
    {
       /** \brief The next item in the queue. */
       QItem *Next;
       /** \brief The worker associated with this item, if any. */
       pkgAcquire::Worker *Worker;
 
+      /** \brief The URI from which to download this item. */
+      std::string URI;
+      /** \brief A description of this item. */
+      std::string Description;
+      /** \brief A shorter description of this item. */
+      std::string ShortDesc;
+      /** \brief The underlying items interested in the download */
+      std::vector<Item*> Owners;
+      // both, backward compatibility and easy access as syncing is interal
+      Item * Owner;
+
+      typedef std::vector<Item*>::const_iterator owner_iterator;
+
       /** \brief Assign the ItemDesc portion of this QItem from
        *  another ItemDesc
        */
@@ -433,10 +447,24 @@ class pkgAcquire::Queue
 	 URI = I.URI;
 	 Description = I.Description;
 	 ShortDesc = I.ShortDesc;
+	 Owners.clear();
+	 Owners.push_back(I.Owner);
 	 Owner = I.Owner;
       };
+
+      /** @return the sum of all expected hashes by all owners */
+      HashStringList GetExpectedHashes() const;
+
+      /** @return smallest maximum size of all owners */
+      unsigned long long GetMaximumSize() const;
+
+      /** \brief get partial files in order */
+      void SyncDestinationFiles() const;
+
+      /** @return the custom headers to use for this item */
+      std::string Custom600Headers() const;
    };
-   
+
    /** \brief The name of this queue. */
    std::string Name;
 
@@ -589,7 +617,7 @@ class pkgAcquire::UriIterator
       }
    };
    
-   inline pkgAcquire::ItemDesc const *operator ->() const {return CurItem;};
+   inline pkgAcquire::Queue::QItem const *operator ->() const {return CurItem;};
    inline bool operator !=(UriIterator const &rhs) const {return rhs.CurQ != CurQ || rhs.CurItem != CurItem;};
    inline bool operator ==(UriIterator const &rhs) const {return rhs.CurQ == CurQ && rhs.CurItem == CurItem;};
    
@@ -597,14 +625,7 @@ class pkgAcquire::UriIterator
     *
     *  \param Q The queue over which this UriIterator should iterate.
     */
-   UriIterator(pkgAcquire::Queue *Q) : d(NULL), CurQ(Q), CurItem(0)
-   {
-      while (CurItem == 0 && CurQ != 0)
-      {
-	 CurItem = CurQ->Items;
-	 CurQ = CurQ->Next;
-      }
-   }   
+   UriIterator(pkgAcquire::Queue *Q);
    virtual ~UriIterator();
 };
 									/*}}}*/

+ 13 - 1
apt-pkg/algorithms.cc

@@ -468,7 +468,7 @@ void pkgProblemResolver::MakeScores()
 	 if (D->Version != 0)
 	 {
 	    pkgCache::VerIterator const IV = Cache[T].InstVerIter(Cache);
-	    if (IV.end() == true || D.IsSatisfied(IV) != D.IsNegative())
+	    if (IV.end() == true || D.IsSatisfied(IV) == false)
 	       continue;
 	 }
 	 Scores[T->ID] += DepMap[D->Type];
@@ -640,6 +640,12 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
 // ProblemResolver::Resolve - calls a resolver to fix the situation	/*{{{*/
 // ---------------------------------------------------------------------
 /* */
+#if APT_PKG_ABI < 413
+bool pkgProblemResolver::Resolve(bool BrokenFix)
+{
+   return Resolve(BrokenFix, NULL);
+}
+#endif
 bool pkgProblemResolver::Resolve(bool BrokenFix, OpProgress * const Progress)
 {
    std::string const solver = _config->Find("APT::Solver", "internal");
@@ -1138,6 +1144,12 @@ bool pkgProblemResolver::InstOrNewPolicyBroken(pkgCache::PkgIterator I)
 /* This is the work horse of the soft upgrade routine. It is very gental 
    in that it does not install or remove any packages. It is assumed that the
    system was non-broken previously. */
+#if APT_PKG_ABI < 413
+bool pkgProblemResolver::ResolveByKeep()
+{
+   return ResolveByKeep(NULL);
+}
+#endif
 bool pkgProblemResolver::ResolveByKeep(OpProgress * const Progress)
 {
    std::string const solver = _config->Find("APT::Solver", "internal");

+ 13 - 3
apt-pkg/algorithms.h

@@ -1,6 +1,5 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: algorithms.h,v 1.10 2001/05/22 04:17:41 jgg Exp $
 /* ######################################################################
 
    Algorithms - A set of misc algorithms
@@ -55,6 +54,7 @@ using std::ostream;
 
 class pkgSimulate : public pkgPackageManager				/*{{{*/
 {
+   void *d;
    protected:
 
    class Policy : public pkgDepCache::Policy
@@ -88,7 +88,7 @@ private:
    public:
 
    pkgSimulate(pkgDepCache *Cache);
-   ~pkgSimulate();
+   virtual ~pkgSimulate();
 };
 									/*}}}*/
 class pkgProblemResolver						/*{{{*/
@@ -138,15 +138,25 @@ class pkgProblemResolver						/*{{{*/
    inline void Clear(pkgCache::PkgIterator Pkg) {Flags[Pkg->ID] &= ~(Protected | ToRemove);};
 
    // Try to intelligently resolve problems by installing and removing packages
+#if APT_PKG_ABI >= 413
    bool Resolve(bool BrokenFix = false, OpProgress * const Progress = NULL);
+#else
+   bool Resolve(bool BrokenFix = false);
+   bool Resolve(bool BrokenFix, OpProgress * const Progress);
+#endif
 
    // Try to resolve problems only by using keep
+#if APT_PKG_ABI >= 413
    bool ResolveByKeep(OpProgress * const Progress = NULL);
+#else
+   bool ResolveByKeep();
+   bool ResolveByKeep(OpProgress * const Progress);
+#endif
 
    APT_DEPRECATED void InstallProtect();
 
    pkgProblemResolver(pkgDepCache *Cache);
-   ~pkgProblemResolver();
+   virtual ~pkgProblemResolver();
 };
 									/*}}}*/
 bool pkgApplyStatus(pkgDepCache &Cache);

+ 10 - 11
apt-pkg/aptconfiguration.h

@@ -16,8 +16,7 @@
 #include <limits>
 									/*}}}*/
 namespace APT {
-class Configuration {							/*{{{*/
-public:									/*{{{*/
+namespace Configuration {							/*{{{*/
 	/** \brief Returns a vector of usable Compression Types
 	 *
 	 *  Files can be compressed in various ways to decrease the size of the
@@ -39,7 +38,7 @@ public:									/*{{{*/
 	 *
 	 *  \return a vector of the compression types in the preferred usage order
 	 */
-	std::vector<std::string> static const getCompressionTypes(bool const &Cached = true);
+	std::vector<std::string> const getCompressionTypes(bool const &Cached = true);
 
 	/** \brief Returns a vector of Language Codes
 	 *
@@ -64,7 +63,7 @@ public:									/*{{{*/
 	 *
 	 *  \return a vector of (all) Language Codes in the preferred usage order
 	 */
-	std::vector<std::string> static const getLanguages(bool const &All = false,
+	std::vector<std::string> const getLanguages(bool const &All = false,
 			bool const &Cached = true, char const ** const Locale = 0);
 
 	/** \brief Are we interested in the given Language?
@@ -73,7 +72,7 @@ public:									/*{{{*/
 	 *  \param All defines if we check against all codes or only against used codes
 	 *  \return true if we are interested, false otherwise
 	 */
-	bool static checkLanguage(std::string Lang, bool const All = false);
+	bool checkLanguage(std::string Lang, bool const All = false);
 
 	/** \brief Returns a vector of Architectures we support
 	 *
@@ -82,14 +81,14 @@ public:									/*{{{*/
 	 *
 	 *  \return a vector of Architectures in preferred order
 	 */
-	std::vector<std::string> static const getArchitectures(bool const &Cached = true);
+	std::vector<std::string> const getArchitectures(bool const &Cached = true);
 
 	/** \brief Are we interested in the given Architecture?
 	 *
 	 *  \param Arch we want to check
 	 *  \return true if we are interested, false otherwise
 	 */
-	bool static checkArchitecture(std::string const &Arch);
+	bool checkArchitecture(std::string const &Arch);
 
 	/** \brief Representation of supported compressors */
 	struct Compressor {
@@ -113,15 +112,15 @@ public:									/*{{{*/
 	 *
 	 *  \return a vector of Compressors
 	 */
-	std::vector<Compressor> static const getCompressors(bool const Cached = true);
+	std::vector<Compressor> const getCompressors(bool const Cached = true);
 
 	/** \brief Return a vector of extensions supported for data.tar's */
-	std::vector<std::string> static const getCompressorExtensions();
+	std::vector<std::string> const getCompressorExtensions();
 
 	/** \return Return a vector of enabled build profile specifications */
-	std::vector<std::string> static const getBuildProfiles();
+	std::vector<std::string> const getBuildProfiles();
 	/** \return Return a comma-separated list of enabled build profile specifications */
-	std::string static const getBuildProfilesString();
+	std::string const getBuildProfilesString();
 									/*}}}*/
 };
 									/*}}}*/

+ 0 - 1
apt-pkg/cachefile.h

@@ -1,6 +1,5 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: cachefile.h,v 1.5 2002/04/27 04:28:04 jgg Exp $
 /* ######################################################################
    
    CacheFile - Simple wrapper class for opening, generating and whatnot

+ 48 - 10
apt-pkg/cacheiterators.h

@@ -161,10 +161,12 @@ class pkgCache::PkgIterator: public Iterator<Package, PkgIterator> {
 	// Accessors
 	inline const char *Name() const { return Group().Name(); }
 	// Versions have sections - and packages can have different versions with different sections
-	// so this interface is broken by design. It used to return the section of the "first parsed
-	// package stanza", but as this can potentially be anything it now returns the section of the
-	// newest version instead (if any). aka: Run as fast as you can to Version.Section().
-	APT_DEPRECATED const char *Section() const;
+	// so this interface is broken by design. Run as fast as you can to Version.Section().
+	APT_DEPRECATED inline const char *Section() const {
+	   APT_IGNORE_DEPRECATED_PUSH
+	   return S->Section == 0?0:Owner->StrP + S->Section;
+	   APT_IGNORE_DEPRECATED_POP
+	}
 	inline bool Purge() const {return S->CurrentState == pkgCache::State::Purge ||
 		(S->CurrentVer == 0 && S->CurrentState == pkgCache::State::NotInstalled);}
 	inline const char *Arch() const {return S->Arch == 0?0:Owner->StrP + S->Arch;}
@@ -215,12 +217,14 @@ class pkgCache::VerIterator : public Iterator<Version, VerIterator> {
 	// Accessors
 	inline const char *VerStr() const {return S->VerStr == 0?0:Owner->StrP + S->VerStr;}
 	inline const char *Section() const {return S->Section == 0?0:Owner->StrP + S->Section;}
+#if APT_PKG_ABI >= 413
 	/** \brief source package name this version comes from
 	   Always contains the name, even if it is the same as the binary name */
 	inline const char *SourcePkgName() const {return Owner->StrP + S->SourcePkgName;}
 	/** \brief source version this version comes from
 	   Always contains the version string, even if it is the same as the binary version */
 	inline const char *SourceVerStr() const {return Owner->StrP + S->SourceVerStr;}
+#endif
 	inline const char *Arch() const {
 		if ((S->MultiArch & pkgCache::Version::All) == pkgCache::Version::All)
 			return "all";
@@ -363,27 +367,61 @@ class pkgCache::PrvIterator : public Iterator<Provides, PrvIterator> {
 	}
 };
 									/*}}}*/
-// Package file								/*{{{*/
-class pkgCache::PkgFileIterator : public Iterator<PackageFile, PkgFileIterator> {
+// Release file								/*{{{*/
+class pkgCache::RlsFileIterator : public Iterator<ReleaseFile, RlsFileIterator> {
 	protected:
-	inline PackageFile* OwnerPointer() const {
-		return (Owner != 0) ? Owner->PkgFileP : 0;
+	inline ReleaseFile* OwnerPointer() const {
+		return (Owner != 0) ? Owner->RlsFileP : 0;
 	}
 
 	public:
 	// Iteration
-	void operator ++(int) {if (S != Owner->PkgFileP) S = Owner->PkgFileP + S->NextFile;}
+	void operator ++(int) {if (S != Owner->RlsFileP) S = Owner->RlsFileP + S->NextFile;}
 	inline void operator ++() {operator ++(0);}
 
 	// Accessors
 	inline const char *FileName() const {return S->FileName == 0?0:Owner->StrP + S->FileName;}
 	inline const char *Archive() const {return S->Archive == 0?0:Owner->StrP + S->Archive;}
-	inline const char *Component() const {return S->Component == 0?0:Owner->StrP + S->Component;}
 	inline const char *Version() const {return S->Version == 0?0:Owner->StrP + S->Version;}
 	inline const char *Origin() const {return S->Origin == 0?0:Owner->StrP + S->Origin;}
 	inline const char *Codename() const {return S->Codename ==0?0:Owner->StrP + S->Codename;}
 	inline const char *Label() const {return S->Label == 0?0:Owner->StrP + S->Label;}
 	inline const char *Site() const {return S->Site == 0?0:Owner->StrP + S->Site;}
+	inline bool Flagged(pkgCache::Flag::ReleaseFileFlags const flag) const {return (S->Flags & flag) == flag; }
+
+	bool IsOk();
+	std::string RelStr();
+
+	// Constructors
+	inline RlsFileIterator() : Iterator<ReleaseFile, RlsFileIterator>() {}
+	inline RlsFileIterator(pkgCache &Owner) : Iterator<ReleaseFile, RlsFileIterator>(Owner, Owner.RlsFileP) {}
+	inline RlsFileIterator(pkgCache &Owner,ReleaseFile *Trg) : Iterator<ReleaseFile, RlsFileIterator>(Owner, Trg) {}
+};
+									/*}}}*/
+// Package file								/*{{{*/
+class pkgCache::PkgFileIterator : public Iterator<PackageFile, PkgFileIterator> {
+	protected:
+	inline PackageFile* OwnerPointer() const {
+		return (Owner != 0) ? Owner->PkgFileP : 0;
+	}
+
+	public:
+	// Iteration
+	void operator ++(int) {if (S != Owner->PkgFileP) S = Owner->PkgFileP + S->NextFile;}
+	inline void operator ++() {operator ++(0);}
+
+	// Accessors
+	inline const char *FileName() const {return S->FileName == 0?0:Owner->StrP + S->FileName;}
+	inline pkgCache::RlsFileIterator ReleaseFile() const {return RlsFileIterator(*Owner, Owner->RlsFileP + S->Release);}
+	inline const char *Archive() const {return S->Release == 0 ? Component() : ReleaseFile().Archive();}
+	inline const char *Version() const {return S->Release == 0 ? NULL : ReleaseFile().Version();}
+	inline const char *Origin() const {return S->Release == 0 ? NULL : ReleaseFile().Origin();}
+	inline const char *Codename() const {return S->Release == 0 ? NULL : ReleaseFile().Codename();}
+	inline const char *Label() const {return S->Release == 0 ? NULL : ReleaseFile().Label();}
+	inline const char *Site() const {return S->Release == 0 ? NULL : ReleaseFile().Site();}
+	inline bool Flagged(pkgCache::Flag::ReleaseFileFlags const flag) const {return S->Release== 0 ? false : ReleaseFile().Flagged(flag);}
+	inline bool Flagged(pkgCache::Flag::PkgFFlags const flag) const {return (S->Flags & flag) == flag;}
+	inline const char *Component() const {return S->Component == 0?0:Owner->StrP + S->Component;}
 	inline const char *Architecture() const {return S->Architecture == 0?0:Owner->StrP + S->Architecture;}
 	inline const char *IndexType() const {return S->IndexType == 0?0:Owner->StrP + S->IndexType;}
 

+ 26 - 39
apt-pkg/cacheset.cc

@@ -37,7 +37,6 @@
 #include <apti18n.h>
 									/*}}}*/
 namespace APT {
-
 // PackageFrom - selecting the appropriate method for package selection	/*{{{*/
 bool CacheSetHelper::PackageFrom(enum PkgSelector const select, PackageContainerInterface * const pci,
       pkgCacheFile &Cache, std::string const &pattern) {
@@ -613,19 +612,14 @@ void CacheSetHelper::canNotFindPackage(enum PkgSelector const select,
       PackageContainerInterface * const pci, pkgCacheFile &Cache,
       std::string const &pattern) {
 	switch (select) {
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+APT_IGNORE_DEPRECATED_PUSH
 	case REGEX: canNotFindRegEx(pci, Cache, pattern); break;
 	case TASK: canNotFindTask(pci, Cache, pattern); break;
 	case FNMATCH: canNotFindFnmatch(pci, Cache, pattern); break;
 	case PACKAGENAME: canNotFindPackage(pci, Cache, pattern); break;
 	case STRING: canNotFindPackage(pci, Cache, pattern); break;
 	case UNKNOWN: break;
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP
 	}
 }
 // canNotFindTask - handle the case no package is found for a task	/*{{{*/
@@ -663,19 +657,14 @@ pkgCache::PkgIterator CacheSetHelper::canNotFindPkgName(pkgCacheFile &Cache,
 void CacheSetHelper::canNotFindVersion(enum VerSelector const select, VersionContainerInterface * const vci, pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg)
 {
 	switch (select) {
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+APT_IGNORE_DEPRECATED_PUSH
 	case ALL: canNotFindAllVer(vci, Cache, Pkg); break;
 	case INSTCAND: canNotFindInstCandVer(vci, Cache, Pkg); break;
 	case CANDINST: canNotFindCandInstVer(vci, Cache, Pkg); break;
 	case NEWEST: canNotFindNewestVer(Cache, Pkg); break;
 	case CANDIDATE: canNotFindCandidateVer(Cache, Pkg); break;
 	case INSTALLED: canNotFindInstalledVer(Cache, Pkg); break;
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP
 	case CANDANDINST: canNotGetCandInstVer(Cache, Pkg); break;
 	case RELEASE:
 	case VERSIONNUMBER:
@@ -706,16 +695,11 @@ void CacheSetHelper::canNotFindCandInstVer(VersionContainerInterface * const /*v
 // canNotGetVersion - for package by selector				/*{{{*/
 pkgCache::VerIterator CacheSetHelper::canNotGetVersion(enum VerSelector const select, pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
 	switch (select) {
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+APT_IGNORE_DEPRECATED_PUSH
 	case NEWEST: return canNotFindNewestVer(Cache, Pkg);
 	case CANDIDATE: return canNotFindCandidateVer(Cache, Pkg);
 	case INSTALLED: return canNotFindInstalledVer(Cache, Pkg);
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP
 	case CANDINST: return canNotGetCandInstVer(Cache, Pkg);
 	case INSTCAND: return canNotGetInstCandVer(Cache, Pkg);
 	case ALL:
@@ -769,19 +753,14 @@ pkgCache::VerIterator CacheSetHelper::canNotGetCandInstVer(pkgCacheFile &Cache,
 									/*}}}*/
 									/*}}}*/
 // showPackageSelection - by selector and given pattern			/*{{{*/
-APT_CONST void CacheSetHelper::showPackageSelection(pkgCache::PkgIterator const &pkg, enum PkgSelector const select,
+void CacheSetHelper::showPackageSelection(pkgCache::PkgIterator const &pkg, enum PkgSelector const select,
 				       std::string const &pattern) {
 	switch (select) {
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+APT_IGNORE_DEPRECATED_PUSH
 	case REGEX: showRegExSelection(pkg, pattern); break;
 	case TASK: showTaskSelection(pkg, pattern); break;
 	case FNMATCH: showFnmatchSelection(pkg, pattern); break;
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP
 	case PACKAGENAME: /* no suprises here */ break;
 	case STRING: /* handled by the special cases */ break;
 	case UNKNOWN: break;
@@ -804,23 +783,17 @@ APT_CONST void CacheSetHelper::showFnmatchSelection(pkgCache::PkgIterator const
 									/*}}}*/
 									/*}}}*/
 // showVersionSelection							/*{{{*/
-APT_CONST void CacheSetHelper::showVersionSelection(pkgCache::PkgIterator const &Pkg,
+void CacheSetHelper::showVersionSelection(pkgCache::PkgIterator const &Pkg,
       pkgCache::VerIterator const &Ver, enum VerSelector const select, std::string const &pattern) {
 	switch (select) {
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+APT_IGNORE_DEPRECATED_PUSH
 	case RELEASE:
 		showSelectedVersion(Pkg, Ver, pattern, true);
 		break;
 	case VERSIONNUMBER:
 		showSelectedVersion(Pkg, Ver, pattern, false);
 		break;
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+APT_IGNORE_DEPRECATED_POP
 	case NEWEST:
 	case CANDIDATE:
 	case INSTALLED:
@@ -838,4 +811,18 @@ APT_CONST void CacheSetHelper::showSelectedVersion(pkgCache::PkgIterator const &
 					 bool const /*verIsRel*/) {
 }
 									/*}}}*/
+
+CacheSetHelper::CacheSetHelper(bool const ShowError, GlobalError::MsgType ErrorType) :
+   ShowError(ShowError), ErrorType(ErrorType) {}
+CacheSetHelper::~CacheSetHelper() {}
+
+PackageContainerInterface::PackageContainerInterface() : ConstructedBy(CacheSetHelper::UNKNOWN) {}
+PackageContainerInterface::PackageContainerInterface(CacheSetHelper::PkgSelector const by) : ConstructedBy(by) {}
+PackageContainerInterface::~PackageContainerInterface() {}
+
+PackageUniverse::PackageUniverse(pkgCache * const Owner) : _cont(Owner) { }
+PackageUniverse::~PackageUniverse() {}
+
+VersionContainerInterface::VersionContainerInterface() {}
+VersionContainerInterface::~VersionContainerInterface() {}
 }

+ 45 - 99
apt-pkg/cacheset.h

@@ -23,6 +23,7 @@
 #include <apt-pkg/error.h>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/cacheiterators.h>
+#include <apt-pkg/macros.h>
 
 #ifndef APT_8_CLEANER_HEADERS
 #include <apt-pkg/cachefile.h>
@@ -49,9 +50,8 @@ class CacheSetHelper {							/*{{{*/
 */
 public:									/*{{{*/
 	CacheSetHelper(bool const ShowError = true,
-		GlobalError::MsgType ErrorType = GlobalError::ERROR) :
-			ShowError(ShowError), ErrorType(ErrorType) {}
-	virtual ~CacheSetHelper() {}
+		GlobalError::MsgType ErrorType = GlobalError::ERROR);
+	virtual ~CacheSetHelper();
 
 	enum PkgSelector { UNKNOWN, REGEX, TASK, FNMATCH, PACKAGENAME, STRING };
 
@@ -202,6 +202,8 @@ protected:
 	bool PackageFromFnmatch(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern);
 	bool PackageFromPackageName(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern);
 	bool PackageFromString(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &pattern);
+private:
+	void *d;
 };									/*}}}*/
 
 class PackageContainerInterface {					/*{{{*/
@@ -224,14 +226,9 @@ public:
 		inline std::string FullName(bool const Pretty) const { return getPkg().FullName(Pretty); }
 		inline std::string FullName() const { return getPkg().FullName(); }
 		APT_DEPRECATED inline const char *Section() const {
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-	   return getPkg().Section();
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+		   APT_IGNORE_DEPRECATED_PUSH
+		      return getPkg().Section();
+		   APT_IGNORE_DEPRECATED_POP
 		}
 		inline bool Purge() const {return getPkg().Purge(); }
 		inline const char *Arch() const {return getPkg().Arch(); }
@@ -261,19 +258,15 @@ public:
 		REGEX = CacheSetHelper::REGEX,
 		TASK = CacheSetHelper::TASK,
 		FNMATCH = CacheSetHelper::FNMATCH };
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+APT_IGNORE_DEPRECATED_PUSH
 	void setConstructor(Constructor const by) { ConstructedBy = (CacheSetHelper::PkgSelector)by; }
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP
 
 	void setConstructor(CacheSetHelper::PkgSelector const by) { ConstructedBy = by; }
 	CacheSetHelper::PkgSelector getConstructor() const { return ConstructedBy; }
-	PackageContainerInterface() : ConstructedBy(CacheSetHelper::UNKNOWN) {}
-	PackageContainerInterface(CacheSetHelper::PkgSelector const by) : ConstructedBy(by) {}
+	PackageContainerInterface();
+	PackageContainerInterface(CacheSetHelper::PkgSelector const by);
+	virtual ~PackageContainerInterface();
 
 	APT_DEPRECATED static bool FromTask(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper) {
 	   return helper.PackageFrom(CacheSetHelper::TASK, pci, Cache, pattern); }
@@ -290,22 +283,18 @@ public:
 
 	APT_DEPRECATED typedef CacheSetHelper::PkgModifier Modifier;
 
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+APT_IGNORE_DEPRECATED_PUSH
 	APT_DEPRECATED static pkgCache::PkgIterator FromName(pkgCacheFile &Cache, std::string const &pattern, CacheSetHelper &helper) {
 	   return helper.PackageFromName(Cache, pattern); }
 	APT_DEPRECATED static bool FromModifierCommandLine(unsigned short &modID, PackageContainerInterface * const pci,
 	      pkgCacheFile &Cache, const char * cmdline,
 	      std::list<Modifier> const &mods, CacheSetHelper &helper) {
 	   return helper.PackageFromModifierCommandLine(modID, pci, Cache, cmdline, mods); }
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP
 
 private:
 	CacheSetHelper::PkgSelector ConstructedBy;
+	void *d;
 };
 									/*}}}*/
 template<class Container> class PackageContainer : public PackageContainerInterface {/*{{{*/
@@ -369,16 +358,11 @@ public:									/*{{{*/
 	iterator end() { return iterator(_cont.end()); }
 	const_iterator find(pkgCache::PkgIterator const &P) const { return const_iterator(_cont.find(P)); }
 
-	PackageContainer() : PackageContainerInterface() {}
+	PackageContainer() : PackageContainerInterface(CacheSetHelper::UNKNOWN) {}
 	PackageContainer(CacheSetHelper::PkgSelector const &by) : PackageContainerInterface(by) {}
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+APT_IGNORE_DEPRECATED_PUSH
 	APT_DEPRECATED PackageContainer(Constructor const &by) : PackageContainerInterface((CacheSetHelper::PkgSelector)by) {}
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP
 
 	/** \brief sort all included versions with given comparer
 
@@ -439,10 +423,7 @@ public:									/*{{{*/
 		return FromFnmatch(Cache, pattern, helper);
 	}
 
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+APT_IGNORE_DEPRECATED_PUSH
 	/** \brief returns a package specified by a string
 
 	    \param Cache the package is in
@@ -455,9 +436,7 @@ public:									/*{{{*/
 		CacheSetHelper helper;
 		return FromName(Cache, pattern, helper);
 	}
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP
 
 	/** \brief returns all packages specified by a string
 
@@ -576,6 +555,7 @@ template<> template<class Compare> inline bool PackageContainer<std::vector<pkgC
     private methods. */
 class APT_HIDDEN PackageUniverse : public PackageContainerInterface {
 	pkgCache * const _cont;
+	void *d;
 public:
 	typedef pkgCache::PkgIterator iterator;
 	typedef pkgCache::PkgIterator const_iterator;
@@ -588,7 +568,8 @@ public:
 	APT_PUBLIC iterator begin() { return _cont->PkgBegin(); }
 	APT_PUBLIC iterator end() { return _cont->PkgEnd(); }
 
-	APT_PUBLIC PackageUniverse(pkgCache * const Owner) : _cont(Owner) { }
+	APT_PUBLIC PackageUniverse(pkgCache * const Owner);
+	APT_PUBLIC virtual ~PackageUniverse();
 
 private:
 	bool insert(pkgCache::PkgIterator const &) { return true; }
@@ -663,65 +644,45 @@ public:
 		Modifier (unsigned short const &id, const char * const alias, Position const &pos,
 			  enum CacheSetHelper::VerSelector const select) : ID(id), Alias(alias), Pos(pos),
 			 SelectVersion(select) {}
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+APT_IGNORE_DEPRECATED_PUSH
 		APT_DEPRECATED Modifier(unsigned short const &id, const char * const alias, Position const &pos,
 			  Version const &select) : ID(id), Alias(alias), Pos(pos),
 			 SelectVersion((CacheSetHelper::VerSelector)select) {}
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP
 	};
 
 	static bool FromCommandLine(VersionContainerInterface * const vci, pkgCacheFile &Cache,
 				    const char **cmdline, CacheSetHelper::VerSelector const fallback,
 				    CacheSetHelper &helper);
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+APT_IGNORE_DEPRECATED_PUSH
 	APT_DEPRECATED static bool FromCommandLine(VersionContainerInterface * const vci, pkgCacheFile &Cache,
 				    const char **cmdline, Version const &fallback,
 				    CacheSetHelper &helper) {
 	   return FromCommandLine(vci, Cache, cmdline, (CacheSetHelper::VerSelector)fallback, helper);
 	}
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP
 
 	static bool FromString(VersionContainerInterface * const vci, pkgCacheFile &Cache,
 			       std::string pkg, CacheSetHelper::VerSelector const fallback, CacheSetHelper &helper,
 			       bool const onlyFromName = false);
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+APT_IGNORE_DEPRECATED_PUSH
 	APT_DEPRECATED static bool FromString(VersionContainerInterface * const vci, pkgCacheFile &Cache,
 			       std::string pkg, Version const &fallback, CacheSetHelper &helper,
 			       bool const onlyFromName = false) {
 	   return FromString(vci, Cache, pkg, (CacheSetHelper::VerSelector)fallback, helper, onlyFromName);
 	}
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP
 
 	static bool FromPackage(VersionContainerInterface * const vci, pkgCacheFile &Cache,
 				pkgCache::PkgIterator const &P, CacheSetHelper::VerSelector const fallback,
 				CacheSetHelper &helper);
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+APT_IGNORE_DEPRECATED_PUSH
 	APT_DEPRECATED static bool FromPackage(VersionContainerInterface * const vci, pkgCacheFile &Cache,
 				pkgCache::PkgIterator const &P, Version const &fallback,
 				CacheSetHelper &helper) {
 	   return FromPackage(vci, Cache, P, (CacheSetHelper::VerSelector)fallback, helper);
 	}
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP
 
 	static bool FromModifierCommandLine(unsigned short &modID,
 					    VersionContainerInterface * const vci,
@@ -735,10 +696,7 @@ public:
 				   pkgCache::DepIterator const &D,
 				   CacheSetHelper::VerSelector const selector,
 				   CacheSetHelper &helper);
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+APT_IGNORE_DEPRECATED_PUSH
 	APT_DEPRECATED static bool FromDependency(VersionContainerInterface * const vci,
 				   pkgCacheFile &Cache,
 				   pkgCache::DepIterator const &D,
@@ -746,9 +704,12 @@ public:
 				   CacheSetHelper &helper) {
 	   return FromDependency(vci, Cache, D, (CacheSetHelper::VerSelector)selector, helper);
 	}
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP
+
+	VersionContainerInterface();
+	virtual ~VersionContainerInterface();
+private:
+	void *d;
 
 protected:								/*{{{*/
 
@@ -879,10 +840,7 @@ public:									/*{{{*/
 	static VersionContainer FromString(pkgCacheFile &Cache, std::string pkg) {
 		return FromString(Cache, pkg, CacheSetHelper::CANDINST);
 	}
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+APT_IGNORE_DEPRECATED_PUSH
 	static VersionContainer FromCommandLine(pkgCacheFile &Cache, const char **cmdline,
 			Version const &fallback, CacheSetHelper &helper) {
 		VersionContainer vercon;
@@ -906,9 +864,7 @@ public:									/*{{{*/
 		CacheSetHelper helper;
 		return FromString(Cache, pkg, (CacheSetHelper::VerSelector)fallback, helper);
 	}
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP
 
 	/** \brief returns all versions specified for the package
 
@@ -927,10 +883,7 @@ public:									/*{{{*/
 		CacheSetHelper helper;
 		return FromPackage(Cache, P, fallback, helper);
 	}
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+APT_IGNORE_DEPRECATED_PUSH
 	static VersionContainer FromPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &P,
 		Version const &fallback, CacheSetHelper &helper) {
 		VersionContainer vercon;
@@ -942,9 +895,7 @@ public:									/*{{{*/
 		CacheSetHelper helper;
 		return FromPackage(Cache, P, (CacheSetHelper::VerSelector)fallback, helper);
 	}
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP
 	static VersionContainer FromPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &P) {
 		return FromPackage(Cache, P, CacheSetHelper::CANDIDATE);
 	}
@@ -985,10 +936,7 @@ public:									/*{{{*/
 		CacheSetHelper helper;
 		return FromPackage(Cache, D, selector, helper);
 	}
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+APT_IGNORE_DEPRECATED_PUSH
 	static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D,
 					       Version const &selector, CacheSetHelper &helper) {
 		VersionContainer vercon;
@@ -1000,9 +948,7 @@ public:									/*{{{*/
 		CacheSetHelper helper;
 		return FromPackage(Cache, D, (CacheSetHelper::VerSelector)selector, helper);
 	}
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP
 	static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D) {
 		return FromPackage(Cache, D, CacheSetHelper::CANDIDATE);
 	}

+ 20 - 16
apt-pkg/cdrom.cc

@@ -466,7 +466,7 @@ bool pkgCdrom::WriteSourceList(string Name,vector<string> &List,bool Source)
    // Open the stream for reading
    ifstream F((FileExists(File)?File.c_str():"/dev/null"),
 	      ios::in );
-   if (!F != 0)
+   if (F.fail() == true)
       return _error->Errno("ifstream::ifstream","Opening %s",File.c_str());
 
    string NewFile = File + ".new";
@@ -477,7 +477,7 @@ bool pkgCdrom::WriteSourceList(string Name,vector<string> &List,bool Source)
 			   "Failed to open %s.new",File.c_str());
 
    // Create a short uri without the path
-   string ShortURI = "cdrom:[" + Name + "]/";   
+   string ShortURI = "cdrom:[" + Name + "]/";
    string ShortURI2 = "cdrom:" + Name + "/";     // For Compatibility
 
    string Type;
@@ -485,12 +485,12 @@ bool pkgCdrom::WriteSourceList(string Name,vector<string> &List,bool Source)
       Type = "deb-src";
    else
       Type = "deb";
-   
+
    char Buffer[300];
    int CurLine = 0;
    bool First = true;
    while (F.eof() == false)
-   {      
+   {
       F.getline(Buffer,sizeof(Buffer));
       CurLine++;
       if (F.fail() && !F.eof())
@@ -754,7 +754,7 @@ bool pkgCdrom::Add(pkgCdromStatus *log)					/*{{{*/
 	  FileExists(InfoDir + "/info") == true)
       {
 	 ifstream F((InfoDir + "/info").c_str());
-	 if (!F == 0)
+	 if (F.good() == true)
 	    getline(F,Name);
 
 	 if (Name.empty() == false)
@@ -822,8 +822,11 @@ bool pkgCdrom::Add(pkgCdromStatus *log)					/*{{{*/
    // check for existence and possibly create state directory for copying
    string const listDir = _config->FindDir("Dir::State::lists");
    string const partialListDir = listDir + "partial/";
-   if (CreateAPTDirectoryIfNeeded(_config->FindDir("Dir::State"), partialListDir) == false &&
-       CreateAPTDirectoryIfNeeded(listDir, partialListDir) == false)
+   mode_t const mode = umask(S_IWGRP | S_IWOTH);
+   bool const creation_fail = (CreateAPTDirectoryIfNeeded(_config->FindDir("Dir::State"), partialListDir) == false &&
+	 CreateAPTDirectoryIfNeeded(listDir, partialListDir) == false);
+   umask(mode);
+   if (creation_fail == true)
    {
       UnmountCDROM(CDROM, NULL);
       return _error->Errno("cdrom", _("List directory %spartial is missing."), listDir.c_str());
@@ -924,8 +927,7 @@ pkgUdevCdromDevices::pkgUdevCdromDevices()				/*{{{*/
 }
 									/*}}}*/
 
-bool
-pkgUdevCdromDevices::Dlopen()                     		        /*{{{*/
+bool pkgUdevCdromDevices::Dlopen()					/*{{{*/
 {
    // alread open
    if(libudev_handle != NULL)
@@ -954,18 +956,14 @@ pkgUdevCdromDevices::Dlopen()                     		        /*{{{*/
    return true;
 }
 									/*}}}*/
-                                                                        /*{{{*/
-// convenience interface, this will just call ScanForRemovable
-vector<CdromDevice>
-pkgUdevCdromDevices::Scan()
+// convenience interface, this will just call ScanForRemovable		/*{{{*/
+vector<CdromDevice> pkgUdevCdromDevices::Scan()
 {
    bool CdromOnly = _config->FindB("APT::cdrom::CdromOnly", true);
    return ScanForRemovable(CdromOnly);
 }
 									/*}}}*/
-                                                                        /*{{{*/
-vector<CdromDevice>
-pkgUdevCdromDevices::ScanForRemovable(bool CdromOnly)
+vector<CdromDevice> pkgUdevCdromDevices::ScanForRemovable(bool CdromOnly)/*{{{*/
 {
    vector<CdromDevice> cdrom_devices;
    struct udev_enumerate *enumerate;
@@ -1024,3 +1022,9 @@ pkgUdevCdromDevices::~pkgUdevCdromDevices()                             /*{{{*/
       dlclose(libudev_handle);
 }
 									/*}}}*/
+
+pkgCdromStatus::pkgCdromStatus() : totalSteps(0) {}
+pkgCdromStatus::~pkgCdromStatus() {}
+
+pkgCdrom::pkgCdrom() {}
+pkgCdrom::~pkgCdrom() {}

+ 9 - 2
apt-pkg/cdrom.h

@@ -18,12 +18,13 @@ class OpProgress;
 
 class pkgCdromStatus							/*{{{*/
 {
+   void *d;
  protected:
    int totalSteps;
 
  public:
-   pkgCdromStatus() : totalSteps(0) {};
-   virtual ~pkgCdromStatus() {};
+   pkgCdromStatus();
+   virtual ~pkgCdromStatus();
 
    // total steps
    virtual void SetTotal(int total) { totalSteps = total; };
@@ -74,7 +75,12 @@ class pkgCdrom								/*{{{*/
    bool Ident(std::string &ident, pkgCdromStatus *log);
    bool Add(pkgCdromStatus *log);
 
+   pkgCdrom();
+   virtual ~pkgCdrom();
+
  private:
+   void *d;
+
    APT_HIDDEN bool MountAndIdentCDROM(Configuration &Database, std::string &CDROM,
 	 std::string &ident, pkgCdromStatus * const log, bool const interactive);
    APT_HIDDEN bool UnmountCDROM(std::string const &CDROM, pkgCdromStatus * const log);
@@ -92,6 +98,7 @@ struct CdromDevice							/*{{{*/
 									/*}}}*/
 class pkgUdevCdromDevices						/*{{{*/
 {
+   void *d;
  protected:
    // libudev dlopen structure
    void *libudev_handle;

+ 2 - 1
apt-pkg/clean.cc

@@ -106,7 +106,7 @@ bool pkgArchiveCleaner::Go(std::string Dir,pkgCache &Cache)
 		 J.end() == false; ++J)
 	    {
 	       if (CleanInstalled == true &&
-		   (J.File()->Flags & pkgCache::Flag::NotSource) != 0)
+		   J.File().Flagged(pkgCache::Flag::NotSource))
 		  continue;
 	       IsFetchable = true;
 	       break;
@@ -132,4 +132,5 @@ bool pkgArchiveCleaner::Go(std::string Dir,pkgCache &Cache)
 }
 									/*}}}*/
 
+pkgArchiveCleaner::pkgArchiveCleaner() {}
 APT_CONST pkgArchiveCleaner::~pkgArchiveCleaner() {}

+ 2 - 0
apt-pkg/clean.h

@@ -30,6 +30,8 @@ class pkgArchiveCleaner
    public:
 
    bool Go(std::string Dir,pkgCache &Cache);
+
+   pkgArchiveCleaner();
    virtual ~pkgArchiveCleaner();
 };
 

+ 16 - 15
apt-pkg/contrib/cdromutl.cc

@@ -207,7 +207,6 @@ bool IdentCdrom(string CD,string &Res,unsigned int Version)
    /* Run over the directory, we assume that the reader order will never
       change as the media is read-only. In theory if the kernel did
       some sort of wacked caching this might not be true.. */
-   char S[300];
    for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D))
    {
       // Skip some files..
@@ -215,30 +214,32 @@ bool IdentCdrom(string CD,string &Res,unsigned int Version)
 	  strcmp(Dir->d_name,"..") == 0)
 	 continue;
 
+      std::string S;
       if (Version <= 1)
       {
-	 sprintf(S,"%lu",(unsigned long)Dir->d_ino);
+	 strprintf(S, "%lu", (unsigned long)Dir->d_ino);
       }
       else
       {
 	 struct stat Buf;
 	 if (stat(Dir->d_name,&Buf) != 0)
 	    continue;
-	 sprintf(S,"%lu",(unsigned long)Buf.st_mtime);
+	 strprintf(S, "%lu", (unsigned long)Buf.st_mtime);
       }
-      
-      Hash.Add(S);
+
+      Hash.Add(S.c_str());
       Hash.Add(Dir->d_name);
    };
-   
+
    if (chdir(StartDir.c_str()) != 0) {
       _error->Errno("chdir",_("Unable to change to %s"),StartDir.c_str());
       closedir(D);
       return false;
    }
    closedir(D);
-   
+
    // Some stats from the fsys
+   std::string S;
    if (_config->FindB("Debug::identcdrom",false) == false)
    {
       struct statvfs Buf;
@@ -248,19 +249,19 @@ bool IdentCdrom(string CD,string &Res,unsigned int Version)
       // We use a kilobyte block size to advoid overflow
       if (writable_media)
       {
-         sprintf(S,"%lu",(long)(Buf.f_blocks*(Buf.f_bsize/1024)));
+         strprintf(S, "%lu", (unsigned long)(Buf.f_blocks*(Buf.f_bsize/1024)));
       } else {
-         sprintf(S,"%lu %lu",(long)(Buf.f_blocks*(Buf.f_bsize/1024)),
-                 (long)(Buf.f_bfree*(Buf.f_bsize/1024)));
+         strprintf(S, "%lu %lu", (unsigned long)(Buf.f_blocks*(Buf.f_bsize/1024)),
+                 (unsigned long)(Buf.f_bfree*(Buf.f_bsize/1024)));
       }
-      Hash.Add(S);
-      sprintf(S,"-%u",Version);
+      Hash.Add(S.c_str());
+      strprintf(S, "-%u", Version);
    }
    else
-      sprintf(S,"-%u.debug",Version);
-   
+      strprintf(S, "-%u.debug", Version);
+
    Res = Hash.Result().Value() + S;
-   return true;   
+   return true;
 }
 									/*}}}*/
 // FindMountPointForDevice - Find mountpoint for the given device	/*{{{*/

+ 3 - 0
apt-pkg/contrib/cmndline.cc

@@ -33,6 +33,9 @@ using namespace std;
 CommandLine::CommandLine(Args *AList,Configuration *Conf) : ArgList(AList), 
                                  Conf(Conf), FileList(0)
 {
+}
+CommandLine::CommandLine() : ArgList(NULL), Conf(NULL), FileList(0)
+{
 }
 									/*}}}*/
 // CommandLine::~CommandLine - Destructor				/*{{{*/

+ 1 - 0
apt-pkg/contrib/cmndline.h

@@ -91,6 +91,7 @@ class CommandLine
    static CommandLine::Args MakeArgs(char ShortOpt, char const *LongOpt,
 	 char const *ConfName, unsigned long Flags) APT_CONST;
 
+   CommandLine();
    CommandLine(Args *AList,Configuration *Conf);
    ~CommandLine();
 };

+ 13 - 7
apt-pkg/contrib/configuration.cc

@@ -253,7 +253,13 @@ string Configuration::FindDir(const char *Name,const char *Default) const
 // Configuration::FindVector - Find a vector of values			/*{{{*/
 // ---------------------------------------------------------------------
 /* Returns a vector of config values under the given item */
-vector<string> Configuration::FindVector(const char *Name, std::string const &Default) const
+#if APT_PKG_ABI < 413
+vector<string> Configuration::FindVector(const char *Name) const
+{
+   return FindVector(Name, "");
+}
+#endif
+vector<string> Configuration::FindVector(const char *Name, std::string const &Default, bool const Keys) const
 {
    vector<string> Vec;
    const Item *Top = Lookup(Name);
@@ -266,7 +272,7 @@ vector<string> Configuration::FindVector(const char *Name, std::string const &De
    Item *I = Top->Child;
    while(I != NULL)
    {
-      Vec.push_back(I->Value);
+      Vec.push_back(Keys ? I->Tag : I->Value);
       I = I->Next;
    }
    if (Vec.empty() == true)
@@ -623,19 +629,19 @@ string Configuration::Item::FullTag(const Item *Stop) const
    tag/value. AsSectional enables Sectional parsing.*/
 bool ReadConfigFile(Configuration &Conf,const string &FName,bool const &AsSectional,
 		    unsigned const &Depth)
-{   
+{
    // Open the stream for reading
-   ifstream F(FName.c_str(),ios::in); 
-   if (!F != 0)
+   ifstream F(FName.c_str(),ios::in);
+   if (F.fail() == true)
       return _error->Errno("ifstream::ifstream",_("Opening configuration file %s"),FName.c_str());
 
    string LineBuffer;
    string Stack[100];
    unsigned int StackPos = 0;
-   
+
    // Parser state
    string ParentTag;
-   
+
    int CurLine = 0;
    bool InComment = false;
    while (F.eof() == false)

+ 3 - 2
apt-pkg/contrib/configuration.h

@@ -84,8 +84,9 @@ class Configuration
     *
     * \param Name of the parent node
     * \param Default list of values separated by commas */
-   std::vector<std::string> FindVector(const char *Name, std::string const &Default = "") const;
-   std::vector<std::string> FindVector(std::string const &Name, std::string const &Default = "") const { return FindVector(Name.c_str(), Default); };
+   std::vector<std::string> FindVector(const char *Name, std::string const &Default = "", bool const Keys = false) const;
+   std::vector<std::string> FindVector(std::string const &Name, std::string const &Default = "", bool const Keys = false) const { return FindVector(Name.c_str(), Default, Keys); };
+
    int FindI(const char *Name,int const &Default = 0) const;
    int FindI(std::string const &Name,int const &Default = 0) const {return FindI(Name.c_str(),Default);};
    bool FindB(const char *Name,bool const &Default = false) const;

+ 21 - 1
apt-pkg/contrib/fileutl.cc

@@ -800,8 +800,9 @@ pid_t ExecFork(std::set<int> KeepFDs)
       signal(SIGCONT,SIG_DFL);
       signal(SIGTSTP,SIG_DFL);
 
+      long ScOpenMax = sysconf(_SC_OPEN_MAX);
       // Close all of our FDs - just in case
-      for (int K = 3; K != sysconf(_SC_OPEN_MAX); K++)
+      for (int K = 3; K != ScOpenMax; K++)
       {
 	 if(KeepFDs.find(K) == KeepFDs.end())
 	    fcntl(K,F_SETFD,FD_CLOEXEC);
@@ -874,6 +875,25 @@ bool StartsWithGPGClearTextSignature(string const &FileName)
    return true;
 }
 									/*}}}*/
+// ChangeOwnerAndPermissionOfFile - set file attributes to requested values /*{{{*/
+bool ChangeOwnerAndPermissionOfFile(char const * const requester, char const * const file, char const * const user, char const * const group, mode_t const mode)
+{
+   if (strcmp(file, "/dev/null") == 0)
+      return true;
+   bool Res = true;
+   if (getuid() == 0 && strlen(user) != 0 && strlen(group) != 0) // if we aren't root, we can't chown, so don't try it
+   {
+      // ensure the file is owned by root and has good permissions
+      struct passwd const * const pw = getpwnam(user);
+      struct group const * const gr = getgrnam(group);
+      if (pw != NULL && gr != NULL && chown(file, pw->pw_uid, gr->gr_gid) != 0)
+	 Res &= _error->WarningE(requester, "chown to %s:%s of file %s failed", user, group, file);
+   }
+   if (chmod(file, mode) != 0)
+      Res &= _error->WarningE(requester, "chmod 0%o of file %s failed", mode, file);
+   return Res;
+}
+									/*}}}*/
 
 class FileFdPrivate {							/*{{{*/
 	public:

+ 12 - 1
apt-pkg/contrib/fileutl.h

@@ -195,10 +195,21 @@ pid_t ExecFork(std::set<int> keep_fds);
 void MergeKeepFdsFromConfiguration(std::set<int> &keep_fds);
 bool ExecWait(pid_t Pid,const char *Name,bool Reap = false);
 
-
 // check if the given file starts with a PGP cleartext signature
 bool StartsWithGPGClearTextSignature(std::string const &FileName);
 
+/** change file attributes to requested known good values
+ *
+ * The method skips the user:group setting if not root.
+ *
+ * @param requester is printed as functionname in error cases
+ * @param file is the file to be modified
+ * @param user is the (new) owner of the file, e.g. _apt
+ * @param group is the (new) group owning the file, e.g. root
+ * @param mode is the access mode of the file, e.g. 0644
+ */
+bool ChangeOwnerAndPermissionOfFile(char const * const requester, char const * const file, char const * const user, char const * const group, mode_t const mode);
+
 /**
  * \brief Drop privileges
  *

+ 86 - 46
apt-pkg/contrib/hashes.cc

@@ -23,6 +23,7 @@
 #include <stddef.h>
 #include <algorithm>
 #include <unistd.h>
+#include <stdlib.h>
 #include <string>
 #include <iostream>
 									/*}}}*/
@@ -178,6 +179,22 @@ HashString const * HashStringList::find(char const * const type) const /*{{{*/
    return NULL;
 }
 									/*}}}*/
+unsigned long long HashStringList::FileSize() const			/*{{{*/
+{
+   HashString const * const hsf = find("Checksum-FileSize");
+   if (hsf == NULL)
+      return 0;
+   std::string const hv = hsf->HashValue();
+   return strtoull(hv.c_str(), NULL, 10);
+}
+									/*}}}*/
+bool HashStringList::FileSize(unsigned long long const Size)		/*{{{*/
+{
+   std::string size;
+   strprintf(size, "%llu", Size);
+   return push_back(HashString("Checksum-FileSize", size));
+}
+									/*}}}*/
 bool HashStringList::supported(char const * const type)			/*{{{*/
 {
    for (char const * const * t = HashString::SupportedHashes(); *t != NULL; ++t)
@@ -204,15 +221,22 @@ bool HashStringList::push_back(const HashString &hashString)		/*{{{*/
 									/*}}}*/
 bool HashStringList::VerifyFile(std::string filename) const		/*{{{*/
 {
-   if (list.empty() == true)
-      return false;
-   HashString const * const hs = find(NULL);
-   if (hs == NULL || hs->VerifyFile(filename) == false)
+   if (usable() == false)
       return false;
+
+   Hashes hashes(*this);
+   FileFd file(filename, FileFd::ReadOnly);
    HashString const * const hsf = find("Checksum-FileSize");
-   if (hsf != NULL && hsf->VerifyFile(filename) == false)
-      return false;
-   return true;
+   if (hsf != NULL)
+   {
+      std::string fileSize;
+      strprintf(fileSize, "%llu", file.FileSize());
+      if (hsf->HashValue() != fileSize)
+	 return false;
+   }
+   hashes.AddFD(file);
+   HashStringList const hsl = hashes.GetHashStringList();
+   return hsl == *this;
 }
 									/*}}}*/
 bool HashStringList::operator==(HashStringList const &other) const	/*{{{*/
@@ -250,33 +274,34 @@ bool HashStringList::operator!=(HashStringList const &other) const
 class PrivateHashes {
 public:
    unsigned long long FileSize;
+   unsigned int CalcHashes;
 
-   PrivateHashes() : FileSize(0) {}
+   PrivateHashes(unsigned int const CalcHashes) : FileSize(0), CalcHashes(CalcHashes) {}
 };
 									/*}}}*/
 // Hashes::Add* - Add the contents of data or FD			/*{{{*/
-bool Hashes::Add(const unsigned char * const Data,unsigned long long const Size, unsigned int const Hashes)
+bool Hashes::Add(const unsigned char * const Data, unsigned long long const Size)
 {
    bool Res = true;
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-   if ((Hashes & MD5SUM) == MD5SUM)
+APT_IGNORE_DEPRECATED_PUSH
+   if ((d->CalcHashes & MD5SUM) == MD5SUM)
       Res &= MD5.Add(Data, Size);
-   if ((Hashes & SHA1SUM) == SHA1SUM)
+   if ((d->CalcHashes & SHA1SUM) == SHA1SUM)
       Res &= SHA1.Add(Data, Size);
-   if ((Hashes & SHA256SUM) == SHA256SUM)
+   if ((d->CalcHashes & SHA256SUM) == SHA256SUM)
       Res &= SHA256.Add(Data, Size);
-   if ((Hashes & SHA512SUM) == SHA512SUM)
+   if ((d->CalcHashes & SHA512SUM) == SHA512SUM)
       Res &= SHA512.Add(Data, Size);
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP
    d->FileSize += Size;
    return Res;
 }
-bool Hashes::AddFD(int const Fd,unsigned long long Size, unsigned int const Hashes)
+bool Hashes::Add(const unsigned char * const Data, unsigned long long const Size, unsigned int const Hashes)
+{
+   d->CalcHashes = Hashes;
+   return Add(Data, Size);
+}
+bool Hashes::AddFD(int const Fd,unsigned long long Size)
 {
    unsigned char Buf[64*64];
    bool const ToEOF = (Size == UntilEOF);
@@ -290,12 +315,17 @@ bool Hashes::AddFD(int const Fd,unsigned long long Size, unsigned int const Hash
       if (ToEOF && Res == 0) // EOF
 	 break;
       Size -= Res;
-      if (Add(Buf, Res, Hashes) == false)
+      if (Add(Buf, Res) == false)
 	 return false;
    }
    return true;
 }
-bool Hashes::AddFD(FileFd &Fd,unsigned long long Size, unsigned int const Hashes)
+bool Hashes::AddFD(int const Fd,unsigned long long Size, unsigned int const Hashes)
+{
+   d->CalcHashes = Hashes;
+   return AddFD(Fd, Size);
+}
+bool Hashes::AddFD(FileFd &Fd,unsigned long long Size)
 {
    unsigned char Buf[64*64];
    bool const ToEOF = (Size == 0);
@@ -314,37 +344,47 @@ bool Hashes::AddFD(FileFd &Fd,unsigned long long Size, unsigned int const Hashes
       else if (a == 0) // EOF
 	 break;
       Size -= a;
-      if (Add(Buf, a, Hashes) == false)
+      if (Add(Buf, a) == false)
 	 return false;
    }
    return true;
+}
+bool Hashes::AddFD(FileFd &Fd,unsigned long long Size, unsigned int const Hashes)
+{
+   d->CalcHashes = Hashes;
+   return AddFD(Fd, Size);
 }
 									/*}}}*/
 HashStringList Hashes::GetHashStringList()
 {
    HashStringList hashes;
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-   hashes.push_back(HashString("MD5Sum", MD5.Result().Value()));
-   hashes.push_back(HashString("SHA1", SHA1.Result().Value()));
-   hashes.push_back(HashString("SHA256", SHA256.Result().Value()));
-   hashes.push_back(HashString("SHA512", SHA512.Result().Value()));
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
-   std::string SizeStr;
-   strprintf(SizeStr, "%llu", d->FileSize);
-   hashes.push_back(HashString("Checksum-FileSize", SizeStr));
+APT_IGNORE_DEPRECATED_PUSH
+   if ((d->CalcHashes & MD5SUM) == MD5SUM)
+      hashes.push_back(HashString("MD5Sum", MD5.Result().Value()));
+   if ((d->CalcHashes & SHA1SUM) == SHA1SUM)
+      hashes.push_back(HashString("SHA1", SHA1.Result().Value()));
+   if ((d->CalcHashes & SHA256SUM) == SHA256SUM)
+      hashes.push_back(HashString("SHA256", SHA256.Result().Value()));
+   if ((d->CalcHashes & SHA512SUM) == SHA512SUM)
+      hashes.push_back(HashString("SHA512", SHA512.Result().Value()));
+APT_IGNORE_DEPRECATED_POP
+   hashes.FileSize(d->FileSize);
    return hashes;
 }
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-Hashes::Hashes() { d = new PrivateHashes(); }
+APT_IGNORE_DEPRECATED_PUSH
+Hashes::Hashes() { d = new PrivateHashes(~0); }
+Hashes::Hashes(unsigned int const Hashes) { d = new PrivateHashes(Hashes); }
+Hashes::Hashes(HashStringList const &Hashes) {
+   unsigned int calcHashes = Hashes.usable() ? 0 : ~0;
+   if (Hashes.find("MD5Sum") != NULL)
+      calcHashes |= MD5SUM;
+   if (Hashes.find("SHA1") != NULL)
+      calcHashes |= SHA1SUM;
+   if (Hashes.find("SHA256") != NULL)
+      calcHashes |= SHA256SUM;
+   if (Hashes.find("SHA512") != NULL)
+      calcHashes |= SHA512SUM;
+   d = new PrivateHashes(calcHashes);
+}
 Hashes::~Hashes() { delete d; }
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP

+ 37 - 11
apt-pkg/contrib/hashes.h

@@ -55,6 +55,8 @@ class HashString
    // get hash type used
    std::string HashType() const { return Type; };
    std::string HashValue() const { return Hash; };
+   APT_DEPRECATED std::string HashType() { return Type; };
+   APT_DEPRECATED std::string HashValue() { return Hash; };
 
    // verify the given filename against the currently loaded hash
    bool VerifyFile(std::string filename) const;
@@ -85,6 +87,22 @@ class HashStringList
     */
    HashString const * find(char const * const type) const;
    HashString const * find(std::string const &type) const { return find(type.c_str()); }
+
+   /** finds the filesize hash and returns it as number
+    *
+    * @return beware: if the size isn't known we return \b 0 here,
+    * just like we would do for an empty file. If that is a problem
+    * for you have to get the size manually out of the list.
+    */
+   unsigned long long FileSize() const;
+
+   /** sets the filesize hash
+    *
+    * @param Size of the file
+    * @return @see #push_back
+    */
+   bool FileSize(unsigned long long const Size);
+
    /** check if the given hash type is supported
     *
     * @param type to check
@@ -176,7 +194,8 @@ class Hashes
 
    static const int UntilEOF = 0;
 
-   bool Add(const unsigned char * const Data, unsigned long long const Size, unsigned int const Hashes = ~0);
+   bool Add(const unsigned char * const Data, unsigned long long const Size);
+   APT_DEPRECATED bool Add(const unsigned char * const Data, unsigned long long const Size, unsigned int const Hashes);
    inline bool Add(const char * const Data)
    {return Add((unsigned char const * const)Data,strlen(Data));};
    inline bool Add(const unsigned char * const Beg,const unsigned char * const End)
@@ -184,20 +203,26 @@ class Hashes
 
    enum SupportedHashes { MD5SUM = (1 << 0), SHA1SUM = (1 << 1), SHA256SUM = (1 << 2),
       SHA512SUM = (1 << 3) };
-   bool AddFD(int const Fd,unsigned long long Size = 0, unsigned int const Hashes = ~0);
-   bool AddFD(FileFd &Fd,unsigned long long Size = 0, unsigned int const Hashes = ~0);
+   bool AddFD(int const Fd,unsigned long long Size = 0);
+   APT_DEPRECATED bool AddFD(int const Fd,unsigned long long Size, unsigned int const Hashes);
+   bool AddFD(FileFd &Fd,unsigned long long Size = 0);
+   APT_DEPRECATED bool AddFD(FileFd &Fd,unsigned long long Size, unsigned int const Hashes);
 
    HashStringList GetHashStringList();
 
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+APT_IGNORE_DEPRECATED_PUSH
+   /** create a Hashes object to calculate all supported hashes
+    *
+    * If ALL is too much, you can limit which Hashes are calculated
+    * with the following other constructors which mention explicitly
+    * which hashes to generate. */
    Hashes();
+   /** @param Hashes bitflag composed of #SupportedHashes */
+   Hashes(unsigned int const Hashes);
+   /** @param Hashes is a list of hashes */
+   Hashes(HashStringList const &Hashes);
    virtual ~Hashes();
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP
 
    private:
    APT_HIDDEN APT_CONST inline unsigned int boolsToFlag(bool const addMD5, bool const addSHA1, bool const addSHA256, bool const addSHA512)
@@ -211,15 +236,16 @@ class Hashes
    }
 
    public:
+APT_IGNORE_DEPRECATED_PUSH
    APT_DEPRECATED bool AddFD(int const Fd, unsigned long long Size, bool const addMD5,
 	 bool const addSHA1, bool const addSHA256, bool const addSHA512) {
       return AddFD(Fd, Size, boolsToFlag(addMD5, addSHA1, addSHA256, addSHA512));
    };
-
    APT_DEPRECATED bool AddFD(FileFd &Fd, unsigned long long Size, bool const addMD5,
 	 bool const addSHA1, bool const addSHA256, bool const addSHA512) {
       return AddFD(Fd, Size, boolsToFlag(addMD5, addSHA1, addSHA256, addSHA512));
    };
+APT_IGNORE_DEPRECATED_POP
 };
 
 #endif

+ 18 - 1
apt-pkg/contrib/macros.h

@@ -89,7 +89,7 @@
 	#define APT_MUSTCHECK		__attribute__((warn_unused_result))
 #else
 	#define APT_NONNULL(...)
-	#define APT_REQRET
+	#define APT_MUSTCHECK
 #endif
 
 #if APT_GCC_VERSION >= 0x0400
@@ -132,6 +132,22 @@
 #endif
 #endif
 
+#if __GNUC__ >= 4
+	#define APT_IGNORE_DEPRECATED_PUSH \
+		_Pragma("GCC diagnostic push") \
+		_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+	#define APT_IGNORE_DEPRECATED_POP \
+		_Pragma("GCC diagnostic pop")
+	#define APT_IGNORE_DEPRECATED(XXX) \
+		APT_IGNORE_DEPRECATED_PUSH \
+		XXX \
+		APT_IGNORE_DEPRECATED_POP
+#else
+	#define APT_IGNORE_DEPRECATED_PUSH
+	#define APT_IGNORE_DEPRECATED_POP
+	#define APT_IGNORE_DEPRECATED(XXX) XXX
+#endif
+
 // These lines are extracted by the makefiles and the buildsystem
 // Increasing MAJOR or MINOR results in the need of recompiling all
 // reverse-dependencies of libapt-pkg against the new SONAME.
@@ -140,5 +156,6 @@
 #define APT_PKG_MAJOR 4
 #define APT_PKG_MINOR 15
 #define APT_PKG_RELEASE 0
+#define APT_PKG_ABI ((APT_PKG_MAJOR * 100) + APT_PKG_MINOR)
 
 #endif

+ 9 - 0
apt-pkg/contrib/sha2_internal.cc

@@ -129,6 +129,14 @@ typedef u_int64_t sha2_word64;	/* Exactly 8 bytes */
 
 /*** ENDIAN REVERSAL MACROS *******************************************/
 #if BYTE_ORDER == LITTLE_ENDIAN
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
+#define REVERSE32(w,x)	{ \
+	(x) = __builtin_bswap32(w); \
+}
+#define REVERSE64(w,x)	{ \
+	(x) = __builtin_bswap64(w); \
+}
+#else
 #define REVERSE32(w,x)	{ \
 	sha2_word32 tmp = (w); \
 	tmp = (tmp >> 16) | (tmp << 16); \
@@ -142,6 +150,7 @@ typedef u_int64_t sha2_word64;	/* Exactly 8 bytes */
 	(x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
 	      ((tmp & 0x0000ffff0000ffffULL) << 16); \
 }
+#endif
 #endif /* BYTE_ORDER == LITTLE_ENDIAN */
 
 /*

+ 74 - 79
apt-pkg/contrib/strutl.cc

@@ -324,21 +324,19 @@ bool ParseCWord(const char *&String,string &Res)
 /* */
 string QuoteString(const string &Str, const char *Bad)
 {
-   string Res;
+   std::stringstream Res;
    for (string::const_iterator I = Str.begin(); I != Str.end(); ++I)
    {
-      if (strchr(Bad,*I) != 0 || isprint(*I) == 0 || 
+      if (strchr(Bad,*I) != 0 || isprint(*I) == 0 ||
 	  *I == 0x25 || // percent '%' char
 	  *I <= 0x20 || *I >= 0x7F) // control chars
       {
-	 char Buf[10];
-	 sprintf(Buf,"%%%02x",(int)*I);
-	 Res += Buf;
+	 ioprintf(Res,"%%%02x",(int)*I);
       }
       else
-	 Res += *I;
+	 Res << *I;
    }
-   return Res;
+   return Res.str();
 }
 									/*}}}*/
 // DeQuoteString - Convert a string from quoted from                    /*{{{*/
@@ -379,13 +377,12 @@ string DeQuoteString(string::const_iterator const &begin,
    YottaBytes (E24) */
 string SizeToStr(double Size)
 {
-   char S[300];
    double ASize;
    if (Size >= 0)
       ASize = Size;
    else
       ASize = -1*Size;
-   
+
    /* bytes, KiloBytes, MegaBytes, GigaBytes, TeraBytes, PetaBytes, 
       ExaBytes, ZettaBytes, YottaBytes */
    char Ext[] = {'\0','k','M','G','T','P','E','Z','Y'};
@@ -394,20 +391,21 @@ string SizeToStr(double Size)
    {
       if (ASize < 100 && I != 0)
       {
-         sprintf(S,"%'.1f %c",ASize,Ext[I]);
-	 break;
+	 std::string S;
+	 strprintf(S, "%'.1f %c", ASize, Ext[I]);
+	 return S;
       }
-      
+
       if (ASize < 10000)
       {
-         sprintf(S,"%'.0f %c",ASize,Ext[I]);
-	 break;
+	 std::string S;
+	 strprintf(S, "%'.0f %c", ASize, Ext[I]);
+	 return S;
       }
       ASize /= 1000.0;
       I++;
    }
-   
-   return S;
+   return "";
 }
 									/*}}}*/
 // TimeToStr - Convert the time into a string				/*{{{*/
@@ -415,36 +413,27 @@ string SizeToStr(double Size)
 /* Converts a number of seconds to a hms format */
 string TimeToStr(unsigned long Sec)
 {
-   char S[300];
-   
-   while (1)
+   std::string S;
+   if (Sec > 60*60*24)
    {
-      if (Sec > 60*60*24)
-      {
-	 //d means days, h means hours, min means minutes, s means seconds
-	 sprintf(S,_("%lid %lih %limin %lis"),Sec/60/60/24,(Sec/60/60) % 24,(Sec/60) % 60,Sec % 60);
-	 break;
-      }
-      
-      if (Sec > 60*60)
-      {
-	 //h means hours, min means minutes, s means seconds
-	 sprintf(S,_("%lih %limin %lis"),Sec/60/60,(Sec/60) % 60,Sec % 60);
-	 break;
-      }
-      
-      if (Sec > 60)
-      {
-	 //min means minutes, s means seconds
-	 sprintf(S,_("%limin %lis"),Sec/60,Sec % 60);
-	 break;
-      }
-
-      //s means seconds
-      sprintf(S,_("%lis"),Sec);
-      break;
+      //TRANSLATOR: d means days, h means hours, min means minutes, s means seconds
+      strprintf(S,_("%lid %lih %limin %lis"),Sec/60/60/24,(Sec/60/60) % 24,(Sec/60) % 60,Sec % 60);
+   }
+   else if (Sec > 60*60)
+   {
+      //TRANSLATOR: h means hours, min means minutes, s means seconds
+      strprintf(S,_("%lih %limin %lis"),Sec/60/60,(Sec/60) % 60,Sec % 60);
+   }
+   else if (Sec > 60)
+   {
+      //TRANSLATOR: min means minutes, s means seconds
+      strprintf(S,_("%limin %lis"),Sec/60,Sec % 60);
+   }
+   else
+   {
+      //TRANSLATOR: s means seconds
+      strprintf(S,_("%lis"),Sec);
    }
-   
    return S;
 }
 									/*}}}*/
@@ -1319,10 +1308,12 @@ void ioprintf(ostream &out,const char *format,...)
    va_list args;
    ssize_t size = 400;
    while (true) {
+      bool ret = false;
       va_start(args,format);
-      if (iovprintf(out, format, args, size) == true)
-	 return;
+      ret = iovprintf(out, format, args, size);
       va_end(args);
+      if (ret == true)
+	 return;
    }
 }
 void strprintf(string &out,const char *format,...)
@@ -1331,10 +1322,12 @@ void strprintf(string &out,const char *format,...)
    ssize_t size = 400;
    std::ostringstream outstr;
    while (true) {
+      bool ret = false;
       va_start(args,format);
-      if (iovprintf(outstr, format, args, size) == true)
-	 break;
+      ret = iovprintf(outstr, format, args, size);
       va_end(args);
+      if (ret == true)
+	 break;
    }
    out = outstr.str();
 }
@@ -1419,7 +1412,7 @@ size_t strv_length(const char **str_array)
       ;
    return i;
 }
-
+									/*}}}*/
 // DeEscapeString - unescape (\0XX and \xXX) from a string		/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -1601,56 +1594,49 @@ void URI::CopyFrom(const string &U)
 /* */
 URI::operator string()
 {
-   string Res;
-   
+   std::stringstream Res;
+
    if (Access.empty() == false)
-      Res = Access + ':';
-   
+      Res << Access << ':';
+
    if (Host.empty() == false)
-   {	 
+   {
       if (Access.empty() == false)
-	 Res += "//";
-          
+	 Res << "//";
+
       if (User.empty() == false)
       {
 	 // FIXME: Technically userinfo is permitted even less
 	 // characters than these, but this is not conveniently
 	 // expressed with a blacklist.
-	 Res += QuoteString(User, ":/?#[]@");
+	 Res << QuoteString(User, ":/?#[]@");
 	 if (Password.empty() == false)
-	    Res += ":" + QuoteString(Password, ":/?#[]@");
-	 Res += "@";
+	    Res << ":" << QuoteString(Password, ":/?#[]@");
+	 Res << "@";
       }
-      
+
       // Add RFC 2732 escaping characters
-      if (Access.empty() == false &&
-	  (Host.find('/') != string::npos || Host.find(':') != string::npos))
-	 Res += '[' + Host + ']';
+      if (Access.empty() == false && Host.find_first_of("/:") != string::npos)
+	 Res << '[' << Host << ']';
       else
-	 Res += Host;
-      
+	 Res << Host;
+
       if (Port != 0)
-      {
-	 char S[30];
-	 sprintf(S,":%u",Port);
-	 Res += S;
-      }	 
+	 Res << ':' << Port;
    }
-   
+
    if (Path.empty() == false)
    {
       if (Path[0] != '/')
-	 Res += "/" + Path;
+	 Res << "/" << Path;
       else
-	 Res += Path;
+	 Res << Path;
    }
-   
-   return Res;
+
+   return Res.str();
 }
 									/*}}}*/
 // URI::SiteOnly - Return the schema and site for the URI		/*{{{*/
-// ---------------------------------------------------------------------
-/* */
 string URI::SiteOnly(const string &URI)
 {
    ::URI U(URI);
@@ -1660,9 +1646,18 @@ string URI::SiteOnly(const string &URI)
    return U;
 }
 									/*}}}*/
+// URI::ArchiveOnly - Return the schema, site and cleaned path for the URI /*{{{*/
+string URI::ArchiveOnly(const string &URI)
+{
+   ::URI U(URI);
+   U.User.clear();
+   U.Password.clear();
+   if (U.Path.empty() == false && U.Path[U.Path.length() - 1] == '/')
+      U.Path.erase(U.Path.length() - 1);
+   return U;
+}
+									/*}}}*/
 // URI::NoUserPassword - Return the schema, site and path for the URI	/*{{{*/
-// ---------------------------------------------------------------------
-/* */
 string URI::NoUserPassword(const string &URI)
 {
    ::URI U(URI);

+ 2 - 1
apt-pkg/contrib/strutl.h

@@ -81,7 +81,7 @@ bool TokSplitString(char Tok,char *Input,char **List,
 		    unsigned long ListMax);
 
 // split a given string by a char
-std::vector<std::string> VectorizeString(std::string const &haystack, char const &split) APT_CONST;
+std::vector<std::string> VectorizeString(std::string const &haystack, char const &split) APT_PURE;
 
 /* \brief Return a vector of strings from string "input" where "sep"
  * is used as the delimiter string.
@@ -167,6 +167,7 @@ class URI
    inline void operator =(const std::string &From) {CopyFrom(From);}
    inline bool empty() {return Access.empty();};
    static std::string SiteOnly(const std::string &URI);
+   static std::string ArchiveOnly(const std::string &URI);
    static std::string NoUserPassword(const std::string &URI);
    
    URI(std::string Path) {CopyFrom(Path);}

+ 98 - 427
apt-pkg/deb/debindexfile.cc

@@ -34,6 +34,7 @@
 
 #include <stdio.h>
 #include <iostream>
+#include <sstream>
 #include <string>
 #include <sys/stat.h>
 									/*}}}*/
@@ -43,8 +44,8 @@ using std::string;
 // SourcesIndex::debSourcesIndex - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-debSourcesIndex::debSourcesIndex(string URI,string Dist,string Section,bool Trusted) :
-     pkgIndexFile(Trusted), URI(URI), Dist(Dist), Section(Section)
+debSourcesIndex::debSourcesIndex(IndexTarget const &Target,bool const Trusted) :
+     pkgIndexTargetFile(Target, Trusted)
 {
 }
 									/*}}}*/
@@ -55,16 +56,9 @@ debSourcesIndex::debSourcesIndex(string URI,string Dist,string Section,bool Trus
 string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record,
 				   pkgSrcRecords::File const &File) const
 {
-   string Res;
-   Res = ::URI::NoUserPassword(URI) + ' ';
-   if (Dist[Dist.size() - 1] == '/')
-   {
-      if (Dist != "/")
-	 Res += Dist;
-   }      
-   else
-      Res += Dist + '/' + Section;
-   
+   string Res = Target.Description;
+   Res.erase(Target.Description.rfind(' '));
+
    Res += " ";
    Res += Record.Package();
    Res += " ";
@@ -79,129 +73,19 @@ string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record,
 /* */
 pkgSrcRecords::Parser *debSourcesIndex::CreateSrcParser() const
 {
-   string SourcesURI = _config->FindDir("Dir::State::lists") + 
-      URItoFileName(IndexURI("Sources"));
-
-   std::vector<std::string> types = APT::Configuration::getCompressionTypes();
-   for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
-   {
-      string p;
-      p = SourcesURI + '.' + *t;
-      if (FileExists(p))
-         return new debSrcRecordParser(p, this);
-   }
+   string const SourcesURI = IndexFileName();
    if (FileExists(SourcesURI))
       return new debSrcRecordParser(SourcesURI, this);
    return NULL;
 }
 									/*}}}*/
-// SourcesIndex::Describe - Give a descriptive path to the index	/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string debSourcesIndex::Describe(bool Short) const
-{
-   char S[300];
-   if (Short == true)
-      snprintf(S,sizeof(S),"%s",Info("Sources").c_str());
-   else
-      snprintf(S,sizeof(S),"%s (%s)",Info("Sources").c_str(),
-	       IndexFile("Sources").c_str());
-   
-   return S;
-}
-									/*}}}*/
-// SourcesIndex::Info - One liner describing the index URI		/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string debSourcesIndex::Info(const char *Type) const
-{
-   string Info = ::URI::NoUserPassword(URI) + ' ';
-   if (Dist[Dist.size() - 1] == '/')
-   {
-      if (Dist != "/")
-	 Info += Dist;
-   }
-   else
-      Info += Dist + '/' + Section;   
-   Info += " ";
-   Info += Type;
-   return Info;
-}
-									/*}}}*/
-// SourcesIndex::Index* - Return the URI to the index files		/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string debSourcesIndex::IndexFile(const char *Type) const
-{
-   string s = URItoFileName(IndexURI(Type));
-
-   std::vector<std::string> types = APT::Configuration::getCompressionTypes();
-   for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
-   {
-      string p = s + '.' + *t;
-      if (FileExists(p))
-         return p;
-   }
-   return s;
-}
-
-string debSourcesIndex::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 +
-      "/source/";
-   
-   Res += Type;
-   return Res;
-}
-									/*}}}*/
-// SourcesIndex::Exists - Check if the index is available		/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool debSourcesIndex::Exists() const
-{
-   return FileExists(IndexFile("Sources"));
-}
-									/*}}}*/
-// SourcesIndex::Size - Return the size of the index			/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-unsigned long debSourcesIndex::Size() const
-{
-   unsigned long size = 0;
-
-   /* we need to ignore errors here; if the lists are absent, just return 0 */
-   _error->PushToStack();
-
-   FileFd f(IndexFile("Sources"), FileFd::ReadOnly, FileFd::Extension);
-   if (!f.Failed())
-      size = f.Size();
-
-   if (_error->PendingError() == true)
-       size = 0;
-   _error->RevertToStack();
-
-   return size;
-}
-									/*}}}*/
 
 // PackagesIndex::debPackagesIndex - Contructor				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-debPackagesIndex::debPackagesIndex(string const &URI, string const &Dist, string const &Section,
-					bool const &Trusted, string const &Arch) :
-                  pkgIndexFile(Trusted), URI(URI), Dist(Dist), Section(Section), Architecture(Arch)
+debPackagesIndex::debPackagesIndex(IndexTarget const &Target, bool const Trusted) :
+                  pkgIndexTargetFile(Target, Trusted)
 {
-	if (Architecture == "native")
-		Architecture = _config->Find("APT::Architecture");
 }
 									/*}}}*/
 // PackagesIndex::ArchiveInfo - Short version of the archive url	/*{{{*/
@@ -209,137 +93,42 @@ debPackagesIndex::debPackagesIndex(string const &URI, string const &Dist, string
 /* This is a shorter version that is designed to be < 60 chars or so */
 string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator Ver) const
 {
-   string Res = ::URI::NoUserPassword(URI) + ' ';
-   if (Dist[Dist.size() - 1] == '/')
-   {
-      if (Dist != "/")
-	 Res += Dist;
-   }
-   else
-      Res += Dist + '/' + Section;
-   
+   std::string const Dist = Target.Option(IndexTarget::RELEASE);
+   string Res = Target.Option(IndexTarget::SITE) + " " + Dist;
+   std::string const Component = Target.Option(IndexTarget::COMPONENT);
+   if (Component.empty() == false)
+      Res += "/" + Component;
+
    Res += " ";
    Res += Ver.ParentPkg().Name();
    Res += " ";
-   if (Dist[Dist.size() - 1] != '/')
+   if (Dist.empty() == false && Dist[Dist.size() - 1] != '/')
       Res.append(Ver.Arch()).append(" ");
    Res += Ver.VerStr();
    return Res;
 }
 									/*}}}*/
-// PackagesIndex::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 debPackagesIndex::Describe(bool Short) const
-{   
-   char S[300];
-   if (Short == true)
-      snprintf(S,sizeof(S),"%s",Info("Packages").c_str());
-   else
-      snprintf(S,sizeof(S),"%s (%s)",Info("Packages").c_str(),
-	       IndexFile("Packages").c_str());
-   return S;
-}
-									/*}}}*/
-// PackagesIndex::Info - One liner describing the index URI		/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string debPackagesIndex::Info(const char *Type) const 
-{
-   string Info = ::URI::NoUserPassword(URI) + ' ';
-   if (Dist[Dist.size() - 1] == '/')
-   {
-      if (Dist != "/")
-	 Info += Dist;
-   }
-   else
-      Info += Dist + '/' + Section;   
-   Info += " ";
-   if (Dist[Dist.size() - 1] != '/')
-      Info += Architecture + " ";
-   Info += Type;
-   return Info;
-}
-									/*}}}*/
-// PackagesIndex::Index* - Return the URI to the index files		/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string debPackagesIndex::IndexFile(const char *Type) const
-{
-   string s =_config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type));
-
-   std::vector<std::string> types = APT::Configuration::getCompressionTypes();
-   for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
-   {
-      string p = s + '.' + *t;
-      if (FileExists(p))
-         return p;
-   }
-   return s;
-}
-string debPackagesIndex::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 +
-      "/binary-" + Architecture + '/';
-   
-   Res += Type;
-   return Res;
-}
-									/*}}}*/
-// PackagesIndex::Exists - Check if the index is available		/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool debPackagesIndex::Exists() const
-{
-   return FileExists(IndexFile("Packages"));
-}
-									/*}}}*/
-// PackagesIndex::Size - Return the size of the index			/*{{{*/
-// ---------------------------------------------------------------------
-/* This is really only used for progress reporting. */
-unsigned long debPackagesIndex::Size() const
-{
-   unsigned long size = 0;
-
-   /* we need to ignore errors here; if the lists are absent, just return 0 */
-   _error->PushToStack();
-
-   FileFd f(IndexFile("Packages"), FileFd::ReadOnly, FileFd::Extension);
-   if (!f.Failed())
-      size = f.Size();
-
-   if (_error->PendingError() == true)
-       size = 0;
-   _error->RevertToStack();
-
-   return size;
-}
-									/*}}}*/
 // PackagesIndex::Merge - Load the index file into a cache		/*{{{*/
 // ---------------------------------------------------------------------
 /* */
 bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
 {
-   string PackageFile = IndexFile("Packages");
+   string const PackageFile = IndexFileName();
    FileFd Pkg(PackageFile,FileFd::ReadOnly, FileFd::Extension);
-   debListParser Parser(&Pkg, Architecture);
+   debListParser Parser(&Pkg, Target.Option(IndexTarget::ARCHITECTURE));
 
    if (_error->PendingError() == true)
       return _error->Error("Problem opening %s",PackageFile.c_str());
    if (Prog != NULL)
-      Prog->SubProgress(0,Info("Packages"));
+      Prog->SubProgress(0, Target.Description);
+
+
+   std::string const URI = Target.Option(IndexTarget::REPO_URI);
+   std::string Dist = Target.Option(IndexTarget::RELEASE);
+   if (Dist.empty())
+      Dist = "/";
    ::URI Tmp(URI);
-   if (Gen.SelectFile(PackageFile,Tmp.Host,*this) == false)
+   if (Gen.SelectFile(PackageFile, *this, Target.Option(IndexTarget::ARCHITECTURE), Target.Option(IndexTarget::COMPONENT)) == false)
       return _error->Error("Problem with SelectFile %s",PackageFile.c_str());
 
    // Store the IMS information
@@ -347,31 +136,10 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
    pkgCacheGenerator::Dynamic<pkgCache::PkgFileIterator> DynFile(File);
    File->Size = Pkg.FileSize();
    File->mtime = Pkg.ModificationTime();
-   
+
    if (Gen.MergeList(Parser) == false)
       return _error->Error("Problem with MergeList %s",PackageFile.c_str());
 
-   // Check the release file
-   string ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("InRelease");
-   bool releaseExists = false;
-   if (FileExists(ReleaseFile) == true)
-      releaseExists = true;
-   else
-      ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("Release");
-
-   if (releaseExists == true || FileExists(ReleaseFile) == true)
-   {
-      FileFd Rel;
-      // Beware: The 'Release' file might be clearsigned in case the
-      // signature for an 'InRelease' file couldn't be checked
-      if (OpenMaybeClearSignedFile(ReleaseFile, Rel) == false)
-	 return false;
-
-      if (_error->PendingError() == true)
-	 return false;
-      Parser.LoadReleaseInfo(File,Rel,Section);
-   }
-   
    return true;
 }
 									/*}}}*/
@@ -380,7 +148,7 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
 /* */
 pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const
 {
-   string FileName = IndexFile("Packages");
+   string const FileName = IndexFileName();
    pkgCache::PkgFileIterator File = Cache.FileBegin();
    for (; File.end() == false; ++File)
    {
@@ -410,113 +178,13 @@ pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const
 									/*}}}*/
 
 // TranslationsIndex::debTranslationsIndex - Contructor			/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-debTranslationsIndex::debTranslationsIndex(string URI,string Dist,string Section,
-						char const * const Translation) :
-			pkgIndexFile(true), URI(URI), Dist(Dist), Section(Section),
-				Language(Translation)
+debTranslationsIndex::debTranslationsIndex(IndexTarget const &Target) :
+			pkgIndexTargetFile(Target, true)
 {}
 									/*}}}*/
-// TranslationIndex::Trans* - Return the URI to the translation files	/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string debTranslationsIndex::IndexFile(const char *Type) const
-{
-   string s =_config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type));
-
-   std::vector<std::string> types = APT::Configuration::getCompressionTypes();
-   for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
-   {
-      string p = s + '.' + *t;
-      if (FileExists(p))
-         return p;
-   }
-   return s;
-}
-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::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(Language).c_str());
-   return S;
-}
-									/*}}}*/
-// TranslationsIndex::Info - One liner describing the index URI		/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string debTranslationsIndex::Info(const char *Type) const 
-{
-   string Info = ::URI::NoUserPassword(URI) + ' ';
-   if (Dist[Dist.size() - 1] == '/')
-   {
-      if (Dist != "/")
-	 Info += Dist;
-   }
-   else
-      Info += Dist + '/' + Section;   
-   Info += " ";
-   Info += Type;
-   return Info;
-}
-									/*}}}*/
 bool debTranslationsIndex::HasPackages() const				/*{{{*/
 {
-   return FileExists(IndexFile(Language));
-}
-									/*}}}*/
-// TranslationsIndex::Exists - Check if the index is available		/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool debTranslationsIndex::Exists() const
-{
-   return FileExists(IndexFile(Language));
-}
-									/*}}}*/
-// TranslationsIndex::Size - Return the size of the index		/*{{{*/
-// ---------------------------------------------------------------------
-/* This is really only used for progress reporting. */
-unsigned long debTranslationsIndex::Size() const
-{
-   unsigned long size = 0;
-
-   /* we need to ignore errors here; if the lists are absent, just return 0 */
-   _error->PushToStack();
-
-   FileFd f(IndexFile(Language), FileFd::ReadOnly, FileFd::Extension);
-   if (!f.Failed())
-      size = f.Size();
-
-   if (_error->PendingError() == true)
-       size = 0;
-   _error->RevertToStack();
-
-   return size;
+   return Exists();
 }
 									/*}}}*/
 // TranslationsIndex::Merge - Load the index file into a cache		/*{{{*/
@@ -525,24 +193,24 @@ unsigned long debTranslationsIndex::Size() const
 bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
 {
    // Check the translation file, if in use
-   string TranslationFile = IndexFile(Language);
+   string const TranslationFile = IndexFileName();
    if (FileExists(TranslationFile))
    {
      FileFd Trans(TranslationFile,FileFd::ReadOnly, FileFd::Extension);
      debTranslationsParser TransParser(&Trans);
      if (_error->PendingError() == true)
        return false;
-     
+
      if (Prog != NULL)
-	Prog->SubProgress(0, Info(TranslationFile.c_str()));
-     if (Gen.SelectFile(TranslationFile,string(),*this) == false)
+	Prog->SubProgress(0, Target.Description);
+     if (Gen.SelectFile(TranslationFile, *this, "", Target.Option(IndexTarget::COMPONENT), pkgCache::Flag::NotSource | pkgCache::Flag::NoPackages) == false)
        return _error->Error("Problem with SelectFile %s",TranslationFile.c_str());
 
      // Store the IMS information
      pkgCache::PkgFileIterator TransFile = Gen.GetCurFile();
      TransFile->Size = Trans.FileSize();
      TransFile->mtime = Trans.ModificationTime();
-   
+
      if (Gen.MergeList(TransParser) == false)
        return _error->Error("Problem with MergeList %s",TranslationFile.c_str());
    }
@@ -555,8 +223,8 @@ bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
 /* */
 pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) const
 {
-   string FileName = IndexFile(Language);
-   
+   string FileName = IndexFileName();
+
    pkgCache::PkgFileIterator File = Cache.FileBegin();
    for (; File.end() == false; ++File)
    {
@@ -579,10 +247,11 @@ pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) con
 	 return pkgCache::PkgFileIterator(Cache);
       }
       return File;
-   }   
+   }
    return File;
 }
 									/*}}}*/
+
 // StatusIndex::debStatusIndex - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -615,18 +284,17 @@ bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
 
    if (Prog != NULL)
       Prog->SubProgress(0,File);
-   if (Gen.SelectFile(File,string(),*this,pkgCache::Flag::NotSource) == false)
+   if (Gen.SelectFile(File, *this, "", "now", pkgCache::Flag::NotSource) == false)
       return _error->Error("Problem with SelectFile %s",File.c_str());
 
    // Store the IMS information
    pkgCache::PkgFileIterator CFile = Gen.GetCurFile();
+   pkgCacheGenerator::Dynamic<pkgCache::PkgFileIterator> DynFile(CFile);
    CFile->Size = Pkg.FileSize();
    CFile->mtime = Pkg.ModificationTime();
-   map_stringitem_t const storage = Gen.StoreString(pkgCacheGenerator::MIXED, "now");
-   CFile->Archive = storage;
-   
+
    if (Gen.MergeList(Parser) == false)
-      return _error->Error("Problem with MergeList %s",File.c_str());   
+      return _error->Error("Problem with MergeList %s",File.c_str());
    return true;
 }
 									/*}}}*/
@@ -671,8 +339,7 @@ APT_CONST bool debStatusIndex::Exists() const
 }
 									/*}}}*/
 
-// debDebPkgFile - Single .deb file                           		/*{{{*/
-// ---------------------------------------------------------------------
+// debDebPkgFile - Single .deb file					/*{{{*/
 debDebPkgFileIndex::debDebPkgFileIndex(std::string DebFile)
    : pkgIndexFile(true), DebFile(DebFile)
 {
@@ -688,64 +355,67 @@ bool debDebPkgFileIndex::Exists() const
 {
    return FileExists(DebFile);
 }
-bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const
+bool debDebPkgFileIndex::GetContent(std::ostream &content, std::string const &debfile)
 {
-   if(Prog)
-      Prog->SubProgress(0, "Reading deb file");
-
-   // get the control data out of the deb file vid dpkg -I
-   // ... can I haz libdpkg?
-   Configuration::Item const *Opts = _config->Tree("DPkg::Options");
-   std::string dpkg = _config->Find("Dir::Bin::dpkg","dpkg");
+   // get the control data out of the deb file via dpkg-deb -I
+   std::string dpkg = _config->Find("Dir::Bin::dpkg","dpkg-deb");
    std::vector<const char *> Args;
    Args.push_back(dpkg.c_str());
-   if (Opts != 0)
-   {
-      Opts = Opts->Child;
-      for (; Opts != 0; Opts = Opts->Next)
-      {
-	 if (Opts->Value.empty() == true)
-	    continue;
-	 Args.push_back(Opts->Value.c_str());
-      }
-   }
    Args.push_back("-I");
-   Args.push_back(DebFile.c_str());
+   Args.push_back(debfile.c_str());
    Args.push_back("control");
    Args.push_back(NULL);
    FileFd PipeFd;
    pid_t Child;
    if(Popen((const char**)&Args[0], PipeFd, Child, FileFd::ReadOnly) == false)
       return _error->Error("Popen failed");
-   // FIXME: static buffer
-   char buf[8*1024];
-   unsigned long long n = 0;
-   if(PipeFd.Read(buf, sizeof(buf)-1, &n) == false)
-      return _error->Errno("read", "Failed to read dpkg pipe");
+
+   char buffer[1024];
+   do {
+      unsigned long long actual = 0;
+      if (PipeFd.Read(buffer, sizeof(buffer)-1, &actual) == false)
+	 return _error->Errno("read", "Failed to read dpkg pipe");
+      if (actual == 0)
+	 break;
+      buffer[actual] = '\0';
+      content << buffer;
+   } while(true);
    ExecWait(Child, "Popen");
 
-   // now write the control data to a tempfile
+   content << "Filename: " << debfile << "\n";
+   struct stat Buf;
+   if (stat(debfile.c_str(), &Buf) != 0)
+      return false;
+   content << "Size: " << Buf.st_size << "\n";
+
+   return true;
+}
+bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const
+{
+   if(Prog)
+      Prog->SubProgress(0, "Reading deb file");
+
+   // write the control data to a tempfile
    SPtr<FileFd> DebControl = GetTempFile("deb-file-" + flNotDir(DebFile));
    if(DebControl == NULL)
       return false;
-   DebControl->Write(buf, n);
-   // append size of the file
-   FileFd Fd(DebFile, FileFd::ReadOnly);
-   string Size;
-   strprintf(Size, "Size: %llu\n", Fd.Size());
-   DebControl->Write(Size.c_str(), Size.size());
-   // and rewind for the listparser
+   std::ostringstream content;
+   if (GetContent(content, DebFile) == false)
+      return false;
+   std::string const contentstr = content.str();
+   DebControl->Write(contentstr.c_str(), contentstr.length());
+   // rewind for the listparser
    DebControl->Seek(0);
 
    // and give it to the list parser
    debDebFileParser Parser(DebControl, DebFile);
-   if(Gen.SelectFile(DebFile, "local", *this) == false)
+   if(Gen.SelectFile(DebFile, *this, "", "now", pkgCache::Flag::LocalSource) == false)
       return _error->Error("Problem with SelectFile %s", DebFile.c_str());
 
    pkgCache::PkgFileIterator File = Gen.GetCurFile();
    File->Size = DebControl->Size();
    File->mtime = DebControl->ModificationTime();
-   
+
    if (Gen.MergeList(Parser) == false)
       return _error->Error("Problem with MergeLister for %s", DebFile.c_str());
 
@@ -802,13 +472,13 @@ pkgSrcRecords::Parser *debDscFileIndex::CreateSrcParser() const
 }
 									/*}}}*/
 // Index File types for Debian						/*{{{*/
-class debIFTypeSrc : public pkgIndexFile::Type
+class APT_HIDDEN debIFTypeSrc : public pkgIndexFile::Type
 {
    public:
    
    debIFTypeSrc() {Label = "Debian Source Index";};
 };
-class debIFTypePkg : public pkgIndexFile::Type
+class APT_HIDDEN debIFTypePkg : public pkgIndexFile::Type
 {
    public:
    
@@ -818,12 +488,12 @@ class debIFTypePkg : public pkgIndexFile::Type
    };
    debIFTypePkg() {Label = "Debian Package Index";};
 };
-class debIFTypeTrans : public debIFTypePkg
+class APT_HIDDEN debIFTypeTrans : public debIFTypePkg
 {
    public:
    debIFTypeTrans() {Label = "Debian Translation Index";};
 };
-class debIFTypeStatus : public pkgIndexFile::Type
+class APT_HIDDEN debIFTypeStatus : public pkgIndexFile::Type
 {
    public:
    
@@ -833,16 +503,16 @@ class debIFTypeStatus : public pkgIndexFile::Type
    };
    debIFTypeStatus() {Label = "Debian dpkg status file";};
 };
-class debIFTypeDebPkgFile : public pkgIndexFile::Type
+class APT_HIDDEN debIFTypeDebPkgFile : public pkgIndexFile::Type
 {
    public:
    virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const 
    {
-      return new debDebFileRecordParser(File.FileName(),*File.Cache());
+      return new debDebFileRecordParser(File.FileName());
    };
    debIFTypeDebPkgFile() {Label = "deb Package file";};
 };
-class debIFTypeDscFile : public pkgIndexFile::Type
+class APT_HIDDEN debIFTypeDscFile : public pkgIndexFile::Type
 {
    public:
    virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string DscFile) const
@@ -851,7 +521,7 @@ class debIFTypeDscFile : public pkgIndexFile::Type
    };
    debIFTypeDscFile() {Label = "dsc File Source Index";};
 };
-class debIFTypeDebianSourceDir : public pkgIndexFile::Type
+class APT_HIDDEN debIFTypeDebianSourceDir : public pkgIndexFile::Type
 {
    public:
    virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string SourceDir) const
@@ -861,14 +531,14 @@ class debIFTypeDebianSourceDir : public pkgIndexFile::Type
    debIFTypeDebianSourceDir() {Label = "debian/control File Source Index";};
 };
 
-static debIFTypeSrc _apt_Src;
-static debIFTypePkg _apt_Pkg;
-static debIFTypeTrans _apt_Trans;
-static debIFTypeStatus _apt_Status;
-static debIFTypeDebPkgFile _apt_DebPkgFile;
+APT_HIDDEN debIFTypeSrc _apt_Src;
+APT_HIDDEN debIFTypePkg _apt_Pkg;
+APT_HIDDEN debIFTypeTrans _apt_Trans;
+APT_HIDDEN debIFTypeStatus _apt_Status;
+APT_HIDDEN debIFTypeDebPkgFile _apt_DebPkgFile;
 // file based pseudo indexes
-static debIFTypeDscFile _apt_DscFile;
-static debIFTypeDebianSourceDir _apt_DebianSourceDir;
+APT_HIDDEN debIFTypeDscFile _apt_DscFile;
+APT_HIDDEN debIFTypeDebianSourceDir _apt_DebianSourceDir;
 
 const pkgIndexFile::Type *debSourcesIndex::GetType() const
 {
@@ -906,3 +576,4 @@ debTranslationsIndex::~debTranslationsIndex() {}
 debSourcesIndex::~debSourcesIndex() {}
 
 debDebPkgFileIndex::~debDebPkgFileIndex() {}
+debDscFileIndex::~debDscFileIndex() {}

+ 28 - 75
apt-pkg/deb/debindexfile.h

@@ -1,6 +1,5 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: debindexfile.h,v 1.3.2.1 2003/12/24 23:09:17 mdz Exp $
 /* ######################################################################
 
    Debian Index Files
@@ -28,117 +27,68 @@ class pkgAcquire;
 class pkgCacheGenerator;
 
 
-class debStatusIndex : public pkgIndexFile
+class APT_HIDDEN debStatusIndex : public pkgIndexFile
 {
-   /** \brief dpointer placeholder (for later in case we need it) */
    void *d;
-
    protected:
    std::string File;
 
    public:
 
    virtual const Type *GetType() const APT_CONST;
-   
+
    // Interface for acquire
    virtual std::string Describe(bool /*Short*/) const {return File;};
-   
+
    // Interface for the Cache Generator
    virtual bool Exists() const;
    virtual bool HasPackages() const {return true;};
    virtual unsigned long Size() const;
    virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const;
-   bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog, unsigned long const Flag) const;
    virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
 
    debStatusIndex(std::string File);
    virtual ~debStatusIndex();
 };
-    
-class debPackagesIndex : public pkgIndexFile
+
+class APT_HIDDEN debPackagesIndex : public pkgIndexTargetFile
 {
-   /** \brief dpointer placeholder (for later in case we need it) */
    void *d;
-
-   std::string URI;
-   std::string Dist;
-   std::string Section;
-   std::string Architecture;
-
-   APT_HIDDEN std::string Info(const char *Type) const;
-   APT_HIDDEN std::string IndexFile(const char *Type) const;
-   APT_HIDDEN std::string IndexURI(const char *Type) const;
-
    public:
-   
+
    virtual const Type *GetType() const APT_CONST;
 
    // Stuff for accessing files on remote items
    virtual std::string ArchiveInfo(pkgCache::VerIterator Ver) const;
-   virtual std::string ArchiveURI(std::string File) const {return URI + File;};
-   
-   // Interface for acquire
-   virtual std::string Describe(bool Short) const;   
-   
+
    // Interface for the Cache Generator
-   virtual bool Exists() const;
    virtual bool HasPackages() const {return true;};
-   virtual unsigned long Size() const;
    virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const;
    virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
 
-   debPackagesIndex(std::string const &URI, std::string const &Dist, std::string const &Section,
-			bool const &Trusted, std::string const &Arch = "native");
+   debPackagesIndex(IndexTarget const &Target, bool const Trusted);
    virtual ~debPackagesIndex();
 };
 
-class debTranslationsIndex : public pkgIndexFile
+class APT_HIDDEN debTranslationsIndex : public pkgIndexTargetFile
 {
-   /** \brief dpointer placeholder (for later in case we need it) */
    void *d;
-
-   std::string URI;
-   std::string Dist;
-   std::string Section;
-   const char * const Language;
-   
-   APT_HIDDEN std::string Info(const char *Type) const;
-   APT_HIDDEN std::string IndexFile(const char *Type) const;
-   APT_HIDDEN std::string IndexURI(const char *Type) const;
-
-   APT_HIDDEN std::string TranslationFile() const {return std::string("Translation-").append(Language);};
-
    public:
-   
+
    virtual const Type *GetType() const APT_CONST;
 
-   // Interface for acquire
-   virtual std::string Describe(bool Short) 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(std::string URI,std::string Dist,std::string Section, char const * const Language);
+   debTranslationsIndex(IndexTarget const &Target);
    virtual ~debTranslationsIndex();
 };
 
-class debSourcesIndex : public pkgIndexFile
+class APT_HIDDEN debSourcesIndex : public pkgIndexTargetFile
 {
-   /** \brief dpointer placeholder (for later in case we need it) */
    void *d;
-
-   std::string URI;
-   std::string Dist;
-   std::string Section;
-
-   APT_HIDDEN std::string Info(const char *Type) const;
-   APT_HIDDEN std::string IndexFile(const char *Type) const;
-   APT_HIDDEN std::string IndexURI(const char *Type) const;
-
    public:
 
    virtual const Type *GetType() const APT_CONST;
@@ -146,24 +96,18 @@ class debSourcesIndex : public pkgIndexFile
    // Stuff for accessing files on remote items
    virtual std::string SourceInfo(pkgSrcRecords::Parser const &Record,
 			     pkgSrcRecords::File const &File) const;
-   virtual std::string ArchiveURI(std::string File) const {return URI + File;};
-   
-   // Interface for acquire
-   virtual std::string Describe(bool Short) const;   
 
    // Interface for the record parsers
    virtual pkgSrcRecords::Parser *CreateSrcParser() const;
-   
+
    // Interface for the Cache Generator
-   virtual bool Exists() const;
    virtual bool HasPackages() const {return false;};
-   virtual unsigned long Size() const;
-   
-   debSourcesIndex(std::string URI,std::string Dist,std::string Section,bool Trusted);
+
+   debSourcesIndex(IndexTarget const &Target, bool const Trusted);
    virtual ~debSourcesIndex();
 };
 
-class debDebPkgFileIndex : public pkgIndexFile
+class APT_HIDDEN debDebPkgFileIndex : public pkgIndexFile
 {
  private:
    void *d;
@@ -177,6 +121,14 @@ class debDebPkgFileIndex : public pkgIndexFile
       return DebFile;
    }
 
+   /** get the control (file) content of the deb file
+    *
+    * @param[out] content of the control file
+    * @param debfile is the filename of the .deb-file
+    * @return \b true if successful, otherwise \b false.
+    */
+   static bool GetContent(std::ostream &content, std::string const &debfile);
+
    // Interface for the Cache Generator
    virtual bool Exists() const;
    virtual bool HasPackages() const {
@@ -193,9 +145,10 @@ class debDebPkgFileIndex : public pkgIndexFile
    virtual ~debDebPkgFileIndex();
 };
 
-class debDscFileIndex : public pkgIndexFile
+class APT_HIDDEN debDscFileIndex : public pkgIndexFile
 {
  private:
+   void *d;
    std::string DscFile;
  public:
    virtual const Type *GetType() const APT_CONST;
@@ -208,10 +161,10 @@ class debDscFileIndex : public pkgIndexFile
    };
 
    debDscFileIndex(std::string &DscFile);
-   virtual ~debDscFileIndex() {};
+   virtual ~debDscFileIndex();
 };
 
-class debDebianSourceDirIndex : public debDscFileIndex
+class APT_HIDDEN debDebianSourceDirIndex : public debDscFileIndex
 {
  public:
    virtual const Type *GetType() const APT_CONST;

+ 10 - 39
apt-pkg/deb/deblistparser.cc

@@ -141,6 +141,7 @@ bool debListParser::NewVersion(pkgCache::VerIterator &Ver)
       map_stringitem_t const idx = StoreString(pkgCacheGenerator::SECTION, Start, Stop - Start);
       Ver->Section = idx;
    }
+#if APT_PKG_ABI >= 413
    // Parse the source package name
    pkgCache::GrpIterator const G = Ver.ParentPkg().Group();
    Ver->SourcePkgName = G->Name;
@@ -192,6 +193,7 @@ bool debListParser::NewVersion(pkgCache::VerIterator &Ver)
 	 }
       }
    }
+#endif
 
    Ver->MultiArch = ParseMultiArch(true);
    // Archive Size
@@ -804,7 +806,7 @@ bool debListParser::ParseDepends(pkgCache::VerIterator &Ver,
 	 if (NewDepends(Ver,Package,"none",Version,Op,Type) == false)
 	    return false;
       }
-      else if (MultiArchEnabled == true && found != string::npos &&
+      else if (found != string::npos &&
 	       strcmp(Package.c_str() + found, ":any") != 0)
       {
 	 string Arch = Package.substr(found+1, string::npos);
@@ -851,10 +853,16 @@ bool debListParser::ParseProvides(pkgCache::VerIterator &Ver)
       while (1)
       {
 	 Start = ParseDepends(Start,Stop,Package,Version,Op);
+	 const size_t archfound = Package.rfind(':');
 	 if (Start == 0)
 	    return _error->Error("Problem parsing Provides line");
 	 if (Op != pkgCache::Dep::NoOp && Op != pkgCache::Dep::Equals) {
 	    _error->Warning("Ignoring Provides line with non-equal DepCompareOp for package %s", Package.c_str());
+	 } else if (archfound != string::npos) {
+	    string OtherArch = Package.substr(archfound+1, string::npos);
+	    Package = Package.substr(0, archfound);
+	    if (NewProvides(Ver, Package, OtherArch, Version) == false)
+	       return false;
 	 } else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign) {
 	    if (NewProvidesAllArch(Ver, Package, Version) == false)
 	       return false;
@@ -943,43 +951,6 @@ bool debListParser::Step()
    return false;
 }
 									/*}}}*/
-// ListParser::LoadReleaseInfo - Load the release information		/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,
-				    FileFd &File, string component)
-{
-   // apt-secure does no longer download individual (per-section) Release
-   // file. to provide Component pinning we use the section name now
-   map_stringitem_t const storage = StoreString(pkgCacheGenerator::MIXED, component);
-   FileI->Component = storage;
-
-   pkgTagFile TagFile(&File, File.Size());
-   pkgTagSection Section;
-   if (_error->PendingError() == true || TagFile.Step(Section) == false)
-      return false;
-
-   std::string data;
-   #define APT_INRELEASE(TYPE, TAG, STORE) \
-   data = Section.FindS(TAG); \
-   if (data.empty() == false) \
-   { \
-      map_stringitem_t const storage = StoreString(pkgCacheGenerator::TYPE, data); \
-      STORE = storage; \
-   }
-   APT_INRELEASE(MIXED, "Suite", FileI->Archive)
-   APT_INRELEASE(MIXED, "Component", FileI->Component)
-   APT_INRELEASE(VERSIONNUMBER, "Version", FileI->Version)
-   APT_INRELEASE(MIXED, "Origin", FileI->Origin)
-   APT_INRELEASE(MIXED, "Codename", FileI->Codename)
-   APT_INRELEASE(MIXED, "Label", FileI->Label)
-   #undef APT_INRELEASE
-   Section.FindFlag("NotAutomatic", FileI->Flags, pkgCache::Flag::NotAutomatic);
-   Section.FindFlag("ButAutomaticUpgrades", FileI->Flags, pkgCache::Flag::ButAutomaticUpgrades);
-
-   return !_error->PendingError();
-}
-									/*}}}*/
 // ListParser::GetPrio - Convert the priority from a string		/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -992,7 +963,7 @@ unsigned char debListParser::GetPrio(string Str)
    return Out;
 }
 									/*}}}*/
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+#if APT_PKG_ABI >= 413
 bool debListParser::SameVersion(unsigned short const Hash,		/*{{{*/
       pkgCache::VerIterator const &Ver)
 {

+ 13 - 13
apt-pkg/deb/deblistparser.h

@@ -26,7 +26,7 @@
 
 class FileFd;
 
-class debListParser : public pkgCacheGenerator::ListParser
+class APT_HIDDEN debListParser : public pkgCacheGenerator::ListParser
 {
    public:
 
@@ -59,7 +59,7 @@ class debListParser : public pkgCacheGenerator::ListParser
 
    public:
 
-   static unsigned char GetPrio(std::string Str);
+   APT_PUBLIC static unsigned char GetPrio(std::string Str);
       
    // These all operate against the current section
    virtual std::string Package();
@@ -71,7 +71,7 @@ class debListParser : public pkgCacheGenerator::ListParser
    virtual std::vector<std::string> AvailableDescriptionLanguages();
    virtual MD5SumValue Description_md5();
    virtual unsigned short VersionHash();
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+#if APT_PKG_ABI >= 413
    virtual bool SameVersion(unsigned short const Hash, pkgCache::VerIterator const &Ver);
 #endif
    virtual bool UsePackage(pkgCache::PkgIterator &Pkg,
@@ -80,30 +80,30 @@ class debListParser : public pkgCacheGenerator::ListParser
    virtual map_filesize_t Size() {return Section.size();};
 
    virtual bool Step();
-   
-   bool LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,FileFd &File,
-			std::string section);
 
-   static const char *ParseDepends(const char *Start,const char *Stop,
+   bool LoadReleaseInfo(pkgCache::RlsFileIterator &FileI,FileFd &File,
+			std::string const &section);
+
+   APT_PUBLIC static const char *ParseDepends(const char *Start,const char *Stop,
 	 std::string &Package,std::string &Ver,unsigned int &Op);
-   static const char *ParseDepends(const char *Start,const char *Stop,
+   APT_PUBLIC static const char *ParseDepends(const char *Start,const char *Stop,
 	 std::string &Package,std::string &Ver,unsigned int &Op,
 	 bool const &ParseArchFlags);
-   static const char *ParseDepends(const char *Start,const char *Stop,
+   APT_PUBLIC static const char *ParseDepends(const char *Start,const char *Stop,
 	 std::string &Package,std::string &Ver,unsigned int &Op,
 	 bool const &ParseArchFlags, bool const &StripMultiArch);
-   static const char *ParseDepends(const char *Start,const char *Stop,
+   APT_PUBLIC static const char *ParseDepends(const char *Start,const char *Stop,
 	 std::string &Package,std::string &Ver,unsigned int &Op,
 	 bool const &ParseArchFlags, bool const &StripMultiArch,
 	 bool const &ParseRestrictionsList);
 
-   static const char *ConvertRelation(const char *I,unsigned int &Op);
+   APT_PUBLIC static const char *ConvertRelation(const char *I,unsigned int &Op);
 
    debListParser(FileFd *File, std::string const &Arch = "");
    virtual ~debListParser();
 };
 
-class debDebFileParser : public debListParser
+class APT_HIDDEN debDebFileParser : public debListParser
 {
  private:
    std::string DebFile;
@@ -114,7 +114,7 @@ class debDebFileParser : public debListParser
 			   pkgCache::VerIterator &Ver);
 };
 
-class debTranslationsParser : public debListParser
+class APT_HIDDEN debTranslationsParser : public debListParser
 {
  public:
    // a translation can never be a real package

+ 333 - 269
apt-pkg/deb/debmetaindex.cc

@@ -1,5 +1,6 @@
 #include <config.h>
 
+#include <apt-pkg/error.h>
 #include <apt-pkg/debmetaindex.h>
 #include <apt-pkg/debindexfile.h>
 #include <apt-pkg/strutl.h>
@@ -10,10 +11,12 @@
 #include <apt-pkg/indexrecords.h>
 #include <apt-pkg/sourcelist.h>
 #include <apt-pkg/hashes.h>
-#include <apt-pkg/macros.h>
 #include <apt-pkg/metaindex.h>
+#include <apt-pkg/pkgcachegen.h>
+#include <apt-pkg/tagfile.h>
+#include <apt-pkg/gpgv.h>
+#include <apt-pkg/macros.h>
 
-#include <string.h>
 #include <map>
 #include <string>
 #include <utility>
@@ -21,30 +24,16 @@
 #include <set>
 #include <algorithm>
 
-using namespace std;
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
 
-string debReleaseIndex::Info(const char *Type, string const &Section, string const &Arch) const
-{
-   string Info = ::URI::SiteOnly(URI) + ' ';
-   if (Dist[Dist.size() - 1] == '/')
-   {
-      if (Dist != "/")
-         Info += Dist;
-   }
-   else
-   {
-      Info += Dist + '/' + Section;
-      if (Arch.empty() != true)
-	 Info += " " + Arch;
-   }
-   Info += " ";
-   Info += Type;
-   return Info;
-}
+using namespace std;
 
 string debReleaseIndex::MetaIndexInfo(const char *Type) const
 {
-   string Info = ::URI::SiteOnly(URI) + ' ';
+   string Info = ::URI::ArchiveOnly(URI) + ' ';
    if (Dist[Dist.size() - 1] == '/')
    {
       if (Dist != "/")
@@ -56,6 +45,10 @@ string debReleaseIndex::MetaIndexInfo(const char *Type) const
    Info += Type;
    return Info;
 }
+std::string debReleaseIndex::Describe() const
+{
+   return MetaIndexInfo("Release");
+}
 
 string debReleaseIndex::MetaIndexFile(const char *Type) const
 {
@@ -78,7 +71,6 @@ string debReleaseIndex::MetaIndexURI(const char *Type) const
    return Res;
 }
 
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
 std::string debReleaseIndex::LocalFileName() const
 {
    // see if we have a InRelease file
@@ -92,167 +84,183 @@ std::string debReleaseIndex::LocalFileName() const
 
    return "";
 }
-#endif
 
-string debReleaseIndex::IndexURISuffix(const char *Type, string const &Section, string const &Arch) const
-{
-   string Res ="";
-   if (Dist[Dist.size() - 1] != '/')
-   {
-      if (Arch == "native")
-	 Res += Section + "/binary-" + _config->Find("APT::Architecture") + '/';
-      else
-	 Res += Section + "/binary-" + Arch + '/';
-   }
-   return Res + Type;
+debReleaseIndex::debReleaseIndex(string const &URI, string const &Dist) :
+					metaIndex(URI, Dist, "deb"), Trusted(CHECK_TRUST)
+{}
+
+debReleaseIndex::debReleaseIndex(string const &URI, string const &Dist, bool const Trusted) :
+					metaIndex(URI, Dist, "deb") {
+	SetTrusted(Trusted);
+}
+
+debReleaseIndex::~debReleaseIndex() {
+	for (map<string, vector<debSectionEntry const*> >::const_iterator A = ArchEntries.begin();
+	     A != ArchEntries.end(); ++A)
+		for (vector<const debSectionEntry *>::const_iterator S = A->second.begin();
+		     S != A->second.end(); ++S)
+			delete *S;
 }
-   
 
-string debReleaseIndex::IndexURI(const char *Type, string const &Section, string const &Arch) const
+template<typename CallC>
+void foreachTarget(std::string const URI, std::string const Dist,
+      std::map<std::string, std::vector<debReleaseIndex::debSectionEntry const *> > const &ArchEntries,
+      CallC &Call)
 {
-   if (Dist[Dist.size() - 1] == '/')
+   bool const flatArchive = (Dist[Dist.length() - 1] == '/');
+   std::string baseURI = URI;
+   if (flatArchive)
    {
-      string Res;
       if (Dist != "/")
-         Res = URI + Dist;
-      else 
-         Res = URI;
-      return Res + Type;
+         baseURI += Dist;
    }
    else
-      return URI + "dists/" + Dist + '/' + IndexURISuffix(Type, Section, Arch);
- }
+      baseURI += "dists/" + Dist + "/";
+   std::string const Release = (Dist == "/") ? "" : Dist;
+   std::string const Site = ::URI::ArchiveOnly(URI);
+   std::vector<std::string> lang = APT::Configuration::getLanguages(true);
+   if (lang.empty())
+      lang.push_back("none");
+   map<string, vector<debReleaseIndex::debSectionEntry const*> >::const_iterator const src = ArchEntries.find("source");
+   if (src != ArchEntries.end())
+   {
+      std::vector<std::string> const targets = _config->FindVector("APT::Acquire::Targets::deb-src", "", true);
+      for (std::vector<std::string>::const_iterator T = targets.begin(); T != targets.end(); ++T)
+      {
+#define APT_T_CONFIG(X) _config->Find(std::string("APT::Acquire::Targets::deb-src::") + *T + "::" + (X))
+	 std::string const MetaKey = APT_T_CONFIG(flatArchive ? "flatMetaKey" : "MetaKey");
+	 std::string const ShortDesc = APT_T_CONFIG("ShortDescription");
+	 std::string const LongDesc = APT_T_CONFIG(flatArchive ? "flatDescription" : "Description");
+	 bool const IsOptional = _config->FindB(std::string("APT::Acquire::Targets::deb-src::") + *T + "::Optional", true);
+#undef APT_T_CONFIG
+	 if (MetaKey.empty())
+	    continue;
 
-string debReleaseIndex::SourceIndexURISuffix(const char *Type, const string &Section) const
-{
-   string Res ="";
-   if (Dist[Dist.size() - 1] != '/')
-      Res += Section + "/source/";
-   return Res + Type;
-}
+	 vector<debReleaseIndex::debSectionEntry const*> const SectionEntries = src->second;
+	 for (vector<debReleaseIndex::debSectionEntry const*>::const_iterator I = SectionEntries.begin();
+	       I != SectionEntries.end(); ++I)
+	 {
+	    for (vector<std::string>::const_iterator l = lang.begin(); l != lang.end(); ++l)
+	    {
+	       if (*l == "none" && MetaKey.find("$(LANGUAGE)") != std::string::npos)
+		  continue;
+
+	       std::map<std::string, std::string> Options;
+	       Options.insert(std::make_pair("SITE", Site));
+	       Options.insert(std::make_pair("RELEASE", Release));
+	       if (MetaKey.find("$(COMPONENT)") != std::string::npos)
+		  Options.insert(std::make_pair("COMPONENT", (*I)->Section));
+	       if (MetaKey.find("$(LANGUAGE)") != std::string::npos)
+		  Options.insert(std::make_pair("LANGUAGE", *l));
+	       Options.insert(std::make_pair("ARCHITECTURE", "source"));
+	       Options.insert(std::make_pair("BASE_URI", baseURI));
+	       Options.insert(std::make_pair("REPO_URI", URI));
+	       Options.insert(std::make_pair("TARGET_OF", "deb-src"));
+	       Options.insert(std::make_pair("CREATED_BY", *T));
+	       Call(MetaKey, ShortDesc, LongDesc, IsOptional, Options);
+
+	       if (MetaKey.find("$(LANGUAGE)") == std::string::npos)
+		  break;
+	    }
 
-string debReleaseIndex::SourceIndexURI(const char *Type, const string &Section) const
-{
-   string Res;
-   if (Dist[Dist.size() - 1] == '/')
+	    if (MetaKey.find("$(COMPONENT)") == std::string::npos)
+	       break;
+	 }
+      }
+   }
+
+   std::vector<std::string> const targets = _config->FindVector("APT::Acquire::Targets::deb", "", true);
+   for (std::vector<std::string>::const_iterator T = targets.begin(); T != targets.end(); ++T)
    {
-      if (Dist != "/")
-         Res = URI + Dist;
-      else 
-         Res = URI;
-      return Res + Type;
+#define APT_T_CONFIG(X) _config->Find(std::string("APT::Acquire::Targets::deb::") + *T + "::" + (X))
+      std::string const MetaKey = APT_T_CONFIG(flatArchive ? "flatMetaKey" : "MetaKey");
+      std::string const ShortDesc = APT_T_CONFIG("ShortDescription");
+      std::string const LongDesc = APT_T_CONFIG(flatArchive ? "flatDescription" : "Description");
+      bool const IsOptional = _config->FindB(std::string("APT::Acquire::Targets::deb::") + *T + "::Optional", true);
+#undef APT_T_CONFIG
+      if (MetaKey.empty())
+	 continue;
+
+      for (map<string, vector<debReleaseIndex::debSectionEntry const*> >::const_iterator a = ArchEntries.begin();
+	    a != ArchEntries.end(); ++a)
+      {
+	 if (a->first == "source")
+	    continue;
+
+	 for (vector <const debReleaseIndex::debSectionEntry *>::const_iterator I = a->second.begin();
+	       I != a->second.end(); ++I) {
+
+	    for (vector<std::string>::const_iterator l = lang.begin(); l != lang.end(); ++l)
+	    {
+	       if (*l == "none" && MetaKey.find("$(LANGUAGE)") != std::string::npos)
+		  continue;
+
+	       std::map<std::string, std::string> Options;
+	       Options.insert(std::make_pair("SITE", Site));
+	       Options.insert(std::make_pair("RELEASE", Release));
+	       if (MetaKey.find("$(COMPONENT)") != std::string::npos)
+		  Options.insert(std::make_pair("COMPONENT", (*I)->Section));
+	       if (MetaKey.find("$(LANGUAGE)") != std::string::npos)
+		  Options.insert(std::make_pair("LANGUAGE", *l));
+	       if (MetaKey.find("$(ARCHITECTURE)") != std::string::npos)
+		  Options.insert(std::make_pair("ARCHITECTURE", a->first));
+	       Options.insert(std::make_pair("BASE_URI", baseURI));
+	       Options.insert(std::make_pair("REPO_URI", URI));
+	       Options.insert(std::make_pair("TARGET_OF", "deb"));
+	       Options.insert(std::make_pair("CREATED_BY", *T));
+	       Call(MetaKey, ShortDesc, LongDesc, IsOptional, Options);
+
+	       if (MetaKey.find("$(LANGUAGE)") == std::string::npos)
+		  break;
+	    }
+
+	    if (MetaKey.find("$(COMPONENT)") == std::string::npos)
+	       break;
+	 }
+
+	 if (MetaKey.find("$(ARCHITECTURE)") == std::string::npos)
+	    break;
+      }
    }
-   else
-      return URI + "dists/" + Dist + "/" + SourceIndexURISuffix(Type, Section);
 }
 
-string debReleaseIndex::TranslationIndexURISuffix(const char *Type, const string &Section) const
-{
-   string Res ="";
-   if (Dist[Dist.size() - 1] != '/')
-      Res += Section + "/i18n/Translation-";
-   return Res + Type;
-}
 
-string debReleaseIndex::TranslationIndexURI(const char *Type, const string &Section) const
+struct ComputeIndexTargetsClass
 {
-   string Res;
-   if (Dist[Dist.size() - 1] == '/')
+   vector <IndexTarget> IndexTargets;
+
+   void operator()(std::string MetaKey, std::string ShortDesc, std::string LongDesc,
+	 bool const IsOptional, std::map<std::string, std::string> Options)
    {
-      if (Dist != "/")
-         Res = URI + Dist;
-      else 
-         Res = URI;
-      return Res + Type;
+      for (std::map<std::string, std::string>::const_iterator O = Options.begin(); O != Options.end(); ++O)
+      {
+	 MetaKey = SubstVar(MetaKey, std::string("$(") + O->first + ")", O->second);
+	 ShortDesc = SubstVar(ShortDesc, std::string("$(") + O->first + ")", O->second);
+	 LongDesc = SubstVar(LongDesc, std::string("$(") + O->first + ")", O->second);
+      }
+      IndexTarget Target(
+	    MetaKey,
+	    ShortDesc,
+	    LongDesc,
+	    Options.find("BASE_URI")->second + MetaKey,
+	    IsOptional,
+	    Options
+	    );
+      IndexTargets.push_back(Target);
    }
-   else
-      return URI + "dists/" + Dist + "/" + TranslationIndexURISuffix(Type, Section);
-}
-
-debReleaseIndex::debReleaseIndex(string const &URI, string const &Dist) :
-					metaIndex(URI, Dist, "deb"), Trusted(CHECK_TRUST)
-{}
+};
 
-debReleaseIndex::debReleaseIndex(string const &URI, string const &Dist, bool const Trusted) :
-					metaIndex(URI, Dist, "deb") {
-	SetTrusted(Trusted);
+std::vector<IndexTarget> debReleaseIndex::GetIndexTargets() const
+{
+   ComputeIndexTargetsClass comp;
+   foreachTarget(URI, Dist, ArchEntries, comp);
+   return comp.IndexTargets;
 }
 
-debReleaseIndex::~debReleaseIndex() {
-	for (map<string, vector<debSectionEntry const*> >::const_iterator A = ArchEntries.begin();
-	     A != ArchEntries.end(); ++A)
-		for (vector<const debSectionEntry *>::const_iterator S = A->second.begin();
-		     S != A->second.end(); ++S)
-			delete *S;
-}
 
-vector <IndexTarget *>* debReleaseIndex::ComputeIndexTargets() const {
-	vector <IndexTarget *>* IndexTargets = new vector <IndexTarget *>;
-
-	map<string, vector<debSectionEntry const*> >::const_iterator const src = ArchEntries.find("source");
-	if (src != ArchEntries.end()) {
-		vector<debSectionEntry const*> const SectionEntries = src->second;
-		for (vector<debSectionEntry const*>::const_iterator I = SectionEntries.begin();
-		     I != SectionEntries.end(); ++I) {
-			IndexTarget * Target = new IndexTarget();
-			Target->ShortDesc = "Sources";
-			Target->MetaKey = SourceIndexURISuffix(Target->ShortDesc.c_str(), (*I)->Section);
-			Target->URI = SourceIndexURI(Target->ShortDesc.c_str(), (*I)->Section);
-			Target->Description = Info (Target->ShortDesc.c_str(), (*I)->Section);
-			IndexTargets->push_back (Target);
-		}
-	}
-
-	// Only source release
-	if (IndexTargets->empty() == false && ArchEntries.size() == 1)
-		return IndexTargets;
-
-	std::set<std::string> sections;
-	for (map<string, vector<debSectionEntry const*> >::const_iterator a = ArchEntries.begin();
-	     a != ArchEntries.end(); ++a) {
-		if (a->first == "source")
-			continue;
-		for (vector <const debSectionEntry *>::const_iterator I = a->second.begin();
-		     I != a->second.end(); ++I) {
-			IndexTarget * Target = new IndexTarget();
-			Target->ShortDesc = "Packages";
-			Target->MetaKey = IndexURISuffix(Target->ShortDesc.c_str(), (*I)->Section, a->first);
-			Target->URI = IndexURI(Target->ShortDesc.c_str(), (*I)->Section, a->first);
-			Target->Description = Info (Target->ShortDesc.c_str(), (*I)->Section, a->first);
-			IndexTargets->push_back (Target);
-			sections.insert((*I)->Section);
-		}
-	}
-
-	std::vector<std::string> lang = APT::Configuration::getLanguages(true);
-	std::vector<std::string>::iterator lend = std::remove(lang.begin(), lang.end(), "none");
-	if (lend != lang.end())
-		lang.erase(lend);
-
-	if (lang.empty() == true)
-		return IndexTargets;
-
-	// get the Translation-* files, later we will skip download of non-existent if we have an index
-	for (std::set<std::string>::const_iterator s = sections.begin();
-	     s != sections.end(); ++s) {
-		for (std::vector<std::string>::const_iterator l = lang.begin();
-		     l != lang.end(); ++l) {
-			IndexTarget * Target = new OptionalIndexTarget();
-			Target->ShortDesc = "Translation-" + *l;
-			Target->MetaKey = TranslationIndexURISuffix(l->c_str(), *s);
-			Target->URI = TranslationIndexURI(l->c_str(), *s);
-			Target->Description = Info (Target->ShortDesc.c_str(), *s);
-			IndexTargets->push_back(Target);
-		}
-	}
-
-	return IndexTargets;
-}
 									/*}}}*/
 bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const
 {
-   bool const tryInRelease = _config->FindB("Acquire::TryInRelease", true);
-
    indexRecords * const iR = new indexRecords(Dist);
    if (Trusted == ALWAYS_TRUSTED)
       iR->SetTrusted(true);
@@ -260,37 +268,17 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const
       iR->SetTrusted(false);
 
    // special case for --print-uris
-   if (GetAll) {
-      vector <IndexTarget *> *targets = ComputeIndexTargets();
-      for (vector <IndexTarget*>::const_iterator Target = targets->begin(); Target != targets->end(); ++Target) {
-	 new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
-			 (*Target)->ShortDesc, HashStringList());
-      }
-      delete targets;
-
-      // this is normally created in pkgAcqMetaSig, but if we run
-      // in --print-uris mode, we add it here
-      if (tryInRelease == false)
-	 new pkgAcqMetaIndex(Owner, NULL,
-                             MetaIndexURI("Release"),
-                             MetaIndexInfo("Release"), "Release",
-                             MetaIndexURI("Release.gpg"), MetaIndexInfo("Release.gpg"), "Release.gpg",
-                             ComputeIndexTargets(),
-                             iR);
+   std::vector<IndexTarget> const targets = GetIndexTargets();
+#define APT_TARGET(X) IndexTarget("", X, MetaIndexInfo(X), MetaIndexURI(X), false, std::map<std::string,std::string>())
+   pkgAcqMetaBase * const TransactionManager = new pkgAcqMetaClearSig(Owner,
+	 APT_TARGET("InRelease"), APT_TARGET("Release"), APT_TARGET("Release.gpg"),
+	 targets, iR);
+#undef APT_TARGET
+   if (GetAll)
+   {
+      for (std::vector<IndexTarget>::const_iterator Target = targets.begin(); Target != targets.end(); ++Target)
+	 new pkgAcqIndex(Owner, TransactionManager, *Target);
    }
-   if (tryInRelease == true)
-      new pkgAcqMetaClearSig(Owner, 
-            MetaIndexURI("InRelease"), MetaIndexInfo("InRelease"), "InRelease",
-	    MetaIndexURI("Release"), MetaIndexInfo("Release"), "Release",
-	    MetaIndexURI("Release.gpg"), MetaIndexInfo("Release.gpg"), "Release.gpg",
-	    ComputeIndexTargets(),
-	    iR);
-   else
-      new pkgAcqMetaIndex(Owner, NULL,
-          MetaIndexURI("Release"), MetaIndexInfo("Release"), "Release",
-          MetaIndexURI("Release.gpg"), MetaIndexInfo("Release.gpg"), "Release.gpg",
-          ComputeIndexTargets(),
-          iR);
 
    return true;
 }
@@ -327,45 +315,25 @@ bool debReleaseIndex::IsTrusted() const
    return FileExists(VerifiedSigFile);
 }
 
-vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles() {
-	if (Indexes != NULL)
-		return Indexes;
-
-	Indexes = new vector <pkgIndexFile*>;
-	map<string, vector<debSectionEntry const*> >::const_iterator const src = ArchEntries.find("source");
-	if (src != ArchEntries.end()) {
-		vector<debSectionEntry const*> const SectionEntries = src->second;
-		for (vector<debSectionEntry const*>::const_iterator I = SectionEntries.begin();
-		     I != SectionEntries.end(); ++I)
-			Indexes->push_back(new debSourcesIndex (URI, Dist, (*I)->Section, IsTrusted()));
-	}
-
-	// Only source release
-	if (Indexes->empty() == false && ArchEntries.size() == 1)
-		return Indexes;
-
-	std::vector<std::string> const lang = APT::Configuration::getLanguages(true);
-	map<string, set<string> > sections;
-	for (map<string, vector<debSectionEntry const*> >::const_iterator a = ArchEntries.begin();
-	     a != ArchEntries.end(); ++a) {
-		if (a->first == "source")
-			continue;
-		for (vector<debSectionEntry const*>::const_iterator I = a->second.begin();
-		     I != a->second.end(); ++I) {
-			Indexes->push_back(new debPackagesIndex (URI, Dist, (*I)->Section, IsTrusted(), a->first));
-			sections[(*I)->Section].insert(lang.begin(), lang.end());
-		}
-	}
-
-	for (map<string, set<string> >::const_iterator s = sections.begin();
-	     s != sections.end(); ++s)
-		for (set<string>::const_iterator l = s->second.begin();
-		     l != s->second.end(); ++l) {
-			if (*l == "none") continue;
-			Indexes->push_back(new debTranslationsIndex(URI,Dist,s->first,(*l).c_str()));
-		}
-
-	return Indexes;
+std::vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles()
+{
+   if (Indexes != NULL)
+      return Indexes;
+
+   Indexes = new std::vector<pkgIndexFile*>();
+   std::vector<IndexTarget> const Targets = GetIndexTargets();
+   bool const istrusted = IsTrusted();
+   for (std::vector<IndexTarget>::const_iterator T = Targets.begin(); T != Targets.end(); ++T)
+   {
+      std::string const TargetName = T->Option(IndexTarget::CREATED_BY);
+      if (TargetName == "Packages")
+	 Indexes->push_back(new debPackagesIndex(*T, istrusted));
+      else if (TargetName == "Sources")
+	 Indexes->push_back(new debSourcesIndex(*T, istrusted));
+      else if (TargetName == "Translations")
+	 Indexes->push_back(new debTranslationsIndex(*T));
+   }
+   return Indexes;
 }
 
 void debReleaseIndex::PushSectionEntry(vector<string> const &Archs, const debSectionEntry *Entry) {
@@ -379,22 +347,121 @@ void debReleaseIndex::PushSectionEntry(string const &Arch, const debSectionEntry
 	ArchEntries[Arch].push_back(Entry);
 }
 
-void debReleaseIndex::PushSectionEntry(const debSectionEntry *Entry) {
-	if (Entry->IsSrc == true)
-		PushSectionEntry("source", Entry);
-	else {
-		for (map<string, vector<const debSectionEntry *> >::iterator a = ArchEntries.begin();
-		     a != ArchEntries.end(); ++a) {
-			a->second.push_back(Entry);
-		}
-	}
-}
-
 debReleaseIndex::debSectionEntry::debSectionEntry (string const &Section,
 		bool const &IsSrc): Section(Section), IsSrc(IsSrc)
 {}
 
-class debSLTypeDebian : public pkgSourceList::Type
+static bool ReleaseFileName(debReleaseIndex const * const That, std::string &ReleaseFile)
+{
+   ReleaseFile = That->MetaIndexFile("InRelease");
+   bool releaseExists = false;
+   if (FileExists(ReleaseFile) == true)
+      releaseExists = true;
+   else
+   {
+      ReleaseFile = That->MetaIndexFile("Release");
+      if (FileExists(ReleaseFile))
+	 releaseExists = true;
+   }
+   return releaseExists;
+}
+
+bool debReleaseIndex::Merge(pkgCacheGenerator &Gen,OpProgress * /*Prog*/) const/*{{{*/
+{
+   std::string ReleaseFile;
+   bool const releaseExists = ReleaseFileName(this, ReleaseFile);
+
+   ::URI Tmp(URI);
+   if (Gen.SelectReleaseFile(ReleaseFile, Tmp.Host) == false)
+      return _error->Error("Problem with SelectReleaseFile %s", ReleaseFile.c_str());
+
+   if (releaseExists == false)
+      return true;
+
+   FileFd Rel;
+   // Beware: The 'Release' file might be clearsigned in case the
+   // signature for an 'InRelease' file couldn't be checked
+   if (OpenMaybeClearSignedFile(ReleaseFile, Rel) == false)
+      return false;
+   if (_error->PendingError() == true)
+      return false;
+
+   // Store the IMS information
+   pkgCache::RlsFileIterator File = Gen.GetCurRlsFile();
+   pkgCacheGenerator::Dynamic<pkgCache::RlsFileIterator> DynFile(File);
+   // Rel can't be used as this is potentially a temporary file
+   struct stat Buf;
+   if (stat(ReleaseFile.c_str(), &Buf) != 0)
+      return _error->Errno("fstat", "Unable to stat file %s", ReleaseFile.c_str());
+   File->Size = Buf.st_size;
+   File->mtime = Buf.st_mtime;
+
+   pkgTagFile TagFile(&Rel, Rel.Size());
+   pkgTagSection Section;
+   if (_error->PendingError() == true || TagFile.Step(Section) == false)
+      return false;
+
+   std::string data;
+   #define APT_INRELEASE(TYPE, TAG, STORE) \
+   data = Section.FindS(TAG); \
+   if (data.empty() == false) \
+   { \
+      map_stringitem_t const storage = Gen.StoreString(pkgCacheGenerator::TYPE, data); \
+      STORE = storage; \
+   }
+   APT_INRELEASE(MIXED, "Suite", File->Archive)
+   APT_INRELEASE(VERSIONNUMBER, "Version", File->Version)
+   APT_INRELEASE(MIXED, "Origin", File->Origin)
+   APT_INRELEASE(MIXED, "Codename", File->Codename)
+   APT_INRELEASE(MIXED, "Label", File->Label)
+   #undef APT_INRELEASE
+   Section.FindFlag("NotAutomatic", File->Flags, pkgCache::Flag::NotAutomatic);
+   Section.FindFlag("ButAutomaticUpgrades", File->Flags, pkgCache::Flag::ButAutomaticUpgrades);
+
+   return !_error->PendingError();
+}
+									/*}}}*/
+// ReleaseIndex::FindInCache - Find this index				/*{{{*/
+pkgCache::RlsFileIterator debReleaseIndex::FindInCache(pkgCache &Cache, bool const ModifyCheck) const
+{
+   std::string ReleaseFile;
+   bool const releaseExists = ReleaseFileName(this, ReleaseFile);
+
+   pkgCache::RlsFileIterator File = Cache.RlsFileBegin();
+   for (; File.end() == false; ++File)
+   {
+       if (File->FileName == 0 || ReleaseFile != File.FileName())
+	 continue;
+
+       // empty means the file does not exist by "design"
+       if (ModifyCheck == false || (releaseExists == false && File->Size == 0))
+	  return File;
+
+      struct stat St;
+      if (stat(File.FileName(),&St) != 0)
+      {
+         if (_config->FindB("Debug::pkgCacheGen", false))
+	    std::clog << "ReleaseIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
+	 return pkgCache::RlsFileIterator(Cache);
+      }
+      if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
+      {
+         if (_config->FindB("Debug::pkgCacheGen", false))
+	    std::clog << "ReleaseIndex::FindInCache - size (" << St.st_size << " <> " << File->Size
+			<< ") or mtime (" << St.st_mtime << " <> " << File->mtime
+			<< ") doesn't match for " << File.FileName() << std::endl;
+	 return pkgCache::RlsFileIterator(Cache);
+      }
+      return File;
+   }
+
+   return File;
+}
+									/*}}}*/
+
+debDebFileMetaIndex::~debDebFileMetaIndex() {}
+
+class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type
 {
    protected:
 
@@ -404,9 +471,12 @@ class debSLTypeDebian : public pkgSourceList::Type
    {
       // parse arch=, arch+= and arch-= settings
       map<string, string>::const_iterator arch = Options.find("arch");
-      vector<string> Archs =
-		(arch != Options.end()) ? VectorizeString(arch->second, ',') :
-				APT::Configuration::getArchitectures();
+      vector<string> Archs;
+      if (arch != Options.end())
+	 Archs = VectorizeString(arch->second, ',');
+      else
+	 Archs = APT::Configuration::getArchitectures();
+
       if ((arch = Options.find("arch+")) != Options.end())
       {
 	 std::vector<std::string> const plusArch = VectorizeString(arch->second, ',');
@@ -427,6 +497,7 @@ class debSLTypeDebian : public pkgSourceList::Type
 
       map<string, string>::const_iterator const trusted = Options.find("trusted");
 
+      debReleaseIndex *Deb = NULL;
       for (vector<metaIndex *>::const_iterator I = List.begin();
 	   I != List.end(); ++I)
       {
@@ -434,34 +505,23 @@ class debSLTypeDebian : public pkgSourceList::Type
 	 if (strcmp((*I)->GetType(), "deb") != 0)
 	    continue;
 
-	 debReleaseIndex *Deb = (debReleaseIndex *) (*I);
-	 if (trusted != Options.end())
-	    Deb->SetTrusted(StringToBool(trusted->second, false));
-
 	 /* This check insures that there will be only one Release file
 	    queued for all the Packages files and Sources files it
 	    corresponds to. */
-	 if (Deb->GetURI() == URI && Deb->GetDist() == Dist)
+	 if ((*I)->GetURI() == URI && (*I)->GetDist() == Dist)
 	 {
-	    if (IsSrc == true)
-	       Deb->PushSectionEntry("source", new debReleaseIndex::debSectionEntry(Section, IsSrc));
-	    else
-	    {
-	       if (Dist[Dist.size() - 1] == '/')
-		  Deb->PushSectionEntry("any", new debReleaseIndex::debSectionEntry(Section, IsSrc));
-	       else
-		  Deb->PushSectionEntry(Archs, new debReleaseIndex::debSectionEntry(Section, IsSrc));
-	    }
-	    return true;
+	    Deb = dynamic_cast<debReleaseIndex*>(*I);
+	    if (Deb != NULL)
+	       break;
 	 }
       }
 
       // No currently created Release file indexes this entry, so we create a new one.
-      debReleaseIndex *Deb;
-      if (trusted != Options.end())
-	 Deb = new debReleaseIndex(URI, Dist, StringToBool(trusted->second, false));
-      else
+      if (Deb == NULL)
+      {
 	 Deb = new debReleaseIndex(URI, Dist);
+	 List.push_back(Deb);
+      }
 
       if (IsSrc == true)
 	 Deb->PushSectionEntry ("source", new debReleaseIndex::debSectionEntry(Section, IsSrc));
@@ -472,7 +532,10 @@ class debSLTypeDebian : public pkgSourceList::Type
 	 else
 	    Deb->PushSectionEntry (Archs, new debReleaseIndex::debSectionEntry(Section, IsSrc));
       }
-      List.push_back(Deb);
+
+      if (trusted != Options.end())
+	 Deb->SetTrusted(StringToBool(trusted->second, false));
+
       return true;
    }
 };
@@ -486,7 +549,7 @@ debDebFileMetaIndex::debDebFileMetaIndex(std::string const &DebFile)
 }
 
 
-class debSLTypeDeb : public debSLTypeDebian
+class APT_HIDDEN debSLTypeDeb : public debSLTypeDebian
 {
    public:
 
@@ -504,7 +567,7 @@ class debSLTypeDeb : public debSLTypeDebian
    }   
 };
 
-class debSLTypeDebSrc : public debSLTypeDebian
+class APT_HIDDEN debSLTypeDebSrc : public debSLTypeDebian
 {
    public:
 
@@ -522,7 +585,7 @@ class debSLTypeDebSrc : public debSLTypeDebian
    }   
 };
 
-class debSLTypeDebFile : public pkgSourceList::Type
+class APT_HIDDEN debSLTypeDebFile : public pkgSourceList::Type
 {
    public:
 
@@ -541,6 +604,7 @@ class debSLTypeDebFile : public pkgSourceList::Type
       Label = "Debian Deb File";
    }   
 };
-debSLTypeDeb _apt_DebType;
-debSLTypeDebSrc _apt_DebSrcType;
-debSLTypeDebFile _apt_DebFileType;
+
+APT_HIDDEN debSLTypeDeb _apt_DebType;
+APT_HIDDEN debSLTypeDebSrc _apt_DebSrcType;
+APT_HIDDEN debSLTypeDebFile _apt_DebFileType;

+ 17 - 14
apt-pkg/deb/debmetaindex.h

@@ -20,8 +20,10 @@ class pkgAcquire;
 class pkgIndexFile;
 class debDebPkgFileIndex;
 class IndexTarget;
+class pkgCacheGenerator;
+class OpProgress;
 
-class debReleaseIndex : public metaIndex {
+class APT_HIDDEN debReleaseIndex : public metaIndex {
    public:
 
    class debSectionEntry
@@ -46,23 +48,21 @@ class debReleaseIndex : public metaIndex {
 
    virtual std::string ArchiveURI(std::string const &File) const {return URI + File;};
    virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const;
-   std::vector <IndexTarget *>* ComputeIndexTargets() const;
-   std::string Info(const char *Type, std::string const &Section, std::string const &Arch="") const;
+   virtual std::vector<IndexTarget> GetIndexTargets() const;
+
+   virtual std::string Describe() const;
+   virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache, bool const ModifyCheck) const;
+   virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const;
 
    std::string MetaIndexInfo(const char *Type) const;
    std::string MetaIndexFile(const char *Types) const;
    std::string MetaIndexURI(const char *Type) const;
 
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
-   virtual std::string LocalFileName() const;
+#if APT_PKG_ABI >= 413
+   virtual
 #endif
+   std::string LocalFileName() const;
 
-   std::string IndexURI(const char *Type, std::string const &Section, std::string const &Arch="native") const;
-   std::string IndexURISuffix(const char *Type, std::string const &Section, std::string const &Arch="native") const;
-   std::string SourceIndexURI(const char *Type, const std::string &Section) const;
-   std::string SourceIndexURISuffix(const char *Type, const std::string &Section) const;
-   std::string TranslationIndexURI(const char *Type, const std::string &Section) const;
-   std::string TranslationIndexURISuffix(const char *Type, const std::string &Section) const;
    virtual std::vector <pkgIndexFile *> *GetIndexFiles();
 
    void SetTrusted(bool const Trusted);
@@ -70,12 +70,12 @@ class debReleaseIndex : public metaIndex {
 
    void PushSectionEntry(std::vector<std::string> const &Archs, const debSectionEntry *Entry);
    void PushSectionEntry(std::string const &Arch, const debSectionEntry *Entry);
-   void PushSectionEntry(const debSectionEntry *Entry);
 };
 
-class debDebFileMetaIndex : public metaIndex
+class APT_HIDDEN debDebFileMetaIndex : public metaIndex
 {
  private:
+    void *d;
    std::string DebFile;
    debDebPkgFileIndex *DebIndex;
  public:
@@ -85,6 +85,9 @@ class debDebFileMetaIndex : public metaIndex
    virtual bool GetIndexes(pkgAcquire* /*Owner*/, const bool& /*GetAll=false*/) const {
       return true;
    }
+   virtual std::vector<IndexTarget> GetIndexTargets() const {
+      return std::vector<IndexTarget>();
+   }
    virtual std::vector<pkgIndexFile *> *GetIndexFiles() {
       return Indexes;
    }
@@ -92,7 +95,7 @@ class debDebFileMetaIndex : public metaIndex
       return true;
    }
    debDebFileMetaIndex(std::string const &DebFile);
-   virtual ~debDebFileMetaIndex() {};
+   virtual ~debDebFileMetaIndex();
 
 };
 

+ 60 - 55
apt-pkg/deb/debrecords.cc

@@ -11,35 +11,35 @@
 #include <config.h>
 
 #include <apt-pkg/debrecords.h>
+#include <apt-pkg/debindexfile.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/aptconfiguration.h>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/cacheiterators.h>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/tagfile.h>
+#include <apt-pkg/error.h>
 
 #include <string.h>
 #include <algorithm>
+#include <sstream>
 #include <string>
 #include <vector>
 #include <langinfo.h>
+
+#include <apti18n.h>
 									/*}}}*/
 
 using std::string;
 
 // RecordParser::debRecordParser - Constructor				/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-debRecordParser::debRecordParser(string FileName,pkgCache &Cache) : 
-                  File(FileName,FileFd::ReadOnly, FileFd::Extension),
-                  Tags(&File, std::max(Cache.Head().MaxVerFileSize, 
-				       Cache.Head().MaxDescFileSize) + 200)
+debRecordParser::debRecordParser(string FileName,pkgCache &Cache) :
+   debRecordParserBase(), File(FileName, FileFd::ReadOnly, FileFd::Extension),
+   Tags(&File, std::max(Cache.Head().MaxVerFileSize, Cache.Head().MaxDescFileSize) + 200)
 {
 }
 									/*}}}*/
 // RecordParser::Jump - Jump to a specific record			/*{{{*/
-// ---------------------------------------------------------------------
-/* */
 bool debRecordParser::Jump(pkgCache::VerFileIterator const &Ver)
 {
    return Tags.Jump(Section,Ver->Offset);
@@ -49,32 +49,29 @@ bool debRecordParser::Jump(pkgCache::DescFileIterator const &Desc)
    return Tags.Jump(Section,Desc->Offset);
 }
 									/*}}}*/
-// RecordParser::FileName - Return the archive filename on the site	/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string debRecordParser::FileName()
+debRecordParser::~debRecordParser() {}
+
+debRecordParserBase::debRecordParserBase() : Parser() {}
+// RecordParserBase::FileName - Return the archive filename on the site	/*{{{*/
+string debRecordParserBase::FileName()
 {
    return Section.FindS("Filename");
 }
 									/*}}}*/
-// RecordParser::Name - Return the package name				/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string debRecordParser::Name()
+// RecordParserBase::Name - Return the package name			/*{{{*/
+string debRecordParserBase::Name()
 {
    return Section.FindS("Package");
 }
 									/*}}}*/
-// RecordParser::Homepage - Return the package homepage		       	/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string debRecordParser::Homepage()
+// RecordParserBase::Homepage - Return the package homepage		/*{{{*/
+string debRecordParserBase::Homepage()
 {
    return Section.FindS("Homepage");
 }
 									/*}}}*/
-// RecordParser::Hashes - return the available archive hashes		/*{{{*/
-HashStringList debRecordParser::Hashes() const
+// RecordParserBase::Hashes - return the available archive hashes	/*{{{*/
+HashStringList debRecordParserBase::Hashes() const
 {
    HashStringList hashes;
    for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type)
@@ -86,27 +83,20 @@ HashStringList debRecordParser::Hashes() const
    return hashes;
 }
 									/*}}}*/
-// RecordParser::Maintainer - Return the maintainer email		/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string debRecordParser::Maintainer()
+// RecordParserBase::Maintainer - Return the maintainer email		/*{{{*/
+string debRecordParserBase::Maintainer()
 {
    return Section.FindS("Maintainer");
 }
 									/*}}}*/
-// RecordParser::RecordField - Return the value of an arbitrary field       /*{{*/
-// ---------------------------------------------------------------------
-/* */
-string debRecordParser::RecordField(const char *fieldName)
+// RecordParserBase::RecordField - Return the value of an arbitrary field	/*{{*/
+string debRecordParserBase::RecordField(const char *fieldName)
 {
    return Section.FindS(fieldName);
 }
-
-                                                                        /*}}}*/
-// RecordParser::ShortDesc - Return a 1 line description		/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string debRecordParser::ShortDesc(std::string const &lang)
+									/*}}}*/
+// RecordParserBase::ShortDesc - Return a 1 line description		/*{{{*/
+string debRecordParserBase::ShortDesc(std::string const &lang)
 {
    string const Res = LongDesc(lang);
    if (Res.empty() == true)
@@ -117,10 +107,8 @@ string debRecordParser::ShortDesc(std::string const &lang)
    return string(Res,0,Pos);
 }
 									/*}}}*/
-// RecordParser::LongDesc - Return a longer description			/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string debRecordParser::LongDesc(std::string const &lang)
+// RecordParserBase::LongDesc - Return a longer description		/*{{{*/
+string debRecordParserBase::LongDesc(std::string const &lang)
 {
    string orig;
    if (lang.empty() == true)
@@ -162,12 +150,9 @@ string debRecordParser::LongDesc(std::string const &lang)
 }
 									/*}}}*/
 
-static const char *SourceVerSeparators = " ()";
-
-// RecordParser::SourcePkg - Return the source package name if any	/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string debRecordParser::SourcePkg()
+static const char * const SourceVerSeparators = " ()";
+// RecordParserBase::SourcePkg - Return the source package name if any	/*{{{*/
+string debRecordParserBase::SourcePkg()
 {
    string Res = Section.FindS("Source");
    string::size_type Pos = Res.find_first_of(SourceVerSeparators);
@@ -176,10 +161,8 @@ string debRecordParser::SourcePkg()
    return string(Res,0,Pos);
 }
 									/*}}}*/
-// RecordParser::SourceVer - Return the source version number if present	/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string debRecordParser::SourceVer()
+// RecordParserBase::SourceVer - Return the source version number if present	/*{{{*/
+string debRecordParserBase::SourceVer()
 {
    string Pkg = Section.FindS("Source");
    string::size_type Pos = Pkg.find_first_of(SourceVerSeparators);
@@ -199,13 +182,35 @@ string debRecordParser::SourceVer()
      return string(Pkg, VerStart, VerEnd - VerStart);
 }
 									/*}}}*/
-// RecordParser::GetRec - Return the whole record			/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-void debRecordParser::GetRec(const char *&Start,const char *&Stop)
+// RecordParserBase::GetRec - Return the whole record			/*{{{*/
+void debRecordParserBase::GetRec(const char *&Start,const char *&Stop)
 {
    Section.GetSection(Start,Stop);
 }
 									/*}}}*/
+debRecordParserBase::~debRecordParserBase() {}
 
-debRecordParser::~debRecordParser() {}
+bool debDebFileRecordParser::LoadContent()
+{
+   // load content only once
+   if (controlContent.empty() == false)
+      return true;
+
+   std::ostringstream content;
+   if (debDebPkgFileIndex::GetContent(content, debFileName) == false)
+      return false;
+   // add two newlines to make sure the scanner finds the section,
+   // which is usually done by pkgTagFile automatically if needed.
+   content << "\n\n";
+
+   controlContent = content.str();
+   if (Section.Scan(controlContent.c_str(), controlContent.length()) == false)
+      return _error->Error(_("Unable to parse package file %s (%d)"), debFileName.c_str(), 3);
+   return true;
+}
+bool debDebFileRecordParser::Jump(pkgCache::VerFileIterator const &) { return LoadContent(); }
+bool debDebFileRecordParser::Jump(pkgCache::DescFileIterator const &) { return LoadContent(); }
+std::string debDebFileRecordParser::FileName() { return debFileName; }
+
+debDebFileRecordParser::debDebFileRecordParser(std::string FileName) : debRecordParserBase(), debFileName(FileName) {}
+debDebFileRecordParser::~debDebFileRecordParser() {}

+ 33 - 17
apt-pkg/deb/debrecords.h

@@ -25,21 +25,13 @@
 #include <apt-pkg/indexfile.h>
 #endif
 
-class debRecordParser : public pkgRecords::Parser
+class APT_HIDDEN debRecordParserBase : public pkgRecords::Parser
 {
-   /** \brief dpointer placeholder (for later in case we need it) */
    void *d;
-   
  protected:
-   FileFd File;
-   pkgTagFile Tags;
    pkgTagSection Section;
-   
-   virtual bool Jump(pkgCache::VerFileIterator const &Ver);
-   virtual bool Jump(pkgCache::DescFileIterator const &Desc);
-   
- public:
 
+ public:
    // These refer to the archive file for the Version
    virtual std::string FileName();
    virtual std::string SourcePkg();
@@ -58,20 +50,44 @@ class debRecordParser : public pkgRecords::Parser
    virtual std::string RecordField(const char *fieldName);
 
    virtual void GetRec(const char *&Start,const char *&Stop);
-   
+
+   debRecordParserBase();
+   virtual ~debRecordParserBase();
+};
+
+class APT_HIDDEN debRecordParser : public debRecordParserBase
+{
+   void *d;
+ protected:
+   FileFd File;
+   pkgTagFile Tags;
+
+   virtual bool Jump(pkgCache::VerFileIterator const &Ver);
+   virtual bool Jump(pkgCache::DescFileIterator const &Desc);
+
+ public:
    debRecordParser(std::string FileName,pkgCache &Cache);
    virtual ~debRecordParser();
 };
 
 // custom record parser that reads deb files directly
-class debDebFileRecordParser : public debRecordParser
+class APT_HIDDEN debDebFileRecordParser : public debRecordParserBase
 {
+   void *d;
+   std::string debFileName;
+   std::string controlContent;
+
+   APT_HIDDEN bool LoadContent();
+ protected:
+   // single file files, so no jumping whatsoever
+   bool Jump(pkgCache::VerFileIterator const &);
+   bool Jump(pkgCache::DescFileIterator const &);
+
  public:
-   virtual std::string FileName() {
-      return File.Name();
-   }
-   debDebFileRecordParser(std::string FileName,pkgCache &Cache)
-      : debRecordParser(FileName, Cache) {};
+   virtual std::string FileName();
+
+   debDebFileRecordParser(std::string FileName);
+   virtual ~debDebFileRecordParser();
 };
 
 #endif

+ 36 - 22
apt-pkg/deb/debsrcrecords.cc

@@ -32,6 +32,10 @@
 using std::max;
 using std::string;
 
+debSrcRecordParser::debSrcRecordParser(std::string const &File,pkgIndexFile const *Index)
+   : Parser(Index), Fd(File,FileFd::ReadOnly, FileFd::Extension), Tags(&Fd,102400),
+   iOffset(0), Buffer(NULL) {}
+
 // SrcRecordParser::Binaries - Return the binaries field		/*{{{*/
 // ---------------------------------------------------------------------
 /* This member parses the binaries field into a pair of class arrays and
@@ -121,9 +125,32 @@ bool debSrcRecordParser::BuildDepends(std::vector<pkgSrcRecords::Parser::BuildDe
 // ---------------------------------------------------------------------
 /* This parses the list of files and returns it, each file is required to have
    a complete source package */
-bool debSrcRecordParser::Files(std::vector<pkgSrcRecords::File> &List)
+bool debSrcRecordParser::Files(std::vector<pkgSrcRecords::File> &F)
+{
+   std::vector<pkgSrcRecords::File2> F2;
+   if (Files2(F2) == false)
+      return false;
+   for (std::vector<pkgSrcRecords::File2>::const_iterator f2 = F2.begin(); f2 != F2.end(); ++f2)
+   {
+      pkgSrcRecords::File2 f;
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+      f.MD5Hash = f2->MD5Hash;
+      f.Size = f2->Size;
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
+      f.Path = f2->Path;
+      f.Type = f2->Type;
+      F.push_back(f);
+   }
+   return true;
+}
+bool debSrcRecordParser::Files2(std::vector<pkgSrcRecords::File2> &List)
 {
-   List.erase(List.begin(),List.end());
+   List.clear();
 
    // Stash the / terminated directory prefix
    string Base = Sect.FindS("Directory");
@@ -162,7 +189,7 @@ bool debSrcRecordParser::Files(std::vector<pkgSrcRecords::File> &List)
 	    path = Base + path;
 
 	 // look if we have a record for this file already
-	 std::vector<pkgSrcRecords::File>::iterator file = List.begin();
+	 std::vector<pkgSrcRecords::File2>::iterator file = List.begin();
 	 for (; file != List.end(); ++file)
 	    if (file->Path == path)
 	       break;
@@ -170,16 +197,8 @@ bool debSrcRecordParser::Files(std::vector<pkgSrcRecords::File> &List)
 	 // we have it already, store the new hash and be done
 	 if (file != List.end())
 	 {
-#if __GNUC__ >= 4
-	// set for compatibility only, so warn users not us
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
 	    if (checksumField == "Files")
-	       file->MD5Hash = hash;
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+	       APT_IGNORE_DEPRECATED(file->MD5Hash = hash;)
 	    // an error here indicates that we have two different hashes for the same file
 	    if (file->Hashes.push_back(hashString) == false)
 	       return _error->Error("Error parsing checksum in %s of source package %s", checksumField.c_str(), Package().c_str());
@@ -187,21 +206,16 @@ bool debSrcRecordParser::Files(std::vector<pkgSrcRecords::File> &List)
 	 }
 
 	 // we haven't seen this file yet
-	 pkgSrcRecords::File F;
+	 pkgSrcRecords::File2 F;
 	 F.Path = path;
-	 F.Size = strtoull(size.c_str(), NULL, 10);
+	 F.FileSize = strtoull(size.c_str(), NULL, 10);
 	 F.Hashes.push_back(hashString);
 
-#if __GNUC__ >= 4
-	// set for compatibility only, so warn users not us
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+	 APT_IGNORE_DEPRECATED_PUSH
+	 F.Size = F.FileSize;
 	 if (checksumField == "Files")
 	    F.MD5Hash = hash;
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+	 APT_IGNORE_DEPRECATED_POP
 
 	 // Try to guess what sort of file it is we are getting.
 	 string::size_type Pos = F.Path.length()-1;

+ 4 - 5
apt-pkg/deb/debsrcrecords.h

@@ -21,7 +21,7 @@
 
 class pkgIndexFile;
 
-class debSrcRecordParser : public pkgSrcRecords::Parser
+class APT_HIDDEN debSrcRecordParser : public pkgSrcRecords::Parser
 {
    /** \brief dpointer placeholder (for later in case we need it) */
    void *d;
@@ -54,14 +54,13 @@ class debSrcRecordParser : public pkgSrcRecords::Parser
       return std::string(Start,Stop);
    };
    virtual bool Files(std::vector<pkgSrcRecords::File> &F);
+   bool Files2(std::vector<pkgSrcRecords::File2> &F);
 
-   debSrcRecordParser(std::string const &File,pkgIndexFile const *Index) 
-      : Parser(Index), Fd(File,FileFd::ReadOnly, FileFd::Extension), Tags(&Fd,102400),
-        iOffset(0), Buffer(NULL) {}
+   debSrcRecordParser(std::string const &File,pkgIndexFile const *Index);
    virtual ~debSrcRecordParser();
 };
 
-class debDscRecordParser : public debSrcRecordParser
+class APT_HIDDEN debDscRecordParser : public debSrcRecordParser
 {
  public:
    debDscRecordParser(std::string const &DscFile, pkgIndexFile const *Index);

+ 1 - 1
apt-pkg/deb/debsystem.cc

@@ -38,7 +38,7 @@ using std::string;
 
 debSystem debSys;
 
-class debSystemPrivate {
+class APT_HIDDEN debSystemPrivate {
 public:
    debSystemPrivate() : LockFD(-1), LockCount(0), StatusFile(0)
    {

+ 0 - 1
apt-pkg/deb/debversion.h

@@ -1,6 +1,5 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: debversion.h,v 1.3 2001/05/03 05:25:04 jgg Exp $
 /* ######################################################################
 
    Debian Version - Versioning system for Debian

+ 103 - 67
apt-pkg/deb/dpkgpm.cc

@@ -72,7 +72,9 @@ class pkgDPkgPMPrivate
 public:
    pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0),
 			term_out(NULL), history_out(NULL),
-                        progress(NULL), master(-1), slave(NULL)
+			progress(NULL), tt_is_valid(false), master(-1),
+			slave(NULL), protect_slave_from_dying(-1),
+			direct_stdin(false)
    {
       dpkgbuf[0] = '\0';
    }
@@ -90,13 +92,16 @@ public:
 
    // pty stuff
    struct termios tt;
+   bool tt_is_valid;
    int master;
    char * slave;
+   int protect_slave_from_dying;
 
    // signals
    sigset_t sigmask;
    sigset_t original_sigmask;
 
+   bool direct_stdin;
 };
 
 namespace
@@ -198,18 +203,12 @@ pkgCache::VerIterator FindNowVersion(const pkgCache::PkgIterator &Pkg)
 {
    pkgCache::VerIterator Ver;
    for (Ver = Pkg.VersionList(); Ver.end() == false; ++Ver)
-   {
-      pkgCache::VerFileIterator Vf = Ver.FileList();
-      pkgCache::PkgFileIterator F = Vf.File();
-      for (F = Vf.File(); F.end() == false; ++F)
-      {
-         if (F && F.Archive())
-         {
-            if (strcmp(F.Archive(), "now")) 
-               return Ver;
-         }
-      }
-   }
+      for (pkgCache::VerFileIterator Vf = Ver.FileList(); Vf.end() == false; ++Vf)
+	 for (pkgCache::PkgFileIterator F = Vf.File(); F.end() == false; ++F)
+	 {
+	    if (F.Archive() != 0 && strcmp(F.Archive(), "now") == 0)
+	       return Ver;
+	 }
    return Ver;
 }
 									/*}}}*/
@@ -1044,6 +1043,12 @@ void pkgDPkgPM::BuildPackagesProgressMap()
 	 PackagesTotal++;
       }
    }
+   /* one extra: We don't want the progress bar to reach 100%, especially not
+      if we call dpkg --configure --pending and process a bunch of triggers
+      while showing 100%. Also, spindown takes a while, so never reaching 100%
+      is way more correct than reaching 100% while still doing stuff even if
+      doing it this way is slightly bending the rules */
+   ++PackagesTotal;
 }
                                                                         /*}}}*/
 bool pkgDPkgPM::Go(int StatusFd)
@@ -1068,48 +1073,44 @@ void pkgDPkgPM::StartPtyMagic()
       return;
    }
 
+   if (isatty(STDIN_FILENO) == 0)
+      d->direct_stdin = true;
+
    _error->PushToStack();
-   // if tcgetattr for both stdin/stdout returns 0 (no error)
-   // we do the pty magic
-   if (tcgetattr(STDOUT_FILENO, &d->tt) == 0 &&
-	 tcgetattr(STDIN_FILENO, &d->tt) == 0)
+
+   d->master = posix_openpt(O_RDWR | O_NOCTTY);
+   if (d->master == -1)
+      _error->Errno("posix_openpt", _("Can not write log (%s)"), _("Is /dev/pts mounted?"));
+   else if (unlockpt(d->master) == -1)
+      _error->Errno("unlockpt", "Unlocking the slave of master fd %d failed!", d->master);
+   else
    {
-      d->master = posix_openpt(O_RDWR | O_NOCTTY);
-      if (d->master == -1)
-	 _error->Errno("posix_openpt", _("Can not write log (%s)"), _("Is /dev/pts mounted?"));
-      else if (unlockpt(d->master) == -1)
-      {
-	 _error->Errno("unlockpt", "Unlocking the slave of master fd %d failed!", d->master);
-	 close(d->master);
-	 d->master = -1;
-      }
+      char const * const slave_name = ptsname(d->master);
+      if (slave_name == NULL)
+	 _error->Errno("ptsname", "Getting name for slave of master fd %d failed!", d->master);
       else
       {
-	 char const * const slave_name = ptsname(d->master);
-	 if (slave_name == NULL)
-	 {
-	    _error->Errno("unlockpt", "Getting name for slave of master fd %d failed!", d->master);
-	    close(d->master);
-	    d->master = -1;
-	 }
-	 else
+	 d->slave = strdup(slave_name);
+	 if (d->slave == NULL)
+	    _error->Errno("strdup", "Copying name %s for slave of master fd %d failed!", slave_name, d->master);
+	 else if (grantpt(d->master) == -1)
+	    _error->Errno("grantpt", "Granting access to slave %s based on master fd %d failed!", slave_name, d->master);
+	 else if (tcgetattr(STDIN_FILENO, &d->tt) == 0)
 	 {
-	    d->slave = strdup(slave_name);
-	    if (d->slave == NULL)
+	    d->tt_is_valid = true;
+	    struct termios raw_tt;
+	    // copy window size of stdout if its a 'good' terminal
+	    if (tcgetattr(STDOUT_FILENO, &raw_tt) == 0)
 	    {
-	       _error->Errno("strdup", "Copying name %s for slave of master fd %d failed!", slave_name, d->master);
-	       close(d->master);
-	       d->master = -1;
+	       struct winsize win;
+	       if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) < 0)
+		  _error->Errno("ioctl", "Getting TIOCGWINSZ from stdout failed!");
+	       if (ioctl(d->master, TIOCSWINSZ, &win) < 0)
+		  _error->Errno("ioctl", "Setting TIOCSWINSZ for master fd %d failed!", d->master);
 	    }
-	    struct winsize win;
-	    if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) < 0)
-	       _error->Errno("ioctl", "Getting TIOCGWINSZ from stdout failed!");
-	    if (ioctl(d->master, TIOCSWINSZ, &win) < 0)
-	       _error->Errno("ioctl", "Setting TIOCSWINSZ for master fd %d failed!", d->master);
 	    if (tcsetattr(d->master, TCSANOW, &d->tt) == -1)
 	       _error->Errno("tcsetattr", "Setting in Start via TCSANOW for master fd %d failed!", d->master);
 
-	    struct termios raw_tt;
 	    raw_tt = d->tt;
 	    cfmakeraw(&raw_tt);
 	    raw_tt.c_lflag &= ~ECHO;
@@ -1121,18 +1122,22 @@ void pkgDPkgPM::StartPtyMagic()
 	    sigaddset(&d->sigmask, SIGTTOU);
 	    sigprocmask(SIG_BLOCK,&d->sigmask, &d->original_sigmask);
 	    if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw_tt) == -1)
-	       _error->Errno("tcsetattr", "Setting in Start via TCSAFLUSH for stdout failed!");
+	       _error->Errno("tcsetattr", "Setting in Start via TCSAFLUSH for stdin failed!");
 	    sigprocmask(SIG_SETMASK, &d->original_sigmask, NULL);
+
+	 }
+	 if (d->slave != NULL)
+	 {
+	    /* on linux, closing (and later reopening) all references to the slave
+	       makes the slave a death end, so we open it here to have one open all
+	       the time. We could use this fd in SetupSlavePtyMagic() for linux, but
+	       on kfreebsd we get an incorrect ("step like") output then while it has
+	       no problem with closing all references… so to avoid platform specific
+	       code here we combine both and be happy once more */
+	    d->protect_slave_from_dying = open(d->slave, O_RDWR | O_CLOEXEC | O_NOCTTY);
 	 }
       }
    }
-   else
-   {
-      // complain only if stdout is either a terminal (but still failed) or is an invalid
-      // descriptor otherwise we would complain about redirection to e.g. /dev/null as well.
-      if (isatty(STDOUT_FILENO) == 1 || errno == EBADF)
-	 _error->Errno("tcgetattr", _("Can not write log (%s)"), _("Is stdout a terminal?"));
-   }
 
    if (_error->PendingError() == true)
    {
@@ -1141,44 +1146,60 @@ void pkgDPkgPM::StartPtyMagic()
 	 close(d->master);
 	 d->master = -1;
       }
+      if (d->slave != NULL)
+      {
+	 free(d->slave);
+	 d->slave = NULL;
+      }
       _error->DumpErrors(std::cerr);
    }
    _error->RevertToStack();
 }
 void pkgDPkgPM::SetupSlavePtyMagic()
 {
-   if(d->master == -1)
+   if(d->master == -1 || d->slave == NULL)
       return;
 
    if (close(d->master) == -1)
       _error->FatalE("close", "Closing master %d in child failed!", d->master);
+   d->master = -1;
    if (setsid() == -1)
       _error->FatalE("setsid", "Starting a new session for child failed!");
 
-   int const slaveFd = open(d->slave, O_RDWR);
+   int const slaveFd = open(d->slave, O_RDWR | O_NOCTTY);
    if (slaveFd == -1)
       _error->FatalE("open", _("Can not write log (%s)"), _("Is /dev/pts mounted?"));
-
-   if (ioctl(slaveFd, TIOCSCTTY, 0) < 0)
+   else if (ioctl(slaveFd, TIOCSCTTY, 0) < 0)
       _error->FatalE("ioctl", "Setting TIOCSCTTY for slave fd %d failed!", slaveFd);
    else
    {
-      for (unsigned short i = 0; i < 3; ++i)
+      unsigned short i = 0;
+      if (d->direct_stdin == true)
+	 ++i;
+      for (; i < 3; ++i)
 	 if (dup2(slaveFd, i) == -1)
 	    _error->FatalE("dup2", "Dupping %d to %d in child failed!", slaveFd, i);
 
-      if (tcsetattr(0, TCSANOW, &d->tt) < 0)
+      if (d->tt_is_valid == true && tcsetattr(STDIN_FILENO, TCSANOW, &d->tt) < 0)
 	 _error->FatalE("tcsetattr", "Setting in Setup via TCSANOW for slave fd %d failed!", slaveFd);
    }
+
+   if (slaveFd != -1)
+      close(slaveFd);
 }
 void pkgDPkgPM::StopPtyMagic()
 {
    if (d->slave != NULL)
       free(d->slave);
    d->slave = NULL;
+   if (d->protect_slave_from_dying != -1)
+   {
+      close(d->protect_slave_from_dying);
+      d->protect_slave_from_dying = -1;
+   }
    if(d->master >= 0) 
    {
-      if (tcsetattr(0, TCSAFLUSH, &d->tt) == -1)
+      if (d->tt_is_valid == true && tcsetattr(STDIN_FILENO, TCSAFLUSH, &d->tt) == -1)
 	 _error->FatalE("tcsetattr", "Setting in Stop via TCSAFLUSH for stdin failed!");
       close(d->master);
       d->master = -1;
@@ -1261,9 +1282,8 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
 
    // 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)
+   if (_config->FindB("DPkg::ConfigurePending", true) == true)
       List.push_back(Item(Item::ConfigurePending, PkgIterator()));
 
    // for the progress
@@ -1572,8 +1592,8 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
 
 	 // wait for input or output here
 	 FD_ZERO(&rfds);
-	 if (d->master >= 0 && !d->stdin_is_dev_null)
-	    FD_SET(0, &rfds); 
+	 if (d->master >= 0 && d->direct_stdin == false && d->stdin_is_dev_null == false)
+	    FD_SET(STDIN_FILENO, &rfds);
 	 FD_SET(_dpkgin, &rfds);
 	 if(d->master >= 0)
 	    FD_SET(d->master, &rfds);
@@ -1684,7 +1704,7 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg)
    if (apportPkg.end() == true || apportPkg->CurrentVer == 0)
       return;
 
-   string pkgname, reportfile, srcpkgname, pkgver, arch;
+   string pkgname, reportfile, pkgver, arch;
    string::size_type pos;
    FILE *report;
 
@@ -1823,7 +1843,16 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg)
    time_t now = time(NULL);
    fprintf(report, "Date: %s" , ctime(&now));
    fprintf(report, "Package: %s %s\n", pkgname.c_str(), pkgver.c_str());
+#if APT_PKG_ABI >= 413
    fprintf(report, "SourcePackage: %s\n", Ver.SourcePkgName());
+#else
+   pkgRecords Recs(Cache);
+   pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
+   std::string srcpkgname = Parse.SourcePkg();
+   if(srcpkgname.empty())
+      srcpkgname = pkgname;
+   fprintf(report, "SourcePackage: %s\n", srcpkgname.c_str());
+#endif
    fprintf(report, "ErrorMessage:\n %s\n", errormsg);
 
    // ensure that the log is flushed
@@ -1863,8 +1892,15 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg)
       }
    }
 
-   // log the ordering 
-   const char *ops_str[] = {"Install", "Configure","Remove","Purge"};
+   // log the ordering, see dpkgpm.h and the "Ops" enum there
+   const char *ops_str[] = {
+      "Install",
+      "Configure",
+      "Remove",
+      "Purge",
+      "ConfigurePending",
+      "TriggersPending",
+   };
    fprintf(report, "AptOrdering:\n");
    for (vector<Item>::iterator I = List.begin(); I != List.end(); ++I)
       if ((*I).Pkg != NULL)

+ 37 - 40
apt-pkg/depcache.cc

@@ -33,7 +33,6 @@
 #include <vector>
 #include <algorithm>
 #include <iostream>
-#include <sstream>
 #include <set>
 
 #include <sys/stat.h>
@@ -237,9 +236,11 @@ bool pkgDepCache::writeStateFile(OpProgress * /*prog*/, bool InstalledOnly)	/*{{
 
    FileFd StateFile;
    string const state = _config->FindFile("Dir::State::extended_states");
+   if (CreateAPTDirectoryIfNeeded(_config->FindDir("Dir::State"), flNotFile(state)) == false)
+      return false;
 
    // if it does not exist, create a empty one
-   if(!RealFileExists(state)) 
+   if(!RealFileExists(state))
    {
       StateFile.Open(state, FileFd::WriteAtomic);
       StateFile.Close();
@@ -250,17 +251,14 @@ bool pkgDepCache::writeStateFile(OpProgress * /*prog*/, bool InstalledOnly)	/*{{
       return _error->Error(_("Failed to open StateFile %s"),
 			   state.c_str());
 
-   FILE *OutFile;
-   string const outfile = state + ".tmp";
-   if((OutFile = fopen(outfile.c_str(),"w")) == NULL)
-      return _error->Error(_("Failed to write temporary StateFile %s"),
-			   outfile.c_str());
+   FileFd OutFile(state, FileFd::ReadWrite | FileFd::Atomic);
+   if (OutFile.IsOpen() == false || OutFile.Failed() == true)
+      return _error->Error(_("Failed to write temporary StateFile %s"), state.c_str());
 
    // first merge with the existing sections
    pkgTagFile tagfile(&StateFile);
    pkgTagSection section;
    std::set<string> pkgs_seen;
-   const char *nullreorderlist[] = {0};
    while(tagfile.Step(section)) {
 	 string const pkgname = section.FindS("Package");
 	 string pkgarch = section.FindS("Architecture");
@@ -269,7 +267,7 @@ bool pkgDepCache::writeStateFile(OpProgress * /*prog*/, bool InstalledOnly)	/*{{
 	 // Silently ignore unknown packages and packages with no actual
 	 // version.
 	 pkgCache::PkgIterator pkg = Cache->FindPkg(pkgname, pkgarch);
-	 if(pkg.end() || pkg.VersionList().end()) 
+	 if(pkg.end() || pkg.VersionList().end())
 	    continue;
 	 StateCache const &P = PkgState[pkg->ID];
 	 bool newAuto = (P.Flags & Flag::Auto);
@@ -290,21 +288,17 @@ bool pkgDepCache::writeStateFile(OpProgress * /*prog*/, bool InstalledOnly)	/*{{
 	 if(_config->FindB("Debug::pkgAutoRemove",false))
 	    std::clog << "Update existing AutoInstall info: " 
 		      << pkg.FullName() << std::endl;
-	 TFRewriteData rewrite[3];
-	 rewrite[0].Tag = "Architecture";
-	 rewrite[0].Rewrite = pkg.Arch();
-	 rewrite[0].NewTag = 0;
-	 rewrite[1].Tag = "Auto-Installed";
-	 rewrite[1].Rewrite = newAuto ? "1" : "0";
-	 rewrite[1].NewTag = 0;
-	 rewrite[2].Tag = 0;
-	 TFRewrite(OutFile, section, nullreorderlist, rewrite);
-	 fprintf(OutFile,"\n");
+
+	 std::vector<pkgTagSection::Tag> rewrite;
+	 rewrite.push_back(pkgTagSection::Tag::Rewrite("Architecture", pkg.Arch()));
+	 rewrite.push_back(pkgTagSection::Tag::Rewrite("Auto-Installed", newAuto ? "1" : "0"));
+	 section.Write(OutFile, NULL, rewrite);
+	 if (OutFile.Write("\n", 1) == false)
+	    return false;
 	 pkgs_seen.insert(pkg.FullName());
    }
-   
+
    // then write the ones we have not seen yet
-   std::ostringstream ostr;
    for(pkgCache::PkgIterator pkg=Cache->PkgBegin(); !pkg.end(); ++pkg) {
       StateCache const &P = PkgState[pkg->ID];
       if(P.Flags & Flag::Auto) {
@@ -323,19 +317,17 @@ bool pkgDepCache::writeStateFile(OpProgress * /*prog*/, bool InstalledOnly)	/*{{
 	    continue;
 	 if(debug_autoremove)
 	    std::clog << "Writing new AutoInstall: " << pkg.FullName() << std::endl;
-	 ostr.str(string(""));
-	 ostr << "Package: " << pkg.Name()
-	      << "\nArchitecture: " << pkgarch
-	      << "\nAuto-Installed: 1\n\n";
-	 fprintf(OutFile,"%s",ostr.str().c_str());
+	 std::string stanza = "Package: ";
+	 stanza.append(pkg.Name())
+	      .append("\nArchitecture: ").append(pkgarch)
+	      .append("\nAuto-Installed: 1\n\n");
+	 if (OutFile.Write(stanza.c_str(), stanza.length()) == false)
+	    return false;
       }
    }
-   fclose(OutFile);
-
-   // move the outfile over the real file and set permissions
-   rename(outfile.c_str(), state.c_str());
+   if (OutFile.Close() == false)
+      return false;
    chmod(state.c_str(), 0644);
-
    return true;
 }
 									/*}}}*/
@@ -1313,14 +1305,18 @@ bool pkgDepCache::IsInstallOkMultiArchSameVersionSynced(PkgIterator const &Pkg,
    GrpIterator const Grp = Pkg.Group();
    for (PkgIterator P = Grp.PackageList(); P.end() == false; P = Grp.NextPkg(P))
    {
-      // not installed or version synced: fine by definition
+      // not installed or self-check: fine by definition
+      if (P->CurrentVer == 0 || P == Pkg)
+	 continue;
+
+      // not having a candidate or being in sync
       // (simple string-compare as stuff like '1' == '0:1-0' can't happen here)
-      if (P->CurrentVer == 0 || strcmp(Pkg.CandVersion(), P.CandVersion()) == 0)
+      VerIterator CV = PkgState[P->ID].CandidateVerIter(*this);
+      if (CV.end() == true || strcmp(Pkg.CandVersion(), CV.VerStr()) == 0)
 	 continue;
+
       // packages losing M-A:same can be out-of-sync
-      VerIterator CV = PkgState[P->ID].CandidateVerIter(*this);
-      if (unlikely(CV.end() == true) ||
-	    (CV->MultiArch & pkgCache::Version::Same) != pkgCache::Version::Same)
+      if ((CV->MultiArch & pkgCache::Version::Same) != pkgCache::Version::Same)
 	 continue;
 
       // not downloadable means the package is obsolete, so allow out-of-sync
@@ -1330,7 +1326,8 @@ bool pkgDepCache::IsInstallOkMultiArchSameVersionSynced(PkgIterator const &Pkg,
       PkgState[Pkg->ID].iFlags |= AutoKept;
       if (unlikely(DebugMarker == true))
 	 std::clog << OutputInDepth(Depth) << "Ignore MarkInstall of " << Pkg
-	    << " as its M-A:same siblings are not version-synced" << std::endl;
+	    << " as it is not in sync with its M-A:same sibling " << P
+	    << " (" << Pkg.CandVersion() << " != " << CV.VerStr() << ")" << std::endl;
       return false;
    }
 
@@ -1688,13 +1685,13 @@ pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator const &Pk
       
       for (VerFileIterator J = I.FileList(); J.end() == false; ++J)
       {
-	 if ((J.File()->Flags & Flag::NotSource) != 0)
+	 if (J.File().Flagged(Flag::NotSource))
 	    continue;
 
 	 /* Stash the highest version of a not-automatic source, we use it
 	    if there is nothing better */
-	 if ((J.File()->Flags & Flag::NotAutomatic) != 0 ||
-	     (J.File()->Flags & Flag::ButAutomaticUpgrades) != 0)
+	 if (J.File().Flagged(Flag::NotAutomatic) ||
+	     J.File().Flagged(Flag::ButAutomaticUpgrades))
 	 {
 	    if (Last.end() == true)
 	       Last = I;

+ 6 - 4
apt-pkg/depcache.h

@@ -1,6 +1,5 @@
 // -*- mode: c++; mode: fold -*-
 // Description								/*{{{*/
-// $Id: depcache.h,v 1.14 2001/02/20 07:03:17 jgg Exp $
 /* ######################################################################
 
    DepCache - Dependency Extension data for the cache
@@ -109,7 +108,7 @@ class pkgDepCache : protected pkgCache::Namespace
     *
     *  \return \b false if an error occurred.
     */
-   APT_HIDDEN bool MarkRequired(InRootSetFunc &rootFunc);
+   bool MarkRequired(InRootSetFunc &rootFunc);
 
    /** \brief Set the StateCache::Garbage flag on all packages that
     *  should be removed.
@@ -120,7 +119,7 @@ class pkgDepCache : protected pkgCache::Namespace
     *
     *  \return \b false if an error occurred.
     */
-   APT_HIDDEN bool Sweep();
+   bool Sweep();
 
    public:
    
@@ -164,6 +163,7 @@ class pkgDepCache : protected pkgCache::Namespace
     */
    class ActionGroup
    {
+       void *d;
        pkgDepCache &cache;
 
        bool released;
@@ -192,7 +192,7 @@ class pkgDepCache : protected pkgCache::Namespace
 	*  If this is the last action group, the automatic cache
 	*  cleanup operations will be undertaken.
 	*/
-       ~ActionGroup();
+       virtual ~ActionGroup();
    };
 
    /** \brief Returns \b true for packages matching a regular
@@ -503,6 +503,8 @@ class pkgDepCache : protected pkgCache::Namespace
 	 bool const rPurge, unsigned long const Depth, bool const FromUser);
 
    private:
+   void *d;
+
    APT_HIDDEN bool IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg,
 			unsigned long const Depth, bool const FromUser);
 };

+ 70 - 62
apt-pkg/edsp.cc

@@ -39,64 +39,26 @@
 using std::string;
 
 // we could use pkgCache::DepType and ::Priority, but these would be localized strings…
-const char * const EDSP::PrioMap[] = {0, "important", "required", "standard",
+const char * const PrioMap[] = {0, "important", "required", "standard",
 				      "optional", "extra"};
-const char * const EDSP::DepMap[] = {"", "Depends", "Pre-Depends", "Suggests",
+const char * const DepMap[] = {"", "Depends", "Pre-Depends", "Suggests",
 				     "Recommends" , "Conflicts", "Replaces",
 				     "Obsoletes", "Breaks", "Enhances"};
 
-// EDSP::WriteScenario - to the given file descriptor			/*{{{*/
-bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress)
-{
-   if (Progress != NULL)
-      Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to solver"));
-   unsigned long p = 0;
-   std::vector<std::string> archs = APT::Configuration::getArchitectures();
-   for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg)
-   {
-      std::string const arch = Pkg.Arch();
-      if (std::find(archs.begin(), archs.end(), arch) == archs.end())
-	 continue;
-      for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver, ++p)
-      {
-	 WriteScenarioVersion(Cache, output, Pkg, Ver);
-	 WriteScenarioDependency(output, Ver);
-	 fprintf(output, "\n");
-	 if (Progress != NULL && p % 100 == 0)
-	    Progress->Progress(p);
-      }
-   }
-   return true;
-}
-									/*}}}*/
-// EDSP::WriteLimitedScenario - to the given file descriptor		/*{{{*/
-bool EDSP::WriteLimitedScenario(pkgDepCache &Cache, FILE* output,
-				APT::PackageSet const &pkgset,
-				OpProgress *Progress)
-{
-   if (Progress != NULL)
-      Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to solver"));
-   unsigned long p  = 0;
-   for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg, ++p)
-      for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver)
-      {
-	 WriteScenarioVersion(Cache, output, Pkg, Ver);
-	 WriteScenarioLimitedDependency(output, Ver, pkgset);
-	 fprintf(output, "\n");
-	 if (Progress != NULL && p % 100 == 0)
-	    Progress->Progress(p);
-      }
-   if (Progress != NULL)
-      Progress->Done();
-   return true;
-}
-									/*}}}*/
-// EDSP::WriteScenarioVersion						/*{{{*/
-void EDSP::WriteScenarioVersion(pkgDepCache &Cache, FILE* output, pkgCache::PkgIterator const &Pkg,
+
+// WriteScenarioVersion							/*{{{*/
+static void WriteScenarioVersion(pkgDepCache &Cache, FILE* output, pkgCache::PkgIterator const &Pkg,
 				pkgCache::VerIterator const &Ver)
 {
    fprintf(output, "Package: %s\n", Pkg.Name());
+#if APT_PKG_ABI >= 413
    fprintf(output, "Source: %s\n", Ver.SourcePkgName());
+#else
+   pkgRecords Recs(Cache);
+   pkgRecords::Parser &rec = Recs.Lookup(Ver.FileList());
+   string srcpkg = rec.SourcePkg().empty() ? Pkg.Name() : rec.SourcePkg();
+   fprintf(output, "Source: %s\n", srcpkg.c_str());
+#endif
    fprintf(output, "Architecture: %s\n", Ver.Arch());
    fprintf(output, "Version: %s\n", Ver.VerStr());
    if (Pkg.CurrentVer() == Ver)
@@ -122,7 +84,7 @@ void EDSP::WriteScenarioVersion(pkgDepCache &Cache, FILE* output, pkgCache::PkgI
       signed short const p = Cache.GetPolicy().GetPriority(File);
       if (Pin < p)
 	 Pin = p;
-      if ((File->Flags & pkgCache::Flag::NotSource) != pkgCache::Flag::NotSource) {
+      if (File.Flagged(pkgCache::Flag::NotSource) == false) {
 	 string Release = File.RelStr();
 	 if (!Release.empty())
 	    Releases.insert(Release);
@@ -140,8 +102,8 @@ void EDSP::WriteScenarioVersion(pkgDepCache &Cache, FILE* output, pkgCache::PkgI
       fprintf(output, "APT-Automatic: yes\n");
 }
 									/*}}}*/
-// EDSP::WriteScenarioDependency					/*{{{*/
-void EDSP::WriteScenarioDependency( FILE* output, pkgCache::VerIterator const &Ver)
+// WriteScenarioDependency						/*{{{*/
+static void WriteScenarioDependency( FILE* output, pkgCache::VerIterator const &Ver)
 {
    std::string dependencies[pkgCache::Dep::Enhances + 1];
    bool orGroup = false;
@@ -176,8 +138,8 @@ void EDSP::WriteScenarioDependency( FILE* output, pkgCache::VerIterator const &V
       fprintf(output, "Provides: %s\n", provides.c_str()+2);
 }
 									/*}}}*/
-// EDSP::WriteScenarioLimitedDependency					/*{{{*/
-void EDSP::WriteScenarioLimitedDependency(FILE* output,
+// WriteScenarioLimitedDependency					/*{{{*/
+static void WriteScenarioLimitedDependency(FILE* output,
 					  pkgCache::VerIterator const &Ver,
 					  APT::PackageSet const &pkgset)
 {
@@ -228,6 +190,52 @@ void EDSP::WriteScenarioLimitedDependency(FILE* output,
       fprintf(output, "Provides: %s\n", provides.c_str()+2);
 }
 									/*}}}*/
+// EDSP::WriteScenario - to the given file descriptor			/*{{{*/
+bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress)
+{
+   if (Progress != NULL)
+      Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to solver"));
+   unsigned long p = 0;
+   std::vector<std::string> archs = APT::Configuration::getArchitectures();
+   for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg)
+   {
+      std::string const arch = Pkg.Arch();
+      if (std::find(archs.begin(), archs.end(), arch) == archs.end())
+	 continue;
+      for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver, ++p)
+      {
+	 WriteScenarioVersion(Cache, output, Pkg, Ver);
+	 WriteScenarioDependency(output, Ver);
+	 fprintf(output, "\n");
+	 if (Progress != NULL && p % 100 == 0)
+	    Progress->Progress(p);
+      }
+   }
+   return true;
+}
+									/*}}}*/
+// EDSP::WriteLimitedScenario - to the given file descriptor		/*{{{*/
+bool EDSP::WriteLimitedScenario(pkgDepCache &Cache, FILE* output,
+				APT::PackageSet const &pkgset,
+				OpProgress *Progress)
+{
+   if (Progress != NULL)
+      Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to solver"));
+   unsigned long p  = 0;
+   for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg, ++p)
+      for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver)
+      {
+	 WriteScenarioVersion(Cache, output, Pkg, Ver);
+	 WriteScenarioLimitedDependency(output, Ver, pkgset);
+	 fprintf(output, "\n");
+	 if (Progress != NULL && p % 100 == 0)
+	    Progress->Progress(p);
+      }
+   if (Progress != NULL)
+      Progress->Done();
+   return true;
+}
+									/*}}}*/
 // EDSP::WriteRequest - to the given file descriptor			/*{{{*/
 bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output, bool const Upgrade,
 			bool const DistUpgrade, bool const AutoRemove,
@@ -358,13 +366,13 @@ bool EDSP::ReadResponse(int const input, pkgDepCache &Cache, OpProgress *Progres
 	return true;
 }
 									/*}}}*/
-// EDSP::ReadLine - first line from the given file descriptor		/*{{{*/
+// ReadLine - first line from the given file descriptor			/*{{{*/
 // ---------------------------------------------------------------------
 /* Little helper method to read a complete line into a string. Similar to
    fgets but we need to use the low-level read() here as otherwise the
    listparser will be confused later on as mixing of fgets and read isn't
    a supported action according to the manpages and results are undefined */
-bool EDSP::ReadLine(int const input, std::string &line) {
+static bool ReadLine(int const input, std::string &line) {
 	char one;
 	ssize_t data = 0;
 	line.erase();
@@ -383,11 +391,11 @@ bool EDSP::ReadLine(int const input, std::string &line) {
 	return false;
 }
 									/*}}}*/
-// EDSP::StringToBool - convert yes/no to bool				/*{{{*/
+// StringToBool - convert yes/no to bool				/*{{{*/
 // ---------------------------------------------------------------------
 /* we are not as lazy as we are in the global StringToBool as we really
    only accept yes/no here - but we will ignore leading spaces */
-bool EDSP::StringToBool(char const *answer, bool const defValue) {
+static bool StringToBool(char const *answer, bool const defValue) {
    for (; isspace(*answer) != 0; ++answer);
    if (strncasecmp(answer, "yes", 3) == 0)
       return true;
@@ -436,11 +444,11 @@ bool EDSP::ReadRequest(int const input, std::list<std::string> &install,
 	    request = &remove;
 	 }
 	 else if (line.compare(0, 8, "Upgrade:") == 0)
-	    upgrade = EDSP::StringToBool(line.c_str() + 9, false);
+	    upgrade = StringToBool(line.c_str() + 9, false);
 	 else if (line.compare(0, 13, "Dist-Upgrade:") == 0)
-	    distUpgrade = EDSP::StringToBool(line.c_str() + 14, false);
+	    distUpgrade = StringToBool(line.c_str() + 14, false);
 	 else if (line.compare(0, 11, "Autoremove:") == 0)
-	    autoRemove = EDSP::StringToBool(line.c_str() + 12, false);
+	    autoRemove = StringToBool(line.c_str() + 12, false);
 	 else if (line.compare(0, 13, "Architecture:") == 0)
 	    _config->Set("APT::Architecture", line.c_str() + 14);
 	 else if (line.compare(0, 14, "Architectures:") == 0)

+ 13 - 29
apt-pkg/edsp.h

@@ -27,24 +27,8 @@
 class pkgDepCache;
 class OpProgress;
 
-class EDSP								/*{{{*/
+namespace EDSP								/*{{{*/
 {
-	// we could use pkgCache::DepType and ::Priority, but these would be localized strings…
-	static const char * const PrioMap[];
-	static const char * const DepMap[];
-
-	APT_HIDDEN bool static ReadLine(int const input, std::string &line);
-	APT_HIDDEN bool static StringToBool(char const *answer, bool const defValue);
-
-	APT_HIDDEN void static WriteScenarioVersion(pkgDepCache &Cache, FILE* output,
-					 pkgCache::PkgIterator const &Pkg,
-					 pkgCache::VerIterator const &Ver);
-	APT_HIDDEN void static WriteScenarioDependency(FILE* output,
-					    pkgCache::VerIterator const &Ver);
-	APT_HIDDEN void static WriteScenarioLimitedDependency(FILE* output,
-						   pkgCache::VerIterator const &Ver,
-						   APT::PackageSet const &pkgset);
-public:
 	/** \brief creates the EDSP request stanza
 	 *
 	 *  In the EDSP protocol the first thing send to the resolver is a stanza
@@ -61,7 +45,7 @@ public:
 	 *
 	 *  \return true if request was composed successfully, otherwise false
 	 */
-	bool static WriteRequest(pkgDepCache &Cache, FILE* output,
+	bool WriteRequest(pkgDepCache &Cache, FILE* output,
 				 bool const upgrade = false,
 				 bool const distUpgrade = false,
 				 bool const autoRemove = false,
@@ -84,7 +68,7 @@ public:
 	 *
 	 *  \return true if universe was composed successfully, otherwise false
 	 */
-	bool static WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress = NULL);
+	bool WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress = NULL);
 
 	/** \brief creates a limited scenario representing the package universe
 	 *
@@ -101,7 +85,7 @@ public:
 	 *
 	 *  \return true if universe was composed successfully, otherwise false
 	 */
-	bool static WriteLimitedScenario(pkgDepCache &Cache, FILE* output,
+	bool WriteLimitedScenario(pkgDepCache &Cache, FILE* output,
 					 APT::PackageSet const &pkgset,
 					 OpProgress *Progress = NULL);
 
@@ -118,7 +102,7 @@ public:
 	 *
 	 *  \return true if a solution is found and applied correctly, otherwise false
 	 */
-	bool static ReadResponse(int const input, pkgDepCache &Cache, OpProgress *Progress = NULL);
+	bool ReadResponse(int const input, pkgDepCache &Cache, OpProgress *Progress = NULL);
 
 	/** \brief search and read the request stanza for action later
 	 *
@@ -136,7 +120,7 @@ public:
 	 *
 	 *  \return true if the request could be found and worked on, otherwise false
 	 */
-	bool static ReadRequest(int const input, std::list<std::string> &install,
+	bool ReadRequest(int const input, std::list<std::string> &install,
 			std::list<std::string> &remove, bool &upgrade,
 			bool &distUpgrade, bool &autoRemove);
 
@@ -152,7 +136,7 @@ public:
 	 *
 	 *  \return false if the request couldn't be applied, true otherwise
 	 */
-	bool static ApplyRequest(std::list<std::string> const &install,
+	bool ApplyRequest(std::list<std::string> const &install,
 				 std::list<std::string> const &remove,
 				 pkgDepCache &Cache);
 
@@ -168,7 +152,7 @@ public:
 	 *
 	 *  \return true if solution could be written, otherwise false
 	 */
-	bool static WriteSolution(pkgDepCache &Cache, FILE* output);
+	bool WriteSolution(pkgDepCache &Cache, FILE* output);
 
 	/** \brief sends a progress report
 	 *
@@ -176,7 +160,7 @@ public:
 	 *  \param message the solver wants the user to see
 	 *  \param output the front-end listens for progress report
 	 */
-	bool static WriteProgress(unsigned short const percent, const char* const message, FILE* output);
+	bool WriteProgress(unsigned short const percent, const char* const message, FILE* output);
 
 	/** \brief sends an error report
 	 *
@@ -193,7 +177,7 @@ public:
 	 *  \param message is free form text to describe the error
 	 *  \param output the front-end listens for error messages
 	 */
-	bool static WriteError(char const * const uuid, std::string const &message, FILE* output);
+	bool WriteError(char const * const uuid, std::string const &message, FILE* output);
 
 
 	/** \brief executes the given solver and returns the pipe ends
@@ -207,8 +191,8 @@ public:
 	 *
 	 *  \return PID of the started solver or 0 if failure occurred
 	 */
-	pid_t static ExecuteSolver(const char* const solver, int * const solver_in, int * const solver_out, bool /*overload*/);
-	APT_DEPRECATED bool static ExecuteSolver(const char* const solver, int *solver_in, int *solver_out);
+	pid_t ExecuteSolver(const char* const solver, int * const solver_in, int * const solver_out, bool /*overload*/);
+	APT_DEPRECATED bool ExecuteSolver(const char* const solver, int *solver_in, int *solver_out);
 
 	/** \brief call an external resolver to handle the request
 	 *
@@ -224,7 +208,7 @@ public:
 	 *  \return true if the solver has successfully solved the problem,
 	 *  otherwise false
 	 */
-	bool static ResolveExternal(const char* const solver, pkgDepCache &Cache,
+	bool ResolveExternal(const char* const solver, pkgDepCache &Cache,
 				    bool const upgrade, bool const distUpgrade,
 				    bool const autoRemove, OpProgress *Progress = NULL);
 };

+ 6 - 5
apt-pkg/edsp/edspindexfile.cc

@@ -49,15 +49,14 @@ bool edspIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
 
    if (Prog != NULL)
       Prog->SubProgress(0,File);
-   if (Gen.SelectFile(File,std::string(),*this) == false)
+   if (Gen.SelectFile(File, *this, "", "edsp") == false)
       return _error->Error("Problem with SelectFile %s",File.c_str());
 
    // Store the IMS information
    pkgCache::PkgFileIterator CFile = Gen.GetCurFile();
+   pkgCacheGenerator::Dynamic<pkgCache::PkgFileIterator> DynFile(CFile);
    CFile->Size = Pkg.FileSize();
    CFile->mtime = Pkg.ModificationTime();
-   map_stringitem_t const storage = Gen.StoreString(pkgCacheGenerator::MIXED, "edsp::scenario");
-   CFile->Archive = storage;
 
    if (Gen.MergeList(Parser) == false)
       return _error->Error("Problem with MergeList %s",File.c_str());
@@ -65,7 +64,7 @@ bool edspIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
 }
 									/*}}}*/
 // Index File types for APT						/*{{{*/
-class edspIFType: public pkgIndexFile::Type
+class APT_HIDDEN edspIFType: public pkgIndexFile::Type
 {
    public:
    virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator) const
@@ -75,10 +74,12 @@ class edspIFType: public pkgIndexFile::Type
    };
    edspIFType() {Label = "EDSP scenario file";};
 };
-static edspIFType _apt_Universe;
+APT_HIDDEN edspIFType _apt_Universe;
 
 const pkgIndexFile::Type *edspIndex::GetType() const
 {
    return &_apt_Universe;
 }
 									/*}}}*/
+
+edspIndex::~edspIndex() {}

+ 2 - 1
apt-pkg/edsp/edspindexfile.h

@@ -18,7 +18,7 @@
 class OpProgress;
 class pkgCacheGenerator;
 
-class edspIndex : public debStatusIndex
+class APT_HIDDEN edspIndex : public debStatusIndex
 {
    /** \brief dpointer placeholder (for later in case we need it) */
    void *d;
@@ -30,6 +30,7 @@ class edspIndex : public debStatusIndex
    virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const;
 
    edspIndex(std::string File);
+   virtual ~edspIndex();
 };
 
 #endif

+ 4 - 2
apt-pkg/edsp/edsplistparser.cc

@@ -86,9 +86,11 @@ bool edspListParser::ParseStatus(pkgCache::PkgIterator &Pkg,
 }
 									/*}}}*/
 // ListParser::LoadReleaseInfo - Load the release information		/*{{{*/
-APT_CONST bool edspListParser::LoadReleaseInfo(pkgCache::PkgFileIterator & /*FileI*/,
-				    FileFd & /*File*/, std::string /*component*/)
+APT_CONST bool edspListParser::LoadReleaseInfo(pkgCache::RlsFileIterator & /*FileI*/,
+				    FileFd & /*File*/, std::string const &/*component*/)
 {
    return true;
 }
 									/*}}}*/
+
+edspListParser::~edspListParser() {}

+ 5 - 3
apt-pkg/edsp/edsplistparser.h

@@ -25,8 +25,9 @@
 
 class FileFd;
 
-class edspListParser : public debListParser
+class APT_HIDDEN edspListParser : public debListParser
 {
+   void *d;
    public:
    virtual bool NewVersion(pkgCache::VerIterator &Ver);
    virtual std::string Description();
@@ -34,10 +35,11 @@ class edspListParser : public debListParser
    virtual MD5SumValue Description_md5();
    virtual unsigned short VersionHash();
 
-   bool LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,FileFd &File,
-			std::string section);
+   bool LoadReleaseInfo(pkgCache::RlsFileIterator &FileI,FileFd &File,
+			std::string const &section);
 
    edspListParser(FileFd *File, std::string const &Arch = "");
+   virtual ~edspListParser();
 
    protected:
    virtual bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver);

+ 2 - 2
apt-pkg/edsp/edspsystem.cc

@@ -26,8 +26,6 @@
 #include <apti18n.h>
 									/*}}}*/
 
-edspSystem edspSys;
-
 // System::debSystem - Constructor					/*{{{*/
 edspSystem::edspSystem()
 {
@@ -126,3 +124,5 @@ bool edspSystem::FindIndex(pkgCache::PkgFileIterator File,
    return false;
 }
 									/*}}}*/
+
+APT_HIDDEN edspSystem edspSys;

+ 2 - 4
apt-pkg/edsp/edspsystem.h

@@ -22,7 +22,7 @@ class pkgIndexFile;
 class pkgPackageManager;
 class edspIndex;
 
-class edspSystem : public pkgSystem
+class APT_HIDDEN edspSystem : public pkgSystem
 {
    /** \brief dpointer placeholder (for later in case we need it) */
    void *d;
@@ -42,9 +42,7 @@ class edspSystem : public pkgSystem
 			  pkgIndexFile *&Found) const;
 
    edspSystem();
-   ~edspSystem();
+   virtual ~edspSystem();
 };
 
-extern edspSystem edspSys;
-
 #endif

+ 63 - 77
apt-pkg/indexcopy.cc

@@ -108,10 +108,7 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List,
       }
       if (_error->PendingError() == true)
 	 return false;
-      FILE *TargetFl = fdopen(dup(Target.Fd()),"w");
-      if (TargetFl == 0)
-	 return _error->Errno("fdopen","Failed to reopen fd");
-      
+
       // Setup the progress meter
       if(Progress)
 	 Progress->OverallProgress(CurrentSize,TotalSize,FileSize,
@@ -132,14 +129,11 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List,
 	 string File;
 	 unsigned long long Size;
 	 if (GetFile(File,Size) == false)
-	 {
-	    fclose(TargetFl);
 	    return false;
-	 }
-	 
+
 	 if (Chop != 0)
 	    File = OrigPath + ChopDirs(File,Chop);
-	 
+
 	 // See if the file exists
 	 if (NoStat == false || Hits < 10)
 	 {
@@ -157,10 +151,10 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List,
 	       if (Chop != 0)
 		  File = OrigPath + ChopDirs(File,Chop);
 	    }
-	    
+
 	    // Get the size
 	    struct stat Buf;
-	    if (stat((CDROM + Prefix + File).c_str(),&Buf) != 0 || 
+	    if (stat((CDROM + Prefix + File).c_str(),&Buf) != 0 ||
 		Buf.st_size == 0)
 	    {
 	       bool Mangled = false;
@@ -173,7 +167,7 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List,
 		  File.replace(Start,End-Start,"binary-all");
 		  Mangled = true;
 	       }
-	       
+
 	       if (Mangled == false ||
 		   stat((CDROM + Prefix + File).c_str(),&Buf) != 0)
 	       {
@@ -181,9 +175,9 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List,
 		     clog << "Missed(2): " << OrigFile << endl;
 		  NotFound++;
 		  continue;
-	       }	       
-	    }	    
-	    			    	    
+	       }
+	    }
+
 	    // Size match
 	    if ((unsigned long long)Buf.st_size != Size)
 	    {
@@ -193,21 +187,17 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List,
 	       continue;
 	    }
 	 }
-	 
+
 	 Packages++;
 	 Hits++;
-	 
-	 if (RewriteEntry(TargetFl,File) == false)
-	 {
-	    fclose(TargetFl);
+
+	 if (RewriteEntry(Target, File) == false)
 	    return false;
-	 }
       }
-      fclose(TargetFl);
 
       if (Debug == true)
 	 cout << " Processed by using Prefix '" << Prefix << "' and chop " << Chop << endl;
-	 
+
       if (_config->FindB("APT::CDROM::NoAct",false) == false)
       {
 	 // Move out of the partial directory
@@ -216,40 +206,40 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List,
 	 FinalF += URItoFileName(S);
 	 if (rename(TargetF.c_str(),FinalF.c_str()) != 0)
 	    return _error->Errno("rename","Failed to rename");
+	 ChangeOwnerAndPermissionOfFile("CopyPackages", FinalF.c_str(), "root", "root", 0644);
       }
-	 
+
       /* Mangle the source to be in the proper notation with
-       	 prefix dist [component] */ 
+	 prefix dist [component] */
       *I = string(*I,Prefix.length());
       ConvertToSourceList(CDROM,*I);
       *I = Prefix + ' ' + *I;
-      
+
       CurrentSize += FileSize;
-   }   
+   }
    if(Progress)
       Progress->Done();
-   
+
    // Some stats
    if(log) {
       stringstream msg;
       if(NotFound == 0 && WrongSize == 0)
 	 ioprintf(msg, _("Wrote %i records.\n"), Packages);
       else if (NotFound != 0 && WrongSize == 0)
-	 ioprintf(msg, _("Wrote %i records with %i missing files.\n"), 
+	 ioprintf(msg, _("Wrote %i records with %i missing files.\n"),
 		  Packages, NotFound);
       else if (NotFound == 0 && WrongSize != 0)
-	 ioprintf(msg, _("Wrote %i records with %i mismatched files\n"), 
+	 ioprintf(msg, _("Wrote %i records with %i mismatched files\n"),
 		  Packages, WrongSize);
       if (NotFound != 0 && WrongSize != 0)
 	 ioprintf(msg, _("Wrote %i records with %i missing files and %i mismatched files\n"), Packages, NotFound, WrongSize);
    }
-   
+
    if (Packages == 0)
       _error->Warning("No valid records were found.");
 
    if (NotFound + WrongSize > 10)
       _error->Warning("A lot of entries were discarded, something may be wrong.\n");
-   
 
    return true;
 }
@@ -266,10 +256,10 @@ string IndexCopy::ChopDirs(string Path,unsigned int Depth)
       Depth--;
    }
    while (I != string::npos && Depth != 0);
-   
+
    if (I == string::npos)
       return string();
-   
+
    return string(Path,I+1);
 }
 									/*}}}*/
@@ -432,17 +422,15 @@ bool PackageCopy::GetFile(string &File,unsigned long long &Size)
 }
 									/*}}}*/
 // PackageCopy::RewriteEntry - Rewrite the entry with a new filename	/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool PackageCopy::RewriteEntry(FILE *Target,string File)
+bool PackageCopy::RewriteEntry(FileFd &Target,string const &File)
 {
-   TFRewriteData Changes[] = {{ "Filename", File.c_str(), NULL },
-                              { NULL, NULL, NULL }};
-   
-   if (TFRewrite(Target,*Section,TFRewritePackageOrder,Changes) == false)
+   string const Dir(File,0,File.rfind('/'));
+   std::vector<pkgTagSection::Tag> Changes;
+   Changes.push_back(pkgTagSection::Tag::Rewrite("Filename", File));
+
+   if (Section->Write(Target, TFRewritePackageOrder, Changes) == false)
       return false;
-   fputc('\n',Target);
-   return true;
+   return Target.Write("\n", 1);
 }
 									/*}}}*/
 // SourceCopy::GetFile - Get the file information from the section	/*{{{*/
@@ -477,23 +465,18 @@ bool SourceCopy::GetFile(string &File,unsigned long long &Size)
 }
 									/*}}}*/
 // SourceCopy::RewriteEntry - Rewrite the entry with a new filename	/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool SourceCopy::RewriteEntry(FILE *Target,string File)
+bool SourceCopy::RewriteEntry(FileFd &Target, std::string const &File)
 {
-   string Dir(File,0,File.rfind('/'));
-   TFRewriteData Changes[] = {{ "Directory", Dir.c_str(), NULL },
-                              { NULL, NULL, NULL }};
-   
-   if (TFRewrite(Target,*Section,TFRewriteSourceOrder,Changes) == false)
+   string const Dir(File,0,File.rfind('/'));
+   std::vector<pkgTagSection::Tag> Changes;
+   Changes.push_back(pkgTagSection::Tag::Rewrite("Directory", Dir));
+
+   if (Section->Write(Target, TFRewriteSourceOrder, Changes) == false)
       return false;
-   fputc('\n',Target);
-   return true;
+   return Target.Write("\n", 1);
 }
 									/*}}}*/
-// SigVerify::Verify - Verify a files md5sum against its metaindex     	/*{{{*/
-// ---------------------------------------------------------------------
-/* */
+// SigVerify::Verify - Verify a files md5sum against its metaindex	/*{{{*/
 bool SigVerify::Verify(string prefix, string file, indexRecords *MetaIndex)
 {
    const indexRecords::checkSum *Record = MetaIndex->Lookup(file);
@@ -546,8 +529,9 @@ bool SigVerify::CopyMetaIndex(string CDROM, string CDName,		/*{{{*/
       FileFd Rel;
       Target.Open(TargetF,FileFd::WriteAtomic);
       Rel.Open(prefix + file,FileFd::ReadOnly);
-      if (CopyFile(Rel,Target) == false)
+      if (CopyFile(Rel,Target) == false || Target.Close() == false)
 	 return _error->Error("Copying of '%s' for '%s' from '%s' failed", file.c_str(), CDName.c_str(), prefix.c_str());
+      ChangeOwnerAndPermissionOfFile("CopyPackages", TargetF.c_str(), "root", "root", 0644);
 
       return true;
 }
@@ -700,7 +684,7 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name,	/*{{{*/
       pkgTagFile Parser(&Pkg);
       if (_error->PendingError() == true)
 	 return false;
-      
+
       // Open the output file
       char S[400];
       snprintf(S,sizeof(S),"cdrom:[%s]/%s",Name.c_str(),
@@ -717,10 +701,7 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name,	/*{{{*/
       }
       if (_error->PendingError() == true)
 	 return false;
-      FILE *TargetFl = fdopen(dup(Target.Fd()),"w");
-      if (TargetFl == 0)
-	 return _error->Errno("fdopen","Failed to reopen fd");
-      
+
       // Setup the progress meter
       if(Progress)
 	 Progress->OverallProgress(CurrentSize,TotalSize,FileSize,
@@ -738,20 +719,16 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name,	/*{{{*/
 	 if(Progress)
 	    Progress->Progress(Parser.Offset());
 
-	 const char *Start;
-	 const char *Stop;
-	 Section.GetSection(Start,Stop);
-	 fwrite(Start,Stop-Start, 1, TargetFl);
-	 fputc('\n',TargetFl);
+	 if (Section.Write(Target) == false || Target.Write("\n", 1) == false)
+	    return false;
 
 	 Packages++;
 	 Hits++;
       }
-      fclose(TargetFl);
 
       if (Debug == true)
 	 cout << " Processed by using Prefix '" << Prefix << "' and chop " << endl;
-	 
+
       if (_config->FindB("APT::CDROM::NoAct",false) == false)
       {
 	 // Move out of the partial directory
@@ -760,38 +737,47 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name,	/*{{{*/
 	 FinalF += URItoFileName(S);
 	 if (rename(TargetF.c_str(),FinalF.c_str()) != 0)
 	    return _error->Errno("rename","Failed to rename");
+	 ChangeOwnerAndPermissionOfFile("CopyTranslations", FinalF.c_str(), "root", "root", 0644);
       }
-      
-      
+
       CurrentSize += FileSize;
-   }   
+   }
    if(Progress)
       Progress->Done();
-   
+
    // Some stats
    if(log) {
       stringstream msg;
       if(NotFound == 0 && WrongSize == 0)
 	 ioprintf(msg, _("Wrote %i records.\n"), Packages);
       else if (NotFound != 0 && WrongSize == 0)
-	 ioprintf(msg, _("Wrote %i records with %i missing files.\n"), 
+	 ioprintf(msg, _("Wrote %i records with %i missing files.\n"),
 		  Packages, NotFound);
       else if (NotFound == 0 && WrongSize != 0)
-	 ioprintf(msg, _("Wrote %i records with %i mismatched files\n"), 
+	 ioprintf(msg, _("Wrote %i records with %i mismatched files\n"),
 		  Packages, WrongSize);
       if (NotFound != 0 && WrongSize != 0)
 	 ioprintf(msg, _("Wrote %i records with %i missing files and %i mismatched files\n"), Packages, NotFound, WrongSize);
    }
-   
+
    if (Packages == 0)
       _error->Warning("No valid records were found.");
 
    if (NotFound + WrongSize > 10)
       _error->Warning("A lot of entries were discarded, something may be wrong.\n");
-   
 
    return true;
 }
 									/*}}}*/
 
+IndexCopy::IndexCopy() {}
 APT_CONST IndexCopy::~IndexCopy() {}
+
+PackageCopy::PackageCopy() : IndexCopy() {}
+APT_CONST PackageCopy::~PackageCopy() {}
+SourceCopy::SourceCopy() : IndexCopy() {}
+APT_CONST SourceCopy::~SourceCopy() {}
+TranslationsCopy::TranslationsCopy() {}
+APT_CONST TranslationsCopy::~TranslationsCopy() {}
+SigVerify::SigVerify() {}
+APT_CONST SigVerify::~SigVerify() {}

+ 23 - 7
apt-pkg/indexcopy.h

@@ -1,6 +1,5 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: indexcopy.h,v 1.3 2001/05/27 04:46:54 jgg Exp $
 /* ######################################################################
 
    Index Copying - Aid for copying and verifying the index files
@@ -28,6 +27,7 @@ using std::vector;
 class pkgTagSection;
 class indexRecords;
 class pkgCdromStatus;
+class FileFd;
 
 class IndexCopy								/*{{{*/
 {
@@ -45,7 +45,7 @@ class IndexCopy								/*{{{*/
    void ConvertToSourceList(std::string CD,std::string &Path);
    bool GrabFirst(std::string Path,std::string &To,unsigned int Depth);
    virtual bool GetFile(std::string &Filename,unsigned long long &Size) = 0;
-   virtual bool RewriteEntry(FILE *Target,std::string File) = 0;
+   virtual bool RewriteEntry(FileFd &Target, std::string const &File) = 0;
    virtual const char *GetFileName() = 0;
    virtual const char *Type() = 0;
    
@@ -53,39 +53,52 @@ class IndexCopy								/*{{{*/
 
    bool CopyPackages(std::string CDROM,std::string Name,std::vector<std::string> &List,
 		     pkgCdromStatus *log);
+   IndexCopy();
    virtual ~IndexCopy();
 };
 									/*}}}*/
 class PackageCopy : public IndexCopy					/*{{{*/
 {
+   void *d;
    protected:
-   
+
    virtual bool GetFile(std::string &Filename,unsigned long long &Size);
-   virtual bool RewriteEntry(FILE *Target,std::string File);
+   virtual bool RewriteEntry(FileFd &Target, std::string const &File);
    virtual const char *GetFileName() {return "Packages";};
    virtual const char *Type() {return "Package";};
-   
+
+   public:
+   PackageCopy();
+   virtual ~PackageCopy();
 };
 									/*}}}*/
 class SourceCopy : public IndexCopy					/*{{{*/
 {
+   void *d;
    protected:
    
    virtual bool GetFile(std::string &Filename,unsigned long long &Size);
-   virtual bool RewriteEntry(FILE *Target,std::string File);
+   virtual bool RewriteEntry(FileFd &Target, std::string const &File);
    virtual const char *GetFileName() {return "Sources";};
    virtual const char *Type() {return "Source";};
-   
+
+   public:
+   SourceCopy();
+   virtual ~SourceCopy();
 };
 									/*}}}*/
 class TranslationsCopy							/*{{{*/
 {
+   void *d;
    protected:
    pkgTagSection *Section;
 
    public:
    bool CopyTranslations(std::string CDROM,std::string Name,std::vector<std::string> &List,
 			 pkgCdromStatus *log);
+
+   TranslationsCopy();
+   virtual ~TranslationsCopy();
 };
 									/*}}}*/
 class SigVerify								/*{{{*/
@@ -105,6 +118,9 @@ class SigVerify								/*{{{*/
 		       int const &statusfd, int fd[2]);
    APT_DEPRECATED static bool RunGPGV(std::string const &File, std::string const &FileOut,
 			      int const &statusfd = -1);
+
+   SigVerify();
+   virtual ~SigVerify();
 };
 									/*}}}*/
 

+ 126 - 6
apt-pkg/indexfile.cc

@@ -10,8 +10,10 @@
 // Include Files							/*{{{*/
 #include<config.h>
 
+#include <apt-pkg/configuration.h>
 #include <apt-pkg/indexfile.h>
 #include <apt-pkg/error.h>
+#include <apt-pkg/fileutl.h>
 #include <apt-pkg/aptconfiguration.h>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/cacheiterators.h>
@@ -48,27 +50,26 @@ pkgIndexFile::Type *pkgIndexFile::Type::GetType(const char *Type)
       if (strcmp(GlobalList[I]->Label,Type) == 0)
 	 return GlobalList[I];
    return 0;
+}
+									/*}}}*/
+pkgIndexFile::pkgIndexFile(bool Trusted) :				/*{{{*/
+   Trusted(Trusted)
+{
 }
 									/*}}}*/
 // IndexFile::ArchiveInfo - Stub					/*{{{*/
-// ---------------------------------------------------------------------
-/* */
 std::string pkgIndexFile::ArchiveInfo(pkgCache::VerIterator /*Ver*/) const
 {
    return std::string();
 }
 									/*}}}*/
 // IndexFile::FindInCache - Stub					/*{{{*/
-// ---------------------------------------------------------------------
-/* */
 pkgCache::PkgFileIterator pkgIndexFile::FindInCache(pkgCache &Cache) const
 {
    return pkgCache::PkgFileIterator(Cache);
 }
 									/*}}}*/
 // IndexFile::SourceIndex - Stub					/*{{{*/
-// ---------------------------------------------------------------------
-/* */
 std::string pkgIndexFile::SourceInfo(pkgSrcRecords::Parser const &/*Record*/,
 				pkgSrcRecords::File const &/*File*/) const
 {
@@ -110,3 +111,122 @@ APT_DEPRECATED std::string pkgIndexFile::LanguageCode() {
 	return APT::Configuration::getLanguages()[0];
 }
 									/*}}}*/
+
+// IndexTarget - Constructor						/*{{{*/
+IndexTarget::IndexTarget(std::string const &MetaKey, std::string const &ShortDesc,
+      std::string const &LongDesc, std::string const &URI, bool const IsOptional,
+      std::map<std::string, std::string> const &Options) :
+   URI(URI), Description(LongDesc), ShortDesc(ShortDesc), MetaKey(MetaKey), IsOptional(IsOptional), Options(Options)
+{
+}
+									/*}}}*/
+std::string IndexTarget::Option(OptionKeys const EnumKey) const		/*{{{*/
+{
+   std::string Key;
+   switch (EnumKey)
+   {
+#define APT_CASE(X) case X: Key = #X; break
+      APT_CASE(SITE);
+      APT_CASE(RELEASE);
+      APT_CASE(COMPONENT);
+      APT_CASE(LANGUAGE);
+      APT_CASE(ARCHITECTURE);
+      APT_CASE(BASE_URI);
+      APT_CASE(REPO_URI);
+      APT_CASE(TARGET_OF);
+      APT_CASE(CREATED_BY);
+#undef APT_CASE
+      case FILENAME: return _config->FindDir("Dir::State::lists") + URItoFileName(URI);
+      case EXISTING_FILENAME:
+	 std::string const filename = Option(FILENAME);
+	 std::vector<std::string> const types = APT::Configuration::getCompressionTypes();
+	 for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
+	 {
+	    if (t->empty())
+	       continue;
+	    std::string const file = (*t == "uncompressed") ? filename : (filename + "." + *t);
+	    if (FileExists(file))
+	       return file;
+	 }
+	 return "";
+   }
+   std::map<std::string,std::string>::const_iterator const M = Options.find(Key);
+   if (M == Options.end())
+      return "";
+   return M->second;
+}
+									/*}}}*/
+std::string IndexTarget::Format(std::string format) const		/*{{{*/
+{
+   for (std::map<std::string, std::string>::const_iterator O = Options.begin(); O != Options.end(); ++O)
+   {
+      format = SubstVar(format, std::string("$(") + O->first + ")", O->second);
+   }
+   format = SubstVar(format, "$(METAKEY)", MetaKey);
+   format = SubstVar(format, "$(SHORTDESC)", ShortDesc);
+   format = SubstVar(format, "$(DESCRIPTION)", Description);
+   format = SubstVar(format, "$(URI)", URI);
+   format = SubstVar(format, "$(FILENAME)", Option(IndexTarget::FILENAME));
+   return format;
+}
+									/*}}}*/
+
+pkgIndexTargetFile::pkgIndexTargetFile(IndexTarget const &Target, bool const Trusted) :/*{{{*/
+   pkgIndexFile(Trusted), Target(Target)
+{
+}
+									/*}}}*/
+std::string pkgIndexTargetFile::ArchiveURI(std::string File) const/*{{{*/
+{
+   return Target.Option(IndexTarget::REPO_URI) + File;
+}
+									/*}}}*/
+std::string pkgIndexTargetFile::Describe(bool Short) const		/*{{{*/
+{
+   if (Short)
+      return Target.Description;
+   return Target.Description + " (" + IndexFileName() + ")";
+}
+									/*}}}*/
+std::string pkgIndexTargetFile::IndexFileName() const			/*{{{*/
+{
+   std::string const s = Target.Option(IndexTarget::FILENAME);
+   if (FileExists(s))
+      return s;
+
+   std::vector<std::string> types = APT::Configuration::getCompressionTypes();
+   for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
+   {
+      std::string p = s + '.' + *t;
+      if (FileExists(p))
+         return p;
+   }
+   return s;
+}
+									/*}}}*/
+unsigned long pkgIndexTargetFile::Size() const				/*{{{*/
+{
+   unsigned long size = 0;
+
+   /* we need to ignore errors here; if the lists are absent, just return 0 */
+   _error->PushToStack();
+
+   FileFd f(IndexFileName(), FileFd::ReadOnly, FileFd::Extension);
+   if (!f.Failed())
+      size = f.Size();
+
+   if (_error->PendingError() == true)
+       size = 0;
+   _error->RevertToStack();
+
+   return size;
+}
+									/*}}}*/
+bool pkgIndexTargetFile::Exists() const					/*{{{*/
+{
+   return FileExists(IndexFileName());
+}
+									/*}}}*/
+
+APT_CONST pkgIndexFile::~pkgIndexFile() {}
+APT_CONST pkgIndexTargetFile::~pkgIndexTargetFile() {}

+ 73 - 7
apt-pkg/indexfile.h

@@ -1,6 +1,5 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: indexfile.h,v 1.6.2.1 2003/12/24 23:09:17 mdz Exp $
 /* ######################################################################
 
    Index File - Abstraction for an index of archive/source file.
@@ -28,6 +27,7 @@
 #include <apt-pkg/cacheiterators.h>
 #include <apt-pkg/macros.h>
 
+#include <map>
 #include <string>
 
 #ifndef APT_8_CLEANER_HEADERS
@@ -40,17 +40,65 @@ class pkgAcquire;
 class pkgCacheGenerator;
 class OpProgress;
 
+class IndexTarget							/*{{{*/
+/** \brief Information about an index file. */
+{
+   public:
+   /** \brief A URI from which the index file can be downloaded. */
+   std::string URI;
+
+   /** \brief A description of the index file. */
+   std::string Description;
+
+   /** \brief A shorter description of the index file. */
+   std::string ShortDesc;
+
+   /** \brief The key by which this index file should be
+       looked up within the meta index file. */
+   std::string MetaKey;
+
+   /** \brief Is it okay if the file isn't found in the meta index */
+   bool IsOptional;
+
+   /** \brief options with which this target was created
+       Prefer the usage of #Option if at all possible.
+       Beware: Not all of these options are intended for public use */
+   std::map<std::string, std::string> Options;
+
+   IndexTarget(std::string const &MetaKey, std::string const &ShortDesc,
+	 std::string const &LongDesc, std::string const &URI, bool const IsOptional,
+	 std::map<std::string, std::string> const &Options);
+
+   enum OptionKeys {
+      SITE,
+      RELEASE,
+      COMPONENT,
+      LANGUAGE,
+      ARCHITECTURE,
+      BASE_URI,
+      REPO_URI,
+      CREATED_BY,
+      TARGET_OF,
+      FILENAME,
+      EXISTING_FILENAME,
+   };
+   std::string Option(OptionKeys const Key) const;
+   std::string Format(std::string format) const;
+};
+									/*}}}*/
+
 class pkgIndexFile
 {
+   void *d;
    protected:
    bool Trusted;
-     
+
    public:
 
    class Type
    {
       public:
-      
+
       // Global list of Items supported
       static Type **GlobalList;
       static unsigned long GlobalListLen;
@@ -70,7 +118,7 @@ class pkgIndexFile
    virtual std::string ArchiveInfo(pkgCache::VerIterator Ver) const;
    virtual std::string SourceInfo(pkgSrcRecords::Parser const &Record,
 			     pkgSrcRecords::File const &File) const;
-   virtual std::string Describe(bool Short = false) const = 0;   
+   virtual std::string Describe(bool Short = false) const = 0;
 
    // Interface for acquire
    virtual std::string ArchiveURI(std::string /*File*/) const {return std::string();};
@@ -95,9 +143,27 @@ class pkgIndexFile
    static std::string LanguageCode();
 
    bool IsTrusted() const { return Trusted; };
-   
-   pkgIndexFile(bool Trusted): Trusted(Trusted) {};
-   virtual ~pkgIndexFile() {};
+
+   pkgIndexFile(bool Trusted);
+   virtual ~pkgIndexFile();
+};
+
+class pkgIndexTargetFile : public pkgIndexFile
+{
+   void *d;
+protected:
+   IndexTarget const Target;
+
+   std::string IndexFileName() const;
+
+public:
+   virtual std::string ArchiveURI(std::string File) const;
+   virtual std::string Describe(bool Short = false) const;
+   virtual bool Exists() const;
+   virtual unsigned long Size() const;
+
+   pkgIndexTargetFile(IndexTarget const &Target, bool const Trusted);
+   virtual ~pkgIndexTargetFile();
 };
 
 #endif

+ 32 - 24
apt-pkg/indexrecords.cc

@@ -58,6 +58,11 @@ APT_PURE time_t indexRecords::GetValidUntil() const
    return this->ValidUntil;
 }
 
+APT_PURE time_t indexRecords::GetDate() const
+{
+   return this->Date;
+}
+
 APT_PURE indexRecords::checkSum *indexRecords::Lookup(const string MetaKey)
 {
    std::map<std::string, indexRecords::checkSum* >::const_iterator sum = Entries.find(MetaKey);
@@ -68,7 +73,7 @@ APT_PURE indexRecords::checkSum *indexRecords::Lookup(const string MetaKey)
 
 APT_PURE bool indexRecords::Exists(string const &MetaKey) const
 {
-   return Entries.count(MetaKey) == 1;
+   return Entries.find(MetaKey) != Entries.end();
 }
 
 bool indexRecords::Load(const string Filename)				/*{{{*/
@@ -116,17 +121,8 @@ bool indexRecords::Load(const string Filename)				/*{{{*/
             indexRecords::checkSum *Sum = new indexRecords::checkSum;
             Sum->MetaKeyFilename = Name;
             Sum->Size = Size;
-	    std::string SizeStr;
-	    strprintf(SizeStr, "%llu", Size);
-	    Sum->Hashes.push_back(HashString("Checksum-FileSize", SizeStr));
-#if __GNUC__ >= 4
-       #pragma GCC diagnostic push
-       #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-            Sum->Hash = HashString(HashString::SupportedHashes()[i],Hash);
-#if __GNUC__ >= 4
-       #pragma GCC diagnostic pop
-#endif
+	    Sum->Hashes.FileSize(Size);
+            APT_IGNORE_DEPRECATED(Sum->Hash = HashString(HashString::SupportedHashes()[i],Hash);)
             Entries[Name] = Sum;
          }
          Entries[Name]->Hashes.push_back(HashString(HashString::SupportedHashes()[i],Hash));
@@ -140,9 +136,15 @@ bool indexRecords::Load(const string Filename)				/*{{{*/
       return false;
    }
 
-   string Label = Section.FindS("Label");
-   string StrDate = Section.FindS("Date");
-   string StrValidUntil = Section.FindS("Valid-Until");
+   string const StrDate = Section.FindS("Date");
+   if (RFC1123StrToTime(StrDate.c_str(), Date) == false)
+   {
+      strprintf(ErrorText, _("Invalid 'Date' entry in Release file %s"), Filename.c_str());
+      return false;
+   }
+
+   string const Label = Section.FindS("Label");
+   string const StrValidUntil = Section.FindS("Valid-Until");
 
    // if we have a Valid-Until header in the Release file, use it as default
    if (StrValidUntil.empty() == false)
@@ -165,20 +167,13 @@ bool indexRecords::Load(const string Filename)				/*{{{*/
       (MinAge == 0 || ValidUntil == 0)) // No user settings, use the one from the Release file
       return true;
 
-   time_t date;
-   if (RFC1123StrToTime(StrDate.c_str(), date) == false)
-   {
-      strprintf(ErrorText, _("Invalid 'Date' entry in Release file %s"), Filename.c_str());
-      return false;
-   }
-
    if (MinAge != 0 && ValidUntil != 0) {
-      time_t const min_date = date + MinAge;
+      time_t const min_date = Date + MinAge;
       if (ValidUntil < min_date)
 	 ValidUntil = min_date;
    }
    if (MaxAge != 0) {
-      time_t const max_date = date + MaxAge;
+      time_t const max_date = Date + MaxAge;
       if (ValidUntil == 0 || ValidUntil > max_date)
 	 ValidUntil = max_date;
    }
@@ -277,10 +272,23 @@ void indexRecords::SetTrusted(bool const Trusted)
       this->Trusted = NEVER_TRUSTED;
 }
 
+#if APT_PKG_ABI >= 413
 indexRecords::indexRecords(const string &ExpectedDist) :
    Trusted(CHECK_TRUST), d(NULL), ExpectedDist(ExpectedDist), ValidUntil(0),
    SupportsAcquireByHash(false)
 {
 }
+#else
+indexRecords::indexRecords() :
+   Trusted(CHECK_TRUST), d(NULL), ExpectedDist(""), ValidUntil(0),
+   SupportsAcquireByHash(false)
+{
+}
+indexRecords::indexRecords(const string ExpectedDist) :
+   Trusted(CHECK_TRUST), d(NULL), ExpectedDist(ExpectedDist), ValidUntil(0),
+   SupportsAcquireByHash(false)
+{
+}
+#endif
 
 indexRecords::~indexRecords() {}

+ 9 - 12
apt-pkg/indexrecords.h

@@ -1,7 +1,4 @@
 // -*- mode: cpp; mode: fold -*-
-// Description								/*{{{*/
-// $Id: indexrecords.h,v 1.1.2.1 2003/12/24 23:09:17 mdz Exp $
-									/*}}}*/
 #ifndef PKGLIB_INDEXRECORDS_H
 #define PKGLIB_INDEXRECORDS_H
 
@@ -36,14 +33,19 @@ class indexRecords
    std::string Dist;
    std::string Suite;
    std::string ExpectedDist;
+   time_t Date;
    time_t ValidUntil;
    bool SupportsAcquireByHash;
 
    std::map<std::string,checkSum *> Entries;
 
    public:
-
+#if APT_PKG_ABI >= 413
    indexRecords(const std::string &ExpectedDist = "");
+#else
+   indexRecords();
+   indexRecords(const std::string ExpectedDist);
+#endif
 
    // Lookup function
    virtual checkSum *Lookup(const std::string MetaKey);
@@ -58,6 +60,7 @@ class indexRecords
    std::string GetSuite() const;
    bool GetSupportsAcquireByHash() const;
    time_t GetValidUntil() const;
+   time_t GetDate() const;
    std::string GetExpectedDist() const;
 
    /** \brief check if source is marked as always trusted */
@@ -76,11 +79,7 @@ class indexRecords
    virtual ~indexRecords();
 };
 
-#if __GNUC__ >= 4
-	// ensure that con- & de-structor don't trigger this warning
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+APT_IGNORE_DEPRECATED_PUSH
 struct indexRecords::checkSum
 {
    std::string MetaKeyFilename;
@@ -89,8 +88,6 @@ struct indexRecords::checkSum
 
    APT_DEPRECATED HashString Hash;
 };
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP
 
 #endif

+ 24 - 2
apt-pkg/init.cc

@@ -89,7 +89,7 @@ bool pkgInitConfig(Configuration &Cnf)
    Cnf.Set("Dir::Ignore-Files-Silently::", "\\.distUpgrade$");
 
    // Repository security
-   // FIXME: this is set to "true" for backward compatiblity, once
+   // FIXME: this is set to "true" for backward compatibility, once
    //        jessie is out we want to change this to "false" to
    //        improve security
    Cnf.CndSet("Acquire::AllowInsecureRepositories", true);
@@ -101,8 +101,30 @@ bool pkgInitConfig(Configuration &Cnf)
    // The default user we drop to in the methods
    Cnf.CndSet("APT::Sandbox::User", "_apt");
 
+   Cnf.CndSet("APT::Acquire::Targets::deb::Packages::MetaKey", "$(COMPONENT)/binary-$(ARCHITECTURE)/Packages");
+   Cnf.CndSet("APT::Acquire::Targets::deb::Packages::flatMetaKey", "Packages");
+   Cnf.CndSet("APT::Acquire::Targets::deb::Packages::ShortDescription", "Packages");
+   Cnf.CndSet("APT::Acquire::Targets::deb::Packages::Description", "$(SITE) $(RELEASE)/$(COMPONENT) $(ARCHITECTURE) Packages");
+   Cnf.CndSet("APT::Acquire::Targets::deb::Packages::flatDescription", "$(SITE) $(RELEASE) Packages");
+   Cnf.CndSet("APT::Acquire::Targets::deb::Packages::Optional", false);
+   Cnf.CndSet("APT::Acquire::Targets::deb::Translations::MetaKey", "$(COMPONENT)/i18n/Translation-$(LANGUAGE)");
+   Cnf.CndSet("APT::Acquire::Targets::deb::Translations::flatMetaKey", "$(LANGUAGE)");
+   Cnf.CndSet("APT::Acquire::Targets::deb::Translations::ShortDescription", "Translation-$(LANGUAGE)");
+   Cnf.CndSet("APT::Acquire::Targets::deb::Translations::Description", "$(SITE) $(RELEASE)/$(COMPONENT) Translation-$(LANGUAGE)");
+   Cnf.CndSet("APT::Acquire::Targets::deb::Translations::flatDescription", "$(SITE) $(RELEASE) Translation-$(LANGUAGE)");
+   Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::MetaKey", "$(COMPONENT)/source/Sources");
+   Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::flatMetaKey", "Sources");
+   Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::ShortDescription", "Sources");
+   Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::Description", "$(SITE) $(RELEASE)/$(COMPONENT) Sources");
+   Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::flatDescription", "$(SITE) $(RELEASE) Sources");
+   Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::Optional", false);
+
+   Cnf.CndSet("Acquire::Changelogs::URI::Origin::Debian", "http://metadata.ftp-master.debian.org/changelogs/CHANGEPATH_changelog");
+   Cnf.CndSet("Acquire::Changelogs::URI::Origin::Ubuntu", "http://changelogs.ubuntu.com/changelogs/pool/CHANGEPATH/changelog");
+   Cnf.CndSet("Acquire::Changelogs::URI::Origin::Ultimedia", "http://packages.ultimediaos.com/changelogs/pool/CHANGEPATH/changelog.txt");
+
    bool Res = true;
-   
+
    // Read an alternate config file
    const char *Cfg = getenv("APT_CONFIG");
    if (Cfg != 0 && strlen(Cfg) != 0)

+ 6 - 0
apt-pkg/install-progress.cc

@@ -69,6 +69,7 @@ PackageManagerProgressFd::PackageManagerProgressFd(int progress_fd)
 {
    OutStatusFd = progress_fd;
 }
+PackageManagerProgressFd::~PackageManagerProgressFd() {}
 
 void PackageManagerProgressFd::WriteToStatusFd(std::string s)
 {
@@ -157,6 +158,7 @@ PackageManagerProgressDeb822Fd::PackageManagerProgressDeb822Fd(int progress_fd)
 {
    OutStatusFd = progress_fd;
 }
+PackageManagerProgressDeb822Fd::~PackageManagerProgressDeb822Fd() {}
 
 void PackageManagerProgressDeb822Fd::WriteToStatusFd(std::string s)
 {
@@ -433,6 +435,10 @@ bool PackageManagerText::StatusChanged(std::string PackageName,
    return true;
 }
 
+PackageManagerText::PackageManagerText() : PackageManager() {}
+PackageManagerText::~PackageManagerText() {}
+
+
 
 
 } // namespace progress

+ 10 - 1
apt-pkg/install-progress.h

@@ -61,6 +61,7 @@ namespace Progress {
 
  class PackageManagerProgressFd : public PackageManager
  {
+    void *d;
  protected:
     int OutStatusFd;
     int StepsDone;
@@ -69,6 +70,7 @@ namespace Progress {
 
  public:
     PackageManagerProgressFd(int progress_fd);
+    virtual ~PackageManagerProgressFd();
 
     virtual void StartDpkg();
     virtual void Stop();
@@ -90,6 +92,7 @@ namespace Progress {
 
  class PackageManagerProgressDeb822Fd : public PackageManager
  {
+    void *d;
  protected:
     int OutStatusFd;
     int StepsDone;
@@ -98,6 +101,7 @@ namespace Progress {
 
  public:
     PackageManagerProgressDeb822Fd(int progress_fd);
+    virtual ~PackageManagerProgressDeb822Fd();
 
     virtual void StartDpkg();
     virtual void Stop();
@@ -118,6 +122,7 @@ namespace Progress {
 
  class PackageManagerFancy : public PackageManager
  {
+    void *d;
  private:
     APT_HIDDEN static void staticSIGWINCH(int);
     static std::vector<PackageManagerFancy*> instances;
@@ -138,7 +143,7 @@ namespace Progress {
 
  public:
     PackageManagerFancy();
-    ~PackageManagerFancy();
+    virtual ~PackageManagerFancy();
     virtual void Start(int child_pty=-1);
     virtual void Stop();
     virtual bool StatusChanged(std::string PackageName,
@@ -153,11 +158,15 @@ namespace Progress {
 
  class PackageManagerText : public PackageManager
  {
+    void *d;
  public:
     virtual bool StatusChanged(std::string PackageName,
                                unsigned int StepsDone,
                                unsigned int TotalSteps,
                                std::string HumanReadableAction);
+
+    PackageManagerText();
+    virtual ~PackageManagerText();
  };
 
 

+ 57 - 0
apt-pkg/metaindex.cc

@@ -0,0 +1,57 @@
+// Include Files                                                       /*{{{*/
+#include <apt-pkg/pkgcachegen.h>
+#include <apt-pkg/indexfile.h>
+#include <apt-pkg/metaindex.h>
+
+#include <stddef.h>
+
+#include <string>
+#include <vector>
+                                                                       /*}}}*/
+
+#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+std::string metaIndex::LocalFileName() const { return ""; }
+#else
+#include <apt-pkg/debmetaindex.h>
+std::string metaIndex::LocalFileName() const
+{
+   debReleaseIndex const * deb = dynamic_cast<debReleaseIndex const*>(this);
+   if (deb != NULL)
+      return deb->LocalFileName();
+
+   return "";
+}
+#endif
+
+std::string metaIndex::Describe() const
+{
+   return "Release";
+}
+
+pkgCache::RlsFileIterator metaIndex::FindInCache(pkgCache &Cache, bool const) const
+{
+   return pkgCache::RlsFileIterator(Cache);
+}
+
+bool metaIndex::Merge(pkgCacheGenerator &Gen,OpProgress *) const
+{
+   return Gen.SelectReleaseFile("", "");
+}
+
+
+metaIndex::metaIndex(std::string const &URI, std::string const &Dist,
+      char const * const Type)
+: Indexes(NULL), Type(Type), URI(URI), Dist(Dist), Trusted(false)
+{
+   /* nothing */
+}
+
+metaIndex::~metaIndex()
+{
+   if (Indexes == 0)
+      return;
+   for (std::vector<pkgIndexFile *>::iterator I = (*Indexes).begin();
+        I != (*Indexes).end(); ++I)
+      delete *I;
+   delete Indexes;
+}

+ 14 - 20
apt-pkg/metaindex.h

@@ -22,9 +22,13 @@ using std::string;
 #endif
 
 class pkgAcquire;
+class IndexTarget;
+class pkgCacheGenerator;
+class OpProgress;
 
 class metaIndex
 {
+   void *d;
    protected:
    std::vector <pkgIndexFile *> *Indexes;
    const char *Type;
@@ -40,33 +44,23 @@ class metaIndex
    virtual const char* GetType() const {return Type;}
 
    // interface to to query it
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
-   // returns the path of the local file (or "" if its not available)
-   virtual std::string LocalFileName() const {return "";};
-#endif
+   /** \return the path of the local file (or "" if its not available) */
+   virtual std::string LocalFileName() const;
 
    // Interface for acquire
    virtual std::string ArchiveURI(std::string const& File) const = 0;
    virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const = 0;
-   virtual std::vector<pkgIndexFile *> *GetIndexFiles() = 0; 
+   virtual std::vector<IndexTarget> GetIndexTargets() const = 0;
+   virtual std::vector<pkgIndexFile *> *GetIndexFiles() = 0;
    virtual bool IsTrusted() const = 0;
 
-   metaIndex(std::string const &URI, std::string const &Dist, 
-             char const * const Type) 
-      : Indexes(NULL), Type(Type), URI(URI), Dist(Dist), Trusted(false)
-   {
-      /* nothing */
-   }
+   virtual std::string Describe() const;
+   virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache, bool const ModifyCheck) const;
+   virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const;
 
-   virtual ~metaIndex() 
-   {
-      if (Indexes == 0)
-	 return;
-      for (std::vector<pkgIndexFile *>::iterator I = (*Indexes).begin();
-           I != (*Indexes).end(); ++I)
-	 delete *I;
-      delete Indexes;
-   }
+   metaIndex(std::string const &URI, std::string const &Dist,
+             char const * const Type);
+   virtual ~metaIndex();
 };
 
 #endif

+ 2 - 2
apt-pkg/orderlist.h

@@ -1,6 +1,5 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: orderlist.h,v 1.9 2001/02/20 07:03:17 jgg Exp $
 /* ######################################################################
 
    Order List - Represents and Manipulates an ordered list of packages.
@@ -25,6 +24,7 @@
 class pkgDepCache;
 class pkgOrderList : protected pkgCache::Namespace
 {
+   void *d;
    protected:
 
    pkgDepCache &Cache;   
@@ -123,7 +123,7 @@ class pkgOrderList : protected pkgCache::Namespace
    int Score(PkgIterator Pkg);
 
    pkgOrderList(pkgDepCache *Cache);
-   ~pkgOrderList();
+   virtual ~pkgOrderList();
 };
 
 #endif

+ 39 - 13
apt-pkg/packagemanager.cc

@@ -400,7 +400,8 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
 	       // Check if the current version of the package is available and will satisfy this dependency
 	       if (DepPkg.CurrentVer() == Ver && List->IsNow(DepPkg) == true &&
 		   List->IsFlag(DepPkg,pkgOrderList::Removed) == false &&
-		   DepPkg.State() == PkgIterator::NeedsNothing)
+		   DepPkg.State() == PkgIterator::NeedsNothing &&
+		   (Cache[DepPkg].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall)
 	       {
 		  Bad = false;
 		  break;
@@ -413,8 +414,13 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
 	       if (PkgLoop == true)
 	       {
 		  if (Debug)
-		     std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure" << std::endl;
-	          Bad = false;
+		     std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure";
+		  if (List->IsFlag(DepPkg,pkgOrderList::UnPacked))
+		     Bad = false;
+		  else if (Debug)
+		     std::clog << ", but it isn't unpacked yet";
+		  if (Debug)
+		     std::clog << std::endl;
 	       }
 	    }
 
@@ -426,7 +432,7 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
          if (Bad == false)
          {
             if (Debug)
-               std::clog << OutputInDepth(Depth) << "Found ok dep " << D.TargetPkg() << std::endl;
+               std::clog << OutputInDepth(Depth) << "Found ok dep " << Start.TargetPkg() << std::endl;
             continue;
          }
 
@@ -444,7 +450,8 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
 	       // Check if the current version of the package is available and will satisfy this dependency
 	       if (DepPkg.CurrentVer() == Ver && List->IsNow(DepPkg) == true &&
 		   List->IsFlag(DepPkg,pkgOrderList::Removed) == false &&
-		   DepPkg.State() == PkgIterator::NeedsNothing)
+		   DepPkg.State() == PkgIterator::NeedsNothing &&
+		   (Cache[DepPkg].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall)
                   continue;
 
 	       // Check if the version that is going to be installed will satisfy the dependency
@@ -454,8 +461,13 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
 	       if (PkgLoop == true)
 	       {
 		  if (Debug)
-		     std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure" << std::endl;
-	          Bad = false;
+		     std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure";
+		  if (List->IsFlag(DepPkg,pkgOrderList::UnPacked))
+		     Bad = false;
+		  else if (Debug)
+		     std::clog << ", but it isn't unpacked yet";
+		  if (Debug)
+		     std::clog << std::endl;
 	       }
 	       else
 	       {
@@ -722,7 +734,8 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c
 
 		  // See if the current version is ok
 		  if (Pkg.CurrentVer() == Ver && List->IsNow(Pkg) == true &&
-		      Pkg.State() == PkgIterator::NeedsNothing)
+		      Pkg.State() == PkgIterator::NeedsNothing &&
+		      (Cache[Pkg].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall)
 		  {
 		     Bad = false;
 		     if (Debug)
@@ -744,8 +757,11 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c
 		  PkgIterator DepPkg = Ver.ParentPkg();
 
 		  // Not the install version
-		  if (Cache[DepPkg].InstallVer != *I ||
-		      (Cache[DepPkg].Keep() == true && DepPkg.State() == PkgIterator::NeedsNothing))
+		  if (Cache[DepPkg].InstallVer != *I)
+		     continue;
+
+		  if (Cache[DepPkg].Keep() == true && DepPkg.State() == PkgIterator::NeedsNothing &&
+			(Cache[DepPkg].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall)
 		     continue;
 
 		  if (List->IsFlag(DepPkg,pkgOrderList::Configured))
@@ -757,6 +773,16 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c
 		  // check if it needs unpack or if if configure is enough
 		  if (List->IsFlag(DepPkg,pkgOrderList::UnPacked) == false)
 		  {
+		     // two packages pre-depending on each other can't be handled sanely
+		     if (List->IsFlag(DepPkg,pkgOrderList::Loop) && PkgLoop)
+		     {
+			// this isn't an error as there is potential for something else to satisfy it
+			// (like a provides or an or-group member)
+			if (Debug)
+			   clog << OutputInDepth(Depth) << "Unpack loop detected between " << DepPkg.FullName() << " and " << Pkg.FullName() << endl;
+			continue;
+		     }
+
 		     if (Debug)
 			clog << OutputInDepth(Depth) << "Trying to SmartUnpack " << DepPkg.FullName() << endl;
 		     if (NonLoopingSmart(UNPACK_IMMEDIATE, Pkg, DepPkg, Depth, PkgLoop, &Bad, &Changed) == false)
@@ -1059,7 +1085,7 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall()
 // PM::DoInstallPostFork - compat /*{{{*/
 // ---------------------------------------------------------------------
 									/*}}}*/
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+#if APT_PKG_ABI >= 413
 pkgPackageManager::OrderResult
 pkgPackageManager::DoInstallPostFork(int statusFd)
 {
@@ -1096,7 +1122,7 @@ pkgPackageManager::DoInstallPostFork(int statusFd)
 // PM::DoInstall - Does the installation				/*{{{*/
 // ---------------------------------------------------------------------
 /* compat */
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+#if APT_PKG_ABI >= 413
 pkgPackageManager::OrderResult 
 pkgPackageManager::DoInstall(int statusFd)
 {
@@ -1120,7 +1146,7 @@ pkgPackageManager::OrderResult pkgPackageManager::DoInstall(int statusFd)
 // ---------------------------------------------------------------------
 /* This uses the filenames in FileNames and the information in the
    DepCache to perform the installation of packages.*/
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+#if APT_PKG_ABI >= 413
 pkgPackageManager::OrderResult 
 pkgPackageManager::DoInstall(APT::Progress::PackageManager *progress)
 {

+ 6 - 8
apt-pkg/packagemanager.h

@@ -1,6 +1,5 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: packagemanager.h,v 1.14 2001/05/07 04:24:08 jgg Exp $
 /* ######################################################################
 
    Package Manager - Abstacts the package manager
@@ -96,12 +95,10 @@ class pkgPackageManager : protected pkgCache::Namespace
    virtual bool Install(PkgIterator /*Pkg*/,std::string /*File*/) {return false;};
    virtual bool Configure(PkgIterator /*Pkg*/) {return false;};
    virtual bool Remove(PkgIterator /*Pkg*/,bool /*Purge*/=false) {return false;};
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+#if APT_PKG_ABI >= 413
    virtual bool Go(APT::Progress::PackageManager * /*progress*/) {return true;};
-   virtual bool Go(int /*statusFd*/=-1) {return true;};
-#else
-   virtual bool Go(int /*statusFd*/=-1) {return true;};
 #endif
+   virtual bool Go(int /*statusFd*/=-1) {return true;};
 
    virtual void Reset() {};
 
@@ -114,8 +111,8 @@ class pkgPackageManager : protected pkgCache::Namespace
    bool GetArchives(pkgAcquire *Owner,pkgSourceList *Sources,
 		    pkgRecords *Recs);
 
-   // Do the installation 
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+   // Do the installation
+#if APT_PKG_ABI >= 413
    OrderResult DoInstall(APT::Progress::PackageManager *progress);
    // compat
    APT_DEPRECATED OrderResult DoInstall(int statusFd=-1);
@@ -129,7 +126,7 @@ class pkgPackageManager : protected pkgCache::Namespace
       Res = OrderInstall();
       return Res;
    };
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+#if APT_PKG_ABI >= 413
    // stuff that needs to be done after the fork
    OrderResult DoInstallPostFork(APT::Progress::PackageManager *progress);
    // compat
@@ -148,6 +145,7 @@ class pkgPackageManager : protected pkgCache::Namespace
    virtual ~pkgPackageManager();
 
    private:
+   void *d;
    enum APT_HIDDEN SmartAction { UNPACK_IMMEDIATE, UNPACK, CONFIGURE };
    APT_HIDDEN bool NonLoopingSmart(SmartAction const action, pkgCache::PkgIterator &Pkg,
       pkgCache::PkgIterator DepPkg, int const Depth, bool const PkgLoop,

+ 81 - 57
apt-pkg/pkgcache.cc

@@ -61,6 +61,7 @@ pkgCache::Header::Header()
    HeaderSz = sizeof(pkgCache::Header);
    GroupSz = sizeof(pkgCache::Group);
    PackageSz = sizeof(pkgCache::Package);
+   ReleaseFileSz = sizeof(pkgCache::ReleaseFile);
    PackageFileSz = sizeof(pkgCache::PackageFile);
    VersionSz = sizeof(pkgCache::Version);
    DescriptionSz = sizeof(pkgCache::Description);
@@ -74,6 +75,7 @@ pkgCache::Header::Header()
    VersionCount = 0;
    DescriptionCount = 0;
    DependsCount = 0;
+   ReleaseFileCount = 0;
    PackageFileCount = 0;
    VerFileCount = 0;
    DescFileCount = 0;
@@ -82,10 +84,14 @@ pkgCache::Header::Header()
    MaxDescFileSize = 0;
    
    FileList = 0;
+   RlsFileList = 0;
+#if APT_PKG_ABI < 413
+   APT_IGNORE_DEPRECATED(StringList = 0;)
+#endif
    VerSysName = 0;
    Architecture = 0;
-   Architectures = 0;
-   HashTableSize = _config->FindI("APT::Cache-HashTableSize", 10 * 1048);
+   SetArchitectures(0);
+   SetHashTableSize(_config->FindI("APT::Cache-HashTableSize", 10 * 1048));
    memset(Pools,0,sizeof(Pools));
 
    CacheFileSize = 0;
@@ -99,6 +105,7 @@ bool pkgCache::Header::CheckSizes(Header &Against) const
    if (HeaderSz == Against.HeaderSz &&
        GroupSz == Against.GroupSz &&
        PackageSz == Against.PackageSz &&
+       ReleaseFileSz == Against.ReleaseFileSz &&
        PackageFileSz == Against.PackageFileSz &&
        VersionSz == Against.VersionSz &&
        DescriptionSz == Against.DescriptionSz &&
@@ -114,6 +121,7 @@ bool pkgCache::Header::CheckSizes(Header &Against) const
 // Cache::pkgCache - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 /* */
+APT_IGNORE_DEPRECATED_PUSH
 pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map)
 {
    // call getArchitectures() with cached=false to ensure that the 
@@ -123,6 +131,7 @@ pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map)
    if (DoMap == true)
       ReMap();
 }
+APT_IGNORE_DEPRECATED_POP
 									/*}}}*/
 // Cache::ReMap - Reopen the cache file					/*{{{*/
 // ---------------------------------------------------------------------
@@ -135,6 +144,7 @@ bool pkgCache::ReMap(bool const &Errorchecks)
    PkgP = (Package *)Map.Data();
    VerFileP = (VerFile *)Map.Data();
    DescFileP = (DescFile *)Map.Data();
+   RlsFileP = (ReleaseFile *)Map.Data();
    PkgFileP = (PackageFile *)Map.Data();
    VerP = (Version *)Map.Data();
    DescP = (Description *)Map.Data();
@@ -162,7 +172,7 @@ bool pkgCache::ReMap(bool const &Errorchecks)
    if (Map.Size() < HeaderP->CacheFileSize)
       return _error->Error(_("The package cache file is corrupted, it is too small"));
 
-   if (HeaderP->VerSysName == 0 || HeaderP->Architecture == 0 || HeaderP->Architectures == 0)
+   if (HeaderP->VerSysName == 0 || HeaderP->Architecture == 0 || HeaderP->GetArchitectures() == 0)
       return _error->Error(_("The package cache file is corrupted"));
 
    // Locate our VS..
@@ -176,8 +186,8 @@ bool pkgCache::ReMap(bool const &Errorchecks)
    for (++a; a != archs.end(); ++a)
       list.append(",").append(*a);
    if (_config->Find("APT::Architecture") != StrP + HeaderP->Architecture ||
-	 list != StrP + HeaderP->Architectures)
-      return _error->Error(_("The package cache was built for different architectures: %s vs %s"), StrP + HeaderP->Architectures, list.c_str());
+	 list != StrP + HeaderP->GetArchitectures())
+      return _error->Error(_("The package cache was built for different architectures: %s vs %s"), StrP + HeaderP->GetArchitectures(), list.c_str());
 
    return true;
 }
@@ -192,7 +202,7 @@ map_id_t pkgCache::sHash(const string &Str) const
    unsigned long Hash = 0;
    for (string::const_iterator I = Str.begin(); I != Str.end(); ++I)
       Hash = 41 * Hash + tolower_ascii(*I);
-   return Hash % HeaderP->HashTableSize;
+   return Hash % HeaderP->GetHashTableSize();
 }
 
 map_id_t pkgCache::sHash(const char *Str) const
@@ -200,7 +210,7 @@ map_id_t pkgCache::sHash(const char *Str) const
    unsigned long Hash = tolower_ascii(*Str);
    for (const char *I = Str + 1; *I != 0; ++I)
       Hash = 41 * Hash + tolower_ascii(*I);
-   return Hash % HeaderP->HashTableSize;
+   return Hash % HeaderP->GetHashTableSize();
 }
 									/*}}}*/
 // Cache::SingleArchFindPkg - Locate a package by name			/*{{{*/
@@ -211,8 +221,8 @@ map_id_t pkgCache::sHash(const char *Str) const
 pkgCache::PkgIterator pkgCache::SingleArchFindPkg(const string &Name)
 {
    // Look at the hash bucket
-   Package *Pkg = PkgP + HeaderP->PkgHashTable()[Hash(Name)];
-   for (; Pkg != PkgP; Pkg = PkgP + Pkg->Next)
+   Package *Pkg = PkgP + HeaderP->PkgHashTableP()[Hash(Name)];
+   for (; Pkg != PkgP; Pkg = PkgP + Pkg->NextPackage)
    {
       int const cmp = strcmp(Name.c_str(), StrP + (GrpP + Pkg->Group)->Name);
       if (cmp == 0)
@@ -229,12 +239,7 @@ pkgCache::PkgIterator pkgCache::SingleArchFindPkg(const string &Name)
 pkgCache::PkgIterator pkgCache::FindPkg(const string &Name) {
 	size_t const found = Name.find(':');
 	if (found == string::npos)
-	{
-		if (MultiArchCache() == false)
-			return SingleArchFindPkg(Name);
-		else
-			return FindPkg(Name, "native");
-	}
+	   return FindPkg(Name, "native");
 	string const Arch = Name.substr(found+1);
 	/* Beware: This is specialcased to handle pkg:any in dependencies as
 	   these are linked to virtual pkg:any named packages with all archs.
@@ -248,13 +253,6 @@ pkgCache::PkgIterator pkgCache::FindPkg(const string &Name) {
 // ---------------------------------------------------------------------
 /* Returns 0 on error, pointer to the package otherwise */
 pkgCache::PkgIterator pkgCache::FindPkg(const string &Name, string const &Arch) {
-	if (MultiArchCache() == false && Arch != "none") {
-		if (Arch == "native" || Arch == "all" || Arch == "any" ||
-		    Arch == NativeArch())
-			return SingleArchFindPkg(Name);
-		else
-			return PkgIterator(*this,0);
-	}
 	/* We make a detour via the GrpIterator here as
 	   on a multi-arch environment a group is easier to
 	   find than a package (less entries in the buckets) */
@@ -273,7 +271,7 @@ pkgCache::GrpIterator pkgCache::FindGrp(const string &Name) {
 		return GrpIterator(*this,0);
 
 	// Look at the hash bucket for the group
-	Group *Grp = GrpP + HeaderP->GrpHashTable()[sHash(Name)];
+	Group *Grp = GrpP + HeaderP->GrpHashTableP()[sHash(Name)];
 	for (; Grp != GrpP; Grp = GrpP + Grp->Next) {
 		int const cmp = strcmp(Name.c_str(), StrP + Grp->Name);
 		if (cmp == 0)
@@ -359,7 +357,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) const {
 
 	// Iterate over the list to find the matching arch
 	for (pkgCache::Package *Pkg = PackageList(); Pkg != Owner->PkgP;
-	     Pkg = Owner->PkgP + Pkg->Next) {
+	     Pkg = Owner->PkgP + Pkg->NextPackage) {
 		if (stringcmp(Arch, Owner->StrP + Pkg->Arch) == 0)
 			return PkgIterator(*Owner, Pkg);
 		if ((Owner->PkgP + S->LastPackage) == Pkg)
@@ -407,7 +405,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator const
 	if (S->LastPackage == LastPkg.Index())
 		return PkgIterator(*Owner, 0);
 
-	return PkgIterator(*Owner, Owner->PkgP + LastPkg->Next);
+	return PkgIterator(*Owner, Owner->PkgP + LastPkg->NextPackage);
 }
 									/*}}}*/
 // GrpIterator::operator ++ - Postfix incr				/*{{{*/
@@ -420,10 +418,10 @@ void pkgCache::GrpIterator::operator ++(int)
       S = Owner->GrpP + S->Next;
 
    // Follow the hash table
-   while (S == Owner->GrpP && (HashIndex+1) < (signed)Owner->HeaderP->HashTableSize)
+   while (S == Owner->GrpP && (HashIndex+1) < (signed)Owner->HeaderP->GetHashTableSize())
    {
       HashIndex++;
-      S = Owner->GrpP + Owner->HeaderP->GrpHashTable()[HashIndex];
+      S = Owner->GrpP + Owner->HeaderP->GrpHashTableP()[HashIndex];
    }
 }
 									/*}}}*/
@@ -434,13 +432,13 @@ void pkgCache::PkgIterator::operator ++(int)
 {
    // Follow the current links
    if (S != Owner->PkgP)
-      S = Owner->PkgP + S->Next;
+      S = Owner->PkgP + S->NextPackage;
 
    // Follow the hash table
-   while (S == Owner->PkgP && (HashIndex+1) < (signed)Owner->HeaderP->HashTableSize)
+   while (S == Owner->PkgP && (HashIndex+1) < (signed)Owner->HeaderP->GetHashTableSize())
    {
       HashIndex++;
-      S = Owner->PkgP + Owner->HeaderP->PkgHashTable()[HashIndex];
+      S = Owner->PkgP + Owner->HeaderP->PkgHashTableP()[HashIndex];
    }
 }
 									/*}}}*/
@@ -821,7 +819,7 @@ APT_PURE bool pkgCache::VerIterator::Downloadable() const
 {
    VerFileIterator Files = FileList();
    for (; Files.end() == false; ++Files)
-      if ((Files.File()->Flags & pkgCache::Flag::NotSource) != pkgCache::Flag::NotSource)
+      if (Files.File().Flagged(pkgCache::Flag::NotSource) == false)
 	 return true;
    return false;
 }
@@ -835,7 +833,7 @@ APT_PURE bool pkgCache::VerIterator::Automatic() const
    VerFileIterator Files = FileList();
    for (; Files.end() == false; ++Files)
       // Do not check ButAutomaticUpgrades here as it is kind of automatic…
-      if ((Files.File()->Flags & pkgCache::Flag::NotAutomatic) != pkgCache::Flag::NotAutomatic)
+      if (Files.File().Flagged(pkgCache::Flag::NotAutomatic) == false)
 	 return true;
    return false;
 }
@@ -868,27 +866,27 @@ string pkgCache::VerIterator::RelStr() const
    for (pkgCache::VerFileIterator I = this->FileList(); I.end() == false; ++I)
    {
       // Do not print 'not source' entries'
-      pkgCache::PkgFileIterator File = I.File();
-      if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource)
+      pkgCache::PkgFileIterator const File = I.File();
+      if (File.Flagged(pkgCache::Flag::NotSource))
 	 continue;
 
       // See if we have already printed this out..
       bool Seen = false;
       for (pkgCache::VerFileIterator J = this->FileList(); I != J; ++J)
       {
-	 pkgCache::PkgFileIterator File2 = J.File();
-	 if (File2->Label == 0 || File->Label == 0)
+	 pkgCache::PkgFileIterator const File2 = J.File();
+	 if (File2.Label() == 0 || File.Label() == 0)
 	    continue;
 
 	 if (strcmp(File.Label(),File2.Label()) != 0)
 	    continue;
 	 
-	 if (File2->Version == File->Version)
+	 if (File2.Version() == File.Version())
 	 {
 	    Seen = true;
 	    break;
 	 }
-	 if (File2->Version == 0 || File->Version == 0)
+	 if (File2.Version() == 0 || File.Version() == 0)
 	    break;
 	 if (strcmp(File.Version(),File2.Version()) == 0)
 	    Seen = true;
@@ -902,12 +900,12 @@ string pkgCache::VerIterator::RelStr() const
       else
 	 First = false;
       
-      if (File->Label != 0)
+      if (File.Label() != 0)
 	 Res = Res + File.Label() + ':';
 
-      if (File->Archive != 0)
+      if (File.Archive() != 0)
       {
-	 if (File->Version == 0)
+	 if (File.Version() == 0)
 	    Res += File.Archive();
 	 else
 	    Res = Res + File.Version() + '/' +  File.Archive();
@@ -915,7 +913,7 @@ string pkgCache::VerIterator::RelStr() const
       else
       {
 	 // No release file, print the host name that this came from
-	 if (File->Site == 0 || File.Site()[0] == 0)
+	 if (File.Site() == 0 || File.Site()[0] == 0)
 	    Res += "localhost";
 	 else
 	    Res += File.Site();
@@ -938,12 +936,12 @@ const char * pkgCache::VerIterator::MultiArchType() const
    return "none";
 }
 									/*}}}*/
-// PkgFileIterator::IsOk - Checks if the cache is in sync with the file	/*{{{*/
+// RlsFileIterator::IsOk - Checks if the cache is in sync with the file	/*{{{*/
 // ---------------------------------------------------------------------
 /* This stats the file and compares its stats with the ones that were
-   stored during generation. Date checks should probably also be 
+   stored during generation. Date checks should probably also be
    included here. */
-bool pkgCache::PkgFileIterator::IsOk()
+bool pkgCache::RlsFileIterator::IsOk()
 {
    struct stat Buf;
    if (stat(FileName(),&Buf) != 0)
@@ -955,10 +953,8 @@ bool pkgCache::PkgFileIterator::IsOk()
    return true;
 }
 									/*}}}*/
-// PkgFileIterator::RelStr - Return the release string			/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string pkgCache::PkgFileIterator::RelStr()
+// RlsFileIterator::RelStr - Return the release string			/*{{{*/
+string pkgCache::RlsFileIterator::RelStr()
 {
    string Res;
    if (Version() != 0)
@@ -971,8 +967,40 @@ string pkgCache::PkgFileIterator::RelStr()
       Res = Res + (Res.empty() == true?"n=":",n=")  + Codename();
    if (Label() != 0)
       Res = Res + (Res.empty() == true?"l=":",l=")  + Label();
-   if (Component() != 0)
-      Res = Res + (Res.empty() == true?"c=":",c=")  + Component();
+   return Res;
+}
+									/*}}}*/
+// PkgFileIterator::IsOk - Checks if the cache is in sync with the file	/*{{{*/
+// ---------------------------------------------------------------------
+/* This stats the file and compares its stats with the ones that were
+   stored during generation. Date checks should probably also be
+   included here. */
+bool pkgCache::PkgFileIterator::IsOk()
+{
+   struct stat Buf;
+   if (stat(FileName(),&Buf) != 0)
+      return false;
+
+   if (Buf.st_size != (signed)S->Size || Buf.st_mtime != S->mtime)
+      return false;
+
+   return true;
+}
+									/*}}}*/
+string pkgCache::PkgFileIterator::RelStr()				/*{{{*/
+{
+   std::string Res;
+   if (ReleaseFile() == 0)
+   {
+      if (Component() != 0)
+	 Res = Res + (Res.empty() == true?"a=":",a=")  + Component();
+   }
+   else
+   {
+      Res = ReleaseFile().RelStr();
+      if (Component() != 0)
+	 Res = Res + (Res.empty() == true?"c=":",c=")  + Component();
+   }
    if (Architecture() != 0)
       Res = Res + (Res.empty() == true?"b=":",b=")  + Architecture();
    return Res;
@@ -1031,9 +1059,5 @@ bool pkgCache::PrvIterator::IsMultiArchImplicit() const
    return false;
 }
 									/*}}}*/
-APT_DEPRECATED APT_PURE const char * pkgCache::PkgIterator::Section() const {/*{{{*/
-   if (S->VersionList == 0)
-      return 0;
-   return VersionList().Section();
-}
-									/*}}}*/
+
+pkgCache::~pkgCache() {}

+ 151 - 26
apt-pkg/pkgcache.h

@@ -85,16 +85,45 @@
 using std::string;
 #endif
 
+#if APT_PKG_ABI >= 413
 // storing file sizes of indexes, which are way below 4 GB for now
 typedef uint32_t map_filesize_t;
+typedef map_filesize_t should_be_map_filesize_t;
+#else
+typedef unsigned long map_filesize_t;
+typedef unsigned int should_be_map_filesize_t;
+#endif
+#if APT_PKG_ABI >= 413
 // each package/group/dependency gets an id
 typedef uint32_t map_id_t;
+typedef map_id_t should_be_map_id_t;
+#else
+typedef unsigned long map_id_t;
+typedef unsigned int should_be_map_id_t;
+#endif
+#if APT_PKG_ABI >= 413
 // some files get an id, too, but in far less absolute numbers
 typedef uint16_t map_fileid_t;
+typedef map_fileid_t should_be_map_fileid_t;
+#else
+typedef unsigned long map_fileid_t;
+typedef unsigned int should_be_map_fileid_t;
+#endif
+#if APT_PKG_ABI >= 413
 // relative pointer from cache start
 typedef uint32_t map_pointer_t;
+#else
+typedef unsigned int map_pointer_t;
+#endif
 // same as the previous, but documented to be to a string item
 typedef map_pointer_t map_stringitem_t;
+#if APT_PKG_ABI >= 413
+typedef uint64_t should_be_uint64_t;
+typedef uint64_t should_be_uint64_small_t;
+#else
+typedef unsigned long long should_be_uint64_t;
+typedef unsigned long should_be_uint64_small_t;
+#endif
 
 class pkgVersioningSystem;
 class pkgCache								/*{{{*/
@@ -104,11 +133,13 @@ class pkgCache								/*{{{*/
    struct Header;
    struct Group;
    struct Package;
+   struct ReleaseFile;
    struct PackageFile;
    struct Version;
    struct Description;
    struct Provides;
    struct Dependency;
+   struct StringItem;
    struct VerFile;
    struct DescFile;
    
@@ -120,6 +151,7 @@ class pkgCache								/*{{{*/
    class DescIterator;
    class DepIterator;
    class PrvIterator;
+   class RlsFileIterator;
    class PkgFileIterator;
    class VerFileIterator;
    class DescFileIterator;
@@ -160,7 +192,15 @@ class pkgCache								/*{{{*/
    struct Flag
    {
       enum PkgFlags {Auto=(1<<0),Essential=(1<<3),Important=(1<<4)};
-      enum PkgFFlags {NotSource=(1<<0),NotAutomatic=(1<<1),ButAutomaticUpgrades=(1<<2)};
+      enum PkgFFlags {
+	 NotSource=(1<<0), /*!< packages can't be fetched from here, e.g. dpkg/status file */
+	 LocalSource=(1<<1), /*!< local sources can't and will not be verified by hashes */
+	 NoPackages=(1<<2), /*!< the file includes no package records itself, but additions like Translations */
+      };
+      enum ReleaseFileFlags {
+	 NotAutomatic=(1<<0), /*!< archive has a default pin of 1 */
+	 ButAutomaticUpgrades=(1<<1), /*!< (together with the previous) archive has a default pin of 100 */
+      };
    };
    
    protected:
@@ -180,11 +220,13 @@ class pkgCache								/*{{{*/
    Package *PkgP;
    VerFile *VerFileP;
    DescFile *DescFileP;
+   ReleaseFile *RlsFileP;
    PackageFile *PkgFileP;
    Version *VerP;
    Description *DescP;
    Provides *ProvideP;
    Dependency *DepP;
+   APT_DEPRECATED StringItem *StringItemP;
    char *StrP;
 
    virtual bool ReMap(bool const &Errorchecks = true);
@@ -211,6 +253,8 @@ class pkgCache								/*{{{*/
    inline PkgIterator PkgEnd();
    inline PkgFileIterator FileBegin();
    inline PkgFileIterator FileEnd();
+   inline RlsFileIterator RlsFileBegin();
+   inline RlsFileIterator RlsFileEnd();
 
    inline bool MultiArchCache() const { return MultiArchEnabled; }
    inline char const * NativeArch();
@@ -222,11 +266,12 @@ class pkgCache								/*{{{*/
    static const char *CompTypeDeb(unsigned char Comp) APT_CONST;
    static const char *CompType(unsigned char Comp) APT_CONST;
    static const char *DepType(unsigned char Dep);
-   
+
    pkgCache(MMap *Map,bool DoMap = true);
-   virtual ~pkgCache() {}
+   virtual ~pkgCache();
 
 private:
+   void *d;
    bool MultiArchEnabled;
    APT_HIDDEN PkgIterator SingleArchFindPkg(const std::string &Name);
 };
@@ -260,6 +305,7 @@ struct pkgCache::Header
    unsigned short HeaderSz;
    unsigned short GroupSz;
    unsigned short PackageSz;
+   unsigned short ReleaseFileSz;
    unsigned short PackageFileSz;
    unsigned short VersionSz;
    unsigned short DescriptionSz;
@@ -278,6 +324,7 @@ struct pkgCache::Header
    map_id_t VersionCount;
    map_id_t DescriptionCount;
    map_id_t DependsCount;
+   map_fileid_t ReleaseFileCount;
    map_fileid_t PackageFileCount;
    map_fileid_t VerFileCount;
    map_fileid_t DescFileCount;
@@ -288,12 +335,20 @@ struct pkgCache::Header
        The PackageFile structures are singly linked lists that represent
        all package files that have been merged into the cache. */
    map_pointer_t FileList;
+   /** \brief index of the first ReleaseFile structure */
+   map_pointer_t RlsFileList;
+
+#if APT_PKG_ABI < 413
+   APT_DEPRECATED map_pointer_t StringList;
+#endif
    /** \brief String representing the version system used */
    map_pointer_t VerSysName;
    /** \brief native architecture the cache was built against */
    map_pointer_t Architecture;
+#if APT_PKG_ABI >= 413
    /** \brief all architectures the cache was built against */
    map_pointer_t Architectures;
+#endif
    /** \brief The maximum size of a raw entry from the original Package file */
    map_filesize_t MaxVerFileSize;
    /** \brief The maximum size of a raw entry from the original Translation file */
@@ -319,12 +374,26 @@ struct pkgCache::Header
        In the PkgHashTable is it possible that multiple packages have the same name -
        these packages are stored as a sequence in the list.
        The size of both tables is the same. */
+#if APT_PKG_ABI >= 413
    unsigned int HashTableSize;
-   map_pointer_t * PkgHashTable() const { return (map_pointer_t*) (this + 1); }
-   map_pointer_t * GrpHashTable() const { return PkgHashTable() + HashTableSize; }
+   unsigned int GetHashTableSize() const { return HashTableSize; }
+   void SetHashTableSize(unsigned int const sz) { HashTableSize = sz; }
+   map_pointer_t GetArchitectures() const { return Architectures; }
+   void SetArchitectures(map_pointer_t const idx) { Architectures = idx; }
+#else
+   // BEWARE: these tables are pretty much empty and just here for abi compat
+   map_ptrloc PkgHashTable[2*1048];
+   map_ptrloc GrpHashTable[2*1048];
+   unsigned int GetHashTableSize() const { return PkgHashTable[0]; }
+   void SetHashTableSize(unsigned int const sz) { PkgHashTable[0] = sz; }
+   map_pointer_t GetArchitectures() const { return PkgHashTable[1]; }
+   void SetArchitectures(map_pointer_t const idx) { PkgHashTable[1] = idx; }
+#endif
+   map_pointer_t * PkgHashTableP() const { return (map_pointer_t*) (this + 1); }
+   map_pointer_t * GrpHashTableP() const { return PkgHashTableP() + GetHashTableSize(); }
 
    /** \brief Size of the complete cache file */
-   unsigned long long CacheFileSize;
+   should_be_uint64_small_t CacheFileSize;
 
    bool CheckSizes(Header &Against) const APT_PURE;
    Header();
@@ -350,7 +419,7 @@ struct pkgCache::Group
    /** \brief Link to the next Group */
    map_pointer_t Next;		// Group
    /** \brief unique sequel ID */
-   map_id_t ID;
+   should_be_map_id_t ID;
 
 };
 									/*}}}*/
@@ -387,12 +456,18 @@ struct pkgCache::Package
    map_pointer_t VersionList;       // Version
    /** \brief index to the installed version */
    map_pointer_t CurrentVer;        // Version
+   /** \brief indicates nothing (consistently)
+       This field used to contain ONE section the package belongs to,
+       if those differs between versions it is a RANDOM one.
+       The Section() method tries to reproduce it, but the only sane
+       thing to do is use the Section field from the version! */
+   APT_DEPRECATED map_ptrloc Section; // StringItem
    /** \brief index of the group this package belongs to */
    map_pointer_t Group;             // Group the Package belongs to
 
    // Linked list
    /** \brief Link to the next package in the same bucket */
-   map_pointer_t Next;       // Package
+   map_pointer_t NextPackage;       // Package
    /** \brief List of all dependencies on this package */
    map_pointer_t RevDepends;        // Dependency
    /** \brief List of all "packages" this package provide */
@@ -416,20 +491,19 @@ struct pkgCache::Package
        This allows clients to create an array of size PackageCount and use it to store
        state information for the package map. For instance the status file emitter uses
        this to track which packages have been emitted already. */
-   map_id_t ID;
+   should_be_map_id_t ID;
    /** \brief some useful indicators of the package's state */
    unsigned long Flags;
 };
 									/*}}}*/
-// Package File structure						/*{{{*/
-/** \brief stores information about the files used to generate the cache
+// Release File structure						/*{{{*/
+/** \brief stores information about the release files used to generate the cache
 
-    Package files are referenced by Version structures to be able to know
-    after the generation still from which Packages file includes this Version
-    as we need this information later on e.g. for pinning. */
-struct pkgCache::PackageFile
+    PackageFiles reference ReleaseFiles as we need to keep record of which
+    version belongs to which release e.g. for pinning. */
+struct pkgCache::ReleaseFile
 {
-   /** \brief physical disk file that this PackageFile represents */
+   /** \brief physical disk file that this ReleaseFile represents */
    map_stringitem_t FileName;
    /** \brief the release information
 
@@ -437,13 +511,47 @@ struct pkgCache::PackageFile
        release information means. */
    map_stringitem_t Archive;
    map_stringitem_t Codename;
-   map_stringitem_t Component;
    map_stringitem_t Version;
    map_stringitem_t Origin;
    map_stringitem_t Label;
-   map_stringitem_t Architecture;
    /** \brief The site the index file was fetched from */
    map_stringitem_t Site;
+
+   /** \brief Size of the file
+
+       Used together with the modification time as a
+       simple check to ensure that the Packages
+       file has not been altered since Cache generation. */
+   map_filesize_t Size;
+   /** \brief Modification time for the file */
+   time_t mtime;
+
+   /** @TODO document PackageFile::Flags */
+   unsigned long Flags;
+
+   // Linked list
+   /** \brief Link to the next ReleaseFile in the Cache */
+   map_pointer_t NextFile;
+   /** \brief unique sequel ID */
+   should_be_map_fileid_t ID;
+};
+									/*}}}*/
+// Package File structure						/*{{{*/
+/** \brief stores information about the files used to generate the cache
+
+    Package files are referenced by Version structures to be able to know
+    after the generation still from which Packages file includes this Version
+    as we need this information later on e.g. for pinning. */
+struct pkgCache::PackageFile
+{
+   /** \brief physical disk file that this PackageFile represents */
+   map_stringitem_t FileName;
+   /** \brief the release information */
+   map_pointer_t Release;
+
+   map_stringitem_t Component;
+   map_stringitem_t Architecture;
+
    /** \brief indicates what sort of index file this is
 
        @TODO enumerate at least the possible indexes */
@@ -464,7 +572,7 @@ struct pkgCache::PackageFile
    /** \brief Link to the next PackageFile in the Cache */
    map_pointer_t NextFile;        // PackageFile
    /** \brief unique sequel ID */
-   map_fileid_t ID;
+   should_be_map_fileid_t ID;
 };
 									/*}}}*/
 // VerFile structure							/*{{{*/
@@ -479,7 +587,7 @@ struct pkgCache::VerFile
    /** \brief next step in the linked list */
    map_pointer_t NextFile;       // PkgVerFile
    /** \brief position in the package file */
-   map_filesize_t Offset;         // File offset
+   should_be_map_filesize_t Offset;         // File offset
    /** @TODO document pkgCache::VerFile::Size */
    map_filesize_t Size;
 };
@@ -493,7 +601,7 @@ struct pkgCache::DescFile
    /** \brief next step in the linked list */
    map_pointer_t NextFile;       // PkgVerFile
    /** \brief position in the file */
-   map_filesize_t Offset;         // File offset
+   should_be_map_filesize_t Offset;         // File offset
    /** @TODO document pkgCache::DescFile::Size */
    map_filesize_t Size;
 };
@@ -510,12 +618,14 @@ struct pkgCache::Version
    map_stringitem_t VerStr;
    /** \brief section this version is filled in */
    map_stringitem_t Section;
+#if APT_PKG_ABI >= 413
    /** \brief source package name this version comes from
       Always contains the name, even if it is the same as the binary name */
    map_stringitem_t SourcePkgName;
    /** \brief source version this version comes from
       Always contains the version string, even if it is the same as the binary version */
    map_stringitem_t SourceVerStr;
+#endif
 
    /** \brief Multi-Arch capabilities of a package version */
    enum VerMultiArch { None = 0, /*!< is the default and doesn't trigger special behaviour */
@@ -554,16 +664,16 @@ struct pkgCache::Version
    /** \brief archive size for this version
 
        For Debian this is the size of the .deb file. */
-   uint64_t Size; // These are the .deb size
+   should_be_uint64_t Size; // These are the .deb size
    /** \brief uncompressed size for this version */
-   uint64_t InstalledSize;
+   should_be_uint64_t InstalledSize;
    /** \brief characteristic value representing this version
 
        No two packages in existence should have the same VerStr
        and Hash with different contents. */
    unsigned short Hash;
    /** \brief unique sequel ID */
-   map_id_t ID;
+   should_be_map_id_t ID;
    /** \brief parsed priority value */
    unsigned char Priority;
 };
@@ -591,7 +701,7 @@ struct pkgCache::Description
    map_pointer_t ParentPkg;         // Package
 
    /** \brief unique sequel ID */
-   map_id_t ID;
+   should_be_map_id_t ID;
 };
 									/*}}}*/
 // Dependency structure							/*{{{*/
@@ -618,7 +728,7 @@ struct pkgCache::Dependency
    map_pointer_t ParentVer;       // Version
 
    /** \brief unique sequel ID */
-   map_id_t ID;
+   should_be_map_id_t ID;
    /** \brief Dependency type - Depends, Recommends, Conflicts, etc */
    unsigned char Type;
    /** \brief comparison operator specified on the depends line
@@ -654,6 +764,15 @@ struct pkgCache::Provides
    map_pointer_t NextPkgProv;      // Provides
 };
 									/*}}}*/
+// UNUSED StringItem structure						/*{{{*/
+struct APT_DEPRECATED  pkgCache::StringItem
+{
+   /** \brief string this refers to */
+   map_ptrloc String;        // StringItem
+   /** \brief Next link in the chain */
+   map_ptrloc NextItem;      // StringItem
+};
+									/*}}}*/
 
 inline char const * pkgCache::NativeArch()
 	{ return StrP + HeaderP->Architecture; }
@@ -672,6 +791,11 @@ inline pkgCache::PkgFileIterator pkgCache::FileBegin()
        {return PkgFileIterator(*this,PkgFileP + HeaderP->FileList);}
 inline pkgCache::PkgFileIterator pkgCache::FileEnd()
        {return PkgFileIterator(*this,PkgFileP);}
+inline pkgCache::RlsFileIterator pkgCache::RlsFileBegin()
+       {return RlsFileIterator(*this,RlsFileP + HeaderP->RlsFileList);}
+inline pkgCache::RlsFileIterator pkgCache::RlsFileEnd()
+       {return RlsFileIterator(*this,RlsFileP);}
+
 
 // Oh I wish for Real Name Space Support
 class pkgCache::Namespace						/*{{{*/
@@ -683,6 +807,7 @@ class pkgCache::Namespace						/*{{{*/
    typedef pkgCache::DescIterator DescIterator;
    typedef pkgCache::DepIterator DepIterator;
    typedef pkgCache::PrvIterator PrvIterator;
+   typedef pkgCache::RlsFileIterator RlsFileIterator;
    typedef pkgCache::PkgFileIterator PkgFileIterator;
    typedef pkgCache::VerFileIterator VerFileIterator;
    typedef pkgCache::Version Version;

+ 200 - 66
apt-pkg/pkgcachegen.cc

@@ -54,10 +54,8 @@ using std::string;
 /* We set the dirty flag and make sure that is written to the disk */
 pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) :
 		    Map(*pMap), Cache(pMap,false), Progress(Prog),
-		    FoundFileDeps(0)
+		     CurrentRlsFile(NULL), CurrentFile(NULL), FoundFileDeps(0)
 {
-   CurrentFile = 0;
-
    if (_error->PendingError() == true)
       return;
 
@@ -74,7 +72,7 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) :
       *Cache.HeaderP = pkgCache::Header();
 
       // make room for the hashtables for packages and groups
-      if (Map.RawAllocate(2 * (Cache.HeaderP->HashTableSize * sizeof(map_pointer_t))) == 0)
+      if (Map.RawAllocate(2 * (Cache.HeaderP->GetHashTableSize() * sizeof(map_pointer_t))) == 0)
 	 return;
 
       map_stringitem_t const idxVerSysName = WriteStringInMap(_system->VS->Label);
@@ -96,10 +94,10 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) :
 	 map_stringitem_t const idxArchitectures = WriteStringInMap(list);
 	 if (unlikely(idxArchitectures == 0))
 	    return;
-	 Cache.HeaderP->Architectures = idxArchitectures;
+	 Cache.HeaderP->SetArchitectures(idxArchitectures);
       }
       else
-	 Cache.HeaderP->Architectures = idxArchitecture;
+	 Cache.HeaderP->SetArchitectures(idxArchitecture);
 
       Cache.ReMap();
    }
@@ -145,6 +143,7 @@ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newM
    Cache.ReMap(false);
 
    CurrentFile += (pkgCache::PackageFile const * const) newMap - (pkgCache::PackageFile const * const) oldMap;
+   CurrentRlsFile += (pkgCache::ReleaseFile const * const) newMap - (pkgCache::ReleaseFile const * const) oldMap;
 
    for (std::vector<pkgCache::GrpIterator*>::const_iterator i = Dynamic<pkgCache::GrpIterator>::toReMap.begin();
 	i != Dynamic<pkgCache::GrpIterator>::toReMap.end(); ++i)
@@ -167,6 +166,9 @@ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newM
    for (std::vector<pkgCache::PkgFileIterator*>::const_iterator i = Dynamic<pkgCache::PkgFileIterator>::toReMap.begin();
 	i != Dynamic<pkgCache::PkgFileIterator>::toReMap.end(); ++i)
       (*i)->ReMap(oldMap, newMap);
+   for (std::vector<pkgCache::RlsFileIterator*>::const_iterator i = Dynamic<pkgCache::RlsFileIterator>::toReMap.begin();
+	i != Dynamic<pkgCache::RlsFileIterator>::toReMap.end(); ++i)
+      (*i)->ReMap(oldMap, newMap);
 }									/*}}}*/
 // CacheGenerator::WriteStringInMap					/*{{{*/
 map_stringitem_t pkgCacheGenerator::WriteStringInMap(const char *String,
@@ -616,7 +618,7 @@ bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator &Grp, const string &Name)
 
    // Insert it into the hash table
    unsigned long const Hash = Cache.Hash(Name);
-   map_pointer_t *insertAt = &Cache.HeaderP->GrpHashTable()[Hash];
+   map_pointer_t *insertAt = &Cache.HeaderP->GrpHashTableP()[Hash];
    while (*insertAt != 0 && strcasecmp(Name.c_str(), Cache.StrP + (Cache.GrpP + *insertAt)->Name) > 0)
       insertAt = &(Cache.GrpP + *insertAt)->Next;
    Grp->Next = *insertAt;
@@ -652,30 +654,23 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name
       Grp->FirstPackage = Package;
       // Insert it into the hash table
       map_id_t const Hash = Cache.Hash(Name);
-      map_pointer_t *insertAt = &Cache.HeaderP->PkgHashTable()[Hash];
+      map_pointer_t *insertAt = &Cache.HeaderP->PkgHashTableP()[Hash];
       while (*insertAt != 0 && strcasecmp(Name.c_str(), Cache.StrP + (Cache.GrpP + (Cache.PkgP + *insertAt)->Group)->Name) > 0)
-	 insertAt = &(Cache.PkgP + *insertAt)->Next;
-      Pkg->Next = *insertAt;
+	 insertAt = &(Cache.PkgP + *insertAt)->NextPackage;
+      Pkg->NextPackage = *insertAt;
       *insertAt = Package;
    }
    else // Group the Packages together
    {
       // this package is the new last package
       pkgCache::PkgIterator LastPkg(Cache, Cache.PkgP + Grp->LastPackage);
-      Pkg->Next = LastPkg->Next;
-      LastPkg->Next = Package;
+      Pkg->NextPackage = LastPkg->NextPackage;
+      LastPkg->NextPackage = Package;
    }
    Grp->LastPackage = Package;
 
    // Set the name, arch and the ID
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-   Pkg->Name = Grp->Name;
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+   APT_IGNORE_DEPRECATED(Pkg->Name = Grp->Name;)
    Pkg->Group = Grp.Index();
    // all is mapped to the native architecture
    map_stringitem_t const idxArch = (Arch == "all") ? Cache.HeaderP->Architecture : StoreString(MIXED, Arch);
@@ -1079,13 +1074,48 @@ bool pkgCacheGenerator::ListParser::SameVersion(unsigned short const Hash,/*{{{*
    return Hash == Ver->Hash;
 }
 									/*}}}*/
+// CacheGenerator::SelectReleaseFile - Select the current release file the indexes belong to	/*{{{*/
+bool pkgCacheGenerator::SelectReleaseFile(const string &File,const string &Site,
+				   unsigned long Flags)
+{
+   if (File.empty() && Site.empty())
+   {
+      CurrentRlsFile = NULL;
+      return true;
+   }
+
+   // Get some space for the structure
+   map_pointer_t const idxFile = AllocateInMap(sizeof(*CurrentRlsFile));
+   if (unlikely(idxFile == 0))
+      return false;
+   CurrentRlsFile = Cache.RlsFileP + idxFile;
+
+   // Fill it in
+   map_stringitem_t const idxFileName = WriteStringInMap(File);
+   map_stringitem_t const idxSite = StoreString(MIXED, Site);
+   if (unlikely(idxFileName == 0 || idxSite == 0))
+      return false;
+   CurrentRlsFile->FileName = idxFileName;
+   CurrentRlsFile->Site = idxSite;
+   CurrentRlsFile->NextFile = Cache.HeaderP->RlsFileList;
+   CurrentRlsFile->Flags = Flags;
+   CurrentRlsFile->ID = Cache.HeaderP->ReleaseFileCount;
+   RlsFileName = File;
+   Cache.HeaderP->RlsFileList = CurrentRlsFile - Cache.RlsFileP;
+   Cache.HeaderP->ReleaseFileCount++;
+
+   return true;
+}
+									/*}}}*/
 // CacheGenerator::SelectFile - Select the current file being parsed	/*{{{*/
 // ---------------------------------------------------------------------
 /* This is used to select which file is to be associated with all newly
    added versions. The caller is responsible for setting the IMS fields. */
-bool pkgCacheGenerator::SelectFile(const string &File,const string &Site,
-				   const pkgIndexFile &Index,
-				   unsigned long Flags)
+bool pkgCacheGenerator::SelectFile(std::string const &File,
+				   pkgIndexFile const &Index,
+				   std::string const &Architecture,
+				   std::string const &Component,
+				   unsigned long const Flags)
 {
    // Get some space for the structure
    map_pointer_t const idxFile = AllocateInMap(sizeof(*CurrentFile));
@@ -1095,18 +1125,33 @@ bool pkgCacheGenerator::SelectFile(const string &File,const string &Site,
 
    // Fill it in
    map_stringitem_t const idxFileName = WriteStringInMap(File);
-   map_stringitem_t const idxSite = StoreString(MIXED, Site);
-   if (unlikely(idxFileName == 0 || idxSite == 0))
+   if (unlikely(idxFileName == 0))
       return false;
    CurrentFile->FileName = idxFileName;
-   CurrentFile->Site = idxSite;
    CurrentFile->NextFile = Cache.HeaderP->FileList;
-   CurrentFile->Flags = Flags;
    CurrentFile->ID = Cache.HeaderP->PackageFileCount;
    map_stringitem_t const idxIndexType = StoreString(MIXED, Index.GetType()->Label);
    if (unlikely(idxIndexType == 0))
       return false;
    CurrentFile->IndexType = idxIndexType;
+   if (Architecture.empty())
+      CurrentFile->Architecture = 0;
+   else
+   {
+      map_stringitem_t const arch = StoreString(pkgCacheGenerator::MIXED, Architecture);
+      if (unlikely(arch == 0))
+	 return false;
+      CurrentFile->Architecture = arch;
+   }
+   map_stringitem_t const component = StoreString(pkgCacheGenerator::MIXED, Component);
+   if (unlikely(component == 0))
+      return false;
+   CurrentFile->Component = component;
+   CurrentFile->Flags = Flags;
+   if (CurrentRlsFile != NULL)
+      CurrentFile->Release = CurrentRlsFile - Cache.RlsFileP;
+   else
+      CurrentFile->Release = 0;
    PkgFileName = File;
    Cache.HeaderP->FileList = CurrentFile - Cache.PkgFileP;
    Cache.HeaderP->PackageFileCount++;
@@ -1181,35 +1226,59 @@ static bool CheckValidity(const string &CacheFile,
       _error->Discard();
       return false;
    }
-   
+
+   SPtrArray<bool> RlsVisited = new bool[Cache.HeaderP->ReleaseFileCount];
+   memset(RlsVisited,0,sizeof(*RlsVisited)*Cache.HeaderP->ReleaseFileCount);
+   std::vector<pkgIndexFile *> Files;
+   for (pkgSourceList::const_iterator i = List.begin(); i != List.end(); ++i)
+   {
+      if (Debug == true)
+	 std::clog << "Checking RlsFile " << (*i)->Describe() << ": ";
+      pkgCache::RlsFileIterator const RlsFile = (*i)->FindInCache(Cache, true);
+      if (RlsFile.end() == true)
+      {
+	 if (Debug == true)
+	    std::clog << "FindInCache returned end-Pointer" << std::endl;
+	 return false;
+      }
+
+      RlsVisited[RlsFile->ID] = true;
+      if (Debug == true)
+	 std::clog << "with ID " << RlsFile->ID << " is valid" << std::endl;
+
+      std::vector <pkgIndexFile *> *Indexes = (*i)->GetIndexFiles();
+      for (std::vector<pkgIndexFile *>::const_iterator j = Indexes->begin(); j != Indexes->end(); ++j)
+	 if ((*j)->HasPackages())
+	    Files.push_back (*j);
+   }
+   for (unsigned I = 0; I != Cache.HeaderP->ReleaseFileCount; ++I)
+      if (RlsVisited[I] == false)
+      {
+	 if (Debug == true)
+	    std::clog << "RlsFile with ID" << I << " wasn't visited" << std::endl;
+	 return false;
+      }
+
+   for (; Start != End; ++Start)
+      Files.push_back(*Start);
+
    /* Now we check every index file, see if it is in the cache,
       verify the IMS data and check that it is on the disk too.. */
    SPtrArray<bool> Visited = new bool[Cache.HeaderP->PackageFileCount];
    memset(Visited,0,sizeof(*Visited)*Cache.HeaderP->PackageFileCount);
-   for (; Start != End; ++Start)
+   for (std::vector<pkgIndexFile *>::const_reverse_iterator PkgFile = Files.rbegin(); PkgFile != Files.rend(); ++PkgFile)
    {
       if (Debug == true)
-	 std::clog << "Checking PkgFile " << (*Start)->Describe() << ": ";
-      if ((*Start)->HasPackages() == false)
-      {
-         if (Debug == true)
-	    std::clog << "Has NO packages" << std::endl;
-	 continue;
-      }
-    
-      if ((*Start)->Exists() == false)
+	 std::clog << "Checking PkgFile " << (*PkgFile)->Describe() << ": ";
+      if ((*PkgFile)->Exists() == false)
       {
-#if 0 // mvo: we no longer give a message here (Default Sources spec)
-	 _error->WarningE("stat",_("Couldn't stat source package list %s"),
-			  (*Start)->Describe().c_str());
-#endif
          if (Debug == true)
 	    std::clog << "file doesn't exist" << std::endl;
 	 continue;
       }
 
       // FindInCache is also expected to do an IMS check.
-      pkgCache::PkgFileIterator File = (*Start)->FindInCache(Cache);
+      pkgCache::PkgFileIterator File = (*PkgFile)->FindInCache(Cache);
       if (File.end() == true)
       {
 	 if (Debug == true)
@@ -1221,15 +1290,15 @@ static bool CheckValidity(const string &CacheFile,
       if (Debug == true)
 	 std::clog << "with ID " << File->ID << " is valid" << std::endl;
    }
-   
+
    for (unsigned I = 0; I != Cache.HeaderP->PackageFileCount; I++)
       if (Visited[I] == false)
       {
 	 if (Debug == true)
-	    std::clog << "File with ID" << I << " wasn't visited" << std::endl;
+	    std::clog << "PkgFile with ID" << I << " wasn't visited" << std::endl;
 	 return false;
       }
-   
+
    if (_error->PendingError() == true)
    {
       if (Debug == true)
@@ -1250,9 +1319,20 @@ static bool CheckValidity(const string &CacheFile,
 // ---------------------------------------------------------------------
 /* Size is kind of an abstract notion that is only used for the progress
    meter */
-static map_filesize_t ComputeSize(FileIterator Start,FileIterator End)
+static map_filesize_t ComputeSize(pkgSourceList const * const List, FileIterator Start,FileIterator End)
 {
    map_filesize_t TotalSize = 0;
+   if (List !=  NULL)
+   {
+      for (pkgSourceList::const_iterator i = List->begin(); i != List->end(); ++i)
+      {
+	 std::vector <pkgIndexFile *> *Indexes = (*i)->GetIndexFiles();
+	 for (std::vector<pkgIndexFile *>::const_iterator j = Indexes->begin(); j != Indexes->end(); ++j)
+	    if ((*j)->HasPackages() == true)
+	       TotalSize += (*j)->Size();
+      }
+   }
+
    for (; Start < End; ++Start)
    {
       if ((*Start)->HasPackages() == false)
@@ -1268,11 +1348,63 @@ static map_filesize_t ComputeSize(FileIterator Start,FileIterator End)
 static bool BuildCache(pkgCacheGenerator &Gen,
 		       OpProgress *Progress,
 		       map_filesize_t &CurrentSize,map_filesize_t TotalSize,
+		       pkgSourceList const * const List,
 		       FileIterator Start, FileIterator End)
 {
+   std::vector<pkgIndexFile *> Files;
+   bool const HasFileDeps = Gen.HasFileDeps();
+
+   if (List !=  NULL)
+   {
+      for (pkgSourceList::const_iterator i = List->begin(); i != List->end(); ++i)
+      {
+	 if ((*i)->FindInCache(Gen.GetCache(), false).end() == false)
+	 {
+	    _error->Warning("Duplicate sources.list entry %s",
+		  (*i)->Describe().c_str());
+	    continue;
+	 }
+
+	 if ((*i)->Merge(Gen, Progress) == false)
+	    return false;
+
+	 std::vector <pkgIndexFile *> *Indexes = (*i)->GetIndexFiles();
+	 for (std::vector<pkgIndexFile *>::const_iterator I = Indexes->begin(); I != Indexes->end(); ++I)
+	 {
+	    if (HasFileDeps)
+	       Files.push_back(*I);
+
+	    if ((*I)->HasPackages() == false)
+	       continue;
+
+	    if ((*I)->Exists() == false)
+	       continue;
+
+	    if ((*I)->FindInCache(Gen.GetCache()).end() == false)
+	    {
+	       _error->Warning("Duplicate sources.list entry %s",
+		     (*I)->Describe().c_str());
+	       continue;
+	    }
+
+	    map_filesize_t Size = (*I)->Size();
+	    if (Progress != NULL)
+	       Progress->OverallProgress(CurrentSize,TotalSize,Size,_("Reading package lists"));
+	    CurrentSize += Size;
+
+	    if ((*I)->Merge(Gen,Progress) == false)
+	       return false;
+	 }
+      }
+   }
+
+   Gen.SelectReleaseFile("", "");
    FileIterator I;
    for (I = Start; I != End; ++I)
    {
+      if (HasFileDeps)
+	 Files.push_back(*I);
+
       if ((*I)->HasPackages() == false)
 	 continue;
       
@@ -1295,13 +1427,13 @@ static bool BuildCache(pkgCacheGenerator &Gen,
 	 return false;
    }   
 
-   if (Gen.HasFileDeps() == true)
+   if (HasFileDeps == true)
    {
       if (Progress != NULL)
 	 Progress->Done();
-      TotalSize = ComputeSize(Start, End);
+      TotalSize = ComputeSize(List, Start, End);
       CurrentSize = 0;
-      for (I = Start; I != End; ++I)
+      for (std::vector<pkgIndexFile *>::const_iterator I = Files.begin(); I != Files.end(); ++I)
       {
 	 map_filesize_t Size = (*I)->Size();
 	 if (Progress != NULL)
@@ -1346,6 +1478,7 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress
    bool const Debug = _config->FindB("Debug::pkgCacheGen", false);
 
    std::vector<pkgIndexFile *> Files;
+   /*
    for (std::vector<metaIndex *>::const_iterator i = List.begin();
         i != List.end();
         ++i)
@@ -1356,8 +1489,7 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress
 	   ++j)
          Files.push_back (*j);
    }
-   
-   map_filesize_t const EndOfSource = Files.size();
+*/
    if (_system->AddStatusFiles(Files) == false)
       return false;
 
@@ -1449,8 +1581,8 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress
    // Lets try the source cache.
    map_filesize_t CurrentSize = 0;
    map_filesize_t TotalSize = 0;
-   if (CheckValidity(SrcCacheFile, List, Files.begin(),
-		     Files.begin()+EndOfSource) == true)
+   if (CheckValidity(SrcCacheFile, List, Files.end(),
+		     Files.end()) == true)
    {
       if (Debug == true)
 	 std::clog << "srcpkgcache.bin is valid - populate MMap with it." << std::endl;
@@ -1462,28 +1594,28 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress
 				SCacheF.Size()) == false)
 	 return false;
 
-      TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end());
+      TotalSize = ComputeSize(NULL, Files.begin(), Files.end());
 
       // Build the status cache
       pkgCacheGenerator Gen(Map.Get(),Progress);
       if (_error->PendingError() == true)
 	 return false;
-      if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
-		     Files.begin()+EndOfSource,Files.end()) == false)
+      if (BuildCache(Gen, Progress, CurrentSize, TotalSize, NULL,
+		     Files.begin(),Files.end()) == false)
 	 return false;
    }
    else
    {
       if (Debug == true)
 	 std::clog << "srcpkgcache.bin is NOT valid - rebuild" << std::endl;
-      TotalSize = ComputeSize(Files.begin(),Files.end());
+      TotalSize = ComputeSize(&List, Files.begin(),Files.end());
       
       // Build the source cache
       pkgCacheGenerator Gen(Map.Get(),Progress);
       if (_error->PendingError() == true)
 	 return false;
-      if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
-		     Files.begin(),Files.begin()+EndOfSource) == false)
+      if (BuildCache(Gen, Progress, CurrentSize, TotalSize, &List,
+		     Files.end(),Files.end()) == false)
 	 return false;
       
       // Write it back
@@ -1510,8 +1642,8 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress
       }
       
       // Build the status cache
-      if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
-		     Files.begin()+EndOfSource,Files.end()) == false)
+      if (BuildCache(Gen, Progress, CurrentSize, TotalSize, NULL,
+		     Files.begin(), Files.end()) == false)
 	 return false;
    }
    if (Debug == true)
@@ -1543,7 +1675,6 @@ APT_DEPRECATED bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **Ou
 bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap)
 {
    std::vector<pkgIndexFile *> Files;
-   map_filesize_t EndOfSource = Files.size();
    if (_system->AddStatusFiles(Files) == false)
       return false;
 
@@ -1551,7 +1682,7 @@ bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **O
    map_filesize_t CurrentSize = 0;
    map_filesize_t TotalSize = 0;
    
-   TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end());
+   TotalSize = ComputeSize(NULL, Files.begin(), Files.end());
    
    // Build the status cache
    if (Progress != NULL)
@@ -1559,8 +1690,8 @@ bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **O
    pkgCacheGenerator Gen(Map.Get(),Progress);
    if (_error->PendingError() == true)
       return false;
-   if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
-		  Files.begin()+EndOfSource,Files.end()) == false)
+   if (BuildCache(Gen,Progress,CurrentSize,TotalSize, NULL,
+		  Files.begin(), Files.end()) == false)
       return false;
 
    if (_error->PendingError() == true)
@@ -1589,3 +1720,6 @@ bool pkgCacheGenerator::FinishCache(OpProgress * /*Progress*/)
    return true;
 }
 									/*}}}*/
+
+pkgCacheGenerator::ListParser::ListParser() : Owner(NULL), OldDepLast(NULL), FoundFileDeps(false) {}
+pkgCacheGenerator::ListParser::~ListParser() {}

+ 20 - 17
apt-pkg/pkgcachegen.h

@@ -1,6 +1,5 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: pkgcachegen.h,v 1.19 2002/07/08 03:13:30 jgg Exp $
 /* ######################################################################
    
    Package Cache Generator - Generator for the cache structure.
@@ -34,7 +33,7 @@ class pkgSourceList;
 class OpProgress;
 class pkgIndexFile;
 
-class pkgCacheGenerator							/*{{{*/
+class APT_HIDDEN pkgCacheGenerator					/*{{{*/
 {
    private:
    APT_HIDDEN map_stringitem_t WriteStringInMap(std::string const &String) { return WriteStringInMap(String.c_str()); };
@@ -69,7 +68,9 @@ class pkgCacheGenerator							/*{{{*/
    DynamicMMap &Map;
    pkgCache Cache;
    OpProgress *Progress;
-   
+
+   std::string RlsFileName;
+   pkgCache::ReleaseFile *CurrentRlsFile;
    std::string PkgFileName;
    pkgCache::PackageFile *CurrentFile;
 
@@ -100,28 +101,31 @@ class pkgCacheGenerator							/*{{{*/
    inline map_stringitem_t StoreString(enum StringType const type, const std::string &S) {return StoreString(type, S.c_str(),S.length());};
 
    void DropProgress() {Progress = 0;};
-   bool SelectFile(const std::string &File,const std::string &Site,pkgIndexFile const &Index,
-		   unsigned long Flags = 0);
+   bool SelectFile(const std::string &File,pkgIndexFile const &Index, std::string const &Architecture, std::string const &Component, unsigned long Flags = 0);
+   bool SelectReleaseFile(const std::string &File, const std::string &Site, unsigned long Flags = 0);
    bool MergeList(ListParser &List,pkgCache::VerIterator *Ver = 0);
    inline pkgCache &GetCache() {return Cache;};
    inline pkgCache::PkgFileIterator GetCurFile() 
          {return pkgCache::PkgFileIterator(Cache,CurrentFile);};
+   inline pkgCache::RlsFileIterator GetCurRlsFile() 
+         {return pkgCache::RlsFileIterator(Cache,CurrentRlsFile);};
 
    bool HasFileDeps() {return FoundFileDeps;};
    bool MergeFileProvides(ListParser &List);
    bool FinishCache(OpProgress *Progress) APT_DEPRECATED APT_CONST;
 
-   static bool MakeStatusCache(pkgSourceList &List,OpProgress *Progress,
+   APT_PUBLIC static bool MakeStatusCache(pkgSourceList &List,OpProgress *Progress,
 			MMap **OutMap = 0,bool AllowMem = false);
-   static bool MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap);
-   static DynamicMMap* CreateDynamicMMap(FileFd *CacheF, unsigned long Flags = 0);
+   APT_PUBLIC static bool MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap);
+   APT_PUBLIC static DynamicMMap* CreateDynamicMMap(FileFd *CacheF, unsigned long Flags = 0);
 
    void ReMap(void const * const oldMap, void const * const newMap);
 
    pkgCacheGenerator(DynamicMMap *Map,OpProgress *Progress);
-   ~pkgCacheGenerator();
+   virtual ~pkgCacheGenerator();
 
    private:
+   void *d;
    APT_HIDDEN bool MergeListGroup(ListParser &List, std::string const &GrpName);
    APT_HIDDEN bool MergeListPackage(ListParser &List, pkgCache::PkgIterator &Pkg);
    APT_HIDDEN bool MergeListVersion(ListParser &List, pkgCache::PkgIterator &Pkg,
@@ -136,7 +140,7 @@ class pkgCacheGenerator							/*{{{*/
 };
 									/*}}}*/
 // This is the abstract package list parser class.			/*{{{*/
-class pkgCacheGenerator::ListParser
+class APT_HIDDEN pkgCacheGenerator::ListParser
 {
    pkgCacheGenerator *Owner;
    friend class pkgCacheGenerator;
@@ -147,7 +151,9 @@ class pkgCacheGenerator::ListParser
 
    // Flag file dependencies
    bool FoundFileDeps;
-      
+
+   void *d;
+
    protected:
 
    inline map_stringitem_t StoreString(pkgCacheGenerator::StringType const type, std::string const &S) {return Owner->StoreString(type, S);};
@@ -178,10 +184,7 @@ class pkgCacheGenerator::ListParser
     * \param Hash of the currently parsed version
     * \param Ver to compare with
     */
-#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
-   virtual
-#endif
-      APT_PURE bool SameVersion(unsigned short const Hash, pkgCache::VerIterator const &Ver);
+   virtual bool SameVersion(unsigned short const Hash, pkgCache::VerIterator const &Ver);
    virtual bool UsePackage(pkgCache::PkgIterator &Pkg,
 			   pkgCache::VerIterator &Ver) = 0;
    virtual map_filesize_t Offset() = 0;
@@ -193,8 +196,8 @@ class pkgCacheGenerator::ListParser
    virtual bool CollectFileProvides(pkgCache &/*Cache*/,
 				    pkgCache::VerIterator &/*Ver*/) {return true;};
 
-   ListParser() : Owner(NULL), OldDepLast(NULL), FoundFileDeps(false) {};
-   virtual ~ListParser() {};
+   ListParser();
+   virtual ~ListParser();
 };
 									/*}}}*/
 

+ 3 - 0
apt-pkg/pkgrecords.cc

@@ -76,3 +76,6 @@ pkgRecords::Parser &pkgRecords::Lookup(pkgCache::DescFileIterator const &Desc)
    return *Files[Desc.File()->ID];
 }
 									/*}}}*/
+
+pkgRecords::Parser::Parser() {}
+pkgRecords::Parser::~Parser() {}

+ 12 - 3
apt-pkg/pkgrecords.h

@@ -43,7 +43,7 @@ class pkgRecords							/*{{{*/
 
    // Construct destruct
    pkgRecords(pkgCache &Cache);
-   ~pkgRecords();
+   virtual ~pkgRecords();
 };
 									/*}}}*/
 class pkgRecords::Parser						/*{{{*/
@@ -68,10 +68,17 @@ class pkgRecords::Parser						/*{{{*/
     * choose the hash to be used.
     */
    virtual HashStringList Hashes() const { return HashStringList(); };
+#if APT_PKG_ABI >= 413
    APT_DEPRECATED std::string MD5Hash() const { return GetHashFromHashes("MD5Sum"); };
    APT_DEPRECATED std::string SHA1Hash() const { return GetHashFromHashes("SHA1"); };
    APT_DEPRECATED std::string SHA256Hash() const { return GetHashFromHashes("SHA256"); };
    APT_DEPRECATED std::string SHA512Hash() const { return GetHashFromHashes("SHA512"); };
+#else
+   APT_DEPRECATED std::string MD5Hash() { return GetHashFromHashes("MD5Sum"); };
+   APT_DEPRECATED std::string SHA1Hash() { return GetHashFromHashes("SHA1"); };
+   APT_DEPRECATED std::string SHA256Hash() { return GetHashFromHashes("SHA256"); };
+   APT_DEPRECATED std::string SHA512Hash() { return GetHashFromHashes("SHA512"); };
+#endif
 
    // These are some general stats about the package
    virtual std::string Maintainer() {return std::string();};
@@ -99,10 +106,12 @@ class pkgRecords::Parser						/*{{{*/
 
    // The record in binary form
    virtual void GetRec(const char *&Start,const char *&Stop) {Start = Stop = 0;};
-   
-   virtual ~Parser() {};
+
+   Parser();
+   virtual ~Parser();
 
    private:
+   void *d;
    APT_HIDDEN std::string GetHashFromHashes(char const * const type) const
    {
       HashStringList const hashes = Hashes();

+ 2 - 0
apt-pkg/pkgsystem.cc

@@ -45,3 +45,5 @@ APT_PURE pkgSystem *pkgSystem::GetSystem(const char *Label)
    return 0;   
 }
 									/*}}}*/
+
+pkgSystem::~pkgSystem() {}

+ 3 - 2
apt-pkg/pkgsystem.h

@@ -1,6 +1,5 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: pkgsystem.h,v 1.6 2002/11/11 06:55:50 doogie Exp $
 /* ######################################################################
 
    System - Abstraction for running on different systems.
@@ -93,7 +92,9 @@ class pkgSystem
    };
    
    pkgSystem();
-   virtual ~pkgSystem() {};
+   virtual ~pkgSystem();
+   private:
+   void *d;
 };
 
 // The environment we are operating in.

+ 29 - 54
apt-pkg/policy.cc

@@ -4,22 +4,12 @@
 /* ######################################################################
 
    Package Version Policy implementation
-   
+
    This is just a really simple wrapper around pkgVersionMatch with
    some added goodies to manage the list of things..
-   
-   Priority Table:
-   
-   1000 -> inf = Downgradeable priorities
-   1000        = The 'no downgrade' pseduo-status file
-   100 -> 1000 = Standard priorities
-   990         = Config file override package files
-   989         = Start for preference auto-priorities
-   500         = Default package files
-   100         = The status file and ButAutomaticUpgrades sources
-   0 -> 100    = NotAutomatic sources like experimental
-   -inf -> 0   = Never selected   
-   
+
+   See man apt_preferences for what value means what.
+
    ##################################################################### */
 									/*}}}*/
 // Include Files							/*{{{*/
@@ -56,7 +46,7 @@ using namespace std;
    file matches the V0 policy engine. */
 pkgPolicy::pkgPolicy(pkgCache *Owner) : Pins(0), PFPriority(0), Cache(Owner)
 {
-   if (Owner == 0 || &(Owner->Head()) == 0)
+   if (Owner == 0)
       return;
    PFPriority = new signed short[Owner->Head().PackageFileCount];
    Pins = new Pin[Owner->Head().PackageCount];
@@ -73,9 +63,9 @@ pkgPolicy::pkgPolicy(pkgCache *Owner) : Pins(0), PFPriority(0), Cache(Owner)
       pkgVersionMatch vm("", pkgVersionMatch::None);
       for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); ++F)
       {
-	 if ((F->Archive != 0 && vm.ExpressionMatches(DefRel, F.Archive()) == true) ||
-	     (F->Codename != 0 && vm.ExpressionMatches(DefRel, F.Codename()) == true) ||
-	     (F->Version != 0 && vm.ExpressionMatches(DefRel, F.Version()) == true) ||
+	 if (vm.ExpressionMatches(DefRel, F.Archive()) ||
+	     vm.ExpressionMatches(DefRel, F.Codename()) ||
+	     vm.ExpressionMatches(DefRel, F.Version()) ||
 	     (DefRel.length() > 2 && DefRel[1] == '='))
 	    found = true;
       }
@@ -96,48 +86,40 @@ bool pkgPolicy::InitDefaults()
    for (pkgCache::PkgFileIterator I = Cache->FileBegin(); I != Cache->FileEnd(); ++I)
    {
       PFPriority[I->ID] = 500;
-      if ((I->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource)
+      if (I.Flagged(pkgCache::Flag::NotSource))
 	 PFPriority[I->ID] = 100;
-      else if ((I->Flags & pkgCache::Flag::ButAutomaticUpgrades) == pkgCache::Flag::ButAutomaticUpgrades)
+      else if (I.Flagged(pkgCache::Flag::ButAutomaticUpgrades))
 	 PFPriority[I->ID] = 100;
-      else if ((I->Flags & pkgCache::Flag::NotAutomatic) == pkgCache::Flag::NotAutomatic)
+      else if (I.Flagged(pkgCache::Flag::NotAutomatic))
 	 PFPriority[I->ID] = 1;
    }
 
    // Apply the defaults..
    SPtrArray<bool> Fixed = new bool[Cache->HeaderP->PackageFileCount];
    memset(Fixed,0,sizeof(*Fixed)*Cache->HeaderP->PackageFileCount);
-   signed Cur = 989;
    StatusOverride = false;
-   for (vector<Pin>::const_iterator I = Defaults.begin(); I != Defaults.end();
-	++I, --Cur)
+   for (vector<Pin>::const_iterator I = Defaults.begin(); I != Defaults.end(); ++I)
    {
       pkgVersionMatch Match(I->Data,I->Type);
       for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); ++F)
       {
-	 if (Match.FileMatch(F) == true && Fixed[F->ID] == false)
+	 if (Fixed[F->ID] == false && Match.FileMatch(F) == true)
 	 {
-	    if (I->Priority != 0 && I->Priority > 0)
-	       Cur = I->Priority;
-	    
-	    if (I->Priority < 0)
-	       PFPriority[F->ID] =  I->Priority;
-	    else
-	       PFPriority[F->ID] = Cur;
-	    
-	    if (PFPriority[F->ID] > 1000)
+	    PFPriority[F->ID] = I->Priority;
+
+	    if (PFPriority[F->ID] >= 1000)
 	       StatusOverride = true;
-	    
+
 	    Fixed[F->ID] = true;
-	 }      
-      }      
+	 }
+      }
    }
 
    if (_config->FindB("Debug::pkgPolicy",false) == true)
       for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); ++F)
-	 std::clog << "Prio of " << F.FileName() << ' ' << PFPriority[F->ID] << std::endl; 
-   
-   return true;   
+	 std::clog << "Prio of " << F.FileName() << ' ' << PFPriority[F->ID] << std::endl;
+
+   return true;
 }
 									/*}}}*/
 // Policy::GetCandidateVer - Get the candidate install version		/*{{{*/
@@ -166,9 +148,7 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator const &Pk
       effectively excludes everything <= 0 which are the non-automatic
       priorities.. The status file is given a prio of 100 which will exclude
       not-automatic sources, except in a single shot not-installed mode.
-      The second pseduo-status file is at prio 1000, above which will permit
-      the user to force-downgrade things.
-      
+
       The user pin is subject to the same priority rules as default 
       selections. Thus there are two ways to create a pin - a pin that
       tracks the default when the default is taken away, and a permanent
@@ -190,8 +170,7 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator const &Pk
 	    then it is not a candidate for installation, ever. This weeds
 	    out bogus entries that may be due to config-file states, or
 	    other. */
-	 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource &&
-	     instVer == false)
+	 if (VF.File().Flagged(pkgCache::Flag::NotSource) && instVer == false)
 	    continue;
 
 	 signed Prio = PFPriority[VF.File()->ID];
@@ -218,9 +197,9 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator const &Pk
 	    Pref = Ver;
 	    PrefSeen = true;
 	 }
-	 /* Elevate our current selection (or the status file itself)
-	    to the Pseudo-status priority. */
-	 Max = 1000;
+	 /* Elevate our current selection (or the status file itself) so that only
+	    a downgrade can override it from now on */
+	 Max = 999;
 
 	 // Fast path optimize.
 	 if (StatusOverride == false)
@@ -336,13 +315,7 @@ pkgCache::VerIterator pkgPolicy::GetMatch(pkgCache::PkgIterator const &Pkg)
 APT_PURE signed short pkgPolicy::GetPriority(pkgCache::PkgIterator const &Pkg)
 {
    if (Pins[Pkg->ID].Type != pkgVersionMatch::None)
-   {
-      // In this case 0 means default priority
-      if (Pins[Pkg->ID].Priority == 0)
-	 return 989;
       return Pins[Pkg->ID].Priority;
-   }
-   
    return 0;
 }
 APT_PURE signed short pkgPolicy::GetPriority(pkgCache::PkgFileIterator const &File)
@@ -466,3 +439,5 @@ bool ReadPinFile(pkgPolicy &Plcy,string File)
    return true;
 }
 									/*}}}*/
+
+pkgPolicy::~pkgPolicy() {delete [] PFPriority; delete [] Pins;}

+ 3 - 2
apt-pkg/policy.h

@@ -1,6 +1,5 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: policy.h,v 1.4 2001/05/07 04:24:08 jgg Exp $
 /* ######################################################################
 
    Package Version Policy implementation
@@ -85,7 +84,9 @@ class pkgPolicy : public pkgDepCache::Policy
    bool InitDefaults();
    
    pkgPolicy(pkgCache *Owner);
-   virtual ~pkgPolicy() {delete [] PFPriority; delete [] Pins;};
+   virtual ~pkgPolicy();
+   private:
+   void *d;
 };
 
 bool ReadPinFile(pkgPolicy &Plcy, std::string File = "");

+ 1 - 1
apt-pkg/sourcelist.cc

@@ -331,7 +331,7 @@ bool pkgSourceList::ParseFileOldStyle(string File)
 {
    // Open the stream for reading
    ifstream F(File.c_str(),ios::in /*| ios::nocreate*/);
-   if (!F != 0)
+   if (F.fail() == true)
       return _error->Errno("ifstream::ifstream",_("Opening %s"),File.c_str());
 
    // CNC:2003-12-10 - 300 is too short.

+ 12 - 16
apt-pkg/sourcelist.h

@@ -1,6 +1,5 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: sourcelist.h,v 1.12.2.1 2003/12/24 23:09:17 mdz Exp $
 /* ######################################################################
 
    SourceList - Manage a list of sources
@@ -52,23 +51,16 @@ class pkgAcquire;
 class pkgIndexFile;
 class metaIndex;
 
-class pkgSource
-{
-   protected:
-
-   std::vector<metaIndex *> SrcList;
-
-};
-
-class pkgSourceList : public pkgSource
+class pkgSourceList
 {
+   void *d;
    public:
-   
+
    // List of supported source list types
    class Type
    {
       public:
-      
+
       // Global list of Items supported
       static Type **GlobalList;
       static unsigned long GlobalListLen;
@@ -91,14 +83,18 @@ class pkgSourceList : public pkgSource
       Type();
       virtual ~Type() {};
    };
-   
+
    typedef std::vector<metaIndex *>::const_iterator const_iterator;
-   
-   public:
+
+   protected:
+
+   std::vector<metaIndex *> SrcList;
 
    int ParseFileDeb822(std::string File);
    bool ParseFileOldStyle(std::string File);
 
+   public:
+
    bool ReadMainList();
    bool Read(std::string File);
 
@@ -122,7 +118,7 @@ class pkgSourceList : public pkgSource
 
    pkgSourceList();
    pkgSourceList(std::string File);
-   ~pkgSourceList();      
+   virtual ~pkgSourceList();
 };
 
 #endif

+ 30 - 1
apt-pkg/srcrecords.cc

@@ -14,6 +14,7 @@
 #include<config.h>
 
 #include <apt-pkg/srcrecords.h>
+#include <apt-pkg/debsrcrecords.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/sourcelist.h>
 #include <apt-pkg/metaindex.h>
@@ -147,5 +148,33 @@ const char *pkgSrcRecords::Parser::BuildDepType(unsigned char const &Type)
    return fields[Type];
 }
 									/*}}}*/
+bool pkgSrcRecords::Parser::Files2(std::vector<pkgSrcRecords::File2> &F2)/*{{{*/
+{
+   debSrcRecordParser * const deb = dynamic_cast<debSrcRecordParser*>(this);
+   if (deb != NULL)
+      return deb->Files2(F2);
 
-
+   std::vector<pkgSrcRecords::File> F;
+   if (Files(F) == false)
+      return false;
+   for (std::vector<pkgSrcRecords::File>::const_iterator f = F.begin(); f != F.end(); ++f)
+   {
+      pkgSrcRecords::File2 f2;
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+      f2.MD5Hash = f->MD5Hash;
+      f2.Size = f->Size;
+      f2.Hashes.push_back(HashString("MD5Sum", f->MD5Hash));
+      f2.FileSize = f->Size;
+#if __GNUC__ >= 4
+	#pragma GCC diagnostic pop
+#endif
+      f2.Path = f->Path;
+      f2.Type = f->Type;
+      F2.push_back(f2);
+   }
+   return true;
+}
+									/*}}}*/

+ 9 - 11
apt-pkg/srcrecords.h

@@ -1,6 +1,5 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: srcrecords.h,v 1.8.2.1 2003/12/26 16:27:34 mdz Exp $
 /* ######################################################################
    
    Source Package Records - Allows access to source package records
@@ -30,23 +29,21 @@ class pkgSrcRecords
 {
    public:
 
-#if __GNUC__ >= 4
-	// ensure that con- & de-structor don't trigger this warning
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+APT_IGNORE_DEPRECATED_PUSH
    // Describes a single file
    struct File
    {
+      APT_DEPRECATED std::string MD5Hash;
+      APT_DEPRECATED unsigned long Size;
       std::string Path;
       std::string Type;
-      unsigned long long Size;
+   };
+   struct File2 : public File
+   {
+      unsigned long long FileSize;
       HashStringList Hashes;
-      APT_DEPRECATED std::string MD5Hash;
    };
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP
 
    // Abstract parser for each source record
    class Parser
@@ -87,6 +84,7 @@ class pkgSrcRecords
       static const char *BuildDepType(unsigned char const &Type) APT_PURE;
 
       virtual bool Files(std::vector<pkgSrcRecords::File> &F) = 0;
+      bool Files2(std::vector<pkgSrcRecords::File2> &F);
       
       Parser(const pkgIndexFile *Index) : iIndex(Index) {};
       virtual ~Parser() {};

+ 109 - 0
apt-pkg/tagfile-order.c

@@ -0,0 +1,109 @@
+/* In this file is the order defined in which e.g. apt-ftparchive will write stanzas in.
+   Other commands might or might not use this. 'apt-cache show' e.g. does NOT!
+
+   The order we chose here is inspired by both dpkg and dak.
+   The testcase test/integration/test-apt-tagfile-fields-order intends to ensure that
+   this file isn't lacking (too far) behind dpkg over time. */
+
+static const char *iTFRewritePackageOrder[] = {
+   "Package",
+   "Package-Type",
+   "Architecture",
+   "Subarchitecture", // Used only by d-i
+   "Version",
+   "Revision",         // Obsolete (warning in dpkg)
+   "Package-Revision", // Obsolete (warning in dpkg)
+   "Package_Revision", // Obsolete (warning in dpkg)
+   "Kernel-Version", // Used only by d-i
+   "Built-Using",
+   "Built-For-Profiles",
+   "Multi-Arch",
+   "Status",
+   "Priority",
+   "Class", // dpkg nickname for Priority
+   "Essential",
+   "Installer-Menu-Item", // Used only by d-i
+   "Section",
+   "Source",
+   "Origin",
+   "Maintainer",
+   "Original-Maintainer", // unknown in dpkg order
+   "Bugs",
+   "Config-Version", // Internal of dpkg
+   "Conffiles",
+   "Triggers-Awaited",
+   "Triggers-Pending",
+   "Installed-Size",
+   "Provides",
+   "Pre-Depends",
+   "Depends",
+   "Recommends",
+   "Recommended", // dpkg nickname for Recommends
+   "Suggests",
+   "Optional", // dpkg nickname for Suggests
+   "Conflicts",
+   "Breaks",
+   "Replaces",
+   "Enhances",
+   "Filename",
+   "MSDOS-Filename", // Obsolete (used by dselect)
+   "Size",
+   "MD5sum",
+   "SHA1",
+   "SHA256",
+   "SHA512",
+   "Homepage",
+   "Description",
+   "Tag",
+   "Task",
+   0
+};
+static const char *iTFRewriteSourceOrder[] = {
+   "Package",
+   "Source", // dsc file, renamed to Package in Sources
+   "Format",
+   "Binary",
+   "Architecture",
+   "Version",
+   "Priority",
+   "Class", // dpkg nickname for Priority
+   "Section",
+   "Origin",
+   "Maintainer",
+   "Original-Maintainer", // unknown in dpkg order
+   "Uploaders",
+   "Dm-Upload-Allowed", // Obsolete (ignored by dak)
+   "Standards-Version",
+   "Build-Depends",
+   "Build-Depends-Arch",
+   "Build-Depends-Indep",
+   "Build-Conflicts",
+   "Build-Conflicts-Arch",
+   "Build-Conflicts-Indep",
+   "Testsuite",
+   "Homepage",
+   "Vcs-Browser",
+   "Vcs-Browse", // dak only (nickname?)
+   "Vcs-Arch",
+   "Vcs-Bzr",
+   "Vcs-Cvs",
+   "Vcs-Darcs",
+   "Vcs-Git",
+   "Vcs-Hg",
+   "Vcs-Mtn",
+   "Vcs-Svn",
+   "Directory",
+   "Package-List",
+   "Files",
+   "Checksums-Md5",
+   "Checksums-Sha1",
+   "Checksums-Sha256",
+   "Checksums-Sha512",
+   0
+};
+
+/* Two levels of initialization are used because gcc will set the symbol
+   size of an array to the length of the array, causing dynamic relinking
+   errors. Doing this makes the symbol size constant */
+const char **TFRewritePackageOrder = iTFRewritePackageOrder;
+const char **TFRewriteSourceOrder = iTFRewriteSourceOrder;

+ 237 - 95
apt-pkg/tagfile.cc

@@ -47,6 +47,23 @@ public:
    unsigned long long Size;
 };
 
+class pkgTagSectionPrivate
+{
+public:
+   pkgTagSectionPrivate()
+   {
+   }
+   struct TagData {
+      unsigned int StartTag;
+      unsigned int EndTag;
+      unsigned int StartValue;
+      unsigned int NextInBucket;
+
+      TagData(unsigned int const StartTag) : StartTag(StartTag), EndTag(0), StartValue(0), NextInBucket(0) {}
+   };
+   std::vector<TagData> Tags;
+};
+
 static unsigned long AlphaHash(const char *Text, size_t Length)		/*{{{*/
 {
    /* This very simple hash function for the last 8 letters gives
@@ -166,8 +183,8 @@ bool pkgTagFile::Step(pkgTagSection &Tag)
 	    break;
 
 	 if (Resize() == false)
-	    return _error->Error(_("Unable to parse package file %s (1)"),
-		  d->Fd.Name().c_str());
+	    return _error->Error(_("Unable to parse package file %s (%d)"),
+		  d->Fd.Name().c_str(), 1);
 
       } while (Tag.Scan(d->Start,d->End - d->Start, false) == false);
    }
@@ -266,7 +283,7 @@ bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long long Offset)
       return false;
    
    if (Tag.Scan(d->Start, d->End - d->Start, false) == false)
-      return _error->Error(_("Unable to parse package file %s (2)"),d->Fd.Name().c_str());
+      return _error->Error(_("Unable to parse package file %s (%d)"),d->Fd.Name().c_str(), 2);
    
    return true;
 }
@@ -274,21 +291,34 @@ bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long long Offset)
 // pkgTagSection::pkgTagSection - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
+APT_IGNORE_DEPRECATED_PUSH
 pkgTagSection::pkgTagSection()
    : Section(0), d(NULL), Stop(0)
 {
-   memset(&LookupTable, 0, sizeof(LookupTable));
+   d = new pkgTagSectionPrivate();
+#if APT_PKG_ABI < 413
+   TagCount = 0;
+   memset(&Indexes, 0, sizeof(Indexes));
+#endif
+   memset(&AlphaIndexes, 0, sizeof(AlphaIndexes));
 }
+APT_IGNORE_DEPRECATED_POP
 									/*}}}*/
 // TagSection::Scan - Scan for the end of the header information	/*{{{*/
+#if APT_PKG_ABI < 413
+bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength)
+{
+   return Scan(Start, MaxLength, true);
+}
+#endif
 bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const Restart)
 {
    Section = Start;
    const char *End = Start + MaxLength;
 
-   if (Restart == false && Tags.empty() == false)
+   if (Restart == false && d->Tags.empty() == false)
    {
-      Stop = Section + Tags.back().StartTag;
+      Stop = Section + d->Tags.back().StartTag;
       if (End <= Stop)
 	 return false;
       Stop = (const char *)memchr(Stop,'\n',End - Stop);
@@ -299,19 +329,23 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R
    else
    {
       Stop = Section;
-      if (Tags.empty() == false)
+      if (d->Tags.empty() == false)
       {
-	 memset(&LookupTable, 0, sizeof(LookupTable));
-	 Tags.clear();
+	 memset(&AlphaIndexes, 0, sizeof(AlphaIndexes));
+	 d->Tags.clear();
       }
-      Tags.reserve(0x100);
+      d->Tags.reserve(0x100);
    }
-   size_t TagCount = Tags.size();
+#if APT_PKG_ABI >= 413
+   unsigned int TagCount = d->Tags.size();
+#else
+   APT_IGNORE_DEPRECATED(TagCount = d->Tags.size();)
+#endif
 
    if (Stop == 0)
       return false;
 
-   TagData lastTagData(0);
+   pkgTagSectionPrivate::TagData lastTagData(0);
    lastTagData.EndTag = 0;
    unsigned long lastTagHash = 0;
    while (Stop < End)
@@ -329,14 +363,20 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R
 	 // store the last found tag
 	 if (lastTagData.EndTag != 0)
 	 {
-	    if (LookupTable[lastTagHash] != 0)
-	       lastTagData.NextInBucket = LookupTable[lastTagHash];
-	    LookupTable[lastTagHash] = TagCount;
-	    Tags.push_back(lastTagData);
+	    if (AlphaIndexes[lastTagHash] != 0)
+	       lastTagData.NextInBucket = AlphaIndexes[lastTagHash];
+	    APT_IGNORE_DEPRECATED_PUSH
+	    AlphaIndexes[lastTagHash] = TagCount;
+#if APT_PKG_ABI < 413
+	    if (d->Tags.size() < sizeof(Indexes)/sizeof(Indexes[0]))
+	       Indexes[d->Tags.size()] = lastTagData.StartTag;
+#endif
+	    APT_IGNORE_DEPRECATED_POP
+	    d->Tags.push_back(lastTagData);
 	 }
 
-	 ++TagCount;
-	 lastTagData = TagData(Stop - Section);
+	 APT_IGNORE_DEPRECATED(++TagCount;)
+	 lastTagData = pkgTagSectionPrivate::TagData(Stop - Section);
 	 // find the colon separating tag and value
 	 char const * Colon = (char const *) memchr(Stop, ':', End - Stop);
 	 if (Colon == NULL)
@@ -371,14 +411,20 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R
       {
 	 if (lastTagData.EndTag != 0)
 	 {
-	    if (LookupTable[lastTagHash] != 0)
-	       lastTagData.NextInBucket = LookupTable[lastTagHash];
-	    LookupTable[lastTagHash] = TagCount;
-	    Tags.push_back(lastTagData);
+	    if (AlphaIndexes[lastTagHash] != 0)
+	       lastTagData.NextInBucket = AlphaIndexes[lastTagHash];
+	    APT_IGNORE_DEPRECATED(AlphaIndexes[lastTagHash] = TagCount;)
+#if APT_PKG_ABI < 413
+	    APT_IGNORE_DEPRECATED(Indexes[d->Tags.size()] = lastTagData.StartTag;)
+#endif
+	    d->Tags.push_back(lastTagData);
 	 }
 
-	 TagData const td(Stop - Section);
-	 Tags.push_back(td);
+	 pkgTagSectionPrivate::TagData const td(Stop - Section);
+#if APT_PKG_ABI < 413
+	 APT_IGNORE_DEPRECATED(Indexes[d->Tags.size()] = td.StartTag;)
+#endif
+	 d->Tags.push_back(td);
 	 TrimRecord(false,End);
 	 return true;
       }
@@ -408,7 +454,11 @@ void pkgTagSection::Trim()
 }
 									/*}}}*/
 // TagSection::Exists - return True if a tag exists			/*{{{*/
+#if APT_PKG_ABI >= 413
 bool pkgTagSection::Exists(const char* const Tag) const
+#else
+bool pkgTagSection::Exists(const char* const Tag)
+#endif
 {
    unsigned int tmp;
    return Find(Tag, tmp);
@@ -420,16 +470,16 @@ bool pkgTagSection::Exists(const char* const Tag) const
 bool pkgTagSection::Find(const char *Tag,unsigned int &Pos) const
 {
    size_t const Length = strlen(Tag);
-   unsigned int Bucket = LookupTable[AlphaHash(Tag, Length)];
+   unsigned int Bucket = AlphaIndexes[AlphaHash(Tag, Length)];
    if (Bucket == 0)
       return false;
 
-   for (; Bucket != 0; Bucket = Tags[Bucket - 1].NextInBucket)
+   for (; Bucket != 0; Bucket = d->Tags[Bucket - 1].NextInBucket)
    {
-      if ((Tags[Bucket - 1].EndTag - Tags[Bucket - 1].StartTag) != Length)
+      if ((d->Tags[Bucket - 1].EndTag - d->Tags[Bucket - 1].StartTag) != Length)
 	 continue;
 
-      char const * const St = Section + Tags[Bucket - 1].StartTag;
+      char const * const St = Section + d->Tags[Bucket - 1].StartTag;
       if (strncasecmp(Tag,St,Length) != 0)
 	 continue;
 
@@ -447,9 +497,9 @@ bool pkgTagSection::Find(const char *Tag,const char *&Start,
    if (Find(Tag, Pos) == false)
       return false;
 
-   Start = Section + Tags[Pos].StartValue;
+   Start = Section + d->Tags[Pos].StartValue;
    // Strip off the gunk from the end
-   End = Section + Tags[Pos + 1].StartTag;
+   End = Section + d->Tags[Pos + 1].StartTag;
    if (unlikely(Start > End))
       return _error->Error("Internal parsing error");
 
@@ -459,8 +509,6 @@ bool pkgTagSection::Find(const char *Tag,const char *&Start,
 }
 									/*}}}*/
 // TagSection::FindS - Find a string					/*{{{*/
-// ---------------------------------------------------------------------
-/* */
 string pkgTagSection::FindS(const char *Tag) const
 {
    const char *Start;
@@ -470,6 +518,24 @@ string pkgTagSection::FindS(const char *Tag) const
    return string(Start,End);      
 }
 									/*}}}*/
+// TagSection::FindRawS - Find a string					/*{{{*/
+string pkgTagSection::FindRawS(const char *Tag) const
+{
+   unsigned int Pos;
+   if (Find(Tag, Pos) == false)
+      return "";
+
+   char const *Start = (char const *) memchr(Section + d->Tags[Pos].EndTag, ':', d->Tags[Pos].StartValue - d->Tags[Pos].EndTag);
+   ++Start;
+   char const *End = Section + d->Tags[Pos + 1].StartTag;
+   if (unlikely(Start > End))
+      return "";
+
+   for (; isspace(End[-1]) != 0 && End > Start; --End);
+
+   return std::string(Start, End - Start);
+}
+									/*}}}*/
 // TagSection::FindI - Find an integer					/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -561,78 +627,153 @@ bool pkgTagSection::FindFlag(unsigned long &Flags, unsigned long Flag,
    return true;
 }
 									/*}}}*/
+void pkgTagSection::Get(const char *&Start,const char *&Stop,unsigned int I) const
+{
+   Start = Section + d->Tags[I].StartTag;
+   Stop = Section + d->Tags[I+1].StartTag;
+}
 APT_PURE unsigned int pkgTagSection::Count() const {			/*{{{*/
-   if (Tags.empty() == true)
+   if (d->Tags.empty() == true)
       return 0;
    // the last element is just marking the end and isn't a real one
-   return Tags.size() - 1;
+   return d->Tags.size() - 1;
+}
+									/*}}}*/
+// TagSection::Write - Ordered (re)writing of fields			/*{{{*/
+pkgTagSection::Tag pkgTagSection::Tag::Remove(std::string const &Name)
+{
+   return Tag(REMOVE, Name, "");
+}
+pkgTagSection::Tag pkgTagSection::Tag::Rename(std::string const &OldName, std::string const &NewName)
+{
+   return Tag(RENAME, OldName, NewName);
+}
+pkgTagSection::Tag pkgTagSection::Tag::Rewrite(std::string const &Name, std::string const &Data)
+{
+   if (Data.empty() == true)
+      return Tag(REMOVE, Name, "");
+   else
+      return Tag(REWRITE, Name, Data);
+}
+static bool WriteTag(FileFd &File, std::string Tag, std::string const &Value)
+{
+   if (Value.empty() || isspace(Value[0]) != 0)
+      Tag.append(":");
+   else
+      Tag.append(": ");
+   Tag.append(Value);
+   Tag.append("\n");
+   return File.Write(Tag.c_str(), Tag.length());
+}
+static bool RewriteTags(FileFd &File, pkgTagSection const * const This, char const * const Tag,
+      std::vector<pkgTagSection::Tag>::const_iterator &R,
+      std::vector<pkgTagSection::Tag>::const_iterator const &REnd)
+{
+   size_t const TagLen = strlen(Tag);
+   for (; R != REnd; ++R)
+   {
+      std::string data;
+      if (R->Name.length() == TagLen && strncasecmp(R->Name.c_str(), Tag, R->Name.length()) == 0)
+      {
+	 if (R->Action != pkgTagSection::Tag::REWRITE)
+	    break;
+	 data = R->Data;
+      }
+      else if(R->Action == pkgTagSection::Tag::RENAME && R->Data.length() == TagLen &&
+	    strncasecmp(R->Data.c_str(), Tag, R->Data.length()) == 0)
+	 data = This->FindRawS(R->Name.c_str());
+      else
+	 continue;
+
+      return WriteTag(File, Tag, data);
+   }
+   return true;
+}
+bool pkgTagSection::Write(FileFd &File, char const * const * const Order, std::vector<Tag> const &Rewrite) const
+{
+   // first pass: Write everything we have an order for
+   if (Order != NULL)
+   {
+      for (unsigned int I = 0; Order[I] != 0; ++I)
+      {
+	 std::vector<Tag>::const_iterator R = Rewrite.begin();
+	 if (RewriteTags(File, this, Order[I], R, Rewrite.end()) == false)
+	    return false;
+	 if (R != Rewrite.end())
+	    continue;
+
+	 if (Exists(Order[I]) == false)
+	    continue;
+
+	 if (WriteTag(File, Order[I], FindRawS(Order[I])) == false)
+	    return false;
+      }
+   }
+   // second pass: See if we have tags which aren't ordered
+   if (d->Tags.empty() == false)
+   {
+      for (std::vector<pkgTagSectionPrivate::TagData>::const_iterator T = d->Tags.begin(); T != d->Tags.end() - 1; ++T)
+      {
+	 char const * const fieldname = Section + T->StartTag;
+	 size_t fieldnamelen = T->EndTag - T->StartTag;
+	 if (Order != NULL)
+	 {
+	    unsigned int I = 0;
+	    for (; Order[I] != 0; ++I)
+	    {
+	       if (fieldnamelen == strlen(Order[I]) && strncasecmp(fieldname, Order[I], fieldnamelen) == 0)
+		  break;
+	    }
+	    if (Order[I] != 0)
+	       continue;
+	 }
+
+	 std::string const name(fieldname, fieldnamelen);
+	 std::vector<Tag>::const_iterator R = Rewrite.begin();
+	 if (RewriteTags(File, this, name.c_str(), R, Rewrite.end()) == false)
+	    return false;
+	 if (R != Rewrite.end())
+	    continue;
+
+	 if (WriteTag(File, name, FindRawS(name.c_str())) == false)
+	    return false;
+      }
+   }
+   // last pass: see if there are any rewrites remaining we haven't done yet
+   for (std::vector<Tag>::const_iterator R = Rewrite.begin(); R != Rewrite.end(); ++R)
+   {
+      if (R->Action == Tag::REMOVE)
+	 continue;
+      std::string const name = ((R->Action == Tag::RENAME) ? R->Data : R->Name);
+      if (Exists(name.c_str()))
+	 continue;
+      if (Order != NULL)
+      {
+	 unsigned int I = 0;
+	 for (; Order[I] != 0; ++I)
+	 {
+	    if (strncasecmp(name.c_str(), Order[I], name.length()) == 0 && name.length() == strlen(Order[I]))
+	       break;
+	 }
+	 if (Order[I] != 0)
+	    continue;
+      }
+
+      if (WriteTag(File, name, ((R->Action == Tag::RENAME) ? FindRawS(R->Name.c_str()) : R->Data)) == false)
+	 return false;
+   }
+   return true;
 }
 									/*}}}*/
+
+#include "tagfile-order.c"
+
 // TFRewrite - Rewrite a control record					/*{{{*/
 // ---------------------------------------------------------------------
 /* This writes the control record to stdout rewriting it as necessary. The
    override map item specificies the rewriting rules to follow. This also
    takes the time to sort the feild list. */
-
-/* The order of this list is taken from dpkg source lib/parse.c the fieldinfos
-   array. */
-static const char *iTFRewritePackageOrder[] = {
-                          "Package",
-                          "Essential",
-                          "Status",
-                          "Priority",
-                          "Section",
-                          "Installed-Size",
-                          "Maintainer",
-                          "Original-Maintainer",
-                          "Architecture",
-                          "Source",
-                          "Version",
-                           "Revision",         // Obsolete
-                           "Config-Version",   // Obsolete
-                          "Replaces",
-                          "Provides",
-                          "Depends",
-                          "Pre-Depends",
-                          "Recommends",
-                          "Suggests",
-                          "Conflicts",
-                          "Breaks",
-                          "Conffiles",
-                          "Filename",
-                          "Size",
-                          "MD5sum",
-                          "SHA1",
-                          "SHA256",
-                          "SHA512",
-                           "MSDOS-Filename",   // Obsolete
-                          "Description",
-                          0};
-static const char *iTFRewriteSourceOrder[] = {"Package",
-                                      "Source",
-                                      "Binary",
-                                      "Version",
-                                      "Priority",
-                                      "Section",
-                                      "Maintainer",
-				      "Original-Maintainer",
-                                      "Build-Depends",
-                                      "Build-Depends-Indep",
-                                      "Build-Conflicts",
-                                      "Build-Conflicts-Indep",
-                                      "Architecture",
-                                      "Standards-Version",
-                                      "Format",
-                                      "Directory",
-                                      "Files",
-                                      0};   
-
-/* Two levels of initialization are used because gcc will set the symbol
-   size of an array to the length of the array, causing dynamic relinking 
-   errors. Doing this makes the symbol size constant */
-const char **TFRewritePackageOrder = iTFRewritePackageOrder;
-const char **TFRewriteSourceOrder = iTFRewriteSourceOrder;
-   
+APT_IGNORE_DEPRECATED_PUSH
 bool TFRewrite(FILE *Output,pkgTagSection const &Tags,const char *Order[],
 	       TFRewriteData *Rewrite)
 {
@@ -756,6 +897,7 @@ bool TFRewrite(FILE *Output,pkgTagSection const &Tags,const char *Order[],
       
    return true;
 }
+APT_IGNORE_DEPRECATED_POP
 									/*}}}*/
 
-pkgTagSection::~pkgTagSection() {}
+pkgTagSection::~pkgTagSection() { delete d; }

+ 56 - 27
apt-pkg/tagfile.h

@@ -1,6 +1,5 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: tagfile.h,v 1.20 2003/05/19 17:13:57 doogie Exp $
 /* ######################################################################
 
    Fast scanner for RFC-822 type header information
@@ -33,35 +32,34 @@
 #endif
 
 class FileFd;
+class pkgTagSectionPrivate;
 
 class pkgTagSection
 {
    const char *Section;
-   struct TagData {
-      unsigned int StartTag;
-      unsigned int EndTag;
-      unsigned int StartValue;
-      unsigned int NextInBucket;
-
-      TagData(unsigned int const StartTag) : StartTag(StartTag), EndTag(0), StartValue(0), NextInBucket(0) {}
-   };
-   std::vector<TagData> Tags;
-   unsigned int LookupTable[0x100];
+   // We have a limit of 256 tags per section with the old abi
+#if APT_PKG_ABI < 413
+   APT_DEPRECATED unsigned int Indexes[256];
+#endif
+   unsigned int AlphaIndexes[0x100];
+#if APT_PKG_ABI < 413
+   APT_DEPRECATED unsigned int TagCount;
+#endif
 
-   // dpointer placeholder (for later in case we need it)
-   void *d;
+   pkgTagSectionPrivate *d;
 
    protected:
    const char *Stop;
 
    public:
-   
+
    inline bool operator ==(const pkgTagSection &rhs) {return Section == rhs.Section;};
    inline bool operator !=(const pkgTagSection &rhs) {return Section != rhs.Section;};
-   
+
    bool Find(const char *Tag,const char *&Start, const char *&End) const;
    bool Find(const char *Tag,unsigned int &Pos) const;
    std::string FindS(const char *Tag) const;
+   std::string FindRawS(const char *Tag) const;
    signed int FindI(const char *Tag,signed long Default = 0) const;
    bool FindB(const char *Tag, bool const &Default = false) const;
    unsigned long long FindULL(const char *Tag, unsigned long long const &Default = 0) const;
@@ -86,7 +84,13 @@ class pkgTagSection
     * @return \b true if section end was found, \b false otherwise.
     *  Beware that internal state will be inconsistent if \b false is returned!
     */
+#if APT_PKG_ABI >= 413
    APT_MUSTCHECK bool Scan(const char *Start, unsigned long MaxLength, bool const Restart = true);
+#else
+   APT_MUSTCHECK bool Scan(const char *Start, unsigned long MaxLength, bool const Restart);
+   APT_MUSTCHECK bool Scan(const char *Start, unsigned long MaxLength);
+#endif
+
    inline unsigned long size() const {return Stop - Section;};
    void Trim();
    virtual void TrimRecord(bool BeforeRecord, const char* &End);
@@ -97,19 +101,45 @@ class pkgTagSection
     * times, but only the last occurrence is available via Find methods.
     */
    unsigned int Count() const;
+#if APT_PKG_ABI >= 413
    bool Exists(const char* const Tag) const;
+#else
+   bool Exists(const char* const Tag);
+#endif
 
-   inline void Get(const char *&Start,const char *&Stop,unsigned int I) const
-                   {Start = Section + Tags[I].StartTag; Stop = Section + Tags[I+1].StartTag;}
+   void Get(const char *&Start,const char *&Stop,unsigned int I) const;
 
    inline void GetSection(const char *&Start,const char *&Stop) const
    {
       Start = Section;
       Stop = this->Stop;
    };
-   
+
    pkgTagSection();
    virtual ~pkgTagSection();
+
+   struct Tag
+   {
+      enum ActionType { REMOVE, RENAME, REWRITE } Action;
+      std::string Name;
+      std::string Data;
+
+      static Tag Remove(std::string const &Name);
+      static Tag Rename(std::string const &OldName, std::string const &NewName);
+      static Tag Rewrite(std::string const &Name, std::string const &Data);
+      private:
+      Tag(ActionType const Action, std::string const &Name, std::string const &Data) :
+	 Action(Action), Name(Name), Data(Data) {}
+   };
+
+   /** Write this section (with optional rewrites) to a file
+    *
+    * @param File to write the section to
+    * @param Order in which tags should appear in the file
+    * @param Rewrite is a set of tags to be renamed, rewitten and/or removed
+    * @return \b true if successful, otherwise \b false
+    */
+   bool Write(FileFd &File, char const * const * const Order = NULL, std::vector<Tag> const &Rewrite = std::vector<Tag>()) const;
 };
 
 class pkgTagFilePrivate;
@@ -133,20 +163,19 @@ class pkgTagFile
    virtual ~pkgTagFile();
 };
 
-/* This is the list of things to rewrite. The rewriter
-   goes through and changes or adds each of these headers
-   to suit. A zero forces the header to be erased, an empty string
-   causes the old value to be used. (rewrite rule ignored) */
-struct TFRewriteData
+extern const char **TFRewritePackageOrder;
+extern const char **TFRewriteSourceOrder;
+
+// Use pkgTagSection::Tag and pkgTagSection::Write() instead
+APT_IGNORE_DEPRECATED_PUSH
+struct APT_DEPRECATED TFRewriteData
 {
    const char *Tag;
    const char *Rewrite;
    const char *NewTag;
 };
-extern const char **TFRewritePackageOrder;
-extern const char **TFRewriteSourceOrder;
-
-bool TFRewrite(FILE *Output,pkgTagSection const &Tags,const char *Order[],
+APT_DEPRECATED bool TFRewrite(FILE *Output,pkgTagSection const &Tags,const char *Order[],
 	       TFRewriteData *Rewrite);
+APT_IGNORE_DEPRECATED_POP
 
 #endif

+ 18 - 10
apt-pkg/upgrade.cc

@@ -24,7 +24,7 @@
    
    The problem resolver is used to resolve the problems.
  */
-bool pkgDistUpgrade(pkgDepCache &Cache, OpProgress * const Progress)
+static bool pkgDistUpgrade(pkgDepCache &Cache, OpProgress * const Progress)
 {
    std::string const solver = _config->Find("APT::Solver", "internal");
    if (solver != "internal")
@@ -119,6 +119,10 @@ bool pkgDistUpgrade(pkgDepCache &Cache, OpProgress * const Progress)
    if (Progress != NULL)
       Progress->Done();
    return success;
+}
+bool pkgDistUpgrade(pkgDepCache &Cache)
+{
+   return pkgDistUpgrade(Cache, NULL);
 }
 									/*}}}*/
 // AllUpgradeNoNewPackages - Upgrade but no removals or new pkgs        /*{{{*/
@@ -229,9 +233,13 @@ static bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache, OpProgress * const
 /* Right now the system must be consistent before this can be called.
    It also will not change packages marked for install, it only tries
    to install packages not marked for install */
-bool pkgAllUpgrade(pkgDepCache &Cache, OpProgress * const Progress)
+static bool pkgAllUpgrade(pkgDepCache &Cache, OpProgress * const Progress)
 {
    return pkgAllUpgradeNoNewPackages(Cache, Progress);
+}
+bool pkgAllUpgrade(pkgDepCache &Cache)
+{
+   return pkgAllUpgrade(Cache, NULL);
 }
 									/*}}}*/
 // MinimizeUpgrade - Minimizes the set of packages to be upgraded	/*{{{*/
@@ -280,13 +288,15 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache)
 }
 									/*}}}*/
 // APT::Upgrade::Upgrade - Upgrade using a specific strategy		/*{{{*/
-bool APT::Upgrade::Upgrade(pkgDepCache &Cache, int mode, OpProgress * const Progress)
+#if APT_PKG_ABI < 413
+bool APT::Upgrade::Upgrade(pkgDepCache &Cache, int mode)
 {
-#if __GNUC__ >= 4
-	// the deprecated methods will become our privates, so that is fine
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+   return Upgrade(Cache, mode, NULL);
+}
 #endif
+bool APT::Upgrade::Upgrade(pkgDepCache &Cache, int mode, OpProgress * const Progress)
+{
+APT_IGNORE_DEPRECATED_PUSH
    if (mode == ALLOW_EVERYTHING)
       return pkgDistUpgrade(Cache, Progress);
    else if ((mode & ~FORBID_REMOVE_PACKAGES) == 0)
@@ -295,9 +305,7 @@ bool APT::Upgrade::Upgrade(pkgDepCache &Cache, int mode, OpProgress * const Prog
       return pkgAllUpgradeNoNewPackages(Cache, Progress);
    else
       _error->Error("pkgAllUpgrade called with unsupported mode %i", mode);
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP
    return false;
 }
 									/*}}}*/

+ 9 - 4
apt-pkg/upgrade.h

@@ -20,17 +20,22 @@ namespace APT {
    namespace Upgrade {
       // FIXME: make this "enum class UpgradeMode {" once we enable c++11
       enum UpgradeMode {
-	 ALLOW_EVERYTHING = 0,
          FORBID_REMOVE_PACKAGES = 1,
-         FORBID_INSTALL_NEW_PACKAGES = 2
+         FORBID_INSTALL_NEW_PACKAGES = 2,
+	 ALLOW_EVERYTHING = 0
       };
+#if APT_PKG_ABI >= 413
       bool Upgrade(pkgDepCache &Cache, int UpgradeMode, OpProgress * const Progress = NULL);
+#else
+      bool Upgrade(pkgDepCache &Cache, int UpgradeMode);
+      bool Upgrade(pkgDepCache &Cache, int UpgradeMode, OpProgress * const Progress);
+#endif
    }
 }
 
 // please use APT::Upgrade::Upgrade() instead
-APT_DEPRECATED bool pkgDistUpgrade(pkgDepCache &Cache, OpProgress * const Progress = NULL);
-APT_DEPRECATED bool pkgAllUpgrade(pkgDepCache &Cache, OpProgress * const Progress = NULL);
+APT_DEPRECATED bool pkgDistUpgrade(pkgDepCache &Cache);
+APT_DEPRECATED bool pkgAllUpgrade(pkgDepCache &Cache);
 
 bool pkgMinimizeUpgrade(pkgDepCache &Cache);
 #endif

+ 3 - 7
apt-pkg/vendorlist.cc

@@ -11,10 +11,8 @@
 
 #include <apti18n.h>
 
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic push
-	#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+// The whole vendor system is deprecated
+APT_IGNORE_DEPRECATED_PUSH
 
 #include <apt-pkg/vendor.h>
 #include <apt-pkg/vendorlist.h>
@@ -163,6 +161,4 @@ const Vendor* pkgVendorList::FindVendor(const std::vector<string> GPGVOutput)	/*
 }
 									/*}}}*/
 
-#if __GNUC__ >= 4
-	#pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP

+ 3 - 0
apt-pkg/version.cc

@@ -40,3 +40,6 @@ pkgVersioningSystem *pkgVersioningSystem::GetVS(const char *Label)
    return 0;
 }
 									/*}}}*/
+
+
+pkgVersioningSystem::~pkgVersioningSystem() {}

+ 1 - 1
apt-pkg/version.h

@@ -55,7 +55,7 @@ class pkgVersioningSystem
    APT_MKSTRCMP(CmpReleaseVer,DoCmpReleaseVer);
    
    pkgVersioningSystem();
-   virtual ~pkgVersioningSystem() {};
+   virtual ~pkgVersioningSystem();
 };
 
 #endif

+ 23 - 22
apt-pkg/versionmatch.cc

@@ -137,7 +137,10 @@ pkgVersionMatch::pkgVersionMatch(string Data,MatchType Type) : Type(Type)
 // ---------------------------------------------------------------------
 /* */
 bool pkgVersionMatch::MatchVer(const char *A,string B,bool Prefix)
-{   
+{
+   if (A == NULL)
+      return false;
+
    const char *Ab = A;
    const char *Ae = Ab + strlen(A);
    
@@ -178,13 +181,16 @@ pkgCache::VerIterator pkgVersionMatch::Find(pkgCache::PkgIterator Pkg)
    // This will be Ended by now.
    return Ver;
 }
+									/*}}}*/
 
 #ifndef FNM_CASEFOLD
 #define FNM_CASEFOLD 0
 #endif
 
-bool pkgVersionMatch::ExpressionMatches(const char *pattern, const char *string)
+bool pkgVersionMatch::ExpressionMatches(const char *pattern, const char *string)/*{{{*/
 {
+   if (pattern == NULL || string == NULL)
+      return false;
    if (pattern[0] == '/') {
       size_t length = strlen(pattern);
       if (pattern[length - 1] == '/') {
@@ -230,38 +236,30 @@ bool pkgVersionMatch::FileMatch(pkgCache::PkgFileIterator File)
 	 return false;
 
       if (RelVerStr.empty() == false)
-	 if (File->Version == 0 ||
-	     (MatchVer(File.Version(),RelVerStr,RelVerPrefixMatch) == false &&
-	      ExpressionMatches(RelVerStr, File.Version()) == false))
+	 if (MatchVer(File.Version(),RelVerStr,RelVerPrefixMatch) == false &&
+	       ExpressionMatches(RelVerStr, File.Version()) == false)
 	    return false;
       if (RelOrigin.empty() == false)
-	 if (File->Origin == 0 || !ExpressionMatches(RelOrigin,File.Origin()))
+	 if (!ExpressionMatches(RelOrigin,File.Origin()))
 	    return false;
       if (RelArchive.empty() == false)
-	 if (File->Archive == 0 ||
-	     !ExpressionMatches(RelArchive,File.Archive()))
+	 if (!ExpressionMatches(RelArchive,File.Archive()))
             return false;
       if (RelCodename.empty() == false)
-	 if (File->Codename == 0 ||
-	     !ExpressionMatches(RelCodename,File.Codename()))
+	 if (!ExpressionMatches(RelCodename,File.Codename()))
             return false;
       if (RelRelease.empty() == false)
-	 if ((File->Archive == 0 ||
-	     !ExpressionMatches(RelRelease,File.Archive())) &&
-             (File->Codename == 0 ||
-	      !ExpressionMatches(RelRelease,File.Codename())))
+	 if (!ExpressionMatches(RelRelease,File.Archive()) &&
+             !ExpressionMatches(RelRelease,File.Codename()))
 	       return false;
       if (RelLabel.empty() == false)
-	 if (File->Label == 0 ||
-	     !ExpressionMatches(RelLabel,File.Label()))
+	 if (!ExpressionMatches(RelLabel,File.Label()))
 	    return false;
       if (RelComponent.empty() == false)
-	 if (File->Component == 0 ||
-	     !ExpressionMatches(RelComponent,File.Component()))
+	 if (!ExpressionMatches(RelComponent,File.Component()))
 	    return false;
       if (RelArchitecture.empty() == false)
-	 if (File->Architecture == 0 ||
-	     !ExpressionMatches(RelArchitecture,File.Architecture()))
+	 if (!ExpressionMatches(RelArchitecture,File.Architecture()))
 	    return false;
       return true;
    }
@@ -269,11 +267,14 @@ bool pkgVersionMatch::FileMatch(pkgCache::PkgFileIterator File)
    if (Type == Origin)
    {
       if (OrSite.empty() == false) {
-	 if (File->Site == 0)
+	 if (File.Site() == NULL)
 	    return false;
       } else // so we are talking about file:// or status file
-	 if (strcmp(File.Site(),"") == 0 && File->Archive != 0 && strcmp(File.Archive(),"now") == 0) // skip the status file
+      {
+	 pkgCache::RlsFileIterator const RlsFile = File.ReleaseFile();
+	 if (strcmp(File.Site(),"") == 0 && RlsFile->Archive != 0 && strcmp(RlsFile.Archive(),"now") == 0) // skip the status file
 	    return false;
+      }
       return (ExpressionMatches(OrSite, File.Site())); /* both strings match */
    }
 

+ 2 - 2
apt-pkg/versionmatch.h

@@ -70,8 +70,8 @@ class pkgVersionMatch
    enum MatchType {None = 0,Version,Release,Origin} Type;
 
    bool MatchVer(const char *A,std::string B,bool Prefix) APT_PURE;
-   bool ExpressionMatches(const char *pattern, const char *string);
-   bool ExpressionMatches(const std::string& pattern, const char *string);
+   static bool ExpressionMatches(const char *pattern, const char *string);
+   static bool ExpressionMatches(const std::string& pattern, const char *string);
    bool FileMatch(pkgCache::PkgFileIterator File);
    pkgCache::VerIterator Find(pkgCache::PkgIterator Pkg);
 

+ 0 - 0
apt-private/acqprogress.cc


Vissa filer visades inte eftersom för många filer har ändrats