]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/acquire-item.cc
better non-virtual metaIndex.LocalFileName() implementation
[apt.git] / apt-pkg / acquire-item.cc
index 5d0a00055501ca1235746209a7cb8ca76a5cd9c8..2df638a83d5da21657377d7db0f50c22222b08f6 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,36 +62,49 @@ 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)
+static std::string GetPartialFileName(std::string const &file)         /*{{{*/
 {
    std::string DestFile = _config->FindDir("Dir::State::lists") + "partial/";
    DestFile += file;
    return DestFile;
 }
-static std::string GetPartialFileNameFromURI(std::string const &uri)
+                                                                       /*}}}*/
+static std::string GetPartialFileNameFromURI(std::string const &uri)   /*{{{*/
 {
    return GetPartialFileName(URItoFileName(uri));
 }
+                                                                       /*}}}*/
+static std::string GetCompressedFileName(std::string const &URI, std::string const &Name, std::string const &Ext) /*{{{*/
+{
+   if (Ext.empty() || Ext == "uncompressed")
+      return Name;
+
+   // do not reverify cdrom sources as apt-cdrom may rewrite the Packages
+   // file when its doing the indexcopy
+   if (URI.substr(0,6) == "cdrom:")
+      return Name;
+
+   // adjust DestFile if its compressed on disk
+   if (_config->FindB("Acquire::GzipIndexes",false) == true)
+      return Name + '.' + Ext;
+   return Name;
+}
+                                                                       /*}}}*/
+static bool AllowInsecureRepositories(indexRecords const * const MetaIndexParser, pkgAcqMetaBase * const TransactionManager, pkgAcquire::Item * const I) /*{{{*/
+{
+   if(MetaIndexParser->IsAlwaysTrusted() || _config->FindB("Acquire::AllowInsecureRepositories") == true)
+      return true;
+
+   _error->Error(_("Use --allow-insecure-repositories to force the update"));
+   TransactionManager->AbortTransaction();
+   I->Status = pkgAcquire::Item::StatError;
+   return false;
+}
+                                                                       /*}}}*/
 
 
 // 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)
@@ -107,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                                   /*{{{*/
 // ---------------------------------------------------------------------
@@ -125,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)
@@ -148,8 +156,12 @@ void pkgAcquire::Item::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
    else
       Status = StatIdle;
 
+   // check fail reason
+   string const FailReason = LookupTag(Message, "FailReason");
+   if(FailReason == "MaximumSizeExceeded")
+      RenameOnError(MaximumSizeExceeded);
+
    // report mirror failure back to LP if we actually use a mirror
-   string FailReason = LookupTag(Message, "FailReason");
    if(FailReason.size() != 0)
       ReportMirrorFailure(FailReason);
    else
@@ -163,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;
 }
@@ -195,33 +208,30 @@ 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)
+void pkgAcquire::Item::QueueURI(ItemDesc &Item)                                /*{{{*/
 {
-   if (RealFileExists(DestFile))
-      ChangeOwnerAndPermissionOfFile("GetPartialFileName", DestFile.c_str(), "_apt", "root", 0600);
    Owner->Enqueue(Item);
 }
-void pkgAcquire::Item::Dequeue()
+                                                                       /*}}}*/
+void pkgAcquire::Item::Dequeue()                                       /*{{{*/
 {
    Owner->Dequeue(this);
 }
-
+                                                                       /*}}}*/
 bool pkgAcquire::Item::RenameOnError(pkgAcquire::Item::RenameOnErrorState const error)/*{{{*/
 {
-   if(FileExists(DestFile))
+   if (RealFileExists(DestFile))
       Rename(DestFile, DestFile + ".FAILED");
 
    switch (error)
@@ -246,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;
    }
@@ -256,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                                  /*{{{*/
@@ -280,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());
@@ -599,7 +607,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
@@ -664,14 +672,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,        /*{{{*/
@@ -754,8 +762,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;
@@ -1064,10 +1075,9 @@ void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStri
       for (std::vector<pkgAcqIndexMergeDiffs *>::const_iterator I = allPatches->begin();
            I != allPatches->end(); ++I)
       {
-            std::string const PartialFile = GetPartialFileNameFromURI(RealURI);
-           std::string patch = PartialFile + ".ed." + (*I)->patch.file + ".gz";
-            std::cerr << patch << std::endl;
-           unlink(patch.c_str());
+        std::string const PartialFile = GetPartialFileNameFromURI(RealURI);
+        std::string patch = PartialFile + ".ed." + (*I)->patch.file + ".gz";
+        unlink(patch.c_str());
       }
 
       // all set and done
@@ -1238,17 +1248,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;
    }
 
@@ -1260,8 +1276,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     /*{{{*/
@@ -1269,9 +1287,7 @@ std::string pkgAcqIndex::GetFinalFilename() const
 {
    std::string FinalFile = _config->FindDir("Dir::State::lists");
    FinalFile += URItoFileName(RealURI);
-   if (_config->FindB("Acquire::GzipIndexes",false) == true)
-      FinalFile += '.' + CurrentCompressionExtension;
-   return FinalFile;
+   return GetCompressedFileName(RealURI, FinalFile, CurrentCompressionExtension);
 }
                                                                        /*}}}*/
 // AcqIndex::ReverifyAfterIMS - Reverify index after an ims-hit                /*{{{*/
