]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/acquire-method.cc
support compression and by-hash for .diff/Index files
[apt.git] / apt-pkg / acquire-method.cc
index 79a7519a84f2243118b894ba94a98a0767f9f5fa..39d5e61f2acb1ab10d4009f9bad60bfa26672fa5 100644 (file)
    ##################################################################### */
                                                                        /*}}}*/
 // Include Files                                                       /*{{{*/
    ##################################################################### */
                                                                        /*}}}*/
 // Include Files                                                       /*{{{*/
+#include <config.h>
+
 #include <apt-pkg/acquire-method.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/hashes.h>
 #include <apt-pkg/acquire-method.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/hashes.h>
-
+#include <apt-pkg/md5.h>
+#include <apt-pkg/sha1.h>
+#include <apt-pkg/sha2.h>
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <string>
+#include <vector>
 #include <iostream>
 #include <stdio.h>
 #include <iostream>
 #include <stdio.h>
-#include <sys/signal.h>
                                                                        /*}}}*/
 
 using namespace std;
                                                                        /*}}}*/
 
 using namespace std;
@@ -70,9 +80,20 @@ void pkgAcqMethod::Fail(bool Transient)
 {
    string Err = "Undetermined Error";
    if (_error->empty() == false)
 {
    string Err = "Undetermined Error";
    if (_error->empty() == false)
-      _error->PopMessage(Err);   
-   _error->Discard();
-   Fail(Err,Transient);
+   {
+      Err.clear();
+      while (_error->empty() == false)
+      {
+        std::string msg;
+        if (_error->PopMessage(msg))
+        {
+           if (Err.empty() == false)
+              Err.append("\n");
+           Err.append(msg);
+        }
+      }
+   }
+   Fail(Err, Transient);
 }
                                                                        /*}}}*/
 // AcqMethod::Fail - A fetch has failed                                        /*{{{*/
 }
                                                                        /*}}}*/
 // AcqMethod::Fail - A fetch has failed                                        /*{{{*/
