]>
git.saurik.com Git - apt.git/blob - apt-pkg/acquire-item.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: acquire-item.cc,v 1.12 1998/11/13 07:08:48 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();
228 // AcqIndexRel::pkgAcqIndexRel - Constructor /*{{{*/
229 // ---------------------------------------------------------------------
230 /* The Release file is added to the queue */
231 pkgAcqIndexRel::pkgAcqIndexRel(pkgAcquire
*Owner
,
232 const pkgSourceList::Item
*Location
) :
233 Item(Owner
), Location(Location
)
235 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
236 DestFile
+= URItoFileName(Location
->ReleaseURI());
239 Desc
.URI
= Location
->ReleaseURI();
240 Desc
.Description
= Location
->ReleaseInfo();
243 // Set the short description to the archive component
244 if (Location
->Dist
[Location
->Dist
.size() - 1] == '/')
245 Desc
.ShortDesc
= Location
->Dist
;
247 Desc
.ShortDesc
= Location
->Dist
+ '/' + Location
->Section
;
252 // AcqIndexRel::Custom600Headers - Insert custom request headers /*{{{*/
253 // ---------------------------------------------------------------------
254 /* The only header we use is the last-modified header. */
255 string
pkgAcqIndexRel::Custom600Headers()
257 string Final
= _config
->FindDir("Dir::State::lists");
258 Final
+= URItoFileName(Location
->ReleaseURI());
261 if (stat(Final
.c_str(),&Buf
) != 0)
264 return "\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
267 // AcqIndexRel::Done - Item downloaded OK /*{{{*/
268 // ---------------------------------------------------------------------
269 /* The release file was not placed into the download directory then
270 a copy URI is generated and it is copied there otherwise the file
271 in the partial directory is moved into .. and the URI is finished. */
272 void pkgAcqIndexRel::Done(string Message
,unsigned long Size
,string MD5
)
274 Item::Done(Message
,Size
,MD5
);
276 string FileName
= LookupTag(Message
,"Filename");
277 if (FileName
.empty() == true)
280 ErrorText
= "Method gave a blank filename";
286 // The files timestamp matches
287 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true)
290 // We have to copy it into place
291 if (FileName
!= DestFile
)
294 Desc
.URI
= "copy:" + FileName
;
299 // Done, move it into position
300 string FinalFile
= _config
->FindDir("Dir::State::lists");
301 FinalFile
+= URItoFileName(Location
->ReleaseURI());
302 Rename(DestFile
,FinalFile
);
306 // AcqArchive::AcqArchive - Constructor /*{{{*/
307 // ---------------------------------------------------------------------
309 pkgAcqArchive::pkgAcqArchive(pkgAcquire
*Owner
,pkgSourceList
*Sources
,
310 pkgRecords
*Recs
,pkgCache::VerIterator
const &Version
) :
311 Item(Owner
), Version(Version
), Sources(Sources
), Recs(Recs
)
314 pkgCache::VerFileIterator Vf
= Version
.FileList();
315 for (; Vf
.end() == false; Vf
++)
317 // Ignore not source sources
318 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) != 0)
321 // Try to cross match against the source list
322 string PkgFile
= flNotDir(Vf
.File().FileName());
323 pkgSourceList::const_iterator Location
;
324 for (Location
= Sources
->begin(); Location
!= Sources
->end(); Location
++)
325 if (PkgFile
== URItoFileName(Location
->PackagesURI()))
328 if (Location
== Sources
->end())
331 // Grab the text package record
332 pkgRecords::Parser
&Parse
= Recs
->Lookup(Vf
);
333 if (_error
->PendingError() == true)
336 PkgFile
= Parse
.FileName();
337 MD5
= Parse
.MD5Hash();
338 if (PkgFile
.empty() == true)
340 _error
->Error("Unable to locate a file name for package %s, "
341 "perhaps the package files are corrupted.",
342 Version
.ParentPkg().Name());
346 // See if we already have the file.
347 FileSize
= Version
->Size
;
348 string FinalFile
= _config
->FindDir("Dir::Cache::Archives") + flNotDir(PkgFile
);
350 if (stat(FinalFile
.c_str(),&Buf
) == 0)
352 // Make sure the size matches
353 if ((unsigned)Buf
.st_size
== Version
->Size
)
358 DestFile
= FinalFile
;
362 /* Hmm, we have a file and its size does not match, this shouldnt
364 unlink(FinalFile
.c_str());
367 DestFile
= _config
->FindDir("Dir::Cache::Archives") + "partial/" + flNotDir(PkgFile
);
370 Desc
.URI
= Location
->ArchiveURI(PkgFile
);
371 Desc
.Description
= Location
->ArchiveInfo(Version
);
373 Desc
.ShortDesc
= Version
.ParentPkg().Name();
379 _error
->Error("I wasn't able to locate file for the %s package. "
380 "This probably means you need to rerun update.",
381 Version
.ParentPkg().Name());
384 // AcqArchive::Done - Finished fetching /*{{{*/
385 // ---------------------------------------------------------------------
387 void pkgAcqArchive::Done(string Message
,unsigned long Size
,string Md5Hash
)
389 Item::Done(Message
,Size
,MD5
);
392 if (Size
!= Version
->Size
)
394 _error
->Error("Size mismatch for package %s",Version
.ParentPkg().Name());
399 if (Md5Hash
.empty() == false && MD5
.empty() == false)
403 _error
->Error("MD5Sum mismatch for package %s",Version
.ParentPkg().Name());
408 // Grab the output filename
409 string FileName
= LookupTag(Message
,"Filename");
410 if (FileName
.empty() == true)
413 ErrorText
= "Method gave a blank filename";
419 // We have to copy it into place
420 if (FileName
!= DestFile
)
427 // Done, move it into position
428 string FinalFile
= _config
->FindDir("Dir::Cache::Archives");
429 FinalFile
+= flNotDir(DestFile
);
430 Rename(DestFile
,FinalFile
);
432 DestFile
= FinalFile
;