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
) :
141 Item(Owner
), RealURI(URI
), ExpectedMD5(ExpectedMD5
)
143 Decompression
= false;
146 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
147 DestFile
+= URItoFileName(URI
);
150 if(FileExists("/usr/bin/bzip2"))
151 Desc
.URI
= URI
+ ".bz2";
153 Desc
.URI
= URI
+ ".gz";
154 Desc
.Description
= URIDesc
;
156 Desc
.ShortDesc
= ShortDesc
;
161 // AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
162 // ---------------------------------------------------------------------
163 /* The only header we use is the last-modified header. */
164 string
pkgAcqIndex::Custom600Headers()
166 string Final
= _config
->FindDir("Dir::State::lists");
167 Final
+= URItoFileName(RealURI
);
170 if (stat(Final
.c_str(),&Buf
) != 0)
171 return "\nIndex-File: true";
173 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
177 void pkgAcqIndex::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
179 // no .bz2 found, retry with .gz
180 if(Desc
.URI
.substr(Desc
.URI
.size()-3,Desc
.URI
.size()-1) == "bz2") {
181 Desc
.URI
= Desc
.URI
.substr(0,Desc
.URI
.size()-3) + "gz";
187 Item::Failed(Message
,Cnf
);
191 // AcqIndex::Done - Finished a fetch /*{{{*/
192 // ---------------------------------------------------------------------
193 /* This goes through a number of states.. On the initial fetch the
194 method could possibly return an alternate filename which points
195 to the uncompressed version of the file. If this is so the file
196 is copied into the partial directory. In all other cases the file
197 is decompressed with a gzip uri. */
198 void pkgAcqIndex::Done(string Message
,unsigned long Size
,string MD5
,
199 pkgAcquire::MethodConfig
*Cfg
)
201 Item::Done(Message
,Size
,MD5
,Cfg
);
203 if (Decompression
== true)
205 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
207 std::cerr
<< std::endl
<< RealURI
<< ": Computed MD5: " << MD5
;
208 std::cerr
<< " Expected MD5: " << ExpectedMD5
<< std::endl
;
214 FileFd
Fd(DestFile
, FileFd::ReadOnly
);
215 sum
.AddFD(Fd
.Fd(), Fd
.Size());
217 MD5
= (string
)sum
.Result();
220 if (!ExpectedMD5
.empty() && MD5
!= ExpectedMD5
)
222 Status
= StatAuthError
;
223 ErrorText
= _("MD5Sum mismatch");
224 Rename(DestFile
,DestFile
+ ".FAILED");
227 // Done, move it into position
228 string FinalFile
= _config
->FindDir("Dir::State::lists");
229 FinalFile
+= URItoFileName(RealURI
);
230 Rename(DestFile
,FinalFile
);
231 chmod(FinalFile
.c_str(),0644);
233 /* We restore the original name to DestFile so that the clean operation
235 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
236 DestFile
+= URItoFileName(RealURI
);
238 // Remove the compressed version.
240 unlink(DestFile
.c_str());
247 // Handle the unzipd case
248 string FileName
= LookupTag(Message
,"Alt-Filename");
249 if (FileName
.empty() == false)
251 // The files timestamp matches
252 if (StringToBool(LookupTag(Message
,"Alt-IMS-Hit"),false) == true)
255 Decompression
= true;
257 DestFile
+= ".decomp";
258 Desc
.URI
= "copy:" + FileName
;
264 FileName
= LookupTag(Message
,"Filename");
265 if (FileName
.empty() == true)
268 ErrorText
= "Method gave a blank filename";
271 // The files timestamp matches
272 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true)
275 if (FileName
== DestFile
)
280 string compExt
= Desc
.URI
.substr(Desc
.URI
.size()-3,Desc
.URI
.size()-1);
283 decompProg
= "bzip2";
284 else if(compExt
== ".gz")
287 _error
->Error("Unsupported extension: %s", compExt
.c_str());
291 Decompression
= true;
292 DestFile
+= ".decomp";
293 Desc
.URI
= string(decompProg
) + ":" + FileName
;
298 pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire
*Owner
,
299 string URI
,string URIDesc
,string ShortDesc
,
300 string MetaIndexURI
, string MetaIndexURIDesc
,
301 string MetaIndexShortDesc
,
302 const vector
<IndexTarget
*>* IndexTargets
,
303 indexRecords
* MetaIndexParser
) :
304 Item(Owner
), RealURI(URI
), MetaIndexURI(MetaIndexURI
),
305 MetaIndexURIDesc(MetaIndexURIDesc
), MetaIndexShortDesc(MetaIndexShortDesc
)
307 this->MetaIndexParser
= MetaIndexParser
;
308 this->IndexTargets
= IndexTargets
;
309 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
310 DestFile
+= URItoFileName(URI
);
313 Desc
.Description
= URIDesc
;
315 Desc
.ShortDesc
= ShortDesc
;
319 string Final
= _config
->FindDir("Dir::State::lists");
320 Final
+= URItoFileName(RealURI
);
322 if (stat(Final
.c_str(),&Buf
) == 0)
324 // File was already in place. It needs to be re-verified
325 // because Release might have changed, so Move it into partial
326 Rename(Final
,DestFile
);
332 // pkgAcqMetaSig::Custom600Headers - Insert custom request headers /*{{{*/
333 // ---------------------------------------------------------------------
334 /* The only header we use is the last-modified header. */
335 string
pkgAcqMetaSig::Custom600Headers()
337 string Final
= _config
->FindDir("Dir::State::lists");
338 Final
+= URItoFileName(RealURI
);
341 if (stat(Final
.c_str(),&Buf
) != 0)
342 return "\nIndex-File: true";
344 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
347 void pkgAcqMetaSig::Done(string Message
,unsigned long Size
,string MD5
,
348 pkgAcquire::MethodConfig
*Cfg
)
350 Item::Done(Message
,Size
,MD5
,Cfg
);
352 string FileName
= LookupTag(Message
,"Filename");
353 if (FileName
.empty() == true)
356 ErrorText
= "Method gave a blank filename";
360 if (FileName
!= DestFile
)
362 // We have to copy it into place
364 Desc
.URI
= "copy:" + FileName
;
371 // queue a pkgAcqMetaIndex to be verified against the sig we just retrieved
372 new pkgAcqMetaIndex(Owner
, MetaIndexURI
, MetaIndexURIDesc
, MetaIndexShortDesc
,
373 DestFile
, IndexTargets
, MetaIndexParser
);
377 void pkgAcqMetaSig::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
379 // Delete any existing sigfile, so that this source isn't
380 // mistakenly trusted
381 string Final
= _config
->FindDir("Dir::State::lists") + URItoFileName(RealURI
);
382 unlink(Final
.c_str());
384 // queue a pkgAcqMetaIndex with no sigfile
385 new pkgAcqMetaIndex(Owner
, MetaIndexURI
, MetaIndexURIDesc
, MetaIndexShortDesc
,
386 "", IndexTargets
, MetaIndexParser
);
388 if (Cnf
->LocalOnly
== true ||
389 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == false)
398 Item::Failed(Message
,Cnf
);
401 pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire
*Owner
,
402 string URI
,string URIDesc
,string ShortDesc
,
404 const vector
<struct IndexTarget
*>* IndexTargets
,
405 indexRecords
* MetaIndexParser
) :
406 Item(Owner
), RealURI(URI
), SigFile(SigFile
)
408 this->AuthPass
= false;
409 this->MetaIndexParser
= MetaIndexParser
;
410 this->IndexTargets
= IndexTargets
;
411 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
412 DestFile
+= URItoFileName(URI
);
415 Desc
.Description
= URIDesc
;
417 Desc
.ShortDesc
= ShortDesc
;
424 // pkgAcqMetaIndex::Custom600Headers - Insert custom request headers /*{{{*/
425 // ---------------------------------------------------------------------
426 /* The only header we use is the last-modified header. */
427 string
pkgAcqMetaIndex::Custom600Headers()
429 string Final
= _config
->FindDir("Dir::State::lists");
430 Final
+= URItoFileName(RealURI
);
433 if (stat(Final
.c_str(),&Buf
) != 0)
434 return "\nIndex-File: true";
436 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
439 void pkgAcqMetaIndex::Done(string Message
,unsigned long Size
,string MD5
,
440 pkgAcquire::MethodConfig
*Cfg
)
442 Item::Done(Message
,Size
,MD5
,Cfg
);
444 // MetaIndexes are done in two passes: one to download the
445 // metaindex with an appropriate method, and a second to verify it
446 // with the gpgv method
448 if (AuthPass
== true)
454 RetrievalDone(Message
);
456 // Still more retrieving to do
461 // There was no signature file, so we are finished. Download
462 // the indexes without verification.
467 // There was a signature file, so pass it to gpgv for
470 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
471 std::cerr
<< "Metaindex acquired, queueing gpg verification ("
472 << SigFile
<< "," << DestFile
<< ")\n";
474 Desc
.URI
= "gpgv:" + SigFile
;
481 void pkgAcqMetaIndex::RetrievalDone(string Message
)
483 // We have just finished downloading a Release file (it is not
486 string FileName
= LookupTag(Message
,"Filename");
487 if (FileName
.empty() == true)
490 ErrorText
= "Method gave a blank filename";
494 if (FileName
!= DestFile
)
497 Desc
.URI
= "copy:" + FileName
;
504 string FinalFile
= _config
->FindDir("Dir::State::lists");
505 FinalFile
+= URItoFileName(RealURI
);
507 // The files timestamp matches
508 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == false)
510 // Move it into position
511 Rename(DestFile
,FinalFile
);
513 DestFile
= FinalFile
;
516 void pkgAcqMetaIndex::AuthDone(string Message
)
518 // At this point, the gpgv method has succeeded, so there is a
519 // valid signature from a key in the trusted keyring. We
520 // perform additional verification of its contents, and use them
521 // to verify the indexes we are about to download
523 if (!MetaIndexParser
->Load(DestFile
))
525 Status
= StatAuthError
;
526 ErrorText
= MetaIndexParser
->ErrorText
;
535 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
536 std::cerr
<< "Signature verification succeeded: "
537 << DestFile
<< std::endl
;
539 // Download further indexes with verification
542 // Done, move signature file into position
544 string VerifiedSigFile
= _config
->FindDir("Dir::State::lists") +
545 URItoFileName(RealURI
) + ".gpg";
546 Rename(SigFile
,VerifiedSigFile
);
547 chmod(VerifiedSigFile
.c_str(),0644);
550 void pkgAcqMetaIndex::QueueIndexes(bool verify
)
552 for (vector
<struct IndexTarget
*>::const_iterator Target
= IndexTargets
->begin();
553 Target
!= IndexTargets
->end();
556 string ExpectedIndexMD5
;
559 const indexRecords::checkSum
*Record
= MetaIndexParser
->Lookup((*Target
)->MetaKey
);
562 Status
= StatAuthError
;
563 ErrorText
= "Unable to find expected entry "
564 + (*Target
)->MetaKey
+ " in Meta-index file (malformed Release file?)";
567 ExpectedIndexMD5
= Record
->MD5Hash
;
568 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
570 std::cerr
<< "Queueing: " << (*Target
)->URI
<< std::endl
;
571 std::cerr
<< "Expected MD5: " << ExpectedIndexMD5
<< std::endl
;
573 if (ExpectedIndexMD5
.empty())
575 Status
= StatAuthError
;
576 ErrorText
= "Unable to find MD5 sum for "
577 + (*Target
)->MetaKey
+ " in Meta-index file";
582 // Queue Packages file
583 new pkgAcqIndex(Owner
, (*Target
)->URI
, (*Target
)->Description
,
584 (*Target
)->ShortDesc
, ExpectedIndexMD5
);
588 bool pkgAcqMetaIndex::VerifyVendor()
590 // // Maybe this should be made available from above so we don't have
591 // // to read and parse it every time?
592 // pkgVendorList List;
593 // List.ReadMainList();
595 // const Vendor* Vndr = NULL;
596 // for (std::vector<string>::const_iterator I = GPGVOutput.begin(); I != GPGVOutput.end(); I++)
598 // string::size_type pos = (*I).find("VALIDSIG ");
599 // if (_config->FindB("Debug::Vendor", false))
600 // std::cerr << "Looking for VALIDSIG in \"" << (*I) << "\": pos " << pos
602 // if (pos != std::string::npos)
604 // string Fingerprint = (*I).substr(pos+sizeof("VALIDSIG"));
605 // if (_config->FindB("Debug::Vendor", false))
606 // std::cerr << "Looking for \"" << Fingerprint << "\" in vendor..." <<
608 // Vndr = List.FindVendor(Fingerprint) != "";
609 // if (Vndr != NULL);
614 string Transformed
= MetaIndexParser
->GetExpectedDist();
616 if (Transformed
== "../project/experimental")
618 Transformed
= "experimental";
621 string::size_type pos
= Transformed
.rfind('/');
622 if (pos
!= string::npos
)
624 Transformed
= Transformed
.substr(0, pos
);
627 if (Transformed
== ".")
632 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
634 std::cerr
<< "Got Codename: " << MetaIndexParser
->GetDist() << std::endl
;
635 std::cerr
<< "Expecting Dist: " << MetaIndexParser
->GetExpectedDist() << std::endl
;
636 std::cerr
<< "Transformed Dist: " << Transformed
<< std::endl
;
639 if (MetaIndexParser
->CheckDist(Transformed
) == false)
641 // This might become fatal one day
642 // Status = StatAuthError;
643 // ErrorText = "Conflicting distribution; expected "
644 // + MetaIndexParser->GetExpectedDist() + " but got "
645 // + MetaIndexParser->GetDist();
647 if (!Transformed
.empty())
649 _error
->Warning("Conflicting distribution: %s (expected %s but got %s)",
650 Desc
.Description
.c_str(),
652 MetaIndexParser
->GetDist().c_str());
659 // pkgAcqMetaIndex::Failed - no Release file present or no signature
660 // file present /*{{{*/
661 // ---------------------------------------------------------------------
663 void pkgAcqMetaIndex::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
665 if (AuthPass
== true)
667 // gpgv method failed
668 _error
->Warning("GPG error: %s: %s",
669 Desc
.Description
.c_str(),
670 LookupTag(Message
,"Message").c_str());
673 // No Release file was present, or verification failed, so fall
674 // back to queueing Packages files without verification
680 // AcqArchive::AcqArchive - Constructor /*{{{*/
681 // ---------------------------------------------------------------------
682 /* This just sets up the initial fetch environment and queues the first
684 pkgAcqArchive::pkgAcqArchive(pkgAcquire
*Owner
,pkgSourceList
*Sources
,
685 pkgRecords
*Recs
,pkgCache::VerIterator
const &Version
,
686 string
&StoreFilename
) :
687 Item(Owner
), Version(Version
), Sources(Sources
), Recs(Recs
),
688 StoreFilename(StoreFilename
), Vf(Version
.FileList()),
691 Retries
= _config
->FindI("Acquire::Retries",0);
693 if (Version
.Arch() == 0)
695 _error
->Error(_("I wasn't able to locate a file for the %s package. "
696 "This might mean you need to manually fix this package. "
697 "(due to missing arch)"),
698 Version
.ParentPkg().Name());
702 /* We need to find a filename to determine the extension. We make the
703 assumption here that all the available sources for this version share
704 the same extension.. */
705 // Skip not source sources, they do not have file fields.
706 for (; Vf
.end() == false; Vf
++)
708 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) != 0)
713 // Does not really matter here.. we are going to fail out below
714 if (Vf
.end() != true)
716 // If this fails to get a file name we will bomb out below.
717 pkgRecords::Parser
&Parse
= Recs
->Lookup(Vf
);
718 if (_error
->PendingError() == true)
721 // Generate the final file name as: package_version_arch.foo
722 StoreFilename
= QuoteString(Version
.ParentPkg().Name(),"_:") + '_' +
723 QuoteString(Version
.VerStr(),"_:") + '_' +
724 QuoteString(Version
.Arch(),"_:.") +
725 "." + flExtension(Parse
.FileName());
728 // check if we have one trusted source for the package. if so, switch
729 // to "TrustedOnly" mode
730 for (pkgCache::VerFileIterator i
= Version
.FileList(); i
.end() == false; i
++)
733 if (Sources
->FindIndex(i
.File(),Index
) == false)
735 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
737 std::cerr
<< "Checking index: " << Index
->Describe()
738 << "(Trusted=" << Index
->IsTrusted() << ")\n";
740 if (Index
->IsTrusted()) {
747 if (QueueNext() == false && _error
->PendingError() == false)
748 _error
->Error(_("I wasn't able to locate file for the %s package. "
749 "This might mean you need to manually fix this package."),
750 Version
.ParentPkg().Name());
753 // AcqArchive::QueueNext - Queue the next file source /*{{{*/
754 // ---------------------------------------------------------------------
755 /* This queues the next available file version for download. It checks if
756 the archive is already available in the cache and stashs the MD5 for
758 bool pkgAcqArchive::QueueNext()
760 for (; Vf
.end() == false; Vf
++)
762 // Ignore not source sources
763 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) != 0)
766 // Try to cross match against the source list
768 if (Sources
->FindIndex(Vf
.File(),Index
) == false)
771 // only try to get a trusted package from another source if that source
773 if(Trusted
&& !Index
->IsTrusted())
776 // Grab the text package record
777 pkgRecords::Parser
&Parse
= Recs
->Lookup(Vf
);
778 if (_error
->PendingError() == true)
781 string PkgFile
= Parse
.FileName();
782 MD5
= Parse
.MD5Hash();
783 if (PkgFile
.empty() == true)
784 return _error
->Error(_("The package index files are corrupted. No Filename: "
785 "field for package %s."),
786 Version
.ParentPkg().Name());
788 Desc
.URI
= Index
->ArchiveURI(PkgFile
);
789 Desc
.Description
= Index
->ArchiveInfo(Version
);
791 Desc
.ShortDesc
= Version
.ParentPkg().Name();
793 // See if we already have the file. (Legacy filenames)
794 FileSize
= Version
->Size
;
795 string FinalFile
= _config
->FindDir("Dir::Cache::Archives") + flNotDir(PkgFile
);
797 if (stat(FinalFile
.c_str(),&Buf
) == 0)
799 // Make sure the size matches
800 if ((unsigned)Buf
.st_size
== Version
->Size
)
805 StoreFilename
= DestFile
= FinalFile
;
809 /* Hmm, we have a file and its size does not match, this means it is
810 an old style mismatched arch */
811 unlink(FinalFile
.c_str());
814 // Check it again using the new style output filenames
815 FinalFile
= _config
->FindDir("Dir::Cache::Archives") + flNotDir(StoreFilename
);
816 if (stat(FinalFile
.c_str(),&Buf
) == 0)
818 // Make sure the size matches
819 if ((unsigned)Buf
.st_size
== Version
->Size
)
824 StoreFilename
= DestFile
= FinalFile
;
828 /* Hmm, we have a file and its size does not match, this shouldnt
830 unlink(FinalFile
.c_str());
833 DestFile
= _config
->FindDir("Dir::Cache::Archives") + "partial/" + flNotDir(StoreFilename
);
835 // Check the destination file
836 if (stat(DestFile
.c_str(),&Buf
) == 0)
838 // Hmm, the partial file is too big, erase it
839 if ((unsigned)Buf
.st_size
> Version
->Size
)
840 unlink(DestFile
.c_str());
842 PartialSize
= Buf
.st_size
;
847 Desc
.URI
= Index
->ArchiveURI(PkgFile
);
848 Desc
.Description
= Index
->ArchiveInfo(Version
);
850 Desc
.ShortDesc
= Version
.ParentPkg().Name();
859 // AcqArchive::Done - Finished fetching /*{{{*/
860 // ---------------------------------------------------------------------
862 void pkgAcqArchive::Done(string Message
,unsigned long Size
,string Md5Hash
,
863 pkgAcquire::MethodConfig
*Cfg
)
865 Item::Done(Message
,Size
,Md5Hash
,Cfg
);
868 if (Size
!= Version
->Size
)
871 ErrorText
= _("Size mismatch");
876 if (Md5Hash
.empty() == false && MD5
.empty() == false)
881 ErrorText
= _("MD5Sum mismatch");
882 Rename(DestFile
,DestFile
+ ".FAILED");
887 // Grab the output filename
888 string FileName
= LookupTag(Message
,"Filename");
889 if (FileName
.empty() == true)
892 ErrorText
= "Method gave a blank filename";
898 // Reference filename
899 if (FileName
!= DestFile
)
901 StoreFilename
= DestFile
= FileName
;
906 // Done, move it into position
907 string FinalFile
= _config
->FindDir("Dir::Cache::Archives");
908 FinalFile
+= flNotDir(StoreFilename
);
909 Rename(DestFile
,FinalFile
);
911 StoreFilename
= DestFile
= FinalFile
;
915 // AcqArchive::Failed - Failure handler /*{{{*/
916 // ---------------------------------------------------------------------
917 /* Here we try other sources */
918 void pkgAcqArchive::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
920 ErrorText
= LookupTag(Message
,"Message");
922 /* We don't really want to retry on failed media swaps, this prevents
923 that. An interesting observation is that permanent failures are not
925 if (Cnf
->Removable
== true &&
926 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
928 // Vf = Version.FileList();
929 while (Vf
.end() == false) Vf
++;
930 StoreFilename
= string();
931 Item::Failed(Message
,Cnf
);
935 if (QueueNext() == false)
937 // This is the retry counter
939 Cnf
->LocalOnly
== false &&
940 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
943 Vf
= Version
.FileList();
944 if (QueueNext() == true)
948 StoreFilename
= string();
949 Item::Failed(Message
,Cnf
);
953 // AcqArchive::IsTrusted - Determine whether this archive comes from a
954 // trusted source /*{{{*/
955 // ---------------------------------------------------------------------
956 bool pkgAcqArchive::IsTrusted()
961 // AcqArchive::Finished - Fetching has finished, tidy up /*{{{*/
962 // ---------------------------------------------------------------------
964 void pkgAcqArchive::Finished()
966 if (Status
== pkgAcquire::Item::StatDone
&&
969 StoreFilename
= string();
973 // AcqFile::pkgAcqFile - Constructor /*{{{*/
974 // ---------------------------------------------------------------------
975 /* The file is added to the queue */
976 pkgAcqFile::pkgAcqFile(pkgAcquire
*Owner
,string URI
,string MD5
,
977 unsigned long Size
,string Dsc
,string ShortDesc
) :
978 Item(Owner
), Md5Hash(MD5
)
980 Retries
= _config
->FindI("Acquire::Retries",0);
982 DestFile
= flNotDir(URI
);
986 Desc
.Description
= Dsc
;
989 // Set the short description to the archive component
990 Desc
.ShortDesc
= ShortDesc
;
992 // Get the transfer sizes
995 if (stat(DestFile
.c_str(),&Buf
) == 0)
997 // Hmm, the partial file is too big, erase it
998 if ((unsigned)Buf
.st_size
> Size
)
999 unlink(DestFile
.c_str());
1001 PartialSize
= Buf
.st_size
;
1007 // AcqFile::Done - Item downloaded OK /*{{{*/
1008 // ---------------------------------------------------------------------
1010 void pkgAcqFile::Done(string Message
,unsigned long Size
,string MD5
,
1011 pkgAcquire::MethodConfig
*Cnf
)
1014 if (Md5Hash
.empty() == false && MD5
.empty() == false)
1019 ErrorText
= "MD5Sum mismatch";
1020 Rename(DestFile
,DestFile
+ ".FAILED");
1025 Item::Done(Message
,Size
,MD5
,Cnf
);
1027 string FileName
= LookupTag(Message
,"Filename");
1028 if (FileName
.empty() == true)
1031 ErrorText
= "Method gave a blank filename";
1037 // The files timestamp matches
1038 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true)
1041 // We have to copy it into place
1042 if (FileName
!= DestFile
)
1045 if (_config
->FindB("Acquire::Source-Symlinks",true) == false ||
1046 Cnf
->Removable
== true)
1048 Desc
.URI
= "copy:" + FileName
;
1053 // Erase the file if it is a symlink so we can overwrite it
1055 if (lstat(DestFile
.c_str(),&St
) == 0)
1057 if (S_ISLNK(St
.st_mode
) != 0)
1058 unlink(DestFile
.c_str());
1062 if (symlink(FileName
.c_str(),DestFile
.c_str()) != 0)
1064 ErrorText
= "Link to " + DestFile
+ " failure ";
1071 // AcqFile::Failed - Failure handler /*{{{*/
1072 // ---------------------------------------------------------------------
1073 /* Here we try other sources */
1074 void pkgAcqFile::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
1076 ErrorText
= LookupTag(Message
,"Message");
1078 // This is the retry counter
1080 Cnf
->LocalOnly
== false &&
1081 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
1088 Item::Failed(Message
,Cnf
);