@@ -81,7 +102,7 @@ void pkgAcqMethod::Fail(bool Transient)
 void pkgAcqMethod::Fail(string Err,bool Transient)
 {
    // Strip out junk from the error messages
 void pkgAcqMethod::Fail(string Err,bool Transient)
 {
    // Strip out junk from the error messages
-   for (string::iterator I = Err.begin(); I != Err.end(); I++)
+   for (string::iterator I = Err.begin(); I != Err.end(); ++I)
    {
       if (*I == '\r') 
         *I = ' ';
    {
       if (*I == '\r') 
         *I = ' ';
@@ -92,13 +113,11 @@ void pkgAcqMethod::Fail(string Err,bool Transient)
    if (Queue != 0)
    {
       std::cout << "400 URI Failure\nURI: " << Queue->Uri << "\n"
    if (Queue != 0)
    {
       std::cout << "400 URI Failure\nURI: " << Queue->Uri << "\n"
-               << "Message: " << Err << " " << IP << "\n";
-      // Dequeue
-      FetchItem *Tmp = Queue;
-      Queue = Queue->Next;
-      delete Tmp;
-      if (Tmp == QueueBack)
-        QueueBack = Queue;
+               << "Message: " << Err;
+      if (IP.empty() == false && _config->FindB("Acquire::Failure::ShowIP", true) == true)
+        std::cout << " " << IP;
+      std::cout << "\n";
+      Dequeue();
    }
    else
       std::cout << "400 URI Failure\nURI: <UNKNOWN>\nMessage: " << Err << "\n";
    }
    else
       std::cout << "400 URI Failure\nURI: <UNKNOWN>\nMessage: " << Err << "\n";
@@ -113,6 +132,18 @@ void pkgAcqMethod::Fail(string Err,bool Transient)
 
    std::cout << "\n" << std::flush;
 }
 
    std::cout << "\n" << std::flush;
 }
+                                                                       /*}}}*/
+// AcqMethod::DropPrivsOrDie - Drop privileges or die          /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgAcqMethod::DropPrivsOrDie()
+{
+   if (!DropPrivileges()) {
+      Fail(false);
+      exit(112);       /* call the european emergency number */
+   }
+}
+
                                                                        /*}}}*/
 // AcqMethod::URIStart - Indicate a download is starting               /*{{{*/
 // ---------------------------------------------------------------------
                                                                        /*}}}*/
 // AcqMethod::URIStart - Indicate a download is starting               /*{{{*/
 // ---------------------------------------------------------------------
@@ -125,13 +156,13 @@ void pkgAcqMethod::URIStart(FetchResult &Res)
    std::cout << "200 URI Start\n"
             << "URI: " << Queue->Uri << "\n";
    if (Res.Size != 0)
    std::cout << "200 URI Start\n"
             << "URI: " << Queue->Uri << "\n";
    if (Res.Size != 0)
-      std::cout << "Size: " << Res.Size << "\n";
+      std::cout << "Size: " << std::to_string(Res.Size) << "\n";
 
    if (Res.LastModified != 0)
 
    if (Res.LastModified != 0)
-      std::cout << "Last-Modified: " << TimeRFC1123(Res.LastModified) << "\n";
+      std::cout << "Last-Modified: " << TimeRFC1123(Res.LastModified, true) << "\n";
 
    if (Res.ResumePoint != 0)
 
    if (Res.ResumePoint != 0)
-      std::cout << "Resume-Point: " << Res.ResumePoint << "\n";
+      std::cout << "Resume-Point: " << std::to_string(Res.ResumePoint) << "\n";
 
    if (UsedMirror.empty() == false)
       std::cout << "UsedMirror: " << UsedMirror << "\n";
 
    if (UsedMirror.empty() == false)
       std::cout << "UsedMirror: " << UsedMirror << "\n";
@@ -142,6 +173,16 @@ void pkgAcqMethod::URIStart(FetchResult &Res)
 // AcqMethod::URIDone - A URI is finished                              /*{{{*/
 // ---------------------------------------------------------------------
 /* */
 // AcqMethod::URIDone - A URI is finished                              /*{{{*/
 // ---------------------------------------------------------------------
 /* */
+static void printHashStringList(HashStringList const * const list)
+{
+      for (HashStringList::const_iterator hash = list->begin(); hash != list->end(); ++hash)
+      {
+        // very old compatibility name for MD5Sum
+        if (hash->HashType() == "MD5Sum")
+           std::cout << "MD5-Hash: " << hash->HashValue() << "\n";
+        std::cout << hash->HashType() << "-Hash: " << hash->HashValue() << "\n";
+      }
+}
 void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt)
 {
    if (Queue == 0)
 void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt)
 {
    if (Queue == 0)
@@ -154,18 +195,13 @@ void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt)
       std::cout << "Filename: " << Res.Filename << "\n";
 
    if (Res.Size != 0)
       std::cout << "Filename: " << Res.Filename << "\n";
 
    if (Res.Size != 0)
-      std::cout << "Size: " << Res.Size << "\n";
+      std::cout << "Size: " << std::to_string(Res.Size) << "\n";
 
    if (Res.LastModified != 0)
 
    if (Res.LastModified != 0)
-      std::cout << "Last-Modified: " << TimeRFC1123(Res.LastModified) << "\n";
-
-   if (Res.MD5Sum.empty() == false)
-      std::cout << "MD5-Hash: " << Res.MD5Sum << "\n"
-               << "MD5Sum-Hash: " << Res.MD5Sum << "\n";
-   if (Res.SHA1Sum.empty() == false)
-      std::cout << "SHA1-Hash: " << Res.SHA1Sum << "\n";
-   if (Res.SHA256Sum.empty() == false)
-      std::cout << "SHA256-Hash: " << Res.SHA256Sum << "\n";
+      std::cout << "Last-Modified: " << TimeRFC1123(Res.LastModified, true) << "\n";
+
+   printHashStringList(&Res.Hashes);
+
    if (UsedMirror.empty() == false)
       std::cout << "UsedMirror: " << UsedMirror << "\n";
    if (Res.GPGVOutput.empty() == false)
    if (UsedMirror.empty() == false)
       std::cout << "UsedMirror: " << UsedMirror << "\n";
    if (Res.GPGVOutput.empty() == false)
@@ -177,7 +213,7 @@ void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt)
    }
 
    if (Res.ResumePoint != 0)
    }
 
    if (Res.ResumePoint != 0)
-      std::cout << "Resume-Point: " << Res.ResumePoint << "\n";
+      std::cout << "Resume-Point: " << std::to_string(Res.ResumePoint) << "\n";
 
    if (Res.IMSHit == true)
       std::cout << "IMS-Hit: true\n";
 
    if (Res.IMSHit == true)
       std::cout << "IMS-Hit: true\n";
@@ -188,30 +224,19 @@ void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt)
         std::cout << "Alt-Filename: " << Alt->Filename << "\n";
 
       if (Alt->Size != 0)
         std::cout << "Alt-Filename: " << Alt->Filename << "\n";
 
       if (Alt->Size != 0)
