- case TransactionCommit:
- if (EraseFileName.empty() == false)
- unlink(EraseFileName.c_str());
- break;
- }
- return true;
-}
- /*}}}*/
-// pkgAcqIndex::GetFinalFilename - Return the full final file path /*{{{*/
-std::string pkgAcqIndex::GetFinalFilename() const
-{
- std::string const FinalFile = GetFinalFileNameFromURI(RealURI);
- return GetCompressedFileName(RealURI, FinalFile, CurrentCompressionExtension);
-}
- /*}}}*/
-// AcqIndex::ReverifyAfterIMS - Reverify index after an ims-hit /*{{{*/
-void pkgAcqIndex::ReverifyAfterIMS()
-{
- // update destfile to *not* include the compression extension when doing
- // a reverify (as its uncompressed on disk already)
- DestFile = GetCompressedFileName(RealURI, GetPartialFileNameFromURI(RealURI), CurrentCompressionExtension);
-
- // copy FinalFile into partial/ so that we check the hash again
- string FinalFile = GetFinalFilename();
- Stage = STAGE_DECOMPRESS_AND_VERIFY;
- Desc.URI = "copy:" + FinalFile;
- QueueURI(Desc);
-}
- /*}}}*/
-// AcqIndex::ValidateFile - Validate the content of the downloaded file /*{{{*/
-bool pkgAcqIndex::ValidateFile(const std::string &FileName)
-{
- // FIXME: this can go away once we only ever download stuff that
- // has a valid hash and we never do GET based probing
- // FIXME2: this also leaks debian-isms into the code and should go therefore
-
- /* Always validate the index file for correctness (all indexes must
- * have a Package field) (LP: #346386) (Closes: #627642)
- */
- FileFd fd(FileName, 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);
-
- // all our current indexes have a field 'Package' in each section
- if (_error->PendingError() == true ||
- tag.Step(sec) == false ||
- sec.Exists("Package") == false)
- return false;
- }
- return true;
-}
- /*}}}*/
-// 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 compressed uri. */
-void pkgAcqIndex::Done(string Message,
- unsigned long long Size,
- HashStringList const &Hashes,
- pkgAcquire::MethodConfig *Cfg)
-{
- Item::Done(Message,Size,Hashes,Cfg);
-
- switch(Stage)
- {
- case STAGE_DOWNLOAD:
- StageDownloadDone(Message, Hashes, Cfg);
- break;
- case STAGE_DECOMPRESS_AND_VERIFY:
- StageDecompressDone(Message, Hashes, Cfg);
- break;
- }
-}
- /*}}}*/
-// AcqIndex::StageDownloadDone - Queue for decompress and verify /*{{{*/
-void pkgAcqIndex::StageDownloadDone(string Message,
- HashStringList const &Hashes,
- pkgAcquire::MethodConfig *Cfg)
-{
- // First check if the calculcated Hash of the (compressed) downloaded
- // file matches the hash we have in the MetaIndexRecords for this file
- if(VerifyHashByMetaKey(Hashes) == false)
- {
- RenameOnError(HashSumMismatch);
- Failed(Message, Cfg);
- return;
- }
-
- Complete = true;
-
- // Handle the unzipd case
- string FileName = LookupTag(Message,"Alt-Filename");
- if (FileName.empty() == false)
- {
- Stage = STAGE_DECOMPRESS_AND_VERIFY;
- Local = true;
- DestFile += ".decomp";
- Desc.URI = "copy:" + FileName;
- QueueURI(Desc);
- SetActiveSubprocess("copy");
- return;
- }
-
- FileName = LookupTag(Message,"Filename");
- if (FileName.empty() == true)
- {
- Status = StatError;
- ErrorText = "Method gave a blank filename";
- }
-
- // Methods like e.g. "file:" will give us a (compressed) FileName that is
- // not the "DestFile" we set, in this case we uncompress from the local file
- if (FileName != DestFile)
- Local = true;
- else
- EraseFileName = FileName;
-
- // we need to verify the file against the current Release file again
- // on if-modfied-since hit to avoid a stale attack against us
- if(StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
- {
- // The files timestamp matches, reverify by copy into partial/
- EraseFileName = "";
- ReverifyAfterIMS();
- return;
- }
-
- // If we have compressed indexes enabled, queue for hash verification
- if (_config->FindB("Acquire::GzipIndexes",false))
- {
- DestFile = GetPartialFileNameFromURI(RealURI + '.' + CurrentCompressionExtension);
- EraseFileName = "";
- Stage = STAGE_DECOMPRESS_AND_VERIFY;
- Desc.URI = "copy:" + FileName;
- QueueURI(Desc);
- SetActiveSubprocess("copy");
- return;
- }
-
- // get the binary name for your used compression type
- string decompProg;
- if(CurrentCompressionExtension == "uncompressed")
- decompProg = "copy";
- else
- decompProg = _config->Find(string("Acquire::CompressionTypes::").append(CurrentCompressionExtension),"");
- if(decompProg.empty() == true)
- {
- _error->Error("Unsupported extension: %s", CurrentCompressionExtension.c_str());
- return;
- }
-
- // queue uri for the next stage
- Stage = STAGE_DECOMPRESS_AND_VERIFY;
- DestFile += ".decomp";
- Desc.URI = decompProg + ":" + FileName;
- QueueURI(Desc);
- SetActiveSubprocess(decompProg);
-}
- /*}}}*/
-// pkgAcqIndex::StageDecompressDone - Final verification /*{{{*/
-void pkgAcqIndex::StageDecompressDone(string Message,
- HashStringList const &Hashes,
- pkgAcquire::MethodConfig *Cfg)
-{
- if (ExpectedHashes.usable() && ExpectedHashes != Hashes)
- {
- Desc.URI = RealURI;
- RenameOnError(HashSumMismatch);
- printHashSumComparision(RealURI, ExpectedHashes, Hashes);
- Failed(Message, Cfg);
- return;
- }
-
- if(!ValidateFile(DestFile))
- {
- RenameOnError(InvalidFormat);
- Failed(Message, Cfg);
- return;
- }
-
- // Done, queue for rename on transaction finished
- TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename());
-
- return;
-}
- /*}}}*/
-// AcqMetaBase - Constructor /*{{{*/
-pkgAcqMetaBase::pkgAcqMetaBase(pkgAcquire *Owner,
- const std::vector<IndexTarget*>* IndexTargets,
- indexRecords* MetaIndexParser,
- std::string const &RealURI,
- HashStringList const &ExpectedHashes,
- pkgAcqMetaBase *TransactionManager)
-: Item(Owner, ExpectedHashes, TransactionManager),
- MetaIndexParser(MetaIndexParser), LastMetaIndexParser(NULL), IndexTargets(IndexTargets),
- AuthPass(false), RealURI(RealURI), IMSHit(false)
-{
-}
- /*}}}*/
-// AcqMetaBase::Add - Add a item to the current Transaction /*{{{*/
-void pkgAcqMetaBase::Add(Item *I)
-{
- Transaction.push_back(I);
-}
- /*}}}*/
-// AcqMetaBase::AbortTransaction - Abort the current Transaction /*{{{*/
-void pkgAcqMetaBase::AbortTransaction()
-{
- if(_config->FindB("Debug::Acquire::Transaction", false) == true)
- std::clog << "AbortTransaction: " << TransactionManager << std::endl;
-
- // ensure the toplevel is in error state too
- for (std::vector<Item*>::iterator I = Transaction.begin();
- I != Transaction.end(); ++I)
- {
- (*I)->TransactionState(TransactionAbort);
- }
- Transaction.clear();
-}
- /*}}}*/
-// AcqMetaBase::TransactionHasError - Check for errors in Transaction /*{{{*/
-bool pkgAcqMetaBase::TransactionHasError()
-{
- for (pkgAcquire::ItemIterator I = Transaction.begin();
- I != Transaction.end(); ++I)
- {
- switch((*I)->Status) {
- case StatDone: break;
- case StatIdle: break;
- case StatAuthError: return true;
- case StatError: return true;
- case StatTransientNetworkError: return true;
- case StatFetching: break;