]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/acquire-worker.cc
Release 1.2.3
[apt.git] / apt-pkg / acquire-worker.cc
index 8d619e96da9a1daed290d04cbab56712f0aa38fd..37804c67a098f585dadab54c018491299008a4cb 100644 (file)
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/hashes.h>
 
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/hashes.h>
 
+#include <algorithm>
 #include <string>
 #include <vector>
 #include <iostream>
 #include <string>
 #include <vector>
 #include <iostream>
-#include <sstream>
 
 #include <sys/stat.h>
 #include <stdlib.h>
 
 #include <sys/stat.h>
 #include <stdlib.h>
@@ -34,9 +34,7 @@
 #include <signal.h>
 #include <stdio.h>
 #include <errno.h>
 #include <signal.h>
 #include <stdio.h>
 #include <errno.h>
-#include <sys/types.h>
-#include <pwd.h>
-#include <grp.h>
+#include <sstream>
 
 #include <apti18n.h>
                                                                        /*}}}*/
 
 #include <apti18n.h>
                                                                        /*}}}*/
 using namespace std;
 
 // Worker::Worker - Constructor for Queue startup                      /*{{{*/
 using namespace std;
 
 // Worker::Worker - Constructor for Queue startup                      /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-pkgAcquire::Worker::Worker(Queue *Q,MethodConfig *Cnf,
-                          pkgAcquireStatus *log) : d(NULL), Log(log)
+pkgAcquire::Worker::Worker(Queue *Q, MethodConfig *Cnf, pkgAcquireStatus *log) :
+   d(NULL), OwnerQ(Q), Log(log), Config(Cnf), Access(Cnf->Access),
+   CurrentItem(nullptr), CurrentSize(0), TotalSize(0)
 {
 {
-   OwnerQ = Q;
-   Config = Cnf;
-   Access = Cnf->Access;
-   CurrentItem = 0;
-   TotalSize = 0;
-   CurrentSize = 0;
-
    Construct();
 }
                                                                        /*}}}*/
 // Worker::Worker - Constructor for method config startup              /*{{{*/
    Construct();
 }
                                                                        /*}}}*/
 // Worker::Worker - Constructor for method config startup              /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-pkgAcquire::Worker::Worker(MethodConfig *Cnf) : d(NULL), OwnerQ(NULL), Config(Cnf),
-                                               Access(Cnf->Access), CurrentItem(NULL),
-                                               CurrentSize(0), TotalSize(0)
+pkgAcquire::Worker::Worker(MethodConfig *Cnf) : Worker(nullptr, Cnf, nullptr)
 {
 {
-   Construct();
 }
                                                                        /*}}}*/
 // Worker::Construct - Constructor helper                              /*{{{*/
 }
                                                                        /*}}}*/
 // Worker::Construct - Constructor helper                              /*{{{*/
@@ -204,19 +189,22 @@ bool pkgAcquire::Worker::RunMessages()
         return _error->Error("Invalid message from method %s: %s",Access.c_str(),Message.c_str());
 
       string URI = LookupTag(Message,"URI");
         return _error->Error("Invalid message from method %s: %s",Access.c_str(),Message.c_str());
 
       string URI = LookupTag(Message,"URI");
-      pkgAcquire::Queue::QItem *Itm = 0;
+      pkgAcquire::Queue::QItem *Itm = NULL;
       if (URI.empty() == false)
         Itm = OwnerQ->FindItem(URI,this);
 
       if (URI.empty() == false)
         Itm = OwnerQ->FindItem(URI,this);
 
-      // update used mirror
-      string UsedMirror = LookupTag(Message,"UsedMirror", "");
-      if (!UsedMirror.empty() &&
-          Itm && 
-          Itm->Description.find(" ") != string::npos)
+      if (Itm != NULL)
       {
       {
-         Itm->Description.replace(0, Itm->Description.find(" "), UsedMirror);
-         // FIXME: will we need this as well?
-         //Itm->ShortDesc = UsedMirror;
+        // update used mirror
+        string UsedMirror = LookupTag(Message,"UsedMirror", "");
+        if (UsedMirror.empty() == false)
+        {
+           for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O)
+              (*O)->UsedMirror = UsedMirror;
+
+           if (Itm->Description.find(" ") != string::npos)
+              Itm->Description.replace(0, Itm->Description.find(" "), UsedMirror);
+        }
       }
 
       // Determine the message number and dispatch
       }
 
       // Determine the message number and dispatch
@@ -248,17 +236,14 @@ bool pkgAcquire::Worker::RunMessages()
                break;
             }
 
                break;
             }
 
