]> git.saurik.com Git - apt.git/blame - apt-pkg/acquire-method.cc
Minor fixes for FTP support
[apt.git] / apt-pkg / acquire-method.cc
CommitLineData
93bf083d
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
6d5dd02a 3// $Id: acquire-method.cc,v 1.18 1999/03/15 08:10:39 jgg Exp $
93bf083d
AL
4/* ######################################################################
5
6 Acquire Method
7
8 ##################################################################### */
9 /*}}}*/
10// Include Files /*{{{*/
11#ifdef __GNUG__
12#pragma implementation "apt-pkg/acquire-method.h"
13#endif
14#include <apt-pkg/acquire-method.h>
15#include <apt-pkg/error.h>
16#include <apt-pkg/configuration.h>
cdcc6d34 17#include <apt-pkg/strutl.h>
93bf083d
AL
18#include <apt-pkg/fileutl.h>
19
20#include <stdio.h>
65a1e968 21#include <unistd.h>
93bf083d
AL
22 /*}}}*/
23
24// AcqMethod::pkgAcqMethod - Constructor /*{{{*/
25// ---------------------------------------------------------------------
26/* This constructs the initialization text */
27pkgAcqMethod::pkgAcqMethod(const char *Ver,unsigned long Flags)
28{
29 char S[300] = "";
30 char *End = S;
31 strcat(End,"100 Capabilities\n");
32 sprintf(End+strlen(End),"Version: %s\n",Ver);
33
34 if ((Flags & SingleInstance) == SingleInstance)
35 strcat(End,"Single-Instance: true\n");
36
93bf083d
AL
37 if ((Flags & Pipeline) == Pipeline)
38 strcat(End,"Pipeline: true\n");
39
40 if ((Flags & SendConfig) == SendConfig)
41 strcat(End,"Send-Config: true\n");
e331f6ed
AL
42
43 if ((Flags & LocalOnly) == LocalOnly)
44 strcat(End,"Local-Only: true\n");
93bf083d
AL
45 strcat(End,"\n");
46
47 if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
48 exit(100);
be4401bf
AL
49
50 SetNonBlock(STDIN_FILENO,true);
5cb5d8dc 51
92e889c8 52 Queue = 0;
5cb5d8dc 53 QueueBack = 0;
93bf083d
AL
54}
55 /*}}}*/
56// AcqMethod::Fail - A fetch has failed /*{{{*/
57// ---------------------------------------------------------------------
58/* */
a72ace20 59void pkgAcqMethod::Fail(bool Transient)
93bf083d
AL
60{
61 string Err = "Undetermined Error";
62 if (_error->empty() == false)
63 _error->PopMessage(Err);
64 _error->Discard();
a72ace20 65 Fail(Err,Transient);
93bf083d
AL
66}
67 /*}}}*/
68// AcqMethod::Fail - A fetch has failed /*{{{*/
69// ---------------------------------------------------------------------
70/* */
a72ace20 71void pkgAcqMethod::Fail(string Err,bool Transient)
6d5dd02a
AL
72{
73 // Strip out junk from the error messages
74 for (char *I = Err.begin(); I != Err.end(); I++)
75 {
76 if (*I == '\r')
77 *I = ' ';
78 if (*I == '\n')
79 *I = ' ';
80 }
81
93bf083d 82 char S[1024];
be4401bf
AL
83 if (Queue != 0)
84 {
85 snprintf(S,sizeof(S),"400 URI Failure\nURI: %s\n"
a72ace20
AL
86 "Message: %s\n",Queue->Uri.c_str(),Err.c_str());
87
be4401bf
AL
88 // Dequeue
89 FetchItem *Tmp = Queue;
90 Queue = Queue->Next;
91 delete Tmp;
5cb5d8dc
AL
92 if (Tmp == QueueBack)
93 QueueBack = Queue;
be4401bf
AL
94 }
95 else
96 snprintf(S,sizeof(S),"400 URI Failure\nURI: <UNKNOWN>\n"
a72ace20 97 "Message: %s\n",Err.c_str());
be4401bf 98
a72ace20
AL
99 // Set the transient flag
100 if (Transient == true)
101 strcat(S,"Transient-Failure: true\n\n");
102 else
103 strcat(S,"\n");
104
93bf083d
AL
105 if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
106 exit(100);
107}
108 /*}}}*/
109// AcqMethod::URIStart - Indicate a download is starting /*{{{*/
110// ---------------------------------------------------------------------
111/* */
be4401bf 112void pkgAcqMethod::URIStart(FetchResult &Res)
93bf083d 113{
be4401bf
AL
114 if (Queue == 0)
115 abort();
116
93bf083d
AL
117 char S[1024] = "";
118 char *End = S;
119
be4401bf 120 End += snprintf(S,sizeof(S),"200 URI Start\nURI: %s\n",Queue->Uri.c_str());
93bf083d
AL
121 if (Res.Size != 0)
122 End += snprintf(End,sizeof(S) - (End - S),"Size: %u\n",Res.Size);
123
124 if (Res.LastModified != 0)
125 End += snprintf(End,sizeof(S) - (End - S),"Last-Modified: %s\n",
126 TimeRFC1123(Res.LastModified).c_str());
127
be4401bf 128 if (Res.ResumePoint != 0)
93bf083d 129 End += snprintf(End,sizeof(S) - (End - S),"Resume-Point: %u\n",
be4401bf 130 Res.ResumePoint);
93bf083d
AL
131
132 strcat(End,"\n");
133 if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
134 exit(100);
135}
136 /*}}}*/
137// AcqMethod::URIDone - A URI is finished /*{{{*/
138// ---------------------------------------------------------------------
139/* */
140void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt)
141{
be4401bf
AL
142 if (Queue == 0)
143 abort();
144
93bf083d
AL
145 char S[1024] = "";
146 char *End = S;
147
be4401bf 148 End += snprintf(S,sizeof(S),"201 URI Done\nURI: %s\n",Queue->Uri.c_str());
93bf083d
AL
149
150 if (Res.Filename.empty() == false)
151 End += snprintf(End,sizeof(S) - (End - S),"Filename: %s\n",Res.Filename.c_str());
152
153 if (Res.Size != 0)
154 End += snprintf(End,sizeof(S) - (End - S),"Size: %u\n",Res.Size);
155
156 if (Res.LastModified != 0)
157 End += snprintf(End,sizeof(S) - (End - S),"Last-Modified: %s\n",
158 TimeRFC1123(Res.LastModified).c_str());
159
160 if (Res.MD5Sum.empty() == false)
fd9bd3dc 161 End += snprintf(End,sizeof(S) - (End - S),"MD5-Hash: %s\n",Res.MD5Sum.c_str());
93bf083d 162
b98f2859
AL
163 if (Res.ResumePoint != 0)
164 End += snprintf(End,sizeof(S) - (End - S),"Resume-Point: %u\n",
165 Res.ResumePoint);
166
93bf083d
AL
167 if (Res.IMSHit == true)
168 strcat(End,"IMS-Hit: true\n");
169 End = S + strlen(S);
170
171 if (Alt != 0)
172 {
173 if (Alt->Filename.empty() == false)
174 End += snprintf(End,sizeof(S) - (End - S),"Alt-Filename: %s\n",Alt->Filename.c_str());
175
176 if (Alt->Size != 0)
177 End += snprintf(End,sizeof(S) - (End - S),"Alt-Size: %u\n",Alt->Size);
178
179 if (Alt->LastModified != 0)
180 End += snprintf(End,sizeof(S) - (End - S),"Alt-Last-Modified: %s\n",
181 TimeRFC1123(Alt->LastModified).c_str());
182
183 if (Alt->MD5Sum.empty() == false)
fd9bd3dc 184 End += snprintf(End,sizeof(S) - (End - S),"Alt-MD5-Hash: %s\n",
93bf083d
AL
185 Alt->MD5Sum.c_str());
186
187 if (Alt->IMSHit == true)
188 strcat(End,"Alt-IMS-Hit: true\n");
189 }
190
191 strcat(End,"\n");
192 if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
193 exit(100);
be4401bf
AL
194
195 // Dequeue
196 FetchItem *Tmp = Queue;
197 Queue = Queue->Next;
198 delete Tmp;
5cb5d8dc
AL
199 if (Tmp == QueueBack)
200 QueueBack = Queue;
93bf083d
AL
201}
202 /*}}}*/
f46e7681
AL
203// AcqMethod::MediaFail - Syncronous request for new media /*{{{*/
204// ---------------------------------------------------------------------
205/* This sends a 403 Media Failure message to the APT and waits for it
206 to be ackd */
018f1533 207bool pkgAcqMethod::MediaFail(string Required,string Drive)
f46e7681
AL
208{
209 char S[1024];
210 snprintf(S,sizeof(S),"403 Media Failure\nMedia: %s\nDrive: %s\n\n",
211 Required.c_str(),Drive.c_str());
212
213 if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
214 exit(100);
215
216 vector<string> MyMessages;
217
218 /* Here we read messages until we find a 603, each non 603 message is
219 appended to the main message list for later processing */
220 while (1)
221 {
222 if (WaitFd(STDIN_FILENO) == false)
76d97c26 223 return false;
f46e7681
AL
224
225 if (ReadMessages(STDIN_FILENO,MyMessages) == false)
76d97c26
AL
226 return false;
227
f46e7681
AL
228 string Message = MyMessages.front();
229 MyMessages.erase(MyMessages.begin());
230
231 // Fetch the message number
232 char *End;
233 int Number = strtol(Message.c_str(),&End,10);
234 if (End == Message.c_str())
235 {
236 cerr << "Malformed message!" << endl;
237 exit(100);
238 }
239
240 // Change ack
241 if (Number == 603)
242 {
76d97c26 243 while (MyMessages.empty() == false)
f46e7681
AL
244 {
245 Messages.push_back(MyMessages.front());
246 MyMessages.erase(MyMessages.begin());
247 }
542ec555 248
76d97c26 249 return !StringToBool(LookupTag(Message,"Fail"),false);
f46e7681
AL
250 }
251
252 Messages.push_back(Message);
253 }
254}
255 /*}}}*/
93bf083d
AL
256// AcqMethod::Configuration - Handle the configuration message /*{{{*/
257// ---------------------------------------------------------------------
258/* This parses each configuration entry and puts it into the _config
259 Configuration class. */
260bool pkgAcqMethod::Configuration(string Message)
261{
262 ::Configuration &Cnf = *_config;
263
264 const char *I = Message.begin();
265
266 unsigned int Length = strlen("Config-Item");
267 for (; I + Length < Message.end(); I++)
268 {
269 // Not a config item
270 if (I[Length] != ':' || stringcasecmp(I,I+Length,"Config-Item") != 0)
271 continue;
272
273 I += Length + 1;
274
275 for (; I < Message.end() && *I == ' '; I++);
276 const char *Equals = I;
277 for (; Equals < Message.end() && *Equals != '='; Equals++);
278 const char *End = Equals;
279 for (; End < Message.end() && *End != '\n'; End++);
280 if (End == Equals)
281 return false;
282
6d5dd02a
AL
283 Cnf.Set(DeQuoteString(string(I,Equals-I)),
284 DeQuoteString(string(Equals+1,End-Equals-1)));
93bf083d
AL
285 I = End;
286 }
287
288 return true;
289}
290 /*}}}*/
291// AcqMethod::Run - Run the message engine /*{{{*/
292// ---------------------------------------------------------------------
293/* */
be4401bf 294int pkgAcqMethod::Run(bool Single)
93bf083d 295{
93bf083d
AL
296 while (1)
297 {
be4401bf 298 // Block if the message queue is empty
93bf083d 299 if (Messages.empty() == true)
be4401bf
AL
300 {
301 if (Single == false)
302 if (WaitFd(STDIN_FILENO) == false)
303 return 0;
be4401bf 304
92e889c8
AL
305 if (ReadMessages(STDIN_FILENO,Messages) == false)
306 return 0;
307 }
308
be4401bf
AL
309 // Single mode exits if the message queue is empty
310 if (Single == true && Messages.empty() == true)
311 return 0;
312
93bf083d
AL
313 string Message = Messages.front();
314 Messages.erase(Messages.begin());
315
316 // Fetch the message number
317 char *End;
318 int Number = strtol(Message.c_str(),&End,10);
319 if (End == Message.c_str())
320 {
321 cerr << "Malformed message!" << endl;
322 return 100;
323 }
324
325 switch (Number)
326 {
327 case 601:
328 if (Configuration(Message) == false)
329 return 100;
330 break;
331
332 case 600:
be4401bf
AL
333 {
334 FetchItem *Tmp = new FetchItem;
335
336 Tmp->Uri = LookupTag(Message,"URI");
337 Tmp->DestFile = LookupTag(Message,"FileName");
b98f2859
AL
338 if (StrToTime(LookupTag(Message,"Last-Modified"),Tmp->LastModified) == false)
339 Tmp->LastModified = 0;
a72ace20 340 Tmp->IndexFile = StringToBool(LookupTag(Message,"Index-File"),false);
be4401bf
AL
341 Tmp->Next = 0;
342
343 // Append it to the list
344 FetchItem **I = &Queue;
92e889c8 345 for (; *I != 0; I = &(*I)->Next);
be4401bf 346 *I = Tmp;
5cb5d8dc
AL
347 if (QueueBack == 0)
348 QueueBack = Tmp;
349
bfd22fc0 350 // Notify that this item is to be fetched.
be4401bf 351 if (Fetch(Tmp) == false)
93bf083d 352 Fail();
bfd22fc0 353
93bf083d
AL
354 break;
355 }
356 }
357 }
358
359 return 0;
360}
361 /*}}}*/
be4401bf
AL
362// AcqMethod::Log - Send a log message /*{{{*/
363// ---------------------------------------------------------------------
364/* */
365void pkgAcqMethod::Log(const char *Format,...)
366{
367 string CurrentURI = "<UNKNOWN>";
368 if (Queue != 0)
369 CurrentURI = Queue->Uri;
370
371 va_list args;
372 va_start(args,Format);
373
374 // sprintf the description
375 char S[1024];
376 unsigned int Len = snprintf(S,sizeof(S),"101 Log\nURI: %s\n"
377 "Message: ",CurrentURI.c_str());
378
379 vsnprintf(S+Len,sizeof(S)-Len,Format,args);
380 strcat(S,"\n\n");
381
382 if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
383 exit(100);
384}
385 /*}}}*/
386// AcqMethod::Status - Send a status message /*{{{*/
387// ---------------------------------------------------------------------
388/* */
389void pkgAcqMethod::Status(const char *Format,...)
390{
391 string CurrentURI = "<UNKNOWN>";
392 if (Queue != 0)
393 CurrentURI = Queue->Uri;
394
395 va_list args;
396 va_start(args,Format);
397
398 // sprintf the description
399 char S[1024];
8267fe24 400 unsigned int Len = snprintf(S,sizeof(S),"102 Status\nURI: %s\n"
be4401bf
AL
401 "Message: ",CurrentURI.c_str());
402
403 vsnprintf(S+Len,sizeof(S)-Len,Format,args);
404 strcat(S,"\n\n");
405
406 if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
407 exit(100);
408}
409 /*}}}*/
410
93bf083d
AL
411// AcqMethod::FetchResult::FetchResult - Constructor /*{{{*/
412// ---------------------------------------------------------------------
413/* */
93274b8d
AL
414pkgAcqMethod::FetchResult::FetchResult() : LastModified(0),
415 IMSHit(false), Size(0), ResumePoint(0)
93bf083d
AL
416{
417}
418 /*}}}*/
419