1 // -*- mode: cpp; mode: fold -*-
3 // $Id: acquire-item.cc,v 1.46.2.9 2004/01/16 18:51:11 mdz Exp $
4 /* ######################################################################
6 Acquire Item - Item to acquire
8 Each item can download to exactly one file at a time. This means you
9 cannot create an item that fetches two uri's to two files at the same
10 time. The pkgAcqIndex class creates a second class upon instantiation
11 to fetch the other index files because of this.
13 ##################################################################### */
15 // Include Files /*{{{*/
17 #pragma implementation "apt-pkg/acquire-item.h"
19 #include <apt-pkg/acquire-item.h>
20 #include <apt-pkg/configuration.h>
21 #include <apt-pkg/sourcelist.h>
22 #include <apt-pkg/vendorlist.h>
23 #include <apt-pkg/error.h>
24 #include <apt-pkg/strutl.h>
25 #include <apt-pkg/fileutl.h>
26 #include <apt-pkg/md5.h>
39 // Acquire::Item::Item - Constructor /*{{{*/
40 // ---------------------------------------------------------------------
42 pkgAcquire::Item::Item(pkgAcquire
*Owner
) : Owner(Owner
), FileSize(0),
43 PartialSize(0), Mode(0), ID(0), Complete(false),
44 Local(false), QueueCounter(0)
50 // Acquire::Item::~Item - Destructor /*{{{*/
51 // ---------------------------------------------------------------------
53 pkgAcquire::Item::~Item()
58 // Acquire::Item::Failed - Item failed to download /*{{{*/
59 // ---------------------------------------------------------------------
60 /* We return to an idle state if there are still other queues that could
62 void pkgAcquire::Item::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
65 ErrorText
= LookupTag(Message
,"Message");
66 if (QueueCounter
<= 1)
68 /* This indicates that the file is not available right now but might
69 be sometime later. If we do a retry cycle then this should be
71 if (Cnf
->LocalOnly
== true &&
72 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
84 // Acquire::Item::Start - Item has begun to download /*{{{*/
85 // ---------------------------------------------------------------------
86 /* Stash status and the file size. Note that setting Complete means
87 sub-phases of the acquire process such as decompresion are operating */
88 void pkgAcquire::Item::Start(string
/*Message*/,unsigned long Size
)
90 Status
= StatFetching
;
91 if (FileSize
== 0 && Complete
== false)
95 // Acquire::Item::Done - Item downloaded OK /*{{{*/
96 // ---------------------------------------------------------------------
98 void pkgAcquire::Item::Done(string Message
,unsigned long Size
,string
,
99 pkgAcquire::MethodConfig
*Cnf
)
101 // We just downloaded something..
102 string FileName
= LookupTag(Message
,"Filename");
103 if (Complete
== false && FileName
== DestFile
)
106 Owner
->Log
->Fetched(Size
,atoi(LookupTag(Message
,"Resume-Point","0").c_str()));
113 ErrorText
= string();
114 Owner
->Dequeue(this);
117 // Acquire::Item::Rename - Rename a file /*{{{*/
118 // ---------------------------------------------------------------------
119 /* This helper function is used by alot of item methods as thier final
121 void pkgAcquire::Item::Rename(string From
,string To
)
123 if (rename(From
.c_str(),To
.c_str()) != 0)
126 snprintf(S
,sizeof(S
),_("rename failed, %s (%s -> %s)."),strerror(errno
),
127 From
.c_str(),To
.c_str());
134 // AcqIndex::AcqIndex - Constructor /*{{{*/
135 // ---------------------------------------------------------------------
136 /* The package file is added to the queue and a second class is
137 instantiated to fetch the revision file */
138 pkgAcqIndex::pkgAcqIndex(pkgAcquire
*Owner
,
139 string URI
,string URIDesc
,string ShortDesc
,
140 string ExpectedMD5
, string comprExt
) :
141 Item(Owner
), RealURI(URI
), ExpectedMD5(ExpectedMD5
)
143 Decompression
= false;
146 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
147 DestFile
+= URItoFileName(URI
);
151 // autoselect the compression method
152 if(FileExists("/bin/bzip2"))
153 CompressionExtension
= ".bz2";
155 CompressionExtension
= ".gz";
157 CompressionExtension
= comprExt
;
159 Desc
.URI
= URI
+ CompressionExtension
;
161 Desc
.Description
= URIDesc
;
163 Desc
.ShortDesc
= ShortDesc
;
168 // AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
169 // ---------------------------------------------------------------------
170 /* The only header we use is the last-modified header. */
171 string
pkgAcqIndex::Custom600Headers()
173 string Final
= _config
->FindDir("Dir::State::lists");
174 Final
+= URItoFileName(RealURI
);
177 if (stat(Final
.c_str(),&Buf
) != 0)
178 return "\nIndex-File: true";
180 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
184 void pkgAcqIndex::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
186 // no .bz2 found, retry with .gz
187 if(Desc
.URI
.substr(Desc
.URI
.size()-3) == "bz2") {
188 Desc
.URI
= Desc
.URI
.substr(0,Desc
.URI
.size()-3) + "gz";
190 // retry with a gzip one
191 new pkgAcqIndex(Owner
, RealURI
, Desc
.Description
,Desc
.ShortDesc
,
192 ExpectedMD5
, string(".gz"));
200 Item::Failed(Message
,Cnf
);
204 // AcqIndex::Done - Finished a fetch /*{{{*/
205 // ---------------------------------------------------------------------
206 /* This goes through a number of states.. On the initial fetch the
207 method could possibly return an alternate filename which points
208 to the uncompressed version of the file. If this is so the file
209 is copied into the partial directory. In all other cases the file
210 is decompressed with a gzip uri. */
211 void pkgAcqIndex::Done(string Message
,unsigned long Size
,string MD5
,
212 pkgAcquire::MethodConfig
*Cfg
)
214 Item::Done(Message
,Size
,MD5
,Cfg
);
216 if (Decompression
== true)
218 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
220 std::cerr
<< std::endl
<< RealURI
<< ": Computed MD5: " << MD5
;
221 std::cerr
<< " Expected MD5: " << ExpectedMD5
<< std::endl
;
227 FileFd
Fd(DestFile
, FileFd::ReadOnly
);
228 sum
.AddFD(Fd
.Fd(), Fd
.Size());
230 MD5
= (string
)sum
.Result();
233 if (!ExpectedMD5
.empty() && MD5
!= ExpectedMD5
)
235 Status
= StatAuthError
;
236 ErrorText
= _("MD5Sum mismatch");
237 Rename(DestFile
,DestFile
+ ".FAILED");
240 // Done, move it into position
241 string FinalFile
= _config
->FindDir("Dir::State::lists");
242 FinalFile
+= URItoFileName(RealURI
);
243 Rename(DestFile
,FinalFile
);
244 chmod(FinalFile
.c_str(),0644);
246 /* We restore the original name to DestFile so that the clean operation
248 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
249 DestFile
+= URItoFileName(RealURI
);
251 // Remove the compressed version.
253 unlink(DestFile
.c_str());
260 // Handle the unzipd case
261 string FileName
= LookupTag(Message
,"Alt-Filename");
262 if (FileName
.empty() == false)
264 // The files timestamp matches
265 if (StringToBool(LookupTag(Message
,"Alt-IMS-Hit"),false) == true)
268 Decompression
= true;
270 DestFile
+= ".decomp";
271 Desc
.URI
= "copy:" + FileName
;
277 FileName
= LookupTag(Message
,"Filename");
278 if (FileName
.empty() == true)
281 ErrorText
= "Method gave a blank filename";
284 // The files timestamp matches
285 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true)
288 if (FileName
== DestFile
)
293 string compExt
= Desc
.URI
.substr(Desc
.URI
.size()-3);
296 decompProg
= "bzip2";
297 else if(compExt
== ".gz")
300 _error
->Error("Unsupported extension: %s", compExt
.c_str());
304 Decompression
= true;
305 DestFile
+= ".decomp";
306 Desc
.URI
= string(decompProg
) + ":" + FileName
;
311 // AcqIndexTrans::pkgAcqIndexTrans - Constructor /*{{{*/
312 // ---------------------------------------------------------------------
313 /* The Translation file is added to the queue */
314 pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire
*Owner
,
315 string URI
,string URIDesc
,string ShortDesc
) :
316 pkgAcqIndex(Owner
, URI
, URIDesc
, ShortDesc
, "", "")
321 // AcqIndexTrans::Failed - Silence failure messages for missing files /*{{{*/
322 // ---------------------------------------------------------------------
324 void pkgAcqIndexTrans::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
326 if (Cnf
->LocalOnly
== true ||
327 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == false)
336 Item::Failed(Message
,Cnf
);
340 pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire
*Owner
,
341 string URI
,string URIDesc
,string ShortDesc
,
342 string MetaIndexURI
, string MetaIndexURIDesc
,
343 string MetaIndexShortDesc
,
344 const vector
<IndexTarget
*>* IndexTargets
,
345 indexRecords
* MetaIndexParser
) :
346 Item(Owner
), RealURI(URI
), MetaIndexURI(MetaIndexURI
),
347 MetaIndexURIDesc(MetaIndexURIDesc
), MetaIndexShortDesc(MetaIndexShortDesc
),
348 MetaIndexParser(MetaIndexParser
), IndexTargets(IndexTargets
)
350 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
351 DestFile
+= URItoFileName(URI
);
353 // remove any partial downloaded sig-file in partial/.
354 // it may confuse proxies and is too small to warrant a
355 // partial download anyway
356 unlink(DestFile
.c_str());
359 Desc
.Description
= URIDesc
;
361 Desc
.ShortDesc
= ShortDesc
;
365 string Final
= _config
->FindDir("Dir::State::lists");
366 Final
+= URItoFileName(RealURI
);
368 if (stat(Final
.c_str(),&Buf
) == 0)
370 // File was already in place. It needs to be re-verified
371 // because Release might have changed, so Move it into partial
372 Rename(Final
,DestFile
);
378 // pkgAcqMetaSig::Custom600Headers - Insert custom request headers /*{{{*/
379 // ---------------------------------------------------------------------
380 /* The only header we use is the last-modified header. */
381 string
pkgAcqMetaSig::Custom600Headers()
384 if (stat(DestFile
.c_str(),&Buf
) != 0)
385 return "\nIndex-File: true";
387 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
390 void pkgAcqMetaSig::Done(string Message
,unsigned long Size
,string MD5
,
391 pkgAcquire::MethodConfig
*Cfg
)
393 Item::Done(Message
,Size
,MD5
,Cfg
);
395 string FileName
= LookupTag(Message
,"Filename");
396 if (FileName
.empty() == true)
399 ErrorText
= "Method gave a blank filename";
403 if (FileName
!= DestFile
)
405 // We have to copy it into place
407 Desc
.URI
= "copy:" + FileName
;
414 // queue a pkgAcqMetaIndex to be verified against the sig we just retrieved
415 new pkgAcqMetaIndex(Owner
, MetaIndexURI
, MetaIndexURIDesc
, MetaIndexShortDesc
,
416 DestFile
, IndexTargets
, MetaIndexParser
);
420 void pkgAcqMetaSig::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
422 string Final
= _config
->FindDir("Dir::State::lists") + URItoFileName(RealURI
);
424 // if we get a network error we fail gracefully
425 if(Status
== StatTransientNetworkError
)
427 Item::Failed(Message
,Cnf
);
428 // move the sigfile back on network failures (and re-authenticated?)
429 if(FileExists(DestFile
))
430 Rename(DestFile
,Final
);
432 // set the status back to , Item::Failed likes to reset it
433 Status
= pkgAcquire::Item::StatTransientNetworkError
;
437 // Delete any existing sigfile when the acquire failed
438 unlink(Final
.c_str());
440 // queue a pkgAcqMetaIndex with no sigfile
441 new pkgAcqMetaIndex(Owner
, MetaIndexURI
, MetaIndexURIDesc
, MetaIndexShortDesc
,
442 "", IndexTargets
, MetaIndexParser
);
444 if (Cnf
->LocalOnly
== true ||
445 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == false)
454 Item::Failed(Message
,Cnf
);
457 pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire
*Owner
,
458 string URI
,string URIDesc
,string ShortDesc
,
460 const vector
<struct IndexTarget
*>* IndexTargets
,
461 indexRecords
* MetaIndexParser
) :
462 Item(Owner
), RealURI(URI
), SigFile(SigFile
), AuthPass(false),
463 MetaIndexParser(MetaIndexParser
), IndexTargets(IndexTargets
), IMSHit(false)
465 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
466 DestFile
+= URItoFileName(URI
);
469 Desc
.Description
= URIDesc
;
471 Desc
.ShortDesc
= ShortDesc
;
478 // pkgAcqMetaIndex::Custom600Headers - Insert custom request headers /*{{{*/
479 // ---------------------------------------------------------------------
480 /* The only header we use is the last-modified header. */
481 string
pkgAcqMetaIndex::Custom600Headers()
483 string Final
= _config
->FindDir("Dir::State::lists");
484 Final
+= URItoFileName(RealURI
);
487 if (stat(Final
.c_str(),&Buf
) != 0)
488 return "\nIndex-File: true";
490 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
493 void pkgAcqMetaIndex::Done(string Message
,unsigned long Size
,string MD5
,
494 pkgAcquire::MethodConfig
*Cfg
)
496 Item::Done(Message
,Size
,MD5
,Cfg
);
498 // MetaIndexes are done in two passes: one to download the
499 // metaindex with an appropriate method, and a second to verify it
500 // with the gpgv method
502 if (AuthPass
== true)
508 RetrievalDone(Message
);
510 // Still more retrieving to do
515 // There was no signature file, so we are finished. Download
516 // the indexes without verification.
521 // There was a signature file, so pass it to gpgv for
524 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
525 std::cerr
<< "Metaindex acquired, queueing gpg verification ("
526 << SigFile
<< "," << DestFile
<< ")\n";
528 Desc
.URI
= "gpgv:" + SigFile
;
535 void pkgAcqMetaIndex::RetrievalDone(string Message
)
537 // We have just finished downloading a Release file (it is not
540 string FileName
= LookupTag(Message
,"Filename");
541 if (FileName
.empty() == true)
544 ErrorText
= "Method gave a blank filename";
548 if (FileName
!= DestFile
)
551 Desc
.URI
= "copy:" + FileName
;
556 // see if the download was a IMSHit
557 IMSHit
= StringToBool(LookupTag(Message
,"IMS-Hit"),false);
561 string FinalFile
= _config
->FindDir("Dir::State::lists");
562 FinalFile
+= URItoFileName(RealURI
);
564 // The files timestamp matches
565 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == false)
567 // Move it into position
568 Rename(DestFile
,FinalFile
);
570 DestFile
= FinalFile
;
573 void pkgAcqMetaIndex::AuthDone(string Message
)
575 // At this point, the gpgv method has succeeded, so there is a
576 // valid signature from a key in the trusted keyring. We
577 // perform additional verification of its contents, and use them
578 // to verify the indexes we are about to download
580 if (!MetaIndexParser
->Load(DestFile
))
582 Status
= StatAuthError
;
583 ErrorText
= MetaIndexParser
->ErrorText
;
587 if (!VerifyVendor(Message
))
592 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
593 std::cerr
<< "Signature verification succeeded: "
594 << DestFile
<< std::endl
;
596 // Download further indexes with verification
599 // Done, move signature file into position
601 string VerifiedSigFile
= _config
->FindDir("Dir::State::lists") +
602 URItoFileName(RealURI
) + ".gpg";
603 Rename(SigFile
,VerifiedSigFile
);
604 chmod(VerifiedSigFile
.c_str(),0644);
607 void pkgAcqMetaIndex::QueueIndexes(bool verify
)
609 for (vector
<struct IndexTarget
*>::const_iterator Target
= IndexTargets
->begin();
610 Target
!= IndexTargets
->end();
613 string ExpectedIndexMD5
;
616 const indexRecords::checkSum
*Record
= MetaIndexParser
->Lookup((*Target
)->MetaKey
);
619 Status
= StatAuthError
;
620 ErrorText
= "Unable to find expected entry "
621 + (*Target
)->MetaKey
+ " in Meta-index file (malformed Release file?)";
624 ExpectedIndexMD5
= Record
->MD5Hash
;
625 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
627 std::cerr
<< "Queueing: " << (*Target
)->URI
<< std::endl
;
628 std::cerr
<< "Expected MD5: " << ExpectedIndexMD5
<< std::endl
;
630 if (ExpectedIndexMD5
.empty())
632 Status
= StatAuthError
;
633 ErrorText
= "Unable to find MD5 sum for "
634 + (*Target
)->MetaKey
+ " in Meta-index file";
639 // Queue Packages file
640 new pkgAcqIndex(Owner
, (*Target
)->URI
, (*Target
)->Description
,
641 (*Target
)->ShortDesc
, ExpectedIndexMD5
);
645 bool pkgAcqMetaIndex::VerifyVendor(string Message
)
647 // // Maybe this should be made available from above so we don't have
648 // // to read and parse it every time?
649 // pkgVendorList List;
650 // List.ReadMainList();
652 // const Vendor* Vndr = NULL;
653 // for (std::vector<string>::const_iterator I = GPGVOutput.begin(); I != GPGVOutput.end(); I++)
655 // string::size_type pos = (*I).find("VALIDSIG ");
656 // if (_config->FindB("Debug::Vendor", false))
657 // std::cerr << "Looking for VALIDSIG in \"" << (*I) << "\": pos " << pos
659 // if (pos != std::string::npos)
661 // string Fingerprint = (*I).substr(pos+sizeof("VALIDSIG"));
662 // if (_config->FindB("Debug::Vendor", false))
663 // std::cerr << "Looking for \"" << Fingerprint << "\" in vendor..." <<
665 // Vndr = List.FindVendor(Fingerprint) != "";
666 // if (Vndr != NULL);
670 string::size_type pos
;
672 // check for missing sigs (that where not fatal because otherwise we had
675 string msg
= _("There are no public key available for the "
676 "following key IDs:\n");
677 pos
= Message
.find("NO_PUBKEY ");
678 if (pos
!= std::string::npos
)
680 string::size_type start
= pos
+strlen("NO_PUBKEY ");
681 string Fingerprint
= Message
.substr(start
, Message
.find("\n")-start
);
682 missingkeys
+= (Fingerprint
);
684 if(!missingkeys
.empty())
685 _error
->Warning("%s", string(msg
+missingkeys
).c_str());
687 string Transformed
= MetaIndexParser
->GetExpectedDist();
689 if (Transformed
== "../project/experimental")
691 Transformed
= "experimental";
694 pos
= Transformed
.rfind('/');
695 if (pos
!= string::npos
)
697 Transformed
= Transformed
.substr(0, pos
);
700 if (Transformed
== ".")
705 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
707 std::cerr
<< "Got Codename: " << MetaIndexParser
->GetDist() << std::endl
;
708 std::cerr
<< "Expecting Dist: " << MetaIndexParser
->GetExpectedDist() << std::endl
;
709 std::cerr
<< "Transformed Dist: " << Transformed
<< std::endl
;
712 if (MetaIndexParser
->CheckDist(Transformed
) == false)
714 // This might become fatal one day
715 // Status = StatAuthError;
716 // ErrorText = "Conflicting distribution; expected "
717 // + MetaIndexParser->GetExpectedDist() + " but got "
718 // + MetaIndexParser->GetDist();
720 if (!Transformed
.empty())
722 _error
->Warning("Conflicting distribution: %s (expected %s but got %s)",
723 Desc
.Description
.c_str(),
725 MetaIndexParser
->GetDist().c_str());
732 // pkgAcqMetaIndex::Failed - no Release file present or no signature
733 // file present /*{{{*/
734 // ---------------------------------------------------------------------
736 void pkgAcqMetaIndex::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
738 if (AuthPass
== true)
740 // if we fail the authentication but got the file via a IMS-Hit
741 // this means that the file wasn't downloaded and that it might be
742 // just stale (server problem, proxy etc). we delete what we have
743 // queue it again without i-m-s
744 // alternatively we could just unlink the file and let the user try again
750 unlink(DestFile
.c_str());
752 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
753 DestFile
+= URItoFileName(RealURI
);
759 // gpgv method failed
760 _error
->Warning("GPG error: %s: %s",
761 Desc
.Description
.c_str(),
762 LookupTag(Message
,"Message").c_str());
766 // No Release file was present, or verification failed, so fall
767 // back to queueing Packages files without verification
773 // AcqArchive::AcqArchive - Constructor /*{{{*/
774 // ---------------------------------------------------------------------
775 /* This just sets up the initial fetch environment and queues the first
777 pkgAcqArchive::pkgAcqArchive(pkgAcquire
*Owner
,pkgSourceList
*Sources
,
778 pkgRecords
*Recs
,pkgCache::VerIterator
const &Version
,
779 string
&StoreFilename
) :
780 Item(Owner
), Version(Version
), Sources(Sources
), Recs(Recs
),
781 StoreFilename(StoreFilename
), Vf(Version
.FileList()),
784 Retries
= _config
->FindI("Acquire::Retries",0);
786 if (Version
.Arch() == 0)
788 _error
->Error(_("I wasn't able to locate a file for the %s package. "
789 "This might mean you need to manually fix this package. "
790 "(due to missing arch)"),
791 Version
.ParentPkg().Name());
795 /* We need to find a filename to determine the extension. We make the
796 assumption here that all the available sources for this version share
797 the same extension.. */
798 // Skip not source sources, they do not have file fields.
799 for (; Vf
.end() == false; Vf
++)
801 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) != 0)
806 // Does not really matter here.. we are going to fail out below
807 if (Vf
.end() != true)
809 // If this fails to get a file name we will bomb out below.
810 pkgRecords::Parser
&Parse
= Recs
->Lookup(Vf
);
811 if (_error
->PendingError() == true)
814 // Generate the final file name as: package_version_arch.foo
815 StoreFilename
= QuoteString(Version
.ParentPkg().Name(),"_:") + '_' +
816 QuoteString(Version
.VerStr(),"_:") + '_' +
817 QuoteString(Version
.Arch(),"_:.") +
818 "." + flExtension(Parse
.FileName());
821 // check if we have one trusted source for the package. if so, switch
822 // to "TrustedOnly" mode
823 for (pkgCache::VerFileIterator i
= Version
.FileList(); i
.end() == false; i
++)
826 if (Sources
->FindIndex(i
.File(),Index
) == false)
828 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
830 std::cerr
<< "Checking index: " << Index
->Describe()
831 << "(Trusted=" << Index
->IsTrusted() << ")\n";
833 if (Index
->IsTrusted()) {
839 // "allow-unauthenticated" restores apts old fetching behaviour
840 // that means that e.g. unauthenticated file:// uris are higher
841 // priority than authenticated http:// uris
842 if (_config
->FindB("APT::Get::AllowUnauthenticated",false) == true)
846 if (QueueNext() == false && _error
->PendingError() == false)
847 _error
->Error(_("I wasn't able to locate file for the %s package. "
848 "This might mean you need to manually fix this package."),
849 Version
.ParentPkg().Name());
852 // AcqArchive::QueueNext - Queue the next file source /*{{{*/
853 // ---------------------------------------------------------------------
854 /* This queues the next available file version for download. It checks if
855 the archive is already available in the cache and stashs the MD5 for
857 bool pkgAcqArchive::QueueNext()
859 for (; Vf
.end() == false; Vf
++)
861 // Ignore not source sources
862 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) != 0)
865 // Try to cross match against the source list
867 if (Sources
->FindIndex(Vf
.File(),Index
) == false)
870 // only try to get a trusted package from another source if that source
872 if(Trusted
&& !Index
->IsTrusted())
875 // Grab the text package record
876 pkgRecords::Parser
&Parse
= Recs
->Lookup(Vf
);
877 if (_error
->PendingError() == true)
880 string PkgFile
= Parse
.FileName();
881 MD5
= Parse
.MD5Hash();
882 if (PkgFile
.empty() == true)
883 return _error
->Error(_("The package index files are corrupted. No Filename: "
884 "field for package %s."),
885 Version
.ParentPkg().Name());
887 Desc
.URI
= Index
->ArchiveURI(PkgFile
);
888 Desc
.Description
= Index
->ArchiveInfo(Version
);
890 Desc
.ShortDesc
= Version
.ParentPkg().Name();
892 // See if we already have the file. (Legacy filenames)
893 FileSize
= Version
->Size
;
894 string FinalFile
= _config
->FindDir("Dir::Cache::Archives") + flNotDir(PkgFile
);
896 if (stat(FinalFile
.c_str(),&Buf
) == 0)
898 // Make sure the size matches
899 if ((unsigned)Buf
.st_size
== Version
->Size
)
904 StoreFilename
= DestFile
= FinalFile
;
908 /* Hmm, we have a file and its size does not match, this means it is
909 an old style mismatched arch */
910 unlink(FinalFile
.c_str());
913 // Check it again using the new style output filenames
914 FinalFile
= _config
->FindDir("Dir::Cache::Archives") + flNotDir(StoreFilename
);
915 if (stat(FinalFile
.c_str(),&Buf
) == 0)
917 // Make sure the size matches
918 if ((unsigned)Buf
.st_size
== Version
->Size
)
923 StoreFilename
= DestFile
= FinalFile
;
927 /* Hmm, we have a file and its size does not match, this shouldnt
929 unlink(FinalFile
.c_str());
932 DestFile
= _config
->FindDir("Dir::Cache::Archives") + "partial/" + flNotDir(StoreFilename
);
934 // Check the destination file
935 if (stat(DestFile
.c_str(),&Buf
) == 0)
937 // Hmm, the partial file is too big, erase it
938 if ((unsigned)Buf
.st_size
> Version
->Size
)
939 unlink(DestFile
.c_str());
941 PartialSize
= Buf
.st_size
;
946 Desc
.URI
= Index
->ArchiveURI(PkgFile
);
947 Desc
.Description
= Index
->ArchiveInfo(Version
);
949 Desc
.ShortDesc
= Version
.ParentPkg().Name();
958 // AcqArchive::Done - Finished fetching /*{{{*/
959 // ---------------------------------------------------------------------
961 void pkgAcqArchive::Done(string Message
,unsigned long Size
,string Md5Hash
,
962 pkgAcquire::MethodConfig
*Cfg
)
964 Item::Done(Message
,Size
,Md5Hash
,Cfg
);
967 if (Size
!= Version
->Size
)
970 ErrorText
= _("Size mismatch");
975 if (Md5Hash
.empty() == false && MD5
.empty() == false)
980 ErrorText
= _("MD5Sum mismatch");
981 if(FileExists(DestFile
))
982 Rename(DestFile
,DestFile
+ ".FAILED");
987 // Grab the output filename
988 string FileName
= LookupTag(Message
,"Filename");
989 if (FileName
.empty() == true)
992 ErrorText
= "Method gave a blank filename";
998 // Reference filename
999 if (FileName
!= DestFile
)
1001 StoreFilename
= DestFile
= FileName
;
1006 // Done, move it into position
1007 string FinalFile
= _config
->FindDir("Dir::Cache::Archives");
1008 FinalFile
+= flNotDir(StoreFilename
);
1009 Rename(DestFile
,FinalFile
);
1011 StoreFilename
= DestFile
= FinalFile
;
1015 // AcqArchive::Failed - Failure handler /*{{{*/
1016 // ---------------------------------------------------------------------
1017 /* Here we try other sources */
1018 void pkgAcqArchive::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
1020 ErrorText
= LookupTag(Message
,"Message");
1022 /* We don't really want to retry on failed media swaps, this prevents
1023 that. An interesting observation is that permanent failures are not
1025 if (Cnf
->Removable
== true &&
1026 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
1028 // Vf = Version.FileList();
1029 while (Vf
.end() == false) Vf
++;
1030 StoreFilename
= string();
1031 Item::Failed(Message
,Cnf
);
1035 if (QueueNext() == false)
1037 // This is the retry counter
1039 Cnf
->LocalOnly
== false &&
1040 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
1043 Vf
= Version
.FileList();
1044 if (QueueNext() == true)
1048 StoreFilename
= string();
1049 Item::Failed(Message
,Cnf
);
1053 // AcqArchive::IsTrusted - Determine whether this archive comes from a
1054 // trusted source /*{{{*/
1055 // ---------------------------------------------------------------------
1056 bool pkgAcqArchive::IsTrusted()
1061 // AcqArchive::Finished - Fetching has finished, tidy up /*{{{*/
1062 // ---------------------------------------------------------------------
1064 void pkgAcqArchive::Finished()
1066 if (Status
== pkgAcquire::Item::StatDone
&&
1069 StoreFilename
= string();
1073 // AcqFile::pkgAcqFile - Constructor /*{{{*/
1074 // ---------------------------------------------------------------------
1075 /* The file is added to the queue */
1076 pkgAcqFile::pkgAcqFile(pkgAcquire
*Owner
,string URI
,string MD5
,
1077 unsigned long Size
,string Dsc
,string ShortDesc
,
1078 const string
&DestDir
, const string
&DestFilename
) :
1079 Item(Owner
), Md5Hash(MD5
)
1081 Retries
= _config
->FindI("Acquire::Retries",0);
1083 if(!DestFilename
.empty())
1084 DestFile
= DestFilename
;
1085 else if(!DestDir
.empty())
1086 DestFile
= DestDir
+ "/" + flNotDir(URI
);
1088 DestFile
= flNotDir(URI
);
1092 Desc
.Description
= Dsc
;
1095 // Set the short description to the archive component
1096 Desc
.ShortDesc
= ShortDesc
;
1098 // Get the transfer sizes
1101 if (stat(DestFile
.c_str(),&Buf
) == 0)
1103 // Hmm, the partial file is too big, erase it
1104 if ((unsigned)Buf
.st_size
> Size
)
1105 unlink(DestFile
.c_str());
1107 PartialSize
= Buf
.st_size
;
1113 // AcqFile::Done - Item downloaded OK /*{{{*/
1114 // ---------------------------------------------------------------------
1116 void pkgAcqFile::Done(string Message
,unsigned long Size
,string MD5
,
1117 pkgAcquire::MethodConfig
*Cnf
)
1120 if (Md5Hash
.empty() == false && MD5
.empty() == false)
1125 ErrorText
= "MD5Sum mismatch";
1126 Rename(DestFile
,DestFile
+ ".FAILED");
1131 Item::Done(Message
,Size
,MD5
,Cnf
);
1133 string FileName
= LookupTag(Message
,"Filename");
1134 if (FileName
.empty() == true)
1137 ErrorText
= "Method gave a blank filename";
1143 // The files timestamp matches
1144 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true)
1147 // We have to copy it into place
1148 if (FileName
!= DestFile
)
1151 if (_config
->FindB("Acquire::Source-Symlinks",true) == false ||
1152 Cnf
->Removable
== true)
1154 Desc
.URI
= "copy:" + FileName
;
1159 // Erase the file if it is a symlink so we can overwrite it
1161 if (lstat(DestFile
.c_str(),&St
) == 0)
1163 if (S_ISLNK(St
.st_mode
) != 0)
1164 unlink(DestFile
.c_str());
1168 if (symlink(FileName
.c_str(),DestFile
.c_str()) != 0)
1170 ErrorText
= "Link to " + DestFile
+ " failure ";
1177 // AcqFile::Failed - Failure handler /*{{{*/
1178 // ---------------------------------------------------------------------
1179 /* Here we try other sources */
1180 void pkgAcqFile::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
1182 ErrorText
= LookupTag(Message
,"Message");
1184 // This is the retry counter
1186 Cnf
->LocalOnly
== false &&
1187 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
1194 Item::Failed(Message
,Cnf
);