-        std::cout << "Alt-Size: " << Alt->Size << "\n";
+        std::cout << "Alt-Size: " << std::to_string(Alt->Size) << "\n";
 
       if (Alt->LastModified != 0)
 
       if (Alt->LastModified != 0)
-        std::cout << "Alt-Last-Modified: " << TimeRFC1123(Alt->LastModified) << "\n";
+        std::cout << "Alt-Last-Modified: " << TimeRFC1123(Alt->LastModified, true) << "\n";
 
 
-      if (Alt->MD5Sum.empty() == false)
-        std::cout << "Alt-MD5-Hash: " << Alt->MD5Sum << "\n";
-      if (Alt->SHA1Sum.empty() == false)
-        std::cout << "Alt-SHA1-Hash: " << Alt->SHA1Sum << "\n";
-      if (Alt->SHA256Sum.empty() == false)
-        std::cout << "Alt-SHA256-Hash: " << Alt->SHA256Sum << "\n";
+      printHashStringList(&Alt->Hashes);
 
       if (Alt->IMSHit == true)
         std::cout << "Alt-IMS-Hit: true\n";
    }
 
    std::cout << "\n" << std::flush;
 
       if (Alt->IMSHit == true)
         std::cout << "Alt-IMS-Hit: true\n";
    }
 
    std::cout << "\n" << std::flush;
-
-   // Dequeue
-   FetchItem *Tmp = Queue;
-   Queue = Queue->Next;
-   delete Tmp;
-   if (Tmp == QueueBack)
-      QueueBack = Queue;
+   Dequeue();
 }
                                                                        /*}}}*/
 // AcqMethod::MediaFail - Syncronous request for new media             /*{{{*/
 }
                                                                        /*}}}*/
 // AcqMethod::MediaFail - Syncronous request for new media             /*{{{*/
@@ -285,12 +310,12 @@ bool pkgAcqMethod::Configuration(string Message)
       I += Length + 1;
       
       for (; I < MsgEnd && *I == ' '; I++);
       I += Length + 1;
       
       for (; I < MsgEnd && *I == ' '; I++);
-      const char *Equals = I;
-      for (; Equals < MsgEnd && *Equals != '='; Equals++);
-      const char *End = Equals;
-      for (; End < MsgEnd && *End != '\n'; End++);
-      if (End == Equals)
+      const char *Equals = (const char*) memchr(I, '=', MsgEnd - I);
+      if (Equals == NULL)
         return false;
         return false;
+      const char *End = (const char*) memchr(Equals, '\n', MsgEnd - Equals);
+      if (End == NULL)
+        End = MsgEnd;
       
       Cnf.Set(DeQuoteString(string(I,Equals-I)),
              DeQuoteString(string(Equals+1,End-Equals-1)));
       
       Cnf.Set(DeQuoteString(string(I,Equals-I)),
              DeQuoteString(string(Equals+1,End-Equals-1)));
@@ -352,6 +377,20 @@ int pkgAcqMethod::Run(bool Single)
               Tmp->LastModified = 0;
            Tmp->IndexFile = StringToBool(LookupTag(Message,"Index-File"),false);
            Tmp->FailIgnore = StringToBool(LookupTag(Message,"Fail-Ignore"),false);
               Tmp->LastModified = 0;
            Tmp->IndexFile = StringToBool(LookupTag(Message,"Index-File"),false);
            Tmp->FailIgnore = StringToBool(LookupTag(Message,"Fail-Ignore"),false);
+           Tmp->ExpectedHashes = HashStringList();
+           for (char const * const * t = HashString::SupportedHashes(); *t != NULL; ++t)
+           {
+              std::string tag = "Expected-";
+              tag.append(*t);
+              std::string const hash = LookupTag(Message, tag.c_str());
+              if (hash.empty() == false)
+                 Tmp->ExpectedHashes.push_back(HashString(*t, hash));
+           }
+            char *End;
+           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
            Tmp->Next = 0;
            
            // Append it to the list
@@ -360,14 +399,14 @@ int pkgAcqMethod::Run(bool Single)
            *I = Tmp;
            if (QueueBack == 0)
               QueueBack = Tmp;
            *I = Tmp;
            if (QueueBack == 0)
               QueueBack = Tmp;
-           
+
            // Notify that this item is to be fetched.
            // Notify that this item is to be fetched.
-           if (Fetch(Tmp) == false)
+           if (URIAcquire(Message, Tmp) == false)
               Fail();
               Fail();
-           
-           break;                                           
-        }   
-      }      
+
+           break;
+        }
+      }
    }
 
    Exit();
    }
 
    Exit();
