X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/443f5e8a3205162ec6933529c5ca0c95ad3f6941..ea606ec43a364a8e471fd9502d79fe2dfeb6e4ba:/apt-pkg/acquire-worker.cc

diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc
index 77e2fc311..047a655ce 100644
--- a/apt-pkg/acquire-worker.cc
+++ b/apt-pkg/acquire-worker.cc
@@ -14,20 +14,23 @@
 // Include Files							/*{{{*/
 #include <config.h>
 
+#include <apt-pkg/acquire.h>
 #include <apt-pkg/acquire-worker.h>
 #include <apt-pkg/acquire-item.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/strutl.h>
+#include <apt-pkg/hashes.h>
 
+#include <string>
+#include <vector>
 #include <iostream>
 #include <sstream>
-#include <fstream>
 
 #include <sys/stat.h>
+#include <stdlib.h>
 #include <unistd.h>
-#include <fcntl.h>
 #include <signal.h>
 #include <stdio.h>
 #include <errno.h>
@@ -109,7 +112,12 @@ bool pkgAcquire::Worker::Start()
    // Get the method path
    string Method = _config->FindDir("Dir::Bin::Methods") + Access;
    if (FileExists(Method) == false)
-      return _error->Error(_("The method driver %s could not be found."),Method.c_str());
+   {
+      _error->Error(_("The method driver %s could not be found."),Method.c_str());
+      if (Access == "https")
+	 _error->Notice(_("Is the package %s installed?"), "apt-transport-https");
+      return false;
+   }
 
    if (Debug == true)
       clog << "Starting method '" << Method << '\'' << endl;
@@ -244,6 +252,21 @@ bool pkgAcquire::Worker::RunMessages()
  
             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;
+	    // Mark the item as done (taking care of all queues)
+	    // and then put it in the main queue again
+	    OwnerQ->ItemDone(Itm);
+	    OwnerQ->Owner->Enqueue(Desc);
+
+	    if (Log != 0)
+	       Log->Done(Desc);
             break;
          }
    
@@ -290,7 +313,15 @@ bool pkgAcquire::Worker::RunMessages()
 	    
 	    OwnerQ->ItemDone(Itm);
 	    unsigned long long const ServerSize = strtoull(LookupTag(Message,"Size","0").c_str(), NULL, 10);
-	    if (TotalSize != 0 && ServerSize != TotalSize)
+            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);
 
@@ -317,8 +348,7 @@ bool pkgAcquire::Worker::RunMessages()
 	    // Log that we are done
 	    if (Log != 0)
 	    {
-	       if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true ||
-		   StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false) == true)
+	       if (isHit)
 	       {
 		  /* Hide 'hits' for local only sources - we also manage to
 		     hide gets */
@@ -467,40 +497,19 @@ bool pkgAcquire::Worker::SendConfiguration()
 
    if (OutFd == -1)
       return false;
-   
-   string Message = "601 Configuration\n";
-   Message.reserve(2000);
 
-   /* Write out all of the configuration directives by walking the 
+   /* Write out all of the configuration directives by walking the
       configuration tree */
-   const Configuration::Item *Top = _config->Tree(0);
-   for (; Top != 0;)
-   {
-      if (Top->Value.empty() == false)
-      {
-	 string Line = "Config-Item: " + QuoteString(Top->FullTag(),"=\"\n") + "=";
-	 Line += QuoteString(Top->Value,"\n") + '\n';
-	 Message += Line;
-      }
-      
-      if (Top->Child != 0)
-      {
-	 Top = Top->Child;
-	 continue;
-      }
-      
-      while (Top != 0 && Top->Next == 0)
-	 Top = Top->Parent;
-      if (Top != 0)
-	 Top = Top->Next;
-   }   
-   Message += '\n';
+   std::ostringstream Message;
+   Message << "601 Configuration\n";
+   _config->Dump(Message, NULL, "Config-Item: %F=%V\n", false);
+   Message << '\n';
 
    if (Debug == true)
-      clog << " -> " << Access << ':' << QuoteString(Message,"\n") << endl;
-   OutQueue += Message;
-   OutReady = true; 
-   
+      clog << " -> " << Access << ':' << QuoteString(Message.str(),"\n") << endl;
+   OutQueue += Message.str();
+   OutReady = true;
+
    return true;
 }
 									/*}}}*/
@@ -532,10 +541,17 @@ bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item)
 /* */
 bool pkgAcquire::Worker::OutFdReady()
 {
-   if (FileFd::Write(OutFd,OutQueue.c_str(),OutQueue.length()) == false)
+   int Res;
+   do
+   {
+      Res = write(OutFd,OutQueue.c_str(),OutQueue.length());
+   }
+   while (Res < 0 && errno == EINTR);
+
+   if (Res <= 0)
       return MethodFailure();
-   
-   OutQueue.clear();
+
+   OutQueue.erase(0,Res);
    if (OutQueue.empty() == true)
       OutReady = false;
    
@@ -555,7 +571,7 @@ bool pkgAcquire::Worker::InFdReady()
 									/*}}}*/
 // Worker::MethodFailure - Called when the method fails			/*{{{*/
 // ---------------------------------------------------------------------
-/* This is called when the method is belived to have failed, probably because
+/* This is called when the method is believed to have failed, probably because
    read returned -1. */
 bool pkgAcquire::Worker::MethodFailure()
 {