]>
git.saurik.com Git - apt.git/blob - apt-pkg/acquire-item.cc
cfd0e5d028659ea997b62e5915de034cd25bc27a
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: acquire-item.cc,v 1.13 1998/11/22 03:20:30 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 ErrorText
= LookupTag(Message
,"Message");
65 // Acquire::Item::Start - Item has begun to download /*{{{*/
66 // ---------------------------------------------------------------------
68 void pkgAcquire::Item::Start(string Message
,unsigned long Size
)
70 Status
= StatFetching
;
71 if (FileSize
== 0 && Complete
== false)
75 // Acquire::Item::Done - Item downloaded OK /*{{{*/
76 // ---------------------------------------------------------------------
78 void pkgAcquire::Item::Done(string Message
,unsigned long Size
,string
)
80 // We just downloaded something..
81 string FileName
= LookupTag(Message
,"Filename");
82 if (Complete
== false && FileName
== DestFile
)
85 Owner
->Log
->Fetched(Size
,atoi(LookupTag(Message
,"Resume-Point","0").c_str()));
93 // Acquire::Item::Rename - Rename a file /*{{{*/
94 // ---------------------------------------------------------------------
95 /* This helper function is used by alot of item methods as thier final
97 void pkgAcquire::Item::Rename(string From
,string To
)
99 if (rename(From
.c_str(),To
.c_str()) != 0)
102 sprintf(S
,"rename failed, %s (%s -> %s).",strerror(errno
),
103 From
.c_str(),To
.c_str());
110 // AcqIndex::AcqIndex - Constructor /*{{{*/
111 // ---------------------------------------------------------------------
112 /* The package file is added to the queue and a second class is
113 instantiated to fetch the revision file */
114 pkgAcqIndex::pkgAcqIndex(pkgAcquire
*Owner
,const pkgSourceList::Item
*Location
) :
115 Item(Owner
), Location(Location
)
117 Decompression
= false;
120 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
121 DestFile
+= URItoFileName(Location
->PackagesURI());
124 Desc
.URI
= Location
->PackagesURI() + ".gz";
125 Desc
.Description
= Location
->PackagesInfo();
128 // Set the short description to the archive component
129 if (Location
->Dist
[Location
->Dist
.size() - 1] == '/')
130 Desc
.ShortDesc
= Location
->Dist
;
132 Desc
.ShortDesc
= Location
->Dist
+ '/' + Location
->Section
;
136 // Create the Release fetch class
137 new pkgAcqIndexRel(Owner
,Location
);
140 // AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
141 // ---------------------------------------------------------------------
142 /* The only header we use is the last-modified header. */
143 string
pkgAcqIndex::Custom600Headers()
145 string Final
= _config
->FindDir("Dir::State::lists");
146 Final
+= URItoFileName(Location
->PackagesURI());
149 if (stat(Final
.c_str(),&Buf
) != 0)
152 return "\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
155 // AcqIndex::Done - Finished a fetch /*{{{*/
156 // ---------------------------------------------------------------------
157 /* This goes through a number of states.. On the initial fetch the
158 method could possibly return an alternate filename which points
159 to the uncompressed version of the file. If this is so the file
160 is copied into the partial directory. In all other cases the file
161 is decompressed with a gzip uri. */
162 void pkgAcqIndex::Done(string Message
,unsigned long Size
,string MD5
)
164 Item::Done(Message
,Size
,MD5
);
166 if (Decompression
== true)
168 // Done, move it into position
169 string FinalFile
= _config
->FindDir("Dir::State::lists");
170 FinalFile
+= URItoFileName(Location
->PackagesURI());
171 Rename(DestFile
,FinalFile
);
173 /* We restore the original name to DestFile so that the clean operation
175 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
176 DestFile
+= URItoFileName(Location
->PackagesURI());
178 // Remove the compressed version.
180 unlink(DestFile
.c_str());
187 // Handle the unzipd case
188 string FileName
= LookupTag(Message
,"Alt-Filename");
189 if (FileName
.empty() == false)
191 // The files timestamp matches
192 if (StringToBool(LookupTag(Message
,"Alt-IMS-Hit"),false) == true)
195 Decompression
= true;
197 DestFile
+= ".decomp";
198 Desc
.URI
= "copy:" + FileName
;
204 FileName
= LookupTag(Message
,"Filename");
205 if (FileName
.empty() == true)
208 ErrorText
= "Method gave a blank filename";
211 // The files timestamp matches
212 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true)
215 if (FileName
== DestFile
)
220 Decompression
= true;
221 DestFile
+= ".decomp";
222 Desc
.URI
= "gzip:" + FileName
,Location
->PackagesInfo();
227 // AcqIndex::Describe - Describe the Item /*{{{*/
228 // ---------------------------------------------------------------------
230 string
pkgAcqIndex::Describe()
232 return Location
->PackagesURI();
236 // AcqIndexRel::pkgAcqIndexRel - Constructor /*{{{*/
237 // ---------------------------------------------------------------------
238 /* The Release file is added to the queue */
239 pkgAcqIndexRel::pkgAcqIndexRel(pkgAcquire
*Owner
,
240 const pkgSourceList::Item
*Location
) :
241 Item(Owner
), Location(Location
)
243 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
244 DestFile
+= URItoFileName(Location
->ReleaseURI());
247 Desc
.URI
= Location
->ReleaseURI();
248 Desc
.Description
= Location
->ReleaseInfo();
251 // Set the short description to the archive component
252 if (Location
->Dist
[Location
->Dist
.size() - 1] == '/')
253 Desc
.ShortDesc
= Location
->Dist
;
255 Desc
.ShortDesc
= Location
->Dist
+ '/' + Location
->Section
;
260 // AcqIndexRel::Custom600Headers - Insert custom request headers /*{{{*/
261 // ---------------------------------------------------------------------
262 /* The only header we use is the last-modified header. */
263 string
pkgAcqIndexRel::Custom600Headers()
265 string Final
= _config
->FindDir("Dir::State::lists");
266 Final
+= URItoFileName(Location
->ReleaseURI());
269 if (stat(Final
.c_str(),&Buf
) != 0)
272 return "\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
275 // AcqIndexRel::Done - Item downloaded OK /*{{{*/
276 // ---------------------------------------------------------------------
277 /* The release file was not placed into the download directory then
278 a copy URI is generated and it is copied there otherwise the file
279 in the partial directory is moved into .. and the URI is finished. */
280 void pkgAcqIndexRel::Done(string Message
,unsigned long Size
,string MD5
)
282 Item::Done(Message
,Size
,MD5
);
284 string FileName
= LookupTag(Message
,"Filename");
285 if (FileName
.empty() == true)
288 ErrorText
= "Method gave a blank filename";
294 // The files timestamp matches
295 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true)
298 // We have to copy it into place
299 if (FileName
!= DestFile
)
302 Desc
.URI
= "copy:" + FileName
;
307 // Done, move it into position
308 string FinalFile
= _config
->FindDir("Dir::State::lists");
309 FinalFile
+= URItoFileName(Location
->ReleaseURI());
310 Rename(DestFile
,FinalFile
);
313 // AcqIndexRel::Describe - Describe the Item /*{{{*/
314 // ---------------------------------------------------------------------
316 string
pkgAcqIndexRel::Describe()
318 return Location
->ReleaseURI();
322 // AcqArchive::AcqArchive - Constructor /*{{{*/
323 // ---------------------------------------------------------------------
325 pkgAcqArchive::pkgAcqArchive(pkgAcquire
*Owner
,pkgSourceList
*Sources
,
326 pkgRecords
*Recs
,pkgCache::VerIterator
const &Version
,
327 string
&StoreFilename
) :
328 Item(Owner
), Version(Version
), Sources(Sources
), Recs(Recs
),
329 StoreFilename(StoreFilename
)
332 pkgCache::VerFileIterator Vf
= Version
.FileList();
333 for (; Vf
.end() == false; Vf
++)
335 // Ignore not source sources
336 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) != 0)
339 // Try to cross match against the source list
340 string PkgFile
= flNotDir(Vf
.File().FileName());
341 pkgSourceList::const_iterator Location
;
342 for (Location
= Sources
->begin(); Location
!= Sources
->end(); Location
++)
343 if (PkgFile
== URItoFileName(Location
->PackagesURI()))
346 if (Location
== Sources
->end())
349 // Grab the text package record
350 pkgRecords::Parser
&Parse
= Recs
->Lookup(Vf
);
351 if (_error
->PendingError() == true)
354 PkgFile
= Parse
.FileName();
355 MD5
= Parse
.MD5Hash();
356 if (PkgFile
.empty() == true)
358 _error
->Error("Unable to locate a file name for package %s, "
359 "perhaps the package files are corrupted.",
360 Version
.ParentPkg().Name());
364 // See if we already have the file.
365 FileSize
= Version
->Size
;
366 string FinalFile
= _config
->FindDir("Dir::Cache::Archives") + flNotDir(PkgFile
);
368 if (stat(FinalFile
.c_str(),&Buf
) == 0)
370 // Make sure the size matches
371 if ((unsigned)Buf
.st_size
== Version
->Size
)
376 StoreFilename
= DestFile
= FinalFile
;
380 /* Hmm, we have a file and its size does not match, this shouldnt
382 unlink(FinalFile
.c_str());
385 DestFile
= _config
->FindDir("Dir::Cache::Archives") + "partial/" + flNotDir(PkgFile
);
388 Desc
.URI
= Location
->ArchiveURI(PkgFile
);
389 Desc
.Description
= Location
->ArchiveInfo(Version
);
391 Desc
.ShortDesc
= Version
.ParentPkg().Name();
397 _error
->Error("I wasn't able to locate file for the %s package. "
398 "This probably means you need to rerun update.",
399 Version
.ParentPkg().Name());
402 // AcqArchive::Done - Finished fetching /*{{{*/
403 // ---------------------------------------------------------------------
405 void pkgAcqArchive::Done(string Message
,unsigned long Size
,string Md5Hash
)
407 Item::Done(Message
,Size
,MD5
);
410 if (Size
!= Version
->Size
)
412 _error
->Error("Size mismatch for package %s",Version
.ParentPkg().Name());
417 if (Md5Hash
.empty() == false && MD5
.empty() == false)
421 _error
->Error("MD5Sum mismatch for package %s",Version
.ParentPkg().Name());
426 // Grab the output filename
427 string FileName
= LookupTag(Message
,"Filename");
428 if (FileName
.empty() == true)
431 ErrorText
= "Method gave a blank filename";
437 // Reference filename
438 if (FileName
!= DestFile
)
440 StoreFilename
= DestFile
= FileName
;
445 // Done, move it into position
446 string FinalFile
= _config
->FindDir("Dir::Cache::Archives");
447 FinalFile
+= flNotDir(DestFile
);
448 Rename(DestFile
,FinalFile
);
450 StoreFilename
= DestFile
= FinalFile
;
454 // AcqArchive::Describe - Describe the Item /*{{{*/
455 // ---------------------------------------------------------------------
457 string
pkgAcqArchive::Describe()