]> git.saurik.com Git - apt.git/commitdiff
Merge remote-tracking branch 'upstream/debian/experimental' into feature/acq-trans
authorMichael Vogt <mvo@ubuntu.com>
Fri, 5 Sep 2014 12:47:22 +0000 (14:47 +0200)
committerMichael Vogt <mvo@ubuntu.com>
Fri, 5 Sep 2014 12:47:22 +0000 (14:47 +0200)
1  2 
apt-pkg/acquire-item.cc
test/integration/test-ubuntu-bug-346386-apt-get-update-paywall

diff --combined apt-pkg/acquire-item.cc
index 0ec151050386d84a221147b48c0b789aa955a1c6,3feb17ffa841c6f56e3851df8f38e4a801b1fd3f..eee1097e918125a1a3e15e3e9c60b9fa25f58ca2
@@@ -64,12 -64,10 +64,12 @@@ static void printHashSumComparision(std
                                                                        /*}}}*/
  
  // Acquire::Item::Item - Constructor                                  /*{{{*/
 -pkgAcquire::Item::Item(pkgAcquire *Owner, HashStringList const &ExpectedHashes) :
 -   Owner(Owner), FileSize(0), PartialSize(0), Mode(0), ID(0), Complete(false),
 -   Local(false), QueueCounter(0), ExpectedAdditionalItems(0),
 -   ExpectedHashes(ExpectedHashes)
 +pkgAcquire::Item::Item(pkgAcquire *Owner,
 +                       HashStringList const &ExpectedHashes,
 +                       unsigned long TransactionID)
 +   : Owner(Owner), FileSize(0), PartialSize(0), Mode(0), ID(0), Complete(false),
 +     Local(false), QueueCounter(0), TransactionID(TransactionID),
 +     ExpectedAdditionalItems(0), ExpectedHashes(ExpectedHashes)
  {
     Owner->Add(this);
     Status = StatIdle;
@@@ -90,8 -88,7 +90,8 @@@ pkgAcquire::Item::~Item(
  void pkgAcquire::Item::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
  {
     Status = StatIdle;
 -   ErrorText = LookupTag(Message,"Message");
 +   if(ErrorText == "")
 +      ErrorText = LookupTag(Message,"Message");
     UsedMirror =  LookupTag(Message,"UsedMirror");
     if (QueueCounter <= 1)
     {
@@@ -137,7 -134,7 +137,7 @@@ void pkgAcquire::Item::Done(string Mess
  {
     // We just downloaded something..
     string FileName = LookupTag(Message,"Filename");
 -   UsedMirror =  LookupTag(Message,"UsedMirror");
 +   UsedMirror = LookupTag(Message,"UsedMirror");
     if (Complete == false && !Local && FileName == DestFile)
     {
        if (Owner->Log != 0)
@@@ -241,12 -238,10 +241,12 @@@ void pkgAcquire::Item::ReportMirrorFail
  // ---------------------------------------------------------------------
  /* Get a sub-index file based on checksums from a 'master' file and
     possibly query additional files */
 -pkgAcqSubIndex::pkgAcqSubIndex(pkgAcquire *Owner, string const &URI,
 -                               string const &URIDesc, string const &ShortDesc,
 -                               HashStringList const &ExpectedHashes)
 -   : Item(Owner, ExpectedHashes)
 +pkgAcqSubIndex::pkgAcqSubIndex(pkgAcquire *Owner, 
 +                               unsigned long TransactionID,
 +                               string const &URI,
 +                               string const &URIDesc, string const &ShortDesc,
 +                               HashStringList const &ExpectedHashes)
 +   : Item(Owner, ExpectedHashes, TransactionID)
  {
     /* XXX: Beware: Currently this class does nothing (of value) anymore ! */
     Debug = _config->FindB("Debug::pkgAcquire::SubIndex",false);
@@@ -359,12 -354,10 +359,12 @@@ bool pkgAcqSubIndex::ParseIndex(string 
   * the original packages file
   */
  pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner,
 +                                 unsigned long TransactionID,
                                   IndexTarget const * const Target,
                                 HashStringList const &ExpectedHashes,
                                   indexRecords *MetaIndexParser)
 -   : pkgAcqBaseIndex(Owner, Target, ExpectedHashes, MetaIndexParser)
 +   : pkgAcqBaseIndex(Owner, TransactionID, Target, ExpectedHashes, 
 +                     MetaIndexParser)
  {
     
     Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
     Desc.URI = Target->URI + ".diff/Index";
  
     DestFile = _config->FindDir("Dir::State::lists") + "partial/";
-    DestFile += URItoFileName(Target->URI) + string(".DiffIndex");
+    DestFile += URItoFileName(Desc.URI);
  
     if(Debug)
        std::clog << "pkgAcqDiffIndex: " << Desc.URI << std::endl;
  string pkgAcqDiffIndex::Custom600Headers() const
  {
     string Final = _config->FindDir("Dir::State::lists");
-    Final += URItoFileName(RealURI) + string(".IndexDiff");
+    Final += URItoFileName(Desc.URI);
     
     if(Debug)
        std::clog << "Custom600Header-IMS: " << Final << std::endl;
@@@ -462,8 -455,7 +462,8 @@@ bool pkgAcqDiffIndex::ParseDiffIndex(st
            std::clog << "Package file is up-to-date" << std::endl;
         // list cleanup needs to know that this file as well as the already
         // present index is ours, so we create an empty diff to save it for us
 -       new pkgAcqIndexDiffs(Owner, Target, ExpectedHashes, MetaIndexParser, 
 +       new pkgAcqIndexDiffs(Owner, TransactionID, Target, 
 +                              ExpectedHashes, MetaIndexParser, 
                                ServerSha1, available_patches);
         return true;
        }
  
         if (pdiff_merge == false)
           {
 -          new pkgAcqIndexDiffs(Owner, Target, ExpectedHashes, MetaIndexParser,
 +          new pkgAcqIndexDiffs(Owner, TransactionID, Target, ExpectedHashes, 
 +                                 MetaIndexParser,
                                   ServerSha1, available_patches);
           }
           else
         {
            std::vector<pkgAcqIndexMergeDiffs*> *diffs = new std::vector<pkgAcqIndexMergeDiffs*>(available_patches.size());
            for(size_t i = 0; i < available_patches.size(); ++i)
 -             (*diffs)[i] = new pkgAcqIndexMergeDiffs(Owner, Target,
 +             (*diffs)[i] = new pkgAcqIndexMergeDiffs(Owner,
 +                                                       TransactionID,
 +                                                       Target,
                                                         ExpectedHashes,
                                                         MetaIndexParser,
                                                         available_patches[i],
@@@ -588,7 -577,7 +588,7 @@@ void pkgAcqDiffIndex::Failed(string Mes
        std::clog << "pkgAcqDiffIndex failed: " << Desc.URI << " with " << Message << std::endl
                << "Falling back to normal index file acquire" << std::endl;
  
 -   new pkgAcqIndex(Owner, Target, ExpectedHashes, MetaIndexParser);
 +   new pkgAcqIndex(Owner, TransactionID, Target, ExpectedHashes, MetaIndexParser);
  
     Complete = false;
     Status = StatDone;
@@@ -631,13 -620,12 +631,13 @@@ void pkgAcqDiffIndex::Done(string Messa
   * for each diff and the index
   */
  pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner,
 +                                   unsigned long TransactionID,
                                     struct IndexTarget const * const Target,
                                     HashStringList const &ExpectedHashes,
                                     indexRecords *MetaIndexParser,
                                   string ServerSha1,
                                   vector<DiffInfo> diffs)
 -   : pkgAcqBaseIndex(Owner, Target, ExpectedHashes, MetaIndexParser),
 +   : pkgAcqBaseIndex(Owner, TransactionID, Target, ExpectedHashes, MetaIndexParser),
       available_patches(diffs), ServerSha1(ServerSha1)
  {
     
@@@ -669,28 -657,19 +669,28 @@@ void pkgAcqIndexDiffs::Failed(string Me
     if(Debug)
        std::clog << "pkgAcqIndexDiffs failed: " << Desc.URI << " with " << Message << std::endl
                << "Falling back to normal index file acquire" << std::endl;
 -   new pkgAcqIndex(Owner, Target, ExpectedHashes, MetaIndexParser);
 +   new pkgAcqIndex(Owner, TransactionID, Target, ExpectedHashes, MetaIndexParser);
     Finish();
  }
                                                                        /*}}}*/
  // Finish - helper that cleans the item out of the fetcher queue      /*{{{*/
  void pkgAcqIndexDiffs::Finish(bool allDone)
  {
 +   if(Debug)
 +      std::clog << "pkgAcqIndexDiffs::Finish(): " 
 +                << allDone << " "
 +                << Desc.URI << std::endl;
 +
     // we restore the original name, this is required, otherwise
     // the file will be cleaned
     if(allDone) 
     {
        DestFile = _config->FindDir("Dir::State::lists");
        DestFile += URItoFileName(RealURI);
 +      
 +      // FIXME: we want the rred stuff to use the real transactional update
 +      //        this is just a workaround
 +      PartialFile = DestFile;
  
        if(HashSums().usable() && !HashSums().VerifyFile(DestFile))
        {
@@@ -818,7 -797,7 +818,7 @@@ void pkgAcqIndexDiffs::Done(string Mess
  
        // see if there is more to download
        if(available_patches.empty() == false) {
 -       new pkgAcqIndexDiffs(Owner, Target,
 +       new pkgAcqIndexDiffs(Owner, TransactionID, Target,
                              ExpectedHashes, MetaIndexParser,
                                ServerSha1, available_patches);
         return Finish();
                                                                        /*}}}*/
  // AcqIndexMergeDiffs::AcqIndexMergeDiffs - Constructor                       /*{{{*/
  pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire *Owner,
 +                                             unsigned long TransactionID,
                                               struct IndexTarget const * const Target,
                                               HashStringList const &ExpectedHashes,
                                               indexRecords *MetaIndexParser,
                                               DiffInfo const &patch,
                                               std::vector<pkgAcqIndexMergeDiffs*> const * const allPatches)
 -   : pkgAcqBaseIndex(Owner, Target, ExpectedHashes, MetaIndexParser),
 +  : pkgAcqBaseIndex(Owner, TransactionID, Target, ExpectedHashes, MetaIndexParser),
       patch(patch), allPatches(allPatches), State(StateFetchDiff)
  {
  
@@@ -878,7 -856,7 +878,7 @@@ void pkgAcqIndexMergeDiffs::Failed(stri
     // first failure means we should fallback
     State = StateErrorDiff;
     std::clog << "Falling back to normal index file acquire" << std::endl;
 -   new pkgAcqIndex(Owner, Target, ExpectedHashes, MetaIndexParser);
 +   new pkgAcqIndex(Owner, TransactionID, Target, ExpectedHashes, MetaIndexParser);
  }
                                                                        /*}}}*/
  void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStringList const &Hashes, /*{{{*/
  
        // otherwise lists cleanup will eat the file
        DestFile = FinalFile;
 +      // FIXME: make the merged rred code really transactional
 +      PartialFile = FinalFile;
  
        // ensure the ed's are gone regardless of list-cleanup
        for (std::vector<pkgAcqIndexMergeDiffs *>::const_iterator I = allPatches->begin();
  pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,
                         string URI,string URIDesc,string ShortDesc,
                         HashStringList const  &ExpectedHash, string comprExt)
 -   : pkgAcqBaseIndex(Owner, NULL, ExpectedHash, NULL), RealURI(URI)
 +   : pkgAcqBaseIndex(Owner, 0, NULL, ExpectedHash, NULL), RealURI(URI)
  {
 -   if(comprExt.empty() == true)
 -   {
 -      // autoselect the compression method
 -      std::vector<std::string> types = APT::Configuration::getCompressionTypes();
 -      for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
 -       comprExt.append(*t).append(" ");
 -      if (comprExt.empty() == false)
 -       comprExt.erase(comprExt.end()-1);
 -   }
 -   CompressionExtension = comprExt;
 -
 +   AutoSelectCompression();
     Init(URI, URIDesc, ShortDesc);
 +
 +   if(_config->FindB("Debug::Acquire::Transaction", false) == true)
 +      std::clog << "New pkgIndex with TransactionID "
 +                << TransactionID << std::endl;
  }
 -pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, IndexTarget const *Target,
 +                                                                      /*}}}*/
 +// AcqIndex::AcqIndex - Constructor                                   /*{{{*/
 +// ---------------------------------------------------------------------
 +pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,
 +                         unsigned long TransactionID,
 +                         IndexTarget const *Target,
                         HashStringList const &ExpectedHash, 
                           indexRecords *MetaIndexParser)
 -   : pkgAcqBaseIndex(Owner, Target, ExpectedHash, MetaIndexParser)
 -     RealURI(Target->URI)
 +   : pkgAcqBaseIndex(Owner, TransactionID, Target, ExpectedHash
 +                     MetaIndexParser), RealURI(Target->URI)
  {
     // autoselect the compression method
 +   AutoSelectCompression();
 +   Init(Target->URI, Target->Description, Target->ShortDesc);
 +
 +   if(_config->FindB("Debug::Acquire::Transaction", false) == true)
 +      std::clog << "New pkgIndex with TransactionID "
 +                << TransactionID << std::endl;
 +}
 +                                                                      /*}}}*/
 +// AcqIndex::AutoSelectCompression - Select compression                       /*{{{*/
 +// ---------------------------------------------------------------------
 +void pkgAcqIndex::AutoSelectCompression()
 +{
     std::vector<std::string> types = APT::Configuration::getCompressionTypes();
     CompressionExtension = "";
     if (ExpectedHashes.usable())
     }
     if (CompressionExtension.empty() == false)
        CompressionExtension.erase(CompressionExtension.end()-1);
 -
 -   Init(Target->URI, Target->Description, Target->ShortDesc);
  }
 -                                                                      /*}}}*/
  // AcqIndex::Init - defered Constructor                                       /*{{{*/
  void pkgAcqIndex::Init(string const &URI, string const &URIDesc, string const &ShortDesc) {
     Decompression = false;
     DestFile += URItoFileName(URI);
  
     std::string const comprExt = CompressionExtension.substr(0, CompressionExtension.find(' '));
 -   std::string MetaKey;
     if (comprExt == "uncompressed")
     {
        Desc.URI = URI;
@@@ -1105,9 -1074,6 +1105,9 @@@ string pkgAcqIndex::Custom600Headers() 
     return msg;
  }
                                                                        /*}}}*/
 +// pkgAcqIndex::Failed - getting the indexfile failed                 /*{{{*/
 +// ---------------------------------------------------------------------
 +/* */
  void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)        /*{{{*/
  {
     size_t const nextExt = CompressionExtension.find(' ');
     }
  
     Item::Failed(Message,Cnf);
 +
 +   /// cancel the entire transaction
 +   Owner->AbortTransaction(TransactionID);
  }
                                                                        /*}}}*/
 +// pkgAcqIndex::GetFinalFilename - Return the full final file path      /*{{{*/
 +// ---------------------------------------------------------------------
 +/* */
 +std::string pkgAcqIndex::GetFinalFilename(std::string const &URI,
 +                                          std::string const &compExt)
 +{
 +   std::string FinalFile = _config->FindDir("Dir::State::lists");
 +   FinalFile += URItoFileName(URI);
 +   if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz")
 +      FinalFile += ".gz";
 +   return FinalFile;
 +}
 +                                                                       /*}}}*/
 +// AcqIndex::ReverifyAfterIMS - Reverify index after an ims-hit        /*{{{*/
 +// ---------------------------------------------------------------------
 +/* */
 +void pkgAcqIndex::ReverifyAfterIMS(std::string const &FileName)
 +{
 +   std::string const compExt = CompressionExtension.substr(0, CompressionExtension.find(' '));
 +   if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz")
 +      DestFile += ".gz";
 +
 +   // copy FinalFile into partial/ so that we check the hash again
 +   string FinalFile = GetFinalFilename(RealURI, compExt);
 +   Decompression = true;
 +   Desc.URI = "copy:" + FinalFile;
 +   QueueURI(Desc);
 +}
 +                                                                       /*}}}*/
  // AcqIndex::Done - Finished a fetch                                  /*{{{*/
  // ---------------------------------------------------------------------
  /* This goes through a number of states.. On the initial fetch the
     method could possibly return an alternate filename which points
     to the uncompressed version of the file. If this is so the file
     is copied into the partial directory. In all other cases the file
 -   is decompressed with a gzip uri. */
 +   is decompressed with a compressed uri. */
  void pkgAcqIndex::Done(string Message,unsigned long long Size,HashStringList const &Hashes,
                       pkgAcquire::MethodConfig *Cfg)
  {
     Item::Done(Message,Size,Hashes,Cfg);
 +   std::string const compExt = CompressionExtension.substr(0, CompressionExtension.find(' '));
  
     if (Decompression == true)
     {
        {
         RenameOnError(HashSumMismatch);
         printHashSumComparision(RealURI, ExpectedHashes, Hashes);
 +         Failed(Message, Cfg);
           return;
        }
  
        /* Always verify the index file for correctness (all indexes must
         * have a Package field) (LP: #346386) (Closes: #627642) 
         */
 -      FileFd fd(DestFile, FileFd::ReadOnly);
 -      // Only test for correctness if the file is not empty (empty is ok)
 -      if (fd.FileSize() > 0)
 +      FileFd fd(DestFile, FileFd::ReadOnly, FileFd::Extension);
 +      // Only test for correctness if the content of the file is not empty
 +      // (empty is ok)
 +      if (fd.Size() > 0)
        {
           pkgTagSection sec;
           pkgTagFile tag(&fd);
           if (_error->PendingError() == true || tag.Step(sec) == false || sec.Exists("Package") == false)
           {
              RenameOnError(InvalidFormat);
 +            Failed(Message, Cfg);
              return;
           }
        }
         
 -      // Done, move it into position
 -      string FinalFile = _config->FindDir("Dir::State::lists");
 -      FinalFile += URItoFileName(RealURI);
 -      Rename(DestFile,FinalFile);
 -      chmod(FinalFile.c_str(),0644);
 -
 -      /* We restore the original name to DestFile so that the clean operation
 -         will work OK */
 -      DestFile = _config->FindDir("Dir::State::lists") + "partial/";
 -      DestFile += URItoFileName(RealURI);
 -      
 +      // FIXME: can we void the "Erase" bool here as its very non-local?
 +      std::string CompressedFile = _config->FindDir("Dir::State::lists") + "partial/";
 +      CompressedFile += URItoFileName(RealURI);
        // Remove the compressed version.
        if (Erase == true)
 -       unlink(DestFile.c_str());
 +       unlink(CompressedFile.c_str());
 +
 +      // Done, queue for rename on transaction finished
 +      PartialFile = DestFile;
 +      DestFile = GetFinalFilename(RealURI, compExt);
  
        return;
     }
 +   
 +   // FIXME: use the same method to find 
 +   // check the compressed hash too
 +   if(MetaKey != "" && Hashes.size() > 0)
 +   {
 +      indexRecords::checkSum *Record = MetaIndexParser->Lookup(MetaKey);
 +      if(Record && Record->Hashes.usable() && Hashes != Record->Hashes)
 +      {
 +         RenameOnError(HashSumMismatch);
 +         printHashSumComparision(RealURI, Record->Hashes, Hashes);
 +         Failed(Message, Cfg);
 +         return;
 +      }
 +   }
  
     Erase = false;
     Complete = true;
     {
        // The files timestamp matches
        if (StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false) == true)
 +      {
 +         ReverifyAfterIMS(FileName);
         return;
 +      }
        Decompression = true;
        Local = true;
        DestFile += ".decomp";
        ErrorText = "Method gave a blank filename";
     }
  
 -   std::string const compExt = CompressionExtension.substr(0, CompressionExtension.find(' '));
 -
     // The files timestamp matches
 -   if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true) {
 -       if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz")
 -        // Update DestFile for .gz suffix so that the clean operation keeps it
 -        DestFile += ".gz";
 +   if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
 +   {
 +      ReverifyAfterIMS(FileName);
        return;
      }
  
  
     // If we enable compressed indexes and already have gzip, keep it
     if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz" && !Local) {
 -      string FinalFile = _config->FindDir("Dir::State::lists");
 -      FinalFile += URItoFileName(RealURI) + ".gz";
 -      Rename(DestFile,FinalFile);
 -      chmod(FinalFile.c_str(),0644);
 -      
 -      // Update DestFile for .gz suffix so that the clean operation keeps it
 -      DestFile = _config->FindDir("Dir::State::lists") + "partial/";
 -      DestFile += URItoFileName(RealURI) + ".gz";
 +      // Done, queue for rename on transaction finished
 +      PartialFile = DestFile;
 +      DestFile = GetFinalFilename(RealURI, compExt);
        return;
      }
  
@@@ -1312,13 -1237,9 +1312,13 @@@ pkgAcqIndexTrans::pkgAcqIndexTrans(pkgA
    : pkgAcqIndex(Owner, URI, URIDesc, ShortDesc, HashStringList(), "")
  {
  }
 -pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner, IndexTarget const * const Target,
 -                       HashStringList const &ExpectedHashes, indexRecords *MetaIndexParser)
 -  : pkgAcqIndex(Owner, Target, ExpectedHashes, MetaIndexParser)
 +                                                                      /*}}}*/
 +pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner, 
 +                                   unsigned long TransactionID, 
 +                                   IndexTarget const * const Target,
 +                                   HashStringList const &ExpectedHashes, 
 +                                   indexRecords *MetaIndexParser)
 +   : pkgAcqIndex(Owner, TransactionID, Target, ExpectedHashes, MetaIndexParser)
  {
     // load the filesize
     indexRecords::checkSum *Record = MetaIndexParser->Lookup(string(Target->MetaKey));
@@@ -1353,7 -1274,6 +1353,7 @@@ void pkgAcqIndexTrans::Failed(string Me
        return;
     }
  
 +   // FIXME: this is used often (e.g. in pkgAcqIndexTrans) so refactor
     if (Cnf->LocalOnly == true || 
         StringToBool(LookupTag(Message,"Transient-Failure"),false) == false)
     {      
     Item::Failed(Message,Cnf);
  }
                                                                        /*}}}*/
 -pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner,                               /*{{{*/
 +
 +pkgAcqMetaSigBase::pkgAcqMetaSigBase(pkgAcquire *Owner,
 +                                     HashStringList const &ExpectedHashes,
 +                                     unsigned long TransactionID)
 +   : Item(Owner, ExpectedHashes, TransactionID)
 +{
 +}
 +                                                                       /*{{{*/
 +bool pkgAcqMetaSigBase::GenerateAuthWarning(const std::string &RealURI,
 +                                            const std::string &Message)
 +{
 +   string Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
 +   
 +   if(FileExists(Final))
 +   {
 +      Status = StatTransientNetworkError;
 +      _error->Warning(_("An error occurred during the signature "
 +                        "verification. The repository is not updated "
 +                        "and the previous index files will be used. "
 +                        "GPG error: %s: %s\n"),
 +                      Desc.Description.c_str(),
 +                      LookupTag(Message,"Message").c_str());
 +      RunScripts("APT::Update::Auth-Failure");
 +      return true;
 +   } else if (LookupTag(Message,"Message").find("NODATA") != string::npos) {
 +      /* Invalid signature file, reject (LP: #346386) (Closes: #627642) */
 +      _error->Error(_("GPG error: %s: %s"),
 +                    Desc.Description.c_str(),
 +                    LookupTag(Message,"Message").c_str());
 +      Status = StatError;
 +      return true;
 +   } else {
 +      _error->Warning(_("GPG error: %s: %s"),
 +                      Desc.Description.c_str(),
 +                      LookupTag(Message,"Message").c_str());
 +   }
 +   // gpgv method failed 
 +   ReportMirrorFailure("GPGFailure");
 +   return false;
 +}
 +                                                                      /*}}}*/
 +
 +
 +pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner,                       /*{{{*/
 +                             unsigned long TransactionID,
                             string URI,string URIDesc,string ShortDesc,
 -                           string MetaIndexURI, string MetaIndexURIDesc,
 -                           string MetaIndexShortDesc,
 +                             string MetaIndexFile,
                             const vector<IndexTarget*>* IndexTargets,
                             indexRecords* MetaIndexParser) :
 -   Item(Owner, HashStringList()), RealURI(URI), MetaIndexURI(MetaIndexURI),
 -   MetaIndexURIDesc(MetaIndexURIDesc), MetaIndexShortDesc(MetaIndexShortDesc),
 -   MetaIndexParser(MetaIndexParser), IndexTargets(IndexTargets)
 +   pkgAcqMetaSigBase(Owner, HashStringList(), TransactionID), RealURI(URI), 
 +   MetaIndexParser(MetaIndexParser), MetaIndexFile(MetaIndexFile),
 +   IndexTargets(IndexTargets), AuthPass(false), IMSHit(false)
  {
     DestFile = _config->FindDir("Dir::State::lists") + "partial/";
     DestFile += URItoFileName(URI);
     // partial download anyway
     unlink(DestFile.c_str());
  
 +   // set the TransactionID
 +   if(_config->FindB("Debug::Acquire::Transaction", false) == true)
 +      std::clog << "New pkgAcqMetaSig with TransactionID "
 +                << TransactionID << std::endl;
 +
     // Create the item
     Desc.Description = URIDesc;
     Desc.Owner = this;
     Desc.ShortDesc = ShortDesc;
     Desc.URI = URI;
 -      
 -   string Final = _config->FindDir("Dir::State::lists");
 -   Final += URItoFileName(RealURI);
 -   if (RealFileExists(Final) == true)
 -   {
 -      // File was already in place.  It needs to be re-downloaded/verified
 -      // because Release might have changed, we do give it a different
 -      // name than DestFile because otherwise the http method will
 -      // send If-Range requests and there are too many broken servers
 -      // out there that do not understand them
 -      LastGoodSig = DestFile+".reverify";
 -      Rename(Final,LastGoodSig);
 -   }
 -
 -   // we expect the indextargets + one additional Release file
 -   ExpectedAdditionalItems = IndexTargets->size() + 1;
  
     QueueURI(Desc);
  }
                                                                        /*}}}*/
  pkgAcqMetaSig::~pkgAcqMetaSig()                                               /*{{{*/
  {
 -   // if the file was never queued undo file-changes done in the constructor
 -   if (QueueCounter == 1 && Status == StatIdle && FileSize == 0 && Complete == false &&
 -       LastGoodSig.empty() == false)
 -   {
 -      string const Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
 -      if (RealFileExists(Final) == false && RealFileExists(LastGoodSig) == true)
 -       Rename(LastGoodSig, Final);
 -   }
 -
  }
                                                                        /*}}}*/
  // pkgAcqMetaSig::Custom600Headers - Insert custom request headers    /*{{{*/
  /* The only header we use is the last-modified header. */
  string pkgAcqMetaSig::Custom600Headers() const
  {
 +   string FinalFile = _config->FindDir("Dir::State::lists");
 +   FinalFile += URItoFileName(RealURI);
 +
     struct stat Buf;
 -   if (stat(LastGoodSig.c_str(),&Buf) != 0)
 +   if (stat(FinalFile.c_str(),&Buf) != 0)
        return "\nIndex-File: true";
  
     return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
@@@ -1483,40 -1377,21 +1483,40 @@@ void pkgAcqMetaSig::Done(string Message
        return;
     }
  
 -   Complete = true;
 +   if(StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
 +      IMSHit = true;
  
 -   // at this point pkgAcqMetaIndex takes over
 -   ExpectedAdditionalItems = 0;
 +   // adjust paths if its a ims-hit
 +   if(IMSHit)
 +   {
 +      string FinalFile = _config->FindDir("Dir::State::lists");
 +      FinalFile += URItoFileName(RealURI);
 +         
 +      DestFile = PartialFile = FinalFile;
 +   }
  
 -   // put the last known good file back on i-m-s hit (it will
 -   // be re-verified again)
 -   // Else do nothing, we have the new file in DestFile then
 -   if(StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
 -      Rename(LastGoodSig, DestFile);
 +   // queue for verify
 +   if(AuthPass == false)
 +   {
 +      AuthPass = true;
 +      Desc.URI = "gpgv:" + DestFile;
 +      DestFile = MetaIndexFile;
 +      QueueURI(Desc);
 +      return;
 +   }
  
 -   // queue a pkgAcqMetaIndex to be verified against the sig we just retrieved
 -   new pkgAcqMetaIndex(Owner, MetaIndexURI, MetaIndexURIDesc, 
 -                     MetaIndexShortDesc,  DestFile, IndexTargets, 
 -                     MetaIndexParser);
 +   // queue to copy the file in place if it was not a ims hit, on ims
 +   // hit the file is already at the right place
 +   if(IMSHit == false)
 +   {
 +      PartialFile = _config->FindDir("Dir::State::lists") + "partial/";
 +      PartialFile += URItoFileName(RealURI);
 +      
 +      DestFile = _config->FindDir("Dir::State::lists");
 +      DestFile += URItoFileName(RealURI);
 +   }
 +
 +   Complete = true;
  
  }
                                                                        /*}}}*/
@@@ -1524,21 -1399,29 +1524,21 @@@ void pkgAcqMetaSig::Failed(string Messa
  {
     string Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
  
 -   // at this point pkgAcqMetaIndex takes over
 -   ExpectedAdditionalItems = 0;
 +   // this ensures that any file in the lists/ dir is removed by the
 +   // transaction
 +   DestFile =  _config->FindDir("Dir::State::lists") + "partial/";
 +   DestFile += URItoFileName(RealURI);
 +   PartialFile = "";
  
 -   // if we get a network error we fail gracefully
 -   if(Status == StatTransientNetworkError)
 +   // FIXME: duplicated code from pkgAcqMetaIndex
 +   if (AuthPass == true)
     {
 -      Item::Failed(Message,Cnf);
 -      // move the sigfile back on transient network failures 
 -      if(FileExists(LastGoodSig))
 -       Rename(LastGoodSig,Final);
 -
 -      // set the status back to , Item::Failed likes to reset it
 -      Status = pkgAcquire::Item::StatTransientNetworkError;
 -      return;
 +      bool Stop = GenerateAuthWarning(RealURI, Message);
 +      if(Stop)
 +         return;
     }
  
 -   // Delete any existing sigfile when the acquire failed
 -   unlink(Final.c_str());
 -
 -   // queue a pkgAcqMetaIndex with no sigfile
 -   new pkgAcqMetaIndex(Owner, MetaIndexURI, MetaIndexURIDesc, MetaIndexShortDesc,
 -                     "", IndexTargets, MetaIndexParser);
 -
 +   // FIXME: this is used often (e.g. in pkgAcqIndexTrans) so refactor
     if (Cnf->LocalOnly == true || 
         StringToBool(LookupTag(Message,"Transient-Failure"),false) == false)
     {      
        Dequeue();
        return;
     }
 -   
     Item::Failed(Message,Cnf);
  }
                                                                        /*}}}*/
  pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire *Owner,                   /*{{{*/
 +                                 unsigned long TransactionID,
                                 string URI,string URIDesc,string ShortDesc,
 -                               string SigFile,
 +                                 string MetaIndexSigURI,string MetaIndexSigURIDesc, string MetaIndexSigShortDesc,
                                 const vector<IndexTarget*>* IndexTargets,
                                 indexRecords* MetaIndexParser) :
 -   Item(Owner, HashStringList()), RealURI(URI), SigFile(SigFile), IndexTargets(IndexTargets),
 -   MetaIndexParser(MetaIndexParser), AuthPass(false), IMSHit(false)
 +   pkgAcqMetaSigBase(Owner, HashStringList(), TransactionID), RealURI(URI), IndexTargets(IndexTargets),
 +   MetaIndexParser(MetaIndexParser), AuthPass(false), IMSHit(false),
 +   MetaIndexSigURI(MetaIndexSigURI), MetaIndexSigURIDesc(MetaIndexSigURIDesc),
 +   MetaIndexSigShortDesc(MetaIndexSigShortDesc)
 +{
 +   if(TransactionID == 0)
 +      this->TransactionID = (unsigned long)this;
 +
 +   if(_config->FindB("Debug::Acquire::Transaction", false) == true)
 +      std::clog << "New pkgAcqMetaIndex with TransactionID "
 +                << TransactionID << std::endl;
 +
 +   Init(URIDesc, ShortDesc);
 +}
 +                                                                      /*}}}*/
 +// pkgAcqMetaIndex::Init - Delayed constructor                         /*{{{*/
 +void pkgAcqMetaIndex::Init(std::string URIDesc, std::string ShortDesc)
  {
     DestFile = _config->FindDir("Dir::State::lists") + "partial/";
 -   DestFile += URItoFileName(URI);
 +   DestFile += URItoFileName(RealURI);
  
     // Create the item
     Desc.Description = URIDesc;
     Desc.Owner = this;
     Desc.ShortDesc = ShortDesc;
 -   Desc.URI = URI;
 +   Desc.URI = RealURI;
  
     // we expect more item
     ExpectedAdditionalItems = IndexTargets->size();
 -
     QueueURI(Desc);
  }
 -                                                                      /*}}}*/
  // pkgAcqMetaIndex::Custom600Headers - Insert custom request headers  /*{{{*/
  // ---------------------------------------------------------------------
  /* The only header we use is the last-modified header. */
@@@ -1628,12 -1498,25 +1628,12 @@@ void pkgAcqMetaIndex::Done(string Messa
  
        if (SigFile == "")
        {
 -         // There was no signature file, so we are finished.  Download
 -         // the indexes and do only hashsum verification if possible
 +         // load indexes, the signature will downloaded afterwards
           MetaIndexParser->Load(DestFile);
 -         QueueIndexes(false);
 +         QueueIndexes(true);
        }
        else
        {
 -         // FIXME: move this into pkgAcqMetaClearSig::Done on the next
 -         //        ABI break
 -
 -         // 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
 -         if (SigFile == DestFile && !StartsWithGPGClearTextSignature(DestFile))
 -         {
 -            Failed(Message, Cfg);
 -            return;
 -         }
 -
           // There was a signature file, so pass it to gpgv for
           // verification
           if (_config->FindB("Debug::pkgAcquire::Auth", false))
        FinalFile += URItoFileName(RealURI);
        if (SigFile == DestFile)
         SigFile = FinalFile;
 -      Rename(DestFile,FinalFile);
 -      chmod(FinalFile.c_str(),0644);
 +      // queue for copy in place
 +      PartialFile = DestFile;
        DestFile = FinalFile;
     }
  }
@@@ -1689,24 -1572,14 +1689,24 @@@ void pkgAcqMetaIndex::RetrievalDone(str
        if (SigFile == DestFile)
        {
         SigFile = FinalFile;
 +#if 0
         // constructor of pkgAcqMetaClearSig moved it out of the way,
         // now move it back in on IMS hit for the 'old' file
         string const OldClearSig = DestFile + ".reverify";
         if (RealFileExists(OldClearSig) == true)
            Rename(OldClearSig, FinalFile);
 +#endif
        }
        DestFile = FinalFile;
     }
 +
 +   // queue a signature
 +   if(SigFile != DestFile)
 +      new pkgAcqMetaSig(Owner, TransactionID, 
 +                        MetaIndexSigURI, MetaIndexSigURIDesc,
 +                        MetaIndexSigShortDesc, DestFile, IndexTargets, 
 +                        MetaIndexParser);
 +
     Complete = true;
  }
                                                                        /*}}}*/
@@@ -1736,7 -1609,6 +1736,7 @@@ void pkgAcqMetaIndex::AuthDone(string M
     // Download further indexes with verification
     QueueIndexes(true);
  
 +#if 0
     // is it a clearsigned MetaIndex file?
     if (DestFile == SigFile)
        return;
        URItoFileName(RealURI) + ".gpg";
     Rename(SigFile,VerifiedSigFile);
     chmod(VerifiedSigFile.c_str(),0644);
 +#endif
  }
                                                                        /*}}}*/
  void pkgAcqMetaIndex::QueueIndexes(bool verify)                               /*{{{*/
  {
 -#if 0
 -   /* Reject invalid, existing Release files (LP: #346386) (Closes: #627642)
 -    * FIXME: Disabled; it breaks unsigned repositories without hashes */
 -   if (!verify && FileExists(DestFile) && !MetaIndexParser->Load(DestFile))
 -   {
 -      Status = StatError;
 -      ErrorText = MetaIndexParser->ErrorText;
 -      return;
 -   }
 -#endif
     bool transInRelease = false;
     {
        std::vector<std::string> const keys = MetaIndexParser->MetaKeys();
        if ((*Target)->IsOptional() == true)
        {
         if ((*Target)->IsSubIndex() == true)
 -          new pkgAcqSubIndex(Owner, (*Target)->URI, (*Target)->Description,
 +          new pkgAcqSubIndex(Owner, TransactionID, 
 +                               (*Target)->URI, (*Target)->Description,
                                (*Target)->ShortDesc, ExpectedIndexHashes);
         else 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, *Target, ExpectedIndexHashes, MetaIndexParser);
 +             new pkgAcqDiffIndex(Owner, TransactionID, *Target, ExpectedIndexHashes, MetaIndexParser);
            else
 -             new pkgAcqIndexTrans(Owner, *Target, ExpectedIndexHashes, MetaIndexParser);
 +             new pkgAcqIndexTrans(Owner, TransactionID, *Target, ExpectedIndexHashes, MetaIndexParser);
         }
         continue;
        }
           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, *Target, ExpectedIndexHashes, MetaIndexParser);
 +       new pkgAcqDiffIndex(Owner, TransactionID, *Target, ExpectedIndexHashes, MetaIndexParser);
        else
 -       new pkgAcqIndex(Owner, *Target, ExpectedIndexHashes, MetaIndexParser);
 +       new pkgAcqIndex(Owner, TransactionID, *Target, ExpectedIndexHashes, MetaIndexParser);
     }
  }
                                                                        /*}}}*/
@@@ -1919,16 -1799,44 +1919,16 @@@ bool pkgAcqMetaIndex::VerifyVendor(stri
  // pkgAcqMetaIndex::Failed - no Release file present or no signature file present     /*{{{*/
  // ---------------------------------------------------------------------
  /* */
 -void pkgAcqMetaIndex::Failed(string Message,pkgAcquire::MethodConfig * /*Cnf*/)
 +void pkgAcqMetaIndex::Failed(string Message,
 +                             pkgAcquire::MethodConfig * /*Cnf*/)
  {
 +   string Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
 +
     if (AuthPass == true)
     {
 -      // gpgv method failed, if we have a good signature 
 -      string LastGoodSigFile = _config->FindDir("Dir::State::lists").append("partial/").append(URItoFileName(RealURI));
 -      if (DestFile != SigFile)
 -       LastGoodSigFile.append(".gpg");
 -      LastGoodSigFile.append(".reverify");
 -
 -      if(FileExists(LastGoodSigFile))
 -      {
 -       string VerifiedSigFile = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
 -       if (DestFile != SigFile)
 -          VerifiedSigFile.append(".gpg");
 -       Rename(LastGoodSigFile, VerifiedSigFile);
 -       Status = StatTransientNetworkError;
 -       _error->Warning(_("An error occurred during the signature "
 -                         "verification. The repository is not updated "
 -                         "and the previous index files will be used. "
 -                         "GPG error: %s: %s\n"),
 -                       Desc.Description.c_str(),
 -                       LookupTag(Message,"Message").c_str());
 -       RunScripts("APT::Update::Auth-Failure");
 -       return;
 -      } else if (LookupTag(Message,"Message").find("NODATA") != string::npos) {
 -       /* Invalid signature file, reject (LP: #346386) (Closes: #627642) */
 -       _error->Error(_("GPG error: %s: %s"),
 -                       Desc.Description.c_str(),
 -                       LookupTag(Message,"Message").c_str());
 -       return;
 -      } else {
 -       _error->Warning(_("GPG error: %s: %s"),
 -                       Desc.Description.c_str(),
 -                       LookupTag(Message,"Message").c_str());
 -      }
 -      // gpgv method failed 
 -      ReportMirrorFailure("GPGFailure");
 +      bool Stop = GenerateAuthWarning(RealURI, Message);
 +      if(Stop)
 +         return;
     }
  
     /* Always move the meta index, even if gpgv failed. This ensures
                                       "Release");
         SigFile = FinalFile;
        }
 -      Rename(DestFile,FinalFile);
 -      chmod(FinalFile.c_str(),0644);
  
 +      // Done, queue for rename on transaction finished
 +      PartialFile = DestFile;
        DestFile = FinalFile;
     }
  
     QueueIndexes(false);
  }
                                                                        /*}}}*/
 +
 +void pkgAcqMetaIndex::Finished()
 +{
 +   if(_config->FindB("Debug::Acquire::Transaction", false) == true)
 +      std::clog << "Finished: " << DestFile <<std::endl;
 +   if(Owner->TransactionHasError(TransactionID) == false && 
 +      TransactionID > 0)
 +      Owner->CommitTransaction(TransactionID);
 +}
 +
 +
  pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire *Owner,             /*{{{*/
                string const &URI, string const &URIDesc, string const &ShortDesc,
                string const &MetaIndexURI, string const &MetaIndexURIDesc, string const &MetaIndexShortDesc,
                string const &MetaSigURI, string const &MetaSigURIDesc, string const &MetaSigShortDesc,
                const vector<IndexTarget*>* IndexTargets,
                indexRecords* MetaIndexParser) :
 -      pkgAcqMetaIndex(Owner, URI, URIDesc, ShortDesc, "", IndexTargets, MetaIndexParser),
 -      MetaIndexURI(MetaIndexURI), MetaIndexURIDesc(MetaIndexURIDesc), MetaIndexShortDesc(MetaIndexShortDesc),
 -      MetaSigURI(MetaSigURI), MetaSigURIDesc(MetaSigURIDesc), MetaSigShortDesc(MetaSigShortDesc)
 +   pkgAcqMetaIndex(Owner, (unsigned long)this, URI, URIDesc, ShortDesc, MetaSigURI, MetaSigURIDesc,MetaSigShortDesc, IndexTargets, MetaIndexParser),
 +       MetaIndexURI(MetaIndexURI), MetaIndexURIDesc(MetaIndexURIDesc), MetaIndexShortDesc(MetaIndexShortDesc),
 +       MetaSigURI(MetaSigURI), MetaSigURIDesc(MetaSigURIDesc), MetaSigShortDesc(MetaSigShortDesc)
  {
     SigFile = DestFile;
  
     // index targets + (worst case:) Release/Release.gpg
     ExpectedAdditionalItems = IndexTargets->size() + 2;
  
 -
 +#if 0
     // keep the old InRelease around in case of transistent network errors
     string const Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
     if (RealFileExists(Final) == true)
        string const LastGoodSig = DestFile + ".reverify";
        Rename(Final,LastGoodSig);
     }
 +#endif
  }
                                                                        /*}}}*/
  pkgAcqMetaClearSig::~pkgAcqMetaClearSig()                             /*{{{*/
  {
 +#if 0
     // if the file was never queued undo file-changes done in the constructor
     if (QueueCounter == 1 && Status == StatIdle && FileSize == 0 && Complete == false)
     {
        if (RealFileExists(Final) == false && RealFileExists(LastGoodSig) == true)
         Rename(LastGoodSig, Final);
     }
 +#endif
  }
                                                                        /*}}}*/
  // pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers       /*{{{*/
@@@ -2018,6 -1912,7 +2018,6 @@@ string pkgAcqMetaClearSig::Custom600Hea
     struct stat Buf;
     if (stat(Final.c_str(),&Buf) != 0)
     {
 -      Final = DestFile + ".reverify";
        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);
  }
                                                                        /*}}}*/
 +// pkgAcqMetaClearSig::Done - We got a file                           /*{{{*/
 +// ---------------------------------------------------------------------
 +void pkgAcqMetaClearSig::Done(std::string Message,unsigned long long Size, 
 +                              HashStringList const &Hashes,
 +                              pkgAcquire::MethodConfig *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
 +   if (FileExists(DestFile) && !StartsWithGPGClearTextSignature(DestFile))
 +   {
 +      pkgAcquire::Item::Failed(Message, Cnf);
 +      ErrorText = _("Does not start with a cleartext signature");
 +      return;
 +   }
 +   pkgAcqMetaIndex::Done(Message, Size, Hashes, Cnf);
 +}
 +                                                                      /*}}}*/
  void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*{{{*/
  {
     // we failed, we will not get additional items from this method
  
     if (AuthPass == false)
     {
 -      // Remove the 'old' InRelease file if we try Release.gpg now as otherwise
 -      // the file will stay around and gives a false-auth impression (CVE-2012-0214)
 +      // Queue the 'old' InRelease file for removal if we try Release.gpg
 +      // as otherwise the file will stay around and gives a false-auth
 +      // impression (CVE-2012-0214)
        string FinalFile = _config->FindDir("Dir::State::lists");
        FinalFile.append(URItoFileName(RealURI));
 -      if (FileExists(FinalFile))
 -       unlink(FinalFile.c_str());
 +      PartialFile = "";
 +      DestFile = FinalFile;
  
 -      new pkgAcqMetaSig(Owner,
 -                      MetaSigURI, MetaSigURIDesc, MetaSigShortDesc,
 +      new pkgAcqMetaIndex(Owner, TransactionID,
                        MetaIndexURI, MetaIndexURIDesc, MetaIndexShortDesc,
 +                      MetaSigURI, MetaSigURIDesc, MetaSigShortDesc,
                        IndexTargets, MetaIndexParser);
        if (Cnf->LocalOnly == true ||
          StringToBool(LookupTag(Message, "Transient-Failure"), false) == false)
index 388c2bfdb31b853eff6b3c7c3dcff1f692221fa7,f655ae2d8dba74972c62113a43632322f340758d..df2c69cf66a2c04368b066ec53eda55790e79498
@@@ -16,13 -16,12 +16,12 @@@ setupaptarchiv
  changetowebserver -o 'aptwebserver::overwrite::.*::filename=/knights'
  
  msgtest 'Acquire test file from the webserver to check' 'overwrite'
- echo '601 Configuration
- Config-Item: Acquire::http::DependOnSTDIN=0
+ if downloadfile http://localhost:8080/holygrail ./knights-talking >/dev/null; then
+     msgpass
+ else
+     msgfail
+ fi
  
- 600 Acquire URI
- URI: http://localhost:8080/holygrail
- Filename: knights-talking
- ' | runapt ${METHODSDIR}/http >/dev/null 2>&1 && msgpass || msgfail
  testfileequal knights-talking 'ni ni ni'
  
  ensure_n_canary_strings_in_dir() {
@@@ -37,8 -36,8 +36,8 @@@
  
  LISTS='rootdir/var/lib/apt/lists'
  rm -rf rootdir/var/lib/apt/lists
 -msgtest 'Got expected NODATA failure in' 'apt-get update'
 -aptget update -qq 2>&1 | grep -q 'E: GPG error.*NODATA' && msgpass || msgfail
 +msgtest 'Got expected failure message' 'apt-get update'
 +aptget update -qq 2>&1 | grep -q 'W:.*Does not start with a cleartext signature' && msgpass || msgfail
  
  ensure_n_canary_strings_in_dir $LISTS 'ni ni ni' 0
  testequal 'partial' ls $LISTS
@@@ -48,8 -47,8 +47,8 @@@ for f in Release Release.gpg main_binar
      echo 'peng neee-wom' > $LISTS/localhost:8080_dists_stable_${f}
  done
  
 -msgtest 'Got expected NODATA failure in' 'apt-get update'
 -aptget update -qq 2>&1 | grep -q 'E: GPG error.*NODATA' && msgpass || msgfail
 +msgtest 'Got expected failure message in' 'apt-get update'
 +aptget update -qq 2>&1 | grep -q 'W:.*Does not start with a cleartext signature' && msgpass || msgfail
  
  ensure_n_canary_strings_in_dir $LISTS 'peng neee-wom' 4
  ensure_n_canary_strings_in_dir $LISTS 'ni ni ni' 0
@@@ -58,7 -57,7 +57,7 @@@
  echo 'peng neee-wom' > $LISTS/localhost:8080_dists_stable_InRelease
  rm -f $LISTS/localhost:8080_dists_stable_Release $LISTS/localhost:8080_dists_stable_Release.gpg
  msgtest 'excpected failure of' 'apt-get update'
 -aptget update -qq 2>&1 | grep -q 'E: GPG error.*NODATA' && msgpass || msgfail
 +aptget update -qq 2>&1 | grep -q 'W:.*Does not start with a cleartext signature' && msgpass || msgfail
  
  ensure_n_canary_strings_in_dir $LISTS 'peng neee-wom' 3
  ensure_n_canary_strings_in_dir $LISTS 'ni ni ni' 0