@@ -375,8 +414,6 @@ int pkgAcqMethod::Run(bool Single)
 }
                                                                        /*}}}*/
 // AcqMethod::PrintStatus - privately really send a log/status message /*{{{*/
 }
                                                                        /*}}}*/
 // AcqMethod::PrintStatus - privately really send a log/status message /*{{{*/
-// ---------------------------------------------------------------------
-/* */
 void pkgAcqMethod::PrintStatus(char const * const header, const char* Format,
                               va_list &args) const
 {
 void pkgAcqMethod::PrintStatus(char const * const header, const char* Format,
                               va_list &args) const
 {
@@ -417,33 +454,21 @@ void pkgAcqMethod::Status(const char *Format,...)
                                                                        /*}}}*/
 // AcqMethod::Redirect - Send a redirect message                       /*{{{*/
 // ---------------------------------------------------------------------
                                                                        /*}}}*/
 // AcqMethod::Redirect - Send a redirect message                       /*{{{*/
 // ---------------------------------------------------------------------
-/* This method sends the redirect message and also manipulates the queue
  to keep the pipeline synchronized. */
+/* This method sends the redirect message and dequeues the item as
* the worker will enqueue again later on to the right queue */
 void pkgAcqMethod::Redirect(const string &NewURI)
 {
    std::cout << "103 Redirect\nURI: " << Queue->Uri << "\n"
             << "New-URI: " << NewURI << "\n"
             << "\n" << std::flush;
 void pkgAcqMethod::Redirect(const string &NewURI)
 {
    std::cout << "103 Redirect\nURI: " << Queue->Uri << "\n"
             << "New-URI: " << NewURI << "\n"
             << "\n" << std::flush;
-
-   // Change the URI for the request.
-   Queue->Uri = NewURI;
-
-   /* To keep the pipeline synchronized, move the current request to
-      the end of the queue, past the end of the current pipeline. */
-   FetchItem *I;
-   for (I = Queue; I->Next != 0; I = I->Next) ;
-   I->Next = Queue;
-   Queue = Queue->Next;
-   I->Next->Next = 0;
-   if (QueueBack == 0)
-      QueueBack = I->Next;
+   Dequeue();
 }
                                                                         /*}}}*/
 // AcqMethod::FetchResult::FetchResult - Constructor                   /*{{{*/
 // ---------------------------------------------------------------------
 /* */
 pkgAcqMethod::FetchResult::FetchResult() : LastModified(0),
 }
                                                                         /*}}}*/
 // AcqMethod::FetchResult::FetchResult - Constructor                   /*{{{*/
 // ---------------------------------------------------------------------
 /* */
 pkgAcqMethod::FetchResult::FetchResult() : LastModified(0),
-                                   IMSHit(false), Size(0), ResumePoint(0)
+                                   IMSHit(false), Size(0), ResumePoint(0), d(NULL)
 {
 }
                                                                        /*}}}*/
 {
 }
                                                                        /*}}}*/
@@ -451,10 +476,25 @@ pkgAcqMethod::FetchResult::FetchResult() : LastModified(0),
 // ---------------------------------------------------------------------
 /* This hides the number of hashes we are supporting from the caller. 
    It just deals with the hash class. */
 // ---------------------------------------------------------------------
 /* This hides the number of hashes we are supporting from the caller. 
    It just deals with the hash class. */
-void pkgAcqMethod::FetchResult::TakeHashes(Hashes &Hash)
+void pkgAcqMethod::FetchResult::TakeHashes(class Hashes &Hash)
 {
 {
-   MD5Sum = Hash.MD5.Result();
-   SHA1Sum = Hash.SHA1.Result();
-   SHA256Sum = Hash.SHA256.Result();
+   Hashes = Hash.GetHashStringList();
 }
                                                                        /*}}}*/
 }
                                                                        /*}}}*/
+void pkgAcqMethod::Dequeue() {                                         /*{{{*/
+   FetchItem const * const Tmp = Queue;
+   Queue = Queue->Next;
+   if (Tmp == QueueBack)
+      QueueBack = Queue;
+   delete Tmp;
+}
+                                                                       /*}}}*/
+pkgAcqMethod::~pkgAcqMethod() {}
+
+pkgAcqMethod::FetchItem::FetchItem() :
+   Next(nullptr), DestFileFd(-1), LastModified(0), IndexFile(false),
+   FailIgnore(false), MaximumSize(0), d(nullptr)
+{}
+pkgAcqMethod::FetchItem::~FetchItem() {}
+
+pkgAcqMethod::FetchResult::~FetchResult() {}