]>
git.saurik.com Git - apt.git/blob - apt-pkg/acquire-method.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: acquire-method.cc,v 1.24 2000/01/17 07:11:49 jgg Exp $
4 /* ######################################################################
8 This is a skeleton class that implements most of the functionality
9 of a method and some usefull functions to make method implementation
10 simpler. The methods all derive this and specialize it. The most
11 complex implementation is the http method which needs to provide
12 pipelining, it runs the message engine at the same time it is
15 ##################################################################### */
17 // Include Files /*{{{*/
19 #pragma implementation "apt-pkg/acquire-method.h"
21 #include <apt-pkg/acquire-method.h>
22 #include <apt-pkg/error.h>
23 #include <apt-pkg/configuration.h>
24 #include <apt-pkg/strutl.h>
25 #include <apt-pkg/fileutl.h>
32 // AcqMethod::pkgAcqMethod - Constructor /*{{{*/
33 // ---------------------------------------------------------------------
34 /* This constructs the initialization text */
35 pkgAcqMethod::pkgAcqMethod(const char *Ver
,unsigned long Flags
)
39 strcat(End
,"100 Capabilities\n");
40 sprintf(End
+strlen(End
),"Version: %s\n",Ver
);
42 if ((Flags
& SingleInstance
) == SingleInstance
)
43 strcat(End
,"Single-Instance: true\n");
45 if ((Flags
& Pipeline
) == Pipeline
)
46 strcat(End
,"Pipeline: true\n");
48 if ((Flags
& SendConfig
) == SendConfig
)
49 strcat(End
,"Send-Config: true\n");
51 if ((Flags
& LocalOnly
) == LocalOnly
)
52 strcat(End
,"Local-Only: true\n");
54 if ((Flags
& NeedsCleanup
) == NeedsCleanup
)
55 strcat(End
,"Needs-Cleanup: true\n");
57 if ((Flags
& Removable
) == Removable
)
58 strcat(End
,"Removable: true\n");
61 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
64 SetNonBlock(STDIN_FILENO
,true);
70 // AcqMethod::Fail - A fetch has failed /*{{{*/
71 // ---------------------------------------------------------------------
73 void pkgAcqMethod::Fail(bool Transient
)
75 string Err
= "Undetermined Error";
76 if (_error
->empty() == false)
77 _error
->PopMessage(Err
);
82 // AcqMethod::Fail - A fetch has failed /*{{{*/
83 // ---------------------------------------------------------------------
85 void pkgAcqMethod::Fail(string Err
,bool Transient
)
87 // Strip out junk from the error messages
88 for (char *I
= Err
.begin(); I
!= Err
.end(); I
++)
99 snprintf(S
,sizeof(S
)-50,"400 URI Failure\nURI: %s\n"
100 "Message: %s\n",Queue
->Uri
.c_str(),Err
.c_str());
103 FetchItem
*Tmp
= Queue
;
106 if (Tmp
== QueueBack
)
110 snprintf(S
,sizeof(S
)-50,"400 URI Failure\nURI: <UNKNOWN>\n"
111 "Message: %s\n",Err
.c_str());
113 // Set the transient flag
114 if (Transient
== true)
115 strcat(S
,"Transient-Failure: true\n\n");
119 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
123 // AcqMethod::URIStart - Indicate a download is starting /*{{{*/
124 // ---------------------------------------------------------------------
126 void pkgAcqMethod::URIStart(FetchResult
&Res
)
134 End
+= snprintf(S
,sizeof(S
),"200 URI Start\nURI: %s\n",Queue
->Uri
.c_str());
136 End
+= snprintf(End
,sizeof(S
)-4 - (End
- S
),"Size: %lu\n",Res
.Size
);
138 if (Res
.LastModified
!= 0)
139 End
+= snprintf(End
,sizeof(S
)-4 - (End
- S
),"Last-Modified: %s\n",
140 TimeRFC1123(Res
.LastModified
).c_str());
142 if (Res
.ResumePoint
!= 0)
143 End
+= snprintf(End
,sizeof(S
)-4 - (End
- S
),"Resume-Point: %lu\n",
147 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
151 // AcqMethod::URIDone - A URI is finished /*{{{*/
152 // ---------------------------------------------------------------------
154 void pkgAcqMethod::URIDone(FetchResult
&Res
, FetchResult
*Alt
)
162 End
+= snprintf(S
,sizeof(S
),"201 URI Done\nURI: %s\n",Queue
->Uri
.c_str());
164 if (Res
.Filename
.empty() == false)
165 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Filename: %s\n",Res
.Filename
.c_str());
168 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Size: %lu\n",Res
.Size
);
170 if (Res
.LastModified
!= 0)
171 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Last-Modified: %s\n",
172 TimeRFC1123(Res
.LastModified
).c_str());
174 if (Res
.MD5Sum
.empty() == false)
175 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"MD5-Hash: %s\n",Res
.MD5Sum
.c_str());
177 if (Res
.ResumePoint
!= 0)
178 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Resume-Point: %lu\n",
181 if (Res
.IMSHit
== true)
182 strcat(End
,"IMS-Hit: true\n");
187 if (Alt
->Filename
.empty() == false)
188 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Alt-Filename: %s\n",Alt
->Filename
.c_str());
191 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Alt-Size: %lu\n",Alt
->Size
);
193 if (Alt
->LastModified
!= 0)
194 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Alt-Last-Modified: %s\n",
195 TimeRFC1123(Alt
->LastModified
).c_str());
197 if (Alt
->MD5Sum
.empty() == false)
198 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Alt-MD5-Hash: %s\n",
199 Alt
->MD5Sum
.c_str());
201 if (Alt
->IMSHit
== true)
202 strcat(End
,"Alt-IMS-Hit: true\n");
206 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
210 FetchItem
*Tmp
= Queue
;
213 if (Tmp
== QueueBack
)
217 // AcqMethod::MediaFail - Syncronous request for new media /*{{{*/
218 // ---------------------------------------------------------------------
219 /* This sends a 403 Media Failure message to the APT and waits for it
221 bool pkgAcqMethod::MediaFail(string Required
,string Drive
)
224 snprintf(S
,sizeof(S
),"403 Media Failure\nMedia: %s\nDrive: %s\n\n",
225 Required
.c_str(),Drive
.c_str());
227 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
230 vector
<string
> MyMessages
;
232 /* Here we read messages until we find a 603, each non 603 message is
233 appended to the main message list for later processing */
236 if (WaitFd(STDIN_FILENO
) == false)
239 if (ReadMessages(STDIN_FILENO
,MyMessages
) == false)
242 string Message
= MyMessages
.front();
243 MyMessages
.erase(MyMessages
.begin());
245 // Fetch the message number
247 int Number
= strtol(Message
.c_str(),&End
,10);
248 if (End
== Message
.c_str())
250 cerr
<< "Malformed message!" << endl
;
257 while (MyMessages
.empty() == false)
259 Messages
.push_back(MyMessages
.front());
260 MyMessages
.erase(MyMessages
.begin());
263 return !StringToBool(LookupTag(Message
,"Fail"),false);
266 Messages
.push_back(Message
);
270 // AcqMethod::Configuration - Handle the configuration message /*{{{*/
271 // ---------------------------------------------------------------------
272 /* This parses each configuration entry and puts it into the _config
273 Configuration class. */
274 bool pkgAcqMethod::Configuration(string Message
)
276 ::Configuration
&Cnf
= *_config
;
278 const char *I
= Message
.begin();
280 unsigned int Length
= strlen("Config-Item");
281 for (; I
+ Length
< Message
.end(); I
++)
284 if (I
[Length
] != ':' || stringcasecmp(I
,I
+Length
,"Config-Item") != 0)
289 for (; I
< Message
.end() && *I
== ' '; I
++);
290 const char *Equals
= I
;
291 for (; Equals
< Message
.end() && *Equals
!= '='; Equals
++);
292 const char *End
= Equals
;
293 for (; End
< Message
.end() && *End
!= '\n'; End
++);
297 Cnf
.Set(DeQuoteString(string(I
,Equals
-I
)),
298 DeQuoteString(string(Equals
+1,End
-Equals
-1)));
305 // AcqMethod::Run - Run the message engine /*{{{*/
306 // ---------------------------------------------------------------------
307 /* Fetch any messages and execute them. In single mode it returns 1 if
308 there are no more available messages - any other result is a
309 fatal failure code! */
310 int pkgAcqMethod::Run(bool Single
)
314 // Block if the message queue is empty
315 if (Messages
.empty() == true)
318 if (WaitFd(STDIN_FILENO
) == false)
320 if (ReadMessages(STDIN_FILENO
,Messages
) == false)
324 // Single mode exits if the message queue is empty
325 if (Single
== true && Messages
.empty() == true)
328 string Message
= Messages
.front();
329 Messages
.erase(Messages
.begin());
331 // Fetch the message number
333 int Number
= strtol(Message
.c_str(),&End
,10);
334 if (End
== Message
.c_str())
336 cerr
<< "Malformed message!" << endl
;
343 if (Configuration(Message
) == false)
349 FetchItem
*Tmp
= new FetchItem
;
351 Tmp
->Uri
= LookupTag(Message
,"URI");
352 Tmp
->DestFile
= LookupTag(Message
,"FileName");
353 if (StrToTime(LookupTag(Message
,"Last-Modified"),Tmp
->LastModified
) == false)
354 Tmp
->LastModified
= 0;
355 Tmp
->IndexFile
= StringToBool(LookupTag(Message
,"Index-File"),false);
358 // Append it to the list
359 FetchItem
**I
= &Queue
;
360 for (; *I
!= 0; I
= &(*I
)->Next
);
365 // Notify that this item is to be fetched.
366 if (Fetch(Tmp
) == false)
378 // AcqMethod::Log - Send a log message /*{{{*/
379 // ---------------------------------------------------------------------
381 void pkgAcqMethod::Log(const char *Format
,...)
383 string CurrentURI
= "<UNKNOWN>";
385 CurrentURI
= Queue
->Uri
;
388 va_start(args
,Format
);
390 // sprintf the description
392 unsigned int Len
= snprintf(S
,sizeof(S
)-4,"101 Log\nURI: %s\n"
393 "Message: ",CurrentURI
.c_str());
395 vsnprintf(S
+Len
,sizeof(S
)-4-Len
,Format
,args
);
398 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
402 // AcqMethod::Status - Send a status message /*{{{*/
403 // ---------------------------------------------------------------------
405 void pkgAcqMethod::Status(const char *Format
,...)
407 string CurrentURI
= "<UNKNOWN>";
409 CurrentURI
= Queue
->Uri
;
412 va_start(args
,Format
);
414 // sprintf the description
416 unsigned int Len
= snprintf(S
,sizeof(S
)-4,"102 Status\nURI: %s\n"
417 "Message: ",CurrentURI
.c_str());
419 vsnprintf(S
+Len
,sizeof(S
)-4-Len
,Format
,args
);
422 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
427 // AcqMethod::FetchResult::FetchResult - Constructor /*{{{*/
428 // ---------------------------------------------------------------------
430 pkgAcqMethod::FetchResult::FetchResult() : LastModified(0),
431 IMSHit(false), Size(0), ResumePoint(0)