-            string NewURI = LookupTag(Message,"New-URI",URI.c_str());
+           std::string const NewURI = LookupTag(Message,"New-URI",URI.c_str());
             Itm->URI = NewURI;
 
            ItemDone();
 
            // Change the status so that it can be dequeued
             Itm->URI = NewURI;
 
            ItemDone();
 
            // Change the status so that it can be dequeued
-           for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O)
-           {
-              pkgAcquire::Item *Owner = *O;
-              Owner->Status = pkgAcquire::Item::StatIdle;
-           }
+           for (auto const &O: Itm->Owners)
+              O->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;
            // 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;
@@ -267,12 +252,28 @@ bool pkgAcquire::Worker::RunMessages()
            for (pkgAcquire::Queue::QItem::owner_iterator O = ItmOwners.begin(); O != ItmOwners.end(); ++O)
            {
               pkgAcquire::Item *Owner = *O;
            for (pkgAcquire::Queue::QItem::owner_iterator O = ItmOwners.begin(); O != ItmOwners.end(); ++O)
            {
               pkgAcquire::Item *Owner = *O;
-              pkgAcquire::ItemDesc desc = Owner->GetItemDesc();
+              pkgAcquire::ItemDesc &desc = Owner->GetItemDesc();
+              // if we change site, treat it as a mirror change
+              if (URI::SiteOnly(NewURI) != URI::SiteOnly(desc.URI))
+              {
+                 std::string const OldSite = desc.Description.substr(0, desc.Description.find(" "));
+                 if (likely(APT::String::Startswith(desc.URI, OldSite)))
+                 {
+                    std::string const OldExtra = desc.URI.substr(OldSite.length() + 1);
+                    if (likely(APT::String::Endswith(NewURI, OldExtra)))
+                    {
+                       std::string const NewSite = NewURI.substr(0, NewURI.length() - OldExtra.length());
+                       Owner->UsedMirror = URI::ArchiveOnly(NewSite);
+                       if (desc.Description.find(" ") != string::npos)
+                          desc.Description.replace(0, desc.Description.find(" "), Owner->UsedMirror);
+                    }
+                 }
+              }
               desc.URI = NewURI;
               OwnerQ->Owner->Enqueue(desc);
 
               if (Log != 0)
               desc.URI = NewURI;
               OwnerQ->Owner->Enqueue(desc);
 
               if (Log != 0)
-                 Log->Done(Owner->GetItemDesc());
+                 Log->Done(desc);
            }
             break;
          }
            }
             break;
          }
@@ -322,9 +323,10 @@ bool pkgAcquire::Worker::RunMessages()
               for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O)
                  Log->Pulse((*O)->GetOwner());
 
               for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O)
                  Log->Pulse((*O)->GetOwner());
 
-           std::string const filename = LookupTag(Message, "Filename", Itm->Owner->DestFile.c_str());
            HashStringList ReceivedHashes;
            {
            HashStringList ReceivedHashes;
            {
+              std::string const givenfilename = LookupTag(Message, "Filename");
+              std::string const filename = givenfilename.empty() ? Itm->Owner->DestFile : givenfilename;
               // see if we got hashes to verify
               for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type)
               {
               // see if we got hashes to verify
               for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type)
               {
@@ -345,11 +347,11 @@ bool pkgAcquire::Worker::RunMessages()
                     ReceivedHashes = calc.GetHashStringList();
                  }
               }
                     ReceivedHashes = calc.GetHashStringList();
                  }
               }
-           }
 
 
-           // 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()));
+              // only local files can refer other filenames and counting them as fetched would be unfair
+              if (Log != NULL && Itm->Owner->Complete == false && Itm->Owner->Local == false && givenfilename == filename)
+                 Log->Fetched(ReceivedHashes.FileSize(),atoi(LookupTag(Message,"Resume-Point","0").c_str()));
+           }
 
            std::vector<Item*> const ItmOwners = Itm->Owners;
            OwnerQ->ItemDone(Itm);
 
            std::vector<Item*> const ItmOwners = Itm->Owners;
            OwnerQ->ItemDone(Itm);
@@ -393,13 +395,22 @@ bool pkgAcquire::Worker::RunMessages()
               else if (Owner->HashesRequired() == true)
                  consideredOkay = false;
               else
               else if (Owner->HashesRequired() == true)
                  consideredOkay = false;
               else
