]>
git.saurik.com Git - apt.git/blob - apt-pkg/acquire-item.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: acquire-item.cc,v 1.16 1998/12/11 06:01:23 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>
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
)
57 if (QueueCounter
<= 1)
59 /* This indicates that the file is not available right now but might
60 be sometime later. If we do a retry cycle then this should be
62 if (StringToBool(LookupTag(Message
,"Transient-Failure"),false) == true)
69 ErrorText
= LookupTag(Message
,"Message");
75 // Acquire::Item::Start - Item has begun to download /*{{{*/
76 // ---------------------------------------------------------------------
78 void pkgAcquire::Item::Start(string Message
,unsigned long Size
)
80 Status
= StatFetching
;
81 if (FileSize
== 0 && Complete
== false)
85 // Acquire::Item::Done - Item downloaded OK /*{{{*/
86 // ---------------------------------------------------------------------
88 void pkgAcquire::Item::Done(string Message
,unsigned long Size
,string
)
90 // We just downloaded something..
91 string FileName
= LookupTag(Message
,"Filename");
92 if (Complete
== false && FileName
== DestFile
)
95 Owner
->Log
->Fetched(Size
,atoi(LookupTag(Message
,"Resume-Point","0").c_str()));
100 Owner
->Dequeue(this);
103 // Acquire::Item::Rename - Rename a file /*{{{*/
104 // ---------------------------------------------------------------------
105 /* This helper function is used by alot of item methods as thier final
107 void pkgAcquire::Item::Rename(string From
,string To
)
109 if (rename(From
.c_str(),To
.c_str()) != 0)
112 sprintf(S
,"rename failed, %s (%s -> %s).",strerror(errno
),
113 From
.c_str(),To
.c_str());
120 // AcqIndex::AcqIndex - Constructor /*{{{*/
121 // ---------------------------------------------------------------------
122 /* The package file is added to the queue and a second class is
123 instantiated to fetch the revision file */
124 pkgAcqIndex::pkgAcqIndex(pkgAcquire
*Owner
,const pkgSourceList::Item
*Location
) :
125 Item(Owner
), Location(Location
)
127 Decompression
= false;
130 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
131 DestFile
+= URItoFileName(Location
->PackagesURI());
134 Desc
.URI
= Location
->PackagesURI() + ".gz";
135 Desc
.Description
= Location
->PackagesInfo();
138 // Set the short description to the archive component
139 if (Location
->Dist
[Location
->Dist
.size() - 1] == '/')
140 Desc
.ShortDesc
= Location
->Dist
;
142 Desc
.ShortDesc
= Location
->Dist
+ '/' + Location
->Section
;
146 // Create the Release fetch class
147 new pkgAcqIndexRel(Owner
,Location
);
150 // AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
151 // ---------------------------------------------------------------------
152 /* The only header we use is the last-modified header. */
153 string
pkgAcqIndex::Custom600Headers()
155 string Final
= _config
->FindDir("Dir::State::lists");
156 Final
+= URItoFileName(Location
->PackagesURI());
159 if (stat(Final
.c_str(),&Buf
) != 0)
160 return "\nIndex-File: true";
162 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
165 // AcqIndex::Done - Finished a fetch /*{{{*/
166 // ---------------------------------------------------------------------
167 /* This goes through a number of states.. On the initial fetch the
168 method could possibly return an alternate filename which points
169 to the uncompressed version of the file. If this is so the file
170 is copied into the partial directory. In all other cases the file
171 is decompressed with a gzip uri. */
172 void pkgAcqIndex::Done(string Message
,unsigned long Size
,string MD5
)
174 Item::Done(Message
,Size
,MD5
);
176 if (Decompression
== true)
178 // Done, move it into position
179 string FinalFile
= _config
->FindDir("Dir::State::lists");
180 FinalFile
+= URItoFileName(Location
->PackagesURI());
181 Rename(DestFile
,FinalFile
);
183 /* We restore the original name to DestFile so that the clean operation
185 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
186 DestFile
+= URItoFileName(Location
->PackagesURI());
188 // Remove the compressed version.
190 unlink(DestFile
.c_str());
197 // Handle the unzipd case
198 string FileName
= LookupTag(Message
,"Alt-Filename");
199 if (FileName
.empty() == false)
201 // The files timestamp matches
202 if (StringToBool(LookupTag(Message
,"Alt-IMS-Hit"),false) == true)
205 Decompression
= true;
207 DestFile
+= ".decomp";
208 Desc
.URI
= "copy:" + FileName
;
214 FileName
= LookupTag(Message
,"Filename");
215 if (FileName
.empty() == true)
218 ErrorText
= "Method gave a blank filename";
221 // The files timestamp matches
222 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true)
225 if (FileName
== DestFile
)
230 Decompression
= true;
231 DestFile
+= ".decomp";
232 Desc
.URI
= "gzip:" + FileName
,Location
->PackagesInfo();
237 // AcqIndex::Describe - Describe the Item /*{{{*/
238 // ---------------------------------------------------------------------
240 string
pkgAcqIndex::Describe()
242 return Location
->PackagesURI();
246 // AcqIndexRel::pkgAcqIndexRel - Constructor /*{{{*/
247 // ---------------------------------------------------------------------
248 /* The Release file is added to the queue */
249 pkgAcqIndexRel::pkgAcqIndexRel(pkgAcquire
*Owner
,
250 const pkgSourceList::Item
*Location
) :
251 Item(Owner
), Location(Location
)
253 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
254 DestFile
+= URItoFileName(Location
->ReleaseURI());
257 Desc
.URI
= Location
->ReleaseURI();
258 Desc
.Description
= Location
->ReleaseInfo();
261 // Set the short description to the archive component
262 if (Location
->Dist
[Location
->Dist
.size() - 1] == '/')
263 Desc
.ShortDesc
= Location
->Dist
;
265 Desc
.ShortDesc
= Location
->Dist
+ '/' + Location
->Section
;
270 // AcqIndexRel::Custom600Headers - Insert custom request headers /*{{{*/
271 // ---------------------------------------------------------------------
272 /* The only header we use is the last-modified header. */
273 string
pkgAcqIndexRel::Custom600Headers()
275 string Final
= _config
->FindDir("Dir::State::lists");
276 Final
+= URItoFileName(Location
->ReleaseURI());
279 if (stat(Final
.c_str(),&Buf
) != 0)
280 return "\nIndex-File: true";
282 return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
285 // AcqIndexRel::Done - Item downloaded OK /*{{{*/
286 // ---------------------------------------------------------------------
287 /* The release file was not placed into the download directory then
288 a copy URI is generated and it is copied there otherwise the file
289 in the partial directory is moved into .. and the URI is finished. */
290 void pkgAcqIndexRel::Done(string Message
,unsigned long Size
,string MD5
)
292 Item::Done(Message
,Size
,MD5
);
294 string FileName
= LookupTag(Message
,"Filename");
295 if (FileName
.empty() == true)
298 ErrorText
= "Method gave a blank filename";
304 // The files timestamp matches
305 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true)
308 // We have to copy it into place
309 if (FileName
!= DestFile
)
312 Desc
.URI
= "copy:" + FileName
;
317 // Done, move it into position
318 string FinalFile
= _config
->FindDir("Dir::State::lists");
319 FinalFile
+= URItoFileName(Location
->ReleaseURI());
320 Rename(DestFile
,FinalFile
);
323 // AcqIndexRel::Describe - Describe the Item /*{{{*/
324 // ---------------------------------------------------------------------
326 string
pkgAcqIndexRel::Describe()
328 return Location
->ReleaseURI();
332 // AcqArchive::AcqArchive - Constructor /*{{{*/
333 // ---------------------------------------------------------------------
335 pkgAcqArchive::pkgAcqArchive(pkgAcquire
*Owner
,pkgSourceList
*Sources
,
336 pkgRecords
*Recs
,pkgCache::VerIterator
const &Version
,
337 string
&StoreFilename
) :
338 Item(Owner
), Version(Version
), Sources(Sources
), Recs(Recs
),
339 StoreFilename(StoreFilename
), Vf(Version
.FileList())
342 if (QueueNext() == false && _error
->PendingError() == false)
343 _error
->Error("I wasn't able to locate file for the %s package. "
344 "This might mean you need to manually fix this package.",
345 Version
.ParentPkg().Name());
348 // AcqArchive::QueueNext - Queue the next file source /*{{{*/
349 // ---------------------------------------------------------------------
350 /* This queues the next available file version for download. */
351 bool pkgAcqArchive::QueueNext()
353 for (; Vf
.end() == false; Vf
++)
355 // Ignore not source sources
356 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) != 0)
359 // Try to cross match against the source list
360 string PkgFile
= flNotDir(Vf
.File().FileName());
361 pkgSourceList::const_iterator Location
;
362 for (Location
= Sources
->begin(); Location
!= Sources
->end(); Location
++)
363 if (PkgFile
== URItoFileName(Location
->PackagesURI()))
366 if (Location
== Sources
->end())
369 // Grab the text package record
370 pkgRecords::Parser
&Parse
= Recs
->Lookup(Vf
);
371 if (_error
->PendingError() == true)
374 PkgFile
= Parse
.FileName();
375 MD5
= Parse
.MD5Hash();
376 if (PkgFile
.empty() == true)
377 return _error
->Error("The package index files are corrupted. No Filename: "
378 "field for package %s."
379 ,Version
.ParentPkg().Name());
381 // See if we already have the file.
382 FileSize
= Version
->Size
;
383 string FinalFile
= _config
->FindDir("Dir::Cache::Archives") + flNotDir(PkgFile
);
385 if (stat(FinalFile
.c_str(),&Buf
) == 0)
387 // Make sure the size matches
388 if ((unsigned)Buf
.st_size
== Version
->Size
)
393 StoreFilename
= DestFile
= FinalFile
;
397 /* Hmm, we have a file and its size does not match, this shouldnt
399 unlink(FinalFile
.c_str());
402 DestFile
= _config
->FindDir("Dir::Cache::Archives") + "partial/" + flNotDir(PkgFile
);
405 Desc
.URI
= Location
->ArchiveURI(PkgFile
);
406 Desc
.Description
= Location
->ArchiveInfo(Version
);
408 Desc
.ShortDesc
= Version
.ParentPkg().Name();
417 // AcqArchive::Done - Finished fetching /*{{{*/
418 // ---------------------------------------------------------------------
420 void pkgAcqArchive::Done(string Message
,unsigned long Size
,string Md5Hash
)
422 Item::Done(Message
,Size
,MD5
);
425 if (Size
!= Version
->Size
)
427 _error
->Error("Size mismatch for package %s",Version
.ParentPkg().Name());
432 if (Md5Hash
.empty() == false && MD5
.empty() == false)
436 _error
->Error("MD5Sum mismatch for package %s",Version
.ParentPkg().Name());
441 // Grab the output filename
442 string FileName
= LookupTag(Message
,"Filename");
443 if (FileName
.empty() == true)
446 ErrorText
= "Method gave a blank filename";
452 // Reference filename
453 if (FileName
!= DestFile
)
455 StoreFilename
= DestFile
= FileName
;
460 // Done, move it into position
461 string FinalFile
= _config
->FindDir("Dir::Cache::Archives");
462 FinalFile
+= flNotDir(DestFile
);
463 Rename(DestFile
,FinalFile
);
465 StoreFilename
= DestFile
= FinalFile
;
469 // AcqArchive::Describe - Describe the Item /*{{{*/
470 // ---------------------------------------------------------------------
472 string
pkgAcqArchive::Describe()