]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/acquire-item.cc
guard pkg/grp hashtable creation changes
[apt.git] / apt-pkg / acquire-item.cc
index 9a6e0af013a62b9b5313960242ae8e4bbab7e9d0..dd85fda79e112df34a13458ed8a6cf0cbff8496a 100644 (file)
@@ -44,9 +44,6 @@
 #include <sstream>
 #include <stdio.h>
 #include <ctime>
-#include <sys/types.h>
-#include <pwd.h>
-#include <grp.h>
 
 #include <apti18n.h>
                                                                        /*}}}*/
@@ -65,20 +62,6 @@ static void printHashSumComparision(std::string const &URI, HashStringList const
       std::cerr <<  "\t- " << hs->toStr() << std::endl;
 }
                                                                        /*}}}*/
-static void ChangeOwnerAndPermissionOfFile(char const * const requester, char const * const file, char const * const user, char const * const group, mode_t const mode) /*{{{*/
-{
-   // 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 (getuid() == 0) // if we aren't root, we can't chown, so don't try it
-   {
-      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);
-}
-                                                                       /*}}}*/
 static std::string GetPartialFileName(std::string const &file)         /*{{{*/
 {
    std::string DestFile = _config->FindDir("Dir::State::lists") + "partial/";
@@ -121,10 +104,7 @@ static bool AllowInsecureRepositories(indexRecords const * const MetaIndexParser
 
 
 // Acquire::Item::Item - Constructor                                   /*{{{*/
-#if __GNUC__ >= 4
-       #pragma GCC diagnostic push
-       #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+APT_IGNORE_DEPRECATED_PUSH
 pkgAcquire::Item::Item(pkgAcquire *Owner,
                        HashStringList const &ExpectedHashes,
                        pkgAcqMetaBase *TransactionManager)
@@ -137,9 +117,7 @@ pkgAcquire::Item::Item(pkgAcquire *Owner,
    if(TransactionManager != NULL)
       TransactionManager->Add(this);
 }
-#if __GNUC__ >= 4
-       #pragma GCC diagnostic pop
-#endif
+APT_IGNORE_DEPRECATED_POP
                                                                        /*}}}*/
 // Acquire::Item::~Item - Destructor                                   /*{{{*/
 // ---------------------------------------------------------------------
@@ -155,7 +133,7 @@ pkgAcquire::Item::~Item()
    fetch this object */
 void pkgAcquire::Item::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 {
-   if(ErrorText == "")
+   if(ErrorText.empty())
       ErrorText = LookupTag(Message,"Message");
    UsedMirror =  LookupTag(Message,"UsedMirror");
    if (QueueCounter <= 1)
@@ -179,9 +157,9 @@ void pkgAcquire::Item::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
       Status = StatIdle;
 
    // check fail reason
-   string FailReason = LookupTag(Message, "FailReason");
+   string const FailReason = LookupTag(Message, "FailReason");
    if(FailReason == "MaximumSizeExceeded")
-      Rename(DestFile, DestFile+".FAILED");
+      RenameOnError(MaximumSizeExceeded);
 
    // report mirror failure back to LP if we actually use a mirror
    if(FailReason.size() != 0)
@@ -197,6 +175,7 @@ void pkgAcquire::Item::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 void pkgAcquire::Item::Start(string /*Message*/,unsigned long long Size)
 {
    Status = StatFetching;
+   ErrorText.clear();
    if (FileSize == 0 && Complete == false)
       FileSize = Size;
 }
@@ -229,26 +208,19 @@ void pkgAcquire::Item::Done(string Message,unsigned long long Size,HashStringLis
    step */
 bool pkgAcquire::Item::Rename(string From,string To)
 {
-   if (rename(From.c_str(),To.c_str()) != 0)
-   {
-      char S[300];
-      snprintf(S,sizeof(S),_("rename failed, %s (%s -> %s)."),strerror(errno),
-             From.c_str(),To.c_str());
-      Status = StatError;
-      ErrorText += S;
-      return false;
-   }   
-   return true;
+   if (rename(From.c_str(),To.c_str()) == 0)
+      return true;
+
+   std::string S;
+   strprintf(S, _("rename failed, %s (%s -> %s)."), strerror(errno),
+        From.c_str(),To.c_str());
+   Status = StatError;
+   ErrorText += S;
+   return false;
 }
                                                                        /*}}}*/
 void pkgAcquire::Item::QueueURI(ItemDesc &Item)                                /*{{{*/
 {
-   if (RealFileExists(DestFile))
-   {
-      std::string SandboxUser = _config->Find("APT::Sandbox::User");
-      ChangeOwnerAndPermissionOfFile("Item::QueueURI", DestFile.c_str(),
-                                     SandboxUser.c_str(), "root", 0600);
-   }
    Owner->Enqueue(Item);
 }
                                                                        /*}}}*/
@@ -259,7 +231,7 @@ void pkgAcquire::Item::Dequeue()                                    /*{{{*/
                                                                        /*}}}*/
 bool pkgAcquire::Item::RenameOnError(pkgAcquire::Item::RenameOnErrorState const error)/*{{{*/
 {
-   if(FileExists(DestFile))
+   if (RealFileExists(DestFile))
       Rename(DestFile, DestFile + ".FAILED");
 
    switch (error)
@@ -284,7 +256,11 @@ bool pkgAcquire::Item::RenameOnError(pkgAcquire::Item::RenameOnErrorState const
         Status = StatError;
         break;
       case NotClearsigned:
-         ErrorText = _("Does not start with a cleartext signature");
+        ErrorText = _("Does not start with a cleartext signature");
+        Status = StatError;
+        break;
+      case MaximumSizeExceeded:
+        // the method is expected to report a good error for this
         Status = StatError;
         break;
    }
@@ -294,14 +270,7 @@ bool pkgAcquire::Item::RenameOnError(pkgAcquire::Item::RenameOnErrorState const
 void pkgAcquire::Item::SetActiveSubprocess(const std::string &subprocess)/*{{{*/
 {
       ActiveSubprocess = subprocess;
-#if __GNUC__ >= 4
-       #pragma GCC diagnostic push
-       #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-        Mode = ActiveSubprocess.c_str();
-#if __GNUC__ >= 4
-       #pragma GCC diagnostic pop
-#endif
+      APT_IGNORE_DEPRECATED(Mode = ActiveSubprocess.c_str();)
 }
                                                                        /*}}}*/
 // Acquire::Item::ReportMirrorFailure                                  /*{{{*/
@@ -318,30 +287,31 @@ void pkgAcquire::Item::ReportMirrorFailure(string FailCode)
             << " FailCode: " 
             << FailCode << std::endl;
 #endif
-   const char *Args[40];
-   unsigned int i = 0;
    string report = _config->Find("Methods::Mirror::ProblemReporting", 
                                 "/usr/lib/apt/apt-report-mirror-failure");
    if(!FileExists(report))
       return;
-   Args[i++] = report.c_str();
-   Args[i++] = UsedMirror.c_str();
-   Args[i++] = DescURI().c_str();
-   Args[i++] = FailCode.c_str();
-   Args[i++] = NULL;
+
+   std::vector<char const*> Args;
+   Args.push_back(report.c_str());
+   Args.push_back(UsedMirror.c_str());
+   Args.push_back(DescURI().c_str());
+   Args.push_back(FailCode.c_str());
+   Args.push_back(NULL);
+
    pid_t pid = ExecFork();
-   if(pid < 0) 
+   if(pid < 0)
    {
       _error->Error("ReportMirrorFailure Fork failed");
       return;
    }
-   else if(pid == 0) 
+   else if(pid == 0)
    {
-      execvp(Args[0], (char**)Args);
+      execvp(Args[0], (char**)Args.data());
       std::cerr << "Could not exec " << Args[0] << std::endl;
       _exit(100);
    }
-   if(!ExecWait(pid, "report-mirror-failure")) 
+   if(!ExecWait(pid, "report-mirror-failure"))
    {
       _error->Warning("Couldn't report problem to '%s'",
                      _config->Find("Methods::Mirror::ProblemReporting").c_str());
@@ -403,7 +373,11 @@ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner,
 // AcqIndex::Custom600Headers - Insert custom request headers          /*{{{*/
 // ---------------------------------------------------------------------
 /* The only header we use is the last-modified header. */
+#if APT_PKG_ABI >= 413
 string pkgAcqDiffIndex::Custom600Headers() const
+#else
+string pkgAcqDiffIndex::Custom600Headers()
+#endif
 {
    string Final = _config->FindDir("Dir::State::lists");
    Final += URItoFileName(Desc.URI);
@@ -637,7 +611,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)          /*{{{*/
         cur != available_patches.end(); ++cur)
       patchesSize += cur->patch_size;
    unsigned long long const sizeLimit = ServerSize * _config->FindI("Acquire::PDiffs::SizeLimit", 100);
-   if (false && sizeLimit > 0 && (sizeLimit/100) < patchesSize)
+   if (sizeLimit > 0 && (sizeLimit/100) < patchesSize)
    {
       if (Debug)
         std::clog << "Need " << patchesSize << " bytes (Limit is " << sizeLimit/100
@@ -702,14 +676,14 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)                /*{{{*/
                                                                        /*}}}*/
 void pkgAcqDiffIndex::Failed(string Message,pkgAcquire::MethodConfig * Cnf)/*{{{*/
 {
+   Item::Failed(Message,Cnf);
+   Status = StatDone;
+
    if(Debug)
       std::clog << "pkgAcqDiffIndex failed: " << Desc.URI << " with " << Message << std::endl
                << "Falling back to normal index file acquire" << std::endl;
 
    new pkgAcqIndex(Owner, TransactionManager, Target, ExpectedHashes, MetaIndexParser);
-
-   Item::Failed(Message,Cnf);
-   Status = StatDone;
 }
                                                                        /*}}}*/
 void pkgAcqDiffIndex::Done(string Message,unsigned long long Size,HashStringList const &Hashes,        /*{{{*/
@@ -792,8 +766,11 @@ pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner,
    }
 }
                                                                        /*}}}*/
-void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig * /*Cnf*/)/*{{{*/
+void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig * Cnf)/*{{{*/
 {
+   Item::Failed(Message,Cnf);
+   Status = StatDone;
+
    if(Debug)
       std::clog << "pkgAcqIndexDiffs failed: " << Desc.URI << " with " << Message << std::endl
                << "Falling back to normal index file acquire" << std::endl;
@@ -1266,7 +1243,11 @@ void pkgAcqIndex::InitByHashIfNeeded(const std::string MetaKey)
 // AcqIndex::Custom600Headers - Insert custom request headers          /*{{{*/
 // ---------------------------------------------------------------------
 /* The only header we use is the last-modified header. */
+#if APT_PKG_ABI >= 413
 string pkgAcqIndex::Custom600Headers() const
+#else
+string pkgAcqIndex::Custom600Headers()
+#endif
 {
    string Final = GetFinalFilename();
 
@@ -1275,17 +1256,23 @@ string pkgAcqIndex::Custom600Headers() const
    if (stat(Final.c_str(),&Buf) == 0)
       msg += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
 
+   if(Target->IsOptional())
+      msg += "\nFail-Ignore: true";
+
    return msg;
 }
                                                                        /*}}}*/
 // pkgAcqIndex::Failed - getting the indexfile failed                  /*{{{*/
 void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 {
+   Item::Failed(Message,Cnf);
+
    size_t const nextExt = CompressionExtensions.find(' ');
    if (nextExt != std::string::npos)
    {
       CompressionExtensions = CompressionExtensions.substr(nextExt+1);
       Init(RealURI, Desc.Description, Desc.ShortDesc);
+      Status = StatIdle;
       return;
    }
 
@@ -1297,8 +1284,10 @@ void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 
    Item::Failed(Message,Cnf);
 
-   /// cancel the entire transaction
-   TransactionManager->AbortTransaction();
+   if(Target->IsOptional() && ExpectedHashes.empty() && Stage == STAGE_DOWNLOAD)
+      Status = StatDone;
+   else
+      TransactionManager->AbortTransaction();
 }
                                                                        /*}}}*/
 // pkgAcqIndex::GetFinalFilename - Return the full final file path     /*{{{*/
@@ -1490,57 +1479,6 @@ void pkgAcqIndex::StageDecompressDone(string Message,
    return;
 }
                                                                        /*}}}*/
-// AcqIndexTrans::pkgAcqIndexTrans - Constructor                       /*{{{*/
-// ---------------------------------------------------------------------
-/* The Translation file is added to the queue */
-pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner,
-                           string URI,string URIDesc,string ShortDesc)
-  : pkgAcqIndex(Owner, URI, URIDesc, ShortDesc, HashStringList())
-{
-}
-pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner,
-                                   pkgAcqMetaBase *TransactionManager,
-                                   IndexTarget const * const Target,
-                                   HashStringList const &ExpectedHashes,
-                                   indexRecords *MetaIndexParser)
-   : pkgAcqIndex(Owner, TransactionManager, Target, ExpectedHashes, MetaIndexParser)
-{
-}
-                                                                       /*}}}*/
-// AcqIndexTrans::Custom600Headers - Insert custom request headers     /*{{{*/
-string pkgAcqIndexTrans::Custom600Headers() const
-{
-   string Final = GetFinalFilename();
-
-   struct stat Buf;
-   if (stat(Final.c_str(),&Buf) != 0)
-      return "\nFail-Ignore: true\nIndex-File: true";
-   return "\nFail-Ignore: true\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
-}
-                                                                       /*}}}*/
-// AcqIndexTrans::Failed - Silence failure messages for missing files  /*{{{*/
-void pkgAcqIndexTrans::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
-{
-   size_t const nextExt = CompressionExtensions.find(' ');
-   if (nextExt != std::string::npos)
-   {
-      CompressionExtensions = CompressionExtensions.substr(nextExt+1);
-      Init(RealURI, Desc.Description, Desc.ShortDesc);
-      Status = StatIdle;
-      return;
-   }
-
-   Item::Failed(Message,Cnf);
-
-   // FIXME: this is used often (e.g. in pkgAcqIndexTrans) so refactor
-   if (Cnf->LocalOnly == true ||
-       StringToBool(LookupTag(Message,"Transient-Failure"),false) == false)
-   {
-      // Ignore this
-      Status = StatDone;
-   }
-}
-                                                                       /*}}}*/
 // AcqMetaBase::Add - Add a item to the current Transaction            /*{{{*/
 void pkgAcqMetaBase::Add(Item *I)
 {
@@ -1561,19 +1499,10 @@ void pkgAcqMetaBase::AbortTransaction()
          std::clog << "  Cancel: " << (*I)->DestFile << std::endl;
       // the transaction will abort, so stop anything that is idle
       if ((*I)->Status == pkgAcquire::Item::StatIdle)
-         (*I)->Status = pkgAcquire::Item::StatDone;
-
-      // kill failed files in partial
-      if ((*I)->Status == pkgAcquire::Item::StatError)
       {
-         std::string const PartialFile = GetPartialFileName(flNotDir((*I)->DestFile));
-         if(FileExists(PartialFile))
-            Rename(PartialFile, PartialFile + ".FAILED");
+         (*I)->Status = pkgAcquire::Item::StatDone;
+         (*I)->Dequeue();
       }
-      // fix permissions for existing files which were part of a reverify
-      // like InRelease files or files in partial we might work with next time
-      else if (FileExists((*I)->DestFile))
-        ChangeOwnerAndPermissionOfFile("AbortTransaction", (*I)->DestFile.c_str(), "root", "root", 0644);
    }
    Transaction.clear();
 }
@@ -1608,8 +1537,6 @@ void pkgAcqMetaBase::CommitTransaction()
               << (*I)->DescURI() << std::endl;
 
         Rename((*I)->PartialFile, (*I)->DestFile);
-        ChangeOwnerAndPermissionOfFile("CommitTransaction", (*I)->DestFile.c_str(), "root", "root", 0644);
-
       } else {
          if(_config->FindB("Debug::Acquire::Transaction", false) == true)
             std::clog << "rm "
@@ -1719,7 +1646,11 @@ pkgAcqMetaSig::~pkgAcqMetaSig()                                          /*{{{*/
                                                                        /*}}}*/
 // pkgAcqMetaSig::Custom600Headers - Insert custom request headers     /*{{{*/
 // ---------------------------------------------------------------------
+#if APT_PKG_ABI >= 413
 string pkgAcqMetaSig::Custom600Headers() const
+#else
+string pkgAcqMetaSig::Custom600Headers()
+#endif
 {
    std::string Header = GetCustom600Headers(RealURI);
    return Header;
@@ -1758,16 +1689,17 @@ void pkgAcqMetaSig::Done(string Message,unsigned long long Size,
                                                                        /*}}}*/
 void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/
 {
-   string Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
+   Item::Failed(Message,Cnf);
 
    // check if we need to fail at this point 
    if (AuthPass == true && CheckStopAuthentication(RealURI, Message))
          return;
 
    // FIXME: meh, this is not really elegant
-   string InReleaseURI = RealURI.replace(RealURI.rfind("Release.gpg"), 12,
+   string const Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
+   string const InReleaseURI = RealURI.replace(RealURI.rfind("Release.gpg"), 12,
                                          "InRelease");
-   string FinalInRelease = _config->FindDir("Dir::State::lists") + URItoFileName(InReleaseURI);
+   string const FinalInRelease = _config->FindDir("Dir::State::lists") + URItoFileName(InReleaseURI);
 
    if (RealFileExists(Final) || RealFileExists(FinalInRelease))
    {
@@ -1782,7 +1714,7 @@ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/
          _error->Warning(_("This is normally not allowed, but the option "
                            "Acquire::AllowDowngradeToInsecureRepositories was "
                            "given to override it."));
-         
+         Status = StatDone;
       } else {
          _error->Error("%s", downgrade_msg.c_str());
          Rename(MetaIndexFile, MetaIndexFile+".FAILED");
@@ -1810,8 +1742,6 @@ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/
       QueueIndexes(true);
    }
 
-   Item::Failed(Message,Cnf);
-
    // FIXME: this is used often (e.g. in pkgAcqIndexTrans) so refactor
    if (Cnf->LocalOnly == true ||
        StringToBool(LookupTag(Message,"Transient-Failure"),false) == false)
@@ -1865,7 +1795,11 @@ void pkgAcqMetaIndex::Init(std::string URIDesc, std::string ShortDesc)
                                                                        /*}}}*/
 // pkgAcqMetaIndex::Custom600Headers - Insert custom request headers   /*{{{*/
 // ---------------------------------------------------------------------
+#if APT_PKG_ABI >= 413
 string pkgAcqMetaIndex::Custom600Headers() const
+#else
+string pkgAcqMetaIndex::Custom600Headers()
+#endif
 {
    return GetCustom600Headers(RealURI);
 }
@@ -1999,87 +1933,59 @@ bool pkgAcqMetaBase::CheckDownloadDone(const std::string &Message,
                                                                        /*}}}*/
 void pkgAcqMetaBase::QueueIndexes(bool verify)                         /*{{{*/
 {
-   bool transInRelease = false;
-   {
-      std::vector<std::string> const keys = MetaIndexParser->MetaKeys();
-      for (std::vector<std::string>::const_iterator k = keys.begin(); k != keys.end(); ++k)
-        // FIXME: Feels wrong to check for hardcoded string here, but what should we do elseā€¦
-        if (k->find("Translation-") != std::string::npos)
-        {
-           transInRelease = true;
-           break;
-        }
-   }
-
    // at this point the real Items are loaded in the fetcher
    ExpectedAdditionalItems = 0;
-   for (vector <IndexTarget*>::const_iterator Target = IndexTargets->begin();
+
+   vector <struct IndexTarget*>::const_iterator Target;
+   for (Target = IndexTargets->begin();
         Target != IndexTargets->end();
         ++Target)
    {
       HashStringList ExpectedIndexHashes;
       const indexRecords::checkSum *Record = MetaIndexParser->Lookup((*Target)->MetaKey);
-      bool compressedAvailable = false;
-      if (Record == NULL)
+
+      // optional target that we do not have in the Release file are 
+      // skipped
+      if (verify == true && Record == NULL && (*Target)->IsOptional())
+         continue;
+
+      // targets without a hash record are a error when verify is required
+      if (verify == true && Record == NULL)
       {
-        if ((*Target)->IsOptional() == true)
-        {
-           std::vector<std::string> types = APT::Configuration::getCompressionTypes();
-           for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
-              if (MetaIndexParser->Exists((*Target)->MetaKey + "." + *t) == true)
-              {
-                 compressedAvailable = true;
-                 break;
-              }
-        }
-        else if (verify == true)
-        {
-           Status = StatAuthError;
-           strprintf(ErrorText, _("Unable to find expected entry '%s' in Release file (Wrong sources.list entry or malformed file)"), (*Target)->MetaKey.c_str());
-           return;
-        }
+         Status = StatAuthError;
+         strprintf(ErrorText, _("Unable to find expected entry '%s' in Release file (Wrong sources.list entry or malformed file)"), (*Target)->MetaKey.c_str());
+         return;
       }
-      else
+
+      if (Record)
+         ExpectedIndexHashes = Record->Hashes;
+      
+      if (_config->FindB("Debug::pkgAcquire::Auth", false))
       {
-        ExpectedIndexHashes = Record->Hashes;
-        if (_config->FindB("Debug::pkgAcquire::Auth", false))
-        {
-           std::cerr << "Queueing: " << (*Target)->URI << std::endl
-              << "Expected Hash:" << std::endl;
-           for (HashStringList::const_iterator hs = ExpectedIndexHashes.begin(); hs != ExpectedIndexHashes.end(); ++hs)
-              std::cerr <<  "\t- " << hs->toStr() << std::endl;
-           std::cerr << "For: " << Record->MetaKeyFilename << std::endl;
-        }
-        if (verify == true && ExpectedIndexHashes.empty() == true && (*Target)->IsOptional() == false)
-        {
-           Status = StatAuthError;
-           strprintf(ErrorText, _("Unable to find hash sum for '%s' in Release file"), (*Target)->MetaKey.c_str());
-           return;
-        }
-      }
+         std::cerr << "Queueing: " << (*Target)->URI << std::endl
+                   << "Expected Hash:" << std::endl;
+         for (HashStringList::const_iterator hs = ExpectedIndexHashes.begin(); hs != ExpectedIndexHashes.end(); ++hs)
+            std::cerr <<  "\t- " << hs->toStr() << std::endl;
+         std::cerr << "For: " << Record->MetaKeyFilename << std::endl;
 
-      if ((*Target)->IsOptional() == true)
+      }
+      if (verify == true && ExpectedIndexHashes.empty() == true)
       {
-        if (transInRelease == false || Record != NULL || compressedAvailable == true)
-        {
-           if (_config->FindB("Acquire::PDiffs",true) == true && transInRelease == true &&
-               MetaIndexParser->Exists((*Target)->MetaKey + ".diff/Index") == true)
-              new pkgAcqDiffIndex(Owner, TransactionManager, *Target, ExpectedIndexHashes, MetaIndexParser);
-           else
-              new pkgAcqIndexTrans(Owner, TransactionManager, *Target, ExpectedIndexHashes, MetaIndexParser);
-        }
-        continue;
+         Status = StatAuthError;
+         strprintf(ErrorText, _("Unable to find hash sum for '%s' in Release file"), (*Target)->MetaKey.c_str());
+         return;
       }
 
-      /* Queue Packages file (either diff or full packages files, depending
+      /* Queue the Index file (Packages, Sources, Translation-$foo
+         (either diff or full packages files, depending
          on the users option) - we also check if the PDiff Index file is listed
          in the Meta-Index file. Ideal would be if pkgAcqDiffIndex would test this
          instead, but passing the required info to it is to much hassle */
       if(_config->FindB("Acquire::PDiffs",true) == true && (verify == false ||
-         MetaIndexParser->Exists((*Target)->MetaKey + ".diff/Index") == true))
-        new pkgAcqDiffIndex(Owner, TransactionManager, *Target, ExpectedIndexHashes, MetaIndexParser);
+          MetaIndexParser->Exists((*Target)->MetaKey + ".diff/Index") == true))
+         new pkgAcqDiffIndex(Owner, TransactionManager, *Target, ExpectedIndexHashes, MetaIndexParser);
       else
-        new pkgAcqIndex(Owner, TransactionManager, *Target, ExpectedIndexHashes, MetaIndexParser);
+         new pkgAcqIndex(Owner, TransactionManager, *Target, ExpectedIndexHashes, MetaIndexParser);
    }
 }
                                                                        /*}}}*/
@@ -2217,7 +2123,11 @@ pkgAcqMetaClearSig::~pkgAcqMetaClearSig()                                /*{{{*/
                                                                        /*}}}*/
 // pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers        /*{{{*/
 // ---------------------------------------------------------------------
+#if APT_PKG_ABI >= 413
 string pkgAcqMetaClearSig::Custom600Headers() const
+#else
+string pkgAcqMetaClearSig::Custom600Headers()
+#endif
 {
    string Header = GetCustom600Headers(RealURI);
    Header += "\nFail-Ignore: true";
@@ -2226,10 +2136,12 @@ string pkgAcqMetaClearSig::Custom600Headers() const
                                                                        /*}}}*/
 // pkgAcqMetaClearSig::Done - We got a file                            /*{{{*/
 // ---------------------------------------------------------------------
-void pkgAcqMetaClearSig::Done(std::string Message,unsigned long long /*Size*/,
-                              HashStringList const &/*Hashes*/,
+void pkgAcqMetaClearSig::Done(std::string Message,unsigned long long Size,
+                              HashStringList const &Hashes,
                               pkgAcquire::MethodConfig *Cnf)
 {
+   Item::Done(Message, Size, Hashes, Cnf);
+
    // if we expect a ClearTextSignature (InRelase), ensure that
    // this is what we get and if not fail to queue a 
    // Release/Release.gpg, see #346386
@@ -2494,11 +2406,7 @@ bool pkgAcqArchive::QueueNext()
         if ((unsigned long long)Buf.st_size > Version->Size)
            unlink(DestFile.c_str());
         else
-        {
            PartialSize = Buf.st_size;
-            std::string SandboxUser = _config->Find("APT::Sandbox::User");
-           ChangeOwnerAndPermissionOfFile("pkgAcqArchive::QueueNext",DestFile.c_str(), SandboxUser.c_str(), "root", 0600);
-        }
       }
 
       // Disables download of archives - useful if no real installation follows,
@@ -2567,7 +2475,6 @@ void pkgAcqArchive::Done(string Message,unsigned long long Size, HashStringList
    string FinalFile = _config->FindDir("Dir::Cache::Archives");
    FinalFile += flNotDir(StoreFilename);
    Rename(DestFile,FinalFile);
-   ChangeOwnerAndPermissionOfFile("pkgAcqArchive::Done", FinalFile.c_str(), "root", "root", 0644);
    StoreFilename = DestFile = FinalFile;
    Complete = true;
 }
@@ -2577,8 +2484,8 @@ void pkgAcqArchive::Done(string Message,unsigned long long Size, HashStringList
 /* Here we try other sources */
 void pkgAcqArchive::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 {
-   ErrorText = LookupTag(Message,"Message");
-   
+   Item::Failed(Message,Cnf);
+
    /* We don't really want to retry on failed media swaps, this prevents 
       that. An interesting observation is that permanent failures are not
       recorded. */
@@ -2588,10 +2495,10 @@ void pkgAcqArchive::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
       // Vf = Version.FileList();
       while (Vf.end() == false) ++Vf;
       StoreFilename = string();
-      Item::Failed(Message,Cnf);
       return;
    }
-   
+
+   Status = StatIdle;
    if (QueueNext() == false)
    {
       // This is the retry counter
@@ -2604,15 +2511,19 @@ void pkgAcqArchive::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
         if (QueueNext() == true)
            return;
       }
-      
+
       StoreFilename = string();
-      Item::Failed(Message,Cnf);
+      Status = StatError;
    }
 }
                                                                        /*}}}*/
 // AcqArchive::IsTrusted - Determine whether this archive comes from a trusted source /*{{{*/
 // ---------------------------------------------------------------------
+#if APT_PKG_ABI >= 413
 APT_PURE bool pkgAcqArchive::IsTrusted() const
+#else
+APT_PURE bool pkgAcqArchive::IsTrusted()
+#endif
 {
    return Trusted;
 }
@@ -2663,11 +2574,7 @@ pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI, HashStringList const &Hashe
       if ((Size > 0) && (unsigned long long)Buf.st_size > Size)
         unlink(DestFile.c_str());
       else
-      {
         PartialSize = Buf.st_size;
-         std::string SandboxUser = _config->Find("APT::Sandbox::User");
-        ChangeOwnerAndPermissionOfFile("pkgAcqFile", DestFile.c_str(), SandboxUser.c_str(), "root", 0600);
-      }
    }
 
    QueueURI(Desc);
@@ -2726,7 +2633,12 @@ void pkgAcqFile::Done(string Message,unsigned long long Size,HashStringList cons
       // Symlink the file
       if (symlink(FileName.c_str(),DestFile.c_str()) != 0)
       {
-        ErrorText = "Link to " + DestFile + " failure ";
+        _error->PushToStack();
+        _error->Errno("pkgAcqFile::Done", "Symlinking file %s failed", DestFile.c_str());
+        std::stringstream msg;
+        _error->DumpErrors(msg);
+        _error->RevertToStack();
+        ErrorText = msg.str();
         Status = StatError;
         Complete = false;
       }      
@@ -2738,25 +2650,29 @@ void pkgAcqFile::Done(string Message,unsigned long long Size,HashStringList cons
 /* Here we try other sources */
 void pkgAcqFile::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 {
-   ErrorText = LookupTag(Message,"Message");
-   
+   Item::Failed(Message,Cnf);
+
    // This is the retry counter
    if (Retries != 0 &&
        Cnf->LocalOnly == false &&
        StringToBool(LookupTag(Message,"Transient-Failure"),false) == true)
    {
-      Retries--;
+      --Retries;
       QueueURI(Desc);
+      Status = StatIdle;
       return;
    }
-   
-   Item::Failed(Message,Cnf);
+
 }
                                                                        /*}}}*/
 // AcqIndex::Custom600Headers - Insert custom request headers          /*{{{*/
 // ---------------------------------------------------------------------
 /* The only header we use is the last-modified header. */
+#if APT_PKG_ABI >= 413
 string pkgAcqFile::Custom600Headers() const
+#else
+string pkgAcqFile::Custom600Headers()
+#endif
 {
    if (IsIndexFile)
       return "\nIndex-File: true";