]> git.saurik.com Git - apt.git/blob - apt-pkg/acquire-item.cc
apt-get update works
[apt.git] / apt-pkg / acquire-item.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: acquire-item.cc,v 1.9 1998/11/11 06:54:13 jgg Exp $
4 /* ######################################################################
5
6 Acquire Item - Item to acquire
7
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.
12
13 ##################################################################### */
14 /*}}}*/
15 // Include Files /*{{{*/
16 #ifdef __GNUG__
17 #pragma implementation "apt-pkg/acquire-item.h"
18 #endif
19 #include <apt-pkg/acquire-item.h>
20 #include <apt-pkg/configuration.h>
21 #include <strutl.h>
22
23 #include <sys/stat.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <string.h>
27 #include <stdio.h>
28 /*}}}*/
29
30 // Acquire::Item::Item - Constructor /*{{{*/
31 // ---------------------------------------------------------------------
32 /* */
33 pkgAcquire::Item::Item(pkgAcquire *Owner) : Owner(Owner), FileSize(0),
34 Mode(0), ID(0), Complete(false), QueueCounter(0)
35 {
36 Owner->Add(this);
37 Status = StatIdle;
38 }
39 /*}}}*/
40 // Acquire::Item::~Item - Destructor /*{{{*/
41 // ---------------------------------------------------------------------
42 /* */
43 pkgAcquire::Item::~Item()
44 {
45 Owner->Remove(this);
46 }
47 /*}}}*/
48 // Acquire::Item::Failed - Item failed to download /*{{{*/
49 // ---------------------------------------------------------------------
50 /* We return to an idle state if there are still other queues that could
51 fetch this object */
52 void pkgAcquire::Item::Failed(string Message)
53 {
54 Status = StatIdle;
55 if (QueueCounter <= 1)
56 {
57 ErrorText = LookupTag(Message,"Message");
58 Status = StatError;
59 Owner->Dequeue(this);
60 }
61 }
62 /*}}}*/
63 // Acquire::Item::Start - Item has begun to download /*{{{*/
64 // ---------------------------------------------------------------------
65 /* */
66 void pkgAcquire::Item::Start(string Message,unsigned long Size)
67 {
68 Status = StatFetching;
69 if (FileSize == 0 && Complete == false)
70 FileSize = Size;
71 }
72 /*}}}*/
73 // Acquire::Item::Done - Item downloaded OK /*{{{*/
74 // ---------------------------------------------------------------------
75 /* */
76 void pkgAcquire::Item::Done(string Message,unsigned long Size,string)
77 {
78 // We just downloaded something..
79 string FileName = LookupTag(Message,"Filename");
80 if (Complete == false && FileName == DestFile)
81 {
82 if (Owner->Log != 0)
83 Owner->Log->Fetched(Size,atoi(LookupTag(Message,"Resume-Point","0").c_str()));
84 }
85
86 Status = StatDone;
87 ErrorText = string();
88 Owner->Dequeue(this);
89 }
90 /*}}}*/
91 // Acquire::Item::Rename - Rename a file /*{{{*/
92 // ---------------------------------------------------------------------
93 /* This helper function is used by alot of item methods as thier final
94 step */
95 void pkgAcquire::Item::Rename(string From,string To)
96 {
97 if (rename(From.c_str(),To.c_str()) != 0)
98 {
99 char S[300];
100 sprintf(S,"rename failed, %s (%s -> %s).",strerror(errno),
101 From.c_str(),To.c_str());
102 Status = StatError;
103 ErrorText = S;
104 }
105 }
106 /*}}}*/
107
108 // AcqIndex::AcqIndex - Constructor /*{{{*/
109 // ---------------------------------------------------------------------
110 /* The package file is added to the queue and a second class is
111 instantiated to fetch the revision file */
112 pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,const pkgSourceList::Item *Location) :
113 Item(Owner), Location(Location)
114 {
115 Decompression = false;
116 Erase = false;
117
118 DestFile = _config->FindDir("Dir::State::lists") + "partial/";
119 DestFile += URItoFileName(Location->PackagesURI());
120
121 // Create the item
122 Desc.URI = Location->PackagesURI() + ".gz";
123 Desc.Description = Location->PackagesInfo();
124 Desc.Owner = this;
125
126 // Set the short description to the archive component
127 if (Location->Dist[Location->Dist.size() - 1] == '/')
128 Desc.ShortDesc = Location->Dist;
129 else
130 Desc.ShortDesc = Location->Dist + '/' + Location->Section;
131
132 QueueURI(Desc);
133
134 // Create the Release fetch class
135 new pkgAcqIndexRel(Owner,Location);
136 }
137 /*}}}*/
138 // AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
139 // ---------------------------------------------------------------------
140 /* The only header we use is the last-modified header. */
141 string pkgAcqIndex::Custom600Headers()
142 {
143 string Final = _config->FindDir("Dir::State::lists");
144 Final += URItoFileName(Location->PackagesURI());
145
146 struct stat Buf;
147 if (stat(Final.c_str(),&Buf) != 0)
148 return string();
149
150 return "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
151 }
152 /*}}}*/
153 // AcqIndex::Done - Finished a fetch /*{{{*/
154 // ---------------------------------------------------------------------
155 /* This goes through a number of states.. On the initial fetch the
156 method could possibly return an alternate filename which points
157 to the uncompressed version of the file. If this is so the file
158 is copied into the partial directory. In all other cases the file
159 is decompressed with a gzip uri. */
160 void pkgAcqIndex::Done(string Message,unsigned long Size,string MD5)
161 {
162 Item::Done(Message,Size,MD5);
163
164 if (Decompression == true)
165 {
166 // Done, move it into position
167 string FinalFile = _config->FindDir("Dir::State::lists");
168 FinalFile += URItoFileName(Location->PackagesURI());
169 Rename(DestFile,FinalFile);
170
171 // Remove the compressed version.
172 if (Erase == true)
173 {
174 DestFile = _config->FindDir("Dir::State::lists") + "partial/";
175 DestFile += URItoFileName(Location->PackagesURI());
176 unlink(DestFile.c_str());
177 }
178 return;
179 }
180
181 Erase = false;
182 Complete = true;
183
184 // Handle the unzipd case
185 string FileName = LookupTag(Message,"Alt-Filename");
186 if (FileName.empty() == false)
187 {
188 // The files timestamp matches
189 if (StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false) == true)
190 return;
191
192 Decompression = true;
193 FileSize = 0;
194 DestFile += ".decomp";
195 Desc.URI = "copy:" + FileName;
196 QueueURI(Desc);
197 Mode = "copy";
198 return;
199 }
200
201 FileName = LookupTag(Message,"Filename");
202 if (FileName.empty() == true)
203 {
204 Status = StatError;
205 ErrorText = "Method gave a blank filename";
206 }
207
208 // The files timestamp matches
209 if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
210 return;
211
212 if (FileName == DestFile)
213 Erase = true;
214 else
215 FileSize = 0;
216
217 Decompression = true;
218 DestFile += ".decomp";
219 Desc.URI = "gzip:" + FileName,Location->PackagesInfo();
220 QueueURI(Desc);
221 Mode = "gzip";
222 }
223 /*}}}*/
224
225 // AcqIndexRel::pkgAcqIndexRel - Constructor /*{{{*/
226 // ---------------------------------------------------------------------
227 /* The Release file is added to the queue */
228 pkgAcqIndexRel::pkgAcqIndexRel(pkgAcquire *Owner,
229 const pkgSourceList::Item *Location) :
230 Item(Owner), Location(Location)
231 {
232 DestFile = _config->FindDir("Dir::State::lists") + "partial/";
233 DestFile += URItoFileName(Location->ReleaseURI());
234
235 // Create the item
236 Desc.URI = Location->ReleaseURI();
237 Desc.Description = Location->ReleaseInfo();
238 Desc.Owner = this;
239
240 // Set the short description to the archive component
241 if (Location->Dist[Location->Dist.size() - 1] == '/')
242 Desc.ShortDesc = Location->Dist;
243 else
244 Desc.ShortDesc = Location->Dist + '/' + Location->Section;
245
246 QueueURI(Desc);
247 }
248 /*}}}*/
249 // AcqIndexRel::Custom600Headers - Insert custom request headers /*{{{*/
250 // ---------------------------------------------------------------------
251 /* The only header we use is the last-modified header. */
252 string pkgAcqIndexRel::Custom600Headers()
253 {
254 string Final = _config->FindDir("Dir::State::lists");
255 Final += URItoFileName(Location->ReleaseURI());
256
257 struct stat Buf;
258 if (stat(Final.c_str(),&Buf) != 0)
259 return string();
260
261 return "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
262 }
263 /*}}}*/
264 // AcqIndexRel::Done - Item downloaded OK /*{{{*/
265 // ---------------------------------------------------------------------
266 /* The release file was not placed into the download directory then
267 a copy URI is generated and it is copied there otherwise the file
268 in the partial directory is moved into .. and the URI is finished. */
269 void pkgAcqIndexRel::Done(string Message,unsigned long Size,string MD5)
270 {
271 Item::Done(Message,Size,MD5);
272
273 string FileName = LookupTag(Message,"Filename");
274 if (FileName.empty() == true)
275 {
276 Status = StatError;
277 ErrorText = "Method gave a blank filename";
278 return;
279 }
280
281 Complete = true;
282
283 // The files timestamp matches
284 if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
285 return;
286
287 // We have to copy it into place
288 if (FileName != DestFile)
289 {
290 FileSize = 0;
291 Desc.URI = "copy:" + FileName;
292 QueueURI(Desc);
293 return;
294 }
295
296 // Done, move it into position
297 string FinalFile = _config->FindDir("Dir::State::lists");
298 FinalFile += URItoFileName(Location->ReleaseURI());
299 Rename(DestFile,FinalFile);
300 }
301 /*}}}*/