+              {
                  consideredOkay = true;
                  consideredOkay = true;
+                 // even if the hashes aren't usable to declare something secure
+                 // we can at least use them to declare it an integrity failure
+                 if (ExpectedHashes.empty() == false && ReceivedHashes != ExpectedHashes && _config->Find("Acquire::ForceHash").empty())
+                    consideredOkay = false;
+              }
+
+              if (consideredOkay == true)
+                 consideredOkay = Owner->VerifyDone(Message, Config);
+              else // hashsum mismatch
+                 Owner->Status = pkgAcquire::Item::StatAuthError;
 
               if (consideredOkay == true)
               {
                  Owner->Done(Message, ReceivedHashes, Config);
 
               if (consideredOkay == true)
               {
                  Owner->Done(Message, ReceivedHashes, Config);
-
-                 // Log that we are done
                  if (Log != 0)
                  {
                     if (isIMSHit)
                  if (Log != 0)
                  {
                     if (isIMSHit)
@@ -410,9 +421,7 @@ bool pkgAcquire::Worker::RunMessages()
               }
               else
               {
               }
               else
               {
-                 Owner->Status = pkgAcquire::Item::StatAuthError;
                  Owner->Failed(Message,Config);
                  Owner->Failed(Message,Config);
-
                  if (Log != 0)
                     Log->Fail(Owner->GetItemDesc());
               }
                  if (Log != 0)
                     Log->Fail(Owner->GetItemDesc());
               }
@@ -442,15 +451,18 @@ bool pkgAcquire::Worker::RunMessages()
            OwnerQ->ItemDone(Itm);
            Itm = NULL;
 
            OwnerQ->ItemDone(Itm);
            Itm = NULL;
 
+           bool errTransient;
+           {
+              std::string const failReason = LookupTag(Message, "FailReason");
+              std::string const reasons[] = { "Timeout", "ConnectionRefused",
+                 "ConnectionTimedOut", "ResolveFailure", "TmpResolveFailure" };
+              errTransient = std::find(std::begin(reasons), std::end(reasons), failReason) != std::end(reasons);
+           }
+
            for (pkgAcquire::Queue::QItem::owner_iterator O = ItmOwners.begin(); O != ItmOwners.end(); ++O)
            {
            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")
+              if (errTransient)
                  (*O)->Status = pkgAcquire::Item::StatTransientNetworkError;
                  (*O)->Status = pkgAcquire::Item::StatTransientNetworkError;
-
               (*O)->Failed(Message,Config);
 
               if (Log != 0)
               (*O)->Failed(Message,Config);
 
               if (Log != 0)
@@ -521,7 +533,7 @@ bool pkgAcquire::Worker::MediaChange(string Message)
       ostringstream msg,status;
       ioprintf(msg,_("Please insert the disc labeled: "
                     "'%s' "
       ostringstream msg,status;
       ioprintf(msg,_("Please insert the disc labeled: "
                     "'%s' "
-                    "in the drive '%s' and press enter."),
+                    "in the drive '%s' and press [Enter]."),
               Media.c_str(),Drive.c_str());
       status << "media-change: "  // message
             << Media  << ":"     // media
               Media.c_str(),Drive.c_str());
       status << "media-change: "  // message
             << Media  << ":"     // media
@@ -614,7 +626,7 @@ bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item)
 
    if (RealFileExists(Item->Owner->DestFile))
    {
 
    if (RealFileExists(Item->Owner->DestFile))
    {
-      std::string SandboxUser = _config->Find("APT::Sandbox::User");
+      std::string const SandboxUser = _config->Find("APT::Sandbox::User");
       ChangeOwnerAndPermissionOfFile("Item::QueueURI", Item->Owner->DestFile.c_str(),
                                      SandboxUser.c_str(), "root", 0600);
    }
       ChangeOwnerAndPermissionOfFile("Item::QueueURI", Item->Owner->DestFile.c_str(),
                                      SandboxUser.c_str(), "root", 0600);
    }
@@ -717,12 +729,12 @@ void pkgAcquire::Worker::PrepareFiles(char const * const caller, pkgAcquire::Que
       for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O)
       {
         pkgAcquire::Item const * const Owner = *O;
       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)
+        if (Owner->DestFile == filename || filename == "/dev/null")
            continue;
            continue;
-        unlink(Owner->DestFile.c_str());
+        RemoveFile("PrepareFiles", Owner->DestFile);
         if (link(filename.c_str(), Owner->DestFile.c_str()) != 0)
         {
         if (link(filename.c_str(), Owner->DestFile.c_str()) != 0)
         {
-           // diferent mounts can't happen for us as we download to lists/ by default,
+           // different 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
            // 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
@@ -734,7 +746,7 @@ void pkgAcquire::Worker::PrepareFiles(char const * const caller, pkgAcquire::Que
    else
    {
       for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O)
    else
    {
       for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O)
-        unlink((*O)->DestFile.c_str());
+        RemoveFile("PrepareFiles", (*O)->DestFile);
    }
 }
                                                                        /*}}}*/
    }
 }
                                                                        /*}}}*/