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";
179 if(ExpectedMD5
!= "")
180 return "\nExpectedMD5: " + ExpectedMD5
;
181 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
185 void pkgAcqIndex::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
187 // no .bz2 found, retry with .gz
188 if(Desc
.URI
.substr(Desc
.URI
.size()-3) == "bz2") {
189 Desc
.URI
= Desc
.URI
.substr(0,Desc
.URI
.size()-3) + "gz";
191 // retry with a gzip one
192 new pkgAcqIndex(Owner
, RealURI
, Desc
.Description
,Desc
.ShortDesc
,
193 ExpectedMD5
, string(".gz"));
201 Item::Failed(Message
,Cnf
);
205 // AcqIndex::Done - Finished a fetch /*{{{*/
206 // ---------------------------------------------------------------------
207 /* This goes through a number of states.. On the initial fetch the
208 method could possibly return an alternate filename which points
209 to the uncompressed version of the file. If this is so the file
210 is copied into the partial directory. In all other cases the file
211 is decompressed with a gzip uri. */
212 void pkgAcqIndex::Done(string Message
,unsigned long Size
,string MD5
,
213 pkgAcquire::MethodConfig
*Cfg
)
215 Item::Done(Message
,Size
,MD5
,Cfg
);
217 if (Decompression
== true)
219 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
221 std::cerr
<< std::endl
<< RealURI
<< ": Computed MD5: " << MD5
;
222 std::cerr
<< " Expected MD5: " << ExpectedMD5
<< std::endl
;
228 FileFd
Fd(DestFile
, FileFd::ReadOnly
);
229 sum
.AddFD(Fd
.Fd(), Fd
.Size());
231 MD5
= (string
)sum
.Result();
234 if (!ExpectedMD5
.empty() && MD5
!= ExpectedMD5
)
236 Status
= StatAuthError
;
237 ErrorText
= _("MD5Sum mismatch");
238 Rename(DestFile
,DestFile
+ ".FAILED");
241 // Done, move it into position
242 string FinalFile
= _config
->FindDir("Dir::State::lists");
243 FinalFile
+= URItoFileName(RealURI
);
244 Rename(DestFile
,FinalFile
);
245 chmod(FinalFile
.c_str(),0644);
247 /* We restore the original name to DestFile so that the clean operation
249 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
250 DestFile
+= URItoFileName(RealURI
);
252 // Remove the compressed version.
254 unlink(DestFile
.c_str());
261 // Handle the unzipd case
262 string FileName
= LookupTag(Message
,"Alt-Filename");
263 if (FileName
.empty() == false)
265 // The files timestamp matches
266 if (StringToBool(LookupTag(Message
,"Alt-IMS-Hit"),false) == true)
269 Decompression
= true;
271 DestFile
+= ".decomp";
272 Desc
.URI
= "copy:" + FileName
;
278 FileName
= LookupTag(Message
,"Filename");
279 if (FileName
.empty() == true)
282 ErrorText
= "Method gave a blank filename";
285 // The files timestamp matches
286 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true)
289 if (FileName
== DestFile
)
294 string compExt
= Desc
.URI
.substr(Desc
.URI
.size()-3);
297 decompProg
= "bzip2";
298 else if(compExt
== ".gz")
301 _error
->Error("Unsupported extension: %s", compExt
.c_str());
305 Decompression
= true;
306 DestFile
+= ".decomp";
307 Desc
.URI
= string(decompProg
) + ":" + FileName
;
312 pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire
*Owner
,
313 string URI
,string URIDesc
,string ShortDesc
,
314 string MetaIndexURI
, string MetaIndexURIDesc
,
315 string MetaIndexShortDesc
,
316 const vector
<IndexTarget
*>* IndexTargets
,
317 indexRecords
* MetaIndexParser
) :
318 Item(Owner
), RealURI(URI
), MetaIndexURI(MetaIndexURI
),
319 MetaIndexURIDesc(MetaIndexURIDesc
), MetaIndexShortDesc(MetaIndexShortDesc
),
320 MetaIndexParser(MetaIndexParser
), IndexTargets(IndexTargets
)
322 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
323 DestFile
+= URItoFileName(URI
);
325 // remove any partial downloaded sig-file. it may confuse proxies
326 // and is too small to warrant a partial download anyway
327 unlink(DestFile
.c_str());
330 Desc
.Description
= URIDesc
;
332 Desc
.ShortDesc
= ShortDesc
;
336 string Final
= _config
->FindDir("Dir::State::lists");
337 Final
+= URItoFileName(RealURI
);
339 if (stat(Final
.c_str(),&Buf
) == 0)
341 // File was already in place. It needs to be re-verified
342 // because Release might have changed, so Move it into partial
343 Rename(Final
,DestFile
);
349 // pkgAcqMetaSig::Custom600Headers - Insert custom request headers /*{{{*/
350 // ---------------------------------------------------------------------
351 /* The only header we use is the last-modified header. */
352 string
pkgAcqMetaSig::Custom600Headers()
355 if (stat(DestFile
.c_str(),&Buf
) != 0)
356 return "\nIndex-File: true";
358 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
361 void pkgAcqMetaSig::Done(string Message
,unsigned long Size
,string MD5
,
362 pkgAcquire::MethodConfig
*Cfg
)
364 Item::Done(Message
,Size
,MD5
,Cfg
);
366 string FileName
= LookupTag(Message
,"Filename");
367 if (FileName
.empty() == true)
370 ErrorText
= "Method gave a blank filename";
374 if (FileName
!= DestFile
)
376 // We have to copy it into place
378 Desc
.URI
= "copy:" + FileName
;
385 // queue a pkgAcqMetaIndex to be verified against the sig we just retrieved
386 new pkgAcqMetaIndex(Owner
, MetaIndexURI
, MetaIndexURIDesc
, MetaIndexShortDesc
,
387 DestFile
, IndexTargets
, MetaIndexParser
);
391 void pkgAcqMetaSig::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
394 // if we get a network error we fail gracefully
395 if(LookupTag(Message
,"FailReason") == "Timeout" ||
396 LookupTag(Message
,"FailReason") == "TmpResolveFailure" ||
397 LookupTag(Message
,"FailReason") == "ConnectionRefused") {
398 Item::Failed(Message
,Cnf
);
402 // Delete any existing sigfile when the acquire failed
403 string Final
= _config
->FindDir("Dir::State::lists") + URItoFileName(RealURI
);
404 unlink(Final
.c_str());
406 // queue a pkgAcqMetaIndex with no sigfile
407 new pkgAcqMetaIndex(Owner
, MetaIndexURI
, MetaIndexURIDesc
, MetaIndexShortDesc
,
408 "", IndexTargets
, MetaIndexParser
);
410 if (Cnf
->LocalOnly
== true ||
411 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == false)
420 Item::Failed(Message
,Cnf
);
423 pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire
*Owner
,
424 string URI
,string URIDesc
,string ShortDesc
,
426 const vector
<struct IndexTarget
*>* IndexTargets
,
427 indexRecords
* MetaIndexParser
) :
428 Item(Owner
), RealURI(URI
), SigFile(SigFile
), AuthPass(false),
429 MetaIndexParser(MetaIndexParser
), IndexTargets(IndexTargets
), IMSHit(false)
431 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
432 DestFile
+= URItoFileName(URI
);
435 Desc
.Description
= URIDesc
;
437 Desc
.ShortDesc
= ShortDesc
;
444 // pkgAcqMetaIndex::Custom600Headers - Insert custom request headers /*{{{*/
445 // ---------------------------------------------------------------------
446 /* The only header we use is the last-modified header. */
447 string
pkgAcqMetaIndex::Custom600Headers()
449 string Final
= _config
->FindDir("Dir::State::lists");
450 Final
+= URItoFileName(RealURI
);
453 if (stat(Final
.c_str(),&Buf
) != 0)
454 return "\nIndex-File: true";
456 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
459 void pkgAcqMetaIndex::Done(string Message
,unsigned long Size
,string MD5
,
460 pkgAcquire::MethodConfig
*Cfg
)
462 Item::Done(Message
,Size
,MD5
,Cfg
);
464 // MetaIndexes are done in two passes: one to download the
465 // metaindex with an appropriate method, and a second to verify it
466 // with the gpgv method
468 if (AuthPass
== true)
474 RetrievalDone(Message
);
476 // Still more retrieving to do
481 // There was no signature file, so we are finished. Download
482 // the indexes without verification.
487 // There was a signature file, so pass it to gpgv for
490 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
491 std::cerr
<< "Metaindex acquired, queueing gpg verification ("
492 << SigFile
<< "," << DestFile
<< ")\n";
494 Desc
.URI
= "gpgv:" + SigFile
;
501 void pkgAcqMetaIndex::RetrievalDone(string Message
)
503 // We have just finished downloading a Release file (it is not
506 string FileName
= LookupTag(Message
,"Filename");
507 if (FileName
.empty() == true)
510 ErrorText
= "Method gave a blank filename";
514 if (FileName
!= DestFile
)
517 Desc
.URI
= "copy:" + FileName
;
522 // see if the download was a IMSHit
523 IMSHit
= StringToBool(LookupTag(Message
,"IMS-Hit"),false);
527 string FinalFile
= _config
->FindDir("Dir::State::lists");
528 FinalFile
+= URItoFileName(RealURI
);
530 // The files timestamp matches
531 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == false)
533 // Move it into position
534 Rename(DestFile
,FinalFile
);
536 DestFile
= FinalFile
;
539 void pkgAcqMetaIndex::AuthDone(string Message
)
541 // At this point, the gpgv method has succeeded, so there is a
542 // valid signature from a key in the trusted keyring. We
543 // perform additional verification of its contents, and use them
544 // to verify the indexes we are about to download
546 if (!MetaIndexParser
->Load(DestFile
))
548 Status
= StatAuthError
;
549 ErrorText
= MetaIndexParser
->ErrorText
;
553 if (!VerifyVendor(Message
))
558 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
559 std::cerr
<< "Signature verification succeeded: "
560 << DestFile
<< std::endl
;
562 // Download further indexes with verification
565 // Done, move signature file into position
567 string VerifiedSigFile
= _config
->FindDir("Dir::State::lists") +
568 URItoFileName(RealURI
) + ".gpg";
569 Rename(SigFile
,VerifiedSigFile
);
570 chmod(VerifiedSigFile
.c_str(),0644);
573 void pkgAcqMetaIndex::QueueIndexes(bool verify
)
575 for (vector
<struct IndexTarget
*>::const_iterator Target
= IndexTargets
->begin();
576 Target
!= IndexTargets
->end();
579 string ExpectedIndexMD5
;
582 const indexRecords::checkSum
*Record
= MetaIndexParser
->Lookup((*Target
)->MetaKey
);
585 Status
= StatAuthError
;
586 ErrorText
= "Unable to find expected entry "
587 + (*Target
)->MetaKey
+ " in Meta-index file (malformed Release file?)";
590 ExpectedIndexMD5
= Record
->MD5Hash
;
591 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
593 std::cerr
<< "Queueing: " << (*Target
)->URI
<< std::endl
;
594 std::cerr
<< "Expected MD5: " << ExpectedIndexMD5
<< std::endl
;
596 if (ExpectedIndexMD5
.empty())
598 Status
= StatAuthError
;
599 ErrorText
= "Unable to find MD5 sum for "
600 + (*Target
)->MetaKey
+ " in Meta-index file";
605 // Queue Packages file
606 new pkgAcqIndex(Owner
, (*Target
)->URI
, (*Target
)->Description
,
607 (*Target
)->ShortDesc
, ExpectedIndexMD5
);
611 bool pkgAcqMetaIndex::VerifyVendor(string Message
)
613 // // Maybe this should be made available from above so we don't have
614 // // to read and parse it every time?
615 // pkgVendorList List;
616 // List.ReadMainList();
618 // const Vendor* Vndr = NULL;
619 // for (std::vector<string>::const_iterator I = GPGVOutput.begin(); I != GPGVOutput.end(); I++)
621 // string::size_type pos = (*I).find("VALIDSIG ");
622 // if (_config->FindB("Debug::Vendor", false))
623 // std::cerr << "Looking for VALIDSIG in \"" << (*I) << "\": pos " << pos
625 // if (pos != std::string::npos)
627 // string Fingerprint = (*I).substr(pos+sizeof("VALIDSIG"));
628 // if (_config->FindB("Debug::Vendor", false))
629 // std::cerr << "Looking for \"" << Fingerprint << "\" in vendor..." <<
631 // Vndr = List.FindVendor(Fingerprint) != "";
632 // if (Vndr != NULL);
636 string::size_type pos
;
638 // check for missing sigs (that where not fatal because otherwise we had
641 string msg
= _("There is no public key available for the "
642 "following key IDs:\n");
643 pos
= Message
.find("NO_PUBKEY ");
644 if (pos
!= std::string::npos
)
646 string::size_type start
= pos
+strlen("NO_PUBKEY ");
647 string Fingerprint
= Message
.substr(start
, Message
.find("\n")-start
);
648 missingkeys
+= (Fingerprint
);
650 if(!missingkeys
.empty())
651 _error
->Warning("%s", string(msg
+missingkeys
).c_str());
653 string Transformed
= MetaIndexParser
->GetExpectedDist();
655 if (Transformed
== "../project/experimental")
657 Transformed
= "experimental";
660 pos
= Transformed
.rfind('/');
661 if (pos
!= string::npos
)
663 Transformed
= Transformed
.substr(0, pos
);
666 if (Transformed
== ".")
671 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
673 std::cerr
<< "Got Codename: " << MetaIndexParser
->GetDist() << std::endl
;
674 std::cerr
<< "Expecting Dist: " << MetaIndexParser
->GetExpectedDist() << std::endl
;
675 std::cerr
<< "Transformed Dist: " << Transformed
<< std::endl
;
678 if (MetaIndexParser
->CheckDist(Transformed
) == false)
680 // This might become fatal one day
681 // Status = StatAuthError;
682 // ErrorText = "Conflicting distribution; expected "
683 // + MetaIndexParser->GetExpectedDist() + " but got "
684 // + MetaIndexParser->GetDist();
686 if (!Transformed
.empty())
688 _error
->Warning("Conflicting distribution: %s (expected %s but got %s)",
689 Desc
.Description
.c_str(),
691 MetaIndexParser
->GetDist().c_str());
698 // pkgAcqMetaIndex::Failed - no Release file present or no signature
699 // file present /*{{{*/
700 // ---------------------------------------------------------------------
702 void pkgAcqMetaIndex::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
704 if (AuthPass
== true)
706 // if we fail the authentication but got the file via a IMS-Hit
707 // this means that the file wasn't downloaded and that it might be
708 // just stale (server problem, proxy etc). we delete what we have
709 // queue it again without i-m-s
710 // alternatively we could just unlink the file and let the user try again
716 unlink(DestFile
.c_str());
718 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
719 DestFile
+= URItoFileName(RealURI
);
725 // gpgv method failed
726 _error
->Warning("GPG error: %s: %s",
727 Desc
.Description
.c_str(),
728 LookupTag(Message
,"Message").c_str());
732 // No Release file was present, or verification failed, so fall
733 // back to queueing Packages files without verification
739 // AcqArchive::AcqArchive - Constructor /*{{{*/
740 // ---------------------------------------------------------------------
741 /* This just sets up the initial fetch environment and queues the first
743 pkgAcqArchive::pkgAcqArchive(pkgAcquire
*Owner
,pkgSourceList
*Sources
,
744 pkgRecords
*Recs
,pkgCache::VerIterator
const &Version
,
745 string
&StoreFilename
) :
746 Item(Owner
), Version(Version
), Sources(Sources
), Recs(Recs
),
747 StoreFilename(StoreFilename
), Vf(Version
.FileList()),
750 Retries
= _config
->FindI("Acquire::Retries",0);
752 if (Version
.Arch() == 0)
754 _error
->Error(_("I wasn't able to locate a file for the %s package. "
755 "This might mean you need to manually fix this package. "
756 "(due to missing arch)"),
757 Version
.ParentPkg().Name());
761 /* We need to find a filename to determine the extension. We make the
762 assumption here that all the available sources for this version share
763 the same extension.. */
764 // Skip not source sources, they do not have file fields.
765 for (; Vf
.end() == false; Vf
++)
767 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) != 0)
772 // Does not really matter here.. we are going to fail out below
773 if (Vf
.end() != true)
775 // If this fails to get a file name we will bomb out below.
776 pkgRecords::Parser
&Parse
= Recs
->Lookup(Vf
);
777 if (_error
->PendingError() == true)
780 // Generate the final file name as: package_version_arch.foo
781 StoreFilename
= QuoteString(Version
.ParentPkg().Name(),"_:") + '_' +
782 QuoteString(Version
.VerStr(),"_:") + '_' +
783 QuoteString(Version
.Arch(),"_:.") +
784 "." + flExtension(Parse
.FileName());
787 // check if we have one trusted source for the package. if so, switch
788 // to "TrustedOnly" mode
789 for (pkgCache::VerFileIterator i
= Version
.FileList(); i
.end() == false; i
++)
792 if (Sources
->FindIndex(i
.File(),Index
) == false)
794 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
796 std::cerr
<< "Checking index: " << Index
->Describe()
797 << "(Trusted=" << Index
->IsTrusted() << ")\n";
799 if (Index
->IsTrusted()) {
805 // "allow-unauthenticated" restores apts old fetching behaviour
806 // that means that e.g. unauthenticated file:// uris are higher
807 // priority than authenticated http:// uris
808 if (_config
->FindB("APT::Get::AllowUnauthenticated",false) == true)
812 if (QueueNext() == false && _error
->PendingError() == false)
813 _error
->Error(_("I wasn't able to locate file for the %s package. "
814 "This might mean you need to manually fix this package."),
815 Version
.ParentPkg().Name());
818 // AcqArchive::QueueNext - Queue the next file source /*{{{*/
819 // ---------------------------------------------------------------------
820 /* This queues the next available file version for download. It checks if
821 the archive is already available in the cache and stashs the MD5 for
823 bool pkgAcqArchive::QueueNext()
825 for (; Vf
.end() == false; Vf
++)
827 // Ignore not source sources
828 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) != 0)
831 // Try to cross match against the source list
833 if (Sources
->FindIndex(Vf
.File(),Index
) == false)
836 // only try to get a trusted package from another source if that source
838 if(Trusted
&& !Index
->IsTrusted())
841 // Grab the text package record
842 pkgRecords::Parser
&Parse
= Recs
->Lookup(Vf
);
843 if (_error
->PendingError() == true)
846 string PkgFile
= Parse
.FileName();
847 MD5
= Parse
.MD5Hash();
848 if (PkgFile
.empty() == true)
849 return _error
->Error(_("The package index files are corrupted. No Filename: "
850 "field for package %s."),
851 Version
.ParentPkg().Name());
853 Desc
.URI
= Index
->ArchiveURI(PkgFile
);
854 Desc
.Description
= Index
->ArchiveInfo(Version
);
856 Desc
.ShortDesc
= Version
.ParentPkg().Name();
858 // See if we already have the file. (Legacy filenames)
859 FileSize
= Version
->Size
;
860 string FinalFile
= _config
->FindDir("Dir::Cache::Archives") + flNotDir(PkgFile
);
862 if (stat(FinalFile
.c_str(),&Buf
) == 0)
864 // Make sure the size matches
865 if ((unsigned)Buf
.st_size
== Version
->Size
)
870 StoreFilename
= DestFile
= FinalFile
;
874 /* Hmm, we have a file and its size does not match, this means it is
875 an old style mismatched arch */
876 unlink(FinalFile
.c_str());
879 // Check it again using the new style output filenames
880 FinalFile
= _config
->FindDir("Dir::Cache::Archives") + flNotDir(StoreFilename
);
881 if (stat(FinalFile
.c_str(),&Buf
) == 0)
883 // Make sure the size matches
884 if ((unsigned)Buf
.st_size
== Version
->Size
)
889 StoreFilename
= DestFile
= FinalFile
;
893 /* Hmm, we have a file and its size does not match, this shouldnt
895 unlink(FinalFile
.c_str());
898 DestFile
= _config
->FindDir("Dir::Cache::Archives") + "partial/" + flNotDir(StoreFilename
);
900 // Check the destination file
901 if (stat(DestFile
.c_str(),&Buf
) == 0)
903 // Hmm, the partial file is too big, erase it
904 if ((unsigned)Buf
.st_size
> Version
->Size
)
905 unlink(DestFile
.c_str());
907 PartialSize
= Buf
.st_size
;
912 Desc
.URI
= Index
->ArchiveURI(PkgFile
);
913 Desc
.Description
= Index
->ArchiveInfo(Version
);
915 Desc
.ShortDesc
= Version
.ParentPkg().Name();
924 // AcqArchive::Done - Finished fetching /*{{{*/
925 // ---------------------------------------------------------------------
927 void pkgAcqArchive::Done(string Message
,unsigned long Size
,string Md5Hash
,
928 pkgAcquire::MethodConfig
*Cfg
)
930 Item::Done(Message
,Size
,Md5Hash
,Cfg
);
933 if (Size
!= Version
->Size
)
936 ErrorText
= _("Size mismatch");
941 if (Md5Hash
.empty() == false && MD5
.empty() == false)
946 ErrorText
= _("MD5Sum mismatch");
947 if(FileExists(DestFile
))
948 Rename(DestFile
,DestFile
+ ".FAILED");
953 // Grab the output filename
954 string FileName
= LookupTag(Message
,"Filename");
955 if (FileName
.empty() == true)
958 ErrorText
= "Method gave a blank filename";
964 // Reference filename
965 if (FileName
!= DestFile
)
967 StoreFilename
= DestFile
= FileName
;
972 // Done, move it into position
973 string FinalFile
= _config
->FindDir("Dir::Cache::Archives");
974 FinalFile
+= flNotDir(StoreFilename
);
975 Rename(DestFile
,FinalFile
);
977 StoreFilename
= DestFile
= FinalFile
;
981 // AcqArchive::Failed - Failure handler /*{{{*/
982 // ---------------------------------------------------------------------
983 /* Here we try other sources */
984 void pkgAcqArchive::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
986 ErrorText
= LookupTag(Message
,"Message");
988 /* We don't really want to retry on failed media swaps, this prevents
989 that. An interesting observation is that permanent failures are not
991 if (Cnf
->Removable
== true &&
992 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
994 // Vf = Version.FileList();
995 while (Vf
.end() == false) Vf
++;
996 StoreFilename
= string();
997 Item::Failed(Message
,Cnf
);
1001 if (QueueNext() == false)
1003 // This is the retry counter
1005 Cnf
->LocalOnly
== false &&
1006 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
1009 Vf
= Version
.FileList();
1010 if (QueueNext() == true)
1014 StoreFilename
= string();
1015 Item::Failed(Message
,Cnf
);
1019 // ---------------------------------------------------------------------
1020 string
pkgAcqArchive::Custom600Headers()
1023 return "\nExpectedMD5: " + MD5
;
1026 // AcqArchive::IsTrusted - Determine whether this archive comes from a
1027 // trusted source /*{{{*/
1028 // ---------------------------------------------------------------------
1029 bool pkgAcqArchive::IsTrusted()
1034 // AcqArchive::Finished - Fetching has finished, tidy up /*{{{*/
1035 // ---------------------------------------------------------------------
1037 void pkgAcqArchive::Finished()
1039 if (Status
== pkgAcquire::Item::StatDone
&&
1042 StoreFilename
= string();
1046 // AcqFile::pkgAcqFile - Constructor /*{{{*/
1047 // ---------------------------------------------------------------------
1048 /* The file is added to the queue */
1049 pkgAcqFile::pkgAcqFile(pkgAcquire
*Owner
,string URI
,string MD5
,
1050 unsigned long Size
,string Dsc
,string ShortDesc
,
1051 const string
&DestDir
, const string
&DestFilename
) :
1052 Item(Owner
), Md5Hash(MD5
)
1054 Retries
= _config
->FindI("Acquire::Retries",0);
1056 if(!DestFilename
.empty())
1057 DestFile
= DestFilename
;
1058 else if(!DestDir
.empty())
1059 DestFile
= DestDir
+ "/" + flNotDir(URI
);
1061 DestFile
= flNotDir(URI
);
1065 Desc
.Description
= Dsc
;
1068 // Set the short description to the archive component
1069 Desc
.ShortDesc
= ShortDesc
;
1071 // Get the transfer sizes
1074 if (stat(DestFile
.c_str(),&Buf
) == 0)
1076 // Hmm, the partial file is too big, erase it
1077 if ((unsigned)Buf
.st_size
> Size
)
1078 unlink(DestFile
.c_str());
1080 PartialSize
= Buf
.st_size
;
1086 // AcqFile::Done - Item downloaded OK /*{{{*/
1087 // ---------------------------------------------------------------------
1089 void pkgAcqFile::Done(string Message
,unsigned long Size
,string MD5
,
1090 pkgAcquire::MethodConfig
*Cnf
)
1093 if (Md5Hash
.empty() == false && MD5
.empty() == false)
1098 ErrorText
= "MD5Sum mismatch";
1099 Rename(DestFile
,DestFile
+ ".FAILED");
1104 Item::Done(Message
,Size
,MD5
,Cnf
);
1106 string FileName
= LookupTag(Message
,"Filename");
1107 if (FileName
.empty() == true)
1110 ErrorText
= "Method gave a blank filename";
1116 // The files timestamp matches
1117 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true)
1120 // We have to copy it into place
1121 if (FileName
!= DestFile
)
1124 if (_config
->FindB("Acquire::Source-Symlinks",true) == false ||
1125 Cnf
->Removable
== true)
1127 Desc
.URI
= "copy:" + FileName
;
1132 // Erase the file if it is a symlink so we can overwrite it
1134 if (lstat(DestFile
.c_str(),&St
) == 0)
1136 if (S_ISLNK(St
.st_mode
) != 0)
1137 unlink(DestFile
.c_str());
1141 if (symlink(FileName
.c_str(),DestFile
.c_str()) != 0)
1143 ErrorText
= "Link to " + DestFile
+ " failure ";
1150 // AcqFile::Failed - Failure handler /*{{{*/
1151 // ---------------------------------------------------------------------
1152 /* Here we try other sources */
1153 void pkgAcqFile::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
1155 ErrorText
= LookupTag(Message
,"Message");
1157 // This is the retry counter
1159 Cnf
->LocalOnly
== false &&
1160 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
1167 Item::Failed(Message
,Cnf
);