]>
git.saurik.com Git - apt.git/blob - apt-pkg/acquire-item.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: acquire-item.cc,v 1.21 1999/01/31 22:25:34 jgg Exp $
4 /* ######################################################################
6 Acquire Item - Item to acquire
8 Each item can download to exactly one file at a time. This means you
9 cannot create an item that fetches two uri's to two files at the same
10 time. The pkgAcqIndex class creates a second class upon instantiation
11 to fetch the other index files because of this.
13 ##################################################################### */
15 // Include Files /*{{{*/
17 #pragma implementation "apt-pkg/acquire-item.h"
19 #include <apt-pkg/acquire-item.h>
20 #include <apt-pkg/configuration.h>
21 #include <apt-pkg/error.h>
22 #include <apt-pkg/strutl.h>
31 // Acquire::Item::Item - Constructor /*{{{*/
32 // ---------------------------------------------------------------------
34 pkgAcquire::Item::Item(pkgAcquire
*Owner
) : Owner(Owner
), FileSize(0),
35 Mode(0), ID(0), Complete(false), Local(false),
42 // Acquire::Item::~Item - Destructor /*{{{*/
43 // ---------------------------------------------------------------------
45 pkgAcquire::Item::~Item()
50 // Acquire::Item::Failed - Item failed to download /*{{{*/
51 // ---------------------------------------------------------------------
52 /* We return to an idle state if there are still other queues that could
54 void pkgAcquire::Item::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
57 ErrorText
= LookupTag(Message
,"Message");
58 if (QueueCounter
<= 1)
60 /* This indicates that the file is not available right now but might
61 be sometime later. If we do a retry cycle then this should be
63 if (Cnf
->LocalOnly
== true &&
64 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
76 // Acquire::Item::Start - Item has begun to download /*{{{*/
77 // ---------------------------------------------------------------------
79 void pkgAcquire::Item::Start(string Message
,unsigned long Size
)
81 Status
= StatFetching
;
82 if (FileSize
== 0 && Complete
== false)
86 // Acquire::Item::Done - Item downloaded OK /*{{{*/
87 // ---------------------------------------------------------------------
89 void pkgAcquire::Item::Done(string Message
,unsigned long Size
,string
)
91 // We just downloaded something..
92 string FileName
= LookupTag(Message
,"Filename");
93 if (Complete
== false && FileName
== DestFile
)
96 Owner
->Log
->Fetched(Size
,atoi(LookupTag(Message
,"Resume-Point","0").c_str()));
100 ErrorText
= string();
101 Owner
->Dequeue(this);
104 // Acquire::Item::Rename - Rename a file /*{{{*/
105 // ---------------------------------------------------------------------
106 /* This helper function is used by alot of item methods as thier final
108 void pkgAcquire::Item::Rename(string From
,string To
)
110 if (rename(From
.c_str(),To
.c_str()) != 0)
113 sprintf(S
,"rename failed, %s (%s -> %s).",strerror(errno
),
114 From
.c_str(),To
.c_str());
121 // AcqIndex::AcqIndex - Constructor /*{{{*/
122 // ---------------------------------------------------------------------
123 /* The package file is added to the queue and a second class is
124 instantiated to fetch the revision file */
125 pkgAcqIndex::pkgAcqIndex(pkgAcquire
*Owner
,const pkgSourceList::Item
*Location
) :
126 Item(Owner
), Location(Location
)
128 Decompression
= false;
131 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
132 DestFile
+= URItoFileName(Location
->PackagesURI());
135 Desc
.URI
= Location
->PackagesURI() + ".gz";
136 Desc
.Description
= Location
->PackagesInfo();
139 // Set the short description to the archive component
140 if (Location
->Dist
[Location
->Dist
.size() - 1] == '/')
141 Desc
.ShortDesc
= Location
->Dist
;
143 Desc
.ShortDesc
= Location
->Dist
+ '/' + Location
->Section
;
147 // Create the Release fetch class
148 new pkgAcqIndexRel(Owner
,Location
);
151 // AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
152 // ---------------------------------------------------------------------
153 /* The only header we use is the last-modified header. */
154 string
pkgAcqIndex::Custom600Headers()
156 string Final
= _config
->FindDir("Dir::State::lists");
157 Final
+= URItoFileName(Location
->PackagesURI());
160 if (stat(Final
.c_str(),&Buf
) != 0)
161 return "\nIndex-File: true";
163 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
166 // AcqIndex::Done - Finished a fetch /*{{{*/
167 // ---------------------------------------------------------------------
168 /* This goes through a number of states.. On the initial fetch the
169 method could possibly return an alternate filename which points
170 to the uncompressed version of the file. If this is so the file
171 is copied into the partial directory. In all other cases the file
172 is decompressed with a gzip uri. */
173 void pkgAcqIndex::Done(string Message
,unsigned long Size
,string MD5
)
175 Item::Done(Message
,Size
,MD5
);
177 if (Decompression
== true)
179 // Done, move it into position
180 string FinalFile
= _config
->FindDir("Dir::State::lists");
181 FinalFile
+= URItoFileName(Location
->PackagesURI());
182 Rename(DestFile
,FinalFile
);
184 /* We restore the original name to DestFile so that the clean operation
186 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
187 DestFile
+= URItoFileName(Location
->PackagesURI());
189 // Remove the compressed version.
191 unlink(DestFile
.c_str());
198 // Handle the unzipd case
199 string FileName
= LookupTag(Message
,"Alt-Filename");
200 if (FileName
.empty() == false)
202 // The files timestamp matches
203 if (StringToBool(LookupTag(Message
,"Alt-IMS-Hit"),false) == true)
206 Decompression
= true;
208 DestFile
+= ".decomp";
209 Desc
.URI
= "copy:" + FileName
;
215 FileName
= LookupTag(Message
,"Filename");
216 if (FileName
.empty() == true)
219 ErrorText
= "Method gave a blank filename";
222 // The files timestamp matches
223 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true)
226 if (FileName
== DestFile
)
231 Decompression
= true;
232 DestFile
+= ".decomp";
233 Desc
.URI
= "gzip:" + FileName
,Location
->PackagesInfo();
238 // AcqIndex::Describe - Describe the Item /*{{{*/
239 // ---------------------------------------------------------------------
241 string
pkgAcqIndex::Describe()
243 return Location
->PackagesURI();
247 // AcqIndexRel::pkgAcqIndexRel - Constructor /*{{{*/
248 // ---------------------------------------------------------------------
249 /* The Release file is added to the queue */
250 pkgAcqIndexRel::pkgAcqIndexRel(pkgAcquire
*Owner
,
251 const pkgSourceList::Item
*Location
) :
252 Item(Owner
), Location(Location
)
254 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
255 DestFile
+= URItoFileName(Location
->ReleaseURI());
258 Desc
.URI
= Location
->ReleaseURI();
259 Desc
.Description
= Location
->ReleaseInfo();
262 // Set the short description to the archive component
263 if (Location
->Dist
[Location
->Dist
.size() - 1] == '/')
264 Desc
.ShortDesc
= Location
->Dist
;
266 Desc
.ShortDesc
= Location
->Dist
+ '/' + Location
->Section
;
271 // AcqIndexRel::Custom600Headers - Insert custom request headers /*{{{*/
272 // ---------------------------------------------------------------------
273 /* The only header we use is the last-modified header. */
274 string
pkgAcqIndexRel::Custom600Headers()
276 string Final
= _config
->FindDir("Dir::State::lists");
277 Final
+= URItoFileName(Location
->ReleaseURI());
280 if (stat(Final
.c_str(),&Buf
) != 0)
281 return "\nIndex-File: true";
283 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
286 // AcqIndexRel::Done - Item downloaded OK /*{{{*/
287 // ---------------------------------------------------------------------
288 /* The release file was not placed into the download directory then
289 a copy URI is generated and it is copied there otherwise the file
290 in the partial directory is moved into .. and the URI is finished. */
291 void pkgAcqIndexRel::Done(string Message
,unsigned long Size
,string MD5
)
293 Item::Done(Message
,Size
,MD5
);
295 string FileName
= LookupTag(Message
,"Filename");
296 if (FileName
.empty() == true)
299 ErrorText
= "Method gave a blank filename";
305 // The files timestamp matches
306 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true)
309 // We have to copy it into place
310 if (FileName
!= DestFile
)
313 Desc
.URI
= "copy:" + FileName
;
318 // Done, move it into position
319 string FinalFile
= _config
->FindDir("Dir::State::lists");
320 FinalFile
+= URItoFileName(Location
->ReleaseURI());
321 Rename(DestFile
,FinalFile
);
324 // AcqIndexRel::Describe - Describe the Item /*{{{*/
325 // ---------------------------------------------------------------------
327 string
pkgAcqIndexRel::Describe()
329 return Location
->ReleaseURI();
332 // AcqIndexRel::Failed - Silence failure messages for missing rel files /*{{{*/
333 // ---------------------------------------------------------------------
335 void pkgAcqIndexRel::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
337 // This is the retry counter
338 if (Cnf
->LocalOnly
== true ||
339 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == false)
346 Item::Failed(Message
,Cnf
);
350 // AcqArchive::AcqArchive - Constructor /*{{{*/
351 // ---------------------------------------------------------------------
353 pkgAcqArchive::pkgAcqArchive(pkgAcquire
*Owner
,pkgSourceList
*Sources
,
354 pkgRecords
*Recs
,pkgCache::VerIterator
const &Version
,
355 string
&StoreFilename
) :
356 Item(Owner
), Version(Version
), Sources(Sources
), Recs(Recs
),
357 StoreFilename(StoreFilename
), Vf(Version
.FileList())
359 Retries
= _config
->FindI("Acquire::Retries",0);
362 if (QueueNext() == false && _error
->PendingError() == false)
363 _error
->Error("I wasn't able to locate file for the %s package. "
364 "This might mean you need to manually fix this package.",
365 Version
.ParentPkg().Name());
368 // AcqArchive::QueueNext - Queue the next file source /*{{{*/
369 // ---------------------------------------------------------------------
370 /* This queues the next available file version for download. */
371 bool pkgAcqArchive::QueueNext()
373 for (; Vf
.end() == false; Vf
++)
375 // Ignore not source sources
376 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) != 0)
379 // Try to cross match against the source list
380 string PkgFile
= flNotDir(Vf
.File().FileName());
381 pkgSourceList::const_iterator Location
;
382 for (Location
= Sources
->begin(); Location
!= Sources
->end(); Location
++)
383 if (PkgFile
== URItoFileName(Location
->PackagesURI()))
386 if (Location
== Sources
->end())
389 // Grab the text package record
390 pkgRecords::Parser
&Parse
= Recs
->Lookup(Vf
);
391 if (_error
->PendingError() == true)
394 PkgFile
= Parse
.FileName();
395 MD5
= Parse
.MD5Hash();
396 if (PkgFile
.empty() == true)
397 return _error
->Error("The package index files are corrupted. No Filename: "
398 "field for package %s."
399 ,Version
.ParentPkg().Name());
401 // See if we already have the file.
402 FileSize
= Version
->Size
;
403 string FinalFile
= _config
->FindDir("Dir::Cache::Archives") + flNotDir(PkgFile
);
405 if (stat(FinalFile
.c_str(),&Buf
) == 0)
407 // Make sure the size matches
408 if ((unsigned)Buf
.st_size
== Version
->Size
)
413 StoreFilename
= DestFile
= FinalFile
;
417 /* Hmm, we have a file and its size does not match, this shouldnt
419 unlink(FinalFile
.c_str());
422 DestFile
= _config
->FindDir("Dir::Cache::Archives") + "partial/" + flNotDir(PkgFile
);
425 Desc
.URI
= Location
->ArchiveURI(PkgFile
);
426 Desc
.Description
= Location
->ArchiveInfo(Version
);
428 Desc
.ShortDesc
= Version
.ParentPkg().Name();
437 // AcqArchive::Done - Finished fetching /*{{{*/
438 // ---------------------------------------------------------------------
440 void pkgAcqArchive::Done(string Message
,unsigned long Size
,string Md5Hash
)
442 Item::Done(Message
,Size
,Md5Hash
);
445 if (Size
!= Version
->Size
)
447 _error
->Error("Size mismatch for package %s",Version
.ParentPkg().Name());
452 if (Md5Hash
.empty() == false && MD5
.empty() == false)
456 _error
->Error("MD5Sum mismatch for package %s",Version
.ParentPkg().Name());
461 // Grab the output filename
462 string FileName
= LookupTag(Message
,"Filename");
463 if (FileName
.empty() == true)
466 ErrorText
= "Method gave a blank filename";
472 // Reference filename
473 if (FileName
!= DestFile
)
475 StoreFilename
= DestFile
= FileName
;
480 // Done, move it into position
481 string FinalFile
= _config
->FindDir("Dir::Cache::Archives");
482 FinalFile
+= flNotDir(DestFile
);
483 Rename(DestFile
,FinalFile
);
485 StoreFilename
= DestFile
= FinalFile
;
489 // AcqArchive::Describe - Describe the Item /*{{{*/
490 // ---------------------------------------------------------------------
492 string
pkgAcqArchive::Describe()
497 // AcqArchive::Failed - Failure handler /*{{{*/
498 // ---------------------------------------------------------------------
499 /* Here we try other sources */
500 void pkgAcqArchive::Failed(string Message
,pkgAcquire::MethodConfig
*Cnf
)
502 ErrorText
= LookupTag(Message
,"Message");
503 if (QueueNext() == false)
505 // This is the retry counter
507 Cnf
->LocalOnly
== false &&
508 StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
511 Vf
= Version
.FileList();
512 if (QueueNext() == true)
516 Item::Failed(Message
,Cnf
);