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 UsedMirror
= LookupTag(Message
,"UsedMirror");
67 if (QueueCounter
<= 1)
69 /* This indicates that the file is not available right now but might
70 be sometime later. If we do a retry cycle then this should be
72 if (Cnf
->LocalOnly
== true &&
73 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
84 // report mirror failure back to LP if we actually use a mirror
85 string FailReason
= LookupTag(Message
, "FailReason");
86 if(FailReason
.size() != 0)
87 ReportMirrorFailure(FailReason
);
89 ReportMirrorFailure(ErrorText
);
92 // Acquire::Item::Start - Item has begun to download /*{{{*/
93 // ---------------------------------------------------------------------
94 /* Stash status and the file size. Note that setting Complete means
95 sub-phases of the acquire process such as decompresion are operating */
96 void pkgAcquire::Item::Start(string
/*Message*/,unsigned long Size
)
98 Status
= StatFetching
;
99 if (FileSize
== 0 && Complete
== false)
103 // Acquire::Item::Done - Item downloaded OK /*{{{*/
104 // ---------------------------------------------------------------------
106 void pkgAcquire::Item::Done(string Message
,unsigned long Size
,string
,
107 pkgAcquire::MethodConfig
*Cnf
)
109 // We just downloaded something..
110 string FileName
= LookupTag(Message
,"Filename");
111 UsedMirror
= LookupTag(Message
,"UsedMirror");
112 if (Complete
== false && FileName
== DestFile
)
115 Owner
->Log
->Fetched(Size
,atoi(LookupTag(Message
,"Resume-Point","0").c_str()));
121 ErrorText
= string();
122 Owner
->Dequeue(this);
125 // Acquire::Item::Rename - Rename a file /*{{{*/
126 // ---------------------------------------------------------------------
127 /* This helper function is used by alot of item methods as thier final
129 void pkgAcquire::Item::Rename(string From
,string To
)
131 if (rename(From
.c_str(),To
.c_str()) != 0)
134 snprintf(S
,sizeof(S
),_("rename failed, %s (%s -> %s)."),strerror(errno
),
135 From
.c_str(),To
.c_str());
142 void pkgAcquire::Item::ReportMirrorFailure(string FailCode
)
144 // we only act if a mirror was used at all
145 if(UsedMirror
.empty())
148 std::cerr
<< "\nReportMirrorFailure: "
150 << " Uri: " << DescURI()
152 << FailCode
<< std::endl
;
154 const char *Args
[40];
156 string report
= _config
->Find("Methods::Mirror::ProblemReporting",
157 "/usr/lib/apt/apt-report-mirror-failure");
158 if(!FileExists(report
))
160 Args
[i
++] = report
.c_str();
161 Args
[i
++] = UsedMirror
.c_str();
162 Args
[i
++] = DescURI().c_str();
163 Args
[i
++] = FailCode
.c_str();
165 pid_t pid
= ExecFork();
168 _error
->Error("ReportMirrorFailure Fork failed");
173 execvp(Args
[0], (char**)Args
);
174 std::cerr
<< "Could not exec " << Args
[0] << std::endl
;
177 if(!ExecWait(pid
, "report-mirror-failure"))
179 _error
->Warning("Couldn't report problem to '%s'",
180 _config
->Find("Methods::Mirror::ProblemReporting").c_str());
185 // AcqIndex::AcqIndex - Constructor /*{{{*/
186 // ---------------------------------------------------------------------
187 /* The package file is added to the queue and a second class is
188 instantiated to fetch the revision file */
189 pkgAcqIndex::pkgAcqIndex(pkgAcquire
*Owner
,
190 string URI
,string URIDesc
,string ShortDesc
,
191 string ExpectedMD5
, string comprExt
) :
192 Item(Owner
), RealURI(URI
), ExpectedMD5(ExpectedMD5
)
194 Decompression
= false;
197 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
198 DestFile
+= URItoFileName(URI
);
202 // autoselect the compression method
203 if(FileExists("/bin/bzip2"))
204 CompressionExtension
= ".bz2";
206 CompressionExtension
= ".gz";
208 CompressionExtension
= comprExt
;
210 Desc
.URI
= URI
+ CompressionExtension
;
212 Desc
.Description
= URIDesc
;
214 Desc
.ShortDesc
= ShortDesc
;
219 // AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
220 // ---------------------------------------------------------------------
221 /* The only header we use is the last-modified header. */
222 string
pkgAcqIndex::Custom600Headers()
224 string Final
= _config
->FindDir("Dir::State::lists");
225 Final
+= URItoFileName(RealURI
);
228 if (stat(Final
.c_str(),&Buf
) != 0)
229 return "\nIndex-File: true";
230 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
234 void pkgAcqIndex::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
236 // no .bz2 found, retry with .gz
237 if(Desc
.URI
.substr(Desc
.URI
.size()-3) == "bz2") {
238 Desc
.URI
= Desc
.URI
.substr(0,Desc
.URI
.size()-3) + "gz";
240 // retry with a gzip one
241 new pkgAcqIndex(Owner
, RealURI
, Desc
.Description
,Desc
.ShortDesc
,
242 ExpectedMD5
, string(".gz"));
250 Item::Failed(Message
,Cnf
);
254 // AcqIndex::Done - Finished a fetch /*{{{*/
255 // ---------------------------------------------------------------------
256 /* This goes through a number of states.. On the initial fetch the
257 method could possibly return an alternate filename which points
258 to the uncompressed version of the file. If this is so the file
259 is copied into the partial directory. In all other cases the file
260 is decompressed with a gzip uri. */
261 void pkgAcqIndex::Done(string Message
,unsigned long Size
,string MD5
,
262 pkgAcquire::MethodConfig
*Cfg
)
264 Item::Done(Message
,Size
,MD5
,Cfg
);
266 if (Decompression
== true)
268 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
270 std::cerr
<< std::endl
<< RealURI
<< ": Computed MD5: " << MD5
;
271 std::cerr
<< " Expected MD5: " << ExpectedMD5
<< std::endl
;
277 FileFd
Fd(DestFile
, FileFd::ReadOnly
);
278 sum
.AddFD(Fd
.Fd(), Fd
.Size());
280 MD5
= (string
)sum
.Result();
283 if (!ExpectedMD5
.empty() && MD5
!= ExpectedMD5
)
285 Status
= StatAuthError
;
286 ErrorText
= _("MD5Sum mismatch");
287 Rename(DestFile
,DestFile
+ ".FAILED");
288 ReportMirrorFailure("HashChecksumFailure");
291 // Done, move it into position
292 string FinalFile
= _config
->FindDir("Dir::State::lists");
293 FinalFile
+= URItoFileName(RealURI
);
294 Rename(DestFile
,FinalFile
);
295 chmod(FinalFile
.c_str(),0644);
297 /* We restore the original name to DestFile so that the clean operation
299 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
300 DestFile
+= URItoFileName(RealURI
);
302 // Remove the compressed version.
304 unlink(DestFile
.c_str());
311 // Handle the unzipd case
312 string FileName
= LookupTag(Message
,"Alt-Filename");
313 if (FileName
.empty() == false)
315 // The files timestamp matches
316 if (StringToBool(LookupTag(Message
,"Alt-IMS-Hit"),false) == true)
319 Decompression
= true;
321 DestFile
+= ".decomp";
322 Desc
.URI
= "copy:" + FileName
;
328 FileName
= LookupTag(Message
,"Filename");
329 if (FileName
.empty() == true)
332 ErrorText
= "Method gave a blank filename";
335 // The files timestamp matches
336 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true)
339 if (FileName
== DestFile
)
344 string compExt
= Desc
.URI
.substr(Desc
.URI
.size()-3);
347 decompProg
= "bzip2";
348 else if(compExt
== ".gz")
351 _error
->Error("Unsupported extension: %s", compExt
.c_str());
355 Decompression
= true;
356 DestFile
+= ".decomp";
357 Desc
.URI
= string(decompProg
) + ":" + FileName
;
362 // AcqIndexTrans::pkgAcqIndexTrans - Constructor /*{{{*/
363 // ---------------------------------------------------------------------
364 /* The Translation file is added to the queue */
365 pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire
*Owner
,
366 string URI
,string URIDesc
,string ShortDesc
) :
367 pkgAcqIndex(Owner
, URI
, URIDesc
, ShortDesc
, "", "")
372 // AcqIndexTrans::Failed - Silence failure messages for missing files /*{{{*/
373 // ---------------------------------------------------------------------
375 void pkgAcqIndexTrans::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
377 if (Cnf
->LocalOnly
== true ||
378 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == false)
387 Item::Failed(Message
,Cnf
);
391 pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire
*Owner
,
392 string URI
,string URIDesc
,string ShortDesc
,
393 string MetaIndexURI
, string MetaIndexURIDesc
,
394 string MetaIndexShortDesc
,
395 const vector
<IndexTarget
*>* IndexTargets
,
396 indexRecords
* MetaIndexParser
) :
397 Item(Owner
), RealURI(URI
), MetaIndexURI(MetaIndexURI
),
398 MetaIndexURIDesc(MetaIndexURIDesc
), MetaIndexShortDesc(MetaIndexShortDesc
),
399 MetaIndexParser(MetaIndexParser
), IndexTargets(IndexTargets
)
401 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
402 DestFile
+= URItoFileName(URI
);
404 // remove any partial downloaded sig-file in partial/.
405 // it may confuse proxies and is too small to warrant a
406 // partial download anyway
407 unlink(DestFile
.c_str());
410 Desc
.Description
= URIDesc
;
412 Desc
.ShortDesc
= ShortDesc
;
416 string Final
= _config
->FindDir("Dir::State::lists");
417 Final
+= URItoFileName(RealURI
);
419 if (stat(Final
.c_str(),&Buf
) == 0)
421 // File was already in place. It needs to be re-verified
422 // because Release might have changed, so Move it into partial
423 Rename(Final
,DestFile
);
429 // pkgAcqMetaSig::Custom600Headers - Insert custom request headers /*{{{*/
430 // ---------------------------------------------------------------------
431 /* The only header we use is the last-modified header. */
432 string
pkgAcqMetaSig::Custom600Headers()
435 if (stat(DestFile
.c_str(),&Buf
) != 0)
436 return "\nIndex-File: true";
438 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
441 void pkgAcqMetaSig::Done(string Message
,unsigned long Size
,string MD5
,
442 pkgAcquire::MethodConfig
*Cfg
)
444 Item::Done(Message
,Size
,MD5
,Cfg
);
446 string FileName
= LookupTag(Message
,"Filename");
447 if (FileName
.empty() == true)
450 ErrorText
= "Method gave a blank filename";
454 if (FileName
!= DestFile
)
456 // We have to copy it into place
458 Desc
.URI
= "copy:" + FileName
;
465 // queue a pkgAcqMetaIndex to be verified against the sig we just retrieved
466 new pkgAcqMetaIndex(Owner
, MetaIndexURI
, MetaIndexURIDesc
, MetaIndexShortDesc
,
467 DestFile
, IndexTargets
, MetaIndexParser
);
471 void pkgAcqMetaSig::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
473 string Final
= _config
->FindDir("Dir::State::lists") + URItoFileName(RealURI
);
475 // if we get a network error we fail gracefully
476 if(Status
== StatTransientNetworkError
)
478 Item::Failed(Message
,Cnf
);
479 // move the sigfile back on network failures (and re-authenticated?)
480 if(FileExists(DestFile
))
481 Rename(DestFile
,Final
);
483 // set the status back to , Item::Failed likes to reset it
484 Status
= pkgAcquire::Item::StatTransientNetworkError
;
488 // Delete any existing sigfile when the acquire failed
489 unlink(Final
.c_str());
491 // queue a pkgAcqMetaIndex with no sigfile
492 new pkgAcqMetaIndex(Owner
, MetaIndexURI
, MetaIndexURIDesc
, MetaIndexShortDesc
,
493 "", IndexTargets
, MetaIndexParser
);
495 if (Cnf
->LocalOnly
== true ||
496 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == false)
505 Item::Failed(Message
,Cnf
);
508 pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire
*Owner
,
509 string URI
,string URIDesc
,string ShortDesc
,
511 const vector
<struct IndexTarget
*>* IndexTargets
,
512 indexRecords
* MetaIndexParser
) :
513 Item(Owner
), RealURI(URI
), SigFile(SigFile
), AuthPass(false),
514 MetaIndexParser(MetaIndexParser
), IndexTargets(IndexTargets
), IMSHit(false)
516 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
517 DestFile
+= URItoFileName(URI
);
520 Desc
.Description
= URIDesc
;
522 Desc
.ShortDesc
= ShortDesc
;
529 // pkgAcqMetaIndex::Custom600Headers - Insert custom request headers /*{{{*/
530 // ---------------------------------------------------------------------
531 /* The only header we use is the last-modified header. */
532 string
pkgAcqMetaIndex::Custom600Headers()
534 string Final
= _config
->FindDir("Dir::State::lists");
535 Final
+= URItoFileName(RealURI
);
538 if (stat(Final
.c_str(),&Buf
) != 0)
539 return "\nIndex-File: true";
541 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
544 void pkgAcqMetaIndex::Done(string Message
,unsigned long Size
,string MD5
,
545 pkgAcquire::MethodConfig
*Cfg
)
547 Item::Done(Message
,Size
,MD5
,Cfg
);
549 // MetaIndexes are done in two passes: one to download the
550 // metaindex with an appropriate method, and a second to verify it
551 // with the gpgv method
553 if (AuthPass
== true)
559 RetrievalDone(Message
);
561 // Still more retrieving to do
566 // There was no signature file, so we are finished. Download
567 // the indexes without verification.
572 // There was a signature file, so pass it to gpgv for
575 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
576 std::cerr
<< "Metaindex acquired, queueing gpg verification ("
577 << SigFile
<< "," << DestFile
<< ")\n";
579 Desc
.URI
= "gpgv:" + SigFile
;
586 void pkgAcqMetaIndex::RetrievalDone(string Message
)
588 // We have just finished downloading a Release file (it is not
591 string FileName
= LookupTag(Message
,"Filename");
592 if (FileName
.empty() == true)
595 ErrorText
= "Method gave a blank filename";
599 if (FileName
!= DestFile
)
602 Desc
.URI
= "copy:" + FileName
;
607 // see if the download was a IMSHit
608 IMSHit
= StringToBool(LookupTag(Message
,"IMS-Hit"),false);
612 string FinalFile
= _config
->FindDir("Dir::State::lists");
613 FinalFile
+= URItoFileName(RealURI
);
615 // The files timestamp matches
616 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == false)
618 // Move it into position
619 Rename(DestFile
,FinalFile
);
621 DestFile
= FinalFile
;
624 void pkgAcqMetaIndex::AuthDone(string Message
)
626 // At this point, the gpgv method has succeeded, so there is a
627 // valid signature from a key in the trusted keyring. We
628 // perform additional verification of its contents, and use them
629 // to verify the indexes we are about to download
631 if (!MetaIndexParser
->Load(DestFile
))
633 Status
= StatAuthError
;
634 ErrorText
= MetaIndexParser
->ErrorText
;
638 if (!VerifyVendor(Message
))
643 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
644 std::cerr
<< "Signature verification succeeded: "
645 << DestFile
<< std::endl
;
647 // Download further indexes with verification
650 // Done, move signature file into position
652 string VerifiedSigFile
= _config
->FindDir("Dir::State::lists") +
653 URItoFileName(RealURI
) + ".gpg";
654 Rename(SigFile
,VerifiedSigFile
);
655 chmod(VerifiedSigFile
.c_str(),0644);
658 void pkgAcqMetaIndex::QueueIndexes(bool verify
)
660 for (vector
<struct IndexTarget
*>::const_iterator Target
= IndexTargets
->begin();
661 Target
!= IndexTargets
->end();
664 string ExpectedIndexMD5
;
667 const indexRecords::checkSum
*Record
= MetaIndexParser
->Lookup((*Target
)->MetaKey
);
670 Status
= StatAuthError
;
671 ErrorText
= "Unable to find expected entry "
672 + (*Target
)->MetaKey
+ " in Meta-index file (malformed Release file?)";
675 ExpectedIndexMD5
= Record
->MD5Hash
;
676 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
678 std::cerr
<< "Queueing: " << (*Target
)->URI
<< std::endl
;
679 std::cerr
<< "Expected MD5: " << ExpectedIndexMD5
<< std::endl
;
681 if (ExpectedIndexMD5
.empty())
683 Status
= StatAuthError
;
684 ErrorText
= "Unable to find MD5 sum for "
685 + (*Target
)->MetaKey
+ " in Meta-index file";
690 // Queue Packages file
691 new pkgAcqIndex(Owner
, (*Target
)->URI
, (*Target
)->Description
,
692 (*Target
)->ShortDesc
, ExpectedIndexMD5
);
696 bool pkgAcqMetaIndex::VerifyVendor(string Message
)
698 // // Maybe this should be made available from above so we don't have
699 // // to read and parse it every time?
700 // pkgVendorList List;
701 // List.ReadMainList();
703 // const Vendor* Vndr = NULL;
704 // for (std::vector<string>::const_iterator I = GPGVOutput.begin(); I != GPGVOutput.end(); I++)
706 // string::size_type pos = (*I).find("VALIDSIG ");
707 // if (_config->FindB("Debug::Vendor", false))
708 // std::cerr << "Looking for VALIDSIG in \"" << (*I) << "\": pos " << pos
710 // if (pos != std::string::npos)
712 // string Fingerprint = (*I).substr(pos+sizeof("VALIDSIG"));
713 // if (_config->FindB("Debug::Vendor", false))
714 // std::cerr << "Looking for \"" << Fingerprint << "\" in vendor..." <<
716 // Vndr = List.FindVendor(Fingerprint) != "";
717 // if (Vndr != NULL);
721 string::size_type pos
;
723 // check for missing sigs (that where not fatal because otherwise we had
726 string msg
= _("There is no public key available for the "
727 "following key IDs:\n");
728 pos
= Message
.find("NO_PUBKEY ");
729 if (pos
!= std::string::npos
)
731 string::size_type start
= pos
+strlen("NO_PUBKEY ");
732 string Fingerprint
= Message
.substr(start
, Message
.find("\n")-start
);
733 missingkeys
+= (Fingerprint
);
735 if(!missingkeys
.empty())
736 _error
->Warning("%s", string(msg
+missingkeys
).c_str());
738 string Transformed
= MetaIndexParser
->GetExpectedDist();
740 if (Transformed
== "../project/experimental")
742 Transformed
= "experimental";
745 pos
= Transformed
.rfind('/');
746 if (pos
!= string::npos
)
748 Transformed
= Transformed
.substr(0, pos
);
751 if (Transformed
== ".")
756 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
758 std::cerr
<< "Got Codename: " << MetaIndexParser
->GetDist() << std::endl
;
759 std::cerr
<< "Expecting Dist: " << MetaIndexParser
->GetExpectedDist() << std::endl
;
760 std::cerr
<< "Transformed Dist: " << Transformed
<< std::endl
;
763 if (MetaIndexParser
->CheckDist(Transformed
) == false)
765 // This might become fatal one day
766 // Status = StatAuthError;
767 // ErrorText = "Conflicting distribution; expected "
768 // + MetaIndexParser->GetExpectedDist() + " but got "
769 // + MetaIndexParser->GetDist();
771 if (!Transformed
.empty())
773 _error
->Warning("Conflicting distribution: %s (expected %s but got %s)",
774 Desc
.Description
.c_str(),
776 MetaIndexParser
->GetDist().c_str());
783 // pkgAcqMetaIndex::Failed - no Release file present or no signature
784 // file present /*{{{*/
785 // ---------------------------------------------------------------------
787 void pkgAcqMetaIndex::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
789 if (AuthPass
== true)
791 // if we fail the authentication but got the file via a IMS-Hit
792 // this means that the file wasn't downloaded and that it might be
793 // just stale (server problem, proxy etc). we delete what we have
794 // queue it again without i-m-s
795 // alternatively we could just unlink the file and let the user try again
801 unlink(DestFile
.c_str());
803 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
804 DestFile
+= URItoFileName(RealURI
);
810 // gpgv method failed
811 ReportMirrorFailure("GPGFailure");
812 _error
->Warning("GPG error: %s: %s",
813 Desc
.Description
.c_str(),
814 LookupTag(Message
,"Message").c_str());
818 // No Release file was present, or verification failed, so fall
819 // back to queueing Packages files without verification
825 // AcqArchive::AcqArchive - Constructor /*{{{*/
826 // ---------------------------------------------------------------------
827 /* This just sets up the initial fetch environment and queues the first
829 pkgAcqArchive::pkgAcqArchive(pkgAcquire
*Owner
,pkgSourceList
*Sources
,
830 pkgRecords
*Recs
,pkgCache::VerIterator
const &Version
,
831 string
&StoreFilename
) :
832 Item(Owner
), Version(Version
), Sources(Sources
), Recs(Recs
),
833 StoreFilename(StoreFilename
), Vf(Version
.FileList()),
836 Retries
= _config
->FindI("Acquire::Retries",0);
838 if (Version
.Arch() == 0)
840 _error
->Error(_("I wasn't able to locate a file for the %s package. "
841 "This might mean you need to manually fix this package. "
842 "(due to missing arch)"),
843 Version
.ParentPkg().Name());
847 /* We need to find a filename to determine the extension. We make the
848 assumption here that all the available sources for this version share
849 the same extension.. */
850 // Skip not source sources, they do not have file fields.
851 for (; Vf
.end() == false; Vf
++)
853 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) != 0)
858 // Does not really matter here.. we are going to fail out below
859 if (Vf
.end() != true)
861 // If this fails to get a file name we will bomb out below.
862 pkgRecords::Parser
&Parse
= Recs
->Lookup(Vf
);
863 if (_error
->PendingError() == true)
866 // Generate the final file name as: package_version_arch.foo
867 StoreFilename
= QuoteString(Version
.ParentPkg().Name(),"_:") + '_' +
868 QuoteString(Version
.VerStr(),"_:") + '_' +
869 QuoteString(Version
.Arch(),"_:.") +
870 "." + flExtension(Parse
.FileName());
873 // check if we have one trusted source for the package. if so, switch
874 // to "TrustedOnly" mode
875 for (pkgCache::VerFileIterator i
= Version
.FileList(); i
.end() == false; i
++)
878 if (Sources
->FindIndex(i
.File(),Index
) == false)
880 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
882 std::cerr
<< "Checking index: " << Index
->Describe()
883 << "(Trusted=" << Index
->IsTrusted() << ")\n";
885 if (Index
->IsTrusted()) {
891 // "allow-unauthenticated" restores apts old fetching behaviour
892 // that means that e.g. unauthenticated file:// uris are higher
893 // priority than authenticated http:// uris
894 if (_config
->FindB("APT::Get::AllowUnauthenticated",false) == true)
898 if (QueueNext() == false && _error
->PendingError() == false)
899 _error
->Error(_("I wasn't able to locate file for the %s package. "
900 "This might mean you need to manually fix this package."),
901 Version
.ParentPkg().Name());
904 // AcqArchive::QueueNext - Queue the next file source /*{{{*/
905 // ---------------------------------------------------------------------
906 /* This queues the next available file version for download. It checks if
907 the archive is already available in the cache and stashs the MD5 for
909 bool pkgAcqArchive::QueueNext()
911 for (; Vf
.end() == false; Vf
++)
913 // Ignore not source sources
914 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) != 0)
917 // Try to cross match against the source list
919 if (Sources
->FindIndex(Vf
.File(),Index
) == false)
922 // only try to get a trusted package from another source if that source
924 if(Trusted
&& !Index
->IsTrusted())
927 // Grab the text package record
928 pkgRecords::Parser
&Parse
= Recs
->Lookup(Vf
);
929 if (_error
->PendingError() == true)
932 string PkgFile
= Parse
.FileName();
933 MD5
= Parse
.MD5Hash();
934 if (PkgFile
.empty() == true)
935 return _error
->Error(_("The package index files are corrupted. No Filename: "
936 "field for package %s."),
937 Version
.ParentPkg().Name());
939 Desc
.URI
= Index
->ArchiveURI(PkgFile
);
940 Desc
.Description
= Index
->ArchiveInfo(Version
);
942 Desc
.ShortDesc
= Version
.ParentPkg().Name();
944 // See if we already have the file. (Legacy filenames)
945 FileSize
= Version
->Size
;
946 string FinalFile
= _config
->FindDir("Dir::Cache::Archives") + flNotDir(PkgFile
);
948 if (stat(FinalFile
.c_str(),&Buf
) == 0)
950 // Make sure the size matches
951 if ((unsigned)Buf
.st_size
== Version
->Size
)
956 StoreFilename
= DestFile
= FinalFile
;
960 /* Hmm, we have a file and its size does not match, this means it is
961 an old style mismatched arch */
962 unlink(FinalFile
.c_str());
965 // Check it again using the new style output filenames
966 FinalFile
= _config
->FindDir("Dir::Cache::Archives") + flNotDir(StoreFilename
);
967 if (stat(FinalFile
.c_str(),&Buf
) == 0)
969 // Make sure the size matches
970 if ((unsigned)Buf
.st_size
== Version
->Size
)
975 StoreFilename
= DestFile
= FinalFile
;
979 /* Hmm, we have a file and its size does not match, this shouldnt
981 unlink(FinalFile
.c_str());
984 DestFile
= _config
->FindDir("Dir::Cache::Archives") + "partial/" + flNotDir(StoreFilename
);
986 // Check the destination file
987 if (stat(DestFile
.c_str(),&Buf
) == 0)
989 // Hmm, the partial file is too big, erase it
990 if ((unsigned)Buf
.st_size
> Version
->Size
)
991 unlink(DestFile
.c_str());
993 PartialSize
= Buf
.st_size
;
998 Desc
.URI
= Index
->ArchiveURI(PkgFile
);
999 Desc
.Description
= Index
->ArchiveInfo(Version
);
1001 Desc
.ShortDesc
= Version
.ParentPkg().Name();
1010 // AcqArchive::Done - Finished fetching /*{{{*/
1011 // ---------------------------------------------------------------------
1013 void pkgAcqArchive::Done(string Message
,unsigned long Size
,string Md5Hash
,
1014 pkgAcquire::MethodConfig
*Cfg
)
1016 Item::Done(Message
,Size
,Md5Hash
,Cfg
);
1019 if (Size
!= Version
->Size
)
1022 ErrorText
= _("Size mismatch");
1027 if (Md5Hash
.empty() == false && MD5
.empty() == false)
1032 ErrorText
= _("MD5Sum mismatch");
1033 if(FileExists(DestFile
))
1034 Rename(DestFile
,DestFile
+ ".FAILED");
1039 // Grab the output filename
1040 string FileName
= LookupTag(Message
,"Filename");
1041 if (FileName
.empty() == true)
1044 ErrorText
= "Method gave a blank filename";
1050 // Reference filename
1051 if (FileName
!= DestFile
)
1053 StoreFilename
= DestFile
= FileName
;
1058 // Done, move it into position
1059 string FinalFile
= _config
->FindDir("Dir::Cache::Archives");
1060 FinalFile
+= flNotDir(StoreFilename
);
1061 Rename(DestFile
,FinalFile
);
1063 StoreFilename
= DestFile
= FinalFile
;
1067 // AcqArchive::Failed - Failure handler /*{{{*/
1068 // ---------------------------------------------------------------------
1069 /* Here we try other sources */
1070 void pkgAcqArchive::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
1072 ErrorText
= LookupTag(Message
,"Message");
1074 /* We don't really want to retry on failed media swaps, this prevents
1075 that. An interesting observation is that permanent failures are not
1077 if (Cnf
->Removable
== true &&
1078 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
1080 // Vf = Version.FileList();
1081 while (Vf
.end() == false) Vf
++;
1082 StoreFilename
= string();
1083 Item::Failed(Message
,Cnf
);
1087 if (QueueNext() == false)
1089 // This is the retry counter
1091 Cnf
->LocalOnly
== false &&
1092 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
1095 Vf
= Version
.FileList();
1096 if (QueueNext() == true)
1100 StoreFilename
= string();
1101 Item::Failed(Message
,Cnf
);
1105 // AcqArchive::IsTrusted - Determine whether this archive comes from a
1106 // trusted source /*{{{*/
1107 // ---------------------------------------------------------------------
1108 bool pkgAcqArchive::IsTrusted()
1113 // AcqArchive::Finished - Fetching has finished, tidy up /*{{{*/
1114 // ---------------------------------------------------------------------
1116 void pkgAcqArchive::Finished()
1118 if (Status
== pkgAcquire::Item::StatDone
&&
1121 StoreFilename
= string();
1125 // AcqFile::pkgAcqFile - Constructor /*{{{*/
1126 // ---------------------------------------------------------------------
1127 /* The file is added to the queue */
1128 pkgAcqFile::pkgAcqFile(pkgAcquire
*Owner
,string URI
,string MD5
,
1129 unsigned long Size
,string Dsc
,string ShortDesc
,
1130 const string
&DestDir
, const string
&DestFilename
) :
1131 Item(Owner
), Md5Hash(MD5
)
1133 Retries
= _config
->FindI("Acquire::Retries",0);
1135 if(!DestFilename
.empty())
1136 DestFile
= DestFilename
;
1137 else if(!DestDir
.empty())
1138 DestFile
= DestDir
+ "/" + flNotDir(URI
);
1140 DestFile
= flNotDir(URI
);
1144 Desc
.Description
= Dsc
;
1147 // Set the short description to the archive component
1148 Desc
.ShortDesc
= ShortDesc
;
1150 // Get the transfer sizes
1153 if (stat(DestFile
.c_str(),&Buf
) == 0)
1155 // Hmm, the partial file is too big, erase it
1156 if ((unsigned)Buf
.st_size
> Size
)
1157 unlink(DestFile
.c_str());
1159 PartialSize
= Buf
.st_size
;
1165 // AcqFile::Done - Item downloaded OK /*{{{*/
1166 // ---------------------------------------------------------------------
1168 void pkgAcqFile::Done(string Message
,unsigned long Size
,string MD5
,
1169 pkgAcquire::MethodConfig
*Cnf
)
1172 if (Md5Hash
.empty() == false && MD5
.empty() == false)
1177 ErrorText
= "MD5Sum mismatch";
1178 Rename(DestFile
,DestFile
+ ".FAILED");
1183 Item::Done(Message
,Size
,MD5
,Cnf
);
1185 string FileName
= LookupTag(Message
,"Filename");
1186 if (FileName
.empty() == true)
1189 ErrorText
= "Method gave a blank filename";
1195 // The files timestamp matches
1196 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true)
1199 // We have to copy it into place
1200 if (FileName
!= DestFile
)
1203 if (_config
->FindB("Acquire::Source-Symlinks",true) == false ||
1204 Cnf
->Removable
== true)
1206 Desc
.URI
= "copy:" + FileName
;
1211 // Erase the file if it is a symlink so we can overwrite it
1213 if (lstat(DestFile
.c_str(),&St
) == 0)
1215 if (S_ISLNK(St
.st_mode
) != 0)
1216 unlink(DestFile
.c_str());
1220 if (symlink(FileName
.c_str(),DestFile
.c_str()) != 0)
1222 ErrorText
= "Link to " + DestFile
+ " failure ";
1229 // AcqFile::Failed - Failure handler /*{{{*/
1230 // ---------------------------------------------------------------------
1231 /* Here we try other sources */
1232 void pkgAcqFile::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
1234 ErrorText
= LookupTag(Message
,"Message");
1236 // This is the retry counter
1238 Cnf
->LocalOnly
== false &&
1239 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
1246 Item::Failed(Message
,Cnf
);