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 /*{{{*/
16 #include <apt-pkg/acquire-item.h>
17 #include <apt-pkg/configuration.h>
18 #include <apt-pkg/aptconfiguration.h>
19 #include <apt-pkg/sourcelist.h>
20 #include <apt-pkg/vendorlist.h>
21 #include <apt-pkg/error.h>
22 #include <apt-pkg/strutl.h>
23 #include <apt-pkg/fileutl.h>
24 #include <apt-pkg/md5.h>
25 #include <apt-pkg/sha1.h>
26 #include <apt-pkg/tagfile.h>
41 // Acquire::Item::Item - Constructor /*{{{*/
42 // ---------------------------------------------------------------------
44 pkgAcquire::Item::Item(pkgAcquire
*Owner
) : Owner(Owner
), FileSize(0),
45 PartialSize(0), Mode(0), ID(0), Complete(false),
46 Local(false), QueueCounter(0)
52 // Acquire::Item::~Item - Destructor /*{{{*/
53 // ---------------------------------------------------------------------
55 pkgAcquire::Item::~Item()
60 // Acquire::Item::Failed - Item failed to download /*{{{*/
61 // ---------------------------------------------------------------------
62 /* We return to an idle state if there are still other queues that could
64 void pkgAcquire::Item::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
67 ErrorText
= LookupTag(Message
,"Message");
68 UsedMirror
= LookupTag(Message
,"UsedMirror");
69 if (QueueCounter
<= 1)
71 /* This indicates that the file is not available right now but might
72 be sometime later. If we do a retry cycle then this should be
74 if (Cnf
->LocalOnly
== true &&
75 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
86 // report mirror failure back to LP if we actually use a mirror
87 string FailReason
= LookupTag(Message
, "FailReason");
88 if(FailReason
.size() != 0)
89 ReportMirrorFailure(FailReason
);
91 ReportMirrorFailure(ErrorText
);
94 // Acquire::Item::Start - Item has begun to download /*{{{*/
95 // ---------------------------------------------------------------------
96 /* Stash status and the file size. Note that setting Complete means
97 sub-phases of the acquire process such as decompresion are operating */
98 void pkgAcquire::Item::Start(string
/*Message*/,unsigned long Size
)
100 Status
= StatFetching
;
101 if (FileSize
== 0 && Complete
== false)
105 // Acquire::Item::Done - Item downloaded OK /*{{{*/
106 // ---------------------------------------------------------------------
108 void pkgAcquire::Item::Done(string Message
,unsigned long Size
,string Hash
,
109 pkgAcquire::MethodConfig
*Cnf
)
111 // We just downloaded something..
112 string FileName
= LookupTag(Message
,"Filename");
113 UsedMirror
= LookupTag(Message
,"UsedMirror");
114 if (Complete
== false && !Local
&& FileName
== DestFile
)
117 Owner
->Log
->Fetched(Size
,atoi(LookupTag(Message
,"Resume-Point","0").c_str()));
123 ErrorText
= string();
124 Owner
->Dequeue(this);
127 // Acquire::Item::Rename - Rename a file /*{{{*/
128 // ---------------------------------------------------------------------
129 /* This helper function is used by alot of item methods as thier final
131 void pkgAcquire::Item::Rename(string From
,string To
)
133 if (rename(From
.c_str(),To
.c_str()) != 0)
136 snprintf(S
,sizeof(S
),_("rename failed, %s (%s -> %s)."),strerror(errno
),
137 From
.c_str(),To
.c_str());
144 void pkgAcquire::Item::ReportMirrorFailure(string FailCode
)
146 // we only act if a mirror was used at all
147 if(UsedMirror
.empty())
150 std::cerr
<< "\nReportMirrorFailure: "
152 << " Uri: " << DescURI()
154 << FailCode
<< std::endl
;
156 const char *Args
[40];
158 string report
= _config
->Find("Methods::Mirror::ProblemReporting",
159 "/usr/lib/apt/apt-report-mirror-failure");
160 if(!FileExists(report
))
162 Args
[i
++] = report
.c_str();
163 Args
[i
++] = UsedMirror
.c_str();
164 Args
[i
++] = DescURI().c_str();
165 Args
[i
++] = FailCode
.c_str();
167 pid_t pid
= ExecFork();
170 _error
->Error("ReportMirrorFailure Fork failed");
175 execvp(Args
[0], (char**)Args
);
176 std::cerr
<< "Could not exec " << Args
[0] << std::endl
;
179 if(!ExecWait(pid
, "report-mirror-failure"))
181 _error
->Warning("Couldn't report problem to '%s'",
182 _config
->Find("Methods::Mirror::ProblemReporting").c_str());
186 // AcqDiffIndex::AcqDiffIndex - Constructor /*{{{*/
187 // ---------------------------------------------------------------------
188 /* Get the DiffIndex file first and see if there are patches availabe
189 * If so, create a pkgAcqIndexDiffs fetcher that will get and apply the
190 * patches. If anything goes wrong in that process, it will fall back to
191 * the original packages file
193 pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire
*Owner
,
194 string URI
,string URIDesc
,string ShortDesc
,
195 HashString ExpectedHash
)
196 : Item(Owner
), RealURI(URI
), ExpectedHash(ExpectedHash
),
200 Debug
= _config
->FindB("Debug::pkgAcquire::Diffs",false);
202 Desc
.Description
= URIDesc
+ "/DiffIndex";
204 Desc
.ShortDesc
= ShortDesc
;
205 Desc
.URI
= URI
+ ".diff/Index";
207 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
208 DestFile
+= URItoFileName(URI
) + string(".DiffIndex");
211 std::clog
<< "pkgAcqDiffIndex: " << Desc
.URI
<< std::endl
;
213 // look for the current package file
214 CurrentPackagesFile
= _config
->FindDir("Dir::State::lists");
215 CurrentPackagesFile
+= URItoFileName(RealURI
);
217 // FIXME: this file:/ check is a hack to prevent fetching
218 // from local sources. this is really silly, and
219 // should be fixed cleanly as soon as possible
220 if(!FileExists(CurrentPackagesFile
) ||
221 Desc
.URI
.substr(0,strlen("file:/")) == "file:/")
223 // we don't have a pkg file or we don't want to queue
225 std::clog
<< "No index file, local or canceld by user" << std::endl
;
231 std::clog
<< "pkgAcqIndexDiffs::pkgAcqIndexDiffs(): "
232 << CurrentPackagesFile
<< std::endl
;
238 // AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
239 // ---------------------------------------------------------------------
240 /* The only header we use is the last-modified header. */
241 string
pkgAcqDiffIndex::Custom600Headers()
243 string Final
= _config
->FindDir("Dir::State::lists");
244 Final
+= URItoFileName(RealURI
) + string(".IndexDiff");
247 std::clog
<< "Custom600Header-IMS: " << Final
<< std::endl
;
250 if (stat(Final
.c_str(),&Buf
) != 0)
251 return "\nIndex-File: true";
253 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
256 bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile
) /*{{{*/
259 std::clog
<< "pkgAcqIndexDiffs::ParseIndexDiff() " << IndexDiffFile
264 vector
<DiffInfo
> available_patches
;
266 FileFd
Fd(IndexDiffFile
,FileFd::ReadOnly
);
268 if (_error
->PendingError() == true)
271 if(TF
.Step(Tags
) == true)
277 string
const tmp
= Tags
.FindS("SHA1-Current");
278 std::stringstream
ss(tmp
);
279 ss
>> ServerSha1
>> size
;
280 unsigned long const ServerSize
= atol(size
.c_str());
282 FileFd
fd(CurrentPackagesFile
, FileFd::ReadOnly
);
284 SHA1
.AddFD(fd
.Fd(), fd
.Size());
285 string
const local_sha1
= SHA1
.Result();
287 if(local_sha1
== ServerSha1
)
289 // we have the same sha1 as the server
291 std::clog
<< "Package file is up-to-date" << std::endl
;
292 // set found to true, this will queue a pkgAcqIndexDiffs with
293 // a empty availabe_patches
299 std::clog
<< "SHA1-Current: " << ServerSha1
<< std::endl
;
301 // check the historie and see what patches we need
302 string
const history
= Tags
.FindS("SHA1-History");
303 std::stringstream
hist(history
);
304 while(hist
>> d
.sha1
>> size
>> d
.file
)
306 // read until the first match is found
307 // from that point on, we probably need all diffs
308 if(d
.sha1
== local_sha1
)
310 else if (found
== false)
314 std::clog
<< "Need to get diff: " << d
.file
<< std::endl
;
315 available_patches
.push_back(d
);
318 if (available_patches
.empty() == false)
320 // patching with too many files is rather slow compared to a fast download
321 unsigned long const fileLimit
= _config
->FindI("Acquire::PDiffs::FileLimit", 0);
322 if (fileLimit
!= 0 && fileLimit
< available_patches
.size())
325 std::clog
<< "Need " << available_patches
.size() << " diffs (Limit is " << fileLimit
326 << ") so fallback to complete download" << std::endl
;
330 // see if the patches are too big
331 found
= false; // it was true and it will be true again at the end
332 d
= *available_patches
.begin();
333 string
const firstPatch
= d
.file
;
334 unsigned long patchesSize
= 0;
335 std::stringstream
patches(Tags
.FindS("SHA1-Patches"));
336 while(patches
>> d
.sha1
>> size
>> d
.file
)
338 if (firstPatch
== d
.file
)
340 else if (found
== false)
343 patchesSize
+= atol(size
.c_str());
345 unsigned long const sizeLimit
= ServerSize
* _config
->FindI("Acquire::PDiffs::SizeLimit", 100);
346 if (sizeLimit
> 0 && (sizeLimit
/100) < patchesSize
)
349 std::clog
<< "Need " << patchesSize
<< " bytes (Limit is " << sizeLimit
/100
350 << ") so fallback to complete download" << std::endl
;
356 // we have something, queue the next diff
360 string::size_type
const last_space
= Description
.rfind(" ");
361 if(last_space
!= string::npos
)
362 Description
.erase(last_space
, Description
.size()-last_space
);
363 new pkgAcqIndexDiffs(Owner
, RealURI
, Description
, Desc
.ShortDesc
,
364 ExpectedHash
, ServerSha1
, available_patches
);
372 // Nothing found, report and return false
373 // Failing here is ok, if we return false later, the full
374 // IndexFile is queued
376 std::clog
<< "Can't find a patch in the index file" << std::endl
;
380 void pkgAcqDiffIndex::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
) /*{{{*/
383 std::clog
<< "pkgAcqDiffIndex failed: " << Desc
.URI
<< std::endl
384 << "Falling back to normal index file aquire" << std::endl
;
386 new pkgAcqIndex(Owner
, RealURI
, Description
, Desc
.ShortDesc
,
394 void pkgAcqDiffIndex::Done(string Message
,unsigned long Size
,string Md5Hash
, /*{{{*/
395 pkgAcquire::MethodConfig
*Cnf
)
398 std::clog
<< "pkgAcqDiffIndex::Done(): " << Desc
.URI
<< std::endl
;
400 Item::Done(Message
,Size
,Md5Hash
,Cnf
);
403 FinalFile
= _config
->FindDir("Dir::State::lists")+URItoFileName(RealURI
);
405 // sucess in downloading the index
407 FinalFile
+= string(".IndexDiff");
409 std::clog
<< "Renaming: " << DestFile
<< " -> " << FinalFile
411 Rename(DestFile
,FinalFile
);
412 chmod(FinalFile
.c_str(),0644);
413 DestFile
= FinalFile
;
415 if(!ParseDiffIndex(DestFile
))
416 return Failed("", NULL
);
424 // AcqIndexDiffs::AcqIndexDiffs - Constructor /*{{{*/
425 // ---------------------------------------------------------------------
426 /* The package diff is added to the queue. one object is constructed
427 * for each diff and the index
429 pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire
*Owner
,
430 string URI
,string URIDesc
,string ShortDesc
,
431 HashString ExpectedHash
,
433 vector
<DiffInfo
> diffs
)
434 : Item(Owner
), RealURI(URI
), ExpectedHash(ExpectedHash
),
435 available_patches(diffs
), ServerSha1(ServerSha1
)
438 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
439 DestFile
+= URItoFileName(URI
);
441 Debug
= _config
->FindB("Debug::pkgAcquire::Diffs",false);
443 Description
= URIDesc
;
445 Desc
.ShortDesc
= ShortDesc
;
447 if(available_patches
.size() == 0)
449 // we are done (yeah!)
455 State
= StateFetchDiff
;
460 void pkgAcqIndexDiffs::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
) /*{{{*/
463 std::clog
<< "pkgAcqIndexDiffs failed: " << Desc
.URI
<< std::endl
464 << "Falling back to normal index file aquire" << std::endl
;
465 new pkgAcqIndex(Owner
, RealURI
, Description
,Desc
.ShortDesc
,
470 // Finish - helper that cleans the item out of the fetcher queue /*{{{*/
471 void pkgAcqIndexDiffs::Finish(bool allDone
)
473 // we restore the original name, this is required, otherwise
474 // the file will be cleaned
477 DestFile
= _config
->FindDir("Dir::State::lists");
478 DestFile
+= URItoFileName(RealURI
);
480 if(!ExpectedHash
.empty() && !ExpectedHash
.VerifyFile(DestFile
))
482 Status
= StatAuthError
;
483 ErrorText
= _("MD5Sum mismatch");
484 Rename(DestFile
,DestFile
+ ".FAILED");
489 // this is for the "real" finish
494 std::clog
<< "\n\nallDone: " << DestFile
<< "\n" << std::endl
;
499 std::clog
<< "Finishing: " << Desc
.URI
<< std::endl
;
506 bool pkgAcqIndexDiffs::QueueNextDiff() /*{{{*/
509 // calc sha1 of the just patched file
510 string FinalFile
= _config
->FindDir("Dir::State::lists");
511 FinalFile
+= URItoFileName(RealURI
);
513 FileFd
fd(FinalFile
, FileFd::ReadOnly
);
515 SHA1
.AddFD(fd
.Fd(), fd
.Size());
516 string local_sha1
= string(SHA1
.Result());
518 std::clog
<< "QueueNextDiff: "
519 << FinalFile
<< " (" << local_sha1
<< ")"<<std::endl
;
521 // final file reached before all patches are applied
522 if(local_sha1
== ServerSha1
)
528 // remove all patches until the next matching patch is found
529 // this requires the Index file to be ordered
530 for(vector
<DiffInfo
>::iterator I
=available_patches
.begin();
531 available_patches
.size() > 0 &&
532 I
!= available_patches
.end() &&
533 (*I
).sha1
!= local_sha1
;
536 available_patches
.erase(I
);
539 // error checking and falling back if no patch was found
540 if(available_patches
.size() == 0)
546 // queue the right diff
547 Desc
.URI
= string(RealURI
) + ".diff/" + available_patches
[0].file
+ ".gz";
548 Desc
.Description
= Description
+ " " + available_patches
[0].file
+ string(".pdiff");
549 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
550 DestFile
+= URItoFileName(RealURI
+ ".diff/" + available_patches
[0].file
);
553 std::clog
<< "pkgAcqIndexDiffs::QueueNextDiff(): " << Desc
.URI
<< std::endl
;
560 void pkgAcqIndexDiffs::Done(string Message
,unsigned long Size
,string Md5Hash
, /*{{{*/
561 pkgAcquire::MethodConfig
*Cnf
)
564 std::clog
<< "pkgAcqIndexDiffs::Done(): " << Desc
.URI
<< std::endl
;
566 Item::Done(Message
,Size
,Md5Hash
,Cnf
);
569 FinalFile
= _config
->FindDir("Dir::State::lists")+URItoFileName(RealURI
);
571 // sucess in downloading a diff, enter ApplyDiff state
572 if(State
== StateFetchDiff
)
576 std::clog
<< "Sending to gzip method: " << FinalFile
<< std::endl
;
578 string FileName
= LookupTag(Message
,"Filename");
579 State
= StateUnzipDiff
;
581 Desc
.URI
= "gzip:" + FileName
;
582 DestFile
+= ".decomp";
588 // sucess in downloading a diff, enter ApplyDiff state
589 if(State
== StateUnzipDiff
)
592 // rred excepts the patch as $FinalFile.ed
593 Rename(DestFile
,FinalFile
+".ed");
596 std::clog
<< "Sending to rred method: " << FinalFile
<< std::endl
;
598 State
= StateApplyDiff
;
600 Desc
.URI
= "rred:" + FinalFile
;
607 // success in download/apply a diff, queue next (if needed)
608 if(State
== StateApplyDiff
)
610 // remove the just applied patch
611 available_patches
.erase(available_patches
.begin());
616 std::clog
<< "Moving patched file in place: " << std::endl
617 << DestFile
<< " -> " << FinalFile
<< std::endl
;
619 Rename(DestFile
,FinalFile
);
620 chmod(FinalFile
.c_str(),0644);
622 // see if there is more to download
623 if(available_patches
.size() > 0) {
624 new pkgAcqIndexDiffs(Owner
, RealURI
, Description
, Desc
.ShortDesc
,
625 ExpectedHash
, ServerSha1
, available_patches
);
632 // AcqIndex::AcqIndex - Constructor /*{{{*/
633 // ---------------------------------------------------------------------
634 /* The package file is added to the queue and a second class is
635 instantiated to fetch the revision file */
636 pkgAcqIndex::pkgAcqIndex(pkgAcquire
*Owner
,
637 string URI
,string URIDesc
,string ShortDesc
,
638 HashString ExpectedHash
, string comprExt
)
639 : Item(Owner
), RealURI(URI
), ExpectedHash(ExpectedHash
)
641 Decompression
= false;
644 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
645 DestFile
+= URItoFileName(URI
);
649 // autoselect the compression method
650 std::vector
<std::string
> types
= APT::Configuration::getCompressionTypes();
651 if (types
.empty() == true)
654 comprExt
= "." + types
[0];
656 CompressionExtension
= ((comprExt
== "plain" || comprExt
== ".") ? "" : comprExt
);
658 Desc
.URI
= URI
+ CompressionExtension
;
660 Desc
.Description
= URIDesc
;
662 Desc
.ShortDesc
= ShortDesc
;
667 // AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
668 // ---------------------------------------------------------------------
669 /* The only header we use is the last-modified header. */
670 string
pkgAcqIndex::Custom600Headers()
672 string Final
= _config
->FindDir("Dir::State::lists");
673 Final
+= URItoFileName(RealURI
);
676 if (stat(Final
.c_str(),&Buf
) != 0)
677 return "\nIndex-File: true";
678 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
681 void pkgAcqIndex::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
) /*{{{*/
683 std::vector
<std::string
> types
= APT::Configuration::getCompressionTypes();
685 for (std::vector
<std::string
>::const_iterator t
= types
.begin();
686 t
!= types
.end(); t
++)
688 // jump over all already tried compression types
689 const unsigned int nameLen
= Desc
.URI
.size() - (*t
).size();
690 if(Desc
.URI
.substr(nameLen
) != *t
)
693 // we want to try it with the next extension (and make sure to
694 // not skip over the end)
696 if (t
== types
.end())
699 // queue new download
700 Desc
.URI
= Desc
.URI
.substr(0, nameLen
) + *t
;
701 new pkgAcqIndex(Owner
, RealURI
, Desc
.Description
, Desc
.ShortDesc
,
702 ExpectedHash
, string(".").append(*t
));
710 // on decompression failure, remove bad versions in partial/
711 if(Decompression
&& Erase
) {
712 string s
= _config
->FindDir("Dir::State::lists") + "partial/";
713 s
+= URItoFileName(RealURI
);
717 Item::Failed(Message
,Cnf
);
720 // AcqIndex::Done - Finished a fetch /*{{{*/
721 // ---------------------------------------------------------------------
722 /* This goes through a number of states.. On the initial fetch the
723 method could possibly return an alternate filename which points
724 to the uncompressed version of the file. If this is so the file
725 is copied into the partial directory. In all other cases the file
726 is decompressed with a gzip uri. */
727 void pkgAcqIndex::Done(string Message
,unsigned long Size
,string Hash
,
728 pkgAcquire::MethodConfig
*Cfg
)
730 Item::Done(Message
,Size
,Hash
,Cfg
);
732 if (Decompression
== true)
734 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
736 std::cerr
<< std::endl
<< RealURI
<< ": Computed Hash: " << Hash
;
737 std::cerr
<< " Expected Hash: " << ExpectedHash
.toStr() << std::endl
;
740 if (!ExpectedHash
.empty() && ExpectedHash
.toStr() != Hash
)
742 Status
= StatAuthError
;
743 ErrorText
= _("Hash Sum mismatch");
744 Rename(DestFile
,DestFile
+ ".FAILED");
745 ReportMirrorFailure("HashChecksumFailure");
748 // Done, move it into position
749 string FinalFile
= _config
->FindDir("Dir::State::lists");
750 FinalFile
+= URItoFileName(RealURI
);
751 Rename(DestFile
,FinalFile
);
752 chmod(FinalFile
.c_str(),0644);
754 /* We restore the original name to DestFile so that the clean operation
756 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
757 DestFile
+= URItoFileName(RealURI
);
759 // Remove the compressed version.
761 unlink(DestFile
.c_str());
768 // Handle the unzipd case
769 string FileName
= LookupTag(Message
,"Alt-Filename");
770 if (FileName
.empty() == false)
772 // The files timestamp matches
773 if (StringToBool(LookupTag(Message
,"Alt-IMS-Hit"),false) == true)
775 Decompression
= true;
777 DestFile
+= ".decomp";
778 Desc
.URI
= "copy:" + FileName
;
784 FileName
= LookupTag(Message
,"Filename");
785 if (FileName
.empty() == true)
788 ErrorText
= "Method gave a blank filename";
791 // The files timestamp matches
792 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true)
795 if (FileName
== DestFile
)
800 string compExt
= flExtension(flNotDir(URI(Desc
.URI
).Path
));
803 // get the binary name for your used compression type
804 decompProg
= _config
->Find(string("Acquire::CompressionTypes::").append(compExt
),"");
805 if(decompProg
.empty() == false);
806 // flExtensions returns the full name if no extension is found
807 // this is why we have this complicated compare operation here
808 // FIMXE: add a new flJustExtension() that return "" if no
809 // extension is found and use that above so that it can
810 // be tested against ""
811 else if(compExt
== flNotDir(URI(Desc
.URI
).Path
))
814 _error
->Error("Unsupported extension: %s", compExt
.c_str());
818 Decompression
= true;
819 DestFile
+= ".decomp";
820 Desc
.URI
= decompProg
+ ":" + FileName
;
822 Mode
= decompProg
.c_str();
825 // AcqIndexTrans::pkgAcqIndexTrans - Constructor /*{{{*/
826 // ---------------------------------------------------------------------
827 /* The Translation file is added to the queue */
828 pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire
*Owner
,
829 string URI
,string URIDesc
,string ShortDesc
)
830 : pkgAcqIndex(Owner
, URI
, URIDesc
, ShortDesc
, HashString(), "")
834 // AcqIndexTrans::Custom600Headers - Insert custom request headers /*{{{*/
835 // ---------------------------------------------------------------------
836 string
pkgAcqIndexTrans::Custom600Headers()
838 return "\nFail-Ignore: true";
841 // AcqIndexTrans::Failed - Silence failure messages for missing files /*{{{*/
842 // ---------------------------------------------------------------------
844 void pkgAcqIndexTrans::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
846 if (Cnf
->LocalOnly
== true ||
847 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == false)
856 Item::Failed(Message
,Cnf
);
859 pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire
*Owner
, /*{{{*/
860 string URI
,string URIDesc
,string ShortDesc
,
861 string MetaIndexURI
, string MetaIndexURIDesc
,
862 string MetaIndexShortDesc
,
863 const vector
<IndexTarget
*>* IndexTargets
,
864 indexRecords
* MetaIndexParser
) :
865 Item(Owner
), RealURI(URI
), MetaIndexURI(MetaIndexURI
),
866 MetaIndexURIDesc(MetaIndexURIDesc
), MetaIndexShortDesc(MetaIndexShortDesc
),
867 MetaIndexParser(MetaIndexParser
), IndexTargets(IndexTargets
)
869 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
870 DestFile
+= URItoFileName(URI
);
872 // remove any partial downloaded sig-file in partial/.
873 // it may confuse proxies and is too small to warrant a
874 // partial download anyway
875 unlink(DestFile
.c_str());
878 Desc
.Description
= URIDesc
;
880 Desc
.ShortDesc
= ShortDesc
;
883 string Final
= _config
->FindDir("Dir::State::lists");
884 Final
+= URItoFileName(RealURI
);
886 if (stat(Final
.c_str(),&Buf
) == 0)
888 // File was already in place. It needs to be re-downloaded/verified
889 // because Release might have changed, we do give it a differnt
890 // name than DestFile because otherwise the http method will
891 // send If-Range requests and there are too many broken servers
892 // out there that do not understand them
893 LastGoodSig
= DestFile
+".reverify";
894 Rename(Final
,LastGoodSig
);
900 // pkgAcqMetaSig::Custom600Headers - Insert custom request headers /*{{{*/
901 // ---------------------------------------------------------------------
902 /* The only header we use is the last-modified header. */
903 string
pkgAcqMetaSig::Custom600Headers()
906 if (stat(LastGoodSig
.c_str(),&Buf
) != 0)
907 return "\nIndex-File: true";
909 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
912 void pkgAcqMetaSig::Done(string Message
,unsigned long Size
,string MD5
,
913 pkgAcquire::MethodConfig
*Cfg
)
915 Item::Done(Message
,Size
,MD5
,Cfg
);
917 string FileName
= LookupTag(Message
,"Filename");
918 if (FileName
.empty() == true)
921 ErrorText
= "Method gave a blank filename";
925 if (FileName
!= DestFile
)
927 // We have to copy it into place
929 Desc
.URI
= "copy:" + FileName
;
936 // put the last known good file back on i-m-s hit (it will
937 // be re-verified again)
938 // Else do nothing, we have the new file in DestFile then
939 if(StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true)
940 Rename(LastGoodSig
, DestFile
);
942 // queue a pkgAcqMetaIndex to be verified against the sig we just retrieved
943 new pkgAcqMetaIndex(Owner
, MetaIndexURI
, MetaIndexURIDesc
,
944 MetaIndexShortDesc
, DestFile
, IndexTargets
,
949 void pkgAcqMetaSig::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)/*{{{*/
951 string Final
= _config
->FindDir("Dir::State::lists") + URItoFileName(RealURI
);
953 // if we get a network error we fail gracefully
954 if(Status
== StatTransientNetworkError
)
956 Item::Failed(Message
,Cnf
);
957 // move the sigfile back on transient network failures
958 if(FileExists(LastGoodSig
))
959 Rename(LastGoodSig
,Final
);
961 // set the status back to , Item::Failed likes to reset it
962 Status
= pkgAcquire::Item::StatTransientNetworkError
;
966 // Delete any existing sigfile when the acquire failed
967 unlink(Final
.c_str());
969 // queue a pkgAcqMetaIndex with no sigfile
970 new pkgAcqMetaIndex(Owner
, MetaIndexURI
, MetaIndexURIDesc
, MetaIndexShortDesc
,
971 "", IndexTargets
, MetaIndexParser
);
973 if (Cnf
->LocalOnly
== true ||
974 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == false)
983 Item::Failed(Message
,Cnf
);
986 pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire
*Owner
, /*{{{*/
987 string URI
,string URIDesc
,string ShortDesc
,
989 const vector
<struct IndexTarget
*>* IndexTargets
,
990 indexRecords
* MetaIndexParser
) :
991 Item(Owner
), RealURI(URI
), SigFile(SigFile
), IndexTargets(IndexTargets
),
992 MetaIndexParser(MetaIndexParser
), AuthPass(false), IMSHit(false)
994 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
995 DestFile
+= URItoFileName(URI
);
998 Desc
.Description
= URIDesc
;
1000 Desc
.ShortDesc
= ShortDesc
;
1006 // pkgAcqMetaIndex::Custom600Headers - Insert custom request headers /*{{{*/
1007 // ---------------------------------------------------------------------
1008 /* The only header we use is the last-modified header. */
1009 string
pkgAcqMetaIndex::Custom600Headers()
1011 string Final
= _config
->FindDir("Dir::State::lists");
1012 Final
+= URItoFileName(RealURI
);
1015 if (stat(Final
.c_str(),&Buf
) != 0)
1016 return "\nIndex-File: true";
1018 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
1021 void pkgAcqMetaIndex::Done(string Message
,unsigned long Size
,string Hash
, /*{{{*/
1022 pkgAcquire::MethodConfig
*Cfg
)
1024 Item::Done(Message
,Size
,Hash
,Cfg
);
1026 // MetaIndexes are done in two passes: one to download the
1027 // metaindex with an appropriate method, and a second to verify it
1028 // with the gpgv method
1030 if (AuthPass
== true)
1034 // all cool, move Release file into place
1037 string FinalFile
= _config
->FindDir("Dir::State::lists");
1038 FinalFile
+= URItoFileName(RealURI
);
1039 Rename(DestFile
,FinalFile
);
1040 chmod(FinalFile
.c_str(),0644);
1041 DestFile
= FinalFile
;
1045 RetrievalDone(Message
);
1047 // Still more retrieving to do
1052 // There was no signature file, so we are finished. Download
1053 // the indexes without verification.
1054 QueueIndexes(false);
1058 // There was a signature file, so pass it to gpgv for
1061 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
1062 std::cerr
<< "Metaindex acquired, queueing gpg verification ("
1063 << SigFile
<< "," << DestFile
<< ")\n";
1065 Desc
.URI
= "gpgv:" + SigFile
;
1072 void pkgAcqMetaIndex::RetrievalDone(string Message
) /*{{{*/
1074 // We have just finished downloading a Release file (it is not
1077 string FileName
= LookupTag(Message
,"Filename");
1078 if (FileName
.empty() == true)
1081 ErrorText
= "Method gave a blank filename";
1085 if (FileName
!= DestFile
)
1088 Desc
.URI
= "copy:" + FileName
;
1093 // make sure to verify against the right file on I-M-S hit
1094 IMSHit
= StringToBool(LookupTag(Message
,"IMS-Hit"),false);
1097 string FinalFile
= _config
->FindDir("Dir::State::lists");
1098 FinalFile
+= URItoFileName(RealURI
);
1099 DestFile
= FinalFile
;
1104 void pkgAcqMetaIndex::AuthDone(string Message
) /*{{{*/
1106 // At this point, the gpgv method has succeeded, so there is a
1107 // valid signature from a key in the trusted keyring. We
1108 // perform additional verification of its contents, and use them
1109 // to verify the indexes we are about to download
1111 if (!MetaIndexParser
->Load(DestFile
))
1113 Status
= StatAuthError
;
1114 ErrorText
= MetaIndexParser
->ErrorText
;
1118 if (!VerifyVendor(Message
))
1123 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
1124 std::cerr
<< "Signature verification succeeded: "
1125 << DestFile
<< std::endl
;
1127 // Download further indexes with verification
1130 // Done, move signature file into position
1131 string VerifiedSigFile
= _config
->FindDir("Dir::State::lists") +
1132 URItoFileName(RealURI
) + ".gpg";
1133 Rename(SigFile
,VerifiedSigFile
);
1134 chmod(VerifiedSigFile
.c_str(),0644);
1137 void pkgAcqMetaIndex::QueueIndexes(bool verify
) /*{{{*/
1139 for (vector
<struct IndexTarget
*>::const_iterator Target
= IndexTargets
->begin();
1140 Target
!= IndexTargets
->end();
1143 HashString ExpectedIndexHash
;
1146 const indexRecords::checkSum
*Record
= MetaIndexParser
->Lookup((*Target
)->MetaKey
);
1149 Status
= StatAuthError
;
1150 ErrorText
= "Unable to find expected entry "
1151 + (*Target
)->MetaKey
+ " in Meta-index file (malformed Release file?)";
1154 ExpectedIndexHash
= Record
->Hash
;
1155 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
1157 std::cerr
<< "Queueing: " << (*Target
)->URI
<< std::endl
;
1158 std::cerr
<< "Expected Hash: " << ExpectedIndexHash
.toStr() << std::endl
;
1160 if (ExpectedIndexHash
.empty())
1162 Status
= StatAuthError
;
1163 ErrorText
= "Unable to find hash sum for "
1164 + (*Target
)->MetaKey
+ " in Meta-index file";
1169 /* Queue Packages file (either diff or full packages files, depending
1170 on the users option) - we also check if the PDiff Index file is listed
1171 in the Meta-Index file. Ideal would be if pkgAcqDiffIndex would test this
1172 instead, but passing the required info to it is to much hassle */
1173 if(_config
->FindB("Acquire::PDiffs",true) == true && (verify
== false ||
1174 MetaIndexParser
->Exists(string((*Target
)->MetaKey
).append(".diff/Index")) == true))
1175 new pkgAcqDiffIndex(Owner
, (*Target
)->URI
, (*Target
)->Description
,
1176 (*Target
)->ShortDesc
, ExpectedIndexHash
);
1178 new pkgAcqIndex(Owner
, (*Target
)->URI
, (*Target
)->Description
,
1179 (*Target
)->ShortDesc
, ExpectedIndexHash
);
1183 bool pkgAcqMetaIndex::VerifyVendor(string Message
) /*{{{*/
1185 // // Maybe this should be made available from above so we don't have
1186 // // to read and parse it every time?
1187 // pkgVendorList List;
1188 // List.ReadMainList();
1190 // const Vendor* Vndr = NULL;
1191 // for (std::vector<string>::const_iterator I = GPGVOutput.begin(); I != GPGVOutput.end(); I++)
1193 // string::size_type pos = (*I).find("VALIDSIG ");
1194 // if (_config->FindB("Debug::Vendor", false))
1195 // std::cerr << "Looking for VALIDSIG in \"" << (*I) << "\": pos " << pos
1197 // if (pos != std::string::npos)
1199 // string Fingerprint = (*I).substr(pos+sizeof("VALIDSIG"));
1200 // if (_config->FindB("Debug::Vendor", false))
1201 // std::cerr << "Looking for \"" << Fingerprint << "\" in vendor..." <<
1203 // Vndr = List.FindVendor(Fingerprint) != "";
1204 // if (Vndr != NULL);
1208 string::size_type pos
;
1210 // check for missing sigs (that where not fatal because otherwise we had
1213 string msg
= _("There is no public key available for the "
1214 "following key IDs:\n");
1215 pos
= Message
.find("NO_PUBKEY ");
1216 if (pos
!= std::string::npos
)
1218 string::size_type start
= pos
+strlen("NO_PUBKEY ");
1219 string Fingerprint
= Message
.substr(start
, Message
.find("\n")-start
);
1220 missingkeys
+= (Fingerprint
);
1222 if(!missingkeys
.empty())
1223 _error
->Warning("%s", string(msg
+missingkeys
).c_str());
1225 string Transformed
= MetaIndexParser
->GetExpectedDist();
1227 if (Transformed
== "../project/experimental")
1229 Transformed
= "experimental";
1232 pos
= Transformed
.rfind('/');
1233 if (pos
!= string::npos
)
1235 Transformed
= Transformed
.substr(0, pos
);
1238 if (Transformed
== ".")
1243 if (_config
->FindB("Acquire::Check-Valid-Until", true) == true &&
1244 MetaIndexParser
->GetValidUntil() > 0) {
1245 time_t const invalid_since
= time(NULL
) - MetaIndexParser
->GetValidUntil();
1246 if (invalid_since
> 0)
1247 // TRANSLATOR: The first %s is the URL of the bad Release file, the second is
1248 // the time since then the file is invalid - formated in the same way as in
1249 // the download progress display (e.g. 7d 3h 42min 1s)
1250 return _error
->Error(_("Release file expired, ignoring %s (invalid since %s)"),
1251 RealURI
.c_str(), TimeToStr(invalid_since
).c_str());
1254 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
1256 std::cerr
<< "Got Codename: " << MetaIndexParser
->GetDist() << std::endl
;
1257 std::cerr
<< "Expecting Dist: " << MetaIndexParser
->GetExpectedDist() << std::endl
;
1258 std::cerr
<< "Transformed Dist: " << Transformed
<< std::endl
;
1261 if (MetaIndexParser
->CheckDist(Transformed
) == false)
1263 // This might become fatal one day
1264 // Status = StatAuthError;
1265 // ErrorText = "Conflicting distribution; expected "
1266 // + MetaIndexParser->GetExpectedDist() + " but got "
1267 // + MetaIndexParser->GetDist();
1269 if (!Transformed
.empty())
1271 _error
->Warning(_("Conflicting distribution: %s (expected %s but got %s)"),
1272 Desc
.Description
.c_str(),
1273 Transformed
.c_str(),
1274 MetaIndexParser
->GetDist().c_str());
1281 // pkgAcqMetaIndex::Failed - no Release file present or no signature file present /*{{{*/
1282 // ---------------------------------------------------------------------
1284 void pkgAcqMetaIndex::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
1286 if (AuthPass
== true)
1288 // gpgv method failed, if we have a good signature
1289 string LastGoodSigFile
= _config
->FindDir("Dir::State::lists") +
1290 "partial/" + URItoFileName(RealURI
) + ".gpg.reverify";
1291 if(FileExists(LastGoodSigFile
))
1293 string VerifiedSigFile
= _config
->FindDir("Dir::State::lists") +
1294 URItoFileName(RealURI
) + ".gpg";
1295 Rename(LastGoodSigFile
,VerifiedSigFile
);
1296 Status
= StatTransientNetworkError
;
1297 _error
->Warning(_("A error occurred during the signature "
1298 "verification. The repository is not updated "
1299 "and the previous index files will be used."
1300 "GPG error: %s: %s\n"),
1301 Desc
.Description
.c_str(),
1302 LookupTag(Message
,"Message").c_str());
1303 RunScripts("APT::Update::Auth-Failure");
1306 _error
->Warning(_("GPG error: %s: %s"),
1307 Desc
.Description
.c_str(),
1308 LookupTag(Message
,"Message").c_str());
1310 // gpgv method failed
1311 ReportMirrorFailure("GPGFailure");
1314 // No Release file was present, or verification failed, so fall
1315 // back to queueing Packages files without verification
1316 QueueIndexes(false);
1319 // AcqArchive::AcqArchive - Constructor /*{{{*/
1320 // ---------------------------------------------------------------------
1321 /* This just sets up the initial fetch environment and queues the first
1323 pkgAcqArchive::pkgAcqArchive(pkgAcquire
*Owner
,pkgSourceList
*Sources
,
1324 pkgRecords
*Recs
,pkgCache::VerIterator
const &Version
,
1325 string
&StoreFilename
) :
1326 Item(Owner
), Version(Version
), Sources(Sources
), Recs(Recs
),
1327 StoreFilename(StoreFilename
), Vf(Version
.FileList()),
1330 Retries
= _config
->FindI("Acquire::Retries",0);
1332 if (Version
.Arch() == 0)
1334 _error
->Error(_("I wasn't able to locate a file for the %s package. "
1335 "This might mean you need to manually fix this package. "
1336 "(due to missing arch)"),
1337 Version
.ParentPkg().Name());
1341 /* We need to find a filename to determine the extension. We make the
1342 assumption here that all the available sources for this version share
1343 the same extension.. */
1344 // Skip not source sources, they do not have file fields.
1345 for (; Vf
.end() == false; Vf
++)
1347 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) != 0)
1352 // Does not really matter here.. we are going to fail out below
1353 if (Vf
.end() != true)
1355 // If this fails to get a file name we will bomb out below.
1356 pkgRecords::Parser
&Parse
= Recs
->Lookup(Vf
);
1357 if (_error
->PendingError() == true)
1360 // Generate the final file name as: package_version_arch.foo
1361 StoreFilename
= QuoteString(Version
.ParentPkg().Name(),"_:") + '_' +
1362 QuoteString(Version
.VerStr(),"_:") + '_' +
1363 QuoteString(Version
.Arch(),"_:.") +
1364 "." + flExtension(Parse
.FileName());
1367 // check if we have one trusted source for the package. if so, switch
1368 // to "TrustedOnly" mode
1369 for (pkgCache::VerFileIterator i
= Version
.FileList(); i
.end() == false; i
++)
1371 pkgIndexFile
*Index
;
1372 if (Sources
->FindIndex(i
.File(),Index
) == false)
1374 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
1376 std::cerr
<< "Checking index: " << Index
->Describe()
1377 << "(Trusted=" << Index
->IsTrusted() << ")\n";
1379 if (Index
->IsTrusted()) {
1385 // "allow-unauthenticated" restores apts old fetching behaviour
1386 // that means that e.g. unauthenticated file:// uris are higher
1387 // priority than authenticated http:// uris
1388 if (_config
->FindB("APT::Get::AllowUnauthenticated",false) == true)
1392 if (QueueNext() == false && _error
->PendingError() == false)
1393 _error
->Error(_("I wasn't able to locate file for the %s package. "
1394 "This might mean you need to manually fix this package."),
1395 Version
.ParentPkg().Name());
1398 // AcqArchive::QueueNext - Queue the next file source /*{{{*/
1399 // ---------------------------------------------------------------------
1400 /* This queues the next available file version for download. It checks if
1401 the archive is already available in the cache and stashs the MD5 for
1403 bool pkgAcqArchive::QueueNext()
1405 string
const ForceHash
= _config
->Find("Acquire::ForceHash");
1406 for (; Vf
.end() == false; Vf
++)
1408 // Ignore not source sources
1409 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) != 0)
1412 // Try to cross match against the source list
1413 pkgIndexFile
*Index
;
1414 if (Sources
->FindIndex(Vf
.File(),Index
) == false)
1417 // only try to get a trusted package from another source if that source
1419 if(Trusted
&& !Index
->IsTrusted())
1422 // Grab the text package record
1423 pkgRecords::Parser
&Parse
= Recs
->Lookup(Vf
);
1424 if (_error
->PendingError() == true)
1427 string PkgFile
= Parse
.FileName();
1428 if (ForceHash
.empty() == false)
1430 if(stringcasecmp(ForceHash
, "sha256") == 0)
1431 ExpectedHash
= HashString("SHA256", Parse
.SHA256Hash());
1432 else if (stringcasecmp(ForceHash
, "sha1") == 0)
1433 ExpectedHash
= HashString("SHA1", Parse
.SHA1Hash());
1435 ExpectedHash
= HashString("MD5Sum", Parse
.MD5Hash());
1440 if ((Hash
= Parse
.SHA256Hash()).empty() == false)
1441 ExpectedHash
= HashString("SHA256", Hash
);
1442 else if ((Hash
= Parse
.SHA1Hash()).empty() == false)
1443 ExpectedHash
= HashString("SHA1", Hash
);
1445 ExpectedHash
= HashString("MD5Sum", Parse
.MD5Hash());
1447 if (PkgFile
.empty() == true)
1448 return _error
->Error(_("The package index files are corrupted. No Filename: "
1449 "field for package %s."),
1450 Version
.ParentPkg().Name());
1452 Desc
.URI
= Index
->ArchiveURI(PkgFile
);
1453 Desc
.Description
= Index
->ArchiveInfo(Version
);
1455 Desc
.ShortDesc
= Version
.ParentPkg().Name();
1457 // See if we already have the file. (Legacy filenames)
1458 FileSize
= Version
->Size
;
1459 string FinalFile
= _config
->FindDir("Dir::Cache::Archives") + flNotDir(PkgFile
);
1461 if (stat(FinalFile
.c_str(),&Buf
) == 0)
1463 // Make sure the size matches
1464 if ((unsigned)Buf
.st_size
== Version
->Size
)
1469 StoreFilename
= DestFile
= FinalFile
;
1473 /* Hmm, we have a file and its size does not match, this means it is
1474 an old style mismatched arch */
1475 unlink(FinalFile
.c_str());
1478 // Check it again using the new style output filenames
1479 FinalFile
= _config
->FindDir("Dir::Cache::Archives") + flNotDir(StoreFilename
);
1480 if (stat(FinalFile
.c_str(),&Buf
) == 0)
1482 // Make sure the size matches
1483 if ((unsigned)Buf
.st_size
== Version
->Size
)
1488 StoreFilename
= DestFile
= FinalFile
;
1492 /* Hmm, we have a file and its size does not match, this shouldnt
1494 unlink(FinalFile
.c_str());
1497 DestFile
= _config
->FindDir("Dir::Cache::Archives") + "partial/" + flNotDir(StoreFilename
);
1499 // Check the destination file
1500 if (stat(DestFile
.c_str(),&Buf
) == 0)
1502 // Hmm, the partial file is too big, erase it
1503 if ((unsigned)Buf
.st_size
> Version
->Size
)
1504 unlink(DestFile
.c_str());
1506 PartialSize
= Buf
.st_size
;
1511 Desc
.URI
= Index
->ArchiveURI(PkgFile
);
1512 Desc
.Description
= Index
->ArchiveInfo(Version
);
1514 Desc
.ShortDesc
= Version
.ParentPkg().Name();
1523 // AcqArchive::Done - Finished fetching /*{{{*/
1524 // ---------------------------------------------------------------------
1526 void pkgAcqArchive::Done(string Message
,unsigned long Size
,string CalcHash
,
1527 pkgAcquire::MethodConfig
*Cfg
)
1529 Item::Done(Message
,Size
,CalcHash
,Cfg
);
1532 if (Size
!= Version
->Size
)
1535 ErrorText
= _("Size mismatch");
1540 if(ExpectedHash
.toStr() != CalcHash
)
1543 ErrorText
= _("Hash Sum mismatch");
1544 if(FileExists(DestFile
))
1545 Rename(DestFile
,DestFile
+ ".FAILED");
1549 // Grab the output filename
1550 string FileName
= LookupTag(Message
,"Filename");
1551 if (FileName
.empty() == true)
1554 ErrorText
= "Method gave a blank filename";
1560 // Reference filename
1561 if (FileName
!= DestFile
)
1563 StoreFilename
= DestFile
= FileName
;
1568 // Done, move it into position
1569 string FinalFile
= _config
->FindDir("Dir::Cache::Archives");
1570 FinalFile
+= flNotDir(StoreFilename
);
1571 Rename(DestFile
,FinalFile
);
1573 StoreFilename
= DestFile
= FinalFile
;
1577 // AcqArchive::Failed - Failure handler /*{{{*/
1578 // ---------------------------------------------------------------------
1579 /* Here we try other sources */
1580 void pkgAcqArchive::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
1582 ErrorText
= LookupTag(Message
,"Message");
1584 /* We don't really want to retry on failed media swaps, this prevents
1585 that. An interesting observation is that permanent failures are not
1587 if (Cnf
->Removable
== true &&
1588 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
1590 // Vf = Version.FileList();
1591 while (Vf
.end() == false) Vf
++;
1592 StoreFilename
= string();
1593 Item::Failed(Message
,Cnf
);
1597 if (QueueNext() == false)
1599 // This is the retry counter
1601 Cnf
->LocalOnly
== false &&
1602 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
1605 Vf
= Version
.FileList();
1606 if (QueueNext() == true)
1610 StoreFilename
= string();
1611 Item::Failed(Message
,Cnf
);
1615 // AcqArchive::IsTrusted - Determine whether this archive comes from a trusted source /*{{{*/
1616 // ---------------------------------------------------------------------
1617 bool pkgAcqArchive::IsTrusted()
1622 // AcqArchive::Finished - Fetching has finished, tidy up /*{{{*/
1623 // ---------------------------------------------------------------------
1625 void pkgAcqArchive::Finished()
1627 if (Status
== pkgAcquire::Item::StatDone
&&
1630 StoreFilename
= string();
1633 // AcqFile::pkgAcqFile - Constructor /*{{{*/
1634 // ---------------------------------------------------------------------
1635 /* The file is added to the queue */
1636 pkgAcqFile::pkgAcqFile(pkgAcquire
*Owner
,string URI
,string Hash
,
1637 unsigned long Size
,string Dsc
,string ShortDesc
,
1638 const string
&DestDir
, const string
&DestFilename
,
1640 Item(Owner
), ExpectedHash(Hash
), IsIndexFile(IsIndexFile
)
1642 Retries
= _config
->FindI("Acquire::Retries",0);
1644 if(!DestFilename
.empty())
1645 DestFile
= DestFilename
;
1646 else if(!DestDir
.empty())
1647 DestFile
= DestDir
+ "/" + flNotDir(URI
);
1649 DestFile
= flNotDir(URI
);
1653 Desc
.Description
= Dsc
;
1656 // Set the short description to the archive component
1657 Desc
.ShortDesc
= ShortDesc
;
1659 // Get the transfer sizes
1662 if (stat(DestFile
.c_str(),&Buf
) == 0)
1664 // Hmm, the partial file is too big, erase it
1665 if ((unsigned)Buf
.st_size
> Size
)
1666 unlink(DestFile
.c_str());
1668 PartialSize
= Buf
.st_size
;
1674 // AcqFile::Done - Item downloaded OK /*{{{*/
1675 // ---------------------------------------------------------------------
1677 void pkgAcqFile::Done(string Message
,unsigned long Size
,string CalcHash
,
1678 pkgAcquire::MethodConfig
*Cnf
)
1680 Item::Done(Message
,Size
,CalcHash
,Cnf
);
1683 if(!ExpectedHash
.empty() && ExpectedHash
.toStr() != CalcHash
)
1686 ErrorText
= "Hash Sum mismatch";
1687 Rename(DestFile
,DestFile
+ ".FAILED");
1691 string FileName
= LookupTag(Message
,"Filename");
1692 if (FileName
.empty() == true)
1695 ErrorText
= "Method gave a blank filename";
1701 // The files timestamp matches
1702 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true)
1705 // We have to copy it into place
1706 if (FileName
!= DestFile
)
1709 if (_config
->FindB("Acquire::Source-Symlinks",true) == false ||
1710 Cnf
->Removable
== true)
1712 Desc
.URI
= "copy:" + FileName
;
1717 // Erase the file if it is a symlink so we can overwrite it
1719 if (lstat(DestFile
.c_str(),&St
) == 0)
1721 if (S_ISLNK(St
.st_mode
) != 0)
1722 unlink(DestFile
.c_str());
1726 if (symlink(FileName
.c_str(),DestFile
.c_str()) != 0)
1728 ErrorText
= "Link to " + DestFile
+ " failure ";
1735 // AcqFile::Failed - Failure handler /*{{{*/
1736 // ---------------------------------------------------------------------
1737 /* Here we try other sources */
1738 void pkgAcqFile::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
1740 ErrorText
= LookupTag(Message
,"Message");
1742 // This is the retry counter
1744 Cnf
->LocalOnly
== false &&
1745 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
1752 Item::Failed(Message
,Cnf
);
1755 // AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
1756 // ---------------------------------------------------------------------
1757 /* The only header we use is the last-modified header. */
1758 string
pkgAcqFile::Custom600Headers()
1761 return "\nIndex-File: true";