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 /*{{{*/
18 #include <apt-pkg/acquire-item.h>
19 #include <apt-pkg/configuration.h>
20 #include <apt-pkg/aptconfiguration.h>
21 #include <apt-pkg/sourcelist.h>
22 #include <apt-pkg/error.h>
23 #include <apt-pkg/strutl.h>
24 #include <apt-pkg/fileutl.h>
25 #include <apt-pkg/sha1.h>
26 #include <apt-pkg/tagfile.h>
27 #include <apt-pkg/indexrecords.h>
28 #include <apt-pkg/acquire.h>
29 #include <apt-pkg/hashes.h>
30 #include <apt-pkg/indexfile.h>
31 #include <apt-pkg/pkgcache.h>
32 #include <apt-pkg/cacheiterators.h>
33 #include <apt-pkg/pkgrecords.h>
53 // Acquire::Item::Item - Constructor /*{{{*/
54 // ---------------------------------------------------------------------
56 pkgAcquire::Item::Item(pkgAcquire
*Owner
) : Owner(Owner
), FileSize(0),
57 PartialSize(0), Mode(0), ID(0), Complete(false),
58 Local(false), QueueCounter(0),
59 ExpectedAdditionalItems(0)
65 // Acquire::Item::~Item - Destructor /*{{{*/
66 // ---------------------------------------------------------------------
68 pkgAcquire::Item::~Item()
73 // Acquire::Item::Failed - Item failed to download /*{{{*/
74 // ---------------------------------------------------------------------
75 /* We return to an idle state if there are still other queues that could
77 void pkgAcquire::Item::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
80 ErrorText
= LookupTag(Message
,"Message");
81 UsedMirror
= LookupTag(Message
,"UsedMirror");
82 if (QueueCounter
<= 1)
84 /* This indicates that the file is not available right now but might
85 be sometime later. If we do a retry cycle then this should be
87 if (Cnf
->LocalOnly
== true &&
88 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
99 // report mirror failure back to LP if we actually use a mirror
100 string FailReason
= LookupTag(Message
, "FailReason");
101 if(FailReason
.size() != 0)
102 ReportMirrorFailure(FailReason
);
104 ReportMirrorFailure(ErrorText
);
107 // Acquire::Item::Start - Item has begun to download /*{{{*/
108 // ---------------------------------------------------------------------
109 /* Stash status and the file size. Note that setting Complete means
110 sub-phases of the acquire process such as decompresion are operating */
111 void pkgAcquire::Item::Start(string
/*Message*/,unsigned long long Size
)
113 Status
= StatFetching
;
114 if (FileSize
== 0 && Complete
== false)
118 // Acquire::Item::Done - Item downloaded OK /*{{{*/
119 // ---------------------------------------------------------------------
121 void pkgAcquire::Item::Done(string Message
,unsigned long long Size
,string
/*Hash*/,
122 pkgAcquire::MethodConfig
* /*Cnf*/)
124 // We just downloaded something..
125 string FileName
= LookupTag(Message
,"Filename");
126 UsedMirror
= LookupTag(Message
,"UsedMirror");
127 if (Complete
== false && !Local
&& FileName
== DestFile
)
130 Owner
->Log
->Fetched(Size
,atoi(LookupTag(Message
,"Resume-Point","0").c_str()));
136 ErrorText
= string();
137 Owner
->Dequeue(this);
140 // Acquire::Item::Rename - Rename a file /*{{{*/
141 // ---------------------------------------------------------------------
142 /* This helper function is used by a lot of item methods as their final
144 void pkgAcquire::Item::Rename(string From
,string To
)
146 if (rename(From
.c_str(),To
.c_str()) != 0)
149 snprintf(S
,sizeof(S
),_("rename failed, %s (%s -> %s)."),strerror(errno
),
150 From
.c_str(),To
.c_str());
156 bool pkgAcquire::Item::RenameOnError(pkgAcquire::Item::RenameOnErrorState
const error
)/*{{{*/
158 if(FileExists(DestFile
))
159 Rename(DestFile
, DestFile
+ ".FAILED");
163 case HashSumMismatch
:
164 ErrorText
= _("Hash Sum mismatch");
165 Status
= StatAuthError
;
166 ReportMirrorFailure("HashChecksumFailure");
169 ErrorText
= _("Size mismatch");
170 Status
= StatAuthError
;
171 ReportMirrorFailure("SizeFailure");
174 ErrorText
= _("Invalid file format");
176 // do not report as usually its not the mirrors fault, but Portal/Proxy
182 // Acquire::Item::ReportMirrorFailure /*{{{*/
183 // ---------------------------------------------------------------------
184 void pkgAcquire::Item::ReportMirrorFailure(string FailCode
)
186 // we only act if a mirror was used at all
187 if(UsedMirror
.empty())
190 std::cerr
<< "\nReportMirrorFailure: "
192 << " Uri: " << DescURI()
194 << FailCode
<< std::endl
;
196 const char *Args
[40];
198 string report
= _config
->Find("Methods::Mirror::ProblemReporting",
199 "/usr/lib/apt/apt-report-mirror-failure");
200 if(!FileExists(report
))
202 Args
[i
++] = report
.c_str();
203 Args
[i
++] = UsedMirror
.c_str();
204 Args
[i
++] = DescURI().c_str();
205 Args
[i
++] = FailCode
.c_str();
207 pid_t pid
= ExecFork();
210 _error
->Error("ReportMirrorFailure Fork failed");
215 execvp(Args
[0], (char**)Args
);
216 std::cerr
<< "Could not exec " << Args
[0] << std::endl
;
219 if(!ExecWait(pid
, "report-mirror-failure"))
221 _error
->Warning("Couldn't report problem to '%s'",
222 _config
->Find("Methods::Mirror::ProblemReporting").c_str());
226 // AcqSubIndex::AcqSubIndex - Constructor /*{{{*/
227 // ---------------------------------------------------------------------
228 /* Get a sub-index file based on checksums from a 'master' file and
229 possibly query additional files */
230 pkgAcqSubIndex::pkgAcqSubIndex(pkgAcquire
*Owner
, string
const &URI
,
231 string
const &URIDesc
, string
const &ShortDesc
,
232 HashString
const &ExpectedHash
)
233 : Item(Owner
), ExpectedHash(ExpectedHash
)
235 /* XXX: Beware: Currently this class does nothing (of value) anymore ! */
236 Debug
= _config
->FindB("Debug::pkgAcquire::SubIndex",false);
238 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
239 DestFile
+= URItoFileName(URI
);
242 Desc
.Description
= URIDesc
;
244 Desc
.ShortDesc
= ShortDesc
;
249 std::clog
<< "pkgAcqSubIndex: " << Desc
.URI
<< std::endl
;
252 // AcqSubIndex::Custom600Headers - Insert custom request headers /*{{{*/
253 // ---------------------------------------------------------------------
254 /* The only header we use is the last-modified header. */
255 string
pkgAcqSubIndex::Custom600Headers()
257 string Final
= _config
->FindDir("Dir::State::lists");
258 Final
+= URItoFileName(Desc
.URI
);
261 if (stat(Final
.c_str(),&Buf
) != 0)
262 return "\nIndex-File: true\nFail-Ignore: true\n";
263 return "\nIndex-File: true\nFail-Ignore: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
266 void pkgAcqSubIndex::Failed(string Message
,pkgAcquire::MethodConfig
* /*Cnf*/)/*{{{*/
269 std::clog
<< "pkgAcqSubIndex failed: " << Desc
.URI
<< " with " << Message
<< std::endl
;
275 // No good Index is provided
278 void pkgAcqSubIndex::Done(string Message
,unsigned long long Size
,string Md5Hash
, /*{{{*/
279 pkgAcquire::MethodConfig
*Cnf
)
282 std::clog
<< "pkgAcqSubIndex::Done(): " << Desc
.URI
<< std::endl
;
284 string FileName
= LookupTag(Message
,"Filename");
285 if (FileName
.empty() == true)
288 ErrorText
= "Method gave a blank filename";
292 if (FileName
!= DestFile
)
295 Desc
.URI
= "copy:" + FileName
;
300 Item::Done(Message
,Size
,Md5Hash
,Cnf
);
302 string FinalFile
= _config
->FindDir("Dir::State::lists")+URItoFileName(Desc
.URI
);
304 /* Downloaded invalid transindex => Error (LP: #346386) (Closes: #627642) */
305 indexRecords SubIndexParser
;
306 if (FileExists(DestFile
) == true && !SubIndexParser
.Load(DestFile
)) {
308 ErrorText
= SubIndexParser
.ErrorText
;
312 // success in downloading the index
315 std::clog
<< "Renaming: " << DestFile
<< " -> " << FinalFile
<< std::endl
;
316 Rename(DestFile
,FinalFile
);
317 chmod(FinalFile
.c_str(),0644);
318 DestFile
= FinalFile
;
320 if(ParseIndex(DestFile
) == false)
321 return Failed("", NULL
);
329 bool pkgAcqSubIndex::ParseIndex(string
const &IndexFile
) /*{{{*/
331 indexRecords SubIndexParser
;
332 if (FileExists(IndexFile
) == false || SubIndexParser
.Load(IndexFile
) == false)
334 // so something with the downloaded index
338 // AcqDiffIndex::AcqDiffIndex - Constructor /*{{{*/
339 // ---------------------------------------------------------------------
340 /* Get the DiffIndex file first and see if there are patches available
341 * If so, create a pkgAcqIndexDiffs fetcher that will get and apply the
342 * patches. If anything goes wrong in that process, it will fall back to
343 * the original packages file
345 pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire
*Owner
,
346 string URI
,string URIDesc
,string ShortDesc
,
347 HashString ExpectedHash
)
348 : Item(Owner
), RealURI(URI
), ExpectedHash(ExpectedHash
),
352 Debug
= _config
->FindB("Debug::pkgAcquire::Diffs",false);
354 Desc
.Description
= URIDesc
+ "/DiffIndex";
356 Desc
.ShortDesc
= ShortDesc
;
357 Desc
.URI
= URI
+ ".diff/Index";
359 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
360 DestFile
+= URItoFileName(URI
) + string(".DiffIndex");
363 std::clog
<< "pkgAcqDiffIndex: " << Desc
.URI
<< std::endl
;
365 // look for the current package file
366 CurrentPackagesFile
= _config
->FindDir("Dir::State::lists");
367 CurrentPackagesFile
+= URItoFileName(RealURI
);
369 // FIXME: this file:/ check is a hack to prevent fetching
370 // from local sources. this is really silly, and
371 // should be fixed cleanly as soon as possible
372 if(!FileExists(CurrentPackagesFile
) ||
373 Desc
.URI
.substr(0,strlen("file:/")) == "file:/")
375 // we don't have a pkg file or we don't want to queue
377 std::clog
<< "No index file, local or canceld by user" << std::endl
;
383 std::clog
<< "pkgAcqDiffIndex::pkgAcqDiffIndex(): "
384 << CurrentPackagesFile
<< std::endl
;
390 // AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
391 // ---------------------------------------------------------------------
392 /* The only header we use is the last-modified header. */
393 string
pkgAcqDiffIndex::Custom600Headers()
395 string Final
= _config
->FindDir("Dir::State::lists");
396 Final
+= URItoFileName(RealURI
) + string(".IndexDiff");
399 std::clog
<< "Custom600Header-IMS: " << Final
<< std::endl
;
402 if (stat(Final
.c_str(),&Buf
) != 0)
403 return "\nIndex-File: true";
405 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
408 bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile
) /*{{{*/
411 std::clog
<< "pkgAcqDiffIndex::ParseIndexDiff() " << IndexDiffFile
416 vector
<DiffInfo
> available_patches
;
418 FileFd
Fd(IndexDiffFile
,FileFd::ReadOnly
);
420 if (_error
->PendingError() == true)
423 if(TF
.Step(Tags
) == true)
429 string
const tmp
= Tags
.FindS("SHA1-Current");
430 std::stringstream
ss(tmp
);
431 ss
>> ServerSha1
>> size
;
432 unsigned long const ServerSize
= atol(size
.c_str());
434 FileFd
fd(CurrentPackagesFile
, FileFd::ReadOnly
);
437 string
const local_sha1
= SHA1
.Result();
439 if(local_sha1
== ServerSha1
)
441 // we have the same sha1 as the server so we are done here
443 std::clog
<< "Package file is up-to-date" << std::endl
;
444 // list cleanup needs to know that this file as well as the already
445 // present index is ours, so we create an empty diff to save it for us
446 new pkgAcqIndexDiffs(Owner
, RealURI
, Description
, Desc
.ShortDesc
,
447 ExpectedHash
, ServerSha1
, available_patches
);
453 std::clog
<< "SHA1-Current: " << ServerSha1
<< " and we start at "<< fd
.Name() << " " << fd
.Size() << " " << local_sha1
<< std::endl
;
455 // check the historie and see what patches we need
456 string
const history
= Tags
.FindS("SHA1-History");
457 std::stringstream
hist(history
);
458 while(hist
>> d
.sha1
>> size
>> d
.file
)
460 // read until the first match is found
461 // from that point on, we probably need all diffs
462 if(d
.sha1
== local_sha1
)
464 else if (found
== false)
468 std::clog
<< "Need to get diff: " << d
.file
<< std::endl
;
469 available_patches
.push_back(d
);
472 if (available_patches
.empty() == false)
474 // patching with too many files is rather slow compared to a fast download
475 unsigned long const fileLimit
= _config
->FindI("Acquire::PDiffs::FileLimit", 0);
476 if (fileLimit
!= 0 && fileLimit
< available_patches
.size())
479 std::clog
<< "Need " << available_patches
.size() << " diffs (Limit is " << fileLimit
480 << ") so fallback to complete download" << std::endl
;
484 // see if the patches are too big
485 found
= false; // it was true and it will be true again at the end
486 d
= *available_patches
.begin();
487 string
const firstPatch
= d
.file
;
488 unsigned long patchesSize
= 0;
489 std::stringstream
patches(Tags
.FindS("SHA1-Patches"));
490 while(patches
>> d
.sha1
>> size
>> d
.file
)
492 if (firstPatch
== d
.file
)
494 else if (found
== false)
497 patchesSize
+= atol(size
.c_str());
499 unsigned long const sizeLimit
= ServerSize
* _config
->FindI("Acquire::PDiffs::SizeLimit", 100);
500 if (sizeLimit
> 0 && (sizeLimit
/100) < patchesSize
)
503 std::clog
<< "Need " << patchesSize
<< " bytes (Limit is " << sizeLimit
/100
504 << ") so fallback to complete download" << std::endl
;
510 // we have something, queue the next diff
514 string::size_type
const last_space
= Description
.rfind(" ");
515 if(last_space
!= string::npos
)
516 Description
.erase(last_space
, Description
.size()-last_space
);
518 /* decide if we should download patches one by one or in one go:
519 The first is good if the server merges patches, but many don't so client
520 based merging can be attempt in which case the second is better.
521 "bad things" will happen if patches are merged on the server,
522 but client side merging is attempt as well */
523 bool pdiff_merge
= _config
->FindB("Acquire::PDiffs::Merge", true);
524 if (pdiff_merge
== true)
526 // reprepro adds this flag if it has merged patches on the server
527 std::string
const precedence
= Tags
.FindS("X-Patch-Precedence");
528 pdiff_merge
= (precedence
!= "merged");
531 if (pdiff_merge
== false)
532 new pkgAcqIndexDiffs(Owner
, RealURI
, Description
, Desc
.ShortDesc
,
533 ExpectedHash
, ServerSha1
, available_patches
);
536 std::vector
<pkgAcqIndexMergeDiffs
*> *diffs
= new std::vector
<pkgAcqIndexMergeDiffs
*>(available_patches
.size());
537 for(size_t i
= 0; i
< available_patches
.size(); ++i
)
538 (*diffs
)[i
] = new pkgAcqIndexMergeDiffs(Owner
, RealURI
, Description
, Desc
.ShortDesc
, ExpectedHash
,
539 available_patches
[i
], diffs
);
549 // Nothing found, report and return false
550 // Failing here is ok, if we return false later, the full
551 // IndexFile is queued
553 std::clog
<< "Can't find a patch in the index file" << std::endl
;
557 void pkgAcqDiffIndex::Failed(string Message
,pkgAcquire::MethodConfig
* /*Cnf*/)/*{{{*/
560 std::clog
<< "pkgAcqDiffIndex failed: " << Desc
.URI
<< " with " << Message
<< std::endl
561 << "Falling back to normal index file acquire" << std::endl
;
563 new pkgAcqIndex(Owner
, RealURI
, Description
, Desc
.ShortDesc
,
571 void pkgAcqDiffIndex::Done(string Message
,unsigned long long Size
,string Md5Hash
, /*{{{*/
572 pkgAcquire::MethodConfig
*Cnf
)
575 std::clog
<< "pkgAcqDiffIndex::Done(): " << Desc
.URI
<< std::endl
;
577 Item::Done(Message
,Size
,Md5Hash
,Cnf
);
580 FinalFile
= _config
->FindDir("Dir::State::lists")+URItoFileName(RealURI
);
582 // success in downloading the index
584 FinalFile
+= string(".IndexDiff");
586 std::clog
<< "Renaming: " << DestFile
<< " -> " << FinalFile
588 Rename(DestFile
,FinalFile
);
589 chmod(FinalFile
.c_str(),0644);
590 DestFile
= FinalFile
;
592 if(!ParseDiffIndex(DestFile
))
593 return Failed("", NULL
);
601 // AcqIndexDiffs::AcqIndexDiffs - Constructor /*{{{*/
602 // ---------------------------------------------------------------------
603 /* The package diff is added to the queue. one object is constructed
604 * for each diff and the index
606 pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire
*Owner
,
607 string URI
,string URIDesc
,string ShortDesc
,
608 HashString ExpectedHash
,
610 vector
<DiffInfo
> diffs
)
611 : Item(Owner
), RealURI(URI
), ExpectedHash(ExpectedHash
),
612 available_patches(diffs
), ServerSha1(ServerSha1
)
615 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
616 DestFile
+= URItoFileName(URI
);
618 Debug
= _config
->FindB("Debug::pkgAcquire::Diffs",false);
620 Description
= URIDesc
;
622 Desc
.ShortDesc
= ShortDesc
;
624 if(available_patches
.empty() == true)
626 // we are done (yeah!)
632 State
= StateFetchDiff
;
637 void pkgAcqIndexDiffs::Failed(string Message
,pkgAcquire::MethodConfig
* /*Cnf*/)/*{{{*/
640 std::clog
<< "pkgAcqIndexDiffs failed: " << Desc
.URI
<< " with " << Message
<< std::endl
641 << "Falling back to normal index file acquire" << std::endl
;
642 new pkgAcqIndex(Owner
, RealURI
, Description
,Desc
.ShortDesc
,
647 // Finish - helper that cleans the item out of the fetcher queue /*{{{*/
648 void pkgAcqIndexDiffs::Finish(bool allDone
)
650 // we restore the original name, this is required, otherwise
651 // the file will be cleaned
654 DestFile
= _config
->FindDir("Dir::State::lists");
655 DestFile
+= URItoFileName(RealURI
);
657 if(!ExpectedHash
.empty() && !ExpectedHash
.VerifyFile(DestFile
))
659 RenameOnError(HashSumMismatch
);
664 // this is for the "real" finish
669 std::clog
<< "\n\nallDone: " << DestFile
<< "\n" << std::endl
;
674 std::clog
<< "Finishing: " << Desc
.URI
<< std::endl
;
681 bool pkgAcqIndexDiffs::QueueNextDiff() /*{{{*/
684 // calc sha1 of the just patched file
685 string FinalFile
= _config
->FindDir("Dir::State::lists");
686 FinalFile
+= URItoFileName(RealURI
);
688 FileFd
fd(FinalFile
, FileFd::ReadOnly
);
691 string local_sha1
= string(SHA1
.Result());
693 std::clog
<< "QueueNextDiff: "
694 << FinalFile
<< " (" << local_sha1
<< ")"<<std::endl
;
696 // final file reached before all patches are applied
697 if(local_sha1
== ServerSha1
)
703 // remove all patches until the next matching patch is found
704 // this requires the Index file to be ordered
705 for(vector
<DiffInfo
>::iterator I
=available_patches
.begin();
706 available_patches
.empty() == false &&
707 I
!= available_patches
.end() &&
708 I
->sha1
!= local_sha1
;
711 available_patches
.erase(I
);
714 // error checking and falling back if no patch was found
715 if(available_patches
.empty() == true)
721 // queue the right diff
722 Desc
.URI
= RealURI
+ ".diff/" + available_patches
[0].file
+ ".gz";
723 Desc
.Description
= Description
+ " " + available_patches
[0].file
+ string(".pdiff");
724 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
725 DestFile
+= URItoFileName(RealURI
+ ".diff/" + available_patches
[0].file
);
728 std::clog
<< "pkgAcqIndexDiffs::QueueNextDiff(): " << Desc
.URI
<< std::endl
;
735 void pkgAcqIndexDiffs::Done(string Message
,unsigned long long Size
,string Md5Hash
, /*{{{*/
736 pkgAcquire::MethodConfig
*Cnf
)
739 std::clog
<< "pkgAcqIndexDiffs::Done(): " << Desc
.URI
<< std::endl
;
741 Item::Done(Message
,Size
,Md5Hash
,Cnf
);
744 FinalFile
= _config
->FindDir("Dir::State::lists")+URItoFileName(RealURI
);
746 // success in downloading a diff, enter ApplyDiff state
747 if(State
== StateFetchDiff
)
750 // rred excepts the patch as $FinalFile.ed
751 Rename(DestFile
,FinalFile
+".ed");
754 std::clog
<< "Sending to rred method: " << FinalFile
<< std::endl
;
756 State
= StateApplyDiff
;
758 Desc
.URI
= "rred:" + FinalFile
;
765 // success in download/apply a diff, queue next (if needed)
766 if(State
== StateApplyDiff
)
768 // remove the just applied patch
769 available_patches
.erase(available_patches
.begin());
770 unlink((FinalFile
+ ".ed").c_str());
775 std::clog
<< "Moving patched file in place: " << std::endl
776 << DestFile
<< " -> " << FinalFile
<< std::endl
;
778 Rename(DestFile
,FinalFile
);
779 chmod(FinalFile
.c_str(),0644);
781 // see if there is more to download
782 if(available_patches
.empty() == false) {
783 new pkgAcqIndexDiffs(Owner
, RealURI
, Description
, Desc
.ShortDesc
,
784 ExpectedHash
, ServerSha1
, available_patches
);
791 // AcqIndexMergeDiffs::AcqIndexMergeDiffs - Constructor /*{{{*/
792 pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire
*Owner
,
793 string
const &URI
, string
const &URIDesc
,
794 string
const &ShortDesc
, HashString
const &ExpectedHash
,
795 DiffInfo
const &patch
,
796 std::vector
<pkgAcqIndexMergeDiffs
*> const * const allPatches
)
797 : Item(Owner
), RealURI(URI
), ExpectedHash(ExpectedHash
),
798 patch(patch
),allPatches(allPatches
), State(StateFetchDiff
)
801 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
802 DestFile
+= URItoFileName(URI
);
804 Debug
= _config
->FindB("Debug::pkgAcquire::Diffs",false);
806 Description
= URIDesc
;
808 Desc
.ShortDesc
= ShortDesc
;
810 Desc
.URI
= RealURI
+ ".diff/" + patch
.file
+ ".gz";
811 Desc
.Description
= Description
+ " " + patch
.file
+ string(".pdiff");
812 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
813 DestFile
+= URItoFileName(RealURI
+ ".diff/" + patch
.file
);
816 std::clog
<< "pkgAcqIndexMergeDiffs: " << Desc
.URI
<< std::endl
;
821 void pkgAcqIndexMergeDiffs::Failed(string Message
,pkgAcquire::MethodConfig
* /*Cnf*/)/*{{{*/
824 std::clog
<< "pkgAcqIndexMergeDiffs failed: " << Desc
.URI
<< " with " << Message
<< std::endl
;
829 // check if we are the first to fail, otherwise we are done here
830 State
= StateDoneDiff
;
831 for (std::vector
<pkgAcqIndexMergeDiffs
*>::const_iterator I
= allPatches
->begin();
832 I
!= allPatches
->end(); ++I
)
833 if ((*I
)->State
== StateErrorDiff
)
836 // first failure means we should fallback
837 State
= StateErrorDiff
;
838 std::clog
<< "Falling back to normal index file acquire" << std::endl
;
839 new pkgAcqIndex(Owner
, RealURI
, Description
,Desc
.ShortDesc
,
843 void pkgAcqIndexMergeDiffs::Done(string Message
,unsigned long long Size
,string Md5Hash
, /*{{{*/
844 pkgAcquire::MethodConfig
*Cnf
)
847 std::clog
<< "pkgAcqIndexMergeDiffs::Done(): " << Desc
.URI
<< std::endl
;
849 Item::Done(Message
,Size
,Md5Hash
,Cnf
);
851 string
const FinalFile
= _config
->FindDir("Dir::State::lists") + URItoFileName(RealURI
);
853 if (State
== StateFetchDiff
)
855 // rred expects the patch as $FinalFile.ed.$patchname.gz
856 Rename(DestFile
, FinalFile
+ ".ed." + patch
.file
+ ".gz");
858 // check if this is the last completed diff
859 State
= StateDoneDiff
;
860 for (std::vector
<pkgAcqIndexMergeDiffs
*>::const_iterator I
= allPatches
->begin();
861 I
!= allPatches
->end(); ++I
)
862 if ((*I
)->State
!= StateDoneDiff
)
865 std::clog
<< "Not the last done diff in the batch: " << Desc
.URI
<< std::endl
;
869 // this is the last completed diff, so we are ready to apply now
870 State
= StateApplyDiff
;
873 std::clog
<< "Sending to rred method: " << FinalFile
<< std::endl
;
876 Desc
.URI
= "rred:" + FinalFile
;
881 // success in download/apply all diffs, clean up
882 else if (State
== StateApplyDiff
)
884 // see if we really got the expected file
885 if(!ExpectedHash
.empty() && !ExpectedHash
.VerifyFile(DestFile
))
887 RenameOnError(HashSumMismatch
);
891 // move the result into place
893 std::clog
<< "Moving patched file in place: " << std::endl
894 << DestFile
<< " -> " << FinalFile
<< std::endl
;
895 Rename(DestFile
, FinalFile
);
896 chmod(FinalFile
.c_str(), 0644);
898 // otherwise lists cleanup will eat the file
899 DestFile
= FinalFile
;
901 // ensure the ed's are gone regardless of list-cleanup
902 for (std::vector
<pkgAcqIndexMergeDiffs
*>::const_iterator I
= allPatches
->begin();
903 I
!= allPatches
->end(); ++I
)
905 std::string patch
= FinalFile
+ ".ed." + (*I
)->patch
.file
+ ".gz";
906 unlink(patch
.c_str());
912 std::clog
<< "allDone: " << DestFile
<< "\n" << std::endl
;
916 // AcqIndex::AcqIndex - Constructor /*{{{*/
917 // ---------------------------------------------------------------------
918 /* The package file is added to the queue and a second class is
919 instantiated to fetch the revision file */
920 pkgAcqIndex::pkgAcqIndex(pkgAcquire
*Owner
,
921 string URI
,string URIDesc
,string ShortDesc
,
922 HashString ExpectedHash
, string comprExt
)
923 : Item(Owner
), RealURI(URI
), ExpectedHash(ExpectedHash
)
925 if(comprExt
.empty() == true)
927 // autoselect the compression method
928 std::vector
<std::string
> types
= APT::Configuration::getCompressionTypes();
929 for (std::vector
<std::string
>::const_iterator t
= types
.begin(); t
!= types
.end(); ++t
)
930 comprExt
.append(*t
).append(" ");
931 if (comprExt
.empty() == false)
932 comprExt
.erase(comprExt
.end()-1);
934 CompressionExtension
= comprExt
;
936 Init(URI
, URIDesc
, ShortDesc
);
938 pkgAcqIndex::pkgAcqIndex(pkgAcquire
*Owner
, IndexTarget
const *Target
,
939 HashString
const &ExpectedHash
, indexRecords
*MetaIndexParser
)
940 : Item(Owner
), RealURI(Target
->URI
), ExpectedHash(ExpectedHash
)
942 // autoselect the compression method
943 std::vector
<std::string
> types
= APT::Configuration::getCompressionTypes();
944 CompressionExtension
= "";
945 if (ExpectedHash
.empty() == false)
947 for (std::vector
<std::string
>::const_iterator t
= types
.begin(); t
!= types
.end(); ++t
)
948 if (*t
== "uncompressed" || MetaIndexParser
->Exists(string(Target
->MetaKey
).append(".").append(*t
)) == true)
949 CompressionExtension
.append(*t
).append(" ");
953 for (std::vector
<std::string
>::const_iterator t
= types
.begin(); t
!= types
.end(); ++t
)
954 CompressionExtension
.append(*t
).append(" ");
956 if (CompressionExtension
.empty() == false)
957 CompressionExtension
.erase(CompressionExtension
.end()-1);
959 // only verify non-optional targets, see acquire-item.h for a FIXME
960 // to make this more flexible
961 if (Target
->IsOptional())
967 indexRecords::checkSum
*Record
= MetaIndexParser
->Lookup(string(Target
->MetaKey
));
969 FileSize
= Record
->Size
;
971 Init(Target
->URI
, Target
->Description
, Target
->ShortDesc
);
974 // AcqIndex::Init - defered Constructor /*{{{*/
975 void pkgAcqIndex::Init(string
const &URI
, string
const &URIDesc
, string
const &ShortDesc
) {
976 Decompression
= false;
979 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
980 DestFile
+= URItoFileName(URI
);
982 std::string
const comprExt
= CompressionExtension
.substr(0, CompressionExtension
.find(' '));
983 if (comprExt
== "uncompressed")
986 Desc
.URI
= URI
+ '.' + comprExt
;
988 Desc
.Description
= URIDesc
;
990 Desc
.ShortDesc
= ShortDesc
;
995 // AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
996 // ---------------------------------------------------------------------
997 /* The only header we use is the last-modified header. */
998 string
pkgAcqIndex::Custom600Headers()
1000 string Final
= _config
->FindDir("Dir::State::lists");
1001 Final
+= URItoFileName(RealURI
);
1002 if (_config
->FindB("Acquire::GzipIndexes",false))
1005 string msg
= "\nIndex-File: true";
1006 // FIXME: this really should use "IndexTarget::IsOptional()" but that
1007 // seems to be difficult without breaking ABI
1008 if (ShortDesc().find("Translation") != 0)
1009 msg
+= "\nFail-Ignore: true";
1011 if (stat(Final
.c_str(),&Buf
) == 0)
1012 msg
+= "\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
1017 void pkgAcqIndex::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
) /*{{{*/
1019 size_t const nextExt
= CompressionExtension
.find(' ');
1020 if (nextExt
!= std::string::npos
)
1022 CompressionExtension
= CompressionExtension
.substr(nextExt
+1);
1023 Init(RealURI
, Desc
.Description
, Desc
.ShortDesc
);
1027 // on decompression failure, remove bad versions in partial/
1028 if (Decompression
&& Erase
) {
1029 string s
= _config
->FindDir("Dir::State::lists") + "partial/";
1030 s
.append(URItoFileName(RealURI
));
1034 Item::Failed(Message
,Cnf
);
1037 // AcqIndex::Done - Finished a fetch /*{{{*/
1038 // ---------------------------------------------------------------------
1039 /* This goes through a number of states.. On the initial fetch the
1040 method could possibly return an alternate filename which points
1041 to the uncompressed version of the file. If this is so the file
1042 is copied into the partial directory. In all other cases the file
1043 is decompressed with a gzip uri. */
1044 void pkgAcqIndex::Done(string Message
,unsigned long long Size
,string Hash
,
1045 pkgAcquire::MethodConfig
*Cfg
)
1047 Item::Done(Message
,Size
,Hash
,Cfg
);
1049 if (Decompression
== true)
1051 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
1053 std::cerr
<< std::endl
<< RealURI
<< ": Computed Hash: " << Hash
;
1054 std::cerr
<< " Expected Hash: " << ExpectedHash
.toStr() << std::endl
;
1057 if (!ExpectedHash
.empty() && ExpectedHash
.toStr() != Hash
)
1059 RenameOnError(HashSumMismatch
);
1063 /* Verify the index file for correctness (all indexes must
1064 * have a Package field) (LP: #346386) (Closes: #627642) */
1067 FileFd
fd(DestFile
, FileFd::ReadOnly
);
1068 // Only test for correctness if the file is not empty (empty is ok)
1069 if (fd
.FileSize() > 0)
1072 pkgTagFile
tag(&fd
);
1074 // all our current indexes have a field 'Package' in each section
1075 if (_error
->PendingError() == true || tag
.Step(sec
) == false || sec
.Exists("Package") == false)
1077 RenameOnError(InvalidFormat
);
1083 // Done, move it into position
1084 string FinalFile
= _config
->FindDir("Dir::State::lists");
1085 FinalFile
+= URItoFileName(RealURI
);
1086 Rename(DestFile
,FinalFile
);
1087 chmod(FinalFile
.c_str(),0644);
1089 /* We restore the original name to DestFile so that the clean operation
1091 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
1092 DestFile
+= URItoFileName(RealURI
);
1094 // Remove the compressed version.
1096 unlink(DestFile
.c_str());
1103 // Handle the unzipd case
1104 string FileName
= LookupTag(Message
,"Alt-Filename");
1105 if (FileName
.empty() == false)
1107 // The files timestamp matches
1108 if (StringToBool(LookupTag(Message
,"Alt-IMS-Hit"),false) == true)
1110 Decompression
= true;
1112 DestFile
+= ".decomp";
1113 Desc
.URI
= "copy:" + FileName
;
1119 FileName
= LookupTag(Message
,"Filename");
1120 if (FileName
.empty() == true)
1123 ErrorText
= "Method gave a blank filename";
1126 std::string
const compExt
= CompressionExtension
.substr(0, CompressionExtension
.find(' '));
1128 // The files timestamp matches
1129 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true) {
1130 if (_config
->FindB("Acquire::GzipIndexes",false) && compExt
== "gz")
1131 // Update DestFile for .gz suffix so that the clean operation keeps it
1136 if (FileName
== DestFile
)
1143 // If we enable compressed indexes and already have gzip, keep it
1144 if (_config
->FindB("Acquire::GzipIndexes",false) && compExt
== "gz" && !Local
) {
1145 string FinalFile
= _config
->FindDir("Dir::State::lists");
1146 FinalFile
+= URItoFileName(RealURI
) + ".gz";
1147 Rename(DestFile
,FinalFile
);
1148 chmod(FinalFile
.c_str(),0644);
1150 // Update DestFile for .gz suffix so that the clean operation keeps it
1151 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
1152 DestFile
+= URItoFileName(RealURI
) + ".gz";
1156 // get the binary name for your used compression type
1157 decompProg
= _config
->Find(string("Acquire::CompressionTypes::").append(compExt
),"");
1158 if(decompProg
.empty() == false);
1159 else if(compExt
== "uncompressed")
1160 decompProg
= "copy";
1162 _error
->Error("Unsupported extension: %s", compExt
.c_str());
1166 Decompression
= true;
1167 DestFile
+= ".decomp";
1168 Desc
.URI
= decompProg
+ ":" + FileName
;
1171 // FIXME: this points to a c++ string that goes out of scope
1172 Mode
= decompProg
.c_str();
1175 // AcqIndexTrans::pkgAcqIndexTrans - Constructor /*{{{*/
1176 // ---------------------------------------------------------------------
1177 /* The Translation file is added to the queue */
1178 pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire
*Owner
,
1179 string URI
,string URIDesc
,string ShortDesc
)
1180 : pkgAcqIndex(Owner
, URI
, URIDesc
, ShortDesc
, HashString(), "")
1183 pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire
*Owner
, IndexTarget
const *Target
,
1184 HashString
const &ExpectedHash
, indexRecords
*MetaIndexParser
)
1185 : pkgAcqIndex(Owner
, Target
, ExpectedHash
, MetaIndexParser
)
1187 // load the filesize
1188 indexRecords::checkSum
*Record
= MetaIndexParser
->Lookup(string(Target
->MetaKey
));
1190 FileSize
= Record
->Size
;
1193 // AcqIndexTrans::Custom600Headers - Insert custom request headers /*{{{*/
1194 // ---------------------------------------------------------------------
1195 string
pkgAcqIndexTrans::Custom600Headers()
1197 string Final
= _config
->FindDir("Dir::State::lists");
1198 Final
+= URItoFileName(RealURI
);
1201 if (stat(Final
.c_str(),&Buf
) != 0)
1202 return "\nFail-Ignore: true\nIndex-File: true";
1203 return "\nFail-Ignore: true\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
1206 // AcqIndexTrans::Failed - Silence failure messages for missing files /*{{{*/
1207 // ---------------------------------------------------------------------
1209 void pkgAcqIndexTrans::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
1211 size_t const nextExt
= CompressionExtension
.find(' ');
1212 if (nextExt
!= std::string::npos
)
1214 CompressionExtension
= CompressionExtension
.substr(nextExt
+1);
1215 Init(RealURI
, Desc
.Description
, Desc
.ShortDesc
);
1220 if (Cnf
->LocalOnly
== true ||
1221 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == false)
1230 Item::Failed(Message
,Cnf
);
1233 pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire
*Owner
, /*{{{*/
1234 string URI
,string URIDesc
,string ShortDesc
,
1235 string MetaIndexURI
, string MetaIndexURIDesc
,
1236 string MetaIndexShortDesc
,
1237 const vector
<IndexTarget
*>* IndexTargets
,
1238 indexRecords
* MetaIndexParser
) :
1239 Item(Owner
), RealURI(URI
), MetaIndexURI(MetaIndexURI
),
1240 MetaIndexURIDesc(MetaIndexURIDesc
), MetaIndexShortDesc(MetaIndexShortDesc
),
1241 MetaIndexParser(MetaIndexParser
), IndexTargets(IndexTargets
)
1243 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
1244 DestFile
+= URItoFileName(URI
);
1246 // remove any partial downloaded sig-file in partial/.
1247 // it may confuse proxies and is too small to warrant a
1248 // partial download anyway
1249 unlink(DestFile
.c_str());
1252 Desc
.Description
= URIDesc
;
1254 Desc
.ShortDesc
= ShortDesc
;
1257 string Final
= _config
->FindDir("Dir::State::lists");
1258 Final
+= URItoFileName(RealURI
);
1259 if (RealFileExists(Final
) == true)
1261 // File was already in place. It needs to be re-downloaded/verified
1262 // because Release might have changed, we do give it a different
1263 // name than DestFile because otherwise the http method will
1264 // send If-Range requests and there are too many broken servers
1265 // out there that do not understand them
1266 LastGoodSig
= DestFile
+".reverify";
1267 Rename(Final
,LastGoodSig
);
1270 // we expect the indextargets + one additional Release file
1271 ExpectedAdditionalItems
= IndexTargets
->size() + 1;
1276 pkgAcqMetaSig::~pkgAcqMetaSig() /*{{{*/
1278 // if the file was never queued undo file-changes done in the constructor
1279 if (QueueCounter
== 1 && Status
== StatIdle
&& FileSize
== 0 && Complete
== false &&
1280 LastGoodSig
.empty() == false)
1282 string
const Final
= _config
->FindDir("Dir::State::lists") + URItoFileName(RealURI
);
1283 if (RealFileExists(Final
) == false && RealFileExists(LastGoodSig
) == true)
1284 Rename(LastGoodSig
, Final
);
1289 // pkgAcqMetaSig::Custom600Headers - Insert custom request headers /*{{{*/
1290 // ---------------------------------------------------------------------
1291 /* The only header we use is the last-modified header. */
1292 string
pkgAcqMetaSig::Custom600Headers()
1295 if (stat(LastGoodSig
.c_str(),&Buf
) != 0)
1296 return "\nIndex-File: true";
1298 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
1301 void pkgAcqMetaSig::Done(string Message
,unsigned long long Size
,string MD5
,
1302 pkgAcquire::MethodConfig
*Cfg
)
1304 Item::Done(Message
,Size
,MD5
,Cfg
);
1306 string FileName
= LookupTag(Message
,"Filename");
1307 if (FileName
.empty() == true)
1310 ErrorText
= "Method gave a blank filename";
1314 if (FileName
!= DestFile
)
1316 // We have to copy it into place
1318 Desc
.URI
= "copy:" + FileName
;
1325 // at this point pkgAcqMetaIndex takes over
1326 ExpectedAdditionalItems
= 0;
1328 // put the last known good file back on i-m-s hit (it will
1329 // be re-verified again)
1330 // Else do nothing, we have the new file in DestFile then
1331 if(StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true)
1332 Rename(LastGoodSig
, DestFile
);
1334 // queue a pkgAcqMetaIndex to be verified against the sig we just retrieved
1335 new pkgAcqMetaIndex(Owner
, MetaIndexURI
, MetaIndexURIDesc
,
1336 MetaIndexShortDesc
, DestFile
, IndexTargets
,
1341 void pkgAcqMetaSig::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)/*{{{*/
1343 string Final
= _config
->FindDir("Dir::State::lists") + URItoFileName(RealURI
);
1345 // at this point pkgAcqMetaIndex takes over
1346 ExpectedAdditionalItems
= 0;
1348 // if we get a network error we fail gracefully
1349 if(Status
== StatTransientNetworkError
)
1351 Item::Failed(Message
,Cnf
);
1352 // move the sigfile back on transient network failures
1353 if(FileExists(LastGoodSig
))
1354 Rename(LastGoodSig
,Final
);
1356 // set the status back to , Item::Failed likes to reset it
1357 Status
= pkgAcquire::Item::StatTransientNetworkError
;
1361 // Delete any existing sigfile when the acquire failed
1362 unlink(Final
.c_str());
1364 // queue a pkgAcqMetaIndex with no sigfile
1365 new pkgAcqMetaIndex(Owner
, MetaIndexURI
, MetaIndexURIDesc
, MetaIndexShortDesc
,
1366 "", IndexTargets
, MetaIndexParser
);
1368 if (Cnf
->LocalOnly
== true ||
1369 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == false)
1378 Item::Failed(Message
,Cnf
);
1381 pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire
*Owner
, /*{{{*/
1382 string URI
,string URIDesc
,string ShortDesc
,
1384 const vector
<struct IndexTarget
*>* IndexTargets
,
1385 indexRecords
* MetaIndexParser
) :
1386 Item(Owner
), RealURI(URI
), SigFile(SigFile
), IndexTargets(IndexTargets
),
1387 MetaIndexParser(MetaIndexParser
), AuthPass(false), IMSHit(false)
1389 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
1390 DestFile
+= URItoFileName(URI
);
1393 Desc
.Description
= URIDesc
;
1395 Desc
.ShortDesc
= ShortDesc
;
1398 // we expect more item
1399 ExpectedAdditionalItems
= IndexTargets
->size();
1404 // pkgAcqMetaIndex::Custom600Headers - Insert custom request headers /*{{{*/
1405 // ---------------------------------------------------------------------
1406 /* The only header we use is the last-modified header. */
1407 string
pkgAcqMetaIndex::Custom600Headers()
1409 string Final
= _config
->FindDir("Dir::State::lists");
1410 Final
+= URItoFileName(RealURI
);
1413 if (stat(Final
.c_str(),&Buf
) != 0)
1414 return "\nIndex-File: true";
1416 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
1419 void pkgAcqMetaIndex::Done(string Message
,unsigned long long Size
,string Hash
, /*{{{*/
1420 pkgAcquire::MethodConfig
*Cfg
)
1422 Item::Done(Message
,Size
,Hash
,Cfg
);
1424 // MetaIndexes are done in two passes: one to download the
1425 // metaindex with an appropriate method, and a second to verify it
1426 // with the gpgv method
1428 if (AuthPass
== true)
1432 // all cool, move Release file into place
1437 RetrievalDone(Message
);
1439 // Still more retrieving to do
1444 // There was no signature file, so we are finished. Download
1445 // the indexes and do only hashsum verification if possible
1446 MetaIndexParser
->Load(DestFile
);
1447 QueueIndexes(false);
1451 // There was a signature file, so pass it to gpgv for
1454 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
1455 std::cerr
<< "Metaindex acquired, queueing gpg verification ("
1456 << SigFile
<< "," << DestFile
<< ")\n";
1458 Desc
.URI
= "gpgv:" + SigFile
;
1465 if (Complete
== true)
1467 string FinalFile
= _config
->FindDir("Dir::State::lists");
1468 FinalFile
+= URItoFileName(RealURI
);
1469 if (SigFile
== DestFile
)
1470 SigFile
= FinalFile
;
1471 Rename(DestFile
,FinalFile
);
1472 chmod(FinalFile
.c_str(),0644);
1473 DestFile
= FinalFile
;
1477 void pkgAcqMetaIndex::RetrievalDone(string Message
) /*{{{*/
1479 // We have just finished downloading a Release file (it is not
1482 string FileName
= LookupTag(Message
,"Filename");
1483 if (FileName
.empty() == true)
1486 ErrorText
= "Method gave a blank filename";
1490 if (FileName
!= DestFile
)
1493 Desc
.URI
= "copy:" + FileName
;
1498 // make sure to verify against the right file on I-M-S hit
1499 IMSHit
= StringToBool(LookupTag(Message
,"IMS-Hit"),false);
1502 string FinalFile
= _config
->FindDir("Dir::State::lists");
1503 FinalFile
+= URItoFileName(RealURI
);
1504 if (SigFile
== DestFile
)
1506 SigFile
= FinalFile
;
1507 // constructor of pkgAcqMetaClearSig moved it out of the way,
1508 // now move it back in on IMS hit for the 'old' file
1509 string
const OldClearSig
= DestFile
+ ".reverify";
1510 if (RealFileExists(OldClearSig
) == true)
1511 Rename(OldClearSig
, FinalFile
);
1513 DestFile
= FinalFile
;
1518 void pkgAcqMetaIndex::AuthDone(string Message
) /*{{{*/
1520 // At this point, the gpgv method has succeeded, so there is a
1521 // valid signature from a key in the trusted keyring. We
1522 // perform additional verification of its contents, and use them
1523 // to verify the indexes we are about to download
1525 if (!MetaIndexParser
->Load(DestFile
))
1527 Status
= StatAuthError
;
1528 ErrorText
= MetaIndexParser
->ErrorText
;
1532 if (!VerifyVendor(Message
))
1537 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
1538 std::cerr
<< "Signature verification succeeded: "
1539 << DestFile
<< std::endl
;
1541 // Download further indexes with verification
1544 // is it a clearsigned MetaIndex file?
1545 if (DestFile
== SigFile
)
1548 // Done, move signature file into position
1549 string VerifiedSigFile
= _config
->FindDir("Dir::State::lists") +
1550 URItoFileName(RealURI
) + ".gpg";
1551 Rename(SigFile
,VerifiedSigFile
);
1552 chmod(VerifiedSigFile
.c_str(),0644);
1555 void pkgAcqMetaIndex::QueueIndexes(bool verify
) /*{{{*/
1558 /* Reject invalid, existing Release files (LP: #346386) (Closes: #627642)
1559 * FIXME: Disabled; it breaks unsigned repositories without hashes */
1560 if (!verify
&& FileExists(DestFile
) && !MetaIndexParser
->Load(DestFile
))
1563 ErrorText
= MetaIndexParser
->ErrorText
;
1567 bool transInRelease
= false;
1569 std::vector
<std::string
> const keys
= MetaIndexParser
->MetaKeys();
1570 for (std::vector
<std::string
>::const_iterator k
= keys
.begin(); k
!= keys
.end(); ++k
)
1571 // FIXME: Feels wrong to check for hardcoded string here, but what should we do else…
1572 if (k
->find("Translation-") != std::string::npos
)
1574 transInRelease
= true;
1579 // at this point the real Items are loaded in the fetcher
1580 ExpectedAdditionalItems
= 0;
1582 for (vector
<struct IndexTarget
*>::const_iterator Target
= IndexTargets
->begin();
1583 Target
!= IndexTargets
->end();
1586 HashString ExpectedIndexHash
;
1587 indexRecords::checkSum
*Record
= MetaIndexParser
->Lookup((*Target
)->MetaKey
);
1588 bool compressedAvailable
= false;
1591 if ((*Target
)->IsOptional() == true)
1593 std::vector
<std::string
> types
= APT::Configuration::getCompressionTypes();
1594 for (std::vector
<std::string
>::const_iterator t
= types
.begin(); t
!= types
.end(); ++t
)
1595 if (MetaIndexParser
->Exists((*Target
)->MetaKey
+ "." + *t
) == true)
1597 compressedAvailable
= true;
1601 else if (verify
== true)
1603 Status
= StatAuthError
;
1604 strprintf(ErrorText
, _("Unable to find expected entry '%s' in Release file (Wrong sources.list entry or malformed file)"), (*Target
)->MetaKey
.c_str());
1610 ExpectedIndexHash
= Record
->Hash
;
1611 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
1613 std::cerr
<< "Queueing: " << (*Target
)->URI
<< std::endl
;
1614 std::cerr
<< "Expected Hash: " << ExpectedIndexHash
.toStr() << std::endl
;
1615 std::cerr
<< "For: " << Record
->MetaKeyFilename
<< std::endl
;
1617 if (verify
== true && ExpectedIndexHash
.empty() == true && (*Target
)->IsOptional() == false)
1619 Status
= StatAuthError
;
1620 strprintf(ErrorText
, _("Unable to find hash sum for '%s' in Release file"), (*Target
)->MetaKey
.c_str());
1625 if ((*Target
)->IsOptional() == true)
1627 if ((*Target
)->IsSubIndex() == true)
1628 new pkgAcqSubIndex(Owner
, (*Target
)->URI
, (*Target
)->Description
,
1629 (*Target
)->ShortDesc
, ExpectedIndexHash
);
1630 else if (transInRelease
== false || Record
!= NULL
|| compressedAvailable
== true)
1632 if (_config
->FindB("Acquire::PDiffs",true) == true && transInRelease
== true &&
1633 MetaIndexParser
->Exists((*Target
)->MetaKey
+ ".diff/Index") == true)
1634 new pkgAcqDiffIndex(Owner
, (*Target
)->URI
, (*Target
)->Description
,
1635 (*Target
)->ShortDesc
, ExpectedIndexHash
);
1637 new pkgAcqIndexTrans(Owner
, *Target
, ExpectedIndexHash
, MetaIndexParser
);
1642 /* Queue Packages file (either diff or full packages files, depending
1643 on the users option) - we also check if the PDiff Index file is listed
1644 in the Meta-Index file. Ideal would be if pkgAcqDiffIndex would test this
1645 instead, but passing the required info to it is to much hassle */
1646 if(_config
->FindB("Acquire::PDiffs",true) == true && (verify
== false ||
1647 MetaIndexParser
->Exists((*Target
)->MetaKey
+ ".diff/Index") == true))
1648 new pkgAcqDiffIndex(Owner
, (*Target
)->URI
, (*Target
)->Description
,
1649 (*Target
)->ShortDesc
, ExpectedIndexHash
);
1651 new pkgAcqIndex(Owner
, *Target
, ExpectedIndexHash
, MetaIndexParser
);
1655 bool pkgAcqMetaIndex::VerifyVendor(string Message
) /*{{{*/
1657 string::size_type pos
;
1659 // check for missing sigs (that where not fatal because otherwise we had
1662 string msg
= _("There is no public key available for the "
1663 "following key IDs:\n");
1664 pos
= Message
.find("NO_PUBKEY ");
1665 if (pos
!= std::string::npos
)
1667 string::size_type start
= pos
+strlen("NO_PUBKEY ");
1668 string Fingerprint
= Message
.substr(start
, Message
.find("\n")-start
);
1669 missingkeys
+= (Fingerprint
);
1671 if(!missingkeys
.empty())
1672 _error
->Warning("%s", (msg
+ missingkeys
).c_str());
1674 string Transformed
= MetaIndexParser
->GetExpectedDist();
1676 if (Transformed
== "../project/experimental")
1678 Transformed
= "experimental";
1681 pos
= Transformed
.rfind('/');
1682 if (pos
!= string::npos
)
1684 Transformed
= Transformed
.substr(0, pos
);
1687 if (Transformed
== ".")
1692 if (_config
->FindB("Acquire::Check-Valid-Until", true) == true &&
1693 MetaIndexParser
->GetValidUntil() > 0) {
1694 time_t const invalid_since
= time(NULL
) - MetaIndexParser
->GetValidUntil();
1695 if (invalid_since
> 0)
1696 // TRANSLATOR: The first %s is the URL of the bad Release file, the second is
1697 // the time since then the file is invalid - formated in the same way as in
1698 // the download progress display (e.g. 7d 3h 42min 1s)
1699 return _error
->Error(
1700 _("Release file for %s is expired (invalid since %s). "
1701 "Updates for this repository will not be applied."),
1702 RealURI
.c_str(), TimeToStr(invalid_since
).c_str());
1705 if (_config
->FindB("Debug::pkgAcquire::Auth", false))
1707 std::cerr
<< "Got Codename: " << MetaIndexParser
->GetDist() << std::endl
;
1708 std::cerr
<< "Expecting Dist: " << MetaIndexParser
->GetExpectedDist() << std::endl
;
1709 std::cerr
<< "Transformed Dist: " << Transformed
<< std::endl
;
1712 if (MetaIndexParser
->CheckDist(Transformed
) == false)
1714 // This might become fatal one day
1715 // Status = StatAuthError;
1716 // ErrorText = "Conflicting distribution; expected "
1717 // + MetaIndexParser->GetExpectedDist() + " but got "
1718 // + MetaIndexParser->GetDist();
1720 if (!Transformed
.empty())
1722 _error
->Warning(_("Conflicting distribution: %s (expected %s but got %s)"),
1723 Desc
.Description
.c_str(),
1724 Transformed
.c_str(),
1725 MetaIndexParser
->GetDist().c_str());
1732 // pkgAcqMetaIndex::Failed - no Release file present or no signature file present /*{{{*/
1733 // ---------------------------------------------------------------------
1735 void pkgAcqMetaIndex::Failed(string Message
,pkgAcquire::MethodConfig
* /*Cnf*/)
1737 if (AuthPass
== true)
1739 // gpgv method failed, if we have a good signature
1740 string LastGoodSigFile
= _config
->FindDir("Dir::State::lists").append("partial/").append(URItoFileName(RealURI
));
1741 if (DestFile
!= SigFile
)
1742 LastGoodSigFile
.append(".gpg");
1743 LastGoodSigFile
.append(".reverify");
1745 if(FileExists(LastGoodSigFile
))
1747 string VerifiedSigFile
= _config
->FindDir("Dir::State::lists") + URItoFileName(RealURI
);
1748 if (DestFile
!= SigFile
)
1749 VerifiedSigFile
.append(".gpg");
1750 Rename(LastGoodSigFile
, VerifiedSigFile
);
1751 Status
= StatTransientNetworkError
;
1752 _error
->Warning(_("An error occurred during the signature "
1753 "verification. The repository is not updated "
1754 "and the previous index files will be used. "
1755 "GPG error: %s: %s\n"),
1756 Desc
.Description
.c_str(),
1757 LookupTag(Message
,"Message").c_str());
1758 RunScripts("APT::Update::Auth-Failure");
1760 } else if (LookupTag(Message
,"Message").find("NODATA") != string::npos
) {
1761 /* Invalid signature file, reject (LP: #346386) (Closes: #627642) */
1762 _error
->Error(_("GPG error: %s: %s"),
1763 Desc
.Description
.c_str(),
1764 LookupTag(Message
,"Message").c_str());
1767 _error
->Warning(_("GPG error: %s: %s"),
1768 Desc
.Description
.c_str(),
1769 LookupTag(Message
,"Message").c_str());
1771 // gpgv method failed
1772 ReportMirrorFailure("GPGFailure");
1775 /* Always move the meta index, even if gpgv failed. This ensures
1776 * that PackageFile objects are correctly filled in */
1777 if (FileExists(DestFile
)) {
1778 string FinalFile
= _config
->FindDir("Dir::State::lists");
1779 FinalFile
+= URItoFileName(RealURI
);
1780 /* InRelease files become Release files, otherwise
1781 * they would be considered as trusted later on */
1782 if (SigFile
== DestFile
) {
1783 RealURI
= RealURI
.replace(RealURI
.rfind("InRelease"), 9,
1785 FinalFile
= FinalFile
.replace(FinalFile
.rfind("InRelease"), 9,
1787 SigFile
= FinalFile
;
1789 Rename(DestFile
,FinalFile
);
1790 chmod(FinalFile
.c_str(),0644);
1792 DestFile
= FinalFile
;
1795 // No Release file was present, or verification failed, so fall
1796 // back to queueing Packages files without verification
1797 QueueIndexes(false);
1800 pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire
*Owner
, /*{{{*/
1801 string
const &URI
, string
const &URIDesc
, string
const &ShortDesc
,
1802 string
const &MetaIndexURI
, string
const &MetaIndexURIDesc
, string
const &MetaIndexShortDesc
,
1803 string
const &MetaSigURI
, string
const &MetaSigURIDesc
, string
const &MetaSigShortDesc
,
1804 const vector
<struct IndexTarget
*>* IndexTargets
,
1805 indexRecords
* MetaIndexParser
) :
1806 pkgAcqMetaIndex(Owner
, URI
, URIDesc
, ShortDesc
, "", IndexTargets
, MetaIndexParser
),
1807 MetaIndexURI(MetaIndexURI
), MetaIndexURIDesc(MetaIndexURIDesc
), MetaIndexShortDesc(MetaIndexShortDesc
),
1808 MetaSigURI(MetaSigURI
), MetaSigURIDesc(MetaSigURIDesc
), MetaSigShortDesc(MetaSigShortDesc
)
1812 // index targets + (worst case:) Release/Release.gpg
1813 ExpectedAdditionalItems
= IndexTargets
->size() + 2;
1816 // keep the old InRelease around in case of transistent network errors
1817 string
const Final
= _config
->FindDir("Dir::State::lists") + URItoFileName(RealURI
);
1818 if (RealFileExists(Final
) == true)
1820 string
const LastGoodSig
= DestFile
+ ".reverify";
1821 Rename(Final
,LastGoodSig
);
1825 pkgAcqMetaClearSig::~pkgAcqMetaClearSig() /*{{{*/
1827 // if the file was never queued undo file-changes done in the constructor
1828 if (QueueCounter
== 1 && Status
== StatIdle
&& FileSize
== 0 && Complete
== false)
1830 string
const Final
= _config
->FindDir("Dir::State::lists") + URItoFileName(RealURI
);
1831 string
const LastGoodSig
= DestFile
+ ".reverify";
1832 if (RealFileExists(Final
) == false && RealFileExists(LastGoodSig
) == true)
1833 Rename(LastGoodSig
, Final
);
1837 // pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers /*{{{*/
1838 // ---------------------------------------------------------------------
1839 // FIXME: this can go away once the InRelease file is used widely
1840 string
pkgAcqMetaClearSig::Custom600Headers()
1842 string Final
= _config
->FindDir("Dir::State::lists");
1843 Final
+= URItoFileName(RealURI
);
1846 if (stat(Final
.c_str(),&Buf
) != 0)
1848 Final
= DestFile
+ ".reverify";
1849 if (stat(Final
.c_str(),&Buf
) != 0)
1850 return "\nIndex-File: true\nFail-Ignore: true\n";
1853 return "\nIndex-File: true\nFail-Ignore: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
1856 void pkgAcqMetaClearSig::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
) /*{{{*/
1858 // we failed, we will not get additional items from this method
1859 ExpectedAdditionalItems
= 0;
1861 if (AuthPass
== false)
1863 // Remove the 'old' InRelease file if we try Release.gpg now as otherwise
1864 // the file will stay around and gives a false-auth impression (CVE-2012-0214)
1865 string FinalFile
= _config
->FindDir("Dir::State::lists");
1866 FinalFile
.append(URItoFileName(RealURI
));
1867 if (FileExists(FinalFile
))
1868 unlink(FinalFile
.c_str());
1870 new pkgAcqMetaSig(Owner
,
1871 MetaSigURI
, MetaSigURIDesc
, MetaSigShortDesc
,
1872 MetaIndexURI
, MetaIndexURIDesc
, MetaIndexShortDesc
,
1873 IndexTargets
, MetaIndexParser
);
1874 if (Cnf
->LocalOnly
== true ||
1875 StringToBool(LookupTag(Message
, "Transient-Failure"), false) == false)
1879 pkgAcqMetaIndex::Failed(Message
, Cnf
);
1882 // AcqArchive::AcqArchive - Constructor /*{{{*/
1883 // ---------------------------------------------------------------------
1884 /* This just sets up the initial fetch environment and queues the first
1886 pkgAcqArchive::pkgAcqArchive(pkgAcquire
*Owner
,pkgSourceList
*Sources
,
1887 pkgRecords
*Recs
,pkgCache::VerIterator
const &Version
,
1888 string
&StoreFilename
) :
1889 Item(Owner
), Version(Version
), Sources(Sources
), Recs(Recs
),
1890 StoreFilename(StoreFilename
), Vf(Version
.FileList()),
1893 Retries
= _config
->FindI("Acquire::Retries",0);
1895 if (Version
.Arch() == 0)
1897 _error
->Error(_("I wasn't able to locate a file for the %s package. "
1898 "This might mean you need to manually fix this package. "
1899 "(due to missing arch)"),
1900 Version
.ParentPkg().FullName().c_str());
1904 /* We need to find a filename to determine the extension. We make the
1905 assumption here that all the available sources for this version share
1906 the same extension.. */
1907 // Skip not source sources, they do not have file fields.
1908 for (; Vf
.end() == false; ++Vf
)
1910 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) != 0)
1915 // Does not really matter here.. we are going to fail out below
1916 if (Vf
.end() != true)
1918 // If this fails to get a file name we will bomb out below.
1919 pkgRecords::Parser
&Parse
= Recs
->Lookup(Vf
);
1920 if (_error
->PendingError() == true)
1923 // Generate the final file name as: package_version_arch.foo
1924 StoreFilename
= QuoteString(Version
.ParentPkg().Name(),"_:") + '_' +
1925 QuoteString(Version
.VerStr(),"_:") + '_' +
1926 QuoteString(Version
.Arch(),"_:.") +
1927 "." + flExtension(Parse
.FileName());
1930 // check if we have one trusted source for the package. if so, switch
1931 // to "TrustedOnly" mode - but only if not in AllowUnauthenticated mode
1932 bool const allowUnauth
= _config
->FindB("APT::Get::AllowUnauthenticated", false);
1933 bool const debugAuth
= _config
->FindB("Debug::pkgAcquire::Auth", false);
1934 bool seenUntrusted
= false;
1935 for (pkgCache::VerFileIterator i
= Version
.FileList(); i
.end() == false; ++i
)
1937 pkgIndexFile
*Index
;
1938 if (Sources
->FindIndex(i
.File(),Index
) == false)
1941 if (debugAuth
== true)
1942 std::cerr
<< "Checking index: " << Index
->Describe()
1943 << "(Trusted=" << Index
->IsTrusted() << ")" << std::endl
;
1945 if (Index
->IsTrusted() == true)
1948 if (allowUnauth
== false)
1952 seenUntrusted
= true;
1955 // "allow-unauthenticated" restores apts old fetching behaviour
1956 // that means that e.g. unauthenticated file:// uris are higher
1957 // priority than authenticated http:// uris
1958 if (allowUnauth
== true && seenUntrusted
== true)
1962 if (QueueNext() == false && _error
->PendingError() == false)
1963 _error
->Error(_("Can't find a source to download version '%s' of '%s'"),
1964 Version
.VerStr(), Version
.ParentPkg().FullName(false).c_str());
1967 // AcqArchive::QueueNext - Queue the next file source /*{{{*/
1968 // ---------------------------------------------------------------------
1969 /* This queues the next available file version for download. It checks if
1970 the archive is already available in the cache and stashs the MD5 for
1972 bool pkgAcqArchive::QueueNext()
1974 string
const ForceHash
= _config
->Find("Acquire::ForceHash");
1975 for (; Vf
.end() == false; ++Vf
)
1977 // Ignore not source sources
1978 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) != 0)
1981 // Try to cross match against the source list
1982 pkgIndexFile
*Index
;
1983 if (Sources
->FindIndex(Vf
.File(),Index
) == false)
1986 // only try to get a trusted package from another source if that source
1988 if(Trusted
&& !Index
->IsTrusted())
1991 // Grab the text package record
1992 pkgRecords::Parser
&Parse
= Recs
->Lookup(Vf
);
1993 if (_error
->PendingError() == true)
1996 string PkgFile
= Parse
.FileName();
1997 if (ForceHash
.empty() == false)
1999 if(stringcasecmp(ForceHash
, "sha512") == 0)
2000 ExpectedHash
= HashString("SHA512", Parse
.SHA512Hash());
2001 else if(stringcasecmp(ForceHash
, "sha256") == 0)
2002 ExpectedHash
= HashString("SHA256", Parse
.SHA256Hash());
2003 else if (stringcasecmp(ForceHash
, "sha1") == 0)
2004 ExpectedHash
= HashString("SHA1", Parse
.SHA1Hash());
2006 ExpectedHash
= HashString("MD5Sum", Parse
.MD5Hash());
2011 if ((Hash
= Parse
.SHA512Hash()).empty() == false)
2012 ExpectedHash
= HashString("SHA512", Hash
);
2013 else if ((Hash
= Parse
.SHA256Hash()).empty() == false)
2014 ExpectedHash
= HashString("SHA256", Hash
);
2015 else if ((Hash
= Parse
.SHA1Hash()).empty() == false)
2016 ExpectedHash
= HashString("SHA1", Hash
);
2018 ExpectedHash
= HashString("MD5Sum", Parse
.MD5Hash());
2020 if (PkgFile
.empty() == true)
2021 return _error
->Error(_("The package index files are corrupted. No Filename: "
2022 "field for package %s."),
2023 Version
.ParentPkg().Name());
2025 Desc
.URI
= Index
->ArchiveURI(PkgFile
);
2026 Desc
.Description
= Index
->ArchiveInfo(Version
);
2028 Desc
.ShortDesc
= Version
.ParentPkg().FullName(true);
2030 // See if we already have the file. (Legacy filenames)
2031 FileSize
= Version
->Size
;
2032 string FinalFile
= _config
->FindDir("Dir::Cache::Archives") + flNotDir(PkgFile
);
2034 if (stat(FinalFile
.c_str(),&Buf
) == 0)
2036 // Make sure the size matches
2037 if ((unsigned long long)Buf
.st_size
== Version
->Size
)
2042 StoreFilename
= DestFile
= FinalFile
;
2046 /* Hmm, we have a file and its size does not match, this means it is
2047 an old style mismatched arch */
2048 unlink(FinalFile
.c_str());
2051 // Check it again using the new style output filenames
2052 FinalFile
= _config
->FindDir("Dir::Cache::Archives") + flNotDir(StoreFilename
);
2053 if (stat(FinalFile
.c_str(),&Buf
) == 0)
2055 // Make sure the size matches
2056 if ((unsigned long long)Buf
.st_size
== Version
->Size
)
2061 StoreFilename
= DestFile
= FinalFile
;
2065 /* Hmm, we have a file and its size does not match, this shouldn't
2067 unlink(FinalFile
.c_str());
2070 DestFile
= _config
->FindDir("Dir::Cache::Archives") + "partial/" + flNotDir(StoreFilename
);
2072 // Check the destination file
2073 if (stat(DestFile
.c_str(),&Buf
) == 0)
2075 // Hmm, the partial file is too big, erase it
2076 if ((unsigned long long)Buf
.st_size
> Version
->Size
)
2077 unlink(DestFile
.c_str());
2079 PartialSize
= Buf
.st_size
;
2082 // Disables download of archives - useful if no real installation follows,
2083 // e.g. if we are just interested in proposed installation order
2084 if (_config
->FindB("Debug::pkgAcqArchive::NoQueue", false) == true)
2089 StoreFilename
= DestFile
= FinalFile
;
2103 // AcqArchive::Done - Finished fetching /*{{{*/
2104 // ---------------------------------------------------------------------
2106 void pkgAcqArchive::Done(string Message
,unsigned long long Size
,string CalcHash
,
2107 pkgAcquire::MethodConfig
*Cfg
)
2109 Item::Done(Message
,Size
,CalcHash
,Cfg
);
2112 if (Size
!= Version
->Size
)
2114 RenameOnError(SizeMismatch
);
2119 if(ExpectedHash
.toStr() != CalcHash
)
2121 RenameOnError(HashSumMismatch
);
2125 // Grab the output filename
2126 string FileName
= LookupTag(Message
,"Filename");
2127 if (FileName
.empty() == true)
2130 ErrorText
= "Method gave a blank filename";
2136 // Reference filename
2137 if (FileName
!= DestFile
)
2139 StoreFilename
= DestFile
= FileName
;
2144 // Done, move it into position
2145 string FinalFile
= _config
->FindDir("Dir::Cache::Archives");
2146 FinalFile
+= flNotDir(StoreFilename
);
2147 Rename(DestFile
,FinalFile
);
2149 StoreFilename
= DestFile
= FinalFile
;
2153 // AcqArchive::Failed - Failure handler /*{{{*/
2154 // ---------------------------------------------------------------------
2155 /* Here we try other sources */
2156 void pkgAcqArchive::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
2158 ErrorText
= LookupTag(Message
,"Message");
2160 /* We don't really want to retry on failed media swaps, this prevents
2161 that. An interesting observation is that permanent failures are not
2163 if (Cnf
->Removable
== true &&
2164 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
2166 // Vf = Version.FileList();
2167 while (Vf
.end() == false) ++Vf
;
2168 StoreFilename
= string();
2169 Item::Failed(Message
,Cnf
);
2173 if (QueueNext() == false)
2175 // This is the retry counter
2177 Cnf
->LocalOnly
== false &&
2178 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
2181 Vf
= Version
.FileList();
2182 if (QueueNext() == true)
2186 StoreFilename
= string();
2187 Item::Failed(Message
,Cnf
);
2191 // AcqArchive::IsTrusted - Determine whether this archive comes from a trusted source /*{{{*/
2192 // ---------------------------------------------------------------------
2193 APT_PURE
bool pkgAcqArchive::IsTrusted()
2198 // AcqArchive::Finished - Fetching has finished, tidy up /*{{{*/
2199 // ---------------------------------------------------------------------
2201 void pkgAcqArchive::Finished()
2203 if (Status
== pkgAcquire::Item::StatDone
&&
2206 StoreFilename
= string();
2209 // AcqFile::pkgAcqFile - Constructor /*{{{*/
2210 // ---------------------------------------------------------------------
2211 /* The file is added to the queue */
2212 pkgAcqFile::pkgAcqFile(pkgAcquire
*Owner
,string URI
,string Hash
,
2213 unsigned long long Size
,string Dsc
,string ShortDesc
,
2214 const string
&DestDir
, const string
&DestFilename
,
2216 Item(Owner
), ExpectedHash(Hash
), IsIndexFile(IsIndexFile
)
2218 Retries
= _config
->FindI("Acquire::Retries",0);
2220 if(!DestFilename
.empty())
2221 DestFile
= DestFilename
;
2222 else if(!DestDir
.empty())
2223 DestFile
= DestDir
+ "/" + flNotDir(URI
);
2225 DestFile
= flNotDir(URI
);
2229 Desc
.Description
= Dsc
;
2232 // Set the short description to the archive component
2233 Desc
.ShortDesc
= ShortDesc
;
2235 // Get the transfer sizes
2238 if (stat(DestFile
.c_str(),&Buf
) == 0)
2240 // Hmm, the partial file is too big, erase it
2241 if ((Size
> 0) && (unsigned long long)Buf
.st_size
> Size
)
2242 unlink(DestFile
.c_str());
2244 PartialSize
= Buf
.st_size
;
2250 // AcqFile::Done - Item downloaded OK /*{{{*/
2251 // ---------------------------------------------------------------------
2253 void pkgAcqFile::Done(string Message
,unsigned long long Size
,string CalcHash
,
2254 pkgAcquire::MethodConfig
*Cnf
)
2256 Item::Done(Message
,Size
,CalcHash
,Cnf
);
2259 if(!ExpectedHash
.empty() && ExpectedHash
.toStr() != CalcHash
)
2261 RenameOnError(HashSumMismatch
);
2265 string FileName
= LookupTag(Message
,"Filename");
2266 if (FileName
.empty() == true)
2269 ErrorText
= "Method gave a blank filename";
2275 // The files timestamp matches
2276 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true)
2279 // We have to copy it into place
2280 if (FileName
!= DestFile
)
2283 if (_config
->FindB("Acquire::Source-Symlinks",true) == false ||
2284 Cnf
->Removable
== true)
2286 Desc
.URI
= "copy:" + FileName
;
2291 // Erase the file if it is a symlink so we can overwrite it
2293 if (lstat(DestFile
.c_str(),&St
) == 0)
2295 if (S_ISLNK(St
.st_mode
) != 0)
2296 unlink(DestFile
.c_str());
2300 if (symlink(FileName
.c_str(),DestFile
.c_str()) != 0)
2302 ErrorText
= "Link to " + DestFile
+ " failure ";
2309 // AcqFile::Failed - Failure handler /*{{{*/
2310 // ---------------------------------------------------------------------
2311 /* Here we try other sources */
2312 void pkgAcqFile::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
2314 ErrorText
= LookupTag(Message
,"Message");
2316 // This is the retry counter
2318 Cnf
->LocalOnly
== false &&
2319 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
2326 Item::Failed(Message
,Cnf
);
2329 // AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
2330 // ---------------------------------------------------------------------
2331 /* The only header we use is the last-modified header. */
2332 string
pkgAcqFile::Custom600Headers()
2335 return "\nIndex-File: true";