]> git.saurik.com Git - apt.git/blame - apt-pkg/acquire-item.cc
* imported changes from apt--main
[apt.git] / apt-pkg / acquire-item.cc
CommitLineData
0118833a
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
0fcd01de 3// $Id: acquire-item.cc,v 1.46 2003/02/02 22:19:17 jgg Exp $
0118833a
AL
4/* ######################################################################
5
6 Acquire Item - Item to acquire
7
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.
b185acc2 12
0118833a
AL
13 ##################################################################### */
14 /*}}}*/
15// Include Files /*{{{*/
16#ifdef __GNUG__
17#pragma implementation "apt-pkg/acquire-item.h"
18#endif
19#include <apt-pkg/acquire-item.h>
20#include <apt-pkg/configuration.h>
b2e465d6 21#include <apt-pkg/sourcelist.h>
03e39e59 22#include <apt-pkg/error.h>
cdcc6d34 23#include <apt-pkg/strutl.h>
36375005 24#include <apt-pkg/fileutl.h>
0a8a80e5 25
b2e465d6
AL
26#include <apti18n.h>
27
0a8a80e5
AL
28#include <sys/stat.h>
29#include <unistd.h>
c88edf1d 30#include <errno.h>
5819a761 31#include <string>
c88edf1d 32#include <stdio.h>
0118833a
AL
33 /*}}}*/
34
5819a761
AL
35using std::string;
36
0118833a
AL
37// Acquire::Item::Item - Constructor /*{{{*/
38// ---------------------------------------------------------------------
39/* */
8267fe24 40pkgAcquire::Item::Item(pkgAcquire *Owner) : Owner(Owner), FileSize(0),
6b1ff003
AL
41 PartialSize(0), Mode(0), ID(0), Complete(false),
42 Local(false), QueueCounter(0)
0118833a
AL
43{
44 Owner->Add(this);
c88edf1d 45 Status = StatIdle;
0118833a
AL
46}
47 /*}}}*/
48// Acquire::Item::~Item - Destructor /*{{{*/
49// ---------------------------------------------------------------------
50/* */
51pkgAcquire::Item::~Item()
52{
53 Owner->Remove(this);
54}
55 /*}}}*/
c88edf1d
AL
56// Acquire::Item::Failed - Item failed to download /*{{{*/
57// ---------------------------------------------------------------------
93bf083d
AL
58/* We return to an idle state if there are still other queues that could
59 fetch this object */
7d8afa39 60void pkgAcquire::Item::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
c88edf1d 61{
93bf083d 62 Status = StatIdle;
db890fdb 63 ErrorText = LookupTag(Message,"Message");
c88edf1d 64 if (QueueCounter <= 1)
93bf083d 65 {
a72ace20 66 /* This indicates that the file is not available right now but might
7d8afa39 67 be sometime later. If we do a retry cycle then this should be
17caf1b1 68 retried [CDROMs] */
7d8afa39
AL
69 if (Cnf->LocalOnly == true &&
70 StringToBool(LookupTag(Message,"Transient-Failure"),false) == true)
a72ace20
AL
71 {
72 Status = StatIdle;
681d76d0 73 Dequeue();
a72ace20
AL
74 return;
75 }
76
93bf083d 77 Status = StatError;
681d76d0 78 Dequeue();
93bf083d 79 }
c88edf1d
AL
80}
81 /*}}}*/
8267fe24
AL
82// Acquire::Item::Start - Item has begun to download /*{{{*/
83// ---------------------------------------------------------------------
17caf1b1
AL
84/* Stash status and the file size. Note that setting Complete means
85 sub-phases of the acquire process such as decompresion are operating */
727f18af 86void pkgAcquire::Item::Start(string /*Message*/,unsigned long Size)
8267fe24
AL
87{
88 Status = StatFetching;
89 if (FileSize == 0 && Complete == false)
90 FileSize = Size;
91}
92 /*}}}*/
c88edf1d
AL
93// Acquire::Item::Done - Item downloaded OK /*{{{*/
94// ---------------------------------------------------------------------
95/* */
459681d3
AL
96void pkgAcquire::Item::Done(string Message,unsigned long Size,string,
97 pkgAcquire::MethodConfig *Cnf)
c88edf1d 98{
b98f2859
AL
99 // We just downloaded something..
100 string FileName = LookupTag(Message,"Filename");
101 if (Complete == false && FileName == DestFile)
102 {
103 if (Owner->Log != 0)
104 Owner->Log->Fetched(Size,atoi(LookupTag(Message,"Resume-Point","0").c_str()));
105 }
aa0e1101
AL
106
107 if (FileSize == 0)
108 FileSize= Size;
b98f2859 109
c88edf1d
AL
110 Status = StatDone;
111 ErrorText = string();
112 Owner->Dequeue(this);
113}
114 /*}}}*/
8b89e57f
AL
115// Acquire::Item::Rename - Rename a file /*{{{*/
116// ---------------------------------------------------------------------
117/* This helper function is used by alot of item methods as thier final
118 step */
119void pkgAcquire::Item::Rename(string From,string To)
120{
121 if (rename(From.c_str(),To.c_str()) != 0)
122 {
123 char S[300];
0fcd01de 124 snprintf(S,sizeof(S),_("rename failed, %s (%s -> %s)."),strerror(errno),
8b89e57f
AL
125 From.c_str(),To.c_str());
126 Status = StatError;
127 ErrorText = S;
7a3c2ab0 128 }
8b89e57f
AL
129}
130 /*}}}*/
0118833a
AL
131
132// AcqIndex::AcqIndex - Constructor /*{{{*/
133// ---------------------------------------------------------------------
134/* The package file is added to the queue and a second class is
b2e465d6
AL
135 instantiated to fetch the revision file */
136pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,
137 string URI,string URIDesc,string ShortDesc) :
138 Item(Owner), RealURI(URI)
0118833a 139{
8b89e57f 140 Decompression = false;
bfd22fc0 141 Erase = false;
8b89e57f 142
0a8a80e5 143 DestFile = _config->FindDir("Dir::State::lists") + "partial/";
b2e465d6 144 DestFile += URItoFileName(URI);
8267fe24 145
54cf15cb 146 // Create the item
df96f2e5
MV
147 if(FileExists("/usr/bin/bzip2"))
148 Desc.URI = URI + ".bz2";
149 else
150 Desc.URI = URI + ".gz";
b2e465d6 151 Desc.Description = URIDesc;
8267fe24 152 Desc.Owner = this;
b2e465d6 153 Desc.ShortDesc = ShortDesc;
8267fe24
AL
154
155 QueueURI(Desc);
0118833a
AL
156}
157 /*}}}*/
0a8a80e5 158// AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
0118833a 159// ---------------------------------------------------------------------
0a8a80e5
AL
160/* The only header we use is the last-modified header. */
161string pkgAcqIndex::Custom600Headers()
0118833a 162{
0a8a80e5 163 string Final = _config->FindDir("Dir::State::lists");
b2e465d6 164 Final += URItoFileName(RealURI);
0a8a80e5
AL
165
166 struct stat Buf;
167 if (stat(Final.c_str(),&Buf) != 0)
a72ace20 168 return "\nIndex-File: true";
0118833a 169
a72ace20 170 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
0118833a
AL
171}
172 /*}}}*/
debc84b2
MZ
173
174void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
175{
176 // no .bz2 found, retry with .gz
177 if(Desc.URI.substr(Desc.URI.size()-3,Desc.URI.size()-1) == "bz2") {
178 Desc.URI = Desc.URI.substr(0,Desc.URI.size()-3) + "gz";
179 QueueURI(Desc);
180 return;
181 }
182
183
184 Item::Failed(Message,Cnf);
185}
186
187
8b89e57f
AL
188// AcqIndex::Done - Finished a fetch /*{{{*/
189// ---------------------------------------------------------------------
190/* This goes through a number of states.. On the initial fetch the
191 method could possibly return an alternate filename which points
192 to the uncompressed version of the file. If this is so the file
193 is copied into the partial directory. In all other cases the file
194 is decompressed with a gzip uri. */
459681d3
AL
195void pkgAcqIndex::Done(string Message,unsigned long Size,string MD5,
196 pkgAcquire::MethodConfig *Cfg)
8b89e57f 197{
459681d3 198 Item::Done(Message,Size,MD5,Cfg);
8b89e57f
AL
199
200 if (Decompression == true)
201 {
202 // Done, move it into position
203 string FinalFile = _config->FindDir("Dir::State::lists");
b2e465d6 204 FinalFile += URItoFileName(RealURI);
8b89e57f 205 Rename(DestFile,FinalFile);
7a3c2ab0 206 chmod(FinalFile.c_str(),0644);
bfd22fc0 207
7a7fa5f0
AL
208 /* We restore the original name to DestFile so that the clean operation
209 will work OK */
210 DestFile = _config->FindDir("Dir::State::lists") + "partial/";
b2e465d6 211 DestFile += URItoFileName(RealURI);
7a7fa5f0 212
bfd22fc0
AL
213 // Remove the compressed version.
214 if (Erase == true)
bfd22fc0 215 unlink(DestFile.c_str());
8b89e57f
AL
216 return;
217 }
bfd22fc0
AL
218
219 Erase = false;
8267fe24 220 Complete = true;
bfd22fc0 221
8b89e57f
AL
222 // Handle the unzipd case
223 string FileName = LookupTag(Message,"Alt-Filename");
224 if (FileName.empty() == false)
225 {
226 // The files timestamp matches
227 if (StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false) == true)
228 return;
229
230 Decompression = true;
a6568219 231 Local = true;
8b89e57f 232 DestFile += ".decomp";
8267fe24
AL
233 Desc.URI = "copy:" + FileName;
234 QueueURI(Desc);
b98f2859 235 Mode = "copy";
8b89e57f
AL
236 return;
237 }
238
239 FileName = LookupTag(Message,"Filename");
240 if (FileName.empty() == true)
241 {
242 Status = StatError;
243 ErrorText = "Method gave a blank filename";
244 }
245
246 // The files timestamp matches
247 if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
248 return;
bfd22fc0
AL
249
250 if (FileName == DestFile)
251 Erase = true;
8267fe24 252 else
a6568219 253 Local = true;
8b89e57f 254
debc84b2
MZ
255 string compExt = Desc.URI.substr(Desc.URI.size()-3,Desc.URI.size()-1);
256 char *decompProg;
257 if(compExt == "bz2")
258 decompProg = "bzip2";
259 else if(compExt == ".gz")
260 decompProg = "gzip";
261 else {
262 _error->Error("Unsupported extension: %s", compExt.c_str());
263 return;
264 }
265
8b89e57f
AL
266 Decompression = true;
267 DestFile += ".decomp";
debc84b2 268 Desc.URI = string(decompProg) + ":" + FileName;
8267fe24 269 QueueURI(Desc);
debc84b2 270 Mode = decompProg;
8b89e57f
AL
271}
272 /*}}}*/
273
0118833a
AL
274// AcqIndexRel::pkgAcqIndexRel - Constructor /*{{{*/
275// ---------------------------------------------------------------------
276/* The Release file is added to the queue */
277pkgAcqIndexRel::pkgAcqIndexRel(pkgAcquire *Owner,
b2e465d6
AL
278 string URI,string URIDesc,string ShortDesc) :
279 Item(Owner), RealURI(URI)
0118833a 280{
0a8a80e5 281 DestFile = _config->FindDir("Dir::State::lists") + "partial/";
b2e465d6 282 DestFile += URItoFileName(URI);
0a8a80e5 283
8267fe24 284 // Create the item
b2e465d6
AL
285 Desc.URI = URI;
286 Desc.Description = URIDesc;
287 Desc.ShortDesc = ShortDesc;
8267fe24
AL
288 Desc.Owner = this;
289
8267fe24 290 QueueURI(Desc);
0118833a
AL
291}
292 /*}}}*/
0a8a80e5 293// AcqIndexRel::Custom600Headers - Insert custom request headers /*{{{*/
0118833a 294// ---------------------------------------------------------------------
0a8a80e5
AL
295/* The only header we use is the last-modified header. */
296string pkgAcqIndexRel::Custom600Headers()
0118833a 297{
0a8a80e5 298 string Final = _config->FindDir("Dir::State::lists");
b2e465d6 299 Final += URItoFileName(RealURI);
0a8a80e5
AL
300
301 struct stat Buf;
302 if (stat(Final.c_str(),&Buf) != 0)
a72ace20 303 return "\nIndex-File: true";
0118833a 304
a72ace20 305 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
0118833a
AL
306}
307 /*}}}*/
c88edf1d
AL
308// AcqIndexRel::Done - Item downloaded OK /*{{{*/
309// ---------------------------------------------------------------------
310/* The release file was not placed into the download directory then
311 a copy URI is generated and it is copied there otherwise the file
312 in the partial directory is moved into .. and the URI is finished. */
459681d3
AL
313void pkgAcqIndexRel::Done(string Message,unsigned long Size,string MD5,
314 pkgAcquire::MethodConfig *Cfg)
c88edf1d 315{
459681d3 316 Item::Done(Message,Size,MD5,Cfg);
c88edf1d
AL
317
318 string FileName = LookupTag(Message,"Filename");
319 if (FileName.empty() == true)
320 {
321 Status = StatError;
322 ErrorText = "Method gave a blank filename";
8b89e57f 323 return;
c88edf1d 324 }
8b89e57f 325
8267fe24
AL
326 Complete = true;
327
8b89e57f
AL
328 // The files timestamp matches
329 if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
330 return;
c88edf1d
AL
331
332 // We have to copy it into place
333 if (FileName != DestFile)
334 {
a6568219 335 Local = true;
8267fe24
AL
336 Desc.URI = "copy:" + FileName;
337 QueueURI(Desc);
c88edf1d
AL
338 return;
339 }
340
341 // Done, move it into position
342 string FinalFile = _config->FindDir("Dir::State::lists");
b2e465d6 343 FinalFile += URItoFileName(RealURI);
8b89e57f 344 Rename(DestFile,FinalFile);
7a3c2ab0
AL
345
346 chmod(FinalFile.c_str(),0644);
c88edf1d
AL
347}
348 /*}}}*/
681d76d0
AL
349// AcqIndexRel::Failed - Silence failure messages for missing rel files /*{{{*/
350// ---------------------------------------------------------------------
351/* */
352void pkgAcqIndexRel::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
353{
681d76d0
AL
354 if (Cnf->LocalOnly == true ||
355 StringToBool(LookupTag(Message,"Transient-Failure"),false) == false)
356 {
2b154e53
AL
357 // Ignore this
358 Status = StatDone;
359 Complete = false;
681d76d0
AL
360 Dequeue();
361 return;
362 }
363
364 Item::Failed(Message,Cnf);
365}
366 /*}}}*/
03e39e59
AL
367
368// AcqArchive::AcqArchive - Constructor /*{{{*/
369// ---------------------------------------------------------------------
17caf1b1
AL
370/* This just sets up the initial fetch environment and queues the first
371 possibilitiy */
03e39e59 372pkgAcqArchive::pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources,
30e1eab5
AL
373 pkgRecords *Recs,pkgCache::VerIterator const &Version,
374 string &StoreFilename) :
375 Item(Owner), Version(Version), Sources(Sources), Recs(Recs),
b185acc2 376 StoreFilename(StoreFilename), Vf(Version.FileList())
03e39e59 377{
7d8afa39 378 Retries = _config->FindI("Acquire::Retries",0);
813c8eea
AL
379
380 if (Version.Arch() == 0)
bdae53f1 381 {
d1f1f6a8 382 _error->Error(_("I wasn't able to locate a file for the %s package. "
7a3c2ab0
AL
383 "This might mean you need to manually fix this package. "
384 "(due to missing arch)"),
813c8eea 385 Version.ParentPkg().Name());
bdae53f1
AL
386 return;
387 }
813c8eea 388
b2e465d6
AL
389 /* We need to find a filename to determine the extension. We make the
390 assumption here that all the available sources for this version share
391 the same extension.. */
392 // Skip not source sources, they do not have file fields.
393 for (; Vf.end() == false; Vf++)
394 {
395 if ((Vf.File()->Flags & pkgCache::Flag::NotSource) != 0)
396 continue;
397 break;
398 }
399
400 // Does not really matter here.. we are going to fail out below
401 if (Vf.end() != true)
402 {
403 // If this fails to get a file name we will bomb out below.
404 pkgRecords::Parser &Parse = Recs->Lookup(Vf);
405 if (_error->PendingError() == true)
406 return;
407
408 // Generate the final file name as: package_version_arch.foo
409 StoreFilename = QuoteString(Version.ParentPkg().Name(),"_:") + '_' +
410 QuoteString(Version.VerStr(),"_:") + '_' +
411 QuoteString(Version.Arch(),"_:.") +
412 "." + flExtension(Parse.FileName());
413 }
414
03e39e59 415 // Select a source
b185acc2 416 if (QueueNext() == false && _error->PendingError() == false)
b2e465d6
AL
417 _error->Error(_("I wasn't able to locate file for the %s package. "
418 "This might mean you need to manually fix this package."),
b185acc2
AL
419 Version.ParentPkg().Name());
420}
421 /*}}}*/
422// AcqArchive::QueueNext - Queue the next file source /*{{{*/
423// ---------------------------------------------------------------------
17caf1b1
AL
424/* This queues the next available file version for download. It checks if
425 the archive is already available in the cache and stashs the MD5 for
426 checking later. */
b185acc2 427bool pkgAcqArchive::QueueNext()
b2e465d6 428{
03e39e59
AL
429 for (; Vf.end() == false; Vf++)
430 {
431 // Ignore not source sources
432 if ((Vf.File()->Flags & pkgCache::Flag::NotSource) != 0)
433 continue;
434
435 // Try to cross match against the source list
b2e465d6
AL
436 pkgIndexFile *Index;
437 if (Sources->FindIndex(Vf.File(),Index) == false)
438 continue;
03e39e59
AL
439
440 // Grab the text package record
441 pkgRecords::Parser &Parse = Recs->Lookup(Vf);
442 if (_error->PendingError() == true)
b185acc2 443 return false;
03e39e59 444
b2e465d6 445 string PkgFile = Parse.FileName();
03e39e59
AL
446 MD5 = Parse.MD5Hash();
447 if (PkgFile.empty() == true)
b2e465d6
AL
448 return _error->Error(_("The package index files are corrupted. No Filename: "
449 "field for package %s."),
450 Version.ParentPkg().Name());
a6568219 451
17caf1b1 452 // See if we already have the file. (Legacy filenames)
a6568219
AL
453 FileSize = Version->Size;
454 string FinalFile = _config->FindDir("Dir::Cache::Archives") + flNotDir(PkgFile);
455 struct stat Buf;
456 if (stat(FinalFile.c_str(),&Buf) == 0)
457 {
458 // Make sure the size matches
459 if ((unsigned)Buf.st_size == Version->Size)
460 {
461 Complete = true;
462 Local = true;
463 Status = StatDone;
30e1eab5 464 StoreFilename = DestFile = FinalFile;
b185acc2 465 return true;
a6568219
AL
466 }
467
6b1ff003
AL
468 /* Hmm, we have a file and its size does not match, this means it is
469 an old style mismatched arch */
a6568219
AL
470 unlink(FinalFile.c_str());
471 }
17caf1b1
AL
472
473 // Check it again using the new style output filenames
474 FinalFile = _config->FindDir("Dir::Cache::Archives") + flNotDir(StoreFilename);
475 if (stat(FinalFile.c_str(),&Buf) == 0)
476 {
477 // Make sure the size matches
478 if ((unsigned)Buf.st_size == Version->Size)
479 {
480 Complete = true;
481 Local = true;
482 Status = StatDone;
483 StoreFilename = DestFile = FinalFile;
484 return true;
485 }
486
487 /* Hmm, we have a file and its size does not match, this shouldnt
488 happen.. */
489 unlink(FinalFile.c_str());
490 }
491
492 DestFile = _config->FindDir("Dir::Cache::Archives") + "partial/" + flNotDir(StoreFilename);
6b1ff003
AL
493
494 // Check the destination file
495 if (stat(DestFile.c_str(),&Buf) == 0)
496 {
497 // Hmm, the partial file is too big, erase it
498 if ((unsigned)Buf.st_size > Version->Size)
499 unlink(DestFile.c_str());
500 else
501 PartialSize = Buf.st_size;
502 }
503
03e39e59 504 // Create the item
b2e465d6
AL
505 Local = false;
506 Desc.URI = Index->ArchiveURI(PkgFile);
507 Desc.Description = Index->ArchiveInfo(Version);
03e39e59
AL
508 Desc.Owner = this;
509 Desc.ShortDesc = Version.ParentPkg().Name();
510 QueueURI(Desc);
b185acc2
AL
511
512 Vf++;
513 return true;
03e39e59 514 }
b185acc2
AL
515 return false;
516}
03e39e59
AL
517 /*}}}*/
518// AcqArchive::Done - Finished fetching /*{{{*/
519// ---------------------------------------------------------------------
520/* */
459681d3
AL
521void pkgAcqArchive::Done(string Message,unsigned long Size,string Md5Hash,
522 pkgAcquire::MethodConfig *Cfg)
03e39e59 523{
459681d3 524 Item::Done(Message,Size,Md5Hash,Cfg);
03e39e59
AL
525
526 // Check the size
527 if (Size != Version->Size)
528 {
bdae53f1 529 Status = StatError;
b2e465d6 530 ErrorText = _("Size mismatch");
03e39e59
AL
531 return;
532 }
533
534 // Check the md5
535 if (Md5Hash.empty() == false && MD5.empty() == false)
536 {
537 if (Md5Hash != MD5)
538 {
bdae53f1 539 Status = StatError;
b2e465d6 540 ErrorText = _("MD5Sum mismatch");
9978c7b0 541 Rename(DestFile,DestFile + ".FAILED");
03e39e59
AL
542 return;
543 }
544 }
a6568219
AL
545
546 // Grab the output filename
03e39e59
AL
547 string FileName = LookupTag(Message,"Filename");
548 if (FileName.empty() == true)
549 {
550 Status = StatError;
551 ErrorText = "Method gave a blank filename";
552 return;
553 }
a6568219
AL
554
555 Complete = true;
30e1eab5
AL
556
557 // Reference filename
a6568219
AL
558 if (FileName != DestFile)
559 {
30e1eab5 560 StoreFilename = DestFile = FileName;
a6568219
AL
561 Local = true;
562 return;
563 }
564
565 // Done, move it into position
566 string FinalFile = _config->FindDir("Dir::Cache::Archives");
17caf1b1 567 FinalFile += flNotDir(StoreFilename);
a6568219 568 Rename(DestFile,FinalFile);
03e39e59 569
30e1eab5 570 StoreFilename = DestFile = FinalFile;
03e39e59
AL
571 Complete = true;
572}
573 /*}}}*/
db890fdb
AL
574// AcqArchive::Failed - Failure handler /*{{{*/
575// ---------------------------------------------------------------------
576/* Here we try other sources */
7d8afa39 577void pkgAcqArchive::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
db890fdb
AL
578{
579 ErrorText = LookupTag(Message,"Message");
b2e465d6
AL
580
581 /* We don't really want to retry on failed media swaps, this prevents
582 that. An interesting observation is that permanent failures are not
583 recorded. */
584 if (Cnf->Removable == true &&
585 StringToBool(LookupTag(Message,"Transient-Failure"),false) == true)
586 {
587 // Vf = Version.FileList();
588 while (Vf.end() == false) Vf++;
589 StoreFilename = string();
590 Item::Failed(Message,Cnf);
591 return;
592 }
593
db890fdb 594 if (QueueNext() == false)
7d8afa39
AL
595 {
596 // This is the retry counter
597 if (Retries != 0 &&
598 Cnf->LocalOnly == false &&
599 StringToBool(LookupTag(Message,"Transient-Failure"),false) == true)
600 {
601 Retries--;
602 Vf = Version.FileList();
603 if (QueueNext() == true)
604 return;
605 }
606
9dbb421f 607 StoreFilename = string();
7d8afa39
AL
608 Item::Failed(Message,Cnf);
609 }
db890fdb
AL
610}
611 /*}}}*/
ab559b35
AL
612// AcqArchive::Finished - Fetching has finished, tidy up /*{{{*/
613// ---------------------------------------------------------------------
614/* */
615void pkgAcqArchive::Finished()
616{
617 if (Status == pkgAcquire::Item::StatDone &&
618 Complete == true)
619 return;
620 StoreFilename = string();
621}
622 /*}}}*/
36375005
AL
623
624// AcqFile::pkgAcqFile - Constructor /*{{{*/
625// ---------------------------------------------------------------------
626/* The file is added to the queue */
627pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI,string MD5,
628 unsigned long Size,string Dsc,string ShortDesc) :
b3c39978 629 Item(Owner), Md5Hash(MD5)
36375005 630{
08cfc005
AL
631 Retries = _config->FindI("Acquire::Retries",0);
632
36375005
AL
633 DestFile = flNotDir(URI);
634
635 // Create the item
636 Desc.URI = URI;
637 Desc.Description = Dsc;
638 Desc.Owner = this;
639
640 // Set the short description to the archive component
641 Desc.ShortDesc = ShortDesc;
642
643 // Get the transfer sizes
644 FileSize = Size;
645 struct stat Buf;
646 if (stat(DestFile.c_str(),&Buf) == 0)
647 {
648 // Hmm, the partial file is too big, erase it
649 if ((unsigned)Buf.st_size > Size)
650 unlink(DestFile.c_str());
651 else
652 PartialSize = Buf.st_size;
653 }
654
655 QueueURI(Desc);
656}
657 /*}}}*/
658// AcqFile::Done - Item downloaded OK /*{{{*/
659// ---------------------------------------------------------------------
660/* */
459681d3
AL
661void pkgAcqFile::Done(string Message,unsigned long Size,string MD5,
662 pkgAcquire::MethodConfig *Cnf)
36375005 663{
b3c39978
AL
664 // Check the md5
665 if (Md5Hash.empty() == false && MD5.empty() == false)
666 {
667 if (Md5Hash != MD5)
668 {
669 Status = StatError;
670 ErrorText = "MD5Sum mismatch";
671 Rename(DestFile,DestFile + ".FAILED");
672 return;
673 }
674 }
675
459681d3 676 Item::Done(Message,Size,MD5,Cnf);
36375005
AL
677
678 string FileName = LookupTag(Message,"Filename");
679 if (FileName.empty() == true)
680 {
681 Status = StatError;
682 ErrorText = "Method gave a blank filename";
683 return;
684 }
685
686 Complete = true;
687
688 // The files timestamp matches
689 if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
690 return;
691
692 // We have to copy it into place
693 if (FileName != DestFile)
694 {
695 Local = true;
459681d3
AL
696 if (_config->FindB("Acquire::Source-Symlinks",true) == false ||
697 Cnf->Removable == true)
917ae805
AL
698 {
699 Desc.URI = "copy:" + FileName;
700 QueueURI(Desc);
701 return;
702 }
703
83ab33fc
AL
704 // Erase the file if it is a symlink so we can overwrite it
705 struct stat St;
706 if (lstat(DestFile.c_str(),&St) == 0)
707 {
708 if (S_ISLNK(St.st_mode) != 0)
709 unlink(DestFile.c_str());
710 }
711
712 // Symlink the file
917ae805
AL
713 if (symlink(FileName.c_str(),DestFile.c_str()) != 0)
714 {
83ab33fc 715 ErrorText = "Link to " + DestFile + " failure ";
917ae805
AL
716 Status = StatError;
717 Complete = false;
718 }
36375005
AL
719 }
720}
721 /*}}}*/
08cfc005
AL
722// AcqFile::Failed - Failure handler /*{{{*/
723// ---------------------------------------------------------------------
724/* Here we try other sources */
725void pkgAcqFile::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
726{
727 ErrorText = LookupTag(Message,"Message");
728
729 // This is the retry counter
730 if (Retries != 0 &&
731 Cnf->LocalOnly == false &&
732 StringToBool(LookupTag(Message,"Transient-Failure"),false) == true)
733 {
734 Retries--;
735 QueueURI(Desc);
736 return;
737 }
738
739 Item::Failed(Message,Cnf);
740}
741 /*}}}*/