@@ -1279,11 +1295,7 @@ void pkgAcqIndex::ReverifyAfterIMS()
 {
    // update destfile to *not* include the compression extension when doing
    // a reverify (as its uncompressed on disk already)
-   DestFile = GetPartialFileNameFromURI(RealURI);
-
-   // adjust DestFile if its compressed on disk
-   if (_config->FindB("Acquire::GzipIndexes",false) == true)
-      DestFile += '.' + CurrentCompressionExtension;
+   DestFile = GetCompressedFileName(RealURI, GetPartialFileNameFromURI(RealURI), CurrentCompressionExtension);
 
    // copy FinalFile into partial/ so that we check the hash again
    string FinalFile = GetFinalFilename();
@@ -1391,11 +1403,6 @@ void pkgAcqIndex::StageDownloadDone(string Message,
    // on if-modfied-since hit to avoid a stale attack against us
    if(StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
    {
-      // do not reverify cdrom sources as apt-cdrom may rewrite the Packages
-      // file when its doing the indexcopy
-      if (RealURI.substr(0,6) == "cdrom:")
-         return;
-
       // The files timestamp matches, reverify by copy into partial/
       EraseFileName = "";
       ReverifyAfterIMS();
@@ -1464,61 +1471,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)
-{
-   // load the filesize
-   indexRecords::checkSum *Record = MetaIndexParser->Lookup(string(Target->MetaKey));
-   if(Record)
-      FileSize = Record->Size;
-}
-                                                                       /*}}}*/
-// 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)
 {
@@ -1539,13 +1491,12 @@ 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 files in partial
-      std::string const PartialFile = GetPartialFileName(flNotDir((*I)->DestFile));
-      if(FileExists(PartialFile))
-         Rename(PartialFile, PartialFile + ".FAILED");
+         (*I)->Dequeue();
+      }
    }
+   Transaction.clear();
 }
                                                                        /*}}}*/
 // AcqMetaBase::TransactionHasError - Check for errors in Transaction  /*{{{*/
@@ -1578,8 +1529,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 "
@@ -1592,6 +1541,7 @@ void pkgAcqMetaBase::CommitTransaction()
       // mark that this transaction is finished
       (*I)->TransactionManager = 0;
    }
+   Transaction.clear();
 }
                                                                        /*}}}*/
 // AcqMetaBase::TransactionStageCopy - Stage a file for copying                /*{{{*/
@@ -1690,14 +1640,8 @@ pkgAcqMetaSig::~pkgAcqMetaSig()                                          /*{{{*/
 // ---------------------------------------------------------------------
 string pkgAcqMetaSig::Custom600Headers() const
 {
-   string FinalFile = _config->FindDir("Dir::State::lists");
-   FinalFile += URItoFileName(RealURI);
-
-   struct stat Buf;
-   if (stat(FinalFile.c_str(),&Buf) != 0)
-      return "\nIndex-File: true";
-
-   return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
+   std::string Header = GetCustom600Headers(RealURI);
+   return Header;
 }
                                                                        /*}}}*/
 // pkgAcqMetaSig::Done - The signature was downloaded/verified         /*{{{*/
@@ -1733,16 +1677,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))
    {
@@ -1757,7 +1702,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");
@@ -1766,6 +1711,10 @@ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/
          return;
       }
    }
+   else
+      _error->Warning(_("The data from '%s' is not signed. Packages "
+              "from that repository can not be authenticated."),
+           URIDesc.c_str());
 
    // this ensures that any file in the lists/ dir is removed by the
    // transaction
@@ -1773,20 +1722,14 @@ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/
    TransactionManager->TransactionStageRemoval(this, DestFile);
 
    // only allow going further if the users explicitely wants it
-   if(_config->FindB("Acquire::AllowInsecureRepositories") == true)
+   if(AllowInsecureRepositories(MetaIndexParser, TransactionManager, this) == true)
    {
       // we parse the indexes here because at this point the user wanted
       // a repository that may potentially harm him
       MetaIndexParser->Load(MetaIndexFile);
       QueueIndexes(true);
-   } 
-   else 
-   {
-      _error->Warning("Use --allow-insecure-repositories to force the update");
    }
 
-   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)
@@ -1842,14 +1785,7 @@ void pkgAcqMetaIndex::Init(std::string URIDesc, std::string ShortDesc)
 // ---------------------------------------------------------------------
 string pkgAcqMetaIndex::Custom600Headers() const
 {
-   string Final = _config->FindDir("Dir::State::lists");
-   Final += URItoFileName(RealURI);
-   
-   struct stat Buf;
-   if (stat(Final.c_str(),&Buf) != 0)
-      return "\nIndex-File: true";
-   
-   return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
+   return GetCustom600Headers(RealURI);
 }
                                                                        /*}}}*/
 void pkgAcqMetaIndex::Done(string Message,unsigned long long Size,     /*{{{*/
@@ -1910,6 +1846,26 @@ bool pkgAcqMetaBase::CheckAuthDone(string Message, const string &RealURI)        /*{{{*
    return true;
 }
                                                                        /*}}}*/
+// pkgAcqMetaBase::GetCustom600Headers - Get header for AcqMetaBase     /*{{{*/
+// ---------------------------------------------------------------------
+string pkgAcqMetaBase::GetCustom600Headers(const string &RealURI) const
+{
+   std::string Header = "\nIndex-File: true";
+   std::string MaximumSize;
+   strprintf(MaximumSize, "\nMaximum-Size: %i",
+             _config->FindI("Acquire::MaxReleaseFileSize", 10*1000*1000));
+   Header += MaximumSize;
+
+   string FinalFile = _config->FindDir("Dir::State::lists");
+   FinalFile += URItoFileName(RealURI);
+
+   struct stat Buf;
+   if (stat(FinalFile.c_str(),&Buf) == 0)
+      Header += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
+
+   return Header;
+}
+                                                                       /*}}}*/
 // pkgAcqMetaBase::QueueForSignatureVerify                             /*{{{*/
 void pkgAcqMetaBase::QueueForSignatureVerify(const std::string &MetaIndexFile,
                                     const std::string &MetaIndexFileSignature)
@@ -1961,87 +1917,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);
    }
 }
                                                                        /*}}}*/
@@ -2138,7 +2066,7 @@ void pkgAcqMetaIndex::Failed(string Message,
    // No Release file was present so fall
    // back to queueing Packages files without verification
    // only allow going further if the users explicitely wants it
-   if(_config->FindB("Acquire::AllowInsecureRepositories") == true)
+   if(AllowInsecureRepositories(MetaIndexParser, TransactionManager, this) == true)
    {
       // Done, queue for rename on transaction finished
       if (FileExists(DestFile)) 
@@ -2146,12 +2074,6 @@ void pkgAcqMetaIndex::Failed(string Message,
 
       // queue without any kind of hashsum support
       QueueIndexes(false);
-   } else {
-      // warn if the repository is unsinged
-      _error->Warning("Use --allow-insecure-repositories to force the update");
-      TransactionManager->AbortTransaction();
-      Status = StatError;
-      return;
    }
 }
                                                                        /*}}}*/
@@ -2187,25 +2109,19 @@ pkgAcqMetaClearSig::~pkgAcqMetaClearSig()                               /*{{{*/
 // ---------------------------------------------------------------------
 string pkgAcqMetaClearSig::Custom600Headers() const
 {
-   string Final = _config->FindDir("Dir::State::lists");
-   Final += URItoFileName(RealURI);
-
-   struct stat Buf;
-   if (stat(Final.c_str(),&Buf) != 0)
-   {
-      if (stat(Final.c_str(),&Buf) != 0)
-        return "\nIndex-File: true\nFail-Ignore: true\n";
-   }
-
-   return "\nIndex-File: true\nFail-Ignore: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
+   string Header = GetCustom600Headers(RealURI);
+   Header += "\nFail-Ignore: true";
+   return Header;
 }
                                                                        /*}}}*/
 // 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
@@ -2270,7 +2186,7 @@ void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*
       // No Release file was present, or verification failed, so fall
       // back to queueing Packages files without verification
       // only allow going further if the users explicitely wants it
-      if(_config->FindB("Acquire::AllowInsecureRepositories") == true)
+      if(AllowInsecureRepositories(MetaIndexParser, TransactionManager, this) == true)
       {
         Status = StatDone;
 
@@ -2291,11 +2207,6 @@ void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*
             TransactionManager->TransactionStageCopy(this, DestFile, FinalFile);
          }
          QueueIndexes(false);
-      } else {
-         // warn if the repository is unsigned
-         _error->Warning("Use --allow-insecure-repositories to force the update");
-         TransactionManager->AbortTransaction();
-         Status = StatError;
       }
    }
 }
@@ -2475,10 +2386,7 @@ bool pkgAcqArchive::QueueNext()
         if ((unsigned long long)Buf.st_size > Version->Size)
            unlink(DestFile.c_str());
         else
-        {
            PartialSize = Buf.st_size;
-           ChangeOwnerAndPermissionOfFile("pkgAcqArchive::QueueNext", FinalFile.c_str(), "_apt", "root", 0600);
-        }
       }
 
       // Disables download of archives - useful if no real installation follows,
@@ -2547,7 +2455,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;
 }
@@ -2557,8 +2464,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. */
@@ -2568,10 +2475,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
@@ -2584,9 +2491,9 @@ void pkgAcqArchive::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
         if (QueueNext() == true)
            return;
       }
-      
+
       StoreFilename = string();
-      Item::Failed(Message,Cnf);
+      Status = StatError;
    }
 }
                                                                        /*}}}*/
@@ -2643,10 +2550,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;
-        ChangeOwnerAndPermissionOfFile("pkgAcqFile", DestFile.c_str(), "_apt", "root", 0600);
-      }
    }
 
    QueueURI(Desc);
@@ -2705,7 +2609,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;
       }      
@@ -2717,19 +2626,19 @@ 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          /*{{{*/