]>
git.saurik.com Git - apt.git/blob - apt-pkg/acquire-item.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: acquire-item.cc,v 1.11 1998/11/13 04:23:26 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), QueueCounter(0)
41 // Acquire::Item::~Item - Destructor /*{{{*/
42 // ---------------------------------------------------------------------
44 pkgAcquire::Item::~Item()
49 // Acquire::Item::Failed - Item failed to download /*{{{*/
50 // ---------------------------------------------------------------------
51 /* We return to an idle state if there are still other queues that could
53 void pkgAcquire::Item::Failed(string Message
)
56 if (QueueCounter
<= 1)
58 ErrorText
= LookupTag(Message
,"Message");
64 // Acquire::Item::Start - Item has begun to download /*{{{*/
65 // ---------------------------------------------------------------------
67 void pkgAcquire::Item::Start(string Message
,unsigned long Size
)
69 Status
= StatFetching
;
70 if (FileSize
== 0 && Complete
== false)
74 // Acquire::Item::Done - Item downloaded OK /*{{{*/
75 // ---------------------------------------------------------------------
77 void pkgAcquire::Item::Done(string Message
,unsigned long Size
,string
)
79 // We just downloaded something..
80 string FileName
= LookupTag(Message
,"Filename");
81 if (Complete
== false && FileName
== DestFile
)
84 Owner
->Log
->Fetched(Size
,atoi(LookupTag(Message
,"Resume-Point","0").c_str()));
92 // Acquire::Item::Rename - Rename a file /*{{{*/
93 // ---------------------------------------------------------------------
94 /* This helper function is used by alot of item methods as thier final
96 void pkgAcquire::Item::Rename(string From
,string To
)
98 if (rename(From
.c_str(),To
.c_str()) != 0)
101 sprintf(S
,"rename failed, %s (%s -> %s).",strerror(errno
),
102 From
.c_str(),To
.c_str());
109 // AcqIndex::AcqIndex - Constructor /*{{{*/
110 // ---------------------------------------------------------------------
111 /* The package file is added to the queue and a second class is
112 instantiated to fetch the revision file */
113 pkgAcqIndex::pkgAcqIndex(pkgAcquire
*Owner
,const pkgSourceList::Item
*Location
) :
114 Item(Owner
), Location(Location
)
116 Decompression
= false;
119 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
120 DestFile
+= URItoFileName(Location
->PackagesURI());
123 Desc
.URI
= Location
->PackagesURI() + ".gz";
124 Desc
.Description
= Location
->PackagesInfo();
127 // Set the short description to the archive component
128 if (Location
->Dist
[Location
->Dist
.size() - 1] == '/')
129 Desc
.ShortDesc
= Location
->Dist
;
131 Desc
.ShortDesc
= Location
->Dist
+ '/' + Location
->Section
;
135 // Create the Release fetch class
136 new pkgAcqIndexRel(Owner
,Location
);
139 // AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
140 // ---------------------------------------------------------------------
141 /* The only header we use is the last-modified header. */
142 string
pkgAcqIndex::Custom600Headers()
144 string Final
= _config
->FindDir("Dir::State::lists");
145 Final
+= URItoFileName(Location
->PackagesURI());
148 if (stat(Final
.c_str(),&Buf
) != 0)
151 return "\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
154 // AcqIndex::Done - Finished a fetch /*{{{*/
155 // ---------------------------------------------------------------------
156 /* This goes through a number of states.. On the initial fetch the
157 method could possibly return an alternate filename which points
158 to the uncompressed version of the file. If this is so the file
159 is copied into the partial directory. In all other cases the file
160 is decompressed with a gzip uri. */
161 void pkgAcqIndex::Done(string Message
,unsigned long Size
,string MD5
)
163 Item::Done(Message
,Size
,MD5
);
165 if (Decompression
== true)
167 // Done, move it into position
168 string FinalFile
= _config
->FindDir("Dir::State::lists");
169 FinalFile
+= URItoFileName(Location
->PackagesURI());
170 Rename(DestFile
,FinalFile
);
172 /* We restore the original name to DestFile so that the clean operation
174 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
175 DestFile
+= URItoFileName(Location
->PackagesURI());
177 // Remove the compressed version.
179 unlink(DestFile
.c_str());
186 // Handle the unzipd case
187 string FileName
= LookupTag(Message
,"Alt-Filename");
188 if (FileName
.empty() == false)
190 // The files timestamp matches
191 if (StringToBool(LookupTag(Message
,"Alt-IMS-Hit"),false) == true)
194 Decompression
= true;
196 DestFile
+= ".decomp";
197 Desc
.URI
= "copy:" + FileName
;
203 FileName
= LookupTag(Message
,"Filename");
204 if (FileName
.empty() == true)
207 ErrorText
= "Method gave a blank filename";
210 // The files timestamp matches
211 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true)
214 if (FileName
== DestFile
)
219 Decompression
= true;
220 DestFile
+= ".decomp";
221 Desc
.URI
= "gzip:" + FileName
,Location
->PackagesInfo();
227 // AcqIndexRel::pkgAcqIndexRel - Constructor /*{{{*/
228 // ---------------------------------------------------------------------
229 /* The Release file is added to the queue */
230 pkgAcqIndexRel::pkgAcqIndexRel(pkgAcquire
*Owner
,
231 const pkgSourceList::Item
*Location
) :
232 Item(Owner
), Location(Location
)
234 DestFile
= _config
->FindDir("Dir::State::lists") + "partial/";
235 DestFile
+= URItoFileName(Location
->ReleaseURI());
238 Desc
.URI
= Location
->ReleaseURI();
239 Desc
.Description
= Location
->ReleaseInfo();
242 // Set the short description to the archive component
243 if (Location
->Dist
[Location
->Dist
.size() - 1] == '/')
244 Desc
.ShortDesc
= Location
->Dist
;
246 Desc
.ShortDesc
= Location
->Dist
+ '/' + Location
->Section
;
251 // AcqIndexRel::Custom600Headers - Insert custom request headers /*{{{*/
252 // ---------------------------------------------------------------------
253 /* The only header we use is the last-modified header. */
254 string
pkgAcqIndexRel::Custom600Headers()
256 string Final
= _config
->FindDir("Dir::State::lists");
257 Final
+= URItoFileName(Location
->ReleaseURI());
260 if (stat(Final
.c_str(),&Buf
) != 0)
263 return "\nLast-Modified: " + TimeRFC1123(Buf
.st_mtime
);
266 // AcqIndexRel::Done - Item downloaded OK /*{{{*/
267 // ---------------------------------------------------------------------
268 /* The release file was not placed into the download directory then
269 a copy URI is generated and it is copied there otherwise the file
270 in the partial directory is moved into .. and the URI is finished. */
271 void pkgAcqIndexRel::Done(string Message
,unsigned long Size
,string MD5
)
273 Item::Done(Message
,Size
,MD5
);
275 string FileName
= LookupTag(Message
,"Filename");
276 if (FileName
.empty() == true)
279 ErrorText
= "Method gave a blank filename";
285 // The files timestamp matches
286 if (StringToBool(LookupTag(Message
,"IMS-Hit"),false) == true)
289 // We have to copy it into place
290 if (FileName
!= DestFile
)
293 Desc
.URI
= "copy:" + FileName
;
298 // Done, move it into position
299 string FinalFile
= _config
->FindDir("Dir::State::lists");
300 FinalFile
+= URItoFileName(Location
->ReleaseURI());
301 Rename(DestFile
,FinalFile
);
305 // AcqArchive::AcqArchive - Constructor /*{{{*/
306 // ---------------------------------------------------------------------
308 pkgAcqArchive::pkgAcqArchive(pkgAcquire
*Owner
,pkgSourceList
*Sources
,
309 pkgRecords
*Recs
,pkgCache::VerIterator
const &Version
) :
310 Item(Owner
), Version(Version
), Sources(Sources
), Recs(Recs
)
313 pkgCache::VerFileIterator Vf
= Version
.FileList();
314 for (; Vf
.end() == false; Vf
++)
316 // Ignore not source sources
317 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) != 0)
320 // Try to cross match against the source list
321 string PkgFile
= flNotDir(Vf
.File().FileName());
322 pkgSourceList::const_iterator Location
;
323 for (Location
= Sources
->begin(); Location
!= Sources
->end(); Location
++)
324 if (PkgFile
== URItoFileName(Location
->PackagesURI()))
327 if (Location
== Sources
->end())
330 // Grab the text package record
331 pkgRecords::Parser
&Parse
= Recs
->Lookup(Vf
);
332 if (_error
->PendingError() == true)
335 PkgFile
= Parse
.FileName();
336 MD5
= Parse
.MD5Hash();
337 if (PkgFile
.empty() == true)
339 _error
->Error("Unable to locate a file name for package %s, "
340 "perhaps the package files are corrupted.",
341 Version
.ParentPkg().Name());
346 Desc
.URI
= Location
->ArchiveURI(PkgFile
);
347 Desc
.Description
= Location
->ArchiveInfo(Version
);
349 Desc
.ShortDesc
= Version
.ParentPkg().Name();
352 DestFile
= _config
->FindDir("Dir::Cache::Archives") + "partial/" + flNotDir(PkgFile
);
356 _error
->Error("I wasn't able to locate file for the %s package. "
357 "This probably means you need to rerun update.",
358 Version
.ParentPkg().Name());
361 // AcqArchive::Done - Finished fetching /*{{{*/
362 // ---------------------------------------------------------------------
364 void pkgAcqArchive::Done(string Message
,unsigned long Size
,string Md5Hash
)
366 Item::Done(Message
,Size
,MD5
);
369 if (Size
!= Version
->Size
)
371 _error
->Error("Size mismatch for package %s",Version
.ParentPkg().Name());
376 if (Md5Hash
.empty() == false && MD5
.empty() == false)
380 _error
->Error("MD5Sum mismatch for package %s",Version
.ParentPkg().Name());
385 // Store the destination filename
386 string FileName
= LookupTag(Message
,"Filename");
387 if (FileName
.empty() == true)
390 ErrorText
= "Method gave